浏览代码

first commit

tremble 5 年之前
父节点
当前提交
d4a4895f7d
共有 100 个文件被更改,包括 60360 次插入0 次删除
  1. 14 0
      browser_code/.gitignore
  2. 310 0
      browser_code/downloadController-注释.js
  3. 343 0
      browser_code/downloadController.js
  4. 17 0
      browser_code/index.html
  5. 87 0
      browser_code/main.js
  6. 2045 0
      browser_code/package-lock.json
  7. 19 0
      browser_code/package.json
  8. 0 0
      browser_code/preload.js
  9. 14 0
      download_code/.gitignore
  10. 420 0
      download_code/controller/downloadController.js
  11. 0 0
      download_code/controller/static/css/3.txt
  12. 368 0
      download_code/controller/static/css/base.css
  13. 9 0
      download_code/controller/static/css/cropper.min.css
  14. 252 0
      download_code/controller/static/css/cropper1.min.css
  15. 二进制
      download_code/controller/static/css/font/fontawesome-webfont.eot
  16. 655 0
      download_code/controller/static/css/font/fontawesome-webfont.svg
  17. 二进制
      download_code/controller/static/css/font/fontawesome-webfont.ttf
  18. 二进制
      download_code/controller/static/css/font/fontawesome-webfont.woff
  19. 二进制
      download_code/controller/static/css/font/fontawesome-webfont.woff2
  20. 14 0
      download_code/controller/static/css/font/hotImgs.json
  21. 二进制
      download_code/controller/static/css/font/vjs.ttf
  22. 二进制
      download_code/controller/static/css/font/vjs.woff
  23. 539 0
      download_code/controller/static/css/icon/demo.css
  24. 2930 0
      download_code/controller/static/css/icon/demo_index.html
  25. 497 0
      download_code/controller/static/css/icon/iconfont.css
  26. 二进制
      download_code/controller/static/css/icon/iconfont.eot
  27. 1 0
      download_code/controller/static/css/icon/iconfont.js
  28. 849 0
      download_code/controller/static/css/icon/iconfont.json
  29. 386 0
      download_code/controller/static/css/icon/iconfont.svg
  30. 二进制
      download_code/controller/static/css/icon/iconfont.ttf
  31. 二进制
      download_code/controller/static/css/icon/iconfont.woff
  32. 二进制
      download_code/controller/static/css/icon/iconfont.woff2
  33. 10162 0
      download_code/controller/static/css/mainApp.css
  34. 8592 0
      download_code/controller/static/css/mainPC.css
  35. 950 0
      download_code/controller/static/css/quill.snow.css
  36. 598 0
      download_code/controller/static/css/rulerLabel.css
  37. 12 0
      download_code/controller/static/css/swiper-4.3.5.min.css
  38. 2212 0
      download_code/controller/static/css/toolBoxApp.css
  39. 4945 0
      download_code/controller/static/css/toolBoxPC.css
  40. 1942 0
      download_code/controller/static/css/video-js.css
  41. 1 0
      download_code/controller/static/data/screenCap1.json
  42. 1 0
      download_code/controller/static/data/screenCap2.json
  43. 1 0
      download_code/controller/static/data/screenCap3.json
  44. 1 0
      download_code/controller/static/data/screenCap4.json
  45. 1 0
      download_code/controller/static/data/screenCap5.json
  46. 1 0
      download_code/controller/static/data/tourList.json
  47. 二进制
      download_code/controller/static/fonts/open-sans/OpenSansLight.eot
  48. 21034 0
      download_code/controller/static/fonts/open-sans/OpenSansLight.svg
  49. 二进制
      download_code/controller/static/fonts/open-sans/OpenSansLight.ttf
  50. 二进制
      download_code/controller/static/fonts/open-sans/OpenSansLight.woff
  51. 二进制
      download_code/controller/static/fonts/open-sans/OpenSansLight.woff2
  52. 二进制
      download_code/controller/static/fonts/open-sans/OpenSansRegular.woff
  53. 二进制
      download_code/controller/static/fonts/open-sans/OpenSansRegular.woff2
  54. 1 0
      download_code/controller/static/images/4dkk_icon.svg
  55. 137 0
      download_code/controller/static/images/4dkk_icon_en.svg
  56. 二进制
      download_code/controller/static/images/End.png
  57. 二进制
      download_code/controller/static/images/audio/01.mp3
  58. 二进制
      download_code/controller/static/images/audio/02.mp3
  59. 二进制
      download_code/controller/static/images/audio/03.mp3
  60. 二进制
      download_code/controller/static/images/audio/04.mp3
  61. 二进制
      download_code/controller/static/images/audio/05.mp3
  62. 二进制
      download_code/controller/static/images/audio/06.mp3
  63. 二进制
      download_code/controller/static/images/audio/07.mp3
  64. 二进制
      download_code/controller/static/images/audio/08.mp3
  65. 二进制
      download_code/controller/static/images/blueReticle.png
  66. 二进制
      download_code/controller/static/images/bottom_logo.png
  67. 二进制
      download_code/controller/static/images/btn-slider.png
  68. 二进制
      download_code/controller/static/images/cad_column.png
  69. 二进制
      download_code/controller/static/images/cad_door.png
  70. 二进制
      download_code/controller/static/images/cad_point.png
  71. 二进制
      download_code/controller/static/images/cad_window.png
  72. 二进制
      download_code/controller/static/images/canvasPlay.png
  73. 二进制
      download_code/controller/static/images/checked_hook.png
  74. 二进制
      download_code/controller/static/images/default.jpg
  75. 二进制
      download_code/controller/static/images/delAsk-bg.png
  76. 二进制
      download_code/controller/static/images/direction_click.png
  77. 二进制
      download_code/controller/static/images/direction_default.png
  78. 二进制
      download_code/controller/static/images/floorlogo/0.png
  79. 二进制
      download_code/controller/static/images/floorlogo/1.png
  80. 二进制
      download_code/controller/static/images/floorlogo/2.png
  81. 二进制
      download_code/controller/static/images/floorlogo/en/0.png
  82. 二进制
      download_code/controller/static/images/floorlogo/en/1.png
  83. 二进制
      download_code/controller/static/images/floorlogo/en/2.png
  84. 二进制
      download_code/controller/static/images/icon-kankan-style-1.png
  85. 二进制
      download_code/controller/static/images/icon-kankan-style-2.png
  86. 二进制
      download_code/controller/static/images/icon-kankan-style-3.png
  87. 二进制
      download_code/controller/static/images/icon_Google_Chrome_2011.png
  88. 二进制
      download_code/controller/static/images/icon_Internet_Explorer_10.png
  89. 二进制
      download_code/controller/static/images/icon_MacOSX_Safari.png
  90. 二进制
      download_code/controller/static/images/icon_Mozilla_Firefox.png
  91. 二进制
      download_code/controller/static/images/icon_biaochi_defult.png
  92. 二进制
      download_code/controller/static/images/icon_biaochi_select.png
  93. 二进制
      download_code/controller/static/images/icon_close_black.png
  94. 二进制
      download_code/controller/static/images/icon_feiji.png
  95. 二进制
      download_code/controller/static/images/input-bg.png
  96. 二进制
      download_code/controller/static/images/labelline.png
  97. 二进制
      download_code/controller/static/images/line-1.png
  98. 二进制
      download_code/controller/static/images/loadFail.png
  99. 二进制
      download_code/controller/static/images/lock-bg.png
  100. 0 0
      download_code/controller/static/images/marker.png

+ 14 - 0
browser_code/.gitignore

@@ -0,0 +1,14 @@
+.DS_Store
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

+ 310 - 0
browser_code/downloadController-注释.js

@@ -0,0 +1,310 @@
+let OSS = require('ali-oss');
+let fs = require('fs');
+let path = require('path');
+var archiver = require('archiver');
+let request = require("request");
+let http = require('http');
+
+let compressPercent = 0;
+let taskCodeQueue = [];
+let taskDownloaderQueue = {};
+let pathConfig = {
+  ossPrefix: 'http://4dkankan.oss-cn-shenzhen.aliyuncs.com/',  // oss前缀
+  // serverPrefix: 'http://192.168.0.61:8888/',  // 服务器前缀
+  serverPrefix: 'https://test.4dkankan.com/back/down/server/controller/',  // 服务器前缀
+  localDataName: 'localData',
+  layer: './',  // 层级
+  rootFold: 'tmpData',   // 根目录文件夹
+  staticPath: [   // 静态数据路径
+    'static'
+  ],
+  paths: [  // images/data路径
+    'images/images',
+    'data/data'
+  ],
+  filters: ['tiles'],
+  dynamicPath: [   // 一些使用api加载的数据, 提前写入json中
+    'http://pro.4dkankan.com/api/scene/getInfo'
+  ],
+}
+
+function downloader() {
+  this.objArr = [];
+  this.completeFolds = 0;   // 记录已经递归完成的目录, completeFolds == foldNum, 表示所有目录递归完成
+  this.fileNum = 0;  // 需要下载的文件总数
+  this.completeFileNum = 0;  // 已经下载完成的文件总数
+  this.threadNum = 10;   // 同时并发的线程总数
+  this.curActiveThread = 0;
+  this.sta = 0;
+  this.downloadProcess = 0;  // 下载进度
+  this.zipProcess = 0;   // 压缩进度
+  this.sceneCode = '';   // 场景码
+  this.sceneInfo = '';   // 场景的其他json数据
+
+  this.downloadResponse = null;
+  this.timer = null;   // 定时器
+  this.dirPath = path.join(__dirname, pathConfig.rootFold);
+
+  this.foldNum = pathConfig.paths.length + pathConfig.staticPath.length;   // 记录目录的总数, 用于判断是否目录是否递归完成
+  this.client = new OSS({   // 配置阿里云oss
+    region: 'oss-cn-shenzhen',
+    accessKeyId: 'LTAIUrvuHqj8pvry',
+    accessKeySecret: 'JLOVl0k8Ke0aaM8nLMMiUAZ3EiiqI4',
+    bucket: '4dkankan',
+  })
+}
+
+/**
+ * 创建文件夹
+ * @param data 文件路径
+ */
+downloader.prototype.createRootFold = function (data) {
+  if (!fs.existsSync(this.dirPath)) {
+    fs.mkdirSync(this.dirPath);
+  } else {
+    console.log('文件夹已存在');
+  }
+  this.dirPath = path.join(this.dirPath, '/' + data);
+  // 创建文件夹目录
+  if (!fs.existsSync(this.dirPath)) {
+    fs.mkdirSync(this.dirPath);
+  } else {
+    console.log('文件夹已存在');
+  }
+}
+
+/**
+ * 递归列举所有需要下载的文件, 记录文件夹以及所有文件的总数
+ */
+downloader.prototype.listDir = async function (dir, prefixDir) {
+  let that = this;
+  for (let i = 0; i < pathConfig.filters.length; i++) {   // 有些文件夹不需要下载, 则进行过滤
+    let filter = pathConfig.filters[i];
+    if (dir.indexOf(filter) > 0) {
+      console.log('过滤的路径' + dir);
+      that.completeFolds++;
+      if (that.completeFolds === that.foldNum) {   // 已经列举完成的文件夹数目等于需要下载的文件夹总数
+        that.fileNum = that.objArr.length;
+        that.timer = setInterval(that.download, 16);  // 开始下载
+      }
+      return;
+    }
+  }
+
+  // 列举当前文件夹中的所有文件, 最多1000个
+  let result = await this.client.list({
+    prefix: dir,
+    delimiter: '/',
+    'max-keys': 1000 // 最大限制1000
+  });
+  dirArr = `${prefixDir}${dir}`.split('/');   // 分割其目录层级
+  let tmpDir = '';
+  let childDirPath;
+  dirArr.forEach((item) => {  // 对于路径中的每一个层级, 都创建对应的文件夹
+    tmpDir += '/' + item;
+    childDirPath = path.join(this.dirPath, '/' + tmpDir);  // 子路径
+    if (!fs.existsSync(childDirPath)) {
+      fs.mkdirSync(childDirPath);
+      console.log('创建文件夹成功:  ' + childDirPath);
+    } else {
+      console.log('文件夹已存在');
+    }
+  });
+  // result.objects就是当前文件夹下的所有文件
+  result.objects && result.objects.forEach(async function (obj) {
+    let downloadURL = pathConfig.ossPrefix + obj.name;   // 记录每个文件需要下载的url
+    let arr = obj.name.split('/');
+    let objName = arr[arr.length - 1];   // 获取文件名, 上面的obj.name除了文件名, 还包含了文件所属的路径
+    if (objName === '') {  // 过滤非法文件, 因为阿里云有时候会把文件夹当作文件返回, 
+      return;   
+    }
+    let writeURL = path.join(childDirPath, objName);   // 下载完成后, 应当写入的路径
+    let tack = {   // 创建下载任务
+      downloadURL: downloadURL,
+      writeURL: writeURL
+    }
+    that.objArr.push(tack);   // 下载任务入列
+  });
+
+  if (result.prefixes) {   // 如果当前目录还有子目录存在, 则继续递归
+    this.foldNum--;    // 移除当前目录, 因为当前目录还不是最深层级
+    let that = this;
+    result.prefixes.forEach(function (subDir) {
+      that.foldNum++;  // 记录当前目录的子目录
+      that.listDir(subDir, prefixDir);
+    });
+  } else {   // 当前目录已经递归完成
+    this.completeFolds++;
+    console.log(this.completeFolds + '  ' + this.foldNum)
+    if (this.completeFolds === this.foldNum) {  // 已经列举完成的文件夹数目等于需要下载的文件夹总数
+      // console.log(this.objArr)
+      this.fileNum = this.objArr.length;   // 记录需要下载的文件总数
+      this.timer = setInterval(this.download.bind(this), 16);   // 开始下载
+    }
+  }
+}
+
+downloader.prototype.download = function () {
+
+  if (this.objArr.length === 0) {   // 所有文件已经下载完成, 清楚定时器
+    clearInterval(this.timer);
+    this.timer = null;
+    return;
+  }
+  if (this.curActiveThread <= this.threadNum) {    // 当前活跃的线程数<总线程数, 则继续创建创建下载队列, 控制并发
+    let task = this.objArr.shift();   // 取队列中的第一个任务
+    let stream = fs.createWriteStream(task.writeURL);   // 根据任务中的写入路径创建流
+    let readStream = request(task.downloadURL).on('error', function () {   // 通过下载路径去请求文件
+      console.log("文件[" + task.downloadURL + "]下载出错  ");
+    }).pipe(stream);
+
+    let that = this;
+    readStream.on('finish', function () {  // 当前流下载完成, 释放线程
+      that.curActiveThread--;  
+    })
+    stream.on('finish', function () {   // 文件写入完毕
+      that.completeFileNum++;   // 已经下载完成的文件数+1
+      that.downloadProcess = that.completeFileNum / that.fileNum * 100;   // 计算下载进度
+      if (that.completeFileNum === that.fileNum) {   // 所有的oss文件已下载完
+        let sceneCode = that.sceneCode;  // 记录场景码
+        // sceneData.json的写入路径, sceneData.json记录的是场景中的其他信息, 如场景描述、场景密码等可配置信息
+        let sceneJsonPath = path.join(__dirname, `tmpData/${sceneCode}/static/images/images${sceneCode}/sceneData.json`);  
+        // code.txt的写入路径, 其记录的是场景码, 本地浏览器需要读取该文件
+        let sceneCodePath = path.join(__dirname, `tmpData/${sceneCode}/code.txt`);
+        fs.writeFile(sceneJsonPath, that.sceneInfo, function (err) {  // 写入sceneInfo.json
+          if (err) {
+            return console.log(`写入文件出错: ${err}`);
+          }
+          fs.writeFile(sceneCodePath , sceneCode , function (err) {   // 将场景码写入
+            console.log('开始压缩' + that.sceneCode)
+            // let zipStream = fs.createWriteStream(`${__dirname}/tmpData/${that.sceneCode}/` + `/localData.zip`);
+            let zipStream = fs.createWriteStream(`${__dirname}/tmpData/zip/` + `/${that.sceneCode}.zip`);  // 创建压缩包
+            pathConfig.localDataName = that.sceneCode;
+
+            let archive = archiver('zip', {
+              zlib: {
+                level: 9  // 压缩等级
+              }
+            });
+            zipStream.on('close', function () {
+              let respData = 'archiver has been finalized and the output file descriptor has closed.';
+              console.log(archive.pointer() + ' total bytes');
+              console.log('文件压缩已写入完成');
+              // 重置两个进度
+              downloadPercent = 0;
+              compressPercent = 0;
+            });
+            // 计算压缩进度
+            archive.on('progress', function (process) {
+              compressPercent = that.zipProcess = process.fs.processedBytes / process.fs.totalBytes * 100;
+            })
+            archive.on('error', function (err) {
+              console.log(err);
+            })
+            archive.pipe(zipStream);
+            archive.directory(`${__dirname}/tmpData/${that.sceneCode}/`, false);  // 将已经下载完成的全部内容放入至压缩流中
+            archive.directory(`${__dirname}/static/page`, false);  // 追加html文件
+            archive.directory(`${__dirname}/browser/`, false);  // 将浏览器放入压缩流中
+            archive.finalize();
+          })
+        })
+      }
+    })
+    this.curActiveThread++;  // 激活的线程数+1
+  }
+}
+
+downloader.prototype.execute = function (data) {
+  console.log(data);
+  this.createRootFold(data);
+  pathConfig.paths.forEach(path => {
+    this.listDir(path + data, `static/`);
+  })
+  pathConfig.staticPath.forEach(path => {
+    this.listDir(path, '');
+  })
+}
+
+/**
+ * 起始函数
+ * @param {*} response 响应
+ * @param {*} data 前端传过来的数据
+ */
+function start(response, data) {
+  let sceneCode = data.sceneCode;
+  let respData;
+  // 如果已经存在压缩包, 则直接返回压缩包的路径给浏览器进行下载
+  if (fs.existsSync(`${__dirname}/${pathConfig.rootFold}/${sceneCode}/${pathConfig.localDataName}.zip`)) {
+    respData = {
+      sta: 1003,   // 1003 文件已存在
+      data: {
+        percent: 100,
+        url: `${pathConfig.serverPrefix}${pathConfig.rootFold}/${sceneCode}/${pathConfig.localDataName}.zip`
+      },
+      msg: '文件已存在, 直接返回url'
+    };
+    console.log('文件已存在, 直接返回url');
+  } else {
+    respData = {
+      sta: 1002,   // 1002 
+      data: {
+        percent: 0
+      },
+      msg: '已加入任务队列'
+    };
+    taskCodeQueue.push(sceneCode);
+    taskDownloaderQueue[sceneCode] = new downloader();   // 对于每个前端发来的下载请求, 创建一个downloader实例
+    taskDownloaderQueue[sceneCode].sceneCode = data.sceneCode;
+    taskDownloaderQueue[sceneCode].sceneInfo = data.sceneInfo;  // sceneInfo就是场景中其他的可配置信息, 用于写入sceneData.json中
+  }
+  let json = JSON.stringify(respData)
+  response.send(json);
+}
+
+/**
+ * 查询下载进度
+ * @param {*} response 响应
+ * @param {*} data 前端传过来的数据
+ */
+function downloadProcess(response, data) {
+  let sceneCode = data.sceneCode;
+  let downloader = taskDownloaderQueue[sceneCode];
+  if (!downloader) return;
+  if (downloader.downloadProcess < 100) {   // 文件正在下载中
+    let respData = {
+      sta: 1000,   // 状态码 1000-文件正在下载 1001-文件正在压缩
+      data: {
+        percent: downloader.downloadProcess
+      },
+      msg: '文件下载中'
+    };
+    let json = JSON.stringify(respData)
+    response.send(json);
+  } else {  // 文件正在压缩中
+    let respData = {
+      sta: 1001,   // 状态码 1000-文件正在下载 1001-文件正在压缩
+      data: {
+        percent: downloader.zipProcess
+      },
+      msg: '文件压缩中'
+    };
+    if (downloader.zipProcess === 100) {
+      respData.data.url = `${pathConfig.serverPrefix}${pathConfig.rootFold}/zip/${pathConfig.localDataName}.zip`
+    }
+    let json = JSON.stringify(respData)
+    response.send(json);
+  }
+}
+
+(function () {
+  // 服务器的downloader队列, 每隔1s处理一个前端的下载请求, 避免服务器压力过大
+  setInterval(function () {
+    let taskCode = taskCodeQueue.shift();
+    if (taskCode) {
+      taskDownloaderQueue[taskCode].execute(taskCode);
+    }
+  }, 1000)
+})()
+
+exports.start = start;
+exports.downloadProcess = downloadProcess;

+ 343 - 0
browser_code/downloadController.js

