From 81376c93dc5eccfe084280ebf67b76bdd8e79da0 Mon Sep 17 00:00:00 2001
From: liujiangnan <695541723@qq.com>
Date: Wed, 24 Nov 2021 23:30:26 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E7=AC=AC=E4=B8=80=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .DS_Store                                     | Bin 10244 -> 10244 bytes
 .gitignore                                    |   9 +-
 bin/app.js                                    |  52 +++
 bin/build.cmd                                 |   2 -
 bin/build.js                                  |  84 +---
 bin/build.sh                                  |  67 ---
 bin/buildCocos.js                             | 339 +++++++++++++++
 bin/buildConfig.json                          |   4 -
 bin/build_check.js                            |  34 --
 bin/build_step_0.js                           |  55 ---
 bin/build_step_1.js                           |  33 --
 bin/build_step_2.js                           |   9 -
 bin/build_step_3.js                           |   9 -
 bin/build_step_4.js                           |  66 ---
 bin/utils.js                                  |  95 ++---
 form/index.html                               |  75 ++++
 {form => form_angular}/.editorconfig          |   0
 {form => form_angular}/.gitignore             |   0
 {form => form_angular}/.keep                  |   0
 {form => form_angular}/README.md              |   0
 {form => form_angular}/angular.json           |   0
 {form => form_angular}/bin/publish.js         |   0
 {form => form_angular}/browserslist           |   0
 {form => form_angular}/e2e/protractor.conf.js |   0
 .../e2e/src/app.e2e-spec.ts                   |   0
 {form => form_angular}/e2e/src/app.po.ts      |   0
 {form => form_angular}/e2e/tsconfig.json      |   0
 {form => form_angular}/karma.conf.js          |   0
 {form => form_angular}/package-lock.json      |   0
 {form => form_angular}/package.json           |   0
 {form => form_angular}/publish/.keep          |   0
 {form => form_angular}/src/app/MyError.ts     |   0
 .../src/app/app.component.html                |   0
 .../src/app/app.component.scss                |   0
 .../src/app/app.component.ts                  |   0
 {form => form_angular}/src/app/app.module.ts  |   0
 .../audio-recorder.component.html             |   0
 .../audio-recorder.component.scss             |   0
 .../audio-recorder.component.ts               |   0
 .../src/app/common/custom-hot-zone/Unit.ts    |   0
 .../custom-hot-zone.component.html            |   0
 .../custom-hot-zone.component.scss            |   0
 .../custom-hot-zone.component.ts              |   0
 .../lesson-title-config.component.html        |   0
 .../lesson-title-config.component.scss        |   0
 .../lesson-title-config.component.ts          |   0
 .../player-content-wrapper.component.html     |   0
 .../player-content-wrapper.component.scss     |   0
 .../player-content-wrapper.component.ts       |   0
 .../upload-dragon-bone.component.html         |   0
 .../upload-dragon-bone.component.scss         |   0
 .../upload-dragon-bone.component.ts           |   0
 .../upload-image-with-preview.component.html  |   0
 .../upload-image-with-preview.component.scss  |   0
 .../upload-image-with-preview.component.ts    |   0
 .../upload-video/upload-video.component.html  |   0
 .../upload-video/upload-video.component.scss  |   0
 .../upload-video/upload-video.component.ts    |   0
 .../src/app/form/form.component.css           |   0
 .../src/app/form/form.component.html          |   0
 .../src/app/form/form.component.ts            |   0
 .../src/app/pipes/background-image.pipe.ts    |   0
 .../src/app/pipes/resource.pipe.ts            |   0
 .../src/app/pipes/time.pipe.ts                |   0
 {form => form_angular}/src/app/play/Unit.ts   |   0
 .../src/app/play/play.component.css           |   0
 .../src/app/play/play.component.html          |   0
 .../src/app/play/play.component.ts            |   0
 .../src/app/play/resources.js                 |   0
 .../src/app/style/colors.scss                 |   0
 .../src/app/style/common_mixin.css            |   0
 {form => form_angular}/src/assets/.gitkeep    |   0
 .../src/assets/common/arrow.png               | Bin
 .../src/assets/common/arrow_right.png         | Bin
 .../src/assets/common/arrow_top.png           | Bin
 .../src/assets/default/video-not-upload.jpg   | Bin
 .../src/assets/font/BRLNSB.TTF                | Bin
 .../src/assets/font/BRLNSDB.TTF               | Bin
 .../src/assets/font/BRLNSR.TTF                | Bin
 .../src/assets/font/GOTHIC.TTF                | Bin
 .../src/assets/font/GOTHICB.TTF               | Bin
 .../src/assets/font/GOTHICBI.TTF              | Bin
 .../src/assets/font/GOTHICI.TTF               | Bin
 .../src/assets/font/MMTextBook-Bold.otf       | Bin
 .../src/assets/font/MMTextBook-BoldItalic.otf | Bin
 .../src/assets/font/MMTextBook-Italic.otf     | Bin
 .../src/assets/font/MMTextBook.otf            | Bin
 .../assets/libs/audio-recorder/lame.min.js    |   0
 .../assets/libs/audio-recorder/recorder.js    |   0
 .../src/assets/libs/audio-recorder/worker.js  |   0
 .../libs/service-worker/cache-service.js      |   0
 .../assets/libs/video-js-7.0.0/video-js.css   |   0
 .../libs/video-js-7.0.0/video-js.min.css      |   0
 .../src/assets/libs/video-js-7.0.0/video.js   |   0
 .../assets/libs/video-js-7.0.0/video.min.js   |   0
 {form => form_angular}/src/assets/play/bg.jpg | Bin
 .../src/assets/play/btn_left.png              | Bin
 .../src/assets/play/btn_right.png             | Bin
 .../src/assets/play/default/audio.mp3         | Bin
 .../src/assets/play/default/pic.jpg           | Bin
 .../src/assets/play/music/click.mp3           | Bin
 .../src/assets/play/text_bg.png               | Bin
 .../src/environments/environment.prod.ts      |   0
 .../src/environments/environment.ts           |   0
 {form => form_angular}/src/favicon.ico        | Bin
 {form => form_angular}/src/index.html         |   0
 {form => form_angular}/src/main.ts            |   0
 {form => form_angular}/src/online.html        |   0
 {form => form_angular}/src/polyfills.ts       |   0
 {form => form_angular}/src/styles.css         |   0
 {form => form_angular}/src/test.ts            |   0
 {form => form_angular}/tsconfig.app.json      |   0
 {form => form_angular}/tsconfig.json          |   0
 {form => form_angular}/tsconfig.spec.json     |   0
 {form => form_angular}/tslint.json            |   0
 package-lock.json                             | 389 ++++++++++++++++++
 package.json                                  |   8 +-
 play/assets/cocos_generator.meta              |  16 +-
 118 files changed, 919 insertions(+), 427 deletions(-)
 create mode 100644 bin/app.js
 delete mode 100644 bin/build.cmd
 delete mode 100644 bin/build.sh
 create mode 100644 bin/buildCocos.js
 delete mode 100644 bin/buildConfig.json
 delete mode 100644 bin/build_check.js
 delete mode 100644 bin/build_step_0.js
 delete mode 100644 bin/build_step_1.js
 delete mode 100644 bin/build_step_2.js
 delete mode 100644 bin/build_step_3.js
 delete mode 100644 bin/build_step_4.js
 create mode 100644 form/index.html
 rename {form => form_angular}/.editorconfig (100%)
 rename {form => form_angular}/.gitignore (100%)
 rename {form => form_angular}/.keep (100%)
 rename {form => form_angular}/README.md (100%)
 rename {form => form_angular}/angular.json (100%)
 rename {form => form_angular}/bin/publish.js (100%)
 rename {form => form_angular}/browserslist (100%)
 rename {form => form_angular}/e2e/protractor.conf.js (100%)
 rename {form => form_angular}/e2e/src/app.e2e-spec.ts (100%)
 rename {form => form_angular}/e2e/src/app.po.ts (100%)
 rename {form => form_angular}/e2e/tsconfig.json (100%)
 rename {form => form_angular}/karma.conf.js (100%)
 rename {form => form_angular}/package-lock.json (100%)
 rename {form => form_angular}/package.json (100%)
 rename {form => form_angular}/publish/.keep (100%)
 rename {form => form_angular}/src/app/MyError.ts (100%)
 rename {form => form_angular}/src/app/app.component.html (100%)
 rename {form => form_angular}/src/app/app.component.scss (100%)
 rename {form => form_angular}/src/app/app.component.ts (100%)
 rename {form => form_angular}/src/app/app.module.ts (100%)
 rename {form => form_angular}/src/app/common/audio-recorder/audio-recorder.component.html (100%)
 rename {form => form_angular}/src/app/common/audio-recorder/audio-recorder.component.scss (100%)
 rename {form => form_angular}/src/app/common/audio-recorder/audio-recorder.component.ts (100%)
 rename {form => form_angular}/src/app/common/custom-hot-zone/Unit.ts (100%)
 rename {form => form_angular}/src/app/common/custom-hot-zone/custom-hot-zone.component.html (100%)
 rename {form => form_angular}/src/app/common/custom-hot-zone/custom-hot-zone.component.scss (100%)
 rename {form => form_angular}/src/app/common/custom-hot-zone/custom-hot-zone.component.ts (100%)
 rename {form => form_angular}/src/app/common/lesson-title-config/lesson-title-config.component.html (100%)
 rename {form => form_angular}/src/app/common/lesson-title-config/lesson-title-config.component.scss (100%)
 rename {form => form_angular}/src/app/common/lesson-title-config/lesson-title-config.component.ts (100%)
 rename {form => form_angular}/src/app/common/player-content-wrapper/player-content-wrapper.component.html (100%)
 rename {form => form_angular}/src/app/common/player-content-wrapper/player-content-wrapper.component.scss (100%)
 rename {form => form_angular}/src/app/common/player-content-wrapper/player-content-wrapper.component.ts (100%)
 rename {form => form_angular}/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html (100%)
 rename {form => form_angular}/src/app/common/upload-dragon-bone/upload-dragon-bone.component.scss (100%)
 rename {form => form_angular}/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts (100%)
 rename {form => form_angular}/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html (100%)
 rename {form => form_angular}/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss (100%)
 rename {form => form_angular}/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts (100%)
 rename {form => form_angular}/src/app/common/upload-video/upload-video.component.html (100%)
 rename {form => form_angular}/src/app/common/upload-video/upload-video.component.scss (100%)
 rename {form => form_angular}/src/app/common/upload-video/upload-video.component.ts (100%)
 rename {form => form_angular}/src/app/form/form.component.css (100%)
 rename {form => form_angular}/src/app/form/form.component.html (100%)
 rename {form => form_angular}/src/app/form/form.component.ts (100%)
 rename {form => form_angular}/src/app/pipes/background-image.pipe.ts (100%)
 rename {form => form_angular}/src/app/pipes/resource.pipe.ts (100%)
 rename {form => form_angular}/src/app/pipes/time.pipe.ts (100%)
 rename {form => form_angular}/src/app/play/Unit.ts (100%)
 rename {form => form_angular}/src/app/play/play.component.css (100%)
 rename {form => form_angular}/src/app/play/play.component.html (100%)
 rename {form => form_angular}/src/app/play/play.component.ts (100%)
 rename {form => form_angular}/src/app/play/resources.js (100%)
 rename {form => form_angular}/src/app/style/colors.scss (100%)
 rename {form => form_angular}/src/app/style/common_mixin.css (100%)
 rename {form => form_angular}/src/assets/.gitkeep (100%)
 rename {form => form_angular}/src/assets/common/arrow.png (100%)
 rename {form => form_angular}/src/assets/common/arrow_right.png (100%)
 rename {form => form_angular}/src/assets/common/arrow_top.png (100%)
 rename {form => form_angular}/src/assets/default/video-not-upload.jpg (100%)
 rename {form => form_angular}/src/assets/font/BRLNSB.TTF (100%)
 rename {form => form_angular}/src/assets/font/BRLNSDB.TTF (100%)
 rename {form => form_angular}/src/assets/font/BRLNSR.TTF (100%)
 rename {form => form_angular}/src/assets/font/GOTHIC.TTF (100%)
 rename {form => form_angular}/src/assets/font/GOTHICB.TTF (100%)
 rename {form => form_angular}/src/assets/font/GOTHICBI.TTF (100%)
 rename {form => form_angular}/src/assets/font/GOTHICI.TTF (100%)
 rename {form => form_angular}/src/assets/font/MMTextBook-Bold.otf (100%)
 rename {form => form_angular}/src/assets/font/MMTextBook-BoldItalic.otf (100%)
 rename {form => form_angular}/src/assets/font/MMTextBook-Italic.otf (100%)
 rename {form => form_angular}/src/assets/font/MMTextBook.otf (100%)
 rename {form => form_angular}/src/assets/libs/audio-recorder/lame.min.js (100%)
 rename {form => form_angular}/src/assets/libs/audio-recorder/recorder.js (100%)
 rename {form => form_angular}/src/assets/libs/audio-recorder/worker.js (100%)
 rename {form => form_angular}/src/assets/libs/service-worker/cache-service.js (100%)
 rename {form => form_angular}/src/assets/libs/video-js-7.0.0/video-js.css (100%)
 rename {form => form_angular}/src/assets/libs/video-js-7.0.0/video-js.min.css (100%)
 rename {form => form_angular}/src/assets/libs/video-js-7.0.0/video.js (100%)
 rename {form => form_angular}/src/assets/libs/video-js-7.0.0/video.min.js (100%)
 rename {form => form_angular}/src/assets/play/bg.jpg (100%)
 rename {form => form_angular}/src/assets/play/btn_left.png (100%)
 rename {form => form_angular}/src/assets/play/btn_right.png (100%)
 rename {form => form_angular}/src/assets/play/default/audio.mp3 (100%)
 rename {form => form_angular}/src/assets/play/default/pic.jpg (100%)
 rename {form => form_angular}/src/assets/play/music/click.mp3 (100%)
 rename {form => form_angular}/src/assets/play/text_bg.png (100%)
 rename {form => form_angular}/src/environments/environment.prod.ts (100%)
 rename {form => form_angular}/src/environments/environment.ts (100%)
 rename {form => form_angular}/src/favicon.ico (100%)
 rename {form => form_angular}/src/index.html (100%)
 rename {form => form_angular}/src/main.ts (100%)
 rename {form => form_angular}/src/online.html (100%)
 rename {form => form_angular}/src/polyfills.ts (100%)
 rename {form => form_angular}/src/styles.css (100%)
 rename {form => form_angular}/src/test.ts (100%)
 rename {form => form_angular}/tsconfig.app.json (100%)
 rename {form => form_angular}/tsconfig.json (100%)
 rename {form => form_angular}/tsconfig.spec.json (100%)
 rename {form => form_angular}/tslint.json (100%)

diff --git a/.DS_Store b/.DS_Store
index 1c678bf95e5d84735764ecfde8eb5e07bf8043e6..c257b29e612f4d945559633ec58aac425bb66366 100644
GIT binary patch
delta 153
zcmZn(XbG6$FUrfnz`)4BAiz*ukd%|31mvAeD%e;!jeTMR?`C!m77lTc3TB2RhD?UM
zq;iC+$*N)vniAF3W`;Tn#)d|<IttZ>24<!@3TB2DwY8ia;;M$Wo(Z{?Rn;}Mbu%ZQ
l7n2vCg)pfsxF|0tKQA3*`(_>iHvY}*3cpx3^N27r0|3o1CyW39

delta 60
zcmZn(XbG6$FUrlpz`)4BAi$7RUR;orlb;0SpW0YBjeTMR?`C!m77j-4&5VL<{1Y3#
PZe~~b#j^REC^Itv<m3?%

diff --git a/.gitignore b/.gitignore
index aaa1838..a296e69 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,10 @@
 /node_modules
 /dist
-/publish
\ No newline at end of file
+/publish
+/publish/form
+/form/publish/*.zip
+/publish/play
+/node_modules
+/play/build_android
+/play/build_ios
+/play/build_web_desktop
\ No newline at end of file
diff --git a/bin/app.js b/bin/app.js
new file mode 100644
index 0000000..c9c0f89
--- /dev/null
+++ b/bin/app.js
@@ -0,0 +1,52 @@
+const express = require('express');
+const os = require('os');
+const readline = require('readline');
+const { build } = require('./buildCocos');
+
+const networkInfo = os.networkInterfaces();
+
+let host = '';
+for (const infos of Object.values(networkInfo)) {
+  for (const info of infos) {
+    if (info.family == 'IPv4') {
+      if (info.address.split('.')[0] != "127") {
+        host = info.address;
+      }
+    }
+  }
+}
+
+var app = express();
+
+app.use('/dist', express.static('dist'));
+
+app.get('/', function (req, res) {
+  res.send('Hello World');
+})
+
+let port = '';
+var server = app.listen(8081, function () {
+
+  port = server.address().port
+
+  console.log("测试服务已启动:%s:%s", host, port)
+  console.log("如果已经build可访问如下地址");
+  console.log("http://%s:%s/dist/play/index.html", host, port)
+  console.log("http://%s:%s/dist/play/index.html", "localhost", port)
+
+})
+
+const rl = readline.createInterface({
+  input: process.stdin,
+  output: process.stdout
+})
+rl.on('line', async (str) => {
+  if (str.trim() == 'build') {
+    await build();
+    console.log("测试服务已启动:%s:%s", host, port)
+    console.log('输入 build 构建。')
+  } else {
+    console.log("测试服务已启动:%s:%s", host, port)
+    console.log('输入 build 构建。')
+  }
+})
diff --git a/bin/build.cmd b/bin/build.cmd
deleted file mode 100644
index 76a9361..0000000
--- a/bin/build.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-cd ../form & npm install & npm run publish & cd ../play & CocosCreator.exe --path "./" --build "platform=web-desktop;debug=true" --force & cd ../bin & node build.js
-pause
diff --git a/bin/build.js b/bin/build.js
index 8fd95d5..4884ad9 100644
--- a/bin/build.js
+++ b/bin/build.js
@@ -1,82 +1,2 @@
-let fs = require('fs');
-const compressing = require('compressing');
-
-function fix2(num) {
-    if (num >= 10) {
-        return '' + num;
-    } else {
-        return '0' + num;
-    }
-}
-
-async function copyDir(src, dst) {
-    const exists = await fs.existsSync(dst);
-    if (!exists) {
-        await fs.mkdirSync(dst);
-    }
-    //读取目录
-    const paths = await fs.readdirSync(src);
-    for (let i = 0; i < paths.length; i++) {
-        let path = paths[i];
-        const newSrc = `${src}/${path}`;
-        const newDst = `${dst}/${path}`;
-        const st = await fs.statSync(newSrc);
-        if (st.isFile()) {
-            console.log('copy: ' + newDst);
-            const data = await fs.readFileSync(newSrc);
-            await fs.writeFileSync(newDst, data);
-        } else if (st.isDirectory()) {
-            copyDir(newSrc, newDst);
-        }
-    }
-}
-
-async function removeDir(src) {
-    const exists = await fs.existsSync(src);
-    if (!exists) {
-        return;
-    }
-
-    //读取目录
-    const st = await fs.statSync(src);
-    console.log(st);
-    const paths = await fs.readdirSync(src);
-    for (let i = 0; i < paths.length; i++) {
-        let path = paths[i];
-        const newSrc = `${src}/${path}`;
-        const st = await fs.statSync(newSrc);
-        if (st.isFile()) {
-            console.log('remove: ' + newSrc);
-            await fs.unlinkSync(newSrc);
-        } else if (st.isDirectory()) {
-            await removeDir(newSrc);
-        }
-    }
-    await fs.rmdirSync(src);
-}
-
-async function main() {
-    let date = new Date();
-    let fileName = `Release_${date.getFullYear()}${fix2(date.getMonth() + 1)}${fix2(date.getDate())} `;
-    fileName += `${fix2(date.getHours())}-${fix2(date.getMinutes())}-${fix2(date.getSeconds())}`;
-
-    await removeDir('../publish/play');
-    await removeDir('../publish/form');
-
-    await copyDir('../play/build/web-desktop', '../publish/play');
-
-    compressing.zip.uncompress('../form/publish/form.zip', '../publish/form')
-        .then(() => {
-            const tarStream = new compressing.zip.Stream();
-            tarStream.addEntry('../publish/play');
-            tarStream.addEntry('../publish/form');
-
-            const destStream = fs.createWriteStream(`../publish/${fileName}.zip`);
-
-            tarStream.pipe(destStream);
-
-            console.log('打包完成!');
-        });
-}
-
-main();
\ No newline at end of file
+const {build} = require('./buildCocos');
+build();
\ No newline at end of file
diff --git a/bin/build.sh b/bin/build.sh
deleted file mode 100644
index d322ec2..0000000
--- a/bin/build.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/sh
-
-cd bin 
-
-set -e
-
-node build_check.js
-
-set +e
-
-# cd ../form 
-
-# npm install
-
-# npm run publish 
-
-cd ../bin 
-
-node build_step_0.js
-
-cd ../play
-
-/Applications/CocosCreator/Creator/2.4.5/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=web-desktop;debug=true" --force
-
-echo "生成 web desktop 完成~!"
-
-cd ../bin 
-
-node build_step_1.js
-
-echo "build_step_1 完成~!"
-
-cd ../play
-
-/Applications/CocosCreator/Creator/2.4.5/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=ios;debug=false;md5Cache=true;buildPath=build_ios;encryptJs=true;xxteaKey=6bbfce23-28b4-4a;zipCompressJs=true" --force
-
-echo "生成 ios 完成~!"
-
-cd ../bin 
-
-node build_step_2.js
-
-echo "build_step_2 完成~!"
-
-cd ../play
-
-/Applications/CocosCreator/Creator/2.4.5/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=ios;debug=false;md5Cache=true;buildPath=build_android;appABIs=['armeabi-v7a','x86','x86_64','arm64-v8a'];encryptJs=true;xxteaKey=6bbfce23-28b4-4a;zipCompressJs=true" --force
-
-echo "生成 android 完成~!"
-
-cd ../bin 
-
-node build_step_3.js
-
-echo "build_step_3 完成~!"
-
-cd ../play
-
-/Applications/CocosCreator/Creator/2.4.5/CocosCreator.app/Contents/MacOS/CocosCreator --path "./" --build "platform=web-desktop;debug=false;buildPath=build_web_desktop" --force
-
-echo "生成 web-desktop 完成~!"
-
-cd ../bin 
-
-node build_step_4.js
-
-echo "build_step_4 完成~!"
\ No newline at end of file
diff --git a/bin/buildCocos.js b/bin/buildCocos.js
new file mode 100644
index 0000000..4243805
--- /dev/null
+++ b/bin/buildCocos.js
@@ -0,0 +1,339 @@
+const { spawn }  = require("child_process");
+const fs  = require("fs");
+const compressing  = require('compressing');
+const { v4, parse }  = require('uuid');
+const { Base64 }  = require('js-base64');
+const { copyDir, removeDir, fix2 }  = require("./utils");
+
+async function buildForm() {
+  const paths = fs.readdirSync('form');
+
+  if (!paths.includes('tsconfig.json')) {
+    await copyDir('form', 'dist/form');
+    return;
+  }
+
+  if (process.platform == 'win32') {
+    await execCmd('npm.cmd', ['install'], 'form');
+  } else {
+    await execCmd('npm', ['install'], 'form');
+  }
+
+  if (process.platform == 'win32') {
+    await execCmd('npm.cmd', ['run', 'publish'], 'form');
+  } else {
+    await execCmd('npm', ['run', 'publish'], 'form');
+  }
+
+  await compressing.zip.uncompress('form/publish/form.zip', 'dist/form');
+}
+
+function execCmd(cmd, params, path) {
+  return new Promise((resolve, reject) => {
+    const buffer = spawn(
+      cmd,
+      params,
+      { cwd: path }
+    );
+
+    buffer.stdout.on('data', (data) => {
+      console.log(`stdout: ${data}`);
+    });
+
+    buffer.stderr.on('data', (data) => {
+      console.error(`stderr: ${data}`);
+    });
+
+    buffer.on('close', (code) => {
+      console.log(`child process exited with code ${code}`);
+      resolve();
+    });
+  });
+}
+
+
+let creatorBasePath = 'C:\\CocosDashboard_1.0.6\\resources\\.editors\\Creator\\2.4.5\\CocosCreator.exe';
+if (process.platform !== 'win32') {
+  creatorBasePath = "/Applications/CocosCreator/Creator/2.4.5/CocosCreator.app/Contents/MacOS/CocosCreator";
+}
+const buildCocos = function (args) {
+  return new Promise((resolve, reject) => {
+    const buffer = spawn(
+      creatorBasePath,
+      args,
+      { cwd: 'play' }
+    );
+
+    buffer.stdout.on('data', (data) => {
+      console.log(`stdout: ${data}`);
+    });
+
+    buffer.stderr.on('data', (data) => {
+      console.error(`stderr: ${data}`);
+    });
+
+    buffer.on('close', (code) => {
+      console.log(`child process exited with code ${code}`);
+      resolve();
+    });
+  });
+};
+
+function getReleaseFileName(projectName) {
+  let date = new Date();
+  let fileName = `${projectName}_${date.getFullYear()}${fix2(date.getMonth() + 1)}${fix2(date.getDate())} `;
+  fileName += `${fix2(date.getHours())}-${fix2(date.getMinutes())}-${fix2(date.getSeconds())}`;
+  return fileName;
+}
+
+function getFolderName(path) {
+  let folderName = '';
+  fs.readdirSync(path).find(fileName => {
+    const st = fs.statSync(`${path}/${fileName}`);
+    if (st.isDirectory()) {
+      folderName = fileName;
+    }
+  });
+  return folderName;
+}
+function editFolderMeta(path, folderName, isBundle) {
+  const metaPath = `${path}/${folderName}.meta`;
+  const metaDataStr = fs.readFileSync(metaPath);
+  const metaData = JSON.parse(metaDataStr);
+  metaData.isBundle = isBundle;
+  metaData.isRemoteBundle = {
+    ios: isBundle,
+    android: isBundle
+  };
+  fs.writeFileSync(metaPath, JSON.stringify(metaData));
+}
+
+async function buildWebDesktop() {
+  const args = ['--path', './', '--build', 'platform=web-desktop;debug=true', '--force'];
+  await buildCocos(args);
+}
+
+async function buildAndroidBundle() {
+  const args = ['--path', './', '--build', "platform=ios;debug=false;md5Cache=true;buildPath=build_android;appABIs=['armeabi-v7a','x86','x86_64','arm64-v8a'];encryptJs=true;xxteaKey=6bbfce23-28b4-4a;zipCompressJs=true", '--force'];
+  await buildCocos(args);
+}
+
+async function buildIosBundle() {
+  const args = ['--path', './', '--build', "platform=ios;debug=false;md5Cache=true;buildPath=build_ios;encryptJs=true;xxteaKey=6bbfce23-28b4-4a;zipCompressJs=true", '--force'];
+  await buildCocos(args);
+}
+
+async function buildWebBundle() {
+  const args = ['--path', './', '--build', "platform=web-desktop;debug=false;buildPath=build_web_desktop", '--force'];
+  await buildCocos(args);
+}
+
+function createConfigFile (projectName) {
+  const androidPaths = fs.readdirSync(`dist/android/${projectName}`);
+  const androidConfigFileName = androidPaths.find(path => path.indexOf('config') == 0);
+  const androidVersion = androidConfigFileName.split('.')[1];
+
+  const iosPaths = fs.readdirSync(`dist/ios/${projectName}`);
+  const iosConfigFileName = iosPaths.find(path => path.indexOf('config') == 0);
+  const iosVersion = iosConfigFileName.split('.')[1];
+
+  const config = {
+    "ios": {
+      "sceneName": projectName,
+      "version": iosVersion
+    },
+    "android": {
+      "sceneName": projectName,
+      "version": androidVersion
+    }
+  }
+
+  fs.writeFileSync('dist/config.json', JSON.stringify(config));
+}
+
+function compressAll (projectName) {
+  const tarStream = new compressing.zip.Stream();
+  tarStream.addEntry('dist/play');
+  tarStream.addEntry('dist/form');
+  tarStream.addEntry('dist/ios');
+  tarStream.addEntry('dist/android');
+  tarStream.addEntry('dist/web_desktop');
+  tarStream.addEntry('dist/config.json');
+  const destStream = fs.createWriteStream(`publish/${getReleaseFileName(projectName)}.zip`);
+  tarStream.pipe(destStream);
+}
+
+function build_check () {
+  const dirNames = process.cwd().split(/\/|\\/);
+  const projectName = dirNames[dirNames.length - 1];
+  const path = 'play/assets'
+  let folderName = '';
+  fs.readdirSync(path).find(fileName => {
+    const st = fs.statSync(`${path}/${fileName}`);
+    if (st.isDirectory()) {
+      folderName = fileName;
+    }
+  });
+
+  if (projectName != folderName) {
+    throw (`项目名(${projectName})与bundle文件夹名(${folderName})不相同`);
+  }
+  let same = false;
+  const files = fs.readdirSync(`${path}/${folderName}/scene`);
+  files.forEach(fileName => {
+    fileName.split('.').forEach((str, idx, arr) => {
+      if (str == 'fire') {
+        const sceneName = arr[idx - 1];
+        if (folderName == sceneName) {
+          same = true;
+        }
+      }
+    })
+  });
+
+  if (!same) {
+    throw (`bundle文件夹名称(${folderName})与scene名称不相同`);
+  }
+
+  return projectName;
+}
+
+function changeSettingToWebDesktop () {
+  const path = 'play/assets'
+  const folderName = getFolderName(path);
+  editFolderMeta(path, folderName, false);
+}
+
+function changeSettingsToBundle () {
+  const path = 'play/assets'
+  const folderName = getFolderName(path);
+  editFolderMeta(path, folderName, true);
+}
+
+function replaceUuids () {
+  console.log('build_step_0 开始~!');
+
+  function getFolderName(path) {
+    let folderName = '';
+    fs.readdirSync(path).find(fileName => {
+      const st = fs.statSync(`${path}/${fileName}`);
+      if (st.isDirectory()) {
+        folderName = fileName;
+      }
+    });
+    return folderName;
+  }
+  function editFolderMeta(path, folderName) {
+    const metaPath = `${path}/${folderName}.meta`;
+    const metaDataStr = fs.readFileSync(metaPath);
+    const metaData = JSON.parse(metaDataStr);
+    metaData.isBundle = false;
+    fs.writeFileSync(metaPath, JSON.stringify(metaData));
+  }
+
+
+  function fileReplace(path, replaceStr, newStr) {
+    if (!fs.existsSync(path)) {
+      return;
+    }
+
+    const fileStr = fs.readFileSync(path);
+    const newFileStr = fileStr.toString().replace(new RegExp(replaceStr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), 'g'), newStr);
+    fs.writeFileSync(path, newFileStr);
+  }
+
+  const path = 'play/assets'
+  const folderName = getFolderName(path);
+  editFolderMeta(path, folderName);
+
+  const oldFireUuid = '57ea7c61-9b8b-498a-b024-c98ee9124beb';
+  const newFireUuid = v4();
+  fileReplace(`play/assets/${folderName}/scene/${folderName}.fire.meta`, oldFireUuid, newFireUuid);
+  fileReplace(`play/assets/${folderName}/scene/${folderName}.fire`, oldFireUuid, newFireUuid);
+  fileReplace('play/settings/builder.json', oldFireUuid, newFireUuid);
+
+
+  function getShortUuid(uuid) {
+    const bytes = parse(uuid).subarray(1);
+    return uuid.substring(0, 5) + Base64.fromUint8Array(bytes).substring(2);
+  }
+
+  const oldJsUuid = 'f4ede462-f8d7-4069-ba80-915611c058ca';
+  const oldJsShortUuid = 'f4edeRi+NdAabqAkVYRwFjK';
+  const oldJsId = 'e687yyoRBIzZAOVRL8Sseh';
+  const newJsUuid = v4();
+  const newJsShortUuid = getShortUuid(newJsUuid);
+  const newJsId = v4().replace(/-/g, '').substring(0, oldJsId.length);
+  fileReplace(`play/assets/${folderName}/scene/${folderName}.ts.meta`, oldJsUuid, newJsUuid);
+  fileReplace(`play/assets/${folderName}/scene/${folderName}.fire`, oldFireUuid, newFireUuid);
+  fileReplace(`play/assets/${folderName}/scene/${folderName}.fire`, oldJsShortUuid, newJsShortUuid);
+  fileReplace(`play/assets/${folderName}/scene/${folderName}.fire`, oldJsId, newJsId);
+
+  console.log('build_step_0 完成~!');
+}
+
+function replaceIndexHtml () {
+  const data = fs.readFileSync('play/index.html');
+  fs.writeFileSync('dist/play/index.html', data);
+}
+
+module.exports = {
+
+  build: async function () {
+
+    const startTime = new Date().getTime();
+  
+    // 构建前检查
+    const projectName = build_check();
+  
+    // 清理旧文件
+  
+    // 构建form
+    await removeDir('dist/form');
+    await buildForm();
+  
+    // 替换uuid
+    replaceUuids();
+  
+    // 改设置为非bundle
+    changeSettingToWebDesktop();
+  
+    // 构建play
+    await removeDir('dist/play');
+    await buildWebDesktop();
+    await copyDir('play/build/web-desktop', 'dist/play');
+    replaceIndexHtml();
+    console.log('构建 web desktop 成功!');
+  
+    // 改设置为bundle
+    changeSettingsToBundle();
+  
+    await removeDir('dist/android');
+    await buildAndroidBundle();
+    await copyDir('play/build_android/jsb-link/remote', 'dist/android');
+    console.log('构建 android bundle 成功!');
+  
+    await removeDir('dist/ios');
+    await buildIosBundle();
+    await copyDir('play/build_ios/jsb-link/remote', 'dist/ios');
+    console.log('构建 ios bundle 成功!');
+  
+    await removeDir('dist/web_desktop');
+    await buildWebBundle();
+    await copyDir(`play/build_web_desktop/web-desktop/assets/${projectName}`, 'dist/web_desktop');
+    console.log('构建 web bundle 成功!');
+  
+    // 改设置为非bundle
+    changeSettingToWebDesktop();
+  
+    createConfigFile(projectName);
+  
+    compressAll(projectName);
+  
+    const endTime = new Date().getTime();
+    const duration = new Date(endTime - startTime);
+    console.log(`打包完成!`);
+    console.log(`用时${duration.getMinutes()}分${duration.getSeconds()}秒。`);
+  },
+
+};
diff --git a/bin/buildConfig.json b/bin/buildConfig.json
deleted file mode 100644
index bd10daa..0000000
--- a/bin/buildConfig.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-	"platform": "web-desktop",
-	"debug": true
-}
\ No newline at end of file
diff --git a/bin/build_check.js b/bin/build_check.js
deleted file mode 100644
index 5cfcc0a..0000000
--- a/bin/build_check.js
+++ /dev/null
@@ -1,34 +0,0 @@
-let fs = require('fs');
-
-const dirNames = __dirname.split('/');
-const projectName = dirNames[dirNames.length - 2];
-const path = '../play/assets'
-let folderName = '';
-fs.readdirSync(path).find(fileName => {
-  const st = fs.statSync(`${path}/${fileName}`);
-  if (st.isDirectory()) {
-    folderName = fileName;
-  }
-});
-
-if (projectName != folderName) {
-  throw (`项目名(${projectName})与bundle文件夹名(${folderName})不相同`);
-}
-let same = false;
-const files = fs.readdirSync(`${path}/${folderName}/scene`);
-files.forEach(fileName => {
-  fileName.split('.').forEach((str, idx, arr) => {
-    if (str == 'fire') {
-      const sceneName = arr[idx - 1];
-      if (folderName == sceneName) {
-        same = true;
-      }
-    }
-  })
-});
-
-if (!same) {
-  throw (`bundle文件夹名称(${folderName})与scene名称不相同`);
-}
-
-// 'caller', 'callee', and 'arguments'
\ No newline at end of file
diff --git a/bin/build_step_0.js b/bin/build_step_0.js
deleted file mode 100644
index 5d11e5a..0000000
--- a/bin/build_step_0.js
+++ /dev/null
@@ -1,55 +0,0 @@
-const fs = require('fs');
-const { v4, parse } = require('uuid');
-const { Base64 } = require('js-base64');
-
-function getFolderName(path) {
-  let folderName = '';
-  fs.readdirSync(path).find(fileName => {
-    const st = fs.statSync(`${path}/${fileName}`);
-    if (st.isDirectory()) {
-      folderName = fileName;
-    }
-  });
-  return folderName;
-}
-function editFolderMeta(path, folderName) {
-  const metaPath = `${path}/${folderName}.meta`;
-  const metaDataStr = fs.readFileSync(metaPath);
-  const metaData = JSON.parse(metaDataStr);
-  metaData.isBundle = false;
-  fs.writeFileSync(metaPath, JSON.stringify(metaData));
-}
-
-
-function fileReplace(path, replaceStr, newStr) {
-  const fileStr = fs.readFileSync(path);
-  const newFileStr = fileStr.toString().replace(replaceStr, newStr);
-  fs.writeFileSync(path, newFileStr);
-}
-
-const path = '../play/assets'
-const folderName = getFolderName(path);
-editFolderMeta(path, folderName);
-
-const oldFireUuid = '57ea7c61-9b8b-498a-b024-c98ee9124beb';
-const newFireUuid = v4();
-fileReplace(`../play/assets/${folderName}/scene/${folderName}.fire.meta`, oldFireUuid, newFireUuid);
-fileReplace(`../play/assets/${folderName}/scene/${folderName}.fire`, oldFireUuid, newFireUuid);
-fileReplace('../play/settings/builder.json', oldFireUuid, newFireUuid);
-
-
-function getShortUuid(uuid) {
-  const bytes = parse(uuid).subarray(1);
-  return uuid.substring(0, 5) + Base64.fromUint8Array(bytes).substring(2);
-}
-
-const oldJsUuid = 'f4ede462-f8d7-4069-ba80-915611c058ca';
-const oldJsShortUuid = 'f4edeRi+NdAabqAkVYRwFjK';
-const oldJsId = 'e687yyoRBIzZAOVRL8Sseh';
-const newJsUuid = v4();
-const newJsShortUuid = getShortUuid(newJsUuid);
-const newJsId = v4().replace(/-/g, '').substring(0, oldJsId.length);
-fileReplace(`../play/assets/${folderName}/scene/${folderName}.js.meta`, oldJsUuid, newJsUuid);
-fileReplace(`../play/assets/${folderName}/scene/${folderName}.fire`, oldFireUuid, newFireUuid);
-fileReplace(`../play/assets/${folderName}/scene/${folderName}.fire`, oldJsShortUuid, newJsShortUuid);
-fileReplace(`../play/assets/${folderName}/scene/${folderName}.fire`, oldJsId, newJsId);
diff --git a/bin/build_step_1.js b/bin/build_step_1.js
deleted file mode 100644
index 6289445..0000000
--- a/bin/build_step_1.js
+++ /dev/null
@@ -1,33 +0,0 @@
-const { removeDir, copyDir } = require('./utils');
-let fs = require('fs');
-
-async function main() {
-  await removeDir('../dist/play');
-
-  await copyDir('../play/build/web-desktop', '../dist/play');
-  const data = await fs.readFileSync('../play/index.html');
-  await fs.writeFileSync('../dist/play/index.html', data);
-
-  await removeDir('../play/build');
-
-
-  const path = '../play/assets'
-  let folderName = '';
-  fs.readdirSync(path).find(fileName => {
-    const st = fs.statSync(`${path}/${fileName}`);
-    if (st.isDirectory()) {
-      folderName = fileName;
-    }
-  });
-  const metaPath = `${path}/${folderName}.meta`;
-  const metaDataStr = fs.readFileSync(metaPath);
-  const metaData = JSON.parse(metaDataStr);
-  metaData.isBundle = true;
-  metaData.isRemoteBundle = {
-    ios: true,
-    android: true
-  };
-  fs.writeFileSync(metaPath, JSON.stringify(metaData));
-}
-
-main();
\ No newline at end of file
diff --git a/bin/build_step_2.js b/bin/build_step_2.js
deleted file mode 100644
index 477b911..0000000
--- a/bin/build_step_2.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const { removeDir, copyDir } = require('./utils');
-
-async function main() {
-  await removeDir('../dist/ios');
-  await copyDir('../play/build_ios/jsb-link/remote', '../dist/ios');
-  await removeDir('../play/build_ios');
-}
-
-main();
\ No newline at end of file
diff --git a/bin/build_step_3.js b/bin/build_step_3.js
deleted file mode 100644
index 88ed4bb..0000000
--- a/bin/build_step_3.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const { removeDir, copyDir } = require('./utils');
-
-async function main() {
-  await removeDir('../dist/android');
-  await copyDir('../play/build_android/jsb-link/remote', '../dist/android');
-  await removeDir('../play/build_android');
-}
-
-main();
\ No newline at end of file
diff --git a/bin/build_step_4.js b/bin/build_step_4.js
deleted file mode 100644
index b126e3e..0000000
--- a/bin/build_step_4.js
+++ /dev/null
@@ -1,66 +0,0 @@
-const { removeDir, copyDir, fix2 } = require('./utils');
-const compressing = require('compressing');
-let fs = require('fs');
-
-async function main() {
-  await removeDir('../dist/web_desktop');
-  const projectName = await getBundleName('../play/build_web_desktop/web-desktop/assets');
-  await copyDir(`../play/build_web_desktop/web-desktop/assets/${projectName}`, '../dist/web_desktop');
-  await removeDir('../play/build_web_desktop');
-
-  const bundleData = {
-    ios: await getBundleData('../dist/ios'),
-    android: await getBundleData('../dist/android'),
-  }
-
-  fs.writeFileSync('../dist/config.json', JSON.stringify(bundleData));
-
-  const tarStream = new compressing.zip.Stream();
-  tarStream.addEntry('../dist/play');
-  tarStream.addEntry('../dist/ios');
-  tarStream.addEntry('../dist/android');
-  tarStream.addEntry('../dist/web_desktop');
-  tarStream.addEntry('../dist/config.json');
-
-  const destStream = fs.createWriteStream(`../publish/${getReleaseFileName()}.zip`);
-  tarStream.pipe(destStream);
-
-  console.log('打包完成!');
-
-  // 删掉发布打包的多余文件
-  await removeDir('../play/library');
-  await removeDir('../play/local');
-  await removeDir('../play/temp');
-}
-
-async function getBundleName(path) {
-  const paths = fs.readdirSync(path);
-  return paths.find(path => path != 'internal' && path !='main');
-}
-
-async function getBundleData(path) {
-  const bundleData = {
-    sceneName: '',
-    version: '',
-  }
-  const paths = fs.readdirSync(path);
-  bundleData.sceneName = paths[0];
-  const files = fs.readdirSync(path + '/' + bundleData.sceneName);
-  files.forEach(fileName => {
-    fileName.split('.').forEach((str, idx, arr) => {
-      if (str == 'config') {
-        bundleData.version = arr[idx + 1];
-      }
-    })
-  });
-  return bundleData;
-}
-
-function getReleaseFileName() {
-  let date = new Date();
-  let fileName = `Release_${date.getFullYear()}${fix2(date.getMonth() + 1)}${fix2(date.getDate())} `;
-  fileName += `${fix2(date.getHours())}-${fix2(date.getMinutes())}-${fix2(date.getSeconds())}`;
-  return fileName;
-}
-
-main();
\ No newline at end of file
diff --git a/bin/utils.js b/bin/utils.js
index 24ee747..de12653 100644
--- a/bin/utils.js
+++ b/bin/utils.js
@@ -1,5 +1,49 @@
-let fs = require('fs');
+const fs = require('fs');
 
+const removeDir =  async function (src) {
+  const exists = await fs.existsSync(src);
+  if (!exists) {
+    return;
+  }
+
+  //读取目录
+  const st = await fs.statSync(src);
+  const paths = await fs.readdirSync(src);
+  for (let i = 0; i < paths.length; i++) {
+    let path = paths[i];
+    const newSrc = `${src}/${path}`;
+    const st = await fs.statSync(newSrc);
+    if (st.isFile()) {
+      console.log('remove: ' + newSrc);
+      await fs.unlinkSync(newSrc);
+    } else if (st.isDirectory()) {
+      await removeDir(newSrc);
+    }
+  }
+  await fs.rmdirSync(src);
+}
+
+const copyDir = async function (src, dst) {
+  const exists = await fs.existsSync(dst);
+  if (!exists) {
+    await fs.mkdirSync(dst);
+  }
+  //读取目录
+  const paths = await fs.readdirSync(src);
+  for (let i = 0; i < paths.length; i++) {
+    let path = paths[i];
+    const newSrc = `${src}/${path}`;
+    const newDst = `${dst}/${path}`;
+    const st = await fs.statSync(newSrc);
+    if (st.isFile()) {
+      console.log('copy: ' + newDst);
+      const data = await fs.readFileSync(newSrc);
+      await fs.writeFileSync(newDst, data);
+    } else if (st.isDirectory()) {
+      await copyDir(newSrc, newDst);
+    }
+  }
+};
 module.exports = {
   fix2: function (num) {
     if (num >= 10) {
@@ -8,49 +52,6 @@ module.exports = {
       return '0' + num;
     }
   },
-
-  copyDir: async function (src, dst) {
-    const exists = await fs.existsSync(dst);
-    if (!exists) {
-      await fs.mkdirSync(dst);
-    }
-    //读取目录
-    const paths = await fs.readdirSync(src);
-    for (let i = 0; i < paths.length; i++) {
-      let path = paths[i];
-      const newSrc = `${src}/${path}`;
-      const newDst = `${dst}/${path}`;
-      const st = await fs.statSync(newSrc);
-      if (st.isFile()) {
-        console.log('copy: ' + newDst);
-        const data = await fs.readFileSync(newSrc);
-        await fs.writeFileSync(newDst, data);
-      } else if (st.isDirectory()) {
-        arguments.callee(newSrc, newDst);
-      }
-    }
-  },
-
-  removeDir: async function (src) {
-    const exists = await fs.existsSync(src);
-    if (!exists) {
-      return;
-    }
-
-    //读取目录
-    const st = await fs.statSync(src);
-    const paths = await fs.readdirSync(src);
-    for (let i = 0; i < paths.length; i++) {
-      let path = paths[i];
-      const newSrc = `${src}/${path}`;
-      const st = await fs.statSync(newSrc);
-      if (st.isFile()) {
-        console.log('remove: ' + newSrc);
-        await fs.unlinkSync(newSrc);
-      } else if (st.isDirectory()) {
-        await arguments.callee(newSrc);
-      }
-    }
-    await fs.rmdirSync(src);
-  }
-}
+  copyDir: copyDir,
+  removeDir: removeDir,
+};
diff --git a/form/index.html b/form/index.html
new file mode 100644
index 0000000..b91061b
--- /dev/null
+++ b/form/index.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+  <meta charset="utf-8">
+  <title>NgOne</title>
+  <!-- <base href="/"> -->
+  <!--  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <script type="text/javascript" src="//staging-teach.cdn.ireadabc.com/h5template/h5-static-lib/js/air.js"></script>
+
+  <style>
+    .border {
+      border-radius: 20px;
+      border-style: dashed;
+      padding: 20px;
+      margin: 20px;
+      width: 800px;
+      border-radius: 20px;
+      border-width: 2px;
+      border-color: #000000;
+    }
+
+    .error {
+      border-color: red;
+    }
+
+    .right {
+      border-color: rgb(50, 255, 50);
+    }
+
+    .normal {
+      border-color: black;
+    }
+  </style>
+
+  <script>
+    let saveDataStr = '';
+    function loadData() {
+      window.courseware.getData((data, aspect) => {
+        const textarea = document.getElementById('saveDataTextarea');
+        textarea.value = JSON.stringify(data);
+        saveDataStr = textarea.value.trim();
+      });
+    }
+
+    function saveData() {
+      const textarea = document.getElementById('saveDataTextarea');
+      const textareaStr = textarea.value;
+      if (textareaStr.trim() == saveDataStr.trim()) {
+        textarea.className = "normal";
+        return;
+      }
+
+      try {
+        const data = JSON.parse(textareaStr);
+        window.courseware.setData(data);
+        saveDataStr = textarea.value.trim();
+        textarea.className = "right";
+      } catch (e) {
+        textarea.className = "error";
+        console.error(e);
+      }
+    }
+  </script>
+</head>
+
+<body onload="loadData();" style="background-color: white;">
+  <div class="border">
+    保存的数据:
+    <textarea class="normal" style="width: 100%; height: 300px;" id="saveDataTextarea" onBlur="saveData();"></textarea>
+  </div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/form/.editorconfig b/form_angular/.editorconfig
similarity index 100%
rename from form/.editorconfig
rename to form_angular/.editorconfig
diff --git a/form/.gitignore b/form_angular/.gitignore
similarity index 100%
rename from form/.gitignore
rename to form_angular/.gitignore
diff --git a/form/.keep b/form_angular/.keep
similarity index 100%
rename from form/.keep
rename to form_angular/.keep
diff --git a/form/README.md b/form_angular/README.md
similarity index 100%
rename from form/README.md
rename to form_angular/README.md
diff --git a/form/angular.json b/form_angular/angular.json
similarity index 100%
rename from form/angular.json
rename to form_angular/angular.json
diff --git a/form/bin/publish.js b/form_angular/bin/publish.js
similarity index 100%
rename from form/bin/publish.js
rename to form_angular/bin/publish.js
diff --git a/form/browserslist b/form_angular/browserslist
similarity index 100%
rename from form/browserslist
rename to form_angular/browserslist
diff --git a/form/e2e/protractor.conf.js b/form_angular/e2e/protractor.conf.js
similarity index 100%
rename from form/e2e/protractor.conf.js
rename to form_angular/e2e/protractor.conf.js
diff --git a/form/e2e/src/app.e2e-spec.ts b/form_angular/e2e/src/app.e2e-spec.ts
similarity index 100%
rename from form/e2e/src/app.e2e-spec.ts
rename to form_angular/e2e/src/app.e2e-spec.ts
diff --git a/form/e2e/src/app.po.ts b/form_angular/e2e/src/app.po.ts
similarity index 100%
rename from form/e2e/src/app.po.ts
rename to form_angular/e2e/src/app.po.ts
diff --git a/form/e2e/tsconfig.json b/form_angular/e2e/tsconfig.json
similarity index 100%
rename from form/e2e/tsconfig.json
rename to form_angular/e2e/tsconfig.json
diff --git a/form/karma.conf.js b/form_angular/karma.conf.js
similarity index 100%
rename from form/karma.conf.js
rename to form_angular/karma.conf.js
diff --git a/form/package-lock.json b/form_angular/package-lock.json
similarity index 100%
rename from form/package-lock.json
rename to form_angular/package-lock.json
diff --git a/form/package.json b/form_angular/package.json
similarity index 100%
rename from form/package.json
rename to form_angular/package.json
diff --git a/form/publish/.keep b/form_angular/publish/.keep
similarity index 100%
rename from form/publish/.keep
rename to form_angular/publish/.keep
diff --git a/form/src/app/MyError.ts b/form_angular/src/app/MyError.ts
similarity index 100%
rename from form/src/app/MyError.ts
rename to form_angular/src/app/MyError.ts
diff --git a/form/src/app/app.component.html b/form_angular/src/app/app.component.html
similarity index 100%
rename from form/src/app/app.component.html
rename to form_angular/src/app/app.component.html
diff --git a/form/src/app/app.component.scss b/form_angular/src/app/app.component.scss
similarity index 100%
rename from form/src/app/app.component.scss
rename to form_angular/src/app/app.component.scss
diff --git a/form/src/app/app.component.ts b/form_angular/src/app/app.component.ts
similarity index 100%
rename from form/src/app/app.component.ts
rename to form_angular/src/app/app.component.ts
diff --git a/form/src/app/app.module.ts b/form_angular/src/app/app.module.ts
similarity index 100%
rename from form/src/app/app.module.ts
rename to form_angular/src/app/app.module.ts
diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.html b/form_angular/src/app/common/audio-recorder/audio-recorder.component.html
similarity index 100%
rename from form/src/app/common/audio-recorder/audio-recorder.component.html
rename to form_angular/src/app/common/audio-recorder/audio-recorder.component.html
diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.scss b/form_angular/src/app/common/audio-recorder/audio-recorder.component.scss
similarity index 100%
rename from form/src/app/common/audio-recorder/audio-recorder.component.scss
rename to form_angular/src/app/common/audio-recorder/audio-recorder.component.scss
diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.ts b/form_angular/src/app/common/audio-recorder/audio-recorder.component.ts
similarity index 100%
rename from form/src/app/common/audio-recorder/audio-recorder.component.ts
rename to form_angular/src/app/common/audio-recorder/audio-recorder.component.ts
diff --git a/form/src/app/common/custom-hot-zone/Unit.ts b/form_angular/src/app/common/custom-hot-zone/Unit.ts
similarity index 100%
rename from form/src/app/common/custom-hot-zone/Unit.ts
rename to form_angular/src/app/common/custom-hot-zone/Unit.ts
diff --git a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.html
similarity index 100%
rename from form/src/app/common/custom-hot-zone/custom-hot-zone.component.html
rename to form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.html
diff --git a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.scss
similarity index 100%
rename from form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss
rename to form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.scss
diff --git a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.ts
similarity index 100%
rename from form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts
rename to form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.ts
diff --git a/form/src/app/common/lesson-title-config/lesson-title-config.component.html b/form_angular/src/app/common/lesson-title-config/lesson-title-config.component.html
similarity index 100%
rename from form/src/app/common/lesson-title-config/lesson-title-config.component.html
rename to form_angular/src/app/common/lesson-title-config/lesson-title-config.component.html
diff --git a/form/src/app/common/lesson-title-config/lesson-title-config.component.scss b/form_angular/src/app/common/lesson-title-config/lesson-title-config.component.scss
similarity index 100%
rename from form/src/app/common/lesson-title-config/lesson-title-config.component.scss
rename to form_angular/src/app/common/lesson-title-config/lesson-title-config.component.scss
diff --git a/form/src/app/common/lesson-title-config/lesson-title-config.component.ts b/form_angular/src/app/common/lesson-title-config/lesson-title-config.component.ts
similarity index 100%
rename from form/src/app/common/lesson-title-config/lesson-title-config.component.ts
rename to form_angular/src/app/common/lesson-title-config/lesson-title-config.component.ts
diff --git a/form/src/app/common/player-content-wrapper/player-content-wrapper.component.html b/form_angular/src/app/common/player-content-wrapper/player-content-wrapper.component.html
similarity index 100%
rename from form/src/app/common/player-content-wrapper/player-content-wrapper.component.html
rename to form_angular/src/app/common/player-content-wrapper/player-content-wrapper.component.html
diff --git a/form/src/app/common/player-content-wrapper/player-content-wrapper.component.scss b/form_angular/src/app/common/player-content-wrapper/player-content-wrapper.component.scss
similarity index 100%
rename from form/src/app/common/player-content-wrapper/player-content-wrapper.component.scss
rename to form_angular/src/app/common/player-content-wrapper/player-content-wrapper.component.scss
diff --git a/form/src/app/common/player-content-wrapper/player-content-wrapper.component.ts b/form_angular/src/app/common/player-content-wrapper/player-content-wrapper.component.ts
similarity index 100%
rename from form/src/app/common/player-content-wrapper/player-content-wrapper.component.ts
rename to form_angular/src/app/common/player-content-wrapper/player-content-wrapper.component.ts
diff --git a/form/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html
similarity index 100%
rename from form/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html
rename to form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html
diff --git a/form/src/app/common/upload-dragon-bone/upload-dragon-bone.component.scss b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.scss
similarity index 100%
rename from form/src/app/common/upload-dragon-bone/upload-dragon-bone.component.scss
rename to form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.scss
diff --git a/form/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts
similarity index 100%
rename from form/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts
rename to form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts
diff --git a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html
similarity index 100%
rename from form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html
rename to form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html
diff --git a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss
similarity index 100%
rename from form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss
rename to form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss
diff --git a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
similarity index 100%
rename from form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
rename to form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
diff --git a/form/src/app/common/upload-video/upload-video.component.html b/form_angular/src/app/common/upload-video/upload-video.component.html
similarity index 100%
rename from form/src/app/common/upload-video/upload-video.component.html
rename to form_angular/src/app/common/upload-video/upload-video.component.html
diff --git a/form/src/app/common/upload-video/upload-video.component.scss b/form_angular/src/app/common/upload-video/upload-video.component.scss
similarity index 100%
rename from form/src/app/common/upload-video/upload-video.component.scss
rename to form_angular/src/app/common/upload-video/upload-video.component.scss
diff --git a/form/src/app/common/upload-video/upload-video.component.ts b/form_angular/src/app/common/upload-video/upload-video.component.ts
similarity index 100%
rename from form/src/app/common/upload-video/upload-video.component.ts
rename to form_angular/src/app/common/upload-video/upload-video.component.ts
diff --git a/form/src/app/form/form.component.css b/form_angular/src/app/form/form.component.css
similarity index 100%
rename from form/src/app/form/form.component.css
rename to form_angular/src/app/form/form.component.css
diff --git a/form/src/app/form/form.component.html b/form_angular/src/app/form/form.component.html
similarity index 100%
rename from form/src/app/form/form.component.html
rename to form_angular/src/app/form/form.component.html
diff --git a/form/src/app/form/form.component.ts b/form_angular/src/app/form/form.component.ts
similarity index 100%
rename from form/src/app/form/form.component.ts
rename to form_angular/src/app/form/form.component.ts
diff --git a/form/src/app/pipes/background-image.pipe.ts b/form_angular/src/app/pipes/background-image.pipe.ts
similarity index 100%
rename from form/src/app/pipes/background-image.pipe.ts
rename to form_angular/src/app/pipes/background-image.pipe.ts
diff --git a/form/src/app/pipes/resource.pipe.ts b/form_angular/src/app/pipes/resource.pipe.ts
similarity index 100%
rename from form/src/app/pipes/resource.pipe.ts
rename to form_angular/src/app/pipes/resource.pipe.ts
diff --git a/form/src/app/pipes/time.pipe.ts b/form_angular/src/app/pipes/time.pipe.ts
similarity index 100%
rename from form/src/app/pipes/time.pipe.ts
rename to form_angular/src/app/pipes/time.pipe.ts
diff --git a/form/src/app/play/Unit.ts b/form_angular/src/app/play/Unit.ts
similarity index 100%
rename from form/src/app/play/Unit.ts
rename to form_angular/src/app/play/Unit.ts
diff --git a/form/src/app/play/play.component.css b/form_angular/src/app/play/play.component.css
similarity index 100%
rename from form/src/app/play/play.component.css
rename to form_angular/src/app/play/play.component.css
diff --git a/form/src/app/play/play.component.html b/form_angular/src/app/play/play.component.html
similarity index 100%
rename from form/src/app/play/play.component.html
rename to form_angular/src/app/play/play.component.html
diff --git a/form/src/app/play/play.component.ts b/form_angular/src/app/play/play.component.ts
similarity index 100%
rename from form/src/app/play/play.component.ts
rename to form_angular/src/app/play/play.component.ts
diff --git a/form/src/app/play/resources.js b/form_angular/src/app/play/resources.js
similarity index 100%
rename from form/src/app/play/resources.js
rename to form_angular/src/app/play/resources.js
diff --git a/form/src/app/style/colors.scss b/form_angular/src/app/style/colors.scss
similarity index 100%
rename from form/src/app/style/colors.scss
rename to form_angular/src/app/style/colors.scss
diff --git a/form/src/app/style/common_mixin.css b/form_angular/src/app/style/common_mixin.css
similarity index 100%
rename from form/src/app/style/common_mixin.css
rename to form_angular/src/app/style/common_mixin.css
diff --git a/form/src/assets/.gitkeep b/form_angular/src/assets/.gitkeep
similarity index 100%
rename from form/src/assets/.gitkeep
rename to form_angular/src/assets/.gitkeep
diff --git a/form/src/assets/common/arrow.png b/form_angular/src/assets/common/arrow.png
similarity index 100%
rename from form/src/assets/common/arrow.png
rename to form_angular/src/assets/common/arrow.png
diff --git a/form/src/assets/common/arrow_right.png b/form_angular/src/assets/common/arrow_right.png
similarity index 100%
rename from form/src/assets/common/arrow_right.png
rename to form_angular/src/assets/common/arrow_right.png
diff --git a/form/src/assets/common/arrow_top.png b/form_angular/src/assets/common/arrow_top.png
similarity index 100%
rename from form/src/assets/common/arrow_top.png
rename to form_angular/src/assets/common/arrow_top.png
diff --git a/form/src/assets/default/video-not-upload.jpg b/form_angular/src/assets/default/video-not-upload.jpg
similarity index 100%
rename from form/src/assets/default/video-not-upload.jpg
rename to form_angular/src/assets/default/video-not-upload.jpg
diff --git a/form/src/assets/font/BRLNSB.TTF b/form_angular/src/assets/font/BRLNSB.TTF
similarity index 100%
rename from form/src/assets/font/BRLNSB.TTF
rename to form_angular/src/assets/font/BRLNSB.TTF
diff --git a/form/src/assets/font/BRLNSDB.TTF b/form_angular/src/assets/font/BRLNSDB.TTF
similarity index 100%
rename from form/src/assets/font/BRLNSDB.TTF
rename to form_angular/src/assets/font/BRLNSDB.TTF
diff --git a/form/src/assets/font/BRLNSR.TTF b/form_angular/src/assets/font/BRLNSR.TTF
similarity index 100%
rename from form/src/assets/font/BRLNSR.TTF
rename to form_angular/src/assets/font/BRLNSR.TTF
diff --git a/form/src/assets/font/GOTHIC.TTF b/form_angular/src/assets/font/GOTHIC.TTF
similarity index 100%
rename from form/src/assets/font/GOTHIC.TTF
rename to form_angular/src/assets/font/GOTHIC.TTF
diff --git a/form/src/assets/font/GOTHICB.TTF b/form_angular/src/assets/font/GOTHICB.TTF
similarity index 100%
rename from form/src/assets/font/GOTHICB.TTF
rename to form_angular/src/assets/font/GOTHICB.TTF
diff --git a/form/src/assets/font/GOTHICBI.TTF b/form_angular/src/assets/font/GOTHICBI.TTF
similarity index 100%
rename from form/src/assets/font/GOTHICBI.TTF
rename to form_angular/src/assets/font/GOTHICBI.TTF
diff --git a/form/src/assets/font/GOTHICI.TTF b/form_angular/src/assets/font/GOTHICI.TTF
similarity index 100%
rename from form/src/assets/font/GOTHICI.TTF
rename to form_angular/src/assets/font/GOTHICI.TTF
diff --git a/form/src/assets/font/MMTextBook-Bold.otf b/form_angular/src/assets/font/MMTextBook-Bold.otf
similarity index 100%
rename from form/src/assets/font/MMTextBook-Bold.otf
rename to form_angular/src/assets/font/MMTextBook-Bold.otf
diff --git a/form/src/assets/font/MMTextBook-BoldItalic.otf b/form_angular/src/assets/font/MMTextBook-BoldItalic.otf
similarity index 100%
rename from form/src/assets/font/MMTextBook-BoldItalic.otf
rename to form_angular/src/assets/font/MMTextBook-BoldItalic.otf
diff --git a/form/src/assets/font/MMTextBook-Italic.otf b/form_angular/src/assets/font/MMTextBook-Italic.otf
similarity index 100%
rename from form/src/assets/font/MMTextBook-Italic.otf
rename to form_angular/src/assets/font/MMTextBook-Italic.otf
diff --git a/form/src/assets/font/MMTextBook.otf b/form_angular/src/assets/font/MMTextBook.otf
similarity index 100%
rename from form/src/assets/font/MMTextBook.otf
rename to form_angular/src/assets/font/MMTextBook.otf
diff --git a/form/src/assets/libs/audio-recorder/lame.min.js b/form_angular/src/assets/libs/audio-recorder/lame.min.js
similarity index 100%
rename from form/src/assets/libs/audio-recorder/lame.min.js
rename to form_angular/src/assets/libs/audio-recorder/lame.min.js
diff --git a/form/src/assets/libs/audio-recorder/recorder.js b/form_angular/src/assets/libs/audio-recorder/recorder.js
similarity index 100%
rename from form/src/assets/libs/audio-recorder/recorder.js
rename to form_angular/src/assets/libs/audio-recorder/recorder.js
diff --git a/form/src/assets/libs/audio-recorder/worker.js b/form_angular/src/assets/libs/audio-recorder/worker.js
similarity index 100%
rename from form/src/assets/libs/audio-recorder/worker.js
rename to form_angular/src/assets/libs/audio-recorder/worker.js
diff --git a/form/src/assets/libs/service-worker/cache-service.js b/form_angular/src/assets/libs/service-worker/cache-service.js
similarity index 100%
rename from form/src/assets/libs/service-worker/cache-service.js
rename to form_angular/src/assets/libs/service-worker/cache-service.js
diff --git a/form/src/assets/libs/video-js-7.0.0/video-js.css b/form_angular/src/assets/libs/video-js-7.0.0/video-js.css
similarity index 100%
rename from form/src/assets/libs/video-js-7.0.0/video-js.css
rename to form_angular/src/assets/libs/video-js-7.0.0/video-js.css
diff --git a/form/src/assets/libs/video-js-7.0.0/video-js.min.css b/form_angular/src/assets/libs/video-js-7.0.0/video-js.min.css
similarity index 100%
rename from form/src/assets/libs/video-js-7.0.0/video-js.min.css
rename to form_angular/src/assets/libs/video-js-7.0.0/video-js.min.css
diff --git a/form/src/assets/libs/video-js-7.0.0/video.js b/form_angular/src/assets/libs/video-js-7.0.0/video.js
similarity index 100%
rename from form/src/assets/libs/video-js-7.0.0/video.js
rename to form_angular/src/assets/libs/video-js-7.0.0/video.js
diff --git a/form/src/assets/libs/video-js-7.0.0/video.min.js b/form_angular/src/assets/libs/video-js-7.0.0/video.min.js
similarity index 100%
rename from form/src/assets/libs/video-js-7.0.0/video.min.js
rename to form_angular/src/assets/libs/video-js-7.0.0/video.min.js
diff --git a/form/src/assets/play/bg.jpg b/form_angular/src/assets/play/bg.jpg
similarity index 100%
rename from form/src/assets/play/bg.jpg
rename to form_angular/src/assets/play/bg.jpg
diff --git a/form/src/assets/play/btn_left.png b/form_angular/src/assets/play/btn_left.png
similarity index 100%
rename from form/src/assets/play/btn_left.png
rename to form_angular/src/assets/play/btn_left.png
diff --git a/form/src/assets/play/btn_right.png b/form_angular/src/assets/play/btn_right.png
similarity index 100%
rename from form/src/assets/play/btn_right.png
rename to form_angular/src/assets/play/btn_right.png
diff --git a/form/src/assets/play/default/audio.mp3 b/form_angular/src/assets/play/default/audio.mp3
similarity index 100%
rename from form/src/assets/play/default/audio.mp3
rename to form_angular/src/assets/play/default/audio.mp3
diff --git a/form/src/assets/play/default/pic.jpg b/form_angular/src/assets/play/default/pic.jpg
similarity index 100%
rename from form/src/assets/play/default/pic.jpg
rename to form_angular/src/assets/play/default/pic.jpg
diff --git a/form/src/assets/play/music/click.mp3 b/form_angular/src/assets/play/music/click.mp3
similarity index 100%
rename from form/src/assets/play/music/click.mp3
rename to form_angular/src/assets/play/music/click.mp3
diff --git a/form/src/assets/play/text_bg.png b/form_angular/src/assets/play/text_bg.png
similarity index 100%
rename from form/src/assets/play/text_bg.png
rename to form_angular/src/assets/play/text_bg.png
diff --git a/form/src/environments/environment.prod.ts b/form_angular/src/environments/environment.prod.ts
similarity index 100%
rename from form/src/environments/environment.prod.ts
rename to form_angular/src/environments/environment.prod.ts
diff --git a/form/src/environments/environment.ts b/form_angular/src/environments/environment.ts
similarity index 100%
rename from form/src/environments/environment.ts
rename to form_angular/src/environments/environment.ts
diff --git a/form/src/favicon.ico b/form_angular/src/favicon.ico
similarity index 100%
rename from form/src/favicon.ico
rename to form_angular/src/favicon.ico
diff --git a/form/src/index.html b/form_angular/src/index.html
similarity index 100%
rename from form/src/index.html
rename to form_angular/src/index.html
diff --git a/form/src/main.ts b/form_angular/src/main.ts
similarity index 100%
rename from form/src/main.ts
rename to form_angular/src/main.ts
diff --git a/form/src/online.html b/form_angular/src/online.html
similarity index 100%
rename from form/src/online.html
rename to form_angular/src/online.html
diff --git a/form/src/polyfills.ts b/form_angular/src/polyfills.ts
similarity index 100%
rename from form/src/polyfills.ts
rename to form_angular/src/polyfills.ts
diff --git a/form/src/styles.css b/form_angular/src/styles.css
similarity index 100%
rename from form/src/styles.css
rename to form_angular/src/styles.css
diff --git a/form/src/test.ts b/form_angular/src/test.ts
similarity index 100%
rename from form/src/test.ts
rename to form_angular/src/test.ts
diff --git a/form/tsconfig.app.json b/form_angular/tsconfig.app.json
similarity index 100%
rename from form/tsconfig.app.json
rename to form_angular/tsconfig.app.json
diff --git a/form/tsconfig.json b/form_angular/tsconfig.json
similarity index 100%
rename from form/tsconfig.json
rename to form_angular/tsconfig.json
diff --git a/form/tsconfig.spec.json b/form_angular/tsconfig.spec.json
similarity index 100%
rename from form/tsconfig.spec.json
rename to form_angular/tsconfig.spec.json
diff --git a/form/tslint.json b/form_angular/tslint.json
similarity index 100%
rename from form/tslint.json
rename to form_angular/tslint.json
diff --git a/package-lock.json b/package-lock.json
index 25ead4b..fe3ca59 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,20 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "accepts": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz",
+      "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=",
+      "requires": {
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      }
+    },
+    "array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz?cache=0&sync_timestamp=1574313293899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-1.1.1.tgz",
+      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+    },
     "base-64": {
       "version": "1.0.0",
       "resolved": "https://registry.npm.taobao.org/base-64/download/base-64-1.0.0.tgz",
@@ -18,6 +32,33 @@
         "safe-buffer": "^5.1.1"
       }
     },
+    "body-parser": {
+      "version": "1.19.0",
+      "resolved": "https://registry.npm.taobao.org/body-parser/download/body-parser-1.19.0.tgz",
+      "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=",
+      "requires": {
+        "bytes": "3.1.0",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "on-finished": "~2.3.0",
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
+      },
+      "dependencies": {
+        "iconv-lite": {
+          "version": "0.4.24",
+          "resolved": "https://registry.nlark.com/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz",
+          "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        }
+      }
+    },
     "buffer-alloc": {
       "version": "1.2.0",
       "resolved": "https://registry.npm.taobao.org/buffer-alloc/download/buffer-alloc-1.2.0.tgz",
@@ -42,6 +83,16 @@
       "resolved": "https://registry.npm.taobao.org/buffer-fill/download/buffer-fill-1.0.0.tgz",
       "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
     },
+    "bytes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/bytes/download/bytes-3.1.0.tgz?cache=0&sync_timestamp=1637015083874&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fbytes%2Fdownload%2Fbytes-3.1.0.tgz",
+      "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY="
+    },
+    "child_process": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npm.taobao.org/child_process/download/child_process-1.0.2.tgz",
+      "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
+    },
     "compressing": {
       "version": "1.5.1",
       "resolved": "https://registry.npm.taobao.org/compressing/download/compressing-1.5.1.tgz",
@@ -58,11 +109,69 @@
         "yazl": "^2.4.2"
       }
     },
+    "content-disposition": {
+      "version": "0.5.3",
+      "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz",
+      "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
+      "requires": {
+        "safe-buffer": "5.1.2"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz",
+          "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
+        }
+      }
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz",
+      "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js="
+    },
+    "cookie": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz?cache=0&sync_timestamp=1587525865178&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcookie%2Fdownload%2Fcookie-0.4.0.tgz",
+      "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo="
+    },
+    "cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz",
+      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+    },
     "core-util-is": {
       "version": "1.0.3",
       "resolved": "https://registry.nlark.com/core-util-is/download/core-util-is-1.0.3.tgz",
       "integrity": "sha1-pgQtNjTCsn6TKPg3uWX6yDgI24U="
     },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/download/debug-2.6.9.tgz",
+      "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+    },
     "end-of-stream": {
       "version": "1.4.4",
       "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz",
@@ -71,6 +180,60 @@
         "once": "^1.4.0"
       }
     },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz",
+      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+    },
+    "express": {
+      "version": "4.17.1",
+      "resolved": "https://registry.npm.taobao.org/express/download/express-4.17.1.tgz",
+      "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=",
+      "requires": {
+        "accepts": "~1.3.7",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.19.0",
+        "content-disposition": "0.5.3",
+        "content-type": "~1.0.4",
+        "cookie": "0.4.0",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "~1.1.2",
+        "fresh": "0.5.2",
+        "merge-descriptors": "1.0.1",
+        "methods": "~1.1.2",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "path-to-regexp": "0.1.7",
+        "proxy-addr": "~2.0.5",
+        "qs": "6.7.0",
+        "range-parser": "~1.2.1",
+        "safe-buffer": "5.1.2",
+        "send": "0.17.1",
+        "serve-static": "1.14.1",
+        "setprototypeof": "1.1.1",
+        "statuses": "~1.5.0",
+        "type-is": "~1.6.18",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz",
+          "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
+        }
+      }
+    },
     "fd-slicer": {
       "version": "1.1.0",
       "resolved": "https://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.1.0.tgz",
@@ -79,11 +242,35 @@
         "pend": "~1.2.0"
       }
     },
+    "finalhandler": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz",
+      "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=",
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
+        "unpipe": "~1.0.0"
+      }
+    },
     "flushwritable": {
       "version": "1.0.0",
       "resolved": "https://registry.npm.taobao.org/flushwritable/download/flushwritable-1.0.0.tgz",
       "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg="
     },
+    "forwarded": {
+      "version": "0.2.0",
+      "resolved": "https://registry.nlark.com/forwarded/download/forwarded-0.2.0.tgz?cache=0&sync_timestamp=1622503499867&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fforwarded%2Fdownload%2Fforwarded-0.2.0.tgz",
+      "integrity": "sha1-ImmTZCiq1MFcfr6XeahL8LKoGBE="
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+    },
     "fs-constants": {
       "version": "1.0.0",
       "resolved": "https://registry.npm.taobao.org/fs-constants/download/fs-constants-1.0.0.tgz",
@@ -94,6 +281,25 @@
       "resolved": "https://registry.npm.taobao.org/get-ready/download/get-ready-1.0.0.tgz",
       "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I="
     },
+    "http-errors": {
+      "version": "1.7.2",
+      "resolved": "https://registry.npmmirror.com/http-errors/download/http-errors-1.7.2.tgz?cache=0&sync_timestamp=1636932153279&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.2.tgz",
+      "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=",
+      "requires": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.3",
+        "setprototypeof": "1.1.1",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.0"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+        }
+      }
+    },
     "iconv-lite": {
       "version": "0.5.2",
       "resolved": "https://registry.nlark.com/iconv-lite/download/iconv-lite-0.5.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.5.2.tgz",
@@ -107,6 +313,11 @@
       "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz",
       "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
     },
+    "ipaddr.js": {
+      "version": "1.9.1",
+      "resolved": "https://registry.nlark.com/ipaddr.js/download/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha1-v/OFQ+64mEglB5/zoqjmy9RngbM="
+    },
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
@@ -117,6 +328,39 @@
       "resolved": "https://registry.npmmirror.com/js-base64/download/js-base64-3.7.2.tgz",
       "integrity": "sha1-gW0R2BqK/yQWA9Gc5XYeE+Qdd0U="
     },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+    },
+    "merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/mime/download/mime-1.6.0.tgz",
+      "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE="
+    },
+    "mime-db": {
+      "version": "1.51.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/download/mime-db-1.51.0.tgz?cache=0&sync_timestamp=1636426033377&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fmime-db%2Fdownload%2Fmime-db-1.51.0.tgz",
+      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
+    },
+    "mime-types": {
+      "version": "2.1.34",
+      "resolved": "https://registry.npmmirror.com/mime-types/download/mime-types-2.1.34.tgz?cache=0&sync_timestamp=1636432373429&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fmime-types%2Fdownload%2Fmime-types-2.1.34.tgz",
+      "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+      "requires": {
+        "mime-db": "1.51.0"
+      }
+    },
     "minimist": {
       "version": "1.2.5",
       "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1584051509720&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
@@ -130,6 +374,24 @@
         "minimist": "^1.2.5"
       }
     },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/download/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "negotiator": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz",
+      "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs="
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
     "once": {
       "version": "1.4.0",
       "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz",
@@ -138,6 +400,16 @@
         "wrappy": "1"
       }
     },
+    "parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz",
+      "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ="
+    },
+    "path-to-regexp": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz?cache=0&sync_timestamp=1601400247487&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-0.1.7.tgz",
+      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+    },
     "pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz",
@@ -148,6 +420,15 @@
       "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
       "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I="
     },
+    "proxy-addr": {
+      "version": "2.0.7",
+      "resolved": "https://registry.nlark.com/proxy-addr/download/proxy-addr-2.0.7.tgz",
+      "integrity": "sha1-8Z/mnOqzEe65S0LnDowgcPm6ECU=",
+      "requires": {
+        "forwarded": "0.2.0",
+        "ipaddr.js": "1.9.1"
+      }
+    },
     "pump": {
       "version": "3.0.0",
       "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz",
@@ -157,6 +438,37 @@
         "once": "^1.3.1"
       }
     },
+    "qs": {
+      "version": "6.7.0",
+      "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz",
+      "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw="
+    },
+    "range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz",
+      "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE="
+    },
+    "raw-body": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmmirror.com/raw-body/download/raw-body-2.4.0.tgz?cache=0&sync_timestamp=1637116782389&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fraw-body%2Fdownload%2Fraw-body-2.4.0.tgz",
+      "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=",
+      "requires": {
+        "bytes": "3.1.0",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
+        "unpipe": "1.0.0"
+      },
+      "dependencies": {
+        "iconv-lite": {
+          "version": "0.4.24",
+          "resolved": "https://registry.nlark.com/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz",
+          "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        }
+      }
+    },
     "readable-stream": {
       "version": "2.3.7",
       "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz",
@@ -188,6 +500,54 @@
       "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz",
       "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
     },
+    "send": {
+      "version": "0.17.1",
+      "resolved": "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz",
+      "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=",
+      "requires": {
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "destroy": "~1.0.4",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "~1.7.2",
+        "mime": "1.6.0",
+        "ms": "2.1.1",
+        "on-finished": "~2.3.0",
+        "range-parser": "~1.2.1",
+        "statuses": "~1.5.0"
+      },
+      "dependencies": {
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmmirror.com/ms/download/ms-2.1.1.tgz",
+          "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo="
+        }
+      }
+    },
+    "serve-static": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz",
+      "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=",
+      "requires": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.17.1"
+      }
+    },
+    "setprototypeof": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz?cache=0&sync_timestamp=1563425414995&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsetprototypeof%2Fdownload%2Fsetprototypeof-1.1.1.tgz",
+      "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM="
+    },
+    "statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1609654066899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+    },
     "streamifier": {
       "version": "0.1.1",
       "resolved": "https://registry.npm.taobao.org/streamifier/download/streamifier-0.1.1.tgz",
@@ -227,16 +587,45 @@
       "resolved": "https://registry.npm.taobao.org/to-buffer/download/to-buffer-1.1.1.tgz",
       "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA="
     },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/toidentifier/download/toidentifier-1.0.0.tgz?cache=0&sync_timestamp=1636938499270&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ftoidentifier%2Fdownload%2Ftoidentifier-1.0.0.tgz",
+      "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM="
+    },
+    "type-is": {
+      "version": "1.6.18",
+      "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz",
+      "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=",
+      "requires": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.24"
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz",
       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
+    "utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+    },
     "uuid": {
       "version": "8.3.2",
       "resolved": "https://registry.npmmirror.com/uuid/download/uuid-8.3.2.tgz",
       "integrity": "sha1-gNW1ztJxu5r2xEXyGhoExgbO++I="
     },
+    "vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz",
+      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+    },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz",
diff --git a/package.json b/package.json
index 99baccf..2262c42 100644
--- a/package.json
+++ b/package.json
@@ -5,8 +5,8 @@
   "main": "build.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
-    "build": "sh ./bin/build.sh",
-    "win": "cd bin && build.cmd"
+    "build": "node ./bin/build.js",
+    "start": "node ./bin/app.js"
   },
   "author": "",
   "license": "ISC",
@@ -14,6 +14,8 @@
     "base-64": "^1.0.0",
     "compressing": "^1.5.1",
     "js-base64": "^3.7.2",
-    "uuid": "^8.3.2"
+    "uuid": "^8.3.2",
+    "child_process": "^1.0.2",
+    "express": "^4.17.1"
   }
 }
diff --git a/play/assets/cocos_generator.meta b/play/assets/cocos_generator.meta
index a6ac487..35bb685 100644
--- a/play/assets/cocos_generator.meta
+++ b/play/assets/cocos_generator.meta
@@ -1,15 +1 @@
-{
-  "ver": "1.1.2",
-  "uuid": "c35bb2f6-f24a-4850-ae44-643f2fdc7541",
-  "isBundle": true,
-  "bundleName": "",
-  "priority": 1,
-  "compressionType": {},
-  "optimizeHotUpdate": {},
-  "inlineSpriteFrames": {},
-  "isRemoteBundle": {
-    "ios": true,
-    "android": true
-  },
-  "subMetas": {}
-}
\ No newline at end of file
+{"ver":"1.1.2","uuid":"c35bb2f6-f24a-4850-ae44-643f2fdc7541","isBundle":false,"bundleName":"","priority":1,"compressionType":{},"optimizeHotUpdate":{},"inlineSpriteFrames":{},"isRemoteBundle":{"ios":false,"android":false},"subMetas":{}}
\ No newline at end of file
-- 
2.21.0