@@ -0,0 +1,343 @@
+let OSS = require('ali-oss');
+let fs = require('fs');
+let path = require('path');
+var archiver = require('archiver');
+let request = require("request");
+let http = require('http');
+
+let compressPercent = 0;
+let taskCodeQueue = [];
+let taskDownloaderQueue = {};
+let pathConfig = {
+  ossPrefix: 'http://4dkankan.oss-cn-shenzhen.aliyuncs.com/',  // oss前缀
+  // serverPrefix: 'http://192.168.0.61:8888/',  // 服务器前缀
+  serverPrefix: 'https://test.4dkankan.com/back/down/server/controller/',  // 服务器前缀
+  localDataName: 'localData',
+  layer: './',  // 层级
+  rootFold: 'tmpData',   // 根目录文件夹
+  staticPath: [   // 静态数据路径
+    'static'
+  ],
+  paths: [  // images/data路径
+    'images/images',
+    'data/data'
+  ],
+  filters: ['tiles'],
+  dynamicPath: [   // 一些使用api加载的数据, 提前写入json中
+    'http://pro.4dkankan.com/api/scene/getInfo'
+  ],
+}
+
+function downloader() {
+  this.objArr = [];
+  this.completeFolds = 0;   // 记录已经递归完成的目录, completeFolds == foldNum, 表示所有目录递归完成
+  this.fileNum = 0;  // 需要下载的文件总数
+  this.completeFileNum = 0;  // 已经下载完成的文件总数
+  this.threadNum = 10;   // 同时并发的线程总数
+  this.curActiveThread = 0;
+  this.sta = 0;
+  this.downloadProcess = 0;  // 下载进度
+  this.zipProcess = 0;   // 压缩进度
+  this.sceneCode = '';   // 场景码
+  this.sceneInfo = '';   // 场景的其他json数据
+
+  this.downloadResponse = null;
+  this.timer = null;   // 定时器
+  this.dirPath = path.join(__dirname, pathConfig.rootFold);
+
+  this.foldNum = pathConfig.paths.length + pathConfig.staticPath.length;   // 记录目录的总数, 用于判断是否目录是否递归完成
+  this.client = new OSS({   // 配置阿里云oss
+    region: 'oss-cn-shenzhen',
+    accessKeyId: 'LTAIUrvuHqj8pvry',
+    accessKeySecret: 'JLOVl0k8Ke0aaM8nLMMiUAZ3EiiqI4',
+    bucket: '4dkankan',
+  })
+}
+
+downloader.prototype.createRootFold = function (data) {
+  //console.log('pathpath' + this.dirPath);
+  if (!fs.existsSync(this.dirPath)) {
+    fs.mkdirSync(this.dirPath);
+  } else {
+    console.log('文件夹已存在');
+  }
+  this.dirPath = path.join(this.dirPath, '/' + data);
+  // 创建文件夹目录
+
+  if (!fs.existsSync(this.dirPath)) {
+    fs.mkdirSync(this.dirPath);
+  } else {
+    console.log('文件夹已存在');
+  }
+  // this.dirPath = path.join(this.dirPath, '/' + 'static');  
+  // // 创建文件夹目录
+  // if (!fs.existsSync(this.dirPath)) {
+  //     fs.mkdirSync(this.dirPath);
+  // } else {
+  //     console.log('文件夹已存在');
+  // }
+}
+
+downloader.prototype.listDir = async function (dir, prefixDir) {
+  let that = this;
+  for (let i = 0; i < pathConfig.filters.length; i++) {
+    let filter = pathConfig.filters[i];
+    if (dir.indexOf(filter) > 0) {
+      console.log('过滤的路径' + dir);
+      that.completeFolds++;
+      if (that.completeFolds === that.foldNum) {
+        that.fileNum = that.objArr.length;
+        that.timer = setInterval(that.download, 16);
+      }
+      return;
+    }
+  }
+
+  let result = await this.client.list({
+    prefix: dir,
+    delimiter: '/',
+    'max-keys': 1000 // 最大限制1000
+  });
+  // let dirArr = [];
+  // if(staticSta){
+  //     dirArr = `static/${dir}`.split('/');
+  // }else{
+
+  // }
+  dirArr = `${prefixDir}${dir}`.split('/');
+  let tmpDir = '';
+  let childDirPath;
+  dirArr.forEach((item) => {
+    tmpDir += '/' + item;
+    childDirPath = path.join(this.dirPath, '/' + tmpDir);
+    if (!fs.existsSync(childDirPath)) {
+      fs.mkdirSync(childDirPath);
+      console.log('创建文件夹成功:  ' + childDirPath);
+    } else {
+      console.log('文件夹已存在');
+    }
+  });
+  result.objects && result.objects.forEach(async function (obj) {
+    let downloadURL = pathConfig.ossPrefix + obj.name;
+    let arr = obj.name.split('/');
+    let objName = arr[arr.length - 1];
+    if (objName === '') {
+      return;   // 过滤非法文件, 因为阿里云有时候会把文件夹当作文件返回, 
+    }
+    // if(obj.name.indexOf('images') >-1){
+    //     console.log(obj);
+    // }
+    // let writeURL = childDirPath + '/' + objName;
+    let writeURL = path.join(childDirPath, objName);
+    let tack = {
+      downloadURL: downloadURL,
+      writeURL: writeURL
+    }
+    that.objArr.push(tack);
+  });
+
+  if (result.prefixes) {   // 如果当前目录还有子目录存在, 则继续递归
+    this.foldNum--;    // 移除当前目录
+    let that = this;
+    result.prefixes.forEach(function (subDir) {
+      that.foldNum++;  // 记录当前目录的子目录
+      that.listDir(subDir, prefixDir);
+    });
+  } else {   // 当前目录已经递归完成
+    this.completeFolds++;
+    console.log(this.completeFolds + '  ' + this.foldNum)
+    if (this.completeFolds === this.foldNum) {
+      // console.log(this.objArr)
+      this.fileNum = this.objArr.length;
+      this.timer = setInterval(this.download.bind(this), 16);
+    }
+  }
+}
+
+downloader.prototype.download = function () {
+
+  if (this.objArr.length === 0) {
+    clearInterval(this.timer);
+    this.timer = null;
+    return;
+  }
+  if (this.curActiveThread <= this.threadNum) {
+    let task = this.objArr.shift();
+    let stream = fs.createWriteStream(task.writeURL);
+    let readStream = request(task.downloadURL).on('error', function () {
+      console.log("文件[" + task.downloadURL + "]下载出错  ");
+    }).pipe(stream);
+
+    let that = this;
+    readStream.on('finish', function () {
+      that.curActiveThread--;  // 释放线程
+    })
+    stream.on('finish', function () {
+      that.completeFileNum++;
+      that.downloadProcess = that.completeFileNum / that.fileNum * 100;
+      if (that.completeFileNum === that.fileNum) {   // oss文件已下载完
+        let sceneCode = that.sceneCode;
+        let sceneJsonPath = path.join(__dirname, `tmpData/${sceneCode}/static/images/images${sceneCode}/sceneData.json`);
+        let sceneCodePath = path.join(__dirname, `tmpData/${sceneCode}/code.txt`);
+        fs.writeFile(sceneJsonPath, that.sceneInfo, function (err) {  // 写入sceneInfo.json
+          if (err) {
+            return console.log(`写入文件出错: ${err}`);
+          }
+          fs.writeFile(sceneCodePath , sceneCode , function (err) {   // 将场景码写入
+            console.log('开始压缩' + that.sceneCode)
+            // console.log(`scene: ${that.sceneCode}`);
+            // let zipStream = fs.createWriteStream(`${__dirname}/tmpData/${that.sceneCode}/` + `/localData.zip`);
+            let zipStream = fs.createWriteStream(`${__dirname}/tmpData/zip/` + `/${that.sceneCode}.zip`);
+            pathConfig.localDataName = that.sceneCode;
+
+            let archive = archiver('zip', {
+              zlib: {
+                level: 9
+              }
+            });
+            zipStream.on('close', function () {
+              let respData = 'archiver has been finalized and the output file descriptor has closed.';
+              console.log(archive.pointer() + ' total bytes');
+              console.log('文件压缩已写入完成');
+              // 重置两个进度
+              downloadPercent = 0;
+              compressPercent = 0;
+            });
+            archive.on('progress', function (process) {
+              compressPercent = that.zipProcess = process.fs.processedBytes / process.fs.totalBytes * 100;
+            })
+            archive.on('error', function (err) {
+              console.log(err);
+            })
+            archive.pipe(zipStream);
+            archive.directory(`${__dirname}/tmpData/${that.sceneCode}/`, false);  // 放入static目录中
+            archive.directory(`${__dirname}/static/page`, false);  // 放入static目录中
+            archive.directory(`${__dirname}/browser/`, false);  // 将浏览器放入压缩包中
+            // archive.directory(pathConfig.staticPath, 'static');   // 追加固定的文件资源
+            // archive.directory(`${__dirname}/static/`, 'static');
+            archive.finalize();
+          })
+        })
+      }
+    })
+    this.curActiveThread++;
+  }
+}
+
+downloader.prototype.getJson = function (url, callback) {
+  console.log(url);
+  http.get(url, res => {
+    let body = '';
+    res.on('data', chunk => {
+      body += chunk;
+    });
+    res.on('end', () => {
+      // let resp = JSON.parse(body);
+      console.log(body);
+      // callback(resp);
+    })
+  })
+}
+
+downloader.prototype.loadDynamicInfo = function (sceneCode) {
+  for (let i = 0; i < pathConfig.dynamicPath.length; i++) {
+    let time = new Date().getTime();
+    let url = `${pathConfig.dynamicPath[i]}?num=${sceneCode}&t=${time}`;
+    this.getJson(url);
+  }
+}
+
+downloader.prototype.execute = function (data) {
+  console.log(data);
+  this.createRootFold(data);
+  pathConfig.paths.forEach(path => {
+    this.listDir(path + data, `static/`);
+  })
+  pathConfig.staticPath.forEach(path => {
+    this.listDir(path, '');
+  })
+  // this.sceneInfo = data.sceneInfo
+  // this.loadDynamicInfo(this.sceneInfo);
+}
+
+function start(response, data) {
+  let sceneCode = data.sceneCode;
+  let respData;
+  console.log(`${__dirname}/${pathConfig.rootFold}/${sceneCode}/${pathConfig.localDataName}.zip`)
+  if (fs.existsSync(`${__dirname}/${pathConfig.rootFold}/${sceneCode}/${pathConfig.localDataName}.zip`)) {
+    //console.log(`${__dirname}/zip/${sceneCode}/${pathConfig.localDataName}.zip`)
+    //if (fs.existsSync(`${__dirname}/zip/${sceneCode}/${pathConfig.localDataName}.zip`)) {
+    respData = {
+      sta: 1003,   // 1003 文件已存在
+      data: {
+        percent: 100,
+        url: `${pathConfig.serverPrefix}${pathConfig.rootFold}/${sceneCode}/${pathConfig.localDataName}.zip`
+      },
+      msg: '文件已存在, 直接返回url'
+    };
+    console.log('文件已存在, 直接返回url');
+  } else {
+    respData = {
+      sta: 1002,   // 1002 
+      data: {
+        percent: 0
+      },
+      msg: '已加入任务队列'
+    };
+    taskCodeQueue.push(sceneCode);
+    taskDownloaderQueue[sceneCode] = new downloader();
+    taskDownloaderQueue[sceneCode].sceneCode = data.sceneCode;
+    taskDownloaderQueue[sceneCode].sceneInfo = data.sceneInfo;
+  }
+  let json = JSON.stringify(respData)
+  // response.writeHead(200, { "Content-Type": "application/json" });
+  response.send(json);
+  // response.end();
+}
+
+function downloadProcess(response, data) {
+  let sceneCode = data.sceneCode;
+  let downloader = taskDownloaderQueue[sceneCode];
+  if (!downloader) return;
+  if (downloader.downloadProcess < 100) {
+    let respData = {
+      sta: 1000,   // 状态码 1000-文件正在下载 1001-文件正在压缩
+      data: {
+        percent: downloader.downloadProcess
+      },
+      msg: '文件下载中'
+    };
+    let json = JSON.stringify(respData)
+    // response.writeHead(200, { "Content-Type": "application/json" });
+    response.send(json);
+    // response.end();
+  } else {
+    let respData = {
+      sta: 1001,   // 状态码 1000-文件正在下载 1001-文件正在压缩
+      data: {
+        percent: downloader.zipProcess
+      },
+      msg: '文件压缩中'
+    };
+    if (downloader.zipProcess === 100) {
+      // respData.data.url = `${pathConfig.serverPrefix}${pathConfig.rootFold}/${downloader.sceneCode}/${pathConfig.localDataName}.zip`
+      respData.data.url = `${pathConfig.serverPrefix}${pathConfig.rootFold}/zip/${pathConfig.localDataName}.zip`
+    }
+    let json = JSON.stringify(respData)
+    // response.writeHead(200, { "Content-Type": "application/json" });
+    response.send(json);
+    // response.end();
+  }
+}
+
+(function () {
+  setInterval(function () {
+    let taskCode = taskCodeQueue.shift();
+    if (taskCode) {
+      taskDownloaderQueue[taskCode].execute(taskCode);
+    }
+  }, 1000)
+})()
+
+exports.start = start;
+exports.downloadProcess = downloadProcess;

+ 17 - 0
browser_code/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <title>Hello World!</title>
+  </head>
+  <body>
+    <h1>Hello World!</h1>
+    <!-- All of the Node.js APIs are available in this renderer process. -->
+    We are using Node.js <script>document.write(process.versions.node)</script>,
+    Chromium <script>document.write(process.versions.chrome)</script>,
+    and Electron <script>document.write(process.versions.electron)</script>.
+
+    <script>
+    </script>
+  </body>
+</html>

+ 87 - 0
browser_code/main.js

@@ -0,0 +1,87 @@
+// Modules to control application life and create native browser window
+const {
+  app,
+  BrowserWindow
+} = require('electron')
+
+const httpServer = require('http-server/lib/http-server')
+const fs = require("fs");
+
+const server = httpServer.createServer({
+  // root:__dirname
+  root: '../'
+})
+
+server.listen(9000)
+
+
+
+const path = require('path')
+
+// Keep a global reference of the window object, if you don't, the window will
+// be closed automatically when the JavaScript object is garbage collected.
+let mainWindow
+
+function createWindow() {
+  // Create the browser window.
+  mainWindow = new BrowserWindow({
+    width: 800,
+    height: 600,
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: false,
+      webSecurity: true
+    }
+  })
+
+  // and load the index.html of the app.
+  //mainWindow.loadFile('index.html')
+  fs.readFile('../code.txt', 'utf-8', function (err, data) {
+    let sceneArr = []
+    if (err) {
+      console.error(err);
+    }
+    else {
+      console.log(data);
+      sceneArr = data.split(',')
+    }
+    mainWindow.loadURL(`http://localhost:9000/showProPC.html?m=${sceneArr[0]}`, {
+      userAgent: '5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3497.100 Safari/537.36'
+    })
+    
+  })
+
+
+    // Emitted when the window is closed.
+    mainWindow.on('closed', function () {
+      // Dereference the window object, usually you would store windows
+      // in an array if your app supports multi windows, this is the time
+      // when you should delete the corresponding element.
+      mainWindow = null
+    })
+}
+
+// This method will be called when Electron has finished
+// initialization and is ready to create browser windows.
+// Some APIs can only be used after this event occurs.
+app.on('ready', createWindow)
+
+// Quit when all windows are closed.
+app.on('window-all-closed', function () {
+  // On OS X it is common for applications and their menu bar
+  // to stay active until the user quits explicitly with Cmd + Q
+  if (process.platform !== 'darwin') {
+    app.quit()
+  }
+})
+
+app.on('activate', function () {
+  // On OS X it's common to re-create a window in the app when the
+  // dock icon is clicked and there are no other windows open.
+  if (mainWindow === null) {
+    createWindow()
+  }
+})
+
+// In this file you can include the rest of your app's specific main process
+// code. You can also put them in separate files and require them here.

文件差异内容过多而无法显示
+ 2045 - 0
browser_code/package-lock.json


+ 19 - 0
browser_code/package.json

@@ -0,0 +1,19 @@
+{
+  "name": "map",
+  "version": "1.0.0",
+  "main": "main.js",
+  "scripts": {
+    "start": "electron .",
+    "buildWin": "electron-packager . 4dkankan --platform=win32 --overwrite=true --arch=x64 --out=./dists --asar --app-version=3.0.4 --ignore=\"(dists|data)\""
+  },
+  "devDependencies": {
+    "electron": "^3.0.4",
+    "electron-packager": "^12.2.0"
+  },
+  "dependencies": {
+    "eventemitter3": "^4.0.0",
+    "http-proxy": "^1.18.0",
+    "http-server": "^0.12.1",
+    "storejs": "^1.0.20"
+  }
+}

+ 0 - 0
browser_code/preload.js


+ 14 - 0
download_code/.gitignore

@@ -0,0 +1,14 @@
+.DS_Store
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

+ 420 - 0
download_code/controller/downloadController.js

@@ -0,0 +1,420 @@
+let OSS = require('ali-oss');
+let fs = require('fs');
+let path = require('path');
+var archiver = require('archiver');
+let request = require("request");
+let http = require('http');
+
+let compressPercent = 0;
+let taskCodeQueue = [];
+let taskDownloaderQueue = {};
+let pathConfig = {
+  ossPrefix: 'http://4dkankan.oss-cn-shenzhen.aliyuncs.com/',  // oss前缀
+  // serverPrefix: 'http://192.168.0.208:8887/',  // 服务器前缀
+  serverPrefix: 'https://www.4dage.com/download_scene/controller/',  // 服务器前缀
+  localDataName: 'localData',
+  layer: './',  // 层级
+  rootFold: 'tmpData',   // 根目录文件夹
+  staticPath: [   // 静态数据路径
+    'static'
+  ],
+  paths: [  // images/data路径
+    'images/images',
+    'data/data',
+    'voice/voice',
+    'video/video'
+  ],
+  editPaths:[
+    'images/images',
+    'data/data',
+    'voice/voice'
+  ],
+  filters: [],
+  dynamicPath: [   // 一些使用api加载的数据, 提前写入json中
+    'https://www.4dkankan.com/api/scene/getInfo'
+  ],
+  downloadUrlServer:'https://www.4dkankan.com/'
+}
+
+function getEditDataUrl(num,cb = ()=>{}) {
+
+  let URL = `https://www.4dkankan.com/api/scene/getEditDataUrl?num=${num}`
+  let data = ''
+  request(URL,(error, response, body)=>{
+    if (!error) {
+      let temp = JSON.parse(body)
+      if (temp.code==0) {
+        data=temp.data
+        cb(data)
+      }
+    }
+  })
+
+}
+
+
+function downloader() {
+  this.objArr = [];
+  this.completeFolds = 0;   // 记录已经递归完成的目录, completeFolds == foldNum, 表示所有目录递归完成
+  this.fileNum = 0;  // 需要下载的文件总数
+  this.completeFileNum = 0;  // 已经下载完成的文件总数
+  this.threadNum = 10;   // 同时并发的线程总数
+  this.curActiveThread = 0;
+  this.sta = 0;
+  this.downloadProcess = 0;  // 下载进度
+  this.zipProcess = 0;   // 压缩进度
+  this.sceneCode = '';   // 场景码
+  this.sceneCodeArr = [] // 场景码数据
+  this.snCode = '' //sn码
+  this.isTiles = true;   // 是否下载tiles
+  this.sceneInfo = '';   // 场景的其他json数据
+
+  this.downloadResponse = null;
+  this.timer = null;   // 定时器
+  this.dirPath = path.join(__dirname, pathConfig.rootFold);
+
+  this.foldNum = pathConfig.paths.length + pathConfig.staticPath.length;   // 记录目录的总数, 用于判断是否目录是否递归完成
+  this.client = new OSS({   // 配置阿里云oss
+    region: 'oss-cn-shenzhen',
+    accessKeyId: 'LTAIUrvuHqj8pvry',
+    accessKeySecret: 'JLOVl0k8Ke0aaM8nLMMiUAZ3EiiqI4',
+    bucket: '4dkankan',
+  })
+}
+
+/**
+ * 创建文件夹
+ * @param data 文件路径
+ */
+downloader.prototype.createRootFold = function (data) {
+  if (!fs.existsSync(this.dirPath)) {
+    fs.mkdirSync(this.dirPath);
+  } else {
+    // console.log('文件夹已存在');
+  }
+  this.dirPath = path.join(this.dirPath, '/' + data);
+  // 创建文件夹目录
+  if (!fs.existsSync(this.dirPath)) {
+    fs.mkdirSync(this.dirPath);
+  } else {
+    // console.log('文件夹已存在');
+  }
+  console.log('-------dirPath---------',this.dirPath)
+}
+
+/**
+ * 递归列举编辑页面需要下载的文件, 记录文件夹以及所有文件的总数
+ */
+
+downloader.prototype.listEditDir = async function (editUrl) {
+  let that = this;
+
+  editUrl.forEach(item=>{
+    let dirArr = item.split('/')
+    let objName = dirArr.pop()
+    let tmpDir = '';
+    let childDirPath;
+
+    dirArr.forEach((sub) => {  // 对于路径中的每一个层级, 都创建对应的文件夹
+      tmpDir += '/' + sub;
+      childDirPath = path.join(this.dirPath, '/' + tmpDir);  // 子路径
+      if (!fs.existsSync(childDirPath)) {
+        fs.mkdirSync(childDirPath);
+        // console.log('创建文件夹成功:  ' + childDirPath);
+      } else {
+        // console.log('文件夹已存在');
+      }
+    });
+
+    let downloadURL = pathConfig.downloadUrlServer + item;   // 记录每个文件需要下载的url
+    if (objName === '') {  // 过滤非法文件, 因为阿里云有时候会把文件夹当作文件返回, 
+      return;   
+    }
+    let writeURL = path.join(childDirPath, objName);   // 下载完成后, 应当写入的路径
+    let tack = {   // 创建下载任务
+      downloadURL: downloadURL,
+      writeURL: writeURL
+    }
+
+    that.objArr.push(tack);
+
+    // this.completeFolds++;
+    // this.timer = setInterval(this.download.bind(this), 16);   // 开始下载
+  })
+  
+}
+
+/**
+ * 递归列举所有需要下载的文件, 记录文件夹以及所有文件的总数
+ */
+downloader.prototype.listDir = async function (dir, prefixDir) {
+  let that = this;
+  let filters = pathConfig.filters
+  if (!that.isTiles) {
+    filters.push('tiles')
+  }
+
+  
+  for (let i = 0; i < filters.length; i++) {   // 有些文件夹不需要下载, 则进行过滤
+    let filter = filters[i];
+    if (dir.indexOf(filter) > 0) {
+      console.log('过滤的路径' + dir);
+      that.completeFolds++;
+      if (that.completeFolds === that.foldNum) {   // 已经列举完成的文件夹数目等于需要下载的文件夹总数
+        that.fileNum = that.objArr.length;
+        that.timer = setInterval(that.download, 16);  // 开始下载
+      }
+      return;
+    }
+  }
+
+
+  dirArr = `${prefixDir}${dir}`.split('/');   // 分割其目录层级
+  let tmpDir = '';
+  let childDirPath;
+  dirArr.forEach((item) => {  // 对于路径中的每一个层级, 都创建对应的文件夹
+    tmpDir += '/' + item;
+    childDirPath = path.join(this.dirPath, '/' + tmpDir);  // 子路径
+    if (!fs.existsSync(childDirPath)) {
+      fs.mkdirSync(childDirPath);
+      // console.log('创建文件夹成功:  ' + childDirPath);
+    } else {
+      // console.log('文件夹已存在');
+    }
+  });
+
+
+
+  // 列举当前文件夹中的所有文件, 最多1000个
+  let result = await this.client.list({
+    prefix: dir,
+    delimiter: '/',
+    'max-keys': 1000 // 最大限制1000
+  });
+  // result.objects就是当前文件夹下的所有文件
+  result.objects && result.objects.forEach(async function (obj) {
+    let downloadURL = pathConfig.ossPrefix + obj.name;   // 记录每个文件需要下载的url
+    let arr = obj.name.split('/');
+    let objName = arr[arr.length - 1];   // 获取文件名, 上面的obj.name除了文件名, 还包含了文件所属的路径
+    if (objName === '') {  // 过滤非法文件, 因为阿里云有时候会把文件夹当作文件返回, 
+      return;   
+    }
+    let writeURL = path.join(childDirPath, objName);   // 下载完成后, 应当写入的路径
+    let tack = {   // 创建下载任务
+      downloadURL: downloadURL,
+      writeURL: writeURL
+    }
+
+    that.objArr.push(tack);   // 下载任务入列
+  });
+
+  if (result.prefixes) {   // 如果当前目录还有子目录存在, 则继续递归
+    this.foldNum--;    // 移除当前目录, 因为当前目录还不是最深层级
+    let that = this;
+    result.prefixes.forEach(function (subDir) {
+      that.foldNum++;  // 记录当前目录的子目录
+      that.listDir(subDir, prefixDir);
+    });
+  } else {   // 当前目录已经递归完成
+    this.completeFolds++;
+    console.log(this.completeFolds + '  ' + this.foldNum)
+    if (this.completeFolds === this.foldNum) {  // 已经列举完成的文件夹数目等于需要下载的文件夹总数
+      // console.log(this.objArr)
+      this.fileNum = this.objArr.length;   // 记录需要下载的文件总数
+      this.timer = setInterval(this.download.bind(this), 16);   // 开始下载
+    }
+  }
+}
+
+downloader.prototype.download = function () {
+
+  if (this.objArr.length === 0) {   // 所有文件已经下载完成, 清楚定时器
+    clearInterval(this.timer);
+    this.timer = null;
+    return;
+  }
+  if (this.curActiveThread <= this.threadNum) {    // 当前活跃的线程数<总线程数, 则继续创建创建下载队列, 控制并发
+    let task = this.objArr.shift();   // 取队列中的第一个任务
+    let stream = fs.createWriteStream(task.writeURL);   // 根据任务中的写入路径创建流
+    let readStream = request(task.downloadURL).on('error', function () {   // 通过下载路径去请求文件
+      console.log("文件[" + task.downloadURL + "]下载出错  ");
+    }).pipe(stream);
+
+    let that = this;
+    readStream.on('finish', function () {  // 当前流下载完成, 释放线程
+      that.curActiveThread--;  
+    })
+    stream.on('finish', function () {   // 文件写入完毕
+      that.completeFileNum++;   // 已经下载完成的文件数+1
+      that.downloadProcess = that.completeFileNum / that.fileNum * 100;   // 计算下载进度
+      if (that.completeFileNum === that.fileNum) {   // 所有的oss文件已下载完
+        let sceneCode = that.sceneCode;  // 记录场景码
+        let sceneCodeArr = that.sceneCodeArr;  // 记录场景码数组
+        let snCode = that.snCode
+
+        let sceneCodePath = path.join(__dirname, `tmpData/${snCode}/code.txt`);
+
+        fs.writeFileSync(sceneCodePath , '')
+        
+        sceneCodeArr.forEach((item,idx)=>{
+            // sceneData.json的写入路径, sceneData.json记录的是场景中的其他信息, 如场景描述、场景密码等可配置信息
+            let sceneJsonPath = path.join(__dirname, `tmpData/${snCode}/static/images/images${item.sceneCode}/sceneData.json`);  
+            // code.txt的写入路径, 其记录的是场景码, 本地浏览器需要读取该文件
+            
+            fs.writeFileSync(sceneJsonPath, item.sceneInfo, function (err) {  // 写入sceneInfo.json
+              if (err) {
+                return console.log(`写入文件出错: ${err}`);
+              }
+            })
+            fs.writeFileSync(sceneCodePath , item.sceneCode+(idx===sceneCodeArr.length-1?'':','),{flag:'a'}, function (err,code) {   // 将场景码写入
+                console.log('-----code-----',code)
+            })
+        })
+
+        console.log('开始压缩' + that.sceneCode)
+        // let zipStream = fs.createWriteStream(`${__dirname}/tmpData/${that.sceneCode}/` + `/localData.zip`);
+        let zipStream = fs.createWriteStream(`${__dirname}/tmpData/zip/` + `/${snCode}.zip`);  // 创建压缩包
+        pathConfig.localDataName = snCode;
+
+        let archive = archiver('zip', {
+          zlib: {
+            level: 9  // 压缩等级
+          }
+        });
+        zipStream.on('close', function () {
+          let respData = 'archiver has been finalized and the output file descriptor has closed.';
+          console.log(archive.pointer() + ' total bytes');
+          console.log('文件压缩已写入完成');
+          // 重置两个进度
+          downloadPercent = 0;
+          compressPercent = 0;
+        });
+        // 计算压缩进度
+        archive.on('progress', function (process) {
+          compressPercent = that.zipProcess = process.fs.processedBytes / process.fs.totalBytes * 100;
+        })
+        archive.on('error', function (err) {
+          console.log(err);
+        })
+        archive.pipe(zipStream);
+        archive.directory(`${__dirname}/tmpData/${snCode}/`, false);  // 将已经下载完成的全部内容放入至压缩流中
+        archive.directory(`${__dirname}/static/page`, false);  // 追加html文件
+        archive.directory(`${__dirname}/browser/`, false);  // 将浏览器放入压缩流中
+        archive.finalize();
+      }
+    })
+    this.curActiveThread++;  // 激活的线程数+1
+  }
+}
+
+downloader.prototype.execute = function (data) {
+  // let arr = ['t-updScXn','t-J3VGU9J']
+  this.createRootFold(this.snCode);
+  this.sceneCodeArr.forEach(item => {
+    getEditDataUrl(item.sceneCode, (res)=>{
+      this.listEditDir(res);
+      pathConfig.paths.forEach(path => {
+        this.listDir(path + item.sceneCode, `static/`);
+      })
+      pathConfig.staticPath.forEach(path => {
+        this.listDir(path, '');
+      })
+    })
+  })
+  
+}
+
+/**
+ * 起始函数
+ * @param {*} response 响应
+ * @param {*} data 前端传过来的数据
+ */
+function start(response, data) {
+  let sceneCode = data.sceneCode;
+  let sceneCodeArr = data.sceneCodeArr
+  let snCode = data.snCode
+  let respData;
+  // 如果已经存在压缩包, 则直接返回压缩包的路径给浏览器进行下载
+  if (fs.existsSync(`${__dirname}/${pathConfig.rootFold}/${snCode}/${pathConfig.localDataName}.zip`)) {
+    respData = {
+      sta: 1003,   // 1003 文件已存在
+      data: {
+        percent: 100,
+        url: `${pathConfig.serverPrefix}${pathConfig.rootFold}/${snCode}/${pathConfig.localDataName}.zip`
+      },
+      msg: '文件已存在, 直接返回url'
+    };
+    // console.log('文件已存在, 直接返回url');
+  } else {
+    respData = {
+      sta: 1002,   // 1002 
+      data: {
+        percent: 0
+      },
+      msg: '已加入任务队列'
+    };
+    taskCodeQueue.push(snCode);
+    taskDownloaderQueue[snCode] = new downloader();   // 对于每个前端发来的下载请求, 创建一个downloader实例
+
+    // taskDownloaderQueue[snCode].sceneCode = data.sceneCode;
+    taskDownloaderQueue[snCode].sceneCodeArr = sceneCodeArr;
+    taskDownloaderQueue[snCode].snCode = snCode;
+
+
+    // taskDownloaderQueue[snCode].sceneCode = data.sceneCode;
+    taskDownloaderQueue[snCode].isTiles = data.isTiles;
+    // taskDownloaderQueue[snCode].sceneInfo = data.sceneInfo;  // sceneInfo就是场景中其他的可配置信息, 用于写入sceneData.json中
+  }
+  let json = JSON.stringify(respData)
+  response.send(json);
+}
+
+/**
+ * 查询下载进度
+ * @param {*} response 响应
+ * @param {*} data 前端传过来的数据
+ */
+function downloadProcess(response, data) {
+  let snCode = data.snCode;
+  let downloader = taskDownloaderQueue[snCode];
+  if (!downloader) return;
+  if (downloader.downloadProcess < 100) {   // 文件正在下载中
+    let respData = {
+      sta: 1000,   // 状态码 1000-文件正在下载 1001-文件正在压缩
+      data: {
+        percent: downloader.downloadProcess
+      },
+      msg: '文件下载中'
+    };
+    let json = JSON.stringify(respData)
+    response.send(json);
+  } else {  // 文件正在压缩中
+    let respData = {
+      sta: 1001,   // 状态码 1000-文件正在下载 1001-文件正在压缩
+      data: {
+        percent: downloader.zipProcess
+      },
+      msg: '文件压缩中'
+    };
+    if (downloader.zipProcess === 100) {
+      respData.data.url = `${pathConfig.serverPrefix}${pathConfig.rootFold}/zip/${pathConfig.localDataName}.zip`
+    }
+    let json = JSON.stringify(respData)
+    response.send(json);
+  }
+}
+
+(function () {
+  // 服务器的downloader队列, 每隔1s处理一个前端的下载请求, 避免服务器压力过大
+
+  setInterval(function () {
+    let taskCode = taskCodeQueue.shift();
+    if (taskCode) {
+      taskDownloaderQueue[taskCode].execute(taskCode);
+    }
+  }, 1000)
+})()
+
+exports.start = start;
+exports.downloadProcess = downloadProcess;
+

+ 0 - 0
download_code/controller/static/css/3.txt


+ 368 - 0
download_code/controller/static/css/base.css

@@ -0,0 +1,368 @@
+/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+   ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+ *{
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    outline: none;
+    -webkit-appearance: none;
+    appearance: none;
+    -webkit-tap-highlight-color:rgba(255,255,255,0); /* 禁止ios点击有阴影 */
+}
+
+html {
+   line-height: 1.15; /* 1 */
+   -webkit-text-size-adjust: 100%; /* 2 */
+ }
+ 
+ /* Sections
+    ========================================================================== */
+ 
+ /**
+  * Remove the margin in all browsers.
+  */
+ 
+ body {
+   margin: 0;
+ }
+ 
+ /**
+  * Correct the font size and margin on `h1` elements within `section` and
+  * `article` contexts in Chrome, Firefox, and Safari.
+  */
+ 
+ h1 {
+   font-size: 2em;
+   margin: 0.67em 0;
+ }
+ 
+ /* Grouping content
+    ========================================================================== */
+ 
+ /**
+  * 1. Add the correct box sizing in Firefox.
+  * 2. Show the overflow in Edge and IE.
+  */
+ 
+ hr {
+   box-sizing: content-box; /* 1 */
+   height: 0; /* 1 */
+   overflow: visible; /* 2 */
+ }
+ 
+ /**
+  * 1. Correct the inheritance and scaling of font size in all browsers.
+  * 2. Correct the odd `em` font sizing in all browsers.
+  */
+ 
+ pre {
+   font-family: monospace, monospace; /* 1 */
+   font-size: 1em; /* 2 */
+ }
+ 
+
+ 
+ /* Text-level semantics
+    ========================================================================== */
+ 
+ /**
+  * Remove the gray background on active links in IE 10.
+  */
+ 
+ a {
+   background-color: transparent;
+ }
+ 
+ /**
+  * 1. Remove the bottom border in Chrome 57-
+  * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+  */
+ 
+ abbr[title] {
+   border-bottom: none; /* 1 */
+   text-decoration: underline; /* 2 */
+   text-decoration: underline dotted; /* 2 */
+ }
+ 
+ /**
+  * Add the correct font weight in Chrome, Edge, and Safari.
+  */
+ 
+ b,
+ strong {
+   font-weight: bolder;
+ }
+ 
+ /**
+  * 1. Correct the inheritance and scaling of font size in all browsers.
+  * 2. Correct the odd `em` font sizing in all browsers.
+  */
+ 
+ code,
+ kbd,
+ samp {
+   font-family: monospace, monospace; /* 1 */
+   font-size: 1em; /* 2 */
+ }
+ 
+ /**
+  * Add the correct font size in all browsers.
+  */
+ 
+ small {
+   font-size: 80%;
+ }
+ 
+ /**
+  * Prevent `sub` and `sup` elements from affecting the line height in
+  * all browsers.
+  */
+ 
+ sub,
+ sup {
+   font-size: 75%;
+   line-height: 0;
+   position: relative;
+   vertical-align: baseline;
+ }
+ 
+ sub {
+   bottom: -0.25em;
+ }
+ 
+ sup {
+   top: -0.5em;
+ }
+ 
+ /* Embedded content
+    ========================================================================== */
+ 
+ /**
+  * Remove the border on images inside links in IE 10.
+  */
+ 
+ img {
+   border-style: none;
+ }
+ 
+ /* Forms
+    ========================================================================== */
+ 
+ /**
+  * 1. Change the font styles in all browsers.
+  * 2. Remove the margin in Firefox and Safari.
+  */
+ 
+ button,
+ input,
+ optgroup,
+ select,
+ textarea {
+   font-family: inherit; /* 1 */
+   font-size: 100%; /* 1 */
+   line-height: 1.15; /* 1 */
+   margin: 0; /* 2 */
+ }
+ 
+ /**
+  * Show the overflow in IE.
+  * 1. Show the overflow in Edge.
+  */
+ 
+ button,
+ input { /* 1 */
+   overflow: visible;
+ }
+ 
+ /**
+  * Remove the inheritance of text transform in Edge, Firefox, and IE.
+  * 1. Remove the inheritance of text transform in Firefox.
+  */
+ 
+ button,
+ select { /* 1 */
+   text-transform: none;
+ }
+ 
+ /**
+  * Correct the inability to style clickable types in iOS and Safari.
+  */
+ 
+ button,
+ [type="button"],
+ [type="reset"],
+ [type="submit"] {
+   -webkit-appearance: button;
+ }
+ 
+ /**
+  * Remove the inner border and padding in Firefox.
+  */
+ 
+ button::-moz-focus-inner,
+ [type="button"]::-moz-focus-inner,
+ [type="reset"]::-moz-focus-inner,
+ [type="submit"]::-moz-focus-inner {
+   border-style: none;
+   padding: 0;
+ }
+ 
+ /**
+  * Restore the focus styles unset by the previous rule.
+  */
+ 
+ button:-moz-focusring,
+ [type="button"]:-moz-focusring,
+ [type="reset"]:-moz-focusring,
+ [type="submit"]:-moz-focusring {
+   outline: 1px dotted ButtonText;
+ }
+ 
+ /**
+  * Correct the padding in Firefox.
+  */
+ 
+ fieldset {
+   padding: 0.35em 0.75em 0.625em;
+ }
+ 
+ /**
+  * 1. Correct the text wrapping in Edge and IE.
+  * 2. Correct the color inheritance from `fieldset` elements in IE.
+  * 3. Remove the padding so developers are not caught out when they zero out
+  *    `fieldset` elements in all browsers.
+  */
+ 
+ legend {
+   box-sizing: border-box; /* 1 */
+   color: inherit; /* 2 */
+   display: table; /* 1 */
+   max-width: 100%; /* 1 */
+   padding: 0; /* 3 */
+   white-space: normal; /* 1 */
+ }
+ 
+ /**
+  * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+  */
+ 
+ progress {
+   vertical-align: baseline;
+ }
+ 
+ /**
+  * Remove the default vertical scrollbar in IE 10+.
+  */
+ 
+ textarea {
+   overflow: auto;
+ }
+ 
+ /**
+  * 1. Add the correct box sizing in IE 10.
+  * 2. Remove the padding in IE 10.
+  */
+ 
+ [type="checkbox"],
+ [type="radio"] {
+   box-sizing: border-box; /* 1 */
+   padding: 0; /* 2 */
+ }
+ 
+ /**
+  * Correct the cursor style of increment and decrement buttons in Chrome.
+  */
+ 
+ [type="number"]::-webkit-inner-spin-button,
+ [type="number"]::-webkit-outer-spin-button {
+   height: auto;
+ }
+ 
+ /**
+  * 1. Correct the odd appearance in Chrome and Safari.
+  * 2. Correct the outline style in Safari.
+  */
+ 
+ [type="search"] {
+   -webkit-appearance: textfield; /* 1 */
+   outline-offset: -2px; /* 2 */
+ }
+ 
+ /**
+  * Remove the inner padding in Chrome and Safari on macOS.
+  */
+ 
+ [type="search"]::-webkit-search-decoration {
+   -webkit-appearance: none;
+ }
+ 
+ /**
+  * 1. Correct the inability to style clickable types in iOS and Safari.
+  * 2. Change font properties to `inherit` in Safari.
+  */
+ 
+ ::-webkit-file-upload-button {
+   -webkit-appearance: button; /* 1 */
+   font: inherit; /* 2 */
+ }
+ 
+ /* Interactive
+    ========================================================================== */
+ 
+ /*
+  * Add the correct display in Edge, IE 10+, and Firefox.
+  */
+ 
+ details {
+   display: block;
+ }
+ 
+ /*
+  * Add the correct display in all browsers.
+  */
+ 
+ summary {
+   display: list-item;
+ }
+ 
+ /* Misc
+    ========================================================================== */
+ 
+ /**
+  * Add the correct display in IE 10+.
+  */
+ 
+ template {
+   display: none;
+ }
+ 
+ /**
+  * Add the correct display in IE 10.
+  */
+ 
+ [hidden] {
+   display: none;
+ }
+
+ ul,li{
+   list-style: none;
+   margin: 0;
+   padding: 0;
+ }
+ 
+ 
+ 
+ 
+  .outer-chain.loadError  iframe pre{color: #ff4848}
+
+ 
+ 
+ 
+ 

文件差异内容过多而无法显示
+ 9 - 0
download_code/controller/static/css/cropper.min.css


+ 252 - 0
download_code/controller/static/css/cropper1.min.css

@@ -0,0 +1,252 @@
+/*!
+ * Cropper v3.1.3
+ * https://github.com/fengyuanchen/cropper
+ *
+ * Copyright (c) 2014-2017 Chen Fengyuan
+ * Released under the MIT license
+ *
+ * Date: 2017-10-21T10:03:37.133Z
+ */.cropper-container {
+ direction:ltr;
+ font-size:0;
+ line-height:0;
+ position:relative;
+ -ms-touch-action:none;
+ touch-action:none;
+ -webkit-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
+ user-select:none
+}
+.cropper-container img {
+ display:block;
+ height:100%;
+ image-orientation:0deg;
+ max-height:none!important;
+ max-width:none!important;
+ min-height:0!important;
+ min-width:0!important;
+ width:100%
+}
+.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box {
+ bottom:0;
+ left:0;
+ position:absolute;
+ right:0;
+ top:0
+}
+.cropper-canvas,.cropper-wrap-box {
+ overflow:hidden
+}
+.cropper-drag-box {
+ background-color:#fff;
+ opacity:0
+}
+.cropper-modal {
+ background-color:#000;
+ opacity:.5
+}
+.cropper-view-box {
+ display:block;
+ height:100%;
+ outline-color:rgba(51,153,255,.75);
+ outline:1px solid #39f;
+ overflow:hidden;
+ width:100%
+}
+.cropper-dashed {
+ border:0 dashed #eee;
+ display:block;
+ opacity:.5;
+ position:absolute
+}
+.cropper-dashed.dashed-h {
+ border-bottom-width:1px;
+ border-top-width:1px;
+ height:33.33333%;
+ left:0;
+ top:33.33333%;
+ width:100%
+}
+.cropper-dashed.dashed-v {
+ border-left-width:1px;
+ border-right-width:1px;
+ height:100%;
+ left:33.33333%;
+ top:0;
+ width:33.33333%
+}
+.cropper-center {
+ display:block;
+ height:0;
+ left:50%;
+ opacity:.75;
+ position:absolute;
+ top:50%;
+ width:0
+}
+.cropper-center:after,.cropper-center:before {
+ background-color:#eee;
+ content:" ";
+ display:block;
+ position:absolute
+}
+.cropper-center:before {
+ height:1px;
+ left:-3px;
+ top:0;
+ width:7px
+}
+.cropper-center:after {
+ height:7px;
+ left:0;
+ top:-3px;
+ width:1px
+}
+.cropper-face,.cropper-line,.cropper-point {
+ display:block;
+ height:100%;
+ opacity:.1;
+ position:absolute;
+ width:100%
+}
+.cropper-face {
+ background-color:#fff;
+ left:0;
+ top:0
+}
+.cropper-line {
+ background-color:#39f
+}
+.cropper-line.line-e {
+ cursor:e-resize;
+ right:-3px;
+ top:0;
+ width:5px
+}
+.cropper-line.line-n {
+ cursor:n-resize;
+ height:5px;
+ left:0;
+ top:-3px
+}
+.cropper-line.line-w {
+ cursor:w-resize;
+ left:-3px;
+ top:0;
+ width:5px
+}
+.cropper-line.line-s {
+ bottom:-3px;
+ cursor:s-resize;
+ height:5px;
+ left:0
+}
+.cropper-point {
+ background-color:#39f;
+ height:5px;
+ opacity:.75;
+ width:5px
+}
+.cropper-point.point-e {
+ cursor:e-resize;
+ margin-top:-3px;
+ right:-3px;
+ top:50%
+}
+.cropper-point.point-n {
+ cursor:n-resize;
+ left:50%;
+ margin-left:-3px;
+ top:-3px
+}
+.cropper-point.point-w {
+ cursor:w-resize;
+ left:-3px;
+ margin-top:-3px;
+ top:50%
+}
+.cropper-point.point-s {
+ bottom:-3px;
+ cursor:s-resize;
+ left:50%;
+ margin-left:-3px
+}
+.cropper-point.point-ne {
+ cursor:ne-resize;
+ right:-3px;
+ top:-3px
+}
+.cropper-point.point-nw {
+ cursor:nw-resize;
+ left:-3px;
+ top:-3px
+}
+.cropper-point.point-sw {
+ bottom:-3px;
+ cursor:sw-resize;
+ left:-3px
+}
+.cropper-point.point-se {
+ bottom:-3px;
+ cursor:se-resize;
+ height:20px;
+ opacity:1;
+ right:-3px;
+ width:20px
+}
+@media (min-width:768px) {
+ .cropper-point.point-se {
+  height:15px;
+  width:15px
+ }
+}
+@media (min-width:992px) {
+ .cropper-point.point-se {
+  height:10px;
+  width:10px
+ }
+}
+@media (min-width:1200px) {
+ .cropper-point.point-se {
+  height:5px;
+  opacity:.75;
+  width:5px
+ }
+}
+.cropper-point.point-se:before {
+ background-color:#39f;
+ bottom:-50%;
+ content:" ";
+ display:block;
+ height:200%;
+ opacity:0;
+ position:absolute;
+ right:-50%;
+ width:200%
+}
+.cropper-invisible {
+ opacity:0
+}
+.cropper-bg {
+ background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")
+}
+.cropper-hide {
+ display:block;
+ height:0;
+ position:absolute;
+ width:0
+}
+.cropper-hidden {
+ display:none!important
+}
+.cropper-move {
+ cursor:move
+}
+.cropper-crop {
+ cursor:crosshair
+}
+.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point {
+ cursor:not-allowed
+}
+/*# sourceMappingURL=cropper.min.css.map */

二进制
download_code/controller/static/css/font/fontawesome-webfont.eot


文件差异内容过多而无法显示
+ 655 - 0
download_code/controller/static/css/font/fontawesome-webfont.svg


二进制
download_code/controller/static/css/font/fontawesome-webfont.ttf


二进制
download_code/controller/static/css/font/fontawesome-webfont.woff


二进制
download_code/controller/static/css/font/fontawesome-webfont.woff2


文件差异内容过多而无法显示
+ 14 - 0
download_code/controller/static/css/font/hotImgs.json


二进制
download_code/controller/static/css/font/vjs.ttf


二进制
download_code/controller/static/css/font/vjs.woff


+ 539 - 0
download_code/controller/static/css/icon/demo.css

@@ -0,0 +1,539 @@
+/* Logo 字体 */
+@font-face {
+  font-family: "iconfont logo";
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
+}
+
+.logo {
+  font-family: "iconfont logo";
+  font-size: 160px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+/* tabs */
+.nav-tabs {
+  position: relative;
+}
+
+.nav-tabs .nav-more {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  height: 42px;
+  line-height: 42px;
+  color: #666;
+}
+
+#tabs {
+  border-bottom: 1px solid #eee;
+}
+
+#tabs li {
+  cursor: pointer;
+  width: 100px;
+  height: 40px;
+  line-height: 40px;
+  text-align: center;
+  font-size: 16px;
+  border-bottom: 2px solid transparent;
+  position: relative;
+  z-index: 1;
+  margin-bottom: -1px;
+  color: #666;
+}
+
+
+#tabs .active {
+  border-bottom-color: #f00;
+  color: #222;
+}
+
+.tab-container .content {
+  display: none;
+}
+
+/* 页面布局 */
+.main {
+  padding: 30px 100px;
+  width: 960px;
+  margin: 0 auto;
+}
+
+.main .logo {
+  color: #333;
+  text-align: left;
+  margin-bottom: 30px;
+  line-height: 1;
+  height: 110px;
+  margin-top: -50px;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.main .logo a {
+  font-size: 160px;
+  color: #333;
+}
+
+.helps {
+  margin-top: 40px;
+}
+
+.helps pre {
+  padding: 20px;
+  margin: 10px 0;
+  border: solid 1px #e7e1cd;
+  background-color: #fffdef;
+  overflow: auto;
+}
+
+.icon_lists {
+  width: 100% !important;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.icon_lists li {
+  width: 100px;
+  margin-bottom: 10px;
+  margin-right: 20px;
+  text-align: center;
+  list-style: none !important;
+  cursor: default;
+}
+
+.icon_lists li .code-name {
+  line-height: 1.2;
+}
+
+.icon_lists .icon {
+  display: block;
+  height: 100px;
+  line-height: 100px;
+  font-size: 42px;
+  margin: 10px auto;
+  color: #333;
+  -webkit-transition: font-size 0.25s linear, width 0.25s linear;
+  -moz-transition: font-size 0.25s linear, width 0.25s linear;
+  transition: font-size 0.25s linear, width 0.25s linear;
+}
+
+.icon_lists .icon:hover {
+  font-size: 100px;
+}
+
+.icon_lists .svg-icon {
+  /* 通过设置 font-size 来改变图标大小 */
+  width: 1em;
+  /* 图标和文字相邻时,垂直对齐 */
+  vertical-align: -0.15em;
+  /* 通过设置 color 来改变 SVG 的颜色/fill */
+  fill: currentColor;
+  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
+      normalize.css 中也包含这行 */
+  overflow: hidden;
+}
+
+.icon_lists li .name,
+.icon_lists li .code-name {
+  color: #666;
+}
+
+/* markdown 样式 */
+.markdown {
+  color: #666;
+  font-size: 14px;
+  line-height: 1.8;
+}
+
+.highlight {
+  line-height: 1.5;
+}
+
+.markdown img {
+  vertical-align: middle;
+  max-width: 100%;
+}
+
+.markdown h1 {
+  color: #404040;
+  font-weight: 500;
+  line-height: 40px;
+  margin-bottom: 24px;
+}
+
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+  color: #404040;
+  margin: 1.6em 0 0.6em 0;
+  font-weight: 500;
+  clear: both;
+}
+
+.markdown h1 {
+  font-size: 28px;
+}
+
+.markdown h2 {
+  font-size: 22px;
+}
+
+.markdown h3 {
+  font-size: 16px;
+}
+
+.markdown h4 {
+  font-size: 14px;
+}
+
+.markdown h5 {
+  font-size: 12px;
+}
+
+.markdown h6 {
+  font-size: 12px;
+}
+
+.markdown hr {
+  height: 1px;
+  border: 0;
+  background: #e9e9e9;
+  margin: 16px 0;
+  clear: both;
+}
+
+.markdown p {
+  margin: 1em 0;
+}
+
+.markdown>p,
+.markdown>blockquote,
+.markdown>.highlight,
+.markdown>ol,
+.markdown>ul {
+  width: 80%;
+}
+
+.markdown ul>li {
+  list-style: circle;
+}
+
+.markdown>ul li,
+.markdown blockquote ul>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown>ul li p,
+.markdown>ol li p {
+  margin: 0.6em 0;
+}
+
+.markdown ol>li {
+  list-style: decimal;
+}
+
+.markdown>ol li,
+.markdown blockquote ol>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown code {
+  margin: 0 3px;
+  padding: 0 5px;
+  background: #eee;
+  border-radius: 3px;
+}
+
+.markdown strong,
+.markdown b {
+  font-weight: 600;
+}
+
+.markdown>table {
+  border-collapse: collapse;
+  border-spacing: 0px;
+  empty-cells: show;
+  border: 1px solid #e9e9e9;
+  width: 95%;
+  margin-bottom: 24px;
+}
+
+.markdown>table th {
+  white-space: nowrap;
+  color: #333;
+  font-weight: 600;
+}
+
+.markdown>table th,
+.markdown>table td {
+  border: 1px solid #e9e9e9;
+  padding: 8px 16px;
+  text-align: left;
+}
+
+.markdown>table th {
+  background: #F7F7F7;
+}
+
+.markdown blockquote {
+  font-size: 90%;
+  color: #999;
+  border-left: 4px solid #e9e9e9;
+  padding-left: 0.8em;
+  margin: 1em 0;
+}
+
+.markdown blockquote p {
+  margin: 0;
+}
+
+.markdown .anchor {
+  opacity: 0;
+  transition: opacity 0.3s ease;
+  margin-left: 8px;
+}
+
+.markdown .waiting {
+  color: #ccc;
+}
+
+.markdown h1:hover .anchor,
+.markdown h2:hover .anchor,
+.markdown h3:hover .anchor,
+.markdown h4:hover .anchor,
+.markdown h5:hover .anchor,
+.markdown h6:hover .anchor {
+  opacity: 1;
+  display: inline-block;
+}
+
+.markdown>br,
+.markdown>p>br {
+  clear: both;
+}
+
+
+.hljs {
+  display: block;
+  background: white;
+  padding: 0.5em;
+  color: #333333;
+  overflow-x: auto;
+}
+
+.hljs-comment,
+.hljs-meta {
+  color: #969896;
+}
+
+.hljs-string,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-strong,
+.hljs-emphasis,
+.hljs-quote {
+  color: #df5000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+  color: #a71d5d;
+}
+
+.hljs-literal,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-attribute {
+  color: #0086b3;
+}
+
+.hljs-section,
+.hljs-name {
+  color: #63a35c;
+}
+
+.hljs-tag {
+  color: #333333;
+}
+
+.hljs-title,
+.hljs-attr,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo {
+  color: #795da3;
+}
+
+.hljs-addition {
+  color: #55a532;
+  background-color: #eaffea;
+}
+
+.hljs-deletion {
+  color: #bd2c00;
+  background-color: #ffecec;
+}
+
+.hljs-link {
+  text-decoration: underline;
+}
+
+/* 代码高亮 */
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+  color: black;
+  background: none;
+  text-shadow: 0 1px white;
+  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+  text-align: left;
+  white-space: pre;
+  word-spacing: normal;
+  word-break: normal;
+  word-wrap: normal;
+  line-height: 1.5;
+
+  -moz-tab-size: 4;
+  -o-tab-size: 4;
+  tab-size: 4;
+
+  -webkit-hyphens: none;
+  -moz-hyphens: none;
+  -ms-hyphens: none;
+  hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection,
+pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection,
+code[class*="language-"] ::-moz-selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection,
+pre[class*="language-"] ::selection,
+code[class*="language-"]::selection,
+code[class*="language-"] ::selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+@media print {
+
+  code[class*="language-"],
+  pre[class*="language-"] {
+    text-shadow: none;
+  }
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+  padding: 1em;
+  margin: .5em 0;
+  overflow: auto;
+}
+
+:not(pre)>code[class*="language-"],
+pre[class*="language-"] {
+  background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre)>code[class*="language-"] {
+  padding: .1em;
+  border-radius: .3em;
+  white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+  color: slategray;
+}
+
+.token.punctuation {
+  color: #999;
+}
+
+.namespace {
+  opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+  color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+  color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+  color: #9a6e3a;
+  background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+  color: #07a;
+}
+
+.token.function,
+.token.class-name {
+  color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+  color: #e90;
+}
+
+.token.important,
+.token.bold {
+  font-weight: bold;
+}
+
+.token.italic {
+  font-style: italic;
+}
+
+.token.entity {
+  cursor: help;
+}

文件差异内容过多而无法显示
+ 2930 - 0
download_code/controller/static/css/icon/demo_index.html


文件差异内容过多而无法显示
+ 497 - 0
download_code/controller/static/css/icon/iconfont.css


二进制
download_code/controller/static/css/icon/iconfont.eot


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/css/icon/iconfont.js


+ 849 - 0
download_code/controller/static/css/icon/iconfont.json

@@ -0,0 +1,849 @@
+{
+  "id": "1064953",
+  "name": "四维看看",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon",
+  "description": "一款三维空间数据采集的 ",
+  "glyphs": [
+    {
+      "icon_id": "1020530",
+      "name": "baocun",
+      "font_class": "baocun",
+      "unicode": "e64b",
+      "unicode_decimal": 58955
+    },
+    {
+      "icon_id": "1133163",
+      "name": "减",
+      "font_class": "_jian",
+      "unicode": "e660",
+      "unicode_decimal": 58976
+    },
+    {
+      "icon_id": "3141534",
+      "name": "清空",
+      "font_class": "qingkong-copy-copy",
+      "unicode": "e68b",
+      "unicode_decimal": 59019
+    },
+    {
+      "icon_id": "4580255",
+      "name": "暂停",
+      "font_class": "zanting",
+      "unicode": "e65b",
+      "unicode_decimal": 58971
+    },
+    {
+      "icon_id": "5046066",
+      "name": "录音",
+      "font_class": "luyin",
+      "unicode": "e61d",
+      "unicode_decimal": 58909
+    },
+    {
+      "icon_id": "6555460",
+      "name": "加",
+      "font_class": "_jia",
+      "unicode": "e661",
+      "unicode_decimal": 58977
+    },
+    {
+      "icon_id": "6685908",
+      "name": "暂停",
+      "font_class": "CombinedShape",
+      "unicode": "e662",
+      "unicode_decimal": 58978
+    },
+    {
+      "icon_id": "6760625",
+      "name": "预览",
+      "font_class": "yulan",
+      "unicode": "e7ee",
+      "unicode_decimal": 59374
+    },
+    {
+      "icon_id": "7855507",
+      "name": "平面视角",
+      "font_class": "_2d",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
+    {
+      "icon_id": "7855521",
+      "name": "三维视角",
+      "font_class": "_3d",
+      "unicode": "e604",
+      "unicode_decimal": 58884
+    },
+    {
+      "icon_id": "7855544",
+      "name": "漫游视角",
+      "font_class": "_tour",
+      "unicode": "e605",
+      "unicode_decimal": 58885
+    },
+    {
+      "icon_id": "7857927",
+      "name": "锁定视角",
+      "font_class": "_aimvision",
+      "unicode": "e606",
+      "unicode_decimal": 58886
+    },
+    {
+      "icon_id": "7857930",
+      "name": "算法",
+      "font_class": "_algorithm",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
+      "icon_id": "7857932",
+      "name": "自动",
+      "font_class": "_auto",
+      "unicode": "e608",
+      "unicode_decimal": 58888
+    },
+    {
+      "icon_id": "7857935",
+      "name": "返回",
+      "font_class": "_back",
+      "unicode": "e609",
+      "unicode_decimal": 58889
+    },
+    {
+      "icon_id": "7857953",
+      "name": "蓝牙",
+      "font_class": "_bluetooth",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "7857987",
+      "name": "相机",
+      "font_class": "_camera",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "7857989",
+      "name": "清理",
+      "font_class": "_clean",
+      "unicode": "e60c",
+      "unicode_decimal": 58892
+    },
+    {
+      "icon_id": "7857990",
+      "name": "数据",
+      "font_class": "_data",
+      "unicode": "e60d",
+      "unicode_decimal": 58893
+    },
+    {
+      "icon_id": "7857992",
+      "name": "删除",
+      "font_class": "_delete",
+      "unicode": "e60e",
+      "unicode_decimal": 58894
+    },
+    {
+      "icon_id": "7857993",
+      "name": "编辑",
+      "font_class": "_edit",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "7858000",
+      "name": "版本信息",
+      "font_class": "_edition",
+      "unicode": "e610",
+      "unicode_decimal": 58896
+    },
+    {
+      "icon_id": "7858015",
+      "name": "预览/可视",
+      "font_class": "_eye",
+      "unicode": "e612",
+      "unicode_decimal": 58898
+    },
+    {
+      "icon_id": "7858019",
+      "name": "自由视角",
+      "font_class": "_freevision",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "7858024",
+      "name": "全屏",
+      "font_class": "_fullscreen",
+      "unicode": "e614",
+      "unicode_decimal": 58900
+    },
+    {
+      "icon_id": "7858025",
+      "name": "官方网站",
+      "font_class": "_guanfang",
+      "unicode": "e615",
+      "unicode_decimal": 58901
+    },
+    {
+      "icon_id": "7858043",
+      "name": "指引",
+      "font_class": "_guide",
+      "unicode": "e616",
+      "unicode_decimal": 58902
+    },
+    {
+      "icon_id": "7858053",
+      "name": "热点",
+      "font_class": "_hotpoint",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "7858058",
+      "name": "文本",
+      "font_class": "_information",
+      "unicode": "e618",
+      "unicode_decimal": 58904
+    },
+    {
+      "icon_id": "7858061",
+      "name": "标签",
+      "font_class": "_label",
+      "unicode": "e619",
+      "unicode_decimal": 58905
+    },
+    {
+      "icon_id": "7858065",
+      "name": "loading",
+      "font_class": "_loading_",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "7858109",
+      "name": "加密",
+      "font_class": "_lock",
+      "unicode": "e61b",
+      "unicode_decimal": 58907
+    },
+    {
+      "icon_id": "7858282",
+      "name": "更多-竖",
+      "font_class": "_more_",
+      "unicode": "e61e",
+      "unicode_decimal": 58910
+    },
+    {
+      "icon_id": "7858295",
+      "name": "更多-横版",
+      "font_class": "_more_1",
+      "unicode": "e61f",
+      "unicode_decimal": 58911
+    },
+    {
+      "icon_id": "7858341",
+      "name": "音乐",
+      "font_class": "_music",
+      "unicode": "e620",
+      "unicode_decimal": 58912
+    },
+    {
+      "icon_id": "7858359",
+      "name": "附近点",
+      "font_class": "_nearby",
+      "unicode": "e621",
+      "unicode_decimal": 58913
+    },
+    {
+      "icon_id": "7858368",
+      "name": "关闭",
+      "font_class": "_close",
+      "unicode": "e622",
+      "unicode_decimal": 58914
+    },
+    {
+      "icon_id": "7858417",
+      "name": "播放",
+      "font_class": "_play",
+      "unicode": "e623",
+      "unicode_decimal": 58915
+    },
+    {
+      "icon_id": "7858427",
+      "name": "录音",
+      "font_class": "_recording",
+      "unicode": "e624",
+      "unicode_decimal": 58916
+    },
+    {
+      "icon_id": "7858434",
+      "name": "更新",
+      "font_class": "_refresh",
+      "unicode": "e625",
+      "unicode_decimal": 58917
+    },
+    {
+      "icon_id": "7858465",
+      "name": "修复路径",
+      "font_class": "_repairpath",
+      "unicode": "e626",
+      "unicode_decimal": 58918
+    },
+    {
+      "icon_id": "7858493",
+      "name": "前往",
+      "font_class": "_forward",
+      "unicode": "e627",
+      "unicode_decimal": 58919
+    },
+    {
+      "icon_id": "7858512",
+      "name": "保存",
+      "font_class": "_save",
+      "unicode": "e629",
+      "unicode_decimal": 58921
+    },
+    {
+      "icon_id": "7858519",
+      "name": "扫一扫",
+      "font_class": "_scanning",
+      "unicode": "e62a",
+      "unicode_decimal": 58922
+    },
+    {
+      "icon_id": "7858528",
+      "name": "初始画面",
+      "font_class": "_screen",
+      "unicode": "e62b",
+      "unicode_decimal": 58923
+    },
+    {
+      "icon_id": "7858537",
+      "name": "语音播放",
+      "font_class": "_service",
+      "unicode": "e62c",
+      "unicode_decimal": 58924
+    },
+    {
+      "icon_id": "7858774",
+      "name": "调节",
+      "font_class": "_regulate",
+      "unicode": "e62f",
+      "unicode_decimal": 58927
+    },
+    {
+      "icon_id": "7858803",
+      "name": "设置",
+      "font_class": "_setting",
+      "unicode": "e630",
+      "unicode_decimal": 58928
+    },
+    {
+      "icon_id": "7858805",
+      "name": "分享",
+      "font_class": "_share",
+      "unicode": "e631",
+      "unicode_decimal": 58929
+    },
+    {
+      "icon_id": "7858811",
+      "name": "底面标识",
+      "font_class": "_sign",
+      "unicode": "e632",
+      "unicode_decimal": 58930
+    },
+    {
+      "icon_id": "7858820",
+      "name": "标尺",
+      "font_class": "_staff",
+      "unicode": "e633",
+      "unicode_decimal": 58931
+    },
+    {
+      "icon_id": "7858823",
+      "name": "风格",
+      "font_class": "_style",
+      "unicode": "e634",
+      "unicode_decimal": 58932
+    },
+    {
+      "icon_id": "7858828",
+      "name": "暂停",
+      "font_class": "_suspend",
+      "unicode": "e635",
+      "unicode_decimal": 58933
+    },
+    {
+      "icon_id": "7858837",
+      "name": "上传",
+      "font_class": "_upload",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "7859008",
+      "name": "VR",
+      "font_class": "_vr",
+      "unicode": "e637",
+      "unicode_decimal": 58935
+    },
+    {
+      "icon_id": "7859012",
+      "name": "热点可行",
+      "font_class": "_walk",
+      "unicode": "e638",
+      "unicode_decimal": 58936
+    },
+    {
+      "icon_id": "7859022",
+      "name": "wifi",
+      "font_class": "_wifi",
+      "unicode": "e639",
+      "unicode_decimal": 58937
+    },
+    {
+      "icon_id": "7859032",
+      "name": "勾",
+      "font_class": "_yes",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "7859034",
+      "name": "中文",
+      "font_class": "_zhongwen",
+      "unicode": "e63b",
+      "unicode_decimal": 58939
+    },
+    {
+      "icon_id": "7859040",
+      "name": "英文",
+      "font_class": "_english",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    },
+    {
+      "icon_id": "7868595",
+      "name": "楼层",
+      "font_class": "_floor",
+      "unicode": "e63d",
+      "unicode_decimal": 58941
+    },
+    {
+      "icon_id": "7871404",
+      "name": "logo",
+      "font_class": "_logo",
+      "unicode": "e63e",
+      "unicode_decimal": 58942
+    },
+    {
+      "icon_id": "7871405",
+      "name": "标语",
+      "font_class": "_slogan",
+      "unicode": "e63f",
+      "unicode_decimal": 58943
+    },
+    {
+      "icon_id": "7878511",
+      "name": "展开",
+      "font_class": "_pulldown",
+      "unicode": "e640",
+      "unicode_decimal": 58944
+    },
+    {
+      "icon_id": "7878541",
+      "name": ".icon_logo",
+      "font_class": "icon_logo",
+      "unicode": "e641",
+      "unicode_decimal": 58945
+    },
+    {
+      "icon_id": "7878565",
+      "name": "文博",
+      "font_class": "_wenbo",
+      "unicode": "e642",
+      "unicode_decimal": 58946
+    },
+    {
+      "icon_id": "7878566",
+      "name": "家具",
+      "font_class": "_jiaju",
+      "unicode": "e643",
+      "unicode_decimal": 58947
+    },
+    {
+      "icon_id": "7878567",
+      "name": "餐饮",
+      "font_class": "_canyin",
+      "unicode": "e644",
+      "unicode_decimal": 58948
+    },
+    {
+      "icon_id": "7878573",
+      "name": "主页",
+      "font_class": "_zhuye",
+      "unicode": "e645",
+      "unicode_decimal": 58949
+    },
+    {
+      "icon_id": "7878574",
+      "name": "电商",
+      "font_class": "_dianshang",
+      "unicode": "e646",
+      "unicode_decimal": 58950
+    },
+    {
+      "icon_id": "7878582",
+      "name": "QQ",
+      "font_class": "_qq",
+      "unicode": "e647",
+      "unicode_decimal": 58951
+    },
+    {
+      "icon_id": "7878583",
+      "name": "微信",
+      "font_class": "_wechat",
+      "unicode": "e648",
+      "unicode_decimal": 58952
+    },
+    {
+      "icon_id": "7878584",
+      "name": "朋友",
+      "font_class": "_friend",
+      "unicode": "e649",
+      "unicode_decimal": 58953
+    },
+    {
+      "icon_id": "7878603",
+      "name": "+",
+      "font_class": "_plus",
+      "unicode": "e64a",
+      "unicode_decimal": 58954
+    },
+    {
+      "icon_id": "7878633",
+      "name": "指房宝logo",
+      "font_class": "_zfb_logo",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "7878636",
+      "name": "phone-vr",
+      "font_class": "phone-vr",
+      "unicode": "e64d",
+      "unicode_decimal": 58957
+    },
+    {
+      "icon_id": "7878714",
+      "name": "向上",
+      "font_class": "_top",
+      "unicode": "e64e",
+      "unicode_decimal": 58958
+    },
+    {
+      "icon_id": "8044201",
+      "name": "切换",
+      "font_class": "_switch",
+      "unicode": "e64f",
+      "unicode_decimal": 58959
+    },
+    {
+      "icon_id": "8044202",
+      "name": "撤销",
+      "font_class": "_cancel",
+      "unicode": "e650",
+      "unicode_decimal": 58960
+    },
+    {
+      "icon_id": "8044204",
+      "name": "重做",
+      "font_class": "_repeat",
+      "unicode": "e651",
+      "unicode_decimal": 58961
+    },
+    {
+      "icon_id": "8044205",
+      "name": "还原",
+      "font_class": "_restore",
+      "unicode": "e652",
+      "unicode_decimal": 58962
+    },
+    {
+      "icon_id": "8082214",
+      "name": "门",
+      "font_class": "_door",
+      "unicode": "e653",
+      "unicode_decimal": 58963
+    },
+    {
+      "icon_id": "8082215",
+      "name": "窗",
+      "font_class": "_window",
+      "unicode": "e654",
+      "unicode_decimal": 58964
+    },
+    {
+      "icon_id": "8082216",
+      "name": "柱子",
+      "font_class": "_column",
+      "unicode": "e655",
+      "unicode_decimal": 58965
+    },
+    {
+      "icon_id": "8524865",
+      "name": "点",
+      "font_class": "_point",
+      "unicode": "e656",
+      "unicode_decimal": 58966
+    },
+    {
+      "icon_id": "8652176",
+      "name": "_phone",
+      "font_class": "_phone",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "8653241",
+      "name": "_red record open",
+      "font_class": "_redrecordopen",
+      "unicode": "e61c",
+      "unicode_decimal": 58908
+    },
+    {
+      "icon_id": "8672627",
+      "name": "_vedio",
+      "font_class": "_vedio",
+      "unicode": "e62e",
+      "unicode_decimal": 58926
+    },
+    {
+      "icon_id": "8673679",
+      "name": "_voice frequency",
+      "font_class": "_voicefrequency",
+      "unicode": "e659",
+      "unicode_decimal": 58969
+    },
+    {
+      "icon_id": "8704222",
+      "name": "_new project",
+      "font_class": "_newproject",
+      "unicode": "e658",
+      "unicode_decimal": 58968
+    },
+    {
+      "icon_id": "8704223",
+      "name": "_save",
+      "font_class": "_save1",
+      "unicode": "e65a",
+      "unicode_decimal": 58970
+    },
+    {
+      "icon_id": "8723098",
+      "name": "_volume1",
+      "font_class": "_volume1",
+      "unicode": "e65c",
+      "unicode_decimal": 58972
+    },
+    {
+      "icon_id": "8723113",
+      "name": "_roundnesss",
+      "font_class": "_roundnesss",
+      "unicode": "e65d",
+      "unicode_decimal": 58973
+    },
+    {
+      "icon_id": "8723136",
+      "name": "_preview",
+      "font_class": "_preview1",
+      "unicode": "e65f",
+      "unicode_decimal": 58975
+    },
+    {
+      "icon_id": "8746053",
+      "name": "_return",
+      "font_class": "_return",
+      "unicode": "e62d",
+      "unicode_decimal": 58925
+    },
+    {
+      "icon_id": "8749265",
+      "name": "_copy",
+      "font_class": "_copy",
+      "unicode": "e664",
+      "unicode_decimal": 58980
+    },
+    {
+      "icon_id": "8749267",
+      "name": "_del",
+      "font_class": "_del",
+      "unicode": "e666",
+      "unicode_decimal": 58982
+    },
+    {
+      "icon_id": "8749269",
+      "name": "_return",
+      "font_class": "_return1",
+      "unicode": "e668",
+      "unicode_decimal": 58984
+    },
+    {
+      "icon_id": "8749270",
+      "name": "_mute",
+      "font_class": "_mute",
+      "unicode": "e669",
+      "unicode_decimal": 58985
+    },
+    {
+      "icon_id": "8775141",
+      "name": "_cut three",
+      "font_class": "_cutthree1",
+      "unicode": "e66a",
+      "unicode_decimal": 58986
+    },
+    {
+      "icon_id": "8775142",
+      "name": "_cutone",
+      "font_class": "_cutone",
+      "unicode": "e66b",
+      "unicode_decimal": 58987
+    },
+    {
+      "icon_id": "8775143",
+      "name": "_cuttwo",
+      "font_class": "_cuttwo1",
+      "unicode": "e66c",
+      "unicode_decimal": 58988
+    },
+    {
+      "icon_id": "9016105",
+      "name": "场外镜头",
+      "font_class": "_shot",
+      "unicode": "e657",
+      "unicode_decimal": 58967
+    },
+    {
+      "icon_id": "9604066",
+      "name": "平滑",
+      "font_class": "_pinghua",
+      "unicode": "e65e",
+      "unicode_decimal": 58974
+    },
+    {
+      "icon_id": "9604071",
+      "name": "原生",
+      "font_class": "_yuansheng",
+      "unicode": "e663",
+      "unicode_decimal": 58979
+    },
+    {
+      "icon_id": "9669407",
+      "name": "删除音频",
+      "font_class": "_shanchu",
+      "unicode": "e665",
+      "unicode_decimal": 58981
+    },
+    {
+      "icon_id": "9669408",
+      "name": "框框",
+      "font_class": "_fangkuang",
+      "unicode": "e667",
+      "unicode_decimal": 58983
+    },
+    {
+      "icon_id": "9669409",
+      "name": "播放音频",
+      "font_class": "_bofang",
+      "unicode": "e66d",
+      "unicode_decimal": 58989
+    },
+    {
+      "icon_id": "9669410",
+      "name": "音频暂停",
+      "font_class": "_zanting",
+      "unicode": "e66e",
+      "unicode_decimal": 58990
+    },
+    {
+      "icon_id": "9669411",
+      "name": "录制音频",
+      "font_class": "_luzhi",
+      "unicode": "e66f",
+      "unicode_decimal": 58991
+    },
+    {
+      "icon_id": "9669412",
+      "name": "音频停止",
+      "font_class": "_tingzhi",
+      "unicode": "e670",
+      "unicode_decimal": 58992
+    },
+    {
+      "icon_id": "9669413",
+      "name": "勾选",
+      "font_class": "_gou",
+      "unicode": "e671",
+      "unicode_decimal": 58993
+    },
+    {
+      "icon_id": "9845309",
+      "name": "基础设置",
+      "font_class": "_base",
+      "unicode": "e672",
+      "unicode_decimal": 58994
+    },
+    {
+      "icon_id": "10302359",
+      "name": "测距",
+      "font_class": "_measure",
+      "unicode": "e674",
+      "unicode_decimal": 58996
+    },
+    {
+      "icon_id": "11304931",
+      "name": "more read",
+      "font_class": "more",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "12138841",
+      "name": "全景视频",
+      "font_class": "_quanjing",
+      "unicode": "e675",
+      "unicode_decimal": 58997
+    },
+    {
+      "icon_id": "12324807",
+      "name": "方标CN",
+      "font_class": "fangbiaoCN",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "12324808",
+      "name": "方标EN",
+      "font_class": "fangbiaoEN",
+      "unicode": "e6a2",
+      "unicode_decimal": 59042
+    },
+    {
+      "icon_id": "12324809",
+      "name": "横标CN",
+      "font_class": "hengbiaoCN",
+      "unicode": "e6a3",
+      "unicode_decimal": 59043
+    },
+    {
+      "icon_id": "12324810",
+      "name": "横标EN",
+      "font_class": "hengbiaoEN",
+      "unicode": "e6a4",
+      "unicode_decimal": 59044
+    }
+  ]
+}

文件差异内容过多而无法显示
+ 386 - 0
download_code/controller/static/css/icon/iconfont.svg


二进制
download_code/controller/static/css/icon/iconfont.ttf


二进制
download_code/controller/static/css/icon/iconfont.woff


二进制
download_code/controller/static/css/icon/iconfont.woff2


文件差异内容过多而无法显示
+ 10162 - 0
download_code/controller/static/css/mainApp.css


文件差异内容过多而无法显示
+ 8592 - 0
download_code/controller/static/css/mainPC.css


+ 950 - 0
download_code/controller/static/css/quill.snow.css

@@ -0,0 +1,950 @@
+/*!
+ * Quill Editor v1.3.6
+ * https://quilljs.com/
+ * Copyright (c) 2014, Jason Chen
+ * Copyright (c) 2013, salesforce.com
+ */
+ .ql-container {
+    box-sizing: border-box;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: 13px;
+    height: 100%;
+    margin: 0px;
+    position: relative;
+  }
+  .ql-container.ql-disabled .ql-tooltip {
+    visibility: hidden;
+  }
+  .ql-container.ql-disabled .ql-editor ul[data-checked] > li::before {
+    pointer-events: none;
+  }
+  .ql-clipboard {
+    left: -100000px;
+    height: 1px;
+    overflow-y: hidden;
+    position: absolute;
+    top: 50%;
+  }
+  .ql-clipboard p {
+    margin: 0;
+    padding: 0;
+  }
+  .ql-editor {
+    box-sizing: border-box;
+    line-height: 1.42;
+    height: 100%;
+    outline: none;
+    overflow-y: auto;
+    padding: 12px 15px;
+    tab-size: 4;
+    -moz-tab-size: 4;
+    text-align: left;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+  }
+  .ql-editor > * {
+    cursor: text;
+  }
+  .ql-editor p,
+  .ql-editor ol,
+  .ql-editor ul,
+  .ql-editor pre,
+  .ql-editor blockquote,
+  .ql-editor h1,
+  .ql-editor h2,
+  .ql-editor h3,
+  .ql-editor h4,
+  .ql-editor h5,
+  .ql-editor h6 {
+    margin: 0;
+    padding: 0;
+    counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
+  }
+  .ql-editor ol,
+  .ql-editor ul {
+    padding-left: 1.5em;
+  }
+  .ql-editor ol > li,
+  .ql-editor ul > li {
+    list-style-type: none;
+  }
+  .ql-editor ul > li::before {
+    content: '\2022';
+  }
+  .ql-editor ul[data-checked=true],
+  .ql-editor ul[data-checked=false] {
+    pointer-events: none;
+  }
+  .ql-editor ul[data-checked=true] > li *,
+  .ql-editor ul[data-checked=false] > li * {
+    pointer-events: all;
+  }
+  .ql-editor ul[data-checked=true] > li::before,
+  .ql-editor ul[data-checked=false] > li::before {
+    color: #777;
+    cursor: pointer;
+    pointer-events: all;
+  }
+  .ql-editor ul[data-checked=true] > li::before {
+    content: '\2611';
+  }
+  .ql-editor ul[data-checked=false] > li::before {
+    content: '\2610';
+  }
+  .ql-editor li::before {
+    display: inline-block;
+    white-space: nowrap;
+    width: 1.2em;
+  }
+  .ql-editor li:not(.ql-direction-rtl)::before {
+    margin-left: -1.5em;
+    margin-right: 0.3em;
+    text-align: right;
+  }
+  .ql-editor li.ql-direction-rtl::before {
+    margin-left: 0.3em;
+    margin-right: -1.5em;
+  }
+  .ql-editor ol li:not(.ql-direction-rtl),
+  .ql-editor ul li:not(.ql-direction-rtl) {
+    padding-left: 1.5em;
+  }
+  .ql-editor ol li.ql-direction-rtl,
+  .ql-editor ul li.ql-direction-rtl {
+    padding-right: 1.5em;
+  }
+  .ql-editor ol li {
+    counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
+    counter-increment: list-0;
+  }
+  .ql-editor ol li:before {
+    content: counter(list-0, decimal) '. ';
+  }
+  .ql-editor ol li.ql-indent-1 {
+    counter-increment: list-1;
+  }
+  .ql-editor ol li.ql-indent-1:before {
+    content: counter(list-1, lower-alpha) '. ';
+  }
+  .ql-editor ol li.ql-indent-1 {
+    counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-2 {
+    counter-increment: list-2;
+  }
+  .ql-editor ol li.ql-indent-2:before {
+    content: counter(list-2, lower-roman) '. ';
+  }
+  .ql-editor ol li.ql-indent-2 {
+    counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-3 {
+    counter-increment: list-3;
+  }
+  .ql-editor ol li.ql-indent-3:before {
+    content: counter(list-3, decimal) '. ';
+  }
+  .ql-editor ol li.ql-indent-3 {
+    counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-4 {
+    counter-increment: list-4;
+  }
+  .ql-editor ol li.ql-indent-4:before {
+    content: counter(list-4, lower-alpha) '. ';
+  }
+  .ql-editor ol li.ql-indent-4 {
+    counter-reset: list-5 list-6 list-7 list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-5 {
+    counter-increment: list-5;
+  }
+  .ql-editor ol li.ql-indent-5:before {
+    content: counter(list-5, lower-roman) '. ';
+  }
+  .ql-editor ol li.ql-indent-5 {
+    counter-reset: list-6 list-7 list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-6 {
+    counter-increment: list-6;
+  }
+  .ql-editor ol li.ql-indent-6:before {
+    content: counter(list-6, decimal) '. ';
+  }
+  .ql-editor ol li.ql-indent-6 {
+    counter-reset: list-7 list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-7 {
+    counter-increment: list-7;
+  }
+  .ql-editor ol li.ql-indent-7:before {
+    content: counter(list-7, lower-alpha) '. ';
+  }
+  .ql-editor ol li.ql-indent-7 {
+    counter-reset: list-8 list-9;
+  }
+  .ql-editor ol li.ql-indent-8 {
+    counter-increment: list-8;
+  }
+  .ql-editor ol li.ql-indent-8:before {
+    content: counter(list-8, lower-roman) '. ';
+  }
+  .ql-editor ol li.ql-indent-8 {
+    counter-reset: list-9;
+  }
+  .ql-editor ol li.ql-indent-9 {
+    counter-increment: list-9;
+  }
+  .ql-editor ol li.ql-indent-9:before {
+    content: counter(list-9, decimal) '. ';
+  }
+  .ql-editor .ql-indent-1:not(.ql-direction-rtl) {
+    padding-left: 3em;
+  }
+  .ql-editor li.ql-indent-1:not(.ql-direction-rtl) {
+    padding-left: 4.5em;
+  }
+  .ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right {
+    padding-right: 3em;
+  }
+  .ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right {
+    padding-right: 4.5em;
+  }
+  .ql-editor .ql-indent-2:not(.ql-direction-rtl) {
+    padding-left: 6em;
+  }
+  .ql-editor li.ql-indent-2:not(.ql-direction-rtl) {
+    padding-left: 7.5em;
+  }
+  .ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right {
+    padding-right: 6em;
+  }
+  .ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right {
+    padding-right: 7.5em;
+  }
+  .ql-editor .ql-indent-3:not(.ql-direction-rtl) {
+    padding-left: 9em;
+  }
+  .ql-editor li.ql-indent-3:not(.ql-direction-rtl) {
+    padding-left: 10.5em;
+  }
+  .ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right {
+    padding-right: 9em;
+  }
+  .ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right {
+    padding-right: 10.5em;
+  }
+  .ql-editor .ql-indent-4:not(.ql-direction-rtl) {
+    padding-left: 12em;
+  }
+  .ql-editor li.ql-indent-4:not(.ql-direction-rtl) {
+    padding-left: 13.5em;
+  }
+  .ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right {
+    padding-right: 12em;
+  }
+  .ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right {
+    padding-right: 13.5em;
+  }
+  .ql-editor .ql-indent-5:not(.ql-direction-rtl) {
+    padding-left: 15em;
+  }
+  .ql-editor li.ql-indent-5:not(.ql-direction-rtl) {
+    padding-left: 16.5em;
+  }
+  .ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right {
+    padding-right: 15em;
+  }
+  .ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right {
+    padding-right: 16.5em;
+  }
+  .ql-editor .ql-indent-6:not(.ql-direction-rtl) {
+    padding-left: 18em;
+  }
+  .ql-editor li.ql-indent-6:not(.ql-direction-rtl) {
+    padding-left: 19.5em;
+  }
+  .ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right {
+    padding-right: 18em;
+  }
+  .ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right {
+    padding-right: 19.5em;
+  }
+  .ql-editor .ql-indent-7:not(.ql-direction-rtl) {
+    padding-left: 21em;
+  }
+  .ql-editor li.ql-indent-7:not(.ql-direction-rtl) {
+    padding-left: 22.5em;
+  }
+  .ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right {
+    padding-right: 21em;
+  }
+  .ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right {
+    padding-right: 22.5em;
+  }
+  .ql-editor .ql-indent-8:not(.ql-direction-rtl) {
+    padding-left: 24em;
+  }
+  .ql-editor li.ql-indent-8:not(.ql-direction-rtl) {
+    padding-left: 25.5em;
+  }
+  .ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right {
+    padding-right: 24em;
+  }
+  .ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right {
+    padding-right: 25.5em;
+  }
+  .ql-editor .ql-indent-9:not(.ql-direction-rtl) {
+    padding-left: 27em;
+  }
+  .ql-editor li.ql-indent-9:not(.ql-direction-rtl) {
+    padding-left: 28.5em;
+  }
+  .ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right {
+    padding-right: 27em;
+  }
+  .ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right {
+    padding-right: 28.5em;
+  }
+  .ql-editor .ql-video {
+    display: block;
+    max-width: 100%;
+  }
+  .ql-editor .ql-video.ql-align-center {
+    margin: 0 auto;
+  }
+  .ql-editor .ql-video.ql-align-right {
+    margin: 0 0 0 auto;
+  }
+  .ql-editor .ql-bg-black {
+    background-color: #000;
+  }
+  .ql-editor .ql-bg-red {
+    background-color: #e60000;
+  }
+  .ql-editor .ql-bg-orange {
+    background-color: #f90;
+  }
+  .ql-editor .ql-bg-yellow {
+    background-color: #ff0;
+  }
+  .ql-editor .ql-bg-green {
+    background-color: #008a00;
+  }
+  .ql-editor .ql-bg-blue {
+    background-color: #06c;
+  }
+  .ql-editor .ql-bg-purple {
+    background-color: #93f;
+  }
+  .ql-editor .ql-color-white {
+    color: #fff;
+  }
+  .ql-editor .ql-color-red {
+    color: #e60000;
+  }
+  .ql-editor .ql-color-orange {
+    color: #f90;
+  }
+  .ql-editor .ql-color-yellow {
+    color: #ff0;
+  }
+  .ql-editor .ql-color-green {
+    color: #008a00;
+  }
+  .ql-editor .ql-color-blue {
+    color: #06c;
+  }
+  .ql-editor .ql-color-purple {
+    color: #93f;
+  }
+  .ql-editor .ql-font-serif {
+    font-family: Georgia, Times New Roman, serif;
+  }
+  .ql-editor .ql-font-monospace {
+    font-family: Monaco, Courier New, monospace;
+  }
+  .ql-editor .ql-size-small {
+    font-size: 0.75em;
+  }
+  .ql-editor .ql-size-large {
+    font-size: 1.5em;
+  }
+  .ql-editor .ql-size-huge {
+    font-size: 2.5em;
+  }
+  .ql-editor .ql-direction-rtl {
+    direction: rtl;
+    text-align: inherit;
+  }
+  .ql-editor .ql-align-center {
+    text-align: center;
+  }
+  .ql-editor .ql-align-justify {
+    text-align: justify;
+  }
+  .ql-editor .ql-align-right {
+    text-align: right;
+  }
+  .ql-editor.ql-blank::before {
+    color: rgba(0,0,0,0.6);
+    content: attr(data-placeholder);
+    font-style: normal;
+    left: 15px;
+    pointer-events: none;
+    position: absolute;
+    right: 15px;
+    color: #c7c7c7;
+  }
+  .ql-snow.ql-toolbar:after,
+  .ql-snow .ql-toolbar:after {
+    clear: both;
+    content: '';
+    display: table;
+  }
+  .ql-snow.ql-toolbar button,
+  .ql-snow .ql-toolbar button {
+    background: none;
+    border: none;
+    cursor: pointer;
+    display: inline-block;
+    float: left;
+    height: 24px;
+    padding: 3px 5px;
+    width: 28px;
+  }
+  .ql-snow.ql-toolbar button svg,
+  .ql-snow .ql-toolbar button svg {
+    float: left;
+    height: 100%;
+  }
+  .ql-snow.ql-toolbar button:active:hover,
+  .ql-snow .ql-toolbar button:active:hover {
+    outline: none;
+  }
+  .ql-snow.ql-toolbar input.ql-image[type=file],
+  .ql-snow .ql-toolbar input.ql-image[type=file] {
+    display: none;
+  }
+  .ql-snow.ql-toolbar button:hover,
+  .ql-snow .ql-toolbar button:hover,
+  .ql-snow.ql-toolbar button:focus,
+  .ql-snow .ql-toolbar button:focus,
+  .ql-snow.ql-toolbar button.ql-active,
+  .ql-snow .ql-toolbar button.ql-active,
+  .ql-snow.ql-toolbar .ql-picker-label:hover,
+  .ql-snow .ql-toolbar .ql-picker-label:hover,
+  .ql-snow.ql-toolbar .ql-picker-label.ql-active,
+  .ql-snow .ql-toolbar .ql-picker-label.ql-active,
+  .ql-snow.ql-toolbar .ql-picker-item:hover,
+  .ql-snow .ql-toolbar .ql-picker-item:hover,
+  .ql-snow.ql-toolbar .ql-picker-item.ql-selected,
+  .ql-snow .ql-toolbar .ql-picker-item.ql-selected {
+    color: #06c;
+  }
+  .ql-snow.ql-toolbar button:hover .ql-fill,
+  .ql-snow .ql-toolbar button:hover .ql-fill,
+  .ql-snow.ql-toolbar button:focus .ql-fill,
+  .ql-snow .ql-toolbar button:focus .ql-fill,
+  .ql-snow.ql-toolbar button.ql-active .ql-fill,
+  .ql-snow .ql-toolbar button.ql-active .ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,
+  .ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,
+  .ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,
+  .ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
+  .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,
+  .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill {
+    fill: #06c;
+  }
+  .ql-snow.ql-toolbar button:hover .ql-stroke,
+  .ql-snow .ql-toolbar button:hover .ql-stroke,
+  .ql-snow.ql-toolbar button:focus .ql-stroke,
+  .ql-snow .ql-toolbar button:focus .ql-stroke,
+  .ql-snow.ql-toolbar button.ql-active .ql-stroke,
+  .ql-snow .ql-toolbar button.ql-active .ql-stroke,
+  .ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,
+  .ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,
+  .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,
+  .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,
+  .ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,
+  .ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,
+  .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
+  .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
+  .ql-snow.ql-toolbar button:hover .ql-stroke-miter,
+  .ql-snow .ql-toolbar button:hover .ql-stroke-miter,
+  .ql-snow.ql-toolbar button:focus .ql-stroke-miter,
+  .ql-snow .ql-toolbar button:focus .ql-stroke-miter,
+  .ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,
+  .ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,
+  .ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
+  .ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
+  .ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
+  .ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
+  .ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
+  .ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
+  .ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,
+  .ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter {
+    stroke: #06c;
+  }
+  @media (pointer: coarse) {
+    .ql-snow.ql-toolbar button:hover:not(.ql-active),
+    .ql-snow .ql-toolbar button:hover:not(.ql-active) {
+      color: #444;
+    }
+    .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,
+    .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,
+    .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,
+    .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill {
+      fill: #444;
+    }
+    .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,
+    .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,
+    .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,
+    .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter {
+      stroke: #444;
+    }
+  }
+  .ql-snow {
+    box-sizing: border-box;
+  }
+  .ql-snow * {
+    box-sizing: border-box;
+  }
+  .ql-snow .ql-hidden {
+    display: none;
+  }
+  .ql-snow .ql-out-bottom,
+  .ql-snow .ql-out-top {
+    visibility: hidden;
+  }
+  .ql-snow .ql-tooltip {
+    position: absolute;
+    transform: translateY(10px);
+  }
+  .ql-snow .ql-tooltip a {
+    cursor: pointer;
+    text-decoration: none;
+  }
+  .ql-snow .ql-tooltip.ql-flip {
+    transform: translateY(-10px);
+  }
+  .ql-snow .ql-formats {
+    display: inline-block;
+    vertical-align: middle;
+  }
+  .ql-snow .ql-formats:after {
+    clear: both;
+    content: '';
+    display: table;
+  }
+  .ql-snow .ql-stroke {
+    fill: none;
+    stroke: #444;
+    stroke-linecap: round;
+    stroke-linejoin: round;
+    stroke-width: 2;
+  }
+  .ql-snow .ql-stroke-miter {
+    fill: none;
+    stroke: #444;
+    stroke-miterlimit: 10;
+    stroke-width: 2;
+  }
+  .ql-snow .ql-fill,
+  .ql-snow .ql-stroke.ql-fill {
+    fill: #444;
+  }
+  .ql-snow .ql-empty {
+    fill: none;
+  }
+  .ql-snow .ql-even {
+    fill-rule: evenodd;
+  }
+  .ql-snow .ql-thin,
+  .ql-snow .ql-stroke.ql-thin {
+    stroke-width: 1;
+  }
+  .ql-snow .ql-transparent {
+    opacity: 0.4;
+  }
+  .ql-snow .ql-direction svg:last-child {
+    display: none;
+  }
+  .ql-snow .ql-direction.ql-active svg:last-child {
+    display: inline;
+  }
+  .ql-snow .ql-direction.ql-active svg:first-child {
+    display: none;
+  }
+  .ql-snow .ql-editor h1 {
+    font-size: 2em;
+  }
+  .ql-snow .ql-editor h2 {
+    font-size: 1.5em;
+  }
+  .ql-snow .ql-editor h3 {
+    font-size: 1.17em;
+  }
+  .ql-snow .ql-editor h4 {
+    font-size: 1em;
+  }
+  .ql-snow .ql-editor h5 {
+    font-size: 0.83em;
+  }
+  .ql-snow .ql-editor h6 {
+    font-size: 0.67em;
+  }
+  .ql-snow .ql-editor a {
+    text-decoration: underline;
+  }
+  .ql-snow .ql-editor blockquote {
+    border-left: 4px solid #ccc;
+    margin-bottom: 5px;
+    margin-top: 5px;
+    padding-left: 16px;
+  }
+  .ql-snow .ql-editor code,
+  .ql-snow .ql-editor pre {
+    background-color: #f0f0f0;
+    border-radius: 3px;
+  }
+  .ql-snow .ql-editor pre {
+    white-space: pre-wrap;
+    margin-bottom: 5px;
+    margin-top: 5px;
+    padding: 5px 10px;
+  }
+  .ql-snow .ql-editor code {
+    font-size: 85%;
+    padding: 2px 4px;
+  }
+  .ql-snow .ql-editor pre.ql-syntax {
+    background-color: #23241f;
+    color: #f8f8f2;
+    overflow: visible;
+  }
+  .ql-snow .ql-editor img {
+    max-width: 100%;
+  }
+  .ql-snow .ql-picker {
+    color: #444;
+    display: inline-block;
+    float: left;
+    font-size: 14px;
+    font-weight: 500;
+    height: 24px;
+    position: relative;
+    vertical-align: middle;
+  }
+  .ql-snow .ql-picker-label {
+    cursor: pointer;
+    display: inline-block;
+    height: 100%;
+    padding-left: 8px;
+    padding-right: 2px;
+    position: relative;
+    width: 100%;
+  }
+  .ql-snow .ql-picker-label::before {
+    display: inline-block;
+    line-height: 22px;
+  }
+  .ql-snow .ql-picker-options {
+    background-color: #fff;
+    display: none;
+    min-width: 100%;
+    padding: 4px 8px;
+    position: absolute;
+    white-space: nowrap;
+  }
+  .ql-snow .ql-picker-options .ql-picker-item {
+    cursor: pointer;
+    display: block;
+    padding-bottom: 5px;
+    padding-top: 5px;
+  }
+  .ql-snow .ql-picker.ql-expanded .ql-picker-label {
+    color: #ccc;
+    z-index: 2;
+  }
+  .ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill {
+    fill: #ccc;
+  }
+  .ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke {
+    stroke: #ccc;
+  }
+  .ql-snow .ql-picker.ql-expanded .ql-picker-options {
+    display: block;
+    margin-top: -1px;
+    top: 100%;
+    z-index: 1;
+  }
+  .ql-snow .ql-color-picker,
+  .ql-snow .ql-icon-picker {
+    width: 28px;
+  }
+  .ql-snow .ql-color-picker .ql-picker-label,
+  .ql-snow .ql-icon-picker .ql-picker-label {
+    padding: 2px 4px;
+  }
+  .ql-snow .ql-color-picker .ql-picker-label svg,
+  .ql-snow .ql-icon-picker .ql-picker-label svg {
+    right: 4px;
+  }
+  .ql-snow .ql-icon-picker .ql-picker-options {
+    padding: 4px 0px;
+  }
+  .ql-snow .ql-icon-picker .ql-picker-item {
+    height: 24px;
+    width: 24px;
+    padding: 2px 4px;
+  }
+  .ql-snow .ql-color-picker .ql-picker-options {
+    padding: 3px 5px;
+    width: 152px;
+  }
+  .ql-snow .ql-color-picker .ql-picker-item {
+    border: 1px solid transparent;
+    float: left;
+    height: 16px;
+    margin: 2px;
+    padding: 0px;
+    width: 16px;
+  }
+  .ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg {
+    position: absolute;
+    margin-top: -9px;
+    right: 0;
+    top: 50%;
+    width: 18px;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before,
+  .ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before,
+  .ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before,
+  .ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before,
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before {
+    content: attr(data-label);
+  }
+  .ql-snow .ql-picker.ql-header {
+    width: 98px;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item::before {
+    content: 'Normal';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
+    content: 'Heading 1';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
+    content: 'Heading 2';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
+    content: 'Heading 3';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
+    content: 'Heading 4';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
+    content: 'Heading 5';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
+    content: 'Heading 6';
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
+    font-size: 2em;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
+    font-size: 1.5em;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
+    font-size: 1.17em;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
+    font-size: 1em;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
+    font-size: 0.83em;
+  }
+  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
+    font-size: 0.67em;
+  }
+  .ql-snow .ql-picker.ql-font {
+    width: 108px;
+  }
+  .ql-snow .ql-picker.ql-font .ql-picker-label::before,
+  .ql-snow .ql-picker.ql-font .ql-picker-item::before {
+    content: 'Sans Serif';
+  }
+  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
+  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
+    content: 'Serif';
+  }
+  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
+  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
+    content: 'Monospace';
+  }
+  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
+    font-family: Georgia, Times New Roman, serif;
+  }
+  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
+    font-family: Monaco, Courier New, monospace;
+  }
+  .ql-snow .ql-picker.ql-size {
+    width: 98px;
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-label::before,
+  .ql-snow .ql-picker.ql-size .ql-picker-item::before {
+    content: 'Normal';
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
+    content: 'Small';
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
+    content: 'Large';
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
+    content: 'Huge';
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
+    font-size: 10px;
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
+    font-size: 18px;
+  }
+  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
+    font-size: 32px;
+  }
+  .ql-snow .ql-color-picker.ql-background .ql-picker-item {
+    background-color: #fff;
+  }
+  .ql-snow .ql-color-picker.ql-color .ql-picker-item {
+    background-color: #000;
+  }
+  .ql-toolbar.ql-snow {
+    border: 1px solid #ccc;
+    box-sizing: border-box;
+    font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
+    padding: 8px;
+  }
+  .ql-toolbar.ql-snow .ql-formats {
+    margin-right: 15px;
+  }
+  .ql-toolbar.ql-snow .ql-picker-label {
+    border: 1px solid transparent;
+  }
+  .ql-toolbar.ql-snow .ql-picker-options {
+    border: 1px solid transparent;
+    box-shadow: rgba(0,0,0,0.2) 0 2px 8px;
+  }
+  .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
+    border-color: #ccc;
+  }
+  .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
+    border-color: #ccc;
+  }
+  .ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,
+  .ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover {
+    border-color: #000;
+  }
+  .ql-toolbar.ql-snow + .ql-container.ql-snow {
+    border-top: 0px;
+  }
+  .ql-snow .ql-tooltip {
+    background-color: #fff;
+    border: 1px solid #ccc;
+    box-shadow: 0px 0px 5px #ddd;
+    color: #444;
+    padding: 5px 12px;
+    white-space: nowrap;
+  }
+  .ql-snow .ql-tooltip::before {
+    content: "Visit URL:";
+    line-height: 26px;
+    margin-right: 8px;
+  }
+  .ql-snow .ql-tooltip input[type=text] {
+    display: none;
+    border: 1px solid #ccc;
+    font-size: 13px;
+    height: 26px;
+    margin: 0px;
+    padding: 3px 5px;
+    width: 170px;
+  }
+  .ql-snow .ql-tooltip a.ql-preview {
+    display: inline-block;
+    max-width: 200px;
+    overflow-x: hidden;
+    text-overflow: ellipsis;
+    vertical-align: top;
+  }
+  .ql-snow .ql-tooltip a.ql-action::after {
+    border-right: 1px solid #ccc;
+    content: 'Edit';
+    margin-left: 16px;
+    padding-right: 8px;
+  }
+  .ql-snow .ql-tooltip a.ql-remove::before {
+    content: 'Remove';
+    margin-left: 8px;
+  }
+  .ql-snow .ql-tooltip a {
+    line-height: 26px;
+  }
+  .ql-snow .ql-tooltip.ql-editing a.ql-preview,
+  .ql-snow .ql-tooltip.ql-editing a.ql-remove {
+    display: none;
+  }
+  .ql-snow .ql-tooltip.ql-editing input[type=text] {
+    display: inline-block;
+  }
+  .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
+    border-right: 0px;
+    content: 'Save';
+    padding-right: 0px;
+  }
+  .ql-snow .ql-tooltip[data-mode=link]::before {
+    content: "Enter link:";
+  }
+  .ql-snow .ql-tooltip[data-mode=formula]::before {
+    content: "Enter formula:";
+  }
+  .ql-snow .ql-tooltip[data-mode=video]::before {
+    content: "Enter video:";
+  }
+  .ql-snow a {
+    color: #06c;
+  }
+  .ql-container.ql-snow {
+    border: 1px solid #ccc;
+  }
+
+  .ql-editor a{
+      color: #02c8ae;
+  }

+ 598 - 0
download_code/controller/static/css/rulerLabel.css

@@ -0,0 +1,598 @@
+@-webkit-keyframes ruler-point {
+    0% {
+        height: 0
+    }
+
+    to {
+        height: 11.375px
+    }
+}
+
+@keyframes ruler-point {
+    0% {
+        height: 0
+    }
+
+    to {
+        height: 11.375px
+    }
+}
+
+@-webkit-keyframes ruler-label {
+    0% {
+        max-width: 0
+    }
+
+    to {
+        max-width: 131.25px
+    }
+}
+
+@keyframes ruler-label {
+    0% {
+        max-width: 0
+    }
+
+    to {
+        max-width: 131.25px
+    }
+}
+
+@-webkit-keyframes door-label {
+    0% {
+        opacity: 0;
+        margin-top: 8.75px
+    }
+
+    to {
+        opacity: 1;
+        margin-top: 0
+    }
+}
+
+@keyframes door-label {
+    0% {
+        opacity: 0;
+        margin-top: 8.75px
+    }
+
+    to {
+        opacity: 1;
+        margin-top: 0
+    }
+}
+
+@-webkit-keyframes room-label {
+    0% {
+        opacity: 0;
+        margin-top: 8.75px
+    }
+
+    to {
+        opacity: 1;
+        margin-top: 0
+    }
+}
+
+@keyframes room-label {
+    0% {
+        opacity: 0;
+        margin-top: 8.75px
+    }
+
+    to {
+        opacity: 1;
+        margin-top: 0
+    }
+}
+
+@-webkit-keyframes ruler-line {
+    0% {
+        width: 0
+    }
+
+    to {
+        width: 100%
+    }
+}
+
+@keyframes ruler-line {
+    0% {
+        width: 0
+    }
+
+    to {
+        width: 100%
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.rulers {
+    position: absolute;
+    pointer-events: none; 
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+}
+
+.rulers .ruler-line {
+    position: absolute;
+    -webkit-transform-origin: left 0.875px;
+    transform-origin: left 0.875px;
+    width: 0;
+    height: 1.75px;
+}
+
+.rulers .ruler-line em {
+    background: -webkit-gradient(linear,left top,right top,from(hsla(0,0%,100%,.5)),to(hsla(0,0%,100%,.3)));
+    background: linear-gradient(90deg,hsla(0,0%,100%,.5),hsla(0,0%,100%,.3));
+    display: block;
+    height: 100%;
+    -webkit-animation: ruler-line .5s ease 1s;
+    animation: ruler-line .5s ease 1s;
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+    -webkit-box-shadow: 0 0 3.5px rgba(0,0,0,.6);
+    box-shadow: 0 0 3.5px rgba(0,0,0,.6);
+}
+
+.rulers  .ruler-label {
+    position: absolute;
+    /* width: 0; */
+    height: 0;
+    top: 0.875px;
+    left: 38%;
+}
+
+.rulers  .ruler-label .ruler-label-point {
+    position: absolute;
+    width: 28px;
+    height:11.375px;
+    right: 0;
+    bottom: 0;
+    background-position: bottom;
+    background-repeat: no-repeat;
+    background-image: url(../images/ruler-point.svg);
+    background-size: 28px 11.375px;
+    -webkit-transform: translateZ(0);
+    transform: translateZ(0);
+    transform-origin: right center;
+    -webkit-animation: ruler-point .3s ease 1.3s;
+    animation: ruler-point .3s ease 1.3s;
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+}
+
+.rulers   .ruler-label .ruler-label-name {
+	color:white;
+    position: absolute;
+    height: 15.75px;
+    font-size: 12px;
+    line-height: 15.75px;
+    right: 28px;
+    bottom: 0.875px;
+    white-space: nowrap;
+    /* max-width: 0; */
+    overflow: hidden;
+    -webkit-animation: ruler-label 1s ease 1.6s;
+    animation: ruler-label 1s ease 1.6s;
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+    text-shadow: 0 0 3.5px rgba(0,0,0,.6);
+}
+
+.rulers  .ruler-label.reverse .ruler-label-point{
+    -webkit-transform: rotateY(180deg);
+    transform: rotateY(180deg);
+}
+
+.rulers  .ruler-label.reverse .ruler-label-name {
+    /* -webkit-transform: rotateY(-180deg); */
+    /* transform: rotateY(-180deg); */
+    right: auto;
+    left: 28px;
+}
+
+.rulers .measure .ruler-label  .ruler-label-name{
+    color: #f0ff00;
+}
+
+.rulers .ruler-intersection {
+    position: absolute;
+    width: 0;
+    height: 0
+}
+
+.rulers .ruler-intersection .ruler-intersection-point {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    width: 18.375px;
+    height: 7px;
+    background-image: url(../images/intersection-label.svg);
+    background-repeat: no-repeat;
+    background-size: 18.375px 7px;
+    background-position: 50%
+}
+
+.rulers .ruler-intersection .ruler-intersection-text {
+    position: absolute;
+    left: 18.375px;
+    bottom: 0;
+    font-size: 12px;
+    line-height: 12px;
+    white-space: nowrap;
+    color: #12fffb;
+    text-shadow: 0 0 3.5px rgba(0,0,0,.3);
+    -webkit-transform-origin: left center;
+    transform-origin: left center;
+    -webkit-transform: scale(.85);
+    transform: scale(.85)
+}
+
+
+.measure .ruler-label .ruler-label-name{
+    font-size:14px;
+    line-height:14px;
+}
+.measure .ruler-label{
+    position:absolute;
+}
+.measure  .ruler-label .ruler-label-point{
+    background-image: url(../images/ruler-point-yellow.svg);
+   animation-delay: .3s;
+}
+.measure  .ruler-label .ruler-label-name{ 
+   animation-delay: .6s;
+}
+
+ 
+
+
+/* edit 界面 ruler立刻出现 */
+.edit   .ruler-line em {
+	animation-delay: 0s;
+}
+.edit   .ruler-label .ruler-label-point, .wallLine .ruler-label .ruler-label-point{
+   animation-delay: 0s;
+}
+.edit   .ruler-label .ruler-label-name, .wallLine .ruler-label .ruler-label-name{ 
+   animation-delay: .3s;
+}
+
+
+
+
+
+
+
+
+/* dollLabels: */
+
+
+
+.dollLabels, .planLabels{
+    overflow: hidden;
+    position: absolute;
+    pointer-events: none;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0
+}
+
+.dollLabels .roomLabel {
+    position: absolute;
+    width: 0;
+    height: 0;
+   /*  display: none; */
+    -webkit-transform: translateZ(0);
+    transform: translateZ(0);
+    -webkit-animation: room-label .3s ease .1s;
+    animation: room-label .3s ease .1s;
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both
+}
+
+/* .dollLabels .roomLabel.visible {
+    display: block
+} */
+
+.dollLabels .roomLabel:after {
+    content: "";
+    display: block;
+    position: absolute;
+    width: 1px;
+    height: 66px;
+    background-image: url(../images/labelline.png);
+    background-size: contain;
+    bottom: 0;
+    left: 50%;
+    -webkit-transform: translate(-50%);
+    transform: translate(-50%);
+}
+
+.dollLabels .roomLabel a {
+    display: block;
+    position: absolute;
+    /* width: 38.5px; */
+    height: 33px;
+    line-height: 32px;
+    top: -99px;
+    /* left: 50%; */
+    -webkit-transform: translate(-50%);
+    transform: translate(-50%);
+    text-align: center;
+    white-space: nowrap;
+    font-size: 14px;
+    font-style: normal;
+    pointer-events: auto;
+    /* background-size: 38.5px 18.375px; */
+    border: 1px solid #bbb;
+    /* -webkit-box-shadow: 0 1.875px 10.5px rgba(45,45,45,.5); */
+    /* box-shadow: 0 1.875px 10.5px rgba(45,45,45,.5); */
+    border-radius: 18.375px;
+    padding: 0px 14px;
+    background: rgba(30, 30, 30, 0.38);
+}
+
+.dollLabels .roomLabel a span {
+    white-space: nowrap;
+	color:white;
+    /* position: absolute; */
+    user-select: none;
+    /* left: 50%; */
+    /* top: 50%; */
+    -webkit-transform: translate(-50%,-50%);
+    /* transform: translate(-50%,-50%); */
+}
+
+.dollLabels .roomLabel.with-small-font a span {
+    -webkit-transform: translate(-50%,-50%) scale(.83);
+    transform: translate(-50%,-50%) scale(.83)
+}
+
+.dollLabels .roomLabel.with-entrance:after {
+    display: none
+}
+
+.dollLabels .roomLabel.with-entrance a {
+    top: 50%;
+    width: 38.5px;
+    height: 15.75px;
+    background-size: 38.5px 15.75px;
+    background-image: url(../images/roomlabel-entrance.svg);
+    -webkit-transform: translate(-50%,-50%);
+    transform: translate(-50%,-50%)
+}
+
+.dollLabels .roomLabel.with-entrance a span {
+    margin-left:  -0.875px;
+    margin-top:  -0.875px
+}
+
+
+
+
+
+.planLabels .roomLabel{
+	position: absolute;  
+    -webkit-animation: room-label .3s ease .1s;
+    animation: room-label .3s ease .1s;
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both
+}
+.planLabels .roomLabel a {
+	display: block;
+	position: absolute;
+	/* width: 38.5px; */
+	line-height: 24px;
+	/* top: -99px; */
+	/* left: 50%; */
+	-webkit-transform: translate(-50%);
+	transform: translate(-50%,-50%);
+	text-align: center;
+	white-space: nowrap;
+	font-size: 14px;
+	font-style: normal;
+	/* pointer-events: auto */
+	text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
+	color:white;
+}
+
+
+
+
+
+.doors {
+    position: absolute;
+    pointer-events: none;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0
+}
+
+.doors[data-camera-toward=forward] .door.show-arrow.right a:before {
+    margin-right: 3.5px;
+    -webkit-transform: rotate(180deg);
+    transform: rotate(180deg)
+}
+
+.doors[data-camera-toward=forward] .door.show-arrow.left a:after,.doors[data-camera-toward=forward] .door.show-arrow.right a:before {
+    content: "";
+    position: relative;
+    display: inline-block;
+    width: 10.5px;
+    height: 10.5px;
+    background: url(../images/room-arrow-label.svg) no-repeat 50%;
+    background-size: 100% 100%;
+    vertical-align: middle
+}
+
+.doors[data-camera-toward=forward] .door.show-arrow.left a:after {
+    margin-left: 3.5px
+}
+
+.doors[data-camera-toward=forward] .door.show-arrow.back a:after,.doors[data-camera-toward=right] .door.show-arrow.left a:after {
+    content: "";
+    display: inline-block;
+    vertical-align: middle;
+    width: 10.5px;
+    height: 10.5px;
+    background: url(../images/room-arrow-label.svg) no-repeat 50%;
+    background-size: 100% 100%;
+    margin-left: 3.5px;
+    -webkit-transform: rotate(-90deg);
+    transform: rotate(-90deg)
+}
+
+.doors[data-camera-toward=right] .door.show-arrow.back a:before {
+    margin-right: 3.5px;
+    -webkit-transform: rotate(180deg);
+    transform: rotate(180deg)
+}
+
+.doors[data-camera-toward=right] .door.show-arrow.back a:before,.doors[data-camera-toward=right] .door.show-arrow.forward a:after {
+    content: "";
+    position: relative;
+    display: inline-block;
+    width: 10.5px;
+    height: 10.5px;
+    background: url(../images/room-arrow-label.svg) no-repeat 50%;
+    background-size: 100% 100%;
+    vertical-align: middle
+}
+
+.doors[data-camera-toward=right] .door.show-arrow.forward a:after {
+    margin-left: 3.5px
+}
+
+.doors[data-camera-toward=left] .door.show-arrow.right a:after {
+    -webkit-transform: rotate(-90deg);
+    transform: rotate(-90deg)
+}
+
+.doors[data-camera-toward=left] .door.show-arrow.back a:after,.doors[data-camera-toward=left] .door.show-arrow.right a:after {
+    content: "";
+    display: inline-block;
+    vertical-align: middle;
+    width: 10.5px;
+    height: 10.5px;
+    background: url(../images/room-arrow-label.svg) no-repeat 50%;
+    background-size: 100% 100%;
+    margin-left: 3.5px
+}
+
+.doors[data-camera-toward=left] .door.show-arrow.back a:after {
+    position: relative
+}
+
+.doors[data-camera-toward=left] .door.show-arrow.forward a:before {
+    position: relative;
+    margin-right: 3.5px;
+    -webkit-transform: rotate(180deg);
+    transform: rotate(180deg)
+}
+
+.doors[data-camera-toward=back] .door.show-arrow.forward a:after,.doors[data-camera-toward=left] .door.show-arrow.forward a:before {
+    content: "";
+    display: inline-block;
+    width: 10.5px;
+    height: 10.5px;
+    background: url(../images/room-arrow-label.svg) no-repeat 50%;
+    background-size: 100% 100%;
+    vertical-align: middle
+}
+
+.doors[data-camera-toward=back] .door.show-arrow.forward a:after {
+    margin-left: 3.5px;
+    -webkit-transform: rotate(-90deg);
+    transform: rotate(-90deg)
+}
+
+.doors[data-camera-toward=back] .door.show-arrow.right a:after {
+    margin-left: 3.5px
+}
+
+.doors[data-camera-toward=back] .door.show-arrow.left a:before,.doors[data-camera-toward=back] .door.show-arrow.right a:after {
+    content: "";
+    position: relative;
+    display: inline-block;
+    width: 10.5px;
+    height: 10.5px;
+    background: url(../images/room-arrow-label.svg) no-repeat 50%;
+    background-size: 100% 100%;
+    vertical-align: middle
+}
+
+.doors[data-camera-toward=back] .door.show-arrow.left a:before {
+    margin-right: 3.5px;
+    -webkit-transform: rotate(180deg);
+    transform: rotate(180deg)
+}
+
+.doors .door {
+    position: absolute;
+    width: 0;
+    height: 0;
+    /* display: none; */
+    -webkit-animation: viewport-door-label .3s ease 1s;
+    animation: viewport-door-label .3s ease 1s;
+    -webkit-animation-fill-mode: both;
+    animation-fill-mode: both;
+    -webkit-transform: translateZ(0);
+    transform: translateZ(0)
+}
+
+/* .doors .door.visible {
+    display: block
+} */
+
+.doors .door a {
+    display: block;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    -webkit-transform: translate(-50%,-50%);
+    transform: translate(-50%,-50%);
+    border-radius: 1.75px;
+    background: rgba(0,0,0,.3);
+    line-height: 10.5px;
+    padding: 3.5px 4.375px;
+    white-space: nowrap;
+    font-size: 10.5px;
+    font-style: normal;
+    pointer-events: auto;
+    -webkit-transition: background .3s ease,color .3s ease,-webkit-transform 1s ease;
+    transition: background .3s ease,color .3s ease,-webkit-transform 1s ease;
+    transition: transform 1s ease,background .3s ease,color .3s ease;
+    transition: transform 1s ease,background .3s ease,color .3s ease,-webkit-transform 1s ease
+}
+
+.doors .door a:after {
+    -webkit-transition: opacity .3s ease;
+    transition: opacity .3s ease
+}
+
+.doors .door a:active {
+    background: rgba(0,0,0,.5);
+    color: hsla(0,0%,100%,.5)
+}
+
+.doors .door a:active:after {
+    opacity: .5
+}

文件差异内容过多而无法显示
+ 12 - 0
download_code/controller/static/css/swiper-4.3.5.min.css


文件差异内容过多而无法显示
+ 2212 - 0
download_code/controller/static/css/toolBoxApp.css


文件差异内容过多而无法显示
+ 4945 - 0
download_code/controller/static/css/toolBoxPC.css


文件差异内容过多而无法显示
+ 1942 - 0
download_code/controller/static/css/video-js.css


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/data/screenCap1.json


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/data/screenCap2.json


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/data/screenCap3.json


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/data/screenCap4.json


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/data/screenCap5.json


+ 1 - 0
download_code/controller/static/data/tourList.json

@@ -0,0 +1 @@
+[{"index":0,"name":""},{"index":252,"name":""},{"index":321,"name":""},{"index":1176,"name":""},{"index":1786,"name":""},{"index":2373,"name":""},{"index":2557,"name":""},{"index":3109,"name":""},{"index":3596,"name":""},{"index":3778,"name":""},{"index":4173,"name":""},{"index":4393,"name":""},{"index":4836,"name":""}]

二进制
download_code/controller/static/fonts/open-sans/OpenSansLight.eot


文件差异内容过多而无法显示
+ 21034 - 0
download_code/controller/static/fonts/open-sans/OpenSansLight.svg


二进制
download_code/controller/static/fonts/open-sans/OpenSansLight.ttf


二进制
download_code/controller/static/fonts/open-sans/OpenSansLight.woff


二进制
download_code/controller/static/fonts/open-sans/OpenSansLight.woff2


二进制
download_code/controller/static/fonts/open-sans/OpenSansRegular.woff


二进制
download_code/controller/static/fonts/open-sans/OpenSansRegular.woff2


文件差异内容过多而无法显示
+ 1 - 0
download_code/controller/static/images/4dkk_icon.svg


+ 137 - 0
download_code/controller/static/images/4dkk_icon_en.svg

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFFFFF;}
+</style>
+<g>
+	<g>
+		<path class="st0" d="M454.7,532.9h2.5v10.6h5.2v2.1h-7.7V532.9z"/>
+		<path class="st0" d="M464.6,540.8c0-3.1,2.2-5.1,4.5-5.1c2.7,0,4,1.9,4,4.6c0,0.5-0.1,0.9-0.1,1.2H467c0.2,1.6,1.2,2.4,2.7,2.4
+			c0.8,0,1.5-0.2,2.2-0.7l0.9,1.5c-0.9,0.7-2.2,1.1-3.4,1.1C466.7,545.9,464.6,544,464.6,540.8z M470.9,539.8c0-1.3-0.6-2.1-1.8-2.1
+			c-1,0-1.9,0.7-2.1,2.1H470.9z"/>
+		<path class="st0" d="M476.3,542.2V538H475v-1.9l1.5-0.1l0.3-2.6h2.1v2.6h2.4v2h-2.4v4.3c0,1.1,0.4,1.6,1.3,1.6
+			c0.3,0,0.7-0.1,0.9-0.2l0.4,1.8c-0.5,0.2-1.2,0.4-2,0.4C477.2,545.9,476.3,544.4,476.3,542.2z"/>
+		<path class="st0" d="M492.4,544.5l1.2-1.6c0.9,0.7,1.7,1.1,2.6,1.1c1,0,1.4-0.4,1.4-1c0-0.7-1-1.1-2-1.4c-1.2-0.5-2.6-1.2-2.6-2.8
+			c0-1.7,1.4-3,3.6-3c1.4,0,2.5,0.6,3.3,1.2l-1.1,1.5c-0.7-0.5-1.4-0.8-2.1-0.8c-0.9,0-1.3,0.4-1.3,0.9c0,0.7,0.9,1,2,1.3
+			c1.3,0.5,2.7,1.1,2.7,2.9c0,1.7-1.3,3-3.8,3C494.8,545.9,493.4,545.3,492.4,544.5z"/>
+		<path class="st0" d="M502.7,536h2.1l0.2,1h0.1c0.8-0.7,1.8-1.2,2.8-1.2c2.4,0,3.8,1.9,3.8,4.9c0,3.3-2,5.2-4.1,5.2
+			c-0.8,0-1.7-0.4-2.4-1.1l0.1,1.6v2.9h-2.5V536z M509,540.7c0-1.8-0.6-2.9-1.9-2.9c-0.7,0-1.2,0.3-1.9,1v4.2
+			c0.6,0.5,1.2,0.7,1.8,0.7C508.1,543.8,509,542.8,509,540.7z"/>
+		<path class="st0" d="M514,543c0-2.1,1.7-3.2,5.5-3.6c0-0.9-0.4-1.7-1.6-1.7c-0.9,0-1.8,0.4-2.7,0.9l-0.9-1.7
+			c1.1-0.7,2.5-1.3,4-1.3c2.4,0,3.7,1.5,3.7,4.3v5.6h-2.1l-0.2-1h-0.1c-0.8,0.7-1.8,1.3-2.9,1.3C515.2,545.9,514,544.6,514,543z
+			 M519.6,542.9V541c-2.3,0.3-3.1,0.9-3.1,1.8c0,0.8,0.5,1.1,1.3,1.1C518.5,543.9,519,543.5,519.6,542.9z"/>
+		<path class="st0" d="M524.9,540.8c0-3.2,2.3-5.1,4.9-5.1c1.2,0,2.1,0.5,2.8,1.1l-1.2,1.6c-0.5-0.4-0.9-0.6-1.5-0.6
+			c-1.5,0-2.5,1.2-2.5,3c0,1.8,1,3,2.4,3c0.7,0,1.3-0.3,1.9-0.8l1,1.7c-0.9,0.8-2.1,1.2-3.2,1.2C526.9,545.9,524.9,544,524.9,540.8z
+			"/>
+		<path class="st0" d="M534.7,540.8c0-3.1,2.2-5.1,4.5-5.1c2.7,0,4,1.9,4,4.6c0,0.5-0.1,0.9-0.1,1.2h-5.9c0.2,1.6,1.2,2.4,2.7,2.4
+			c0.8,0,1.5-0.2,2.2-0.7l0.9,1.5c-0.9,0.7-2.2,1.1-3.4,1.1C536.8,545.9,534.7,544,534.7,540.8z M541.1,539.8c0-1.3-0.6-2.1-1.8-2.1
+			c-1,0-1.9,0.7-2.1,2.1H541.1z"/>
+		<path class="st0" d="M555.8,542.2V538h-1.4v-1.9l1.5-0.1l0.3-2.6h2.1v2.6h2.4v2h-2.4v4.3c0,1.1,0.4,1.6,1.3,1.6
+			c0.3,0,0.7-0.1,0.9-0.2l0.4,1.8c-0.5,0.2-1.2,0.4-2,0.4C556.7,545.9,555.8,544.4,555.8,542.2z"/>
+		<path class="st0" d="M562.9,540.8c0-3.1,2.2-5.1,4.5-5.1c2.7,0,4,1.9,4,4.6c0,0.5-0.1,0.9-0.1,1.2h-5.9c0.2,1.6,1.2,2.4,2.7,2.4
+			c0.8,0,1.5-0.2,2.2-0.7l0.9,1.5c-0.9,0.7-2.2,1.1-3.4,1.1C565,545.9,562.9,544,562.9,540.8z M569.2,539.8c0-1.3-0.6-2.1-1.8-2.1
+			c-1,0-1.9,0.7-2.1,2.1H569.2z"/>
+		<path class="st0" d="M574.3,542.9v-11h2.5V543c0,0.6,0.3,0.8,0.5,0.8c0.1,0,0.2,0,0.3,0l0.3,1.9c-0.3,0.1-0.7,0.2-1.3,0.2
+			C574.9,545.9,574.3,544.7,574.3,542.9z"/>
+		<path class="st0" d="M580.5,542.9v-11h2.5V543c0,0.6,0.3,0.8,0.5,0.8c0.1,0,0.2,0,0.3,0l0.3,1.9c-0.3,0.1-0.7,0.2-1.3,0.2
+			C581.1,545.9,580.5,544.7,580.5,542.9z"/>
+		<path class="st0" d="M596.4,542.2V538h-1.4v-1.9l1.5-0.1l0.3-2.6h2.1v2.6h2.4v2h-2.4v4.3c0,1.1,0.4,1.6,1.3,1.6
+			c0.3,0,0.7-0.1,0.9-0.2l0.4,1.8c-0.5,0.2-1.2,0.4-2,0.4C597.3,545.9,596.4,544.4,596.4,542.2z"/>
+		<path class="st0" d="M604.1,531.9h2.5v3.5l-0.1,1.8c0.8-0.7,1.7-1.4,3-1.4c2.1,0,3,1.4,3,3.9v6H610v-5.7c0-1.5-0.4-2-1.4-2
+			c-0.8,0-1.3,0.4-2,1.1v6.6h-2.5V531.9z"/>
+		<path class="st0" d="M615.3,540.8c0-3.1,2.2-5.1,4.5-5.1c2.7,0,4,1.9,4,4.6c0,0.5-0.1,0.9-0.1,1.2h-5.9c0.2,1.6,1.2,2.4,2.7,2.4
+			c0.8,0,1.5-0.2,2.2-0.7l0.9,1.5c-0.9,0.7-2.2,1.1-3.4,1.1C617.4,545.9,615.3,544,615.3,540.8z M621.6,539.8c0-1.3-0.6-2.1-1.8-2.1
+			c-1,0-1.9,0.7-2.1,2.1H621.6z"/>
+		<path class="st0" d="M635.1,544.5l1.2-1.6c0.9,0.7,1.7,1.1,2.6,1.1c1,0,1.4-0.4,1.4-1c0-0.7-1-1.1-2-1.4c-1.2-0.5-2.6-1.2-2.6-2.8
+			c0-1.7,1.4-3,3.6-3c1.4,0,2.5,0.6,3.3,1.2l-1.1,1.5c-0.7-0.5-1.4-0.8-2.1-0.8c-0.9,0-1.3,0.4-1.3,0.9c0,0.7,0.9,1,2,1.3
+			c1.3,0.5,2.7,1.1,2.7,2.9c0,1.7-1.3,3-3.8,3C637.5,545.9,636,545.3,635.1,544.5z"/>
+		<path class="st0" d="M645.7,542.2V538h-1.4v-1.9l1.5-0.1l0.3-2.6h2.1v2.6h2.4v2h-2.4v4.3c0,1.1,0.4,1.6,1.3,1.6
+			c0.3,0,0.7-0.1,0.9-0.2l0.4,1.8c-0.5,0.2-1.2,0.4-2,0.4C646.6,545.9,645.7,544.4,645.7,542.2z"/>
+		<path class="st0" d="M652.7,540.8c0-3.2,2.2-5.1,4.6-5.1c2.4,0,4.6,1.9,4.6,5.1c0,3.2-2.2,5-4.6,5
+			C654.9,545.9,652.7,544,652.7,540.8z M659.4,540.8c0-1.8-0.7-3-2-3c-1.3,0-2.1,1.2-2.1,3c0,1.8,0.7,3,2.1,3
+			C658.7,543.8,659.4,542.6,659.4,540.8z"/>
+		<path class="st0" d="M664.9,536h2.1l0.2,1.7h0.1c0.7-1.3,1.7-1.9,2.7-1.9c0.5,0,0.8,0.1,1.1,0.2l-0.4,2.2c-0.3-0.1-0.6-0.2-1-0.2
+			c-0.8,0-1.7,0.5-2.2,1.9v5.8h-2.5V536z"/>
+		<path class="st0" d="M672.7,549.3l0.5-1.9c0.2,0.1,0.4,0.1,0.7,0.1c1,0,1.5-0.6,1.8-1.5l0.2-0.6L672,536h2.5l1.5,4.5
+			c0.3,0.9,0.5,1.8,0.8,2.7h0.1c0.2-0.9,0.5-1.8,0.7-2.7l1.3-4.5h2.4l-3.4,9.9c-0.8,2.3-1.9,3.6-4,3.6
+			C673.4,549.5,673.1,549.4,672.7,549.3z"/>
+	</g>
+	<path class="st0" d="M346.5,502.4c0,12.6,10.2,22.8,22.8,22.8c12.6,0,22.8-10.2,22.8-22.8c0-3.8-1-7.4-2.6-10.6
+		c-0.9,3.4-3.9,5.9-7.6,5.9c-4.3,0-7.8-3.5-7.8-7.8c0-3.7,2.5-6.8,5.9-7.6c-3.2-1.7-6.8-2.6-10.6-2.6
+		C356.7,479.6,346.5,489.8,346.5,502.4"/>
+	<g>
+		<path class="st0" d="M404.6,532.5c4.7-9,7.3-19.2,7.3-30.1c0-23.6-19.1-42.7-42.7-42.7c-23.6,0-42.7,19.1-42.7,42.7
+			c0,3.5,0.3,6.9,0.8,10.2c-6.6,0-10.8,1.2-11.6,3.9c-1.1,4.1,6,9.9,17.8,15.5l0,0c4.2,2.1,8.6,4.1,13,6c2.7,1.2,5.3,2.3,8,3.4
+			c2.7,1.2,5.4,2.3,8.1,3.5c-1.5-0.1-2.9-0.3-4.4-0.6c-1.5-0.2-2.9-0.5-4.4-0.8c-2.9-0.6-5.8-1.4-8.6-2.2c-2.7-0.8-5.3-1.7-7.9-2.7
+			c7.6,11.5,18.7,20.4,31.8,25.3c9.2-3.4,17.4-8.8,24.1-15.7c12.9,1.1,21.9-0.3,23-4.4C417.3,540.5,412.7,536.6,404.6,532.5
+			 M323.4,517.9c0.2-0.8,1.9-1.1,4.8-1c0.4,1.9,1,3.8,1.6,5.7C325.5,520.6,323.1,518.9,323.4,517.9 M369.3,533.6
+			c-17.2,0-31.2-14-31.2-31.2c0-17.2,14-31.2,31.2-31.2c17.2,0,31.2,14,31.2,31.2C400.5,519.6,386.5,533.6,369.3,533.6 M407.3,540.6
+			c-0.3,1-3.3,1.3-8.2,0.8c1.1-1.5,2.2-3.1,3.2-4.8C405.7,538.3,407.5,539.7,407.3,540.6"/>
+	</g>
+	<g>
+		<rect x="688" y="538.9" class="st0" width="20.9" height="1.1"/>
+		<rect x="426.7" y="538.9" class="st0" width="20.9" height="1.1"/>
+	</g>
+	<g>
+		<g>
+			<path class="st0" d="M476.1,520.4h-6.8c-1.5,0-2.6-0.4-3.3-1.1c-0.7-0.7-1-1.8-1-3.4v-32.3c0-1.5,0.3-2.6,1-3.3
+				c0.7-0.7,1.8-1,3.3-1h6.9c6.2,0,11.3,1.9,15.1,5.6c1.9,1.9,3.3,4.1,4.2,6.5c0.8,2.4,1.3,5.3,1.3,8.8c0,8.1-2.3,13.7-7,16.8
+				c-2.1,1.4-4.8,2.4-8.2,3C479.7,520.3,477.9,520.4,476.1,520.4z M477.3,484.2H473c-0.9,0-1.3,0.4-1.3,1.2v28.7
+				c0,0.8,0.4,1.2,1.3,1.2h4.3c2.3,0,4.3-0.4,5.7-1.3c4.3-2.5,6.4-7.2,6.4-14.2c0-5.1-1.2-9-3.6-11.9c-1.1-1.3-2.7-2.3-4.6-3
+				C479.9,484.5,478.6,484.2,477.3,484.2z"/>
+		</g>
+		<path class="st0" d="M457.8,507c-0.3-0.4-0.8-0.6-1.2-0.6h-3.2V484c0-2.4-0.8-4-2.3-4.7c-1-0.5-2-0.7-3-0.7c-2.2,0-4,1.2-5.5,3.5
+			l-13.8,22.1c-0.9,1.5-1.5,2.4-1.6,2.6c-0.4,0.7-0.6,1.4-0.6,2.3c0,1.6,0.9,2.5,2.8,2.5h17.1v6.1c0,1.9,1.5,3.4,3.4,3.4
+			c1.9,0,3.4-1.5,3.4-3.4v-6.1h3.2c0.4,0,0.7-0.2,1-0.5c0.6-0.5,0.8-1.2,0.8-2.1C458.5,508.9,458.3,507.5,457.8,507z M446.6,506.5
+			h-12.4l12.4-19.3V506.5z"/>
+		<g>
+			<g>
+				<path class="st0" d="M509.9,494.7l17.9-15.1c0.7-0.5,1.5-0.8,2.4-0.8c1.4,0,2.6,0.5,3.5,1.4c0.7,0.7,1,1.5,1,2.4
+					c0,1.1-0.4,1.9-1.1,2.5l-14.2,10.9l13.5,17.9c0.8,1,1.2,1.9,1.2,2.7c0,1.1-0.5,2-1.5,2.6c-1,0.7-1.8,0.8-3.2,0.8
+					c-0.8,0-1.4-0.1-2-0.4c-0.6-0.2-1.2-0.8-1.8-1.7l-12.2-17.4l-3.6,2.8"/>
+				<path class="st0" d="M509.9,517.5c0,1.9-1.5,3.4-3.4,3.4l0,0c-1.9,0-3.4-1.5-3.4-3.4v-35.4c0-1.9,1.5-3.4,3.4-3.4l0,0
+					c1.9,0,3.4,1.5,3.4,3.4V517.5z"/>
+			</g>
+			<g>
+				<path class="st0" d="M569.9,516.9c0,1.9-1.5,3.4-3.4,3.4l0,0c-1.9,0-3.4-1.5-3.4-3.4v-23.6c0-1.9,1.5-3.4,3.4-3.4l0,0
+					c1.9,0,3.4,1.5,3.4,3.4V516.9z"/>
+				<path class="st0" d="M552.3,490.1c-7.7,0-13.9,6.7-13.9,15c0,8.3,6.2,15,13.9,15c7.7,0,13.9-6.7,13.9-15
+					C566.2,496.8,560,490.1,552.3,490.1z M552.3,513.8c-4.5,0-8.1-3.9-8.1-8.7c0-4.8,3.6-8.7,8.1-8.7c4.5,0,8.1,3.9,8.1,8.7
+					C560.4,509.9,556.7,513.8,552.3,513.8z"/>
+			</g>
+			<g>
+				<path class="st0" d="M583.1,516.9c0,1.9-1.5,3.4-3.4,3.4l0,0c-1.9,0-3.4-1.5-3.4-3.4v-23.6c0-1.9,1.5-3.4,3.4-3.4l0,0
+					c1.9,0,3.4,1.5,3.4,3.4V516.9z"/>
+				<path class="st0" d="M591,488.7c-3.9,0-6.5,1.2-8.1,3.5c-0.8,1.9-1.6,3.9-2.6,5.1v3.7h1.3c0.3-3.2,3-5.6,6.3-5.6
+					c1.5,0,2.9,0.5,3.9,1.4c0,0,0,0,0,0c0.1,0.1,0.2,0.1,0.3,0.2c0.5,0.4,0.9,0.9,1.2,1.5c0.5,0.9,0.9,2,0.9,3.1c0,0,0,0,0,0.1V516
+					c0.2,2.9,1.5,4.4,4.2,4.4c2.6,0,4.1-1.5,4.4-4.4V500C602.3,493,598.4,489.2,591,488.7z"/>
+			</g>
+		</g>
+		<g>
+			<g>
+				<path class="st0" d="M616,494.7l17.9-15.1c0.7-0.5,1.5-0.8,2.4-0.8c1.4,0,2.6,0.5,3.5,1.4c0.7,0.7,1,1.5,1,2.4
+					c0,1.1-0.4,1.9-1.1,2.5l-14.2,10.9l13.5,17.9c0.8,1,1.2,1.9,1.2,2.7c0,1.1-0.5,2-1.5,2.6c-1,0.7-1.8,0.8-3.2,0.8
+					c-0.8,0-1.4-0.1-2-0.4c-0.6-0.2-1.2-0.8-1.8-1.7l-12.2-17.4l-3.6,2.8"/>
+				<path class="st0" d="M616,517.5c0,1.9-1.5,3.4-3.4,3.4l0,0c-1.9,0-3.4-1.5-3.4-3.4v-35.4c0-1.9,1.5-3.4,3.4-3.4l0,0
+					c1.9,0,3.4,1.5,3.4,3.4V517.5z"/>
+			</g>
+			<g>
+				<path class="st0" d="M676,516.9c0,1.9-1.5,3.4-3.4,3.4l0,0c-1.9,0-3.4-1.5-3.4-3.4v-23.6c0-1.9,1.5-3.4,3.4-3.4l0,0
+					c1.9,0,3.4,1.5,3.4,3.4V516.9z"/>
+				<path class="st0" d="M658.4,490.1c-7.7,0-13.9,6.7-13.9,15c0,8.3,6.2,15,13.9,15c7.7,0,13.9-6.7,13.9-15
+					C672.3,496.8,666.1,490.1,658.4,490.1z M658.4,513.8c-4.5,0-8.1-3.9-8.1-8.7c0-4.8,3.6-8.7,8.1-8.7c4.5,0,8.1,3.9,8.1,8.7
+					C666.4,509.9,662.8,513.8,658.4,513.8z"/>
+			</g>
+			<g>
+				<path class="st0" d="M689.2,516.9c0,1.9-1.5,3.4-3.4,3.4l0,0c-1.9,0-3.4-1.5-3.4-3.4v-23.6c0-1.9,1.5-3.4,3.4-3.4l0,0
+					c1.9,0,3.4,1.5,3.4,3.4V516.9z"/>
+				<path class="st0" d="M697.1,488.7c-3.9,0-6.5,1.2-8.1,3.5c-0.8,1.9-1.6,3.9-2.6,5.1v3.7h1.3c0.3-3.2,3-5.6,6.3-5.6
+					c1.5,0,2.9,0.5,3.9,1.4c0,0,0,0,0,0c0.1,0.1,0.2,0.1,0.3,0.2c0.5,0.4,0.9,0.9,1.2,1.5c0.5,0.9,0.9,2,0.9,3.1c0,0,0,0,0,0.1V516
+					c0.2,2.9,1.5,4.4,4.2,4.4c2.6,0,4.1-1.5,4.4-4.4V500C708.4,493,704.5,489.2,697.1,488.7z"/>
+			</g>
+		</g>
+	</g>
+</g>
+</svg>

二进制
download_code/controller/static/images/End.png


二进制
download_code/controller/static/images/audio/01.mp3


二进制
download_code/controller/static/images/audio/02.mp3


二进制
download_code/controller/static/images/audio/03.mp3


二进制
download_code/controller/static/images/audio/04.mp3


二进制
download_code/controller/static/images/audio/05.mp3


二进制
download_code/controller/static/images/audio/06.mp3


二进制
download_code/controller/static/images/audio/07.mp3


二进制
download_code/controller/static/images/audio/08.mp3


二进制
download_code/controller/static/images/blueReticle.png


二进制
download_code/controller/static/images/bottom_logo.png


二进制
download_code/controller/static/images/btn-slider.png


二进制
download_code/controller/static/images/cad_column.png


二进制
download_code/controller/static/images/cad_door.png


二进制
download_code/controller/static/images/cad_point.png


二进制
download_code/controller/static/images/cad_window.png


二进制
download_code/controller/static/images/canvasPlay.png


二进制
download_code/controller/static/images/checked_hook.png


二进制
download_code/controller/static/images/default.jpg


二进制
download_code/controller/static/images/delAsk-bg.png


二进制
download_code/controller/static/images/direction_click.png


二进制
download_code/controller/static/images/direction_default.png


二进制
download_code/controller/static/images/floorlogo/0.png


二进制
download_code/controller/static/images/floorlogo/1.png


二进制
download_code/controller/static/images/floorlogo/2.png


二进制
download_code/controller/static/images/floorlogo/en/0.png


二进制
download_code/controller/static/images/floorlogo/en/1.png


二进制
download_code/controller/static/images/floorlogo/en/2.png


二进制
download_code/controller/static/images/icon-kankan-style-1.png


二进制
download_code/controller/static/images/icon-kankan-style-2.png


二进制
download_code/controller/static/images/icon-kankan-style-3.png


二进制
download_code/controller/static/images/icon_Google_Chrome_2011.png


二进制
download_code/controller/static/images/icon_Internet_Explorer_10.png


二进制
download_code/controller/static/images/icon_MacOSX_Safari.png


二进制
download_code/controller/static/images/icon_Mozilla_Firefox.png


二进制
download_code/controller/static/images/icon_biaochi_defult.png


二进制
download_code/controller/static/images/icon_biaochi_select.png


二进制
download_code/controller/static/images/icon_close_black.png


二进制
download_code/controller/static/images/icon_feiji.png


二进制
download_code/controller/static/images/input-bg.png


二进制
download_code/controller/static/images/labelline.png


二进制
download_code/controller/static/images/line-1.png


二进制
download_code/controller/static/images/loadFail.png


二进制
download_code/controller/static/images/lock-bg.png


+ 0 - 0
download_code/controller/static/images/marker.png


部分文件因为文件数量过多而无法显示