Browse Source

Signed-off-by: chuwu <1178078758@qq.com>
代码转移,github

chuwu 6 years ago
commit
350df9ce4b
100 changed files with 121976 additions and 0 deletions
  1. 12 0
      .babelrc
  2. 9 0
      .editorconfig
  3. 14 0
      .gitignore
  4. 10 0
      .postcssrc.js
  5. 263 0
      README.md
  6. 41 0
      build/build.js
  7. 54 0
      build/check-versions.js
  8. BIN
      build/logo.png
  9. 101 0
      build/utils.js
  10. 22 0
      build/vue-loader.conf.js
  11. 92 0
      build/webpack.base.conf.js
  12. 89 0
      build/webpack.dev.conf.js
  13. 140 0
      build/webpack.prod.conf.js
  14. 8 0
      config/dev.env.js
  15. 117 0
      config/index.js
  16. 8 0
      config/prod.env.js
  17. BIN
      favicon.ico
  18. 313 0
      handsontable-chosen-editor.js
  19. 21 0
      index.html
  20. 10553 0
      package-lock.json
  21. 79 0
      package.json
  22. 7 0
      photoView/README.md
  23. 77 0
      photoView/css/reset.css
  24. 9 0
      photoView/css/viewer.min.css
  25. 324 0
      photoView/js/CSS3DStereoRenderer.js
  26. 6855 0
      photoView/js/photo-sphere-viewer.js
  27. 2 0
      photoView/js/photo-sphere-viewer.min.js
  28. 46814 0
      photoView/js/three.js
  29. 2443 0
      photoView/js/three.min.js
  30. 10 0
      photoView/js/viewer.min.js
  31. 250 0
      photoView/photo-View.html
  32. 42 0
      photoView/test.html
  33. 18 0
      src/App.vue
  34. 3 0
      src/api/config.js
  35. 30 0
      src/api/fetch.js
  36. 50 0
      src/api/httpUtil.js
  37. 760 0
      src/api/request.js
  38. BIN
      src/assets/css/chosen-sprite.png
  39. BIN
      src/assets/css/chosen-sprite@2x.png
  40. 490 0
      src/assets/css/chosen.css
  41. 477 0
      src/assets/css/jsmind.css
  42. 233 0
      src/assets/css/reset.css
  43. 67 0
      src/assets/icon/iconfont.css
  44. BIN
      src/assets/icon/iconfont.eot
  45. 1 0
      src/assets/icon/iconfont.js
  46. 108 0
      src/assets/icon/iconfont.svg
  47. BIN
      src/assets/icon/iconfont.ttf
  48. BIN
      src/assets/icon/iconfont.woff
  49. BIN
      src/assets/images/point.png
  50. BIN
      src/assets/images/unfold.png
  51. 1378 0
      src/assets/js/chosen.jquery.min.js
  52. 286 0
      src/assets/js/graphyCanvas.js
  53. 7 0
      src/assets/js/graphyEvent.js
  54. 324 0
      src/assets/js/handsontable-chosen-editor.js
  55. 21 0
      src/assets/js/isDuitString.js
  56. 70 0
      src/assets/js/items/SGraphyCircleItem.js
  57. 59 0
      src/assets/js/items/SGraphyImageItem.js
  58. 66 0
      src/assets/js/items/SGraphyLineItem.js
  59. 76 0
      src/assets/js/items/SGraphyPillarItems.js
  60. 257 0
      src/assets/js/items/SGraphyPolygonItem.js
  61. 100 0
      src/assets/js/items/SGraphyRectItem.js
  62. 51 0
      src/assets/js/items/SGraphyTextItems.js
  63. 66 0
      src/assets/js/items/SGraphyVirtualItem.js
  64. 2 0
      src/assets/js/jquery.min.js
  65. 2934 0
      src/assets/js/jsmind.js
  66. 1 0
      src/assets/js/qrcode/qrcode.min.js
  67. 463 0
      src/assets/js/tools.js
  68. BIN
      src/assets/json/1CDC5E0E-50EB-415a-BBC1-099832D12238.txt
  69. BIN
      src/assets/json/bim.jsonz
  70. 12944 0
      src/assets/json/cxds5.json
  71. 5540 0
      src/assets/json/end.json
  72. 39 0
      src/assets/json/mind.json
  73. 81 0
      src/assets/json/relation.json
  74. 424 0
      src/assets/json/roomCl.json
  75. 7795 0
      src/assets/json/space(2).json
  76. 7795 0
      src/assets/json/space(3).json
  77. 7795 0
      src/assets/json/space.json
  78. 1 0
      src/assets/json/test.json
  79. BIN
      src/assets/logo.png
  80. 44 0
      src/assets/node-templete/SGraphy/SCanvas.js
  81. 30 0
      src/assets/node-templete/SGraphy/SGraphyEnums.js
  82. 396 0
      src/assets/node-templete/SGraphy/SGraphyItem.js
  83. 201 0
      src/assets/node-templete/SGraphy/SGraphyScene.js
  84. 280 0
      src/assets/node-templete/SGraphy/SGraphyView.js
  85. 53 0
      src/assets/node-templete/SGraphy/SMouseEvent.js
  86. 201 0
      src/assets/node-templete/SGraphy/items/SGraphyClockItem.js
  87. 58 0
      src/assets/node-templete/SGraphy/items/SGraphyLineItem.js
  88. 57 0
      src/assets/node-templete/SGraphy/items/SGraphyPolygonItem.js
  89. 64 0
      src/assets/node-templete/SGraphy/items/SGraphyRectItem.js
  90. 61 0
      src/assets/node-templete/SGraphy/items/SGraphyVirtualItem.js
  91. 40 0
      src/assets/node-templete/SGraphy/types/SPoint.js
  92. 169 0
      src/assets/node-templete/SGraphy/types/SRect.js
  93. 9 0
      src/assets/node-templete/index.js
  94. 37 0
      src/assets/pako/pako.js
  95. 36 0
      src/components/HelloWorld.vue
  96. 26 0
      src/components/buildData/create.js
  97. 121 0
      src/components/buildData/dataFill.vue
  98. 9 0
      src/components/buildData/findId.js
  99. 493 0
      src/components/buildData/recommend.vue
  100. 0 0
      src/components/buildData/sagaButton.vue

+ 12 - 0
.babelrc

@@ -0,0 +1,12 @@
+{
+  "presets": [
+    ["env", {
+      "modules": false,
+      "targets": {
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
+      }
+    }],
+    "stage-2"
+  ],
+  "plugins": ["transform-vue-jsx", "transform-runtime"]
+}

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true

+ 14 - 0
.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

+ 10 - 0
.postcssrc.js

@@ -0,0 +1,10 @@
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+  "plugins": {
+    "postcss-import": {},
+    "postcss-url": {},
+    // to edit target browsers: use "browserslist" field in package.json
+    "autoprefixer": {}
+  }
+}

+ 263 - 0
README.md

@@ -0,0 +1,263 @@
+# ibms
+
+> A Vue.js project
+
+## Build Setup
+
+``` bash
+# install dependencies
+npm install
+
+# serve with hot reload at localhost:8080
+npm run dev
+
+# build for production with minification
+npm run build
+
+# build for production and view the bundle analyzer report
+npm run build --report
+```
+
+For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
+
+# 扫楼参数解释
+
+## 扫楼日志页/buildLog?projId=??&userId=??
+
+获取扫楼日志,需操作人id(userId)和项目id(projId)
+
+## 扫楼用户页/buildUser?projId=??&userId=??
+
+获取扫楼用户,并给与添加权限,删除权限(右键删除)
+
+## 扫楼异常资产页/buildAssets?projId=??&userId=??&secret=??
+
+获取扫楼异常资产,需操作人id和项目id以及密码(显示详情页使用)
+
+## 扫楼数据页/buildData?projId=??&userId=??
+
+获取扫楼数据进行处理,有修改资产权限,修改点位标签名及点位标签id权限
+
+```
+由于扫楼数据的存放url待定,暂时为IP:(http://172.16.1.21:8090/#)
+```
+```
+|-- RevitWeb
+    |-- .babelrc
+    |-- .editorconfig
+    |-- .gitignore
+    |-- .postcssrc.js
+    |-- favicon.ico
+    |-- handsontable-chosen-editor.js
+    |-- index.html
+    |-- package-lock.json
+    |-- package.json
+    |-- README.md
+    |-- build
+    |   |-- build.js
+    |   |-- check-versions.js
+    |   |-- logo.png
+    |   |-- utils.js
+    |   |-- vue-loader.conf.js
+    |   |-- webpack.base.conf.js
+    |   |-- webpack.dev.conf.js
+    |   |-- webpack.prod.conf.js
+    |-- config
+    |   |-- dev.env.js
+    |   |-- index.js
+    |   |-- prod.env.js                         //打包文件其中有两个应用地址
+    |-- photoView                               //图片查看公共工具
+    |   |-- photo-View.html                     //页面
+    |   |-- README.md
+    |   |-- test.html
+    |   |-- css
+    |   |   |-- reset.css
+    |   |   |-- viewer.min.css
+    |   |-- js
+    |       |-- CSS3DStereoRenderer.js
+    |       |-- photo-sphere-viewer.js
+    |       |-- photo-sphere-viewer.min.js
+    |       |-- three.js
+    |       |-- three.min.js
+    |       |-- viewer.min.js
+    |-- src
+    |   |-- App.vue
+    |   |-- main.js
+    |   |-- package.json
+    |   |-- api                               //请求
+    |   |   |-- config.js                     //设置
+    |   |   |-- fetch.js                      //封装
+    |   |   |-- httpUtil.js                   //再次封装
+    |   |   |-- request.js                    //集合
+    |   |-- assets                            //多个引用
+    |   |   |-- logo.png                      //logo
+    |   |   |-- css                           //css样式
+    |   |   |   |-- chosen-sprite.png         
+    |   |   |   |-- chosen-sprite@2x.png
+    |   |   |   |-- chosen.css                //chonse的样式
+    |   |   |   |-- jsmind.css                //思维导图的样式
+    |   |   |   |-- reset.css                 //重置样式表
+    |   |   |-- icon                          //iconfont--弃用
+    |   |   |   |-- iconfont.css
+    |   |   |   |-- iconfont.eot
+    |   |   |   |-- iconfont.js
+    |   |   |   |-- iconfont.svg
+    |   |   |   |-- iconfont.ttf
+    |   |   |   |-- iconfont.woff
+    |   |   |-- images                        //图片
+    |   |   |   |-- point.png
+    |   |   |   |-- unfold.png
+    |   |   |-- js                            //js工具
+    |   |   |   |-- chosen.jquery.min.js      //hansontable下拉工具
+    |   |   |   |-- graphyCanvas.js           //图形化引擎
+    |   |   |   |-- graphyEvent.js            //图形化引擎事件
+    |   |   |   |-- handsontable-chosen-editor.js  //下拉
+    |   |   |   |-- isDuitString.js                 //判断
+    |   |   |   |-- jquery.min.js               //jq
+    |   |   |   |-- jsmind.js                   //思维导图
+    |   |   |   |-- tools.js                    //工具函数
+    |   |   |   |-- canvas                      
+    |   |   |   |   |-- index.js
+    |   |   |   |   |-- items
+    |   |   |   |   |   |-- ball.js
+    |   |   |   |   |   |-- line.js
+    |   |   |   |   |   |-- point.js
+    |   |   |   |   |-- lib
+    |   |   |   |       |-- event
+    |   |   |   |           |-- SMouseEvent.js
+    |   |   |   |-- items                       //items,图形化引擎items
+    |   |   |   |   |-- SGraphyCircleItem.js    //圆
+    |   |   |   |   |-- SGraphyImageItem.js     //图片
+    |   |   |   |   |-- SGraphyLineItem.js      //线
+    |   |   |   |   |-- SGraphyPillarItems.js   //实心圆
+    |   |   |   |   |-- SGraphyPolygonItem.js   //不规则图形
+    |   |   |   |   |-- SGraphyRectItem.js      //矩形
+    |   |   |   |   |-- SGraphyTextItems.js     //字体
+    |   |   |   |   |-- SGraphyVirtualItem.js   //虚线
+    |   |   |   |-- qrcode
+    |   |   |       |-- qrcode.min.js           //qrcode生成工具
+    |   |   |-- json
+    |   |   |   |-- 1CDC5E0E-50EB-415a-BBC1-099832D12238.txt
+    |   |   |   |-- bim.jsonz
+    |   |   |   |-- cxds5.json
+    |   |   |   |-- end.json
+    |   |   |   |-- mind.json
+    |   |   |   |-- relation.json
+    |   |   |   |-- roomCl.json
+    |   |   |   |-- space(2).json
+    |   |   |   |-- space(3).json
+    |   |   |   |-- space.json
+    |   |   |   |-- test.json
+    |   |   |-- node-templete                   //图形化引擎
+    |   |   |   |-- index.js
+    |   |   |   |-- SGraphy
+    |   |   |       |-- SCanvas.js
+    |   |   |       |-- SGraphyEnums.js
+    |   |   |       |-- SGraphyItem.js
+    |   |   |       |-- SGraphyScene.js
+    |   |   |       |-- SGraphyView.js
+    |   |   |       |-- SMouseEvent.js
+    |   |   |       |-- items
+    |   |   |       |   |-- SGraphyClockItem.js
+    |   |   |       |   |-- SGraphyLineItem.js
+    |   |   |       |   |-- SGraphyPolygonItem.js
+    |   |   |       |   |-- SGraphyRectItem.js
+    |   |   |       |   |-- SGraphyVirtualItem.js
+    |   |   |       |-- types
+    |   |   |           |-- SPoint.js
+    |   |   |           |-- SRect.js
+    |   |   |-- pako
+    |   |       |-- pako.js
+    |   |-- components
+    |   |   |-- cascader.vue
+    |   |   |-- demo1.vue
+    |   |   |-- demo2.vue
+    |   |   |-- demo3.vue
+    |   |   |-- drag.vue
+    |   |   |-- graphyCanvas.vue
+    |   |   |-- graphyCanvas1.vue
+    |   |   |-- graphyTabs.vue
+    |   |   |-- graphyTree.vue
+    |   |   |-- HelloWorld.vue
+    |   |   |-- input.vue
+    |   |   |-- selectTime.vue
+    |   |   |-- business
+    |   |   |   |-- handsontable.vue
+    |   |   |   |-- spaceGraphy.vue
+    |   |   |   |-- spaceHandsontable.vue
+    |   |   |-- dialogHanson
+    |   |   |   |-- addDevice.vue
+    |   |   |-- dialogs
+    |   |   |   |-- detailsDialog.vue
+    |   |   |   |-- facilityDialog.vue
+    |   |   |   |-- influenceDialog.vue
+    |   |   |   |-- noModelDialog.vue
+    |   |   |   |-- notRelated.vue
+    |   |   |   |-- addDialog
+    |   |   |   |   |-- businessDialog.vue
+    |   |   |   |   |-- dialogAssets.vue
+    |   |   |   |   |-- dialogDevice.vue
+    |   |   |   |   |-- dialogSystem.vue
+    |   |   |   |-- list
+    |   |   |       |-- filesDialog.vue
+    |   |   |       |-- firm.vue
+    |   |   |       |-- guaranteeDialog.vue
+    |   |   |       |-- insurerDialog.vue
+    |   |   |       |-- maintainerDialog.vue
+    |   |   |       |-- picDialog.vue
+    |   |   |       |-- supplierDialog.vue
+    |   |   |       |-- supplyDialog.vue
+    |   |   |       |-- uploadImgDialog.vue
+    |   |   |-- graphy
+    |   |   |   |-- business.vue
+    |   |   |-- handsontables
+    |   |   |   |-- assets.vue
+    |   |   |   |-- device.vue
+    |   |   |   |-- system.vue
+    |   |   |-- lib
+    |   |   |   |-- floorCascader.vue
+    |   |   |   |-- formInput.vue
+    |   |   |   |-- myPagination.vue
+    |   |   |   |-- qrcode.vue
+    |   |   |   |-- uploadFiles.vue
+    |   |   |   |-- uploadImg.vue
+    |   |   |   |-- uploadImgs.vue
+    |   |   |   |-- cascaders
+    |   |   |       |-- assets.vue
+    |   |   |       |-- system.vue
+    |   |   |-- list
+    |   |   |   |-- title.vue
+    |   |   |-- table
+    |   |   |   |-- addEquip.vue
+    |   |   |   |-- businessTable.vue
+    |   |   |   |-- equipTable.vue
+    |   |   |-- transfers
+    |   |       |-- tableTransfers.vue
+    |   |-- config
+    |   |   |-- index.js
+    |   |   |-- rem.js
+    |   |-- router
+    |   |   |-- directive.js
+    |   |   |-- ele.js
+    |   |   |-- index.js
+    |   |-- utils
+    |   |   |-- hasontableUtils.js
+    |   |-- views
+    |       |-- assetsList.vue
+    |       |-- buildAssets.vue
+    |       |-- buildFamily.vue
+    |       |-- buildGraphy.vue
+    |       |-- buildingData.vue
+    |       |-- buildLog.vue
+    |       |-- buildUser.vue
+    |       |-- businessSpace.vue
+    |       |-- conduitGraphy.vue
+    |       |-- deviceList.vue
+    |       |-- gplot.vue
+    |       |-- layerPoint.vue
+    |       |-- mindMap.vue
+    |       |-- spaceGraphy.vue
+    |       |-- systemList.vue
+    |-- static
+        |-- .gitkeep
+```

+ 41 - 0
build/build.js

@@ -0,0 +1,41 @@
+'use strict'
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+const ora = require('ora')
+const rm = require('rimraf')
+const path = require('path')
+const chalk = require('chalk')
+const webpack = require('webpack')
+const config = require('../config')
+const webpackConfig = require('./webpack.prod.conf')
+
+const spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, (err, stats) => {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(stats.toString({
+      colors: true,
+      modules: false,
+      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
+      chunks: false,
+      chunkModules: false
+    }) + '\n\n')
+
+    if (stats.hasErrors()) {
+      console.log(chalk.red('  Build failed with errors.\n'))
+      process.exit(1)
+    }
+
+    console.log(chalk.cyan('  Build complete.\n'))
+    console.log(chalk.yellow(
+      '  Tip: built files are meant to be served over an HTTP server.\n' +
+      '  Opening index.html over file:// won\'t work.\n'
+    ))
+  })
+})

+ 54 - 0
build/check-versions.js

@@ -0,0 +1,54 @@
+'use strict'
+const chalk = require('chalk')
+const semver = require('semver')
+const packageConfig = require('../package.json')
+const shell = require('shelljs')
+
+function exec (cmd) {
+  return require('child_process').execSync(cmd).toString().trim()
+}
+
+const versionRequirements = [
+  {
+    name: 'node',
+    currentVersion: semver.clean(process.version),
+    versionRequirement: packageConfig.engines.node
+  }
+]
+
+if (shell.which('npm')) {
+  versionRequirements.push({
+    name: 'npm',
+    currentVersion: exec('npm --version'),
+    versionRequirement: packageConfig.engines.npm
+  })
+}
+
+module.exports = function () {
+  const warnings = []
+
+  for (let i = 0; i < versionRequirements.length; i++) {
+    const mod = versionRequirements[i]
+
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+      warnings.push(mod.name + ': ' +
+        chalk.red(mod.currentVersion) + ' should be ' +
+        chalk.green(mod.versionRequirement)
+      )
+    }
+  }
+
+  if (warnings.length) {
+    console.log('')
+    console.log(chalk.yellow('To use this template, you must update following to modules:'))
+    console.log()
+
+    for (let i = 0; i < warnings.length; i++) {
+      const warning = warnings[i]
+      console.log('  ' + warning)
+    }
+
+    console.log()
+    process.exit(1)
+  }
+}

BIN
build/logo.png


+ 101 - 0
build/utils.js

@@ -0,0 +1,101 @@
+'use strict'
+const path = require('path')
+const config = require('../config')
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
+const packageConfig = require('../package.json')
+
+exports.assetsPath = function (_path) {
+  const assetsSubDirectory = process.env.NODE_ENV === 'production'
+    ? config.build.assetsSubDirectory
+    : config.dev.assetsSubDirectory
+
+  return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function (options) {
+  options = options || {}
+
+  const cssLoader = {
+    loader: 'css-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  const postcssLoader = {
+    loader: 'postcss-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  // generate loader string to be used with extract text plugin
+  function generateLoaders (loader, loaderOptions) {
+    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
+
+    if (loader) {
+      loaders.push({
+        loader: loader + '-loader',
+        options: Object.assign({}, loaderOptions, {
+          sourceMap: options.sourceMap
+        })
+      })
+    }
+
+    // Extract CSS when that option is specified
+    // (which is the case during production build)
+    if (options.extract) {
+      return ExtractTextPlugin.extract({
+        use: loaders,
+        fallback: 'vue-style-loader'
+      })
+    } else {
+      return ['vue-style-loader'].concat(loaders)
+    }
+  }
+
+  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+  return {
+    css: generateLoaders(),
+    postcss: generateLoaders(),
+    less: generateLoaders('less'),
+    sass: generateLoaders('sass', { indentedSyntax: true }),
+    scss: generateLoaders('sass'),
+    stylus: generateLoaders('stylus'),
+    styl: generateLoaders('stylus')
+  }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function (options) {
+  const output = []
+  const loaders = exports.cssLoaders(options)
+
+  for (const extension in loaders) {
+    const loader = loaders[extension]
+    output.push({
+      test: new RegExp('\\.' + extension + '$'),
+      use: loader
+    })
+  }
+
+  return output
+}
+
+exports.createNotifierCallback = () => {
+  const notifier = require('node-notifier')
+
+  return (severity, errors) => {
+    if (severity !== 'error') return
+
+    const error = errors[0]
+    const filename = error.file && error.file.split('!').pop()
+
+    notifier.notify({
+      title: packageConfig.name,
+      message: severity + ': ' + error.name,
+      subtitle: filename || '',
+      icon: path.join(__dirname, 'logo.png')
+    })
+  }
+}

+ 22 - 0
build/vue-loader.conf.js

@@ -0,0 +1,22 @@
+'use strict'
+const utils = require('./utils')
+const config = require('../config')
+const isProduction = process.env.NODE_ENV === 'production'
+const sourceMapEnabled = isProduction
+  ? config.build.productionSourceMap
+  : config.dev.cssSourceMap
+
+module.exports = {
+  loaders: utils.cssLoaders({
+    sourceMap: sourceMapEnabled,
+    extract: isProduction
+  }),
+  cssSourceMap: sourceMapEnabled,
+  cacheBusting: config.dev.cacheBusting,
+  transformToRequire: {
+    video: ['src', 'poster'],
+    source: 'src',
+    img: 'src',
+    image: 'xlink:href'
+  }
+}

+ 92 - 0
build/webpack.base.conf.js

@@ -0,0 +1,92 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const vueLoaderConfig = require('./vue-loader.conf')
+const webpack = require('webpack')
+
+function resolve(dir) {
+    return path.join(__dirname, '..', dir)
+}
+
+
+
+module.exports = {
+    context: path.resolve(__dirname, '../'),
+    entry: {
+        app: './src/main.js'
+    },
+    output: {
+        path: config.build.assetsRoot,
+        filename: '[name].js',
+        publicPath: process.env.NODE_ENV === 'production' ?
+            config.build.assetsPublicPath : config.dev.assetsPublicPath
+    },
+    resolve: {
+        extensions: ['.js', '.vue', '.json'],
+        alias: {
+            'vue$': 'vue/dist/vue.esm.js',
+            '@': resolve('src'),
+            'jquery': 'jquery',
+            'handsontable': 'handsontable-pro'
+        }
+    },
+
+    // 增加一个plugins
+    plugins: [
+        new webpack.ProvidePlugin({
+            $: "jquery",
+            jQuery: "jquery",
+            Handsontable: "handsontable"
+        })
+    ],
+    module: {
+        rules: [{
+                test: /\.vue$/,
+                loader: 'vue-loader',
+                options: vueLoaderConfig
+            },
+            {
+                test: /\.js$/,
+                loader: 'babel-loader',
+                include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
+            },
+            {
+                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                    limit: 10000,
+                    name: utils.assetsPath('img/[name].[hash:7].[ext]')
+                }
+            },
+            {
+                test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                    limit: 10000,
+                    name: utils.assetsPath('media/[name].[hash:7].[ext]')
+                }
+            },
+            {
+                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+                loader: 'url-loader',
+                options: {
+                    limit: 10000,
+                    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+                }
+            }
+        ]
+    },
+    node: {
+        // prevent webpack from injecting useless setImmediate polyfill because Vue
+        // source contains it (although only uses it if it's native).
+        setImmediate: false,
+        // prevent webpack from injecting mocks to Node native modules
+        // that does not make sense for the client
+        dgram: 'empty',
+        fs: 'empty',
+        net: 'empty',
+        tls: 'empty',
+        child_process: 'empty'
+    }
+}

+ 89 - 0
build/webpack.dev.conf.js

@@ -0,0 +1,89 @@
+'use strict'
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const path = require('path')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+const devWebpackConfig = merge(baseWebpackConfig, {
+    module: {
+        rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
+    },
+    // cheap-module-eval-source-map is faster for development
+    devtool: config.dev.devtool,
+
+    // these devServer options should be customized in /config/index.js
+    devServer: {
+        clientLogLevel: 'warning',
+        historyApiFallback: {
+            rewrites: [
+                { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
+            ],
+        },
+        hot: true,
+        contentBase: false, // since we use CopyWebpackPlugin.
+        compress: true,
+        host: HOST || config.dev.host,
+        port: PORT || config.dev.port,
+        open: config.dev.autoOpenBrowser,
+        overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,
+        publicPath: config.dev.assetsPublicPath,
+        proxy: config.dev.proxyTable,
+        quiet: true, // necessary for FriendlyErrorsPlugin
+        watchOptions: {
+            poll: config.dev.poll,
+        }
+    },
+    plugins: [
+        new webpack.DefinePlugin({
+            'process.env': require('../config/dev.env')
+        }),
+        new webpack.HotModuleReplacementPlugin(),
+        new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
+        new webpack.NoEmitOnErrorsPlugin(),
+        // https://github.com/ampedandwired/html-webpack-plugin
+        new HtmlWebpackPlugin({
+            filename: 'index.html',
+            template: 'index.html',
+            inject: true
+        }),
+        // copy custom static assets
+        new CopyWebpackPlugin([{
+            from: path.resolve(__dirname, '../static'),
+            to: config.dev.assetsSubDirectory,
+            ignore: ['.*']
+        }])
+    ]
+})
+
+module.exports = new Promise((resolve, reject) => {
+    portfinder.basePort = process.env.PORT || config.dev.port
+    portfinder.getPort((err, port) => {
+        if (err) {
+            reject(err)
+        } else {
+            // publish the new Port, necessary for e2e tests
+            process.env.PORT = port
+                // add port to devServer config
+            devWebpackConfig.devServer.port = port
+
+            // Add FriendlyErrorsPlugin
+            devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
+                compilationSuccessInfo: {
+                    messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
+                },
+                onErrors: config.dev.notifyOnErrors ?
+                    utils.createNotifierCallback() : undefined
+            }))
+
+            resolve(devWebpackConfig)
+        }
+    })
+})

+ 140 - 0
build/webpack.prod.conf.js

@@ -0,0 +1,140 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
+const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+
+const env = require('../config/prod.env')
+const webpackConfig = merge(baseWebpackConfig, {
+    module: {
+        rules: utils.styleLoaders({
+            sourceMap: config.build.productionSourceMap,
+            extract: true,
+            usePostCSS: true
+        })
+    },
+    devtool: config.build.productionSourceMap ? config.build.devtool : false,
+    output: {
+        path: config.build.assetsRoot,
+        filename: utils.assetsPath('js/[name].[chunkhash].js'),
+        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
+    },
+    plugins: [
+        // http://vuejs.github.io/vue-loader/en/workflow/production.html
+        new webpack.DefinePlugin({
+            'process.env': env
+        }),
+        new UglifyJsPlugin({
+            uglifyOptions: {
+                compress: {
+                    warnings: false
+                }
+            },
+            sourceMap: config.build.productionSourceMap,
+            parallel: true
+        }),
+        // extract css into its own file
+        new ExtractTextPlugin({
+            filename: utils.assetsPath('css/[name].[contenthash].css'),
+            // Setting the following option to `false` will not extract CSS from codesplit chunks.
+            // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
+            // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
+            // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
+            allChunks: true,
+        }),
+        // Compress extracted CSS. We are using this plugin so that possible
+        // duplicated CSS from different components can be deduped.
+        new OptimizeCSSPlugin({
+            cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true }
+        }),
+        // generate dist index.html with correct asset hash for caching.
+        // you can customize output by editing /index.html
+        // see https://github.com/ampedandwired/html-webpack-plugin
+        new HtmlWebpackPlugin({
+            filename: config.build.index,
+            template: 'index.html',
+            inject: true,
+            minify: {
+                removeComments: true,
+                collapseWhitespace: true,
+                removeAttributeQuotes: true
+                    // more options:
+                    // https://github.com/kangax/html-minifier#options-quick-reference
+            },
+            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+            chunksSortMode: 'dependency'
+        }),
+        // keep module.id stable when vendor modules does not change
+        new webpack.HashedModuleIdsPlugin(),
+        // enable scope hoisting
+        new webpack.optimize.ModuleConcatenationPlugin(),
+        // split vendor js into its own file
+        new webpack.optimize.CommonsChunkPlugin({
+            name: 'vendor',
+            minChunks(module) {
+                // any required modules inside node_modules are extracted to vendor
+                return (
+                    module.resource &&
+                    /\.js$/.test(module.resource) &&
+                    module.resource.indexOf(
+                        path.join(__dirname, '../node_modules')
+                    ) === 0
+                )
+            }
+        }),
+        // extract webpack runtime and module manifest to its own file in order to
+        // prevent vendor hash from being updated whenever app bundle is updated
+        new webpack.optimize.CommonsChunkPlugin({
+            name: 'manifest',
+            minChunks: Infinity
+        }),
+        // This instance extracts shared chunks from code splitted chunks and bundles them
+        // in a separate chunk, similar to the vendor chunk
+        // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
+        new webpack.optimize.CommonsChunkPlugin({
+            name: 'app',
+            async: 'vendor-async',
+            children: true,
+            minChunks: 3
+        }),
+
+        // copy custom static assets
+        new CopyWebpackPlugin([{
+            from: path.resolve(__dirname, '../static'),
+            to: config.build.assetsSubDirectory,
+            ignore: ['.*']
+        }])
+    ]
+})
+
+if (config.build.productionGzip) {
+    const CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+    webpackConfig.plugins.push(
+        new CompressionWebpackPlugin({
+            asset: '[path].gz[query]',
+            algorithm: 'gzip',
+            test: new RegExp(
+                '\\.(' +
+                config.build.productionGzipExtensions.join('|') +
+                ')$'
+            ),
+            threshold: 10240,
+            minRatio: 0.8
+        })
+    )
+}
+
+if (config.build.bundleAnalyzerReport) {
+    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+    webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig

+ 8 - 0
config/dev.env.js

@@ -0,0 +1,8 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+    NODE_ENV: '"development"',
+    BASE_URL: '"http://172.16.0.181"'
+})

+ 117 - 0
config/index.js

@@ -0,0 +1,117 @@
+'use strict'
+// Template version: 1.3.1
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+const proxyTable = {
+    '/api': {
+        // target: 'http://mbi.sagacloud.cn:8080', //扫楼revit
+        target: 'http://172.16.3.12:8080', //扫楼revit
+        changeOrigin: true,
+        pathRewrite: {
+            '^/api': ''
+        }
+    },
+    '/sass': {
+        target: 'http://192.168.30.96:8080', //sass平台
+        changeOrigin: true,
+        pathRewrite: {
+            '^/sass': ''
+        }
+    },
+    '/img': {
+        target: 'http://192.168.20.225:8080',
+        changeOrigin: true,
+        pathRewrite: {
+            '^/img': ''
+        }
+    },
+    '/physics': {
+        // target: 'http://101.200.32.13:28888',
+        target: 'http://192.168.20.225:8080',
+        changeOrigin: true,
+        pathRewrite: {
+            '^/physics': ''
+        }
+    },
+    '/seeImg': {
+        target: 'http://172.16.0.181:8890',
+        changeOrigin: true,
+        pathRewrite: {
+            '^/seeImg': ''
+        }
+    },
+    '/arithmetic': {
+        target: 'http://101.200.32.13:8001',
+        changeOrigin: true,
+        pathRewrite: {
+            '^/arithmetic': ''
+        }
+    },
+}
+
+module.exports = {
+    dev: {
+
+        // Paths
+        assetsSubDirectory: 'static',
+        assetsPublicPath: '/',
+
+        // Various Dev Server settings
+        host: '0.0.0.0', // can be overwritten by process.env.HOST
+        port: 8091, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+        autoOpenBrowser: true,
+        errorOverlay: true,
+        notifyOnErrors: true,
+        poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+        proxyTable: proxyTable,
+
+        /**
+         * Source Maps
+         */
+        productionGzip: true,
+        productionGzipExtensions: ['js', 'css'],
+        // https://webpack.js.org/configuration/devtool/#development
+        devtool: 'cheap-module-eval-source-map',
+
+        // If you have problems debugging vue-files in devtools,
+        // set this to false - it *may* help
+        // https://vue-loader.vuejs.org/en/options.html#cachebusting
+        cacheBusting: true,
+
+        cssSourceMap: true
+    },
+
+    build: {
+        // Template for index.html
+        index: path.resolve(__dirname, '../dist/index.html'),
+
+        // Paths
+        assetsRoot: path.resolve(__dirname, '../dist'),
+        assetsSubDirectory: 'static',
+        assetsPublicPath: '/',
+
+        /**
+         * Source Maps
+         */
+
+        productionSourceMap: true,
+        // https://webpack.js.org/configuration/devtool/#production
+        devtool: '#source-map',
+
+        // Gzip off by default as many popular static hosts such as
+        // Surge or Netlify already gzip all static assets for you.
+        // Before setting to `true`, make sure to:
+        // npm install --save-dev compression-webpack-plugin
+        productionGzip: true,
+        productionGzipExtensions: ['js', 'css'],
+
+        // Run the build command with an extra argument to
+        // View the bundle analyzer report after build finishes:
+        // `npm run build --report`
+        // Set to `true` or `false` to always turn it on or off
+        bundleAnalyzerReport: process.env.npm_config_report
+    }
+}

+ 8 - 0
config/prod.env.js

@@ -0,0 +1,8 @@
+'use strict'
+module.exports = {
+    NODE_ENV: '"production"',
+    BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
+    UPLOAD_URL: '"http://prod.dp.sagacloud.cn:28888"', //上传地址
+    // BASE_URL: '"http://172.16.0.181"', //测试环境iframe的地址/
+    // UPLOAD_URL: '"http://192.168.20.225:8080"', //上传地址
+}

BIN
favicon.ico


+ 313 - 0
handsontable-chosen-editor.js

@@ -0,0 +1,313 @@
+/// chosen plugin
+(function(Handsontable) {
+        "use strict";
+
+        var ChosenEditor = Handsontable.editors.TextEditor.prototype.extend();
+
+        ChosenEditor.prototype.prepare = function(row, col, prop, td, originalValue, cellProperties) {
+
+            Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);
+
+            this.options = {};
+
+            if (this.cellProperties.chosenOptions) {
+                this.options = $.extend(this.options, cellProperties.chosenOptions);
+            }
+
+            cellProperties.chosenOptions = $.extend({}, cellProperties.chosenOptions);
+        };
+
+        ChosenEditor.prototype.createElements = function() {
+            this.$body = $(document.body);
+
+            this.TEXTAREA = document.createElement('select');
+            //this.TEXTAREA.setAttribute('type', 'text');
+            this.$textarea = $(this.TEXTAREA);
+
+            Handsontable.dom.addClass(this.TEXTAREA, 'handsontableInput');
+
+            this.textareaStyle = this.TEXTAREA.style;
+            this.textareaStyle.width = 0;
+            this.textareaStyle.height = 0;
+
+            this.TEXTAREA_PARENT = document.createElement('DIV');
+            Handsontable.dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder');
+
+            this.textareaParentStyle = this.TEXTAREA_PARENT.style;
+            this.textareaParentStyle.top = 0;
+            this.textareaParentStyle.left = 0;
+            this.textareaParentStyle.display = 'none';
+            this.textareaParentStyle.width = "200px";
+
+            this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
+
+            this.instance.rootElement.appendChild(this.TEXTAREA_PARENT);
+
+            var that = this;
+            this.instance._registerTimeout(setTimeout(function() {
+                that.refreshDimensions();
+            }, 0));
+        };
+
+        var onChosenChanged = function() {
+            var options = this.cellProperties.chosenOptions;
+
+            if (!options.multiple) {
+                this.close();
+                this.finishEditing();
+            }
+        };
+        var onChosenClosed = function() {
+            var options = this.cellProperties.chosenOptions;
+
+            if (!options.multiple) {
+                this.close();
+                this.finishEditing();
+            } else {}
+        };
+        var onBeforeKeyDown = function(event) {
+            var instance = this;
+            var that = instance.getActiveEditor();
+
+            var keyCodes = Handsontable.helper.KEY_CODES;
+            var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
+
+            //Process only events that have been fired in the editor
+            if (event.target.tagName !== "INPUT") {
+                return;
+            }
+            if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
+                //when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
+                event.stopImmediatePropagation();
+                return;
+            }
+
+            var target = event.target;
+
+            switch (event.keyCode) {
+                case keyCodes.ARROW_RIGHT:
+                    if (Handsontable.dom.getCaretPosition(target) !== target.value.length) {
+                        event.stopImmediatePropagation();
+                    } else {
+                        that.$textarea.trigger("chosen:close");
+                    }
+                    break;
+
+                case keyCodes.ARROW_LEFT:
+                    if (Handsontable.dom.getCaretPosition(target) !== 0) {
+                        event.stopImmediatePropagation();
+                    } else {
+                        that.$textarea.trigger("chosen:close");
+                    }
+                    break;
+
+                case keyCodes.ENTER:
+                    if (that.cellProperties.chosenOptions.multiple) {
+                        event.stopImmediatePropagation();
+                        event.preventDefault();
+                        event.stopPropagation();
+                    }
+
+                    break;
+
+                case keyCodes.A:
+                case keyCodes.X:
+                case keyCodes.C:
+                case keyCodes.V:
+                    if (ctrlDown) {
+                        event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
+                    }
+                    break;
+
+                case keyCodes.BACKSPACE:
+                    var txt = $(that.TEXTAREA_PARENT).find("input").val();
+                    $(that.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
+
+                    event.stopImmediatePropagation();
+                    break;
+                case keyCodes.DELETE:
+                case keyCodes.HOME:
+                case keyCodes.END:
+                    event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)
+                    break;
+            }
+
+        };
+
+        ChosenEditor.prototype.open = function(keyboardEvent) {
+            this.refreshDimensions();
+            this.textareaParentStyle.display = 'block';
+            this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
+
+            this.$textarea.css({
+                height: $(this.TD).height() + 4,
+                'min-width': $(this.TD).outerWidth() - 4
+            });
+
+            //display the list
+            this.$textarea.hide();
+
+            //make sure that list positions matches cell position
+            //this.$textarea.offset($(this.TD).offset());
+
+            var options = $.extend({}, this.options, {
+                width: "100%",
+                search_contains: true
+            });
+
+            if (options.multiple) {
+                this.$textarea.attr("multiple", true);
+            } else {
+                this.$textarea.attr("multiple", false);
+            }
+
+            this.$textarea.empty();
+            this.$textarea.append("<option value=''></option>");
+            var el = null;
+            var originalValue = (this.originalValue + "").split(",");
+            if (options.data && options.data.length) {
+                for (var i = 0; i < options.data.length; i++) {
+                    this.$textarea.append(el);
+                    if (options[i].content && options[i].content.length) {
+                        for (let k = 0; k < options[i].content.length; k++) {
+                            if (options[i].content[k] && options[i].content[k].length) {
+                                for (let j = 0; j < options[i].content[k].length; j++) {
+                                    el = $("<option />");
+                                    el.attr("value", options[i].content[k].content[j].code);
+                                    el.html(options[i].content[k].content[j].name);
+
+                                    if (originalValue.indexOf(options[i].content[k].content[j].code + "") > -1) {
+                                        el.attr("selected", true);
+                                    }
+                                }
+                            } else {
+                                el = $("<option />");
+                                el.attr("value", options[i].content[k].code);
+                                el.html(options[i].content[k].name);
+
+                                if (originalValue.indexOf(options[i].content[k].code + "") > -1) {
+                                    el.attr("selected", true);
+                                }
+                            }
+                        }
+                    } else {
+                        el = $("<option />");
+                        el.attr("value", options[i].content[k].code);
+                        el.html(options[i].content[k].name);
+
+                        if (originalValue.indexOf(options[i].content[k].code + "") > -1) {
+                            el.attr("selected", true);
+                        }
+                    }
+                }
+            }
+        }
+
+        if ($(this.TEXTAREA_PARENT).find(".chosen-container").length) {
+            this.$textarea.chosen("destroy");
+        }
+
+        this.$textarea.chosen(options);
+
+        var self = this;
+        setTimeout(function() {
+
+            self.$textarea.on('change', onChosenChanged.bind(self));
+            self.$textarea.on('chosen:hiding_dropdown', onChosenClosed.bind(self));
+
+            self.$textarea.trigger("chosen:open");
+
+            $(self.TEXTAREA_PARENT).find("input").on("keydown", function(e) {
+                if (e.keyCode === Handsontable.helper.KEY_CODES.ENTER /*|| e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE*/ ) {
+                    if ($(this).val()) {
+                        e.preventDefault();
+                        e.stopPropagation();
+                    } else {
+                        e.preventDefault();
+                        e.stopPropagation();
+
+                        self.close();
+                        self.finishEditing();
+                    }
+
+                }
+
+                if (e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE) {
+                    var txt = $(self.TEXTAREA_PARENT).find("input").val();
+
+                    $(self.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
+
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+                if (e.keyCode === Handsontable.helper.KEY_CODES.ARROW_DOWN || e.keyCode === Handsontable.helper.KEY_CODES.ARROW_UP) {
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+            });
+
+            setTimeout(function() {
+                self.$textarea.trigger("chosen:activate").focus();
+
+                if (keyboardEvent && keyboardEvent.keyCode && keyboardEvent.keyCode != 113) {
+                    var key = keyboardEvent.keyCode;
+                    var keyText = (String.fromCharCode((96 <= key && key <= 105) ? key - 48 : key)).toLowerCase();
+
+                    $(self.TEXTAREA_PARENT).find("input").val(keyText).trigger("keyup.chosen");
+                    self.$textarea.trigger("chosen:activate");
+                }
+            }, 1);
+        }, 1);
+
+    };
+
+    ChosenEditor.prototype.init = function() {
+        Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.close = function() {
+        this.instance.listen();
+        this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
+        this.$textarea.off();
+        this.$textarea.hide();
+        Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.getValue = function() {
+        if (!this.$textarea.val()) {
+            return "";
+        }
+        if (typeof this.$textarea.val() === "object") {
+            return this.$textarea.val().join(",");
+        }
+        return this.$textarea.val();
+    };
+
+
+    ChosenEditor.prototype.focus = function() {
+        this.instance.listen();
+
+        // DO NOT CALL THE BASE TEXTEDITOR FOCUS METHOD HERE, IT CAN MAKE THIS EDITOR BEHAVE POORLY AND HAS NO PURPOSE WITHIN THE CONTEXT OF THIS EDITOR
+        //Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.beginEditing = function(initialValue) {
+        var onBeginEditing = this.instance.getSettings().onBeginEditing;
+        if (onBeginEditing && onBeginEditing() === false) {
+            return;
+        }
+
+        Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);
+
+    };
+
+    ChosenEditor.prototype.finishEditing = function(isCancelled, ctrlDown) {
+        this.instance.listen();
+        return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
+    };
+
+    Handsontable.editors.ChosenEditor = ChosenEditor; Handsontable.editors.registerEditor('chosen', ChosenEditor);
+
+})(Handsontable);

+ 21 - 0
index.html

@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
+    <meta http-equiv="Expires" content="-1000" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+    <meta name="renderer" content="webkit">
+    <link rel="stylesheet" href="//at.alicdn.com/t/font_646072_j1rtd99vj8.css">
+    <title>扫楼工具</title>
+</head>
+
+<body>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+</body>
+
+</html>

File diff suppressed because it is too large
+ 10553 - 0
package-lock.json


+ 79 - 0
package.json

@@ -0,0 +1,79 @@
+{
+    "name": "ibms",
+    "version": "1.0.0",
+    "description": "A Vue.js project",
+    "author": "chuwu",
+    "private": true,
+    "scripts": {
+        "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+        "start": "npm run dev",
+        "build": "node build/build.js"
+    },
+    "dependencies": {
+        "@handsontable/vue": "^2.0.0-beta1",
+        "axios": "^0.18.0",
+        "babel-polyfill": "^6.26.0",
+        "base64-js": "^1.3.0",
+        "element-ui": "^2.3.4",
+        "handsontable": "^2.0.0",
+        "handsontable-pro": "^3.0.0",
+        "jquery": "^3.3.1",
+        "pako": "^1.0.6",
+        "photo-sphere-viewer": "^3.3.3",
+        "qrcanvas": "^3.0.1",
+        "vue": "^2.5.2",
+        "vue-axios": "^2.1.1",
+        "vue-router": "^3.0.1"
+    },
+    "devDependencies": {
+        "autoprefixer": "^7.1.2",
+        "babel-core": "^6.22.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.3",
+        "babel-loader": "^7.1.1",
+        "babel-plugin-syntax-jsx": "^6.18.0",
+        "babel-plugin-transform-runtime": "^6.22.0",
+        "babel-plugin-transform-vue-jsx": "^3.5.0",
+        "babel-preset-env": "^1.3.2",
+        "babel-preset-stage-2": "^6.22.0",
+        "chalk": "^2.0.1",
+        "compression-webpack-plugin": "^1.1.0",
+        "copy-webpack-plugin": "^4.0.1",
+        "css-loader": "^0.28.0",
+        "extract-text-webpack-plugin": "^3.0.0",
+        "file-loader": "^1.1.4",
+        "friendly-errors-webpack-plugin": "^1.6.1",
+        "html-webpack-plugin": "^2.30.1",
+        "less": "^3.0.4",
+        "less-loader": "^4.1.0",
+        "node-notifier": "^5.1.2",
+        "optimize-css-assets-webpack-plugin": "^3.2.0",
+        "ora": "^1.2.0",
+        "portfinder": "^1.0.13",
+        "postcss-import": "^11.0.0",
+        "postcss-loader": "^2.0.8",
+        "postcss-url": "^7.2.1",
+        "rimraf": "^2.6.0",
+        "semver": "^5.3.0",
+        "shelljs": "^0.7.6",
+        "swiper": "^4.0.0",
+        "uglifyjs-webpack-plugin": "^1.1.1",
+        "url-loader": "^0.5.8",
+        "vue-lazyload": "^1.2.3",
+        "vue-loader": "^13.3.0",
+        "vue-style-loader": "^3.0.1",
+        "vue-template-compiler": "^2.5.2",
+        "webpack": "^3.6.0",
+        "webpack-bundle-analyzer": "^2.9.0",
+        "webpack-dev-server": "^2.9.1",
+        "webpack-merge": "^4.1.0"
+    },
+    "engines": {
+        "node": ">= 6.0.0",
+        "npm": ">= 3.0.0"
+    },
+    "browserslist": [
+        "> 1%",
+        "last 2 versions",
+        "not ie <= 8"
+    ]
+}

+ 7 - 0
photoView/README.md

@@ -0,0 +1,7 @@
+#   该页面为照片、视频、全景图查看页
+
+##  照片: type = image && name != '全景照片',key值传入照片key
+
+##  全景图: type=image && name == '全景照片',key值传入图片key值
+
+##  视频: type=video,key值传入视频key值 //视频暂无(后台)

+ 77 - 0
photoView/css/reset.css

@@ -0,0 +1,77 @@
+html,
+body,
+div,
+span,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+abbr,
+address,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+samp,
+small,
+strong,
+sub,
+sup,
+var,
+b,
+i,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    outline: 0;
+    font-size: 100%;
+    vertical-align: baseline;
+    background: transparent;
+}

File diff suppressed because it is too large
+ 9 - 0
photoView/css/viewer.min.css


+ 324 - 0
photoView/js/CSS3DStereoRenderer.js

@@ -0,0 +1,324 @@
+/**
+ * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
+ * @author mrdoob / http://mrdoob.com/
+ * @author yomotsu / https://yomotsu.net/
+ */
+
+THREE.CSS3DObject = function(element) {
+
+    THREE.Object3D.call(this);
+
+    this.element = element;
+    this.element.style.position = 'absolute';
+
+    this.addEventListener('removed', function() {
+
+        if (this.element.parentNode !== null) {
+
+            this.element.parentNode.removeChild(this.element);
+
+        }
+
+    });
+
+};
+
+THREE.CSS3DObject.prototype = Object.create(THREE.Object3D.prototype);
+THREE.CSS3DObject.prototype.constructor = THREE.CSS3DObject;
+
+THREE.CSS3DSprite = function(element) {
+
+    THREE.CSS3DObject.call(this, element);
+
+};
+
+THREE.CSS3DSprite.prototype = Object.create(THREE.CSS3DObject.prototype);
+THREE.CSS3DSprite.prototype.constructor = THREE.CSS3DSprite;
+
+//
+
+THREE.CSS3DRenderer = function() {
+
+    console.log('THREE.CSS3DRenderer', THREE.REVISION);
+
+    var _width, _height;
+    var _widthHalf, _heightHalf;
+
+    var matrix = new THREE.Matrix4();
+
+    var cache = {
+        camera: { fov: 0, style: '' },
+        objects: new WeakMap()
+    };
+
+    var domElement = document.createElement('div');
+    domElement.style.overflow = 'hidden';
+
+    this.domElement = domElement;
+
+    var cameraElement = document.createElement('div');
+
+    cameraElement.style.WebkitTransformStyle = 'preserve-3d';
+    cameraElement.style.transformStyle = 'preserve-3d';
+
+    domElement.appendChild(cameraElement);
+
+    var isIE = /Trident/i.test(navigator.userAgent);
+
+    this.getSize = function() {
+
+        return {
+            width: _width,
+            height: _height
+        };
+
+    };
+
+    this.setSize = function(width, height) {
+
+        _width = width;
+        _height = height;
+        _widthHalf = _width / 2;
+        _heightHalf = _height / 2;
+
+        domElement.style.width = width + 'px';
+        domElement.style.height = height + 'px';
+
+        cameraElement.style.width = width + 'px';
+        cameraElement.style.height = height + 'px';
+
+    };
+
+    function epsilon(value) {
+
+        return Math.abs(value) < 1e-10 ? 0 : value;
+
+    }
+
+    function getCameraCSSMatrix(matrix) {
+
+        var elements = matrix.elements;
+
+        return 'matrix3d(' +
+            epsilon(elements[0]) + ',' +
+            epsilon(-elements[1]) + ',' +
+            epsilon(elements[2]) + ',' +
+            epsilon(elements[3]) + ',' +
+            epsilon(elements[4]) + ',' +
+            epsilon(-elements[5]) + ',' +
+            epsilon(elements[6]) + ',' +
+            epsilon(elements[7]) + ',' +
+            epsilon(elements[8]) + ',' +
+            epsilon(-elements[9]) + ',' +
+            epsilon(elements[10]) + ',' +
+            epsilon(elements[11]) + ',' +
+            epsilon(elements[12]) + ',' +
+            epsilon(-elements[13]) + ',' +
+            epsilon(elements[14]) + ',' +
+            epsilon(elements[15]) +
+            ')';
+
+    }
+
+    function getObjectCSSMatrix(matrix, cameraCSSMatrix) {
+
+        var elements = matrix.elements;
+        var matrix3d = 'matrix3d(' +
+            epsilon(elements[0]) + ',' +
+            epsilon(elements[1]) + ',' +
+            epsilon(elements[2]) + ',' +
+            epsilon(elements[3]) + ',' +
+            epsilon(-elements[4]) + ',' +
+            epsilon(-elements[5]) + ',' +
+            epsilon(-elements[6]) + ',' +
+            epsilon(-elements[7]) + ',' +
+            epsilon(elements[8]) + ',' +
+            epsilon(elements[9]) + ',' +
+            epsilon(elements[10]) + ',' +
+            epsilon(elements[11]) + ',' +
+            epsilon(elements[12]) + ',' +
+            epsilon(elements[13]) + ',' +
+            epsilon(elements[14]) + ',' +
+            epsilon(elements[15]) +
+            ')';
+
+        if (isIE) {
+
+            return 'translate(-50%,-50%)' +
+                'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)' +
+                cameraCSSMatrix +
+                matrix3d;
+
+        }
+
+        return 'translate(-50%,-50%)' + matrix3d;
+
+    }
+
+    function renderObject(object, camera, cameraCSSMatrix) {
+
+        if (object instanceof THREE.CSS3DObject) {
+
+            var style;
+
+            if (object instanceof THREE.CSS3DSprite) {
+
+                // http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/
+
+                matrix.copy(camera.matrixWorldInverse);
+                matrix.transpose();
+                matrix.copyPosition(object.matrixWorld);
+                matrix.scale(object.scale);
+
+                matrix.elements[3] = 0;
+                matrix.elements[7] = 0;
+                matrix.elements[11] = 0;
+                matrix.elements[15] = 1;
+
+                style = getObjectCSSMatrix(matrix, cameraCSSMatrix);
+
+            } else {
+
+                style = getObjectCSSMatrix(object.matrixWorld, cameraCSSMatrix);
+
+            }
+
+            var element = object.element;
+            var cachedStyle = cache.objects.get(object);
+
+            if (cachedStyle === undefined || cachedStyle !== style) {
+
+                element.style.WebkitTransform = style;
+                element.style.transform = style;
+
+                var objectData = { style: style };
+
+                if (isIE) {
+
+                    objectData.distanceToCameraSquared = getDistanceToSquared(camera, object);
+
+                }
+
+                cache.objects.set(object, objectData);
+
+            }
+
+            if (element.parentNode !== cameraElement) {
+
+                cameraElement.appendChild(element);
+
+            }
+
+        }
+
+        for (var i = 0, l = object.children.length; i < l; i++) {
+
+            renderObject(object.children[i], camera, cameraCSSMatrix);
+
+        }
+
+    }
+
+    var getDistanceToSquared = function() {
+
+        var a = new THREE.Vector3();
+        var b = new THREE.Vector3();
+
+        return function(object1, object2) {
+
+            a.setFromMatrixPosition(object1.matrixWorld);
+            b.setFromMatrixPosition(object2.matrixWorld);
+
+            return a.distanceToSquared(b);
+
+        };
+
+    }();
+
+    function filterAndFlatten(scene) {
+
+        var result = [];
+
+        scene.traverse(function(object) {
+
+            if (object instanceof THREE.CSS3DObject) result.push(object);
+
+        });
+
+        return result;
+
+    }
+
+    function zOrder(scene) {
+
+        var sorted = filterAndFlatten(scene).sort(function(a, b) {
+
+            var distanceA = cache.objects.get(a).distanceToCameraSquared;
+            var distanceB = cache.objects.get(b).distanceToCameraSquared;
+
+            return distanceA - distanceB;
+
+        });
+
+        var zMax = sorted.length;
+
+        for (var i = 0, l = sorted.length; i < l; i++) {
+
+            sorted[i].element.style.zIndex = zMax - i;
+
+        }
+
+    }
+
+    this.render = function(scene, camera) {
+
+        var fov = camera.projectionMatrix.elements[5] * _heightHalf;
+
+        if (cache.camera.fov !== fov) {
+
+            if (camera.isPerspectiveCamera) {
+
+                domElement.style.WebkitPerspective = fov + 'px';
+                domElement.style.perspective = fov + 'px';
+
+            }
+
+            cache.camera.fov = fov;
+
+        }
+
+        scene.updateMatrixWorld();
+
+        if (camera.parent === null) camera.updateMatrixWorld();
+
+        var cameraCSSMatrix = camera.isOrthographicCamera ?
+            'scale(' + fov + ')' + getCameraCSSMatrix(camera.matrixWorldInverse) :
+            'translateZ(' + fov + 'px)' + getCameraCSSMatrix(camera.matrixWorldInverse);
+
+        var style = cameraCSSMatrix +
+            'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)';
+
+        if (cache.camera.style !== style && !isIE) {
+
+            cameraElement.style.WebkitTransform = style;
+            cameraElement.style.transform = style;
+
+            cache.camera.style = style;
+
+        }
+
+        renderObject(scene, camera, cameraCSSMatrix);
+
+        if (isIE) {
+
+            // IE10 and 11 does not support 'preserve-3d'.
+            // Thus, z-order in 3D will not work.
+            // We have to calc z-order manually and set CSS z-index for IE.
+            // FYI: z-index can't handle object intersection
+            zOrder(scene);
+
+        }
+
+    };
+
+};

File diff suppressed because it is too large
+ 6855 - 0
photoView/js/photo-sphere-viewer.js


File diff suppressed because it is too large
+ 2 - 0
photoView/js/photo-sphere-viewer.min.js


File diff suppressed because it is too large
+ 46814 - 0
photoView/js/three.js


File diff suppressed because it is too large
+ 2443 - 0
photoView/js/three.min.js


File diff suppressed because it is too large
+ 10 - 0
photoView/js/viewer.min.js


+ 250 - 0
photoView/photo-View.html

@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="utf-8" />
+    <title>Photo Sphere Viewer</title>
+    <meta name="viewport" content="initial-scale=1.0" />
+    <link rel="stylesheet" href="./css/viewer.min.css">
+    <link rel="stylesheet" href="./css/reset.css">
+    <script src="./js/three.min.js"></script>
+    <script src="./js/viewer.min.js"></script>
+    <script src="./js/photo-sphere-viewer.min.js"></script>
+    <style>
+        html,
+        body {
+            margin: 0;
+            width: 100%;
+            height: 100%;
+            overflow: hidden;
+        }
+        
+        #container {
+            width: 100%;
+            height: 100%;
+        }
+        
+        #container video {
+            width: 100%;
+            height: 100%;
+        }
+        
+        #container .div {
+            height: 100%;
+            width: 100%;
+        }
+        
+        #container #images {
+            height: 100%;
+            width: 100%;
+            background-color: rgba(0, 0, 0, .5)
+        }
+        
+        #images img {
+            width: 200px;
+            height: 200px;
+            text-align: center;
+            margin-left: auto;
+            display: block;
+            margin-right: auto;
+            margin-top: 300px;
+        }
+        
+        .spinner {
+            margin: 100px auto;
+            width: 50px;
+            height: 60px;
+            text-align: center;
+            font-size: 10px;
+        }
+        
+        .spinner>div {
+            background-color: #67CF22;
+            height: 100%;
+            width: 6px;
+            display: inline-block;
+            -webkit-animation: stretchdelay 1.2s infinite ease-in-out;
+            animation: stretchdelay 1.2s infinite ease-in-out;
+        }
+        
+        .spinner .rect2 {
+            -webkit-animation-delay: -1.1s;
+            animation-delay: -1.1s;
+        }
+        
+        .spinner .rect3 {
+            -webkit-animation-delay: -1.0s;
+            animation-delay: -1.0s;
+        }
+        
+        .spinner .rect4 {
+            -webkit-animation-delay: -0.9s;
+            animation-delay: -0.9s;
+        }
+        
+        .spinner .rect5 {
+            -webkit-animation-delay: -0.8s;
+            animation-delay: -0.8s;
+        }
+        
+        @-webkit-keyframes stretchdelay {
+            0%,
+            40%,
+            100% {
+                -webkit-transform: scaleY(0.4)
+            }
+            20% {
+                -webkit-transform: scaleY(1.0)
+            }
+        }
+        
+        @keyframes stretchdelay {
+            0%,
+            40%,
+            100% {
+                transform: scaleY(0.4);
+                -webkit-transform: scaleY(0.4);
+            }
+            20% {
+                transform: scaleY(1.0);
+                -webkit-transform: scaleY(1.0);
+            }
+        }
+        
+        .viewer-canvas,
+        html {
+            background-color: rgba(0, 0, 0, .5)
+        }
+        
+        #loading {
+            position: absolute;
+            top: 30%;
+            left: 45%;
+            z-index: 10;
+        }
+        
+        #container>div {
+            z-index: 40;
+        }
+    </style>
+</head>
+
+<body>
+    <div id="container">
+    </div>
+    <div id="loading"></div>
+    <script>
+        var falg = false,
+            dataView
+
+        function receiveMessageFromIndex(event) {
+            console.log('receiveMessageFromIndex', event.data)
+            dataView = event.data
+            falg = true
+            this.postView()
+        }
+
+        //监听message事件
+        window.addEventListener("message", receiveMessageFromIndex, false);
+
+        if (!falg) {
+            var div = document.getElementById('container'), //获取承接容器
+                key = getQueryString('key'), //获取传来的图片或视频key值
+                type = getQueryString('type'), //获取图片的类型 image正常图片 image/name全景图 video视频
+                name = getQueryString('name'); //获得到的名字
+            div.innerHTML = '';
+            if (!!type) {
+                if (type == 'panorama') {
+                    panorama()
+                } else if (type == 'video') {
+                    video()
+                } else if (type.indexOf('image') != '-1') {
+                    preview()
+                }
+            }
+        } else {
+            this.postView()
+        }
+
+        function postView() {
+            var dom = ``
+            for (var j = 0; j < dataView.length; j++) {
+                dom += `<li><img src="img/image-service/common/image_get?systemId=dataPlatform&key=` + dataView[j].key + `" alt=` + dataView[j].name + `></li>`
+            }
+            var text = `
+            <div class="div">
+            <ul id="images">
+                ` + dom + `
+            </ul>
+            </div>`
+            div.innerHTML = text
+            console.log(text, "text")
+            var viewer = new Viewer(document.getElementById('images'), {
+                backdrop: false
+            });
+            viewer.show()
+        }
+
+
+        function preview() {
+            var con = `
+            <div class="div">
+            <ul id="images">
+                <li><img src="img/image-service/common/image_get?systemId=dataPlatform&key=` + key + `" alt="` + name + `"></li>
+            </ul>
+            </div>`
+            div.innerHTML = con
+
+            // View a list of images
+            if (!!key) {
+                var viewer = new Viewer(document.getElementById('images'), {
+                    backdrop: false
+                });
+                viewer.show()
+            }
+        }
+
+        function video() {
+            var videoCainter = document.createElement('video');
+            videoCainter.setAttribute('src', 'img/ image-service/common/fileget?systemId=dataPlatform&key=' + key);
+            videoCainter.setAttribute('controls', 'controls');
+            videoCainter.innerText = '您的浏览器不支持 video 标签。'
+            div.appendChild(videoCainter)
+        }
+
+        //获取url传参
+        function getQueryString(name) {
+            var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
+            var r = window.location.search.substr(1).match(reg);
+            if (r != null) {
+                return unescape(r[2]);
+            }
+            return null;
+        }
+
+        function panorama() {
+            //加上width避免图片过大导致请求时间长而认为请求失败
+            var loading = `<div class="spinner">
+  <div class="rect1"></div>
+  <div class="rect2"></div>
+  <div class="rect3"></div>
+  <div class="rect4"></div>
+  <div class="rect5"></div>
+</div>`;
+            document.getElementById('loading').innerHTML = loading
+            var url = 'img/image-service/common/image_get?systemId=dataPlatform&key=' + key + '&width=5000';
+            var PSV = new PhotoSphereViewer({
+                panorama: url,
+                // panorama: './image/IMG_0518.JPG',
+                container: div,
+                time_anim: 3000,
+                navbar: true,
+                navbar_style: {
+                    backgroundColor: 'rgba(58, 67, 77, 0.7)'
+                },
+            });
+        }
+    </script>
+</body>
+
+</html>

+ 42 - 0
photoView/test.html

@@ -0,0 +1,42 @@
+<HTML>
+
+<HEAD>
+    <TITLE>WMI Scripting HTML</TITLE>
+    <META http-equiv=Content-Type content="text/html; charset=gb2312">
+    <script>
+        function validBrowser() {
+            var u_agent = navigator.userAgent;
+            var browser_name = 'Failed to identify the browser';
+            if (u_agent.indexOf('Firefox') > -1) {
+                browser_name = 'Firefox';
+            } else if (u_agent.indexOf('Chrome') > -1) {
+                browser_name = 'Chrome';
+            } else if (u_agent.indexOf('Trident') > -1 && u_agent.indexOf('rv:11') > -1) {
+                browser_name = 'IE11';
+            } else if (u_agent.indexOf('MSIE') > -1 && u_agent.indexOf('Trident') > -1) {
+                browser_name = 'IE(8-10)';
+            } else if (u_agent.indexOf('MSIE') > -1) {
+                browser_name = 'IE(6-7)';
+            } else if (u_agent.indexOf('Opera') > -1) {
+                browser_name = 'Opera';
+            } else {
+                browser_name += ',info:' + u_agent;
+            }
+            document.write('browser_name:' + browser_name + '<br>');
+            document.write('u_agent:' + u_agent + '<br>');
+        }
+        var a = 1;
+        if (!(b in window)) {
+            var b = 2;
+            a += 1
+        } else {
+            a += 2
+        }
+        console.log(a)
+        console.log(b)
+    </script>
+
+    <body onload="validBrowser()">
+    </body>
+
+</html>

+ 18 - 0
src/App.vue

@@ -0,0 +1,18 @@
+<template>
+  <div id="app">
+    <router-view/>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'App'
+}
+</script>
+
+<style>
+.block{
+  display: block;
+  text-align: center;
+}
+</style>

+ 3 - 0
src/api/config.js

@@ -0,0 +1,3 @@
+export const api = 'api';
+export const sass = 'sass';
+export const physics = 'physics';

+ 30 - 0
src/api/fetch.js

@@ -0,0 +1,30 @@
+import Vue from 'vue'
+import axios from 'axios'
+import vueAxios from 'vue-axios'
+
+Vue.use(vueAxios, axios)
+    //创建实例
+
+const service = axios.create({
+    timeout: 3000000, //请求时间超出
+    withCredentials: true, //是否跨站点访问控制请求
+})
+
+//request拦截
+service.interceptors.request.use(config => {
+    return config
+}, error => {
+    console.log(error)
+    Promise.reject(error)
+})
+
+//response拦截器
+service.interceptors.response.use(
+    response => response,
+    error => {
+        console.log('err' + error)
+        return Promise.reject(error)
+    }
+)
+
+export default service

+ 50 - 0
src/api/httpUtil.js

@@ -0,0 +1,50 @@
+import { Message } from 'element-ui';
+import fetch from './fetch'
+
+function successResponse(vm, response, success, failed) {
+    let resp = response.data;
+    let result = resp.result ? resp.result : resp.Result;
+
+    if (result === 'success') {
+        if (success) {
+            success(resp);
+        }
+    } else {
+        let msg = resp.message ? resp.message : resp.ResultMsg || resp.resultMsg;
+        Message.error({ message: msg });
+        if (failed) {
+            failed(resp);
+        }
+    }
+
+}
+
+function errorResponse(vm, response, err) {
+    let json = JSON.stringify(response)
+    json = JSON.parse(json)
+    console.error(response)
+    if (err) {
+        Message.error({ message: '接口:' + json.config.url + '请求错误' })
+    } else {
+        Message.error({ message: '请求错误' });
+    }
+}
+
+export default {
+    getJson: function(url, data, success, failed, err) {
+        let vm = this;
+        fetch({ url: url, method: 'get', params: data }).then((response) => {
+            successResponse(vm, response, success, failed)
+        }).catch(error => {
+            errorResponse(vm, error, err);
+        });
+    },
+    postJson: function(url, data, success, failed, err) {
+        let vm = this;
+        fetch({ url: url, method: 'post', data: data }).then((response) => {
+            successResponse(vm, response, success, failed)
+        }).catch(error => {
+            errorResponse(vm, error, err);
+        });
+    }
+}

+ 760 - 0
src/api/request.js

@@ -0,0 +1,760 @@
+import fetch from './fetch'
+import { api, physics } from './config'
+import http from './httpUtil'
+let dataForm = '/data-platform-3'
+let arithmetic = '/arithmetic'
+    // let dataForm = ''
+
+var Comming = 'revit'
+var ProjId = 'Pj1101080001'
+var UserId = '25518428919955458'
+    //获取打印标签模板test
+export function getTest() {
+    return fetch({ method: 'GET', url: `${api}/ScanBuilding/service/template/note_template` })
+}
+
+//查看扫楼日志接口
+
+export function getBuildLog(
+    param
+) {
+    let data = {
+        "BeginTime": param.startTime,
+        "Comming": Comming,
+        "EndTime": param.endTime,
+        "Filter": param.filter,
+        "PageNum": param.pageNum,
+        "PageSize": param.pageSize,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/user_log/query`, data })
+}
+
+//下载扫楼日志接口
+
+export function dowmloadLog(
+    param
+) {
+    let data = {
+        "BeginTime": param.startTime,
+        "Comming": Comming,
+        "EndTime": param.endTime,
+        "Filter": param.filter,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/user_log/export`, data })
+}
+
+//获取扫楼用户表格
+export function getUser(
+    param
+) {
+    let data = {
+        "Comming": Comming,
+        "Filter": param.filter,
+        "PageNum": param.pageNum,
+        "PageSize": param.pageSize,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/user/query`, data })
+}
+
+//修改扫楼用户
+export function loadUser(
+    param
+) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "UserList": param.UserList
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/user/update`, data })
+}
+
+//删除扫楼用户
+export function delUser(
+    param
+) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "UserList": param.UserList
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/user/delete`, data })
+}
+
+//添加扫楼用户
+export function addUser(
+    param
+) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "User": param.User
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/user/create`, data })
+}
+
+//根据项目ID获得建筑列表
+export function getBuildSelect(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/building/query`, data })
+}
+
+//根据建筑ID获取楼层系信息
+export function getFloor(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "BuildId": param.BuildId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/building/floor`, data })
+}
+
+//获取异常资产接口
+export function getErrAssets(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "BuildId": param.BuildId,
+        "PageNum": param.PageNum,
+        "PageSize": param.PageSize,
+        "Type": param.Type,
+        "CodeType": param.CodeType
+    }
+    if (param.BuildId == 'all') {
+        delete data.BuildId
+    }
+
+    if (!param.CodeType) {
+        delete data.CodeType
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/exception`, data })
+}
+
+//删除资产接口
+export function delErrAssets(param, paramList) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "FmList": paramList
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/delete`, data })
+}
+
+//根据选择的建筑楼层时间查询点位标签
+export function getPT(param) {
+    let data = {
+        "Comming": Comming,
+        "BeginTime": param.BeginTime,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "BeginTime": param.BeginTime,
+        "EndTime": param.EndTime,
+        "BuildId": param.BuildId,
+        "FloorId": param.FloorId
+    }
+    if (data.FloorId == 'all') {
+        delete data.FloorId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/point_group`, data })
+}
+
+//点位标签查看详情
+export function getPoint(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "PointId": param.PointId,
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/point/query`, data })
+}
+
+//点位标签详情修改
+export function updatePoint(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "PointList": [param.PointList],
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/point/update`, data })
+}
+
+//点击点位标签获取tab设备族列表 
+export function getTabFamily(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId,
+        "BeginTime": param.BeginTime,
+        "EndTime": param.EndTime,
+        "FloorId": param.FloorId,
+        "Checked": param.Checked,
+        "BuildId": param.BuildId,
+        "PointId": param.PointId
+    }
+    if (data.PointId == 'all') {
+        delete data.PointId
+    }
+    if (data.FloorId == 'all') {
+        delete data.FloorId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/family_list`, data })
+}
+
+//获取表格数据的title
+export function getTableHeader(param) {
+    let data = {
+        "AppType": Comming,
+        "Code": param.code,
+        "ProjId": param.ProjId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/dict/infocode_query`, data })
+}
+
+//获取表格主体内容
+export function getTableMain(param) {
+    let data = {
+        "BeginTime": param.BeginTime,
+        "BuildId": param.BuildId,
+        "Checked": param.Checked,
+        "Comming": Comming,
+        "EndTime": param.EndTime,
+        "Family": param.Family,
+        "FloorId": param.FloorId,
+        "PageNum": param.PageNum,
+        "PageSize": param.PageSize,
+        "PointId": param.PointId,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    if (data.PointId == 'all') {
+        delete data.PointId
+    }
+    if (data.Checked === '') {
+        delete data.Checked
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/query`, data })
+}
+
+export function getPointList(param, success) {
+    let url = `${api}/ScanBuilding/service/point/queryByIdList`
+    let data = param
+    data.Comming = Comming
+    http.postJson(url, data, success)
+}
+
+export function getdelMain(param) {
+    let data = {
+        "BeginTime": param.BeginTime,
+        "BuildId": param.BuildId,
+        "Checked": param.Checked,
+        "CodeType": param.CodeType,
+        "Comming": Comming,
+        "EndTime": param.EndTime,
+        "Family": param.Family,
+        "FloorId": param.FloorId,
+        "PageNum": param.PageNum,
+        "PageSize": param.PageSize,
+        "PointId": param.PointId,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    if (data.PointId == 'all') {
+        delete data.PointId
+    }
+    if (data.Checked === '') {
+        delete data.Checked
+    }
+    if (data.FloorId == 'all') {
+        delete data.FloorId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/queryRevit`, data })
+}
+
+export function getTestEquire() {
+    let data = {
+        "Comming": "revit",
+        "FloorId": "Fl110108000327d8f006c39f49feb40e24a7ef223232",
+        "ProjId": "Pj1101080003",
+        "UserId": "string"
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/query`, data })
+}
+
+//批量更新表格数据
+export function upDateTableMain(param, paramList) {
+    let data = {
+        "Comming": Comming,
+        "FmList": paramList,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/update`, data })
+}
+
+//获取所有设备族/service/dict/equipment_family
+export function getAllFamily() {
+    return fetch({ method: 'GET', url: `${api}/ScanBuilding/service/dict/equipment_family` })
+}
+
+//获取当前默认楼层/service/fm/default_floor
+export function defaultFloor(param) {
+    let data = {
+        "Comming": Comming,
+        "ProjId": param.ProjId,
+        "UserId": param.UserId
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/fm/default_floor`, data })
+}
+
+//物理世界新建岗位(设备系统)
+export function createPost(param) {
+    let data = {
+        "building_id": param.BuildId,
+        "floor_id": param.BIMID,
+        "equipment_category": param.category,
+        "infos": {
+            "BIMID": [
+                { "value": param.BIMID }
+            ],
+            "BIMLocation": [
+                { "value": param.BIMLocation }
+            ]
+        }
+    }
+    return fetch({ method: 'POST', url: `${physics}/godhand/equipment/create?projectId=${param.perjectId}&secret=${param.secret}`, data })
+}
+
+
+//物理世界新建岗位(部件)
+export function createComponent(param) {
+    let data = {
+        "building_id": param.BuildId,
+        "component_category": param.category,
+        "floor_id": param.BIMID,
+        "infos": {
+            "BIMID": [
+                { "value": param.BIMID }
+            ],
+            "BIMLocation": [
+                { "value": param.BIMLocation }
+            ]
+        }
+    }
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/component/create?projectId=${param.perjectId}&secret=${param.secret}`, data })
+}
+
+//通过岗位id查询元空间id
+export function getSpaceId(param) {
+    let data = {
+        "criterias": param.list
+    }
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/relation/query?projectId=${param.perjectId}&secret=${param.secret}`, data })
+}
+
+//通过元空间id查询元空间名称
+export function getSpaceName(param) {
+    let data = {
+        "criterias": param.list
+    }
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/object/batch_query?projectId=${param.perjectId}&secret=${param.secret}`, data })
+}
+
+
+//设备族修改显示接口
+export function setHeader(param) {
+    let data = {
+        "Comming": Comming,
+        "InfoType": param.FamilyId,
+        "InfopointCode": param.code,
+        "ProjId": param.perjectId,
+        "UserId": param.UserId,
+        "Visible": param.Visible
+    }
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/dict/infopoint_visible`, data })
+}
+
+//获取头部接口
+export function getHeader(param) {
+    let data = {
+            "AppType": Comming,
+            "Code": param.code,
+            "ProjId": param.perjectId
+        }
+        // return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/dict/equipment_family_info_header`, data })
+    return fetch({ method: 'POST', url: `${api}/ScanBuilding/service/dict/infocode_query_header`, data })
+}
+
+
+/** 业务空间相关 */
+
+// 业务空间
+export function getSpaceHeader(param) {
+    return fetch({ method: 'GET', url: `${physics}${dataForm}/infocode/query_property?projectId=${param.ProjId}&type=${param.code ? param.code : 'space'}&enrich=true` })
+}
+
+
+//获取某个业务空间下的
+export function getAllbusiness(param) {
+    let data = null
+    if (!!param.id) {
+        data = {
+            "criteria": {
+                "id": param.id,
+                "type": param.type
+            }
+        }
+    } else {
+        data = param.data
+    }
+    return fetch({ method: "POST", url: `${physics}${dataForm}/object/subset_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//通过BIMID获取物理世界id
+export function formBIMToPri(param) {
+    let data = {
+        "criteria": {
+            "type": param.type,
+            "BIMID": param.ids
+        }
+    }
+    return fetch({ method: "POST", url: `${physics}${dataForm}/fast/object/in_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//获取业务空间楼层的关系
+export function getSpaceFloor(param) {
+    return fetch({ method: "POST", url: `${physics}/business-space/floor/tree?projectId=${param.ProjId}&secret=${param.secret}` })
+}
+
+//创建业务空间
+export function createBusiness(param) {
+    let data = param.data
+    return fetch({ method: "POST", url: `${physics}${dataForm}/space/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
+        // return fetch({ method: "POST", url: `/test/space/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//批量创建业务空间
+export function createBusinessList(param) {
+    let data = param.data
+    return fetch({ method: "POST", url: `${physics}${dataForm}/space/batch/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//更新业务空间
+export function updateBusiness(param) {
+    let data = param.data
+    return fetch({ method: "POST", url: `${physics}${dataForm}/object/batch_update?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//模糊搜索设备类型
+export function searchCode(param) {
+    let data = param
+    return fetch({ method: "POST", url: `${physics}${dataForm}/dict/query/equipment_all`, data })
+}
+
+//获取所有设备类型
+export function getEqCode() {
+    return fetch({ method: "GET", url: `${physics}${dataForm}/dict/query/equipment_all` })
+}
+
+//批量删除业务空间
+export function delManySpace(param) {
+    let data = param.data
+    return fetch({ method: "POST", url: `${physics}${dataForm}/space/batch/delete?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//添加关系
+export function createRelation(param) {
+    let data = param.data
+    return fetch({ method: "POST", url: `${physics}${dataForm}/relation/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//获取图实例关系
+export function getGraphyId(param) {
+    let data = {
+        "graph_type": param.type
+    }
+    return fetch({ method: "POST", url: `${physics}${dataForm}/relation/graph_instance/get?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//查询业务空间
+export function getBussines(param) {
+    let data = param.data
+    return fetch({ method: "POST", url: `${physics}${dataForm}/object/outside_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+        // return fetch({ method: "POST", url: `/test/object/outside_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//查询业务空间下的元空间
+export function getRelation(param) {
+    let data = param.criterias
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/relation/query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//查询业务空间下的设备
+export function getSpaceEquip(param) {
+    let data = param.data
+    return fetch({ method: 'POST', url: `${physics}/business-space/space/equip/query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//删除关系实例
+export function deleteRelation(param) {
+    let data = param.data
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/relation/delete?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//查询是否关联元空间的业务空间
+export function isSpaceBuss(param) {
+    let data = param.data
+    return fetch({ method: 'POST', url: `${physics}/business-space/floor/space/query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//查询所有提示
+export function getAllMess(param) {
+    let data = {}
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/space/affected/query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//删除提示
+export function deleteNotice(param) {
+    let data = param.data
+    return fetch({ method: 'POST', url: `${physics}${dataForm}/space/affected/delete_notice?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+//模糊查询楼层下的设备
+export function getEquipSearch(param) {
+    let data = param.data
+    return fetch({ method: 'POST', url: `${physics}/business-space/floor/equip/query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+export function getBussTypes(success) {
+    http.getJson(`${physics}${dataForm}/infocode/business_space_type/query`, {}, success)
+}
+
+export function getBussTypes2() {
+    return fetch({ method: 'GET', url: `${physics}${dataForm}/infocode/business_space_type/query` })
+}
+
+
+
+
+//验证元空间是否相邻
+export function isAbut(param) {
+    let data = param.data
+    return fetch({ method: 'POST', url: `${physics}/business-space/space/abut?projectId=${param.ProjId}&secret=${param.secret}`, data })
+}
+
+/**算法接口 */
+export function strDiff(param) {
+    let data = param
+    return fetch({ method: 'POST', url: `${arithmetic}/str_diff`, data })
+}
+
+
+/********* 台账部分  厂商库接口 */
+//获取供应商列表
+export function getManuLib(param, success) {
+    let data = param
+    http.postJson(`${physics}venders/supplier/query`, data, success)
+}
+
+//查询所有供应商信息
+export function getLib(param) {
+    let data = param
+    return fetch({ method: 'POST', url: `${physics}/venders/auxiliary/query/all`, data })
+}
+
+//查询资产的list
+export function getPropertyList(param, success) {
+    let data = param.data
+    let url = `${physics}/data-platform-3/property/relation_query?projectId=${param.ProjId}&secret=${param.secret}`
+    http.postJson(url, data, success)
+}
+
+//获取资产种族编码query/equipment_family
+export function getEquipmentFamily(success) {
+    let url = `${physics}/data-platform-3/dict/query/equipment_family`
+    http.getJson(url, {}, success)
+}
+
+//删除资产
+export function delProperty(param, success) {
+    let url = `${physics}/data-platform-3/property/delete?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//获取制定供应商下的供应合同编号
+export function getListForSupplier(param, success) {
+    let url = `${physics}/venders-dp/supplier/contract/query?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//获取保单列表
+export function getListForGuarantee(param, success) {
+    let url = `${physics}/venders-dp/insurance/contract/query`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//新建保单
+export function createGuarantee(param, success) {
+    let url = `${physics}/venders/insurance/contract/create `
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//创建资产
+export function createProperty(param, success) {
+    let url = `${physics}${dataForm}/property/create?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//获取项目内[岗位]和[绑定岗位的资产]的数量
+export function getNumber(param, success) {
+    let url = `${physics}/business-space/equip/count?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//获取项目内有实例的所有种族
+export function getFamilyList(param, success) {
+    let url = `${physics}/business-space/equip/type/list?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//删除系统、设备
+export function delSystem(param, success) {
+    let url = `${physics}${dataForm}/equipment/delete?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+
+//创建系统设备
+export function createSystem(param, success) {
+    let url = `${physics}${dataForm}/equipment/create?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+
+//获取台账资产列表
+export function getBillPropList(param, success) {
+    let url = `${physics}/business-space/property/list?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//台账修改资产信息
+export function updateProperty(param, success) {
+    let url = `${physics}${dataForm}/property/update?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//台账获取设备列表
+export function getBillEquipList(param, success) {
+    let url = `${physics}/business-space/equip/list?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//台账获取系统列表
+export function getBillSystemList(param, success) {
+    let url = `${physics}/business-space/system/list?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//台账获取系统关联的设备
+export function getSysToEq(param, success) {
+    let url = `${physics}${dataForm}/object/rel_query?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//台账查询型号
+export function getSpecList(param, success) {
+    let url = `${physics}/venders/manufacturer/specification/query_spec`
+    let data = param
+    http.postJson(url, data, success)
+}
+
+//台账根据设备id创建岗位
+export function EqToAssets(param, success) {
+    let url = `${physics}${dataForm}/property/create_by_equip?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//获取设定参数和动态参数
+export function BeatchQueryParam(param, success) {
+    let url = `${physics}${dataForm}/parameter/batch_query_param?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+export function BatchCreateSome(param, success) {
+    let url = `${physics}${dataForm}/equipment/batch/create?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+export function delBatchList(param, success) {
+    let url = `${physics}${dataForm}/equipment/batch/delete?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+
+//扫楼创建资产
+export function createFmList(param, success) {
+    let url = `${api}/ScanBuilding/service/fm/create`
+    param.Comming = Comming
+    let data = param
+    http.postJson(url, data, success)
+}
+
+export function createAssetsList(param, success) {
+    let url = `${api}/ScanBuilding/service/fm/create_list`
+    param.Comming = Comming
+    let data = param
+    http.postJson(url, data, success)
+}
+
+export function getListForBuss(param, success) {
+    let url = `${physics}/business-space/space/ispace/equip/query?projectId=${param.ProjId}&secret=${param.secret}`
+    let data = param.data
+    http.postJson(url, data, success)
+}
+
+//获取产品list
+export function getProductList(param, success) {
+    let url = `${physics}/venders/manufacturer/product/query`
+    http.postJson(url, param, success)
+}
+
+//完全匹配的厂商信息
+export function getBasicMatch(param) {
+    console.log(param, "param")
+    let data = param
+    return fetch({ method: 'POST', url: `${physics}/venders/basic/match`, data })
+}

BIN
src/assets/css/chosen-sprite.png


BIN
src/assets/css/chosen-sprite@2x.png


+ 490 - 0
src/assets/css/chosen.css

@@ -0,0 +1,490 @@
+/*!
+Chosen, a Select Box Enhancer for jQuery and Prototype
+by Patrick Filler for Harvest, http://getharvest.com
+
+Version 1.8.5
+Full source at https://github.com/harvesthq/chosen
+Copyright (c) 2011-2018 Harvest http://getharvest.com
+
+MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
+This file is generated by `grunt build`, do not edit it by hand.
+*/
+
+.chosen-container.chosen-with-drop-top .chosen-drop {
+    left: 0;
+    top: -220px;
+}
+
+.chosen-container {
+    position: relative;
+    display: inline-block;
+    vertical-align: middle;
+    font-size: 13px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none
+}
+
+.chosen-container * {
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box
+}
+
+.chosen-container .chosen-drop {
+    position: absolute;
+    top: 100%;
+    z-index: 1010;
+    width: 100%;
+    border: 1px solid #aaa;
+    border-top: 0;
+    background: #fff;
+    -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+    box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+    display: none
+}
+
+.chosen-container.chosen-with-drop .chosen-drop {
+    display: block
+}
+
+.chosen-container a {
+    cursor: pointer
+}
+
+.chosen-container .chosen-single .group-name,
+.chosen-container .search-choice .group-name {
+    margin-right: 4px;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    font-weight: 400;
+    color: #999
+}
+
+.chosen-container .chosen-single .group-name:after,
+.chosen-container .search-choice .group-name:after {
+    content: ":";
+    padding-left: 2px;
+    vertical-align: top
+}
+
+.chosen-container-single .chosen-single {
+    position: relative;
+    display: block;
+    overflow: hidden;
+    padding: 0 0 0 8px;
+    height: 25px;
+    border: 1px solid #aaa;
+    border-radius: 5px;
+    background-color: #fff;
+    background: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #fff), color-stop(50%, #f6f6f6), color-stop(52%, #eee), to(#f4f4f4));
+    background: linear-gradient(#fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%);
+    background-clip: padding-box;
+    -webkit-box-shadow: 0 0 3px #fff inset, 0 1px 1px rgba(0, 0, 0, .1);
+    box-shadow: 0 0 3px #fff inset, 0 1px 1px rgba(0, 0, 0, .1);
+    color: #444;
+    text-decoration: none;
+    white-space: nowrap;
+    line-height: 24px
+}
+
+.chosen-container-single .chosen-single input[type=text] {
+    cursor: pointer;
+    opacity: 0;
+    position: absolute;
+    width: 0
+}
+
+.chosen-container-single .chosen-default {
+    color: #999
+}
+
+.chosen-container-single .chosen-single span {
+    display: block;
+    overflow: hidden;
+    margin-right: 26px;
+    text-overflow: ellipsis;
+    white-space: nowrap
+}
+
+.chosen-container-single .chosen-single-with-deselect span {
+    margin-right: 38px
+}
+
+.chosen-container-single .chosen-single abbr {
+    position: absolute;
+    top: 6px;
+    right: 26px;
+    display: block;
+    width: 12px;
+    height: 12px;
+    background: url(chosen-sprite.png) -42px 1px no-repeat;
+    font-size: 1px
+}
+
+.chosen-container-single .chosen-single abbr:hover {
+    background-position: -42px -10px
+}
+
+.chosen-container-single.chosen-disabled .chosen-single abbr:hover {
+    background-position: -42px -10px
+}
+
+.chosen-container-single .chosen-single div {
+    position: absolute;
+    top: 0;
+    right: 0;
+    display: block;
+    width: 18px;
+    height: 100%
+}
+
+.chosen-container-single .chosen-single div b {
+    display: block;
+    width: 100%;
+    height: 100%;
+    background: url(chosen-sprite.png) no-repeat 0 2px
+}
+
+.chosen-container-single .chosen-search {
+    position: relative;
+    z-index: 1010;
+    margin: 0;
+    padding: 3px 4px;
+    white-space: nowrap
+}
+
+.chosen-container-single .chosen-search input[type=text] {
+    margin: 1px 0;
+    padding: 4px 20px 4px 5px;
+    width: 100%;
+    height: auto;
+    outline: 0;
+    border: 1px solid #aaa;
+    background: url(chosen-sprite.png) no-repeat 100% -20px;
+    font-size: 1em;
+    font-family: sans-serif;
+    line-height: normal;
+    border-radius: 0
+}
+
+.chosen-container-single .chosen-drop {
+    margin-top: -1px;
+    border-radius: 0 0 4px 4px;
+    background-clip: padding-box
+}
+
+.chosen-container-single.chosen-container-single-nosearch .chosen-search {
+    position: absolute;
+    opacity: 0;
+    pointer-events: none
+}
+
+.chosen-container .chosen-results {
+    color: #444;
+    position: relative;
+    overflow-x: hidden;
+    overflow-y: auto;
+    margin: 0 4px 4px 0;
+    padding: 0 0 0 4px;
+    max-height: 100px;
+    -webkit-overflow-scrolling: touch
+}
+
+.chosen-container .chosen-results li {
+    display: none;
+    margin: 0;
+    padding: 5px 6px;
+    list-style: none;
+    line-height: 15px;
+    word-wrap: break-word;
+    -webkit-touch-callout: none
+}
+
+.chosen-container .chosen-results li.active-result {
+    display: list-item;
+    cursor: pointer
+}
+
+.chosen-container .chosen-results li.disabled-result {
+    display: list-item;
+    color: #ccc;
+    cursor: default
+}
+
+.chosen-container .chosen-results li.highlighted {
+    background-color: #3875d7;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
+    background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
+    color: #fff
+}
+
+.chosen-container .chosen-results li.no-results {
+    color: #777;
+    display: list-item;
+    background: #f4f4f4
+}
+
+.chosen-container .chosen-results li.group-result {
+    display: list-item;
+    font-weight: 700;
+    cursor: default
+}
+
+.chosen-container .chosen-results li.group-option {
+    padding-left: 15px
+}
+
+.chosen-container .chosen-results li em {
+    font-style: normal;
+    text-decoration: underline
+}
+
+.chosen-container-multi .chosen-choices {
+    position: relative;
+    overflow: hidden;
+    margin: 0;
+    padding: 0 5px;
+    width: 100%;
+    height: auto;
+    border: 1px solid #aaa;
+    background-color: #fff;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(1%, #eee), color-stop(15%, #fff));
+    background-image: linear-gradient(#eee 1%, #fff 15%);
+    cursor: text
+}
+
+.chosen-container-multi .chosen-choices li {
+    float: left;
+    list-style: none
+}
+
+.chosen-container-multi .chosen-choices li.search-field {
+    margin: 0;
+    padding: 0;
+    white-space: nowrap
+}
+
+.chosen-container-multi .chosen-choices li.search-field input[type=text] {
+    margin: 1px 0;
+    padding: 0;
+    height: 25px;
+    outline: 0;
+    border: 0!important;
+    background: 0 0!important;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+    color: #999;
+    font-size: 100%;
+    font-family: sans-serif;
+    line-height: normal;
+    border-radius: 0;
+    width: 25px
+}
+
+.chosen-container-multi .chosen-choices li.search-choice {
+    position: relative;
+    margin: 3px 5px 3px 0;
+    padding: 3px 20px 3px 5px;
+    border: 1px solid #aaa;
+    max-width: 100%;
+    border-radius: 3px;
+    background-color: #eee;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), to(#eee));
+    background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
+    background-size: 100% 19px;
+    background-repeat: repeat-x;
+    background-clip: padding-box;
+    -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05);
+    box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05);
+    color: #333;
+    line-height: 13px;
+    cursor: default
+}
+
+.chosen-container-multi .chosen-choices li.search-choice span {
+    word-wrap: break-word
+}
+
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
+    position: absolute;
+    top: 4px;
+    right: 3px;
+    display: block;
+    width: 12px;
+    height: 12px;
+    background: url(chosen-sprite.png) -42px 1px no-repeat;
+    font-size: 1px
+}
+
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
+    background-position: -42px -10px
+}
+
+.chosen-container-multi .chosen-choices li.search-choice-disabled {
+    padding-right: 5px;
+    border: 1px solid #ccc;
+    background-color: #e4e4e4;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), to(#eee));
+    background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
+    color: #666
+}
+
+.chosen-container-multi .chosen-choices li.search-choice-focus {
+    background: #d4d4d4
+}
+
+.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
+    background-position: -42px -10px
+}
+
+.chosen-container-multi .chosen-results {
+    margin: 0;
+    padding: 0
+}
+
+.chosen-container-multi .chosen-drop .result-selected {
+    display: list-item;
+    color: #ccc;
+    cursor: default
+}
+
+.chosen-container-active .chosen-single {
+    border: 1px solid #5897fb;
+    -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
+    box-shadow: 0 0 5px rgba(0, 0, 0, .3)
+}
+
+.chosen-container-active.chosen-with-drop .chosen-single {
+    border: 1px solid #aaa;
+    border-bottom-right-radius: 0;
+    border-bottom-left-radius: 0;
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #eee), color-stop(80%, #fff));
+    background-image: linear-gradient(#eee 20%, #fff 80%);
+    -webkit-box-shadow: 0 1px 0 #fff inset;
+    box-shadow: 0 1px 0 #fff inset
+}
+
+.chosen-container-active.chosen-with-drop .chosen-single div {
+    border-left: none;
+    background: 0 0
+}
+
+.chosen-container-active.chosen-with-drop .chosen-single div b {
+    background-position: -18px 2px
+}
+
+.chosen-container-active .chosen-choices {
+    border: 1px solid #5897fb;
+    -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
+    box-shadow: 0 0 5px rgba(0, 0, 0, .3)
+}
+
+.chosen-container-active .chosen-choices li.search-field input[type=text] {
+    color: #222!important
+}
+
+.chosen-disabled {
+    opacity: .5!important;
+    cursor: default
+}
+
+.chosen-disabled .chosen-single {
+    cursor: default
+}
+
+.chosen-disabled .chosen-choices .search-choice .search-choice-close {
+    cursor: default
+}
+
+.chosen-rtl {
+    text-align: right
+}
+
+.chosen-rtl .chosen-single {
+    overflow: visible;
+    padding: 0 8px 0 0
+}
+
+.chosen-rtl .chosen-single span {
+    margin-right: 0;
+    margin-left: 26px;
+    direction: rtl
+}
+
+.chosen-rtl .chosen-single-with-deselect span {
+    margin-left: 38px
+}
+
+.chosen-rtl .chosen-single div {
+    right: auto;
+    left: 3px
+}
+
+.chosen-rtl .chosen-single abbr {
+    right: auto;
+    left: 26px
+}
+
+.chosen-rtl .chosen-choices li {
+    float: right
+}
+
+.chosen-rtl .chosen-choices li.search-field input[type=text] {
+    direction: rtl
+}
+
+.chosen-rtl .chosen-choices li.search-choice {
+    margin: 3px 5px 3px 0;
+    padding: 3px 5px 3px 19px
+}
+
+.chosen-rtl .chosen-choices li.search-choice .search-choice-close {
+    right: auto;
+    left: 4px
+}
+
+.chosen-rtl.chosen-container-single .chosen-results {
+    margin: 0 0 4px 4px;
+    padding: 0 4px 0 0
+}
+
+.chosen-rtl .chosen-results li.group-option {
+    padding-right: 15px;
+    padding-left: 0
+}
+
+.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
+    border-right: none
+}
+
+.chosen-rtl .chosen-search input[type=text] {
+    padding: 4px 5px 4px 20px;
+    background: url(chosen-sprite.png) no-repeat -30px -20px;
+    direction: rtl
+}
+
+.chosen-rtl.chosen-container-single .chosen-single div b {
+    background-position: 6px 2px
+}
+
+.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
+    background-position: -12px 2px
+}
+
+@media only screen and (-webkit-min-device-pixel-ratio:1.5),
+only screen and (min-resolution:144dpi),
+only screen and (min-resolution:1.5dppx) {
+    .chosen-container .chosen-results-scroll-down span,
+    .chosen-container .chosen-results-scroll-up span,
+    .chosen-container-multi .chosen-choices .search-choice .search-choice-close,
+    .chosen-container-single .chosen-search input[type=text],
+    .chosen-container-single .chosen-single abbr,
+    .chosen-container-single .chosen-single div b,
+    .chosen-rtl .chosen-search input[type=text] {
+        background-image: url(chosen-sprite@2x.png)!important;
+        background-size: 52px 37px!important;
+        background-repeat: no-repeat!important
+    }
+}

+ 477 - 0
src/assets/css/jsmind.css

@@ -0,0 +1,477 @@
+/*
+ * Released under BSD License
+ * Copyright (c) 2014-2015 hizzgdev@163.com
+ * 
+ * Project Home:
+ *   https://github.com/hizzgdev/jsmind/
+ */
+
+
+/* important section */
+
+.jsmind-inner {
+    position: relative;
+    overflow: auto;
+    width: 100%;
+    height: 100%;
+}
+
+
+/*box-shadow:0 0 2px #000;*/
+
+.jsmind-inner {
+    moz-user-select: -moz-none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+
+/* z-index:1 */
+
+canvas {
+    position: absolute;
+    z-index: 1;
+}
+
+
+/* z-index:2 */
+
+jmnodes {
+    position: absolute;
+    z-index: 2;
+    background-color: rgba(0, 0, 0, 0);
+}
+
+
+/*background color is necessary*/
+
+jmnode {
+    position: absolute;
+    cursor: default;
+    max-width: 400px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+jmexpander {
+    position: absolute;
+    width: 11px;
+    height: 11px;
+    display: block;
+    overflow: hidden;
+    line-height: 12px;
+    font-size: 12px;
+    text-align: center;
+    border-radius: 6px;
+    border-width: 1px;
+    border-style: solid;
+    cursor: pointer;
+}
+
+
+/* default theme */
+
+jmnode {
+    padding: 10px;
+    background-color: #fff;
+    color: #333;
+    border-radius: 5px;
+    box-shadow: 1px 1px 1px #666;
+    font: 16px/1.125 Verdana, Arial, Helvetica, sans-serif;
+}
+
+jmnode:hover {
+    box-shadow: 2px 2px 8px #000;
+    background-color: #ebebeb;
+    color: #333;
+}
+
+jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+    box-shadow: 2px 2px 8px #000;
+}
+
+jmnode.root {
+    font-size: 24px;
+}
+
+jmexpander {
+    border-color: gray;
+}
+
+jmexpander:hover {
+    border-color: #000;
+}
+
+@media screen and (max-device-width: 1024px) {
+    jmnode {
+        padding: 5px;
+        border-radius: 3px;
+        font-size: 14px;
+    }
+    jmnode.root {
+        font-size: 21px;
+    }
+}
+
+
+/* primary theme */
+
+jmnodes.theme-primary jmnode {
+    background-color: #428bca;
+    color: #fff;
+    border-color: #357ebd;
+}
+
+jmnodes.theme-primary jmnode:hover {
+    background-color: #3276b1;
+    border-color: #285e8e;
+}
+
+jmnodes.theme-primary jmnode.selected {
+    background-color: #f1c40f;
+    color: #fff;
+}
+
+jmnodes.theme-primary jmnode.root {}
+
+jmnodes.theme-primary jmexpander {}
+
+jmnodes.theme-primary jmexpander:hover {}
+
+
+/* warning theme */
+
+jmnodes.theme-warning jmnode {
+    background-color: #f0ad4e;
+    border-color: #eea236;
+    color: #fff;
+}
+
+jmnodes.theme-warning jmnode:hover {
+    background-color: #ed9c28;
+    border-color: #d58512;
+}
+
+jmnodes.theme-warning jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-warning jmnode.root {}
+
+jmnodes.theme-warning jmexpander {}
+
+jmnodes.theme-warning jmexpander:hover {}
+
+
+/* danger theme */
+
+jmnodes.theme-danger jmnode {
+    background-color: #d9534f;
+    border-color: #d43f3a;
+    color: #fff;
+}
+
+jmnodes.theme-danger jmnode:hover {
+    background-color: #d2322d;
+    border-color: #ac2925;
+}
+
+jmnodes.theme-danger jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-danger jmnode.root {}
+
+jmnodes.theme-danger jmexpander {}
+
+jmnodes.theme-danger jmexpander:hover {}
+
+
+/* success theme */
+
+jmnodes.theme-success jmnode {
+    background-color: #5cb85c;
+    border-color: #4cae4c;
+    color: #fff;
+}
+
+jmnodes.theme-success jmnode:hover {
+    background-color: #47a447;
+    border-color: #398439;
+}
+
+jmnodes.theme-success jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-success jmnode.root {}
+
+jmnodes.theme-success jmexpander {}
+
+jmnodes.theme-success jmexpander:hover {}
+
+
+/* info theme */
+
+jmnodes.theme-info jmnode {
+    background-color: #5dc0de;
+    border-color: #46b8da;
+    ;
+    color: #fff;
+}
+
+jmnodes.theme-info jmnode:hover {
+    background-color: #39b3d7;
+    border-color: #269abc;
+}
+
+jmnodes.theme-info jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-info jmnode.root {}
+
+jmnodes.theme-info jmexpander {}
+
+jmnodes.theme-info jmexpander:hover {}
+
+
+/* greensea theme */
+
+jmnodes.theme-greensea jmnode {
+    background-color: #1abc9c;
+    color: #fff;
+}
+
+jmnodes.theme-greensea jmnode:hover {
+    background-color: #16a085;
+}
+
+jmnodes.theme-greensea jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-greensea jmnode.root {}
+
+jmnodes.theme-greensea jmexpander {}
+
+jmnodes.theme-greensea jmexpander:hover {}
+
+
+/* nephrite theme */
+
+jmnodes.theme-nephrite jmnode {
+    background-color: #2ecc71;
+    color: #fff;
+}
+
+jmnodes.theme-nephrite jmnode:hover {
+    background-color: #27ae60;
+}
+
+jmnodes.theme-nephrite jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-nephrite jmnode.root {}
+
+jmnodes.theme-nephrite jmexpander {}
+
+jmnodes.theme-nephrite jmexpander:hover {}
+
+
+/* belizehole theme */
+
+jmnodes.theme-belizehole jmnode {
+    background-color: #3498db;
+    color: #fff;
+}
+
+jmnodes.theme-belizehole jmnode:hover {
+    background-color: #2980b9;
+}
+
+jmnodes.theme-belizehole jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-belizehole jmnode.root {}
+
+jmnodes.theme-belizehole jmexpander {}
+
+jmnodes.theme-belizehole jmexpander:hover {}
+
+
+/* wisteria theme */
+
+jmnodes.theme-wisteria jmnode {
+    background-color: #9b59b6;
+    color: #fff;
+}
+
+jmnodes.theme-wisteria jmnode:hover {
+    background-color: #8e44ad;
+}
+
+jmnodes.theme-wisteria jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-wisteria jmnode.root {}
+
+jmnodes.theme-wisteria jmexpander {}
+
+jmnodes.theme-wisteria jmexpander:hover {}
+
+
+/* asphalt theme */
+
+jmnodes.theme-asphalt jmnode {
+    background-color: #34495e;
+    color: #fff;
+}
+
+jmnodes.theme-asphalt jmnode:hover {
+    background-color: #2c3e50;
+}
+
+jmnodes.theme-asphalt jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-asphalt jmnode.root {}
+
+jmnodes.theme-asphalt jmexpander {}
+
+jmnodes.theme-asphalt jmexpander:hover {}
+
+
+/* orange theme */
+
+jmnodes.theme-orange jmnode {
+    background-color: #f1c40f;
+    color: #fff;
+}
+
+jmnodes.theme-orange jmnode:hover {
+    background-color: #f39c12;
+}
+
+jmnodes.theme-orange jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-orange jmnode.root {}
+
+jmnodes.theme-orange jmexpander {}
+
+jmnodes.theme-orange jmexpander:hover {}
+
+
+/* pumpkin theme */
+
+jmnodes.theme-pumpkin jmnode {
+    background-color: #e67e22;
+    color: #fff;
+}
+
+jmnodes.theme-pumpkin jmnode:hover {
+    background-color: #d35400;
+}
+
+jmnodes.theme-pumpkin jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-pumpkin jmnode.root {}
+
+jmnodes.theme-pumpkin jmexpander {}
+
+jmnodes.theme-pumpkin jmexpander:hover {}
+
+
+/* pomegranate theme */
+
+jmnodes.theme-pomegranate jmnode {
+    background-color: #e74c3c;
+    color: #fff;
+}
+
+jmnodes.theme-pomegranate jmnode:hover {
+    background-color: #c0392b;
+}
+
+jmnodes.theme-pomegranate jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-pomegranate jmnode.root {}
+
+jmnodes.theme-pomegranate jmexpander {}
+
+jmnodes.theme-pomegranate jmexpander:hover {}
+
+
+/* clouds theme */
+
+jmnodes.theme-clouds jmnode {
+    background-color: #ecf0f1;
+    color: #333;
+}
+
+jmnodes.theme-clouds jmnode:hover {
+    background-color: #bdc3c7;
+}
+
+jmnodes.theme-clouds jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-clouds jmnode.root {}
+
+jmnodes.theme-clouds jmexpander {}
+
+jmnodes.theme-clouds jmexpander:hover {}
+
+
+/* asbestos theme */
+
+jmnodes.theme-asbestos jmnode {
+    background-color: #95a5a6;
+    color: #fff;
+}
+
+jmnodes.theme-asbestos jmnode:hover {
+    background-color: #7f8c8d;
+}
+
+jmnodes.theme-asbestos jmnode.selected {
+    background-color: #11f;
+    color: #fff;
+}
+
+jmnodes.theme-asbestos jmnode.root {}
+
+jmnodes.theme-asbestos jmexpander {}
+
+jmnodes.theme-asbestos jmexpander:hover {}

+ 233 - 0
src/assets/css/reset.css

@@ -0,0 +1,233 @@
+html,
+body,
+div,
+span,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+abbr,
+address,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+samp,
+small,
+strong,
+sub,
+sup,
+var,
+b,
+i,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    outline: 0;
+    vertical-align: baseline;
+    background: transparent;
+    box-sizing: border-box;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+em,
+i {
+    font-weight: 100;
+    font-style: normal
+}
+
+ul,
+ol,
+li {
+    list-style-type: none
+}
+
+a {
+    color: #666;
+    text-decoration: none;
+    outline: 0
+}
+
+a:hover {
+    text-decoration: none
+}
+
+.inline_block {
+    display: inline-block;
+}
+
+html {
+    position: relative;
+}
+
+body,
+html,
+#app {
+    height: 100%;
+}
+
+#app #build_assets .el-tabs--border-card>.el-tabs__content {
+    padding: 0.3rem 0 0 0 !important;
+    overflow-y: auto;
+}
+
+#app .handsontable tr:nth-child(2n) td {
+    background-color: #eee;
+}
+
+#app .handsontable .htRight {
+    text-align: center;
+}
+
+#app .el-pagination {
+    text-align: center;
+}
+
+#app .btn {
+    color: #409EFF;
+}
+
+#app .modification .el-dialog__body {
+    max-height: 38rem;
+    overflow-y: auto;
+}
+
+#app .modification .el-dialog {
+    width: 30rem;
+}
+
+#app .left_main .el-tabs__content {
+    position: absolute;
+    width: 100%;
+    top: 38px;
+    bottom: 0;
+}
+
+#app .left_main .el-tab-pane {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+}
+
+#app .el-loading-mask {
+    z-index: 1999;
+}
+
+#app .left_main .el-tab-pane .assets_page {
+    position: absolute;
+    bottom: 0;
+    text-align: center;
+    width: 100%;
+}
+
+#app #build_assets .iframe .el-dialog {
+    width: 800px;
+    height: 600px;
+}
+
+#app #build_assets .iframe .el-dialog .el-dialog__body {
+    height: 475px;
+}
+
+#app #buildData .chosen-container-single .chosen-search input[type=text] {
+    box-sizing: border-box;
+}
+
+#app #buildData .build_table {
+    height: 100%;
+    /* overflow: hidden; */
+}
+
+#app #buildData .build_table .el-tabs {
+    height: 100%;
+}
+
+#app #build_log .log_dialog .el-dialog__body {
+    max-height: 500px;
+    overflow-y: auto;
+}
+
+#app #buildData .el-tab-pane .htColumnHeaders {
+    margin-bottom: 32px
+}
+
+.no_data {
+    line-height: 5rem;
+    margin-left: 2rem;
+}
+
+#family .el-tabs__content {
+    height: 100%;
+    overflow-y: auto;
+}
+
+.saga-padding0 {
+    padding: 0 !important;
+}
+
+.el-tooltip__popper {
+    max-width: 200px;
+    word-break: break-all;
+    word-wrap: break-word;
+    overflow: inherit;
+}
+
+.custom-dialog {
+    z-index: 3000;
+}
+
+.saga-button .el-button {
+    white-space: normal !important;
+}

File diff suppressed because it is too large
+ 67 - 0
src/assets/icon/iconfont.css


BIN
src/assets/icon/iconfont.eot


File diff suppressed because it is too large
+ 1 - 0
src/assets/icon/iconfont.js


File diff suppressed because it is too large
+ 108 - 0
src/assets/icon/iconfont.svg


BIN
src/assets/icon/iconfont.ttf


BIN
src/assets/icon/iconfont.woff


BIN
src/assets/images/point.png


BIN
src/assets/images/unfold.png


File diff suppressed because it is too large
+ 1378 - 0
src/assets/js/chosen.jquery.min.js


+ 286 - 0
src/assets/js/graphyCanvas.js

@@ -0,0 +1,286 @@
+import tools from './tools'
+
+import Ball from './canvas/items/ball'
+import Line from './canvas/items/line'
+import Point from './canvas/items/point'
+// var graphy = {};
+// var ctx;
+// import graphyClick from './graphyEvent'
+class graphy {
+
+    /**
+     * 创建画布方法,初始化
+     * @param id 为canvas元素的id
+     */
+    zoom //缩放层级
+    cStep = -1 //撤回计数
+    cPushArray = new Array() //存储canvas的base64的图片
+    mousedown = new Object() //mousedown存储的xy
+    mouse //鼠标位置
+    dx = 0
+    dy = 0
+    beginPath
+    data
+    constructor(id, json) {
+        this.data = json
+        this.beginPath = tools.getXY(json)
+        this.canvas = document.getElementById(id);
+        if (!this.canvas.getContext) this.canvas.text = '当前浏览器不支持canvas';
+        this.ctx = this.canvas.getContext("2d");
+        this.executionArray = [];
+        this.mouse = tools.getMouse(this.canvas)
+    }
+
+    //创建point
+    createPoint() {
+        let dom = document.getElementById("canvasView")
+        let point = new Point(10, 10)
+        point.addPoint(dom)
+    }
+
+
+    //添加事件
+    addListener(type, listener) {
+        this.canvas.addEventListener(type, listener, true)
+    }
+
+    //删除事件
+    removeListener(type, listener) {
+        this.canvas.removeEventListener(type, listener, true)
+    }
+
+    //缩放
+    sacle() {
+
+    }
+
+    /**
+     * 画线条
+     * @param data
+     * {
+     *   beginPath:{//必填
+     *      x:,
+     *      y:,
+     *    },
+     *    endPath:{//必填
+     *      x: ,
+     *      y: ,
+     *    },
+     *    color: "",选填,颜色,默认#000;
+     *    width: "",//选填,宽度,默认1px;
+     *    isMove: "",选填,是否可移动,默认false;
+     * }
+     */
+    line(data) {
+        // this.ctx.translate(this.beginPath.x, this.beginPath.y)\
+        var line = new Line(data[0].X, data[0].Y, data[1].X, data[1].Y)
+            // var line = new Line(20, 20, 80, 80)
+
+        // this.ctx.translate(this.beginPath.x, this.beginPath.y)
+
+        line.stroke(this.ctx)
+        line.fill(this.ctx)
+    }
+
+    //创建小球
+    ball() {
+        this.cre = new Ball(50, 50, 15);
+        this.cre.fill(this.ctx);
+    }
+
+    ballDraw() {
+        this.addListener("mousedown", this.ballDown)
+    }
+
+    ballDown = (e) => {
+        if (this.cre.checkMouse(this.mouse)) {
+            this.dx = this.mouse.x - this.cre.x
+            this.dy = this.mouse.y - this.cre.y
+            this.addListener("mousemove", this.ballMove)
+            this.addListener("mouseup", this.ballUp)
+        }
+    }
+
+    ballMove = (e) => {
+        this.cre.x = this.mouse.x - this.dx
+        this.cre.y = this.mouse.y - this.dy
+            // this.cre.fill(this.ctx);
+            //加入边界限制
+            //当小球碰到边界
+            // console.log(this.cre.y, this.cre.x, this.cre.radius, this.canvas.height, this.canvas.width)
+        if (this.cre.x < this.cre.radius) { //左边界
+            this.cre.x = this.cre.radius;
+        } else if (this.cre.x > this.canvas.width - this.cre.radius) {
+            this.cre.x = this.canvas.width - this.cre.radius
+        }
+
+        //碰到上边界
+        if (this.cre.y < this.cre.radius) {
+            this.cre.y = this.cre.radius
+        } else if (this.cre.y > this.canvas.height - this.cre.radius) {
+            this.cre.y = this.canvas.height - this.cre.radius
+        }
+
+        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+        this.cre.fill(this.ctx)
+    }
+
+    ballUp = (e) => {
+        this.removeListener('mousemove', this.ballMove)
+        this.removeListener('mouseup', this.ballUp)
+    }
+
+    //添加画线的事件
+    drawLine() {
+        this.addListener("mousedown", this.lineMouseDown)
+        this.addListener("mousemove", this.lineMouseMove)
+        this.addListener("mouseup", this.lineMouseUp)
+        this.canvas.style.cursor = "crosshair"
+    }
+
+    //删除事件
+    stopdrawLine() {
+        this.removeListener("mousedown", this.lineMouseDown)
+        this.removeListener("mousemove", this.lineMouseMove)
+        this.removeListener("mouseup", this.lineMouseUp)
+        this.canvas.style.cursor = "auto"
+    }
+
+    //线条添加事件当鼠标按下
+    lineMouseDown = (e) => {
+        this.cPush()
+        var ele = {}
+        for (var i in e) {
+            ele[i] = e[i]
+        }
+        ele.clientX = 222
+        var loc = this.mouse;
+        this.saveDrawingSurface();
+        this.mousedown.x = loc.x;
+        this.mousedown.y = loc.y;
+        this.dragging = true;
+    }
+
+    //线条添加移动事件
+    lineMouseMove = (e) => {
+        //判断当前是否用户在拖动
+        if (this.dragging) {
+            e.preventDefault();
+            var loc = this.mouse;
+            this.restoreDrawingSurface();
+            this.drawGuidewires(loc.x, loc.y);
+            this.updateRubberband(loc);
+        }
+    }
+
+    //拖动时的辅助线
+    drawGuidewires(x, y) {
+        this.ctx.save();
+        this.ctx.strokeStyle = "rgba(0,0,230, 0.4)";
+        this.ctx.lineWidth = 0.5;
+        this.drawHorizontLine(y);
+        this.drawVerticalLine(x);
+        this.ctx.restore();
+    }
+
+    //保存图片
+    saveDrawingSurface() {
+        this.drawingSurfacsImageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
+    }
+
+    //恢复canvas的数据,主要用来显示最新的线段,擦除原来的线段
+    restoreDrawingSurface = () => {
+        this.ctx.putImageData(this.drawingSurfacsImageData,
+            0, 0, 0, 0, this.canvas.width, this.canvas.height
+        );
+    }
+
+    // 添加标记
+    addPoint() {
+        let img = new Image()
+        img.src = "../assets/images/point.png"
+        document.getElementById('text').appendChild(img)
+    }
+
+
+    //鼠标弹起事件
+    lineMouseUp = (e) => {
+        var loc = this.mouse;
+        this.restoreDrawingSurface();
+        this.updateRubberband(loc);
+        //鼠标抬起,拖动标记设为否
+        this.dragging = false;
+    }
+
+    //更新
+    updateRubberband(loc) {
+        this.drawRubberbandShape(loc)
+    }
+
+    //画最新的线条
+    drawRubberbandShape(loc) {
+        this.ctx.beginPath();
+        this.ctx.moveTo(this.mousedown.x, this.mousedown.y);
+        this.ctx.lineTo(loc.x, loc.y);
+        this.ctx.stroke();
+    }
+
+    //画辅助横线,在y坐标上
+    drawHorizontLine(y) {
+        this.ctx.beginPath();
+        this.ctx.moveTo(0, y + 0.5);
+        this.ctx.lineTo(this.canvas.width, y + 0.5);
+        this.ctx.stroke();
+    }
+
+
+    //画辅助竖线
+    drawVerticalLine(x) {
+        this.ctx.beginPath();
+        this.ctx.moveTo(x + 0.5, 0);
+        this.ctx.lineTo(x + 0.5, this.canvas.height);
+        this.ctx.stroke();
+    }
+
+
+    /**
+     * 画笔操作时保存canvas的base64图片
+     */
+    cPush() {
+        this.cStep++;
+        if (this.cStep < this.cPushArray.length) { this.cPushArray.length = this.cStep; }
+        this.cPushArray.push(this.canvas.toDataURL());
+    }
+
+    // 清空画布
+    clearCanvas() {
+        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+    }
+
+    //撤回
+    undo() {
+        if (this.cStep > 0) {
+            let _this = this
+            this.cStep--;
+            let canvasPic = new Image();
+            canvasPic.src = this.cPushArray[this.cStep];
+            canvasPic.onload = function() {
+                _this.clearCanvas()
+                _this.ctx.drawImage(canvasPic, 0, 0);
+            }
+        }
+    }
+
+    //取消撤回
+    cRedo() {
+        if (this.cStep < this.cPushArray.length - 1) {
+            cStep++;
+            var canvasPic = new Image();
+            canvasPic.src = this.cPushArray[this.cStep];
+            canvasPic.onload = () => { this.ctx.drawImage(canvasPic, 0, 0); }
+        }
+    }
+}
+
+export default graphy

+ 7 - 0
src/assets/js/graphyEvent.js

@@ -0,0 +1,7 @@
+class graphyEvent {
+    click = function(el) {
+        console.log(el)
+    }
+}
+
+export default graphyEvent

+ 324 - 0
src/assets/js/handsontable-chosen-editor.js

@@ -0,0 +1,324 @@
+/// chosen plugin
+(function(Handsontable) {
+    "use strict";
+
+    var ChosenEditor = Handsontable.editors.TextEditor.prototype.extend();
+
+    ChosenEditor.prototype.prepare = function(row, col, prop, td, originalValue, cellProperties) {
+
+        Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);
+
+        this.options = {};
+
+        if (this.cellProperties.chosenOptions) {
+            this.options = $.extend(this.options, cellProperties.chosenOptions);
+        }
+
+        cellProperties.chosenOptions = $.extend({}, cellProperties.chosenOptions);
+    };
+
+    ChosenEditor.prototype.createElements = function() {
+        this.$body = $(document.body);
+
+        this.TEXTAREA = document.createElement('select');
+        //this.TEXTAREA.setAttribute('type', 'text');
+        this.$textarea = $(this.TEXTAREA);
+
+        Handsontable.dom.addClass(this.TEXTAREA, 'handsontableInput');
+
+        this.textareaStyle = this.TEXTAREA.style;
+        this.textareaStyle.width = 0;
+        this.textareaStyle.height = 0;
+
+        this.TEXTAREA_PARENT = document.createElement('DIV');
+        Handsontable.dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder');
+
+        this.textareaParentStyle = this.TEXTAREA_PARENT.style;
+        this.textareaParentStyle.top = 0;
+        this.textareaParentStyle.left = 0;
+        this.textareaParentStyle.display = 'none';
+        this.textareaParentStyle.width = "200px";
+
+        this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
+
+        this.instance.rootElement.appendChild(this.TEXTAREA_PARENT);
+
+        var that = this;
+        this.instance._registerTimeout(setTimeout(function() {
+            that.refreshDimensions();
+        }, 0));
+    };
+
+    var onChosenChanged = function() {
+        var options = this.cellProperties.chosenOptions;
+
+        if (!options.multiple) {
+            this.close();
+            this.finishEditing();
+        }
+    };
+    var onChosenClosed = function() {
+        var options = this.cellProperties.chosenOptions;
+
+        if (!options.multiple) {
+            this.close();
+            this.finishEditing();
+        } else {}
+    };
+    var onBeforeKeyDown = function(event) {
+        var instance = this;
+        var that = instance.getActiveEditor();
+
+        var keyCodes = Handsontable.helper.KEY_CODES;
+        var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
+
+        //Process only events that have been fired in the editor
+        if (event.target.tagName !== "INPUT") {
+            return;
+        }
+        if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
+            //when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
+            event.stopImmediatePropagation();
+            return;
+        }
+
+        var target = event.target;
+
+        switch (event.keyCode) {
+            case keyCodes.ARROW_RIGHT:
+                if (Handsontable.dom.getCaretPosition(target) !== target.value.length) {
+                    event.stopImmediatePropagation();
+                } else {
+                    that.$textarea.trigger("chosen:close");
+                }
+                break;
+
+            case keyCodes.ARROW_LEFT:
+                if (Handsontable.dom.getCaretPosition(target) !== 0) {
+                    event.stopImmediatePropagation();
+                } else {
+                    that.$textarea.trigger("chosen:close");
+                }
+                break;
+
+            case keyCodes.ENTER:
+                if (that.cellProperties.chosenOptions.multiple) {
+                    event.stopImmediatePropagation();
+                    event.preventDefault();
+                    event.stopPropagation();
+                }
+
+                break;
+
+            case keyCodes.A:
+            case keyCodes.X:
+            case keyCodes.C:
+            case keyCodes.V:
+                if (ctrlDown) {
+                    event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
+                }
+                break;
+
+            case keyCodes.BACKSPACE:
+                var txt = $(that.TEXTAREA_PARENT).find("input").val();
+                $(that.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
+
+                event.stopImmediatePropagation();
+                break;
+            case keyCodes.DELETE:
+            case keyCodes.HOME:
+            case keyCodes.END:
+                event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)
+                break;
+        }
+
+    };
+
+    ChosenEditor.prototype.open = function(keyboardEvent) {
+        this.refreshDimensions();
+        this.textareaParentStyle.display = 'block';
+        this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
+
+        this.$textarea.css({
+            height: $(this.TD).height() + 4,
+            'min-width': $(this.TD).outerWidth() - 4
+        });
+
+        //display the list
+        this.$textarea.hide();
+
+        //make sure that list positions matches cell position
+        //this.$textarea.offset($(this.TD).offset());
+
+        var options = $.extend({}, this.options, {
+            width: "100%",
+            search_contains: true
+        });
+
+        if (options.multiple) {
+            this.$textarea.attr("multiple", true);
+        } else {
+            this.$textarea.attr("multiple", false);
+        }
+
+        this.$textarea.empty();
+        this.$textarea.append("<option value=''></option>");
+        var el = null;
+        var originalValue = (this.originalValue + "").split(",");
+        if (options.data && options.data.length) {
+            for (var i = 0; i < options.data.length; i++) {
+                // el = $("<option />");
+                // el.attr("value", options.data[i].Code);
+                // el.html(options.data[i].Name);
+
+                // if (originalValue.indexOf(options.data[i].Code + "") > -1) {
+                //     el.attr("selected", true);
+                // }
+
+                // this.$textarea.append(el);
+                if (options.data[i].content && options.data[i].content.length) {
+                    for (var k = 0; k < options.data[i].content.length; k++) {
+                        if (options.data[i].content[k] && options.data[i].content[k].length) {
+                            for (var j = 0; j < options.data[i].content[k].length; j++) {
+                                el = $("<option />");
+                                el.attr("value", options.data[i].content[k].content[j].Code);
+                                el.html(options.data[i].content[k].content[j].Name);
+
+                                if (originalValue.indexOf(options.data[i].content[k].content[j].Code + "") > -1) {
+                                    el.attr("selected", true);
+                                }
+                                this.$textarea.append(el);
+                            }
+                        } else {
+                            el = $("<option />");
+                            el.attr("value", options.data[i].content[k].Code);
+                            el.html(options.data[i].content[k].Name);
+
+                            if (originalValue.indexOf(options.data[i].content[k].Code + "") > -1) {
+                                el.attr("selected", true);
+                            }
+                            this.$textarea.append(el);
+                        }
+                    }
+                } else {
+                    el = $("<option />");
+                    el.attr("value", options.data[i].Code);
+                    el.html(options.data[i].Name);
+
+                    if (originalValue.indexOf(options.data[i].Code + "") > -1) {
+                        el.attr("selected", true);
+                    }
+                    this.$textarea.append(el);
+                }
+            }
+        }
+
+        if ($(this.TEXTAREA_PARENT).find(".chosen-container").length) {
+            this.$textarea.chosen("destroy");
+        }
+
+        this.$textarea.chosen(options);
+
+        var self = this;
+        setTimeout(function() {
+
+            self.$textarea.on('change', onChosenChanged.bind(self));
+            self.$textarea.on('chosen:hiding_dropdown', onChosenClosed.bind(self));
+
+            self.$textarea.trigger("chosen:open");
+
+            $(self.TEXTAREA_PARENT).find("input").on("keydown", function(e) {
+                if (e.keyCode === Handsontable.helper.KEY_CODES.ENTER /*|| e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE*/ ) {
+                    if ($(this).val()) {
+                        e.preventDefault();
+                        e.stopPropagation();
+                    } else {
+                        e.preventDefault();
+                        e.stopPropagation();
+
+                        self.close();
+                        self.finishEditing();
+                    }
+
+                }
+
+                if (e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE) {
+                    var txt = $(self.TEXTAREA_PARENT).find("input").val();
+
+                    $(self.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
+
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+                if (e.keyCode === Handsontable.helper.KEY_CODES.ARROW_DOWN || e.keyCode === Handsontable.helper.KEY_CODES.ARROW_UP) {
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+            });
+
+            setTimeout(function() {
+                self.$textarea.trigger("chosen:activate").focus();
+
+                if (keyboardEvent && keyboardEvent.keyCode && keyboardEvent.keyCode != 113) {
+                    var key = keyboardEvent.keyCode;
+                    var keyText = (String.fromCharCode((96 <= key && key <= 105) ? key - 48 : key)).toLowerCase();
+
+                    $(self.TEXTAREA_PARENT).find("input").val(keyText).trigger("keyup.chosen");
+                    self.$textarea.trigger("chosen:activate");
+                }
+            }, 1);
+        }, 1);
+
+    };
+
+    ChosenEditor.prototype.init = function() {
+        Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.close = function() {
+        this.instance.listen();
+        this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
+        this.$textarea.off();
+        this.$textarea.hide();
+        Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.getValue = function() {
+        if (!this.$textarea.val()) {
+            return "";
+        }
+        if (typeof this.$textarea.val() === "object") {
+            return this.$textarea.val().join(",");
+        }
+        return this.$textarea.val();
+    };
+
+
+    ChosenEditor.prototype.focus = function() {
+        this.instance.listen();
+
+        // DO NOT CALL THE BASE TEXTEDITOR FOCUS METHOD HERE, IT CAN MAKE THIS EDITOR BEHAVE POORLY AND HAS NO PURPOSE WITHIN THE CONTEXT OF THIS EDITOR
+        //Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.beginEditing = function(initialValue) {
+        var onBeginEditing = this.instance.getSettings().onBeginEditing;
+        if (onBeginEditing && onBeginEditing() === false) {
+            return;
+        }
+
+        Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);
+
+    };
+
+    ChosenEditor.prototype.finishEditing = function(isCancelled, ctrlDown) {
+        this.instance.listen();
+        return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
+    };
+
+    Handsontable.editors.ChosenEditor = ChosenEditor;
+    Handsontable.editors.registerEditor('chosen', ChosenEditor);
+
+})(Handsontable);

+ 21 - 0
src/assets/js/isDuitString.js

@@ -0,0 +1,21 @@
+import { strDiff } from '@/api/request'
+
+// export default async function isStrDiss(val, cb, color) {
+export default async function isStrDiss(val, color) {
+    await strDiff(val).then(res => {
+        // cb(res.data.result, color, val)
+        return { res: res.data.result, val: val, color: color }
+    })
+}
+
+export default function isStrDiss(val, color) {
+    new Promise(function(resolve, reject) {
+            request.get(options, function(error, response, body) {
+                if (error) {
+                    reject(error);
+                } else {
+                    resolve(body);
+                }
+            });
+        }
+    }

+ 70 - 0
src/assets/js/items/SGraphyCircleItem.js

@@ -0,0 +1,70 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+export default class SGraphyCircleItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param X  圆中心点X
+     * @param Y  圆中心点Y
+     * @param Radius   圆的半径
+     * 
+     * @param color  线的颜色
+     * @param isVirtual    是否为虚线
+     */
+    constructor(X, Y, color, Radius, isSolid, name, parent = null) {
+        super(parent)
+        this.X = X
+        this.Y = Y
+        this.color = color
+        this.Radius = Radius
+        this.isSolid = isSolid
+        this.minX = this.X - this.Radius
+        this.minY = this.Y - this.Radius
+        this.maxX = this.X + this.Radius
+        this.maxY = this.Y + this.Radius
+        this.sAngle = null || 0
+        this.eAngle = null || 2 * Math.PI
+        this.name = name
+        this.type = 6
+        this.lineWidth = null
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.minX, this.minY, this.maxX - this.minX, this.maxY - this.minY)
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        canvas.lineWidth = this.lineWidth || 240
+        canvas.strokeStyle = this.color || '#000'
+        canvas.fillStyle = this.color || '#000'
+        canvas.beginPath();
+        canvas.arc(this.X, this.Y, this.Radius, this.sAngle, this.eAngle);
+        if (!!this.isSolid) {
+            canvas.fillStyle = this.color; //填充颜色,默认是黑色
+            canvas.fill(); //画实心圆
+        }
+        canvas.stroke()
+        if (!!this.name) {
+            canvas.font = "oblique small-caps bold " + this.lineWidth * 10 + "px Arial";
+            // canvas.font = "oblique small-caps bold " + 10 + "px Arial";
+            canvas.fillStyle = 'green'
+            canvas.fillText(this.name, this.X, this.Y);
+        }
+    }
+}

+ 59 - 0
src/assets/js/items/SGraphyImageItem.js

@@ -0,0 +1,59 @@
+/**
+ * 图片
+ * 
+ * 
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect'
+export default class SGraphyImageItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param width  图片宽度
+     * @param height  图片高度
+     * @param url    图片url
+     * @param id     point的Id
+     * @param X      图片向x轴的偏移量
+     * @param Y      图片向y轴的偏移量
+     * @param downUrl 图片按下时的url
+     * @param parent  指向父元素
+     */
+    constructor(width, height, url, id, X, Y, downUrl, parent = null) {
+            super(parent)
+            this.width = width
+            this.height = height
+            this.url = url
+            this.id = id
+            this.X = X
+            this.Y = Y
+            this.downUrl = downUrl
+            this.imgFalg = false
+            this.img = new Image()
+            this.img.src = this.url
+            this.img.style.width = this.width
+            this.img.style.height = this.height
+            this.canMove = true
+            this.type = 1
+        } //constructor
+
+    /**
+     * Item对象边界区域
+     *
+     * @return  SRect
+     */
+    boundingRect() {
+            return new SRect(0, 0, this.width * 100, this.height * 100)
+        } // Function boundingRect()
+
+    /**
+     * 绘制图片
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+    onDraw(canvas, rect) {
+        // canvas.moveTo(this.X, this.Y)
+        // canvas.drawImage(this.img, 0, 0, this.width, this.height, this.X, this.Y, this.width * 100, this.height * 100)
+        canvas.drawImage(this.img, 0, 0, this.width, this.height, 0, 0, this.width * 100, this.height * 100)
+    }
+}

+ 66 - 0
src/assets/js/items/SGraphyLineItem.js

@@ -0,0 +1,66 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+export default class SGraphyLineItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param startX  线的起始x坐标
+     * @param startY  线的起始y坐标
+     * @param endX    线的终止x坐标
+     * @param endY    线的终止y坐标
+     * @param width   线的宽度
+     * 
+     * @param color  线的颜色
+     * @param isVirtual    是否为虚线
+     */
+    constructor(startX, startY, endX, endY, color, width, isVirtual, parent = null) {
+        super(parent)
+        this.startX = startX
+        this.startY = startY
+        this.endX = endX
+        this.endY = endY
+        this.color = color
+        this.width = width
+        this.isVirtual = isVirtual
+        this.minX = Math.min(this.startX, this.endX)
+        this.minY = Math.min(this.startY, this.endY)
+        this.maxX = Math.max(this.startX, this.endX)
+        this.maxY = Math.max(this.startY, this.endY)
+        this.name = null
+        this.type = 2
+        this.lineWidth = null
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.minX, this.minY, this.maxX - this.minX, this.maxY - this.minY)
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        canvas.lineWidth = this.lineWidth || this.width || 240
+        canvas.strokeStyle = this.color || '#000'
+        if (this.isVirtual) {
+            canvas.setLineDash([100, 80])
+            canvas.strokeStyle = 'green'
+        }
+        canvas.beginPath();
+        canvas.moveTo(this.startX, this.startY)
+        canvas.lineTo(this.endX, this.endY)
+        canvas.stroke()
+    }
+}

+ 76 - 0
src/assets/js/items/SGraphyPillarItems.js

@@ -0,0 +1,76 @@
+/**
+ * 不规则多边形,元空间
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+function getItem(arr, name) {
+    if (arr && arr.length) {
+        return arr.map(item => {
+            return item[name]
+        })
+    } else {
+        return [0]
+    }
+}
+
+
+export default class SGraphyPolygonItem extends SGraphyItem {
+    /**
+     * 
+     * 构造函数
+     * 
+     * @param jsonArr  空间线条数组
+     * @param lineWidth    空间线条的宽度
+     * @param color    空间线条的颜色
+     * @param fillColor  空间的填充颜色
+     * 
+     */
+    constructor(jsonArr, lineWidth, color, fillColor, parent = null) {
+            super(parent)
+            this.jsonArr = jsonArr
+            this.lineWidth = lineWidth
+            this.color = color
+            this.fillColor = fillColor
+            let xArr = getItem(this.jsonArr, 'X')
+            let yArr = getItem(this.jsonArr, 'Y')
+            this.minX = Math.min.apply(null, xArr) || 0
+            this.minY = Math.min.apply(null, yArr) || 0
+            this.width = Math.max.apply(null, xArr) - this.minX || 0
+            this.height = Math.max.apply(null, yArr) - this.minY || 0
+            this.type = 5
+        } //constructor
+
+    /**
+     * Item的边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.minX, this.minY, this.width, this.height)
+    }
+
+    /**
+     * 绘制不规则多边形
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+    onDraw(canvas, rect) {
+        if (this.jsonArr && this.jsonArr.length) {
+            canvas.beginPath();
+            canvas.lineWidth = 240
+            canvas.lineCap = 'butt';
+            canvas.strokeStyle = this.color || '#000'
+            canvas.fillStyle = this.fillColor || '#fff'
+            canvas.moveTo(this.jsonArr[0].X, this.jsonArr[0].Y)
+            for (let i = 1; i < this.jsonArr.length; i++) {
+                canvas.lineTo(this.jsonArr[i].X, this.jsonArr[i].Y)
+            }
+            canvas.lineTo(this.jsonArr[0].X, this.jsonArr[0].Y)
+            canvas.closePath()
+            canvas.fill()
+            canvas.stroke()
+        }
+    }
+}

+ 257 - 0
src/assets/js/items/SGraphyPolygonItem.js

@@ -0,0 +1,257 @@
+/**
+ * 不规则多边形,元空间
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+function getItem(arr, name) {
+    if (arr && arr.length) {
+        return arr.map(item => {
+            return item[name]
+        })
+    } else {
+        return [0]
+    }
+}
+
+function changeArr(arr) {
+    if (arr && arr.length) {
+        return arr.map(item => {
+            return [
+                item.X, item.Y
+            ]
+        })
+    } else {
+        return [0]
+    }
+}
+/**
+ * 求不规则多边形重点
+ * @param {points} 数组,多个点位坐标
+ *  
+ * @return {x, y} 重点点位坐标
+ */
+// function getCenterOfGravityPoint(points) {
+//     let area = 0,
+//         gx = 0,
+//         gy = 0,
+//         i = 1,
+//         px1, px2, py1, py2, temp, length = points.length;
+//     for (i; i <= length; i++) {
+//         px1 = points[(i % length)].X;
+//         px2 = points[(i - 1)].X;
+//         py1 = points[(i % length)].Y;
+//         py2 = points[(i - 1)].Y;
+//         temp = (px1 * py2 - py1 * px2) / 2
+//         area += temp;
+//         gx += temp * (px1 + px2) / 3
+//         gy += temp * (py1 + py2) / 3
+//     }
+
+//     gx = gx / area
+//     gy = gy / area
+
+//     return {
+//         x: gx,
+//         y: gy
+//     }
+// }
+
+
+export default class SGraphyPolygonItem extends SGraphyItem {
+    /**
+     * 
+     * 构造函数
+     * 
+     * @param jsonArr  空间线条数组
+     * @param lineWidth    空间线条的宽度
+     * @param color    空间线条的颜色
+     * @param fillColor  空间的填充颜色
+     * 
+     */
+    constructor(jsonArr, lineWidth, color, fillColor, id, centerOfGravityPoint, name, paths, faceColor, businessColor, isBusiness, parent = null) {
+            super(parent)
+            this.jsonArr = jsonArr
+            this.lineWidth = lineWidth
+            this.color = color
+            this.id = id
+            this.name = name //实际渲染名字
+            this.fillColor = fillColor
+            let xArr = getItem(this.jsonArr, 'X')
+            let yArr = getItem(this.jsonArr, 'Y')
+            this.minX = Math.min.apply(null, xArr) || 0
+            this.maxX = Math.max.apply(null, xArr) || 0
+            this.maxY = Math.max.apply(null, yArr) || 0
+            this.minY = Math.min.apply(null, yArr) || 0
+            this.width = this.maxX - this.minX || 0
+            this.height = this.maxY - this.minY || 0
+            this.type = 3
+            this.businessName = null
+            this.faceColor = faceColor || '#cacaca' //颜色
+            this.businessId = null //业务空间id
+            this.isBusiness = isBusiness || 1 //状态
+            this.businessColor = businessColor || 'rgba(68,161,140,.4)' //业务空间颜色
+            this.businessFaceColor = "#333"
+            this.containsArr = changeArr(this.jsonArr)
+            this.paths = null
+            if (paths && paths.length > 1) {
+                this.paths = paths.map(item => {
+                    if (item && item.length) {
+                        return changeArr(item)
+                    } else {
+                        return undefined
+                    }
+                }).filter(d => d)
+            }
+            this.centerOfGravityPoint = centerOfGravityPoint
+        } //constructor
+
+    /**
+     * Item的边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.minX, this.minY, this.width, this.height)
+    }
+
+
+    /**
+     * 判断item是否包含点x,y
+     *
+     * @param   x       横坐标(当前item)
+     * @param   y       纵坐标(当前item)
+     *
+     * @return  boolean
+     */
+    contains(x, y) {
+        let falg = false,
+            isFullIn = false //是否在镂空图形内
+        if (this.paths instanceof Array) {
+            for (let i = 1; i < this.paths.length; i++) {
+                if (this.isIn(x, y, this.paths[i])) {
+                    //位置信息在镂空图形内
+                    isFullIn = true
+                    break
+                }
+            }
+            // //如果鼠标在大图形内切在镂空图形中返回false
+            if (this.isIn(x, y, this.containsArr) && isFullIn) {
+                falg = false
+            } else if (this.isIn(x, y, this.containsArr) && !isFullIn) {
+                falg = true
+            } else {
+                falg = this.isIn(x, y, this.containsArr)
+            }
+        } else {
+            falg = this.isIn(x, y, this.containsArr)
+        }
+        return falg
+    }
+
+
+    isIn(x, y, json) {
+        let nCross = 0,
+            point = typeof(x) == 'object' ? [x.x, x.y] : [x, y],
+            APoints = json,
+            length = APoints.length,
+            p1, p2, i, xinters;
+        p1 = APoints[0];
+        for (i = 1; i <= length; i++) {
+            p2 = APoints[i % length];
+            if (
+                point[0] > Math.min(p1[0], p2[0]) &&
+                point[0] <= Math.max(p1[0], p2[0])
+            ) {
+                if (point[1] <= Math.max(p1[1], p2[1])) {
+                    if (p1[0] != p2[0]) {
+                        //计算位置信息
+                        xinters = (point[0] - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1];
+                        if (p1[1] == p2[1] || point[1] <= xinters) {
+                            nCross++
+                        }
+                    }
+                }
+            }
+            p1 = p2;
+        }
+        if (nCross % 2 == 0) {
+            return false
+        } else {
+            return true
+        }
+
+    }
+
+    /**
+     * 绘制不规则多边形
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+    onDraw(canvas, rect) {
+        if (this.jsonArr && this.jsonArr.length) {
+            canvas.beginPath();
+            canvas.lineWidth = 220
+            canvas.lineCap = 'butt';
+            if (this.isBusiness == 1) {
+                canvas.strokeStyle = this.color || '#000'
+                canvas.fillStyle = this.fillColor
+            } else if (this.isBusiness == 2) {
+                //已有id 的业务空间
+                canvas.strokeStyle = this.color || '#000'
+                canvas.fillStyle = this.businessColor || '#fff'
+            } else if (this.isBusiness == 3) {
+                //被选择的元空间
+                canvas.strokeStyle = this.color || '#000'
+                canvas.lineWidth = 800
+                canvas.fillStyle = '#1abc9c'
+            } else if (this.isBusiness == 4) {
+                canvas.strokeStyle = 'rgba(251,226,1,.8)' || '#000'
+                canvas.fillStyle = '#fff' || '#fff'
+            } else if (this.isBusiness == 5) {
+                canvas.fillStyle = 'rgba(11,12,12,.2)' || '#fff'
+            } else if (this.isBusiness == 6) {
+                canvas.fillStyle = '#1abc9c'
+                canvas.lineWidth = 800
+                canvas.strokeStyle = 'rgba(68,161,140,.4)' || '#fff'
+            } else if (this.isBusiness == 7) {
+                canvas.strokeStyle = this.color || '#000'
+                canvas.fillStyle = this.businessColor || '#fff'
+            }
+            canvas.moveTo(this.jsonArr[0].X, this.jsonArr[0].Y)
+            for (let i = 1; i < this.jsonArr.length; i++) {
+                canvas.lineTo(this.jsonArr[i].X, this.jsonArr[i].Y)
+            }
+            canvas.lineTo(this.jsonArr[0].X, this.jsonArr[0].Y)
+            canvas.closePath()
+            canvas.fill()
+            canvas.stroke()
+            if (!!this.name) {
+                canvas.font = "normal small-caps bold 500px Arial";
+                if (this.isBusiness == 1) {
+                    canvas.fillStyle = this.faceColor
+                } else if (this.isBusiness == 2) {
+                    canvas.fillStyle = this.businessFaceColor;
+                } else if (this.isBusiness == 3) {
+                    //业务空间异常状态
+                    canvas.fillStyle = '#fff'
+                } else if (this.isBusiness == 4) {
+                    canvas.fillStyle = '#cacaca'
+                } else if (this.isBusiness == 6) {
+                    canvas.fillStyle = '#fff'
+                } else if (this.isBusiness == 7) {
+                    canvas.fillStyle = 'red'
+                }
+                if (!!this.businessName || !!this.businessId) {
+                    name = '👇   ' + this.businessName
+                } else {
+                    name = '⬇️   ' + this.name
+                }
+                canvas.fillText(name, this.centerOfGravityPoint.x, this.centerOfGravityPoint.y);
+                // canvas.fillText(this.name, (this.maxX - this.minX) / 2 + this.minX, (this.maxY - this.minY) / 2 + this.minY);
+            }
+            // canvas.fillText(this.name, this.jsonArr[0].X, this.jsonArr[0].Y);
+        }
+    }
+}

+ 100 - 0
src/assets/js/items/SGraphyRectItem.js

@@ -0,0 +1,100 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+export default class SGraphyRectItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param X  矩形的开始点X
+     * @param Y  矩形的开始点Y
+     * @param width   矩形的宽度
+     * @param height  矩形的高度
+     * 
+     * @param isFill  矩形的是否填充
+     * @param fillColor  矩形的填充色彩
+     * @param text  矩形的文字
+     * @param textSize  矩形的文字大小
+     * @param color  矩形的颜色
+     * @param Tip   提示
+     */
+    constructor(X, Y, width, height, isFill, fillColor, text, textSize, color, Tip, parent = null) {
+        super(parent)
+        this.X = X
+        this.Y = Y
+        this.width = width
+        this.height = height
+        this.isFill = isFill
+        this.fillColor = fillColor
+        this.color = color
+        this.textSize = textSize || 6
+        this.type = 10
+        this.hoverColor = null
+        this.text = text.split(",")
+        this.fontStart = this.X
+        this.Tip = Tip
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.X, this.Y, this.width, this.height)
+    }
+
+    /**
+     * 判断item是否包含点x,y
+     *
+     * @param   x       横坐标(当前item)
+     * @param   y       纵坐标(当前item)
+     *
+     * @return  boolean
+     */
+    contains(x) {
+        if (this.X + this.width > x.x && x.x > this.X && this.Y + this.height > x.y && x.y > this.Y) {
+            return true
+        } else {
+            return false
+        }
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        canvas.beginPath();
+        canvas.lineWidth = "1";
+        if (this.isFill) {
+            if (!!this.hoverColor) {
+                canvas.fillStyle = this.hoverColor
+            } else {
+                canvas.fillStyle = this.fillColor
+            }
+            canvas.fillRect(this.X, this.Y, this.width, this.height);
+        } else {
+            canvas.rect(this.X, this.Y, this.width, this.height);
+        }
+        canvas.stroke();
+        if (!!this.text && this.text.length <= 1) {
+            canvas.font = this.textSize + "px 宋体";
+            canvas.fillStyle = this.color
+            canvas.fillText(this.text[0], this.fontStart, this.Y + this.height / 2);
+        } else if (!!this.text && this.text.length > 1) {
+            canvas.font = this.textSize + "px 宋体";
+            canvas.fillStyle = this.color
+            for (let i = 0; i < this.text.length; i++) {
+                canvas.fillText(this.text[i], this.fontStart, this.Y + this.height / 2 - this.textSize * i);
+            }
+        } else {
+            return
+        }
+    }
+}

+ 51 - 0
src/assets/js/items/SGraphyTextItems.js

@@ -0,0 +1,51 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+export default class SGraphyTextItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param X  文字的开始点X
+     * @param Y  文字的开始点Y
+     * @param width   文字的宽度
+     * 
+     * @param color  文字的颜色
+     * @param text   文字的文字
+     */
+    constructor(X, Y, width, color, text, falg, font, parent = null) {
+        super(parent)
+        this.X = X
+        this.Y = Y
+        this.lineWidth = width
+        this.color = color
+        this.font = font ? font : "6px 宋体"
+        this.text = falg ? text + '→' : text
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.X, this.Y, 0, 0)
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        if (!!this.text) {
+            canvas.font = this.font;
+            canvas.fillStyle = this.color
+            canvas.fillText(this.text, this.X, this.Y);
+        }
+    }
+}

+ 66 - 0
src/assets/js/items/SGraphyVirtualItem.js

@@ -0,0 +1,66 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
+import SRect from '../../node-templete/SGraphy/types/SRect';
+
+export default class SGraphyLineItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param startX  线的起始x坐标
+     * @param startY  线的起始y坐标
+     * @param endX    线的终止x坐标
+     * @param endY    线的终止y坐标
+     * @param width   线的宽度
+     * 
+     * @param color  线的颜色
+     * @param isVirtual    是否为虚线
+     * 
+     * @param canMove  移动
+     */
+    constructor(startX, startY, endX, endY, color, width, isVirtual, canMove, parent = null) {
+        super(parent)
+        this.startX = startX
+        this.startY = startY
+        this.endX = endX
+        this.endY = endY
+        this.color = color
+        this.width = width
+        this.isVirtual = isVirtual
+        this.minX = Math.min(this.startX, this.endX)
+        this.minY = Math.min(this.startY, this.endY)
+        this.maxX = Math.max(this.startX, this.endX)
+        this.maxY = Math.max(this.startY, this.endY)
+        this.type = 4
+            // this.canMove = true
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(this.minX, this.minY, (this.maxX - this.minX), (this.maxY - this.minY))
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        if (this.isVirtual) {
+            canvas.setLineDash([240, 240])
+        }
+        canvas.lineWidth = 240
+        canvas.strokeStyle = this.color || '#000'
+        canvas.beginPath();
+        canvas.moveTo(this.startX, this.startY)
+        canvas.lineTo(this.endX, this.endY)
+        canvas.stroke()
+    }
+}

File diff suppressed because it is too large
+ 2 - 0
src/assets/js/jquery.min.js


File diff suppressed because it is too large
+ 2934 - 0
src/assets/js/jsmind.js


File diff suppressed because it is too large
+ 1 - 0
src/assets/js/qrcode/qrcode.min.js


+ 463 - 0
src/assets/js/tools.js

@@ -0,0 +1,463 @@
+const tools = {}
+
+let arrX = []
+let arrY = []
+
+tools.getPointDetails = (arr) => {
+        arr.map(item => {
+            if (item.PointList && item.PointList.length) {
+                item.PointList.map(em => {
+                    arrX.push(em.X)
+                    arrY.push(em.Y)
+                })
+            }
+        })
+    }
+    /**
+     * 
+     * @param {*} obj 将point标签的x,y进行比对
+     * @return object 返回数组,其中包括最大值最小值X,Y 
+     */
+tools.getPoint = function(obj) {
+    arrX = []
+    arrY = []
+    for (let i in obj) {
+        tools.getPointDetails(obj[i])
+    }
+    let maxX = Math.max.apply(null, arrX)
+    let minX = Math.min.apply(null, arrX)
+    let maxY = Math.max.apply(null, arrY)
+    let minY = Math.min.apply(null, arrY)
+    let data = {
+        maxX,
+        minX,
+        maxY,
+        minY
+    }
+    return data
+}
+
+/**
+ * 
+ * @param {*} array  比较数组1
+ * @param {*} array2 比较数组2
+ * 
+ * 返回两个数组中不同的元素
+ */
+tools.compareArr = function(array, array2) {
+    var arr3 = [];
+    for (key in array) {
+        var stra = array[key];
+        var count = 0;
+        for (var j = 0; j < array2.length; j++) {
+            var strb = array2[j];
+            if (stra == strb) {
+                count++;
+            }
+        }
+        if (count === 0) { //表示数组1的这个值没有重复的,放到arr3列表中  
+            arr3.push(stra);
+        }
+    }
+    return arr3;
+}
+
+/**
+ * 
+ * @param {*} arr 需要改变的数组
+ * @param {*} k   其中Y值需要变换的倍数
+ * @param {*} name arr中的key值
+ * 
+ * 返回arr map 后arr[mapIndex]name * k 的数组
+ */
+tools.changeMap = function(arr, k, name) {
+    let data = arr.map(items => {
+        if (items[name] && items[name].length) {
+            items[name].map(children => {
+                if (Array.isArray(children)) {
+                    return children.map(res => {
+                        res.Y = res.Y * k
+                        return res
+                    })
+                } else {
+                    children.Y = children.Y * k
+                    return children
+                }
+            })
+        }
+    })
+    return data
+}
+
+tools.getMouseCanvas = function(view, e) {
+    let bbox = view.canvasView.getBoundingClientRect();
+    let x = e.clientX - bbox.left,
+        y = e.clientY - bbox.top;
+    return view.mapToScene({
+        x: x,
+        y: y
+    });
+}
+
+/**
+ * 
+ * @param {*} view graphy class
+ * @param {*} e    mouse元素e
+ */
+tools.mouseInElement = function(view, e, type) {
+    let mouse = tools.getMouseCanvas(view, e),
+        falg = false,
+        items = view.scene.root.children,
+        i = 0,
+        t = type || 3;
+    for (; i < items.length; i++) {
+        if (items[i].type == t) {
+            if (items[i].contains(mouse)) {
+                falg = true
+                break
+            }
+        }
+    }
+    return {
+        falg,
+        item: items[i] || [],
+        index: i
+    }
+}
+
+/**
+ * 
+ * @param {graphy中的所有children} items 
+ * @param {类型} type 
+ * @param {list} codes 
+ * @param {item中的code} code 
+ */
+tools.clear = function(items, type, codes, code) {
+    let indexArr = [];
+    if (items && items.length) {
+        let i = 0;
+        for (i; i < items.length; i++) {
+            let j = 0;
+            for (j; j < codes.length; j++) {
+                if (items[i][type] = type && items[i][code] == codes[j][code]) {
+                    indexArr.push(i)
+                }
+            }
+        }
+    }
+    return indexArr
+}
+
+tools.getText = function(arr, name) {
+    let text = '';
+    if (arr && arr.length) {
+        arr.map(item => {
+            text += (!!text ? '、' : '') + item[name]
+        })
+    }
+    return text
+}
+
+tools.cutString = function(string, num, text) {
+    return string.substring(0, num) + '...' + text
+}
+
+tools.deepCopy = function(obj) {
+    var out = [],
+        i = 0,
+        len = obj.length;
+    for (; i < len; i++) {
+        if (obj[i] instanceof Array) {
+            out[i] = tools.deepCopy(obj[i]);
+        } else out[i] = obj[i];
+    }
+    return out;
+}
+
+tools.copyArr = (source) => {
+    if (!source || typeof source !== 'object') {
+        throw new Error('error arguments', 'shallowClone');
+    }
+    var targetObj = source.constructor === Array ? [] : {};
+    for (var keys in source) {
+        if (source.hasOwnProperty(keys)) {
+            if (source[keys] && typeof source[keys] === 'object') {
+                targetObj[keys] = source[keys].constructor === Array ? [] : {};
+                targetObj[keys] = tools.copyArr(source[keys]);
+            } else {
+                targetObj[keys] = source[keys];
+            }
+        }
+    }
+    return targetObj;
+}
+
+tools.deepCopyObj = function(v) {
+    var o = v.constructor === Array ? [] : {};
+    for (var key in v) {
+        o[key] = typeof v[key] === 'Object' ? tools.deepCopyObj(v[key]) : v[key];
+    }
+
+    return o;
+}
+
+tools.deepClone = (obj) => {
+    var proto = Object.getPrototypeOf(obj);
+    return Object.assign({}, Object.create(proto), obj);
+}
+
+//hansontable插件的修改
+tools.customDropdownRenderer = function(
+    instance,
+    td,
+    row,
+    col,
+    prop,
+    value,
+    cellProperties
+) {
+    var selectedId;
+    var optionsList = cellProperties.chosenOptions.data;
+    if (
+        typeof optionsList === "undefined" ||
+        typeof optionsList.length === "undefined" ||
+        !optionsList.length
+    ) {
+        Handsontable.renderers.TextRenderer(
+            instance,
+            td,
+            row,
+            col,
+            prop,
+            value,
+            cellProperties
+        );
+        return td;
+    }
+    var values = (value + "").split(",");
+    value = [];
+    for (var index = 0; index < optionsList.length; index++) {
+        if (optionsList[index].content && optionsList[index].content.length) {
+            for (let i = 0; i < optionsList[index].content.length; i++) {
+                if (
+                    optionsList[index].content[i] &&
+                    optionsList[index].content[i].length
+                ) {
+                    for (let j = 0; j < optionsList[index].content[i].length; j++) {
+                        if (
+                            values.indexOf(
+                                optionsList[index].content[i].content[j].Code + ""
+                            ) > -1
+                        ) {
+                            selectedId = optionsList[index].content[i].content[j].Code;
+                            value.push(optionsList[index].content[i].content[j].Name);
+                        }
+                    }
+                } else {
+                    if (
+                        values.indexOf(optionsList[index].content[i].Code + "") > -1
+                    ) {
+                        selectedId = optionsList[index].content[i].Code;
+                        value.push(optionsList[index].content[i].Name);
+                    }
+                }
+            }
+        } else {
+            if (values.indexOf(optionsList[index].Code + "") > -1) {
+                selectedId = optionsList[index].Code;
+                value.push(optionsList[index].Name);
+            }
+        }
+    }
+    value = value.join(", ");
+    Handsontable.renderers.TextRenderer(
+        instance,
+        td,
+        row,
+        col,
+        prop,
+        value,
+        cellProperties
+    );
+    return td;
+}
+
+
+//hansontable插件查看详情
+tools.lookDetails = function(instance, td, row, col, prop, value, cellProperties) {
+    td.style.color = "#409EFF";
+    td.style.cursor = "pointer";
+    if (!!value) {
+        if (typeof(value) == 'object') {
+            td.innerHTML = "已有值,查看";
+        } else {
+            td.innerHTML = value
+        }
+    } else {
+        td.innerHTML = "查看详情";
+    }
+    return td;
+}
+
+//是否关联
+tools.hasRelation = function(instance, td, row, col, prop, value, cellProperties) {
+    if (value) {
+        td.innerHTML = "已关联";
+    } else {
+        td.innerHTML = "未关联";
+    }
+    return td;
+}
+
+tools.num = function(instance, td, row, col, prop, value, cellProperties) {
+    td.style.color = "#409EFF";
+    td.style.cursor = "pointer";
+    td.innerHTML = value;
+    return td;
+}
+
+tools.setItem = (key, value) => {
+    if (typeof value == 'string') {
+        localStorage.setItem(key, value);
+    } else {
+        localStorage.setItem(key, JSON.stringify(value));
+    }
+}
+
+tools.getItem = (key) => {
+    const re = /^\[|\{|\}|\]$/g //判断字符中是否有[]{}
+    let getIt = localStorage.getItem(key)
+    if (re.test(getIt)) {
+        return JSON.parse(getIt)
+    } else {
+        return getIt
+    }
+}
+
+tools.removeItem = (key) => {
+    localStorage.removeItem(key)
+}
+
+//取两个数组的差值
+tools.differenceArr = (a, b) => {
+    return a.concat(b).filter(v => !a.includes(v) || !b.includes(v))
+}
+
+//取两个数组的相同值
+tools.sameArr = (a, b) => {
+    return a.filter(v => b.includes(v))
+}
+
+tools.sortArr = (arr, key, sequence) => {
+    function compare(property) {
+        return function(a, b) {
+            var value1 = a[property];
+            var value2 = b[property];
+            if (sequence) {
+                return value1 - value2;
+            } else {
+                return value2 - value1
+            }
+        }
+    }
+
+    return arr.sort(compare(key))
+}
+
+tools.pagination = (pageNo, pageSize, array) => {
+    let offset = (pageNo - 1) * pageSize;
+    return offset + pageSize >= array.length ?
+        array.slice(offset, array.length) :
+        array.slice(offset, offset + pageSize);
+}
+
+tools.getSameItems = (arr1, key1, arr2, key2) => {
+    let data = []
+    arr1.map(item => {
+        arr2.map(child => {
+            if (item[key1] == child[key2]) {
+                data.push(item)
+            }
+        })
+    })
+    return data
+}
+
+tools.isIn = (x, y, json) => {
+    let nCross = 0,
+        point = typeof(x) == 'object' ? [x.x, x.y] : [x, y],
+        APoints = json,
+        length = APoints.length,
+        p1, p2, i, xinters;
+    p1 = APoints[0];
+    for (i = 1; i <= length; i++) {
+        p2 = APoints[i % length];
+        if (
+            point[0] > Math.min(p1[0], p2[0]) &&
+            point[0] <= Math.max(p1[0], p2[0])
+        ) {
+            if (point[1] <= Math.max(p1[1], p2[1])) {
+                if (p1[0] != p2[0]) {
+                    //计算位置信息
+                    xinters = (point[0] - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1];
+                    if (p1[1] == p2[1] || point[1] <= xinters) {
+                        nCross++
+                    }
+                }
+            }
+        }
+        p1 = p2;
+    }
+    if (nCross % 2 == 0) {
+        return false
+    } else {
+        return true
+    }
+
+}
+
+tools.arrayUnique = (arr, name) => {
+    var hash = {};
+    return arr.reduce(function(item, next) {
+        hash[next[name]] ? '' : hash[next[name]] = true && item.push(next);
+        return item;
+    }, []);
+}
+
+tools.dateAddYear = function(date, yearCount) {
+    var tempDate = dateToDate(date);
+    var count = parseInt(yearCount);
+    var oldYear = tempDate.getFullYear();
+    var oldMonth = tempDate.getMonth();
+    var oldDate = tempDate.getDate();
+    var newYear = oldYear + count;
+    var newDate = new Date(newYear, oldMonth, oldDate);
+    //防止月份数不一致,进行微调
+    while (newDate.getMonth() != oldMonth) {
+        oldDate--;
+        newDate = new Date(newYear, oldMonth, oldDate);
+    }
+    var month = newDate.getMonth() + 1;
+    var day = newDate.getDate();
+    month = (month.toString().length == 1) ? ("0" + month) : month;
+    day = (day.toString().length == 1) ? ("0" + day) : day;
+
+    var result = newDate.getFullYear() + '-' + month + '-' + day; //当前日期
+
+    return result;
+}
+
+function dateToDate(date) {
+    var sDate = new Date();
+    if (typeof date == 'object' && typeof new Date().getMonth == "function") {
+        sDate = date;
+    } else if (typeof date == "string") {
+        var arr = date.split('-');
+        if (arr.length == 3) {
+            sDate = new Date(arr[0] + '-' + arr[1] + '-' + arr[2]);
+        }
+    }
+    return sDate;
+}
+
+export default tools

BIN
src/assets/json/1CDC5E0E-50EB-415a-BBC1-099832D12238.txt


BIN
src/assets/json/bim.jsonz


File diff suppressed because it is too large
+ 12944 - 0
src/assets/json/cxds5.json


File diff suppressed because it is too large
+ 5540 - 0
src/assets/json/end.json


File diff suppressed because it is too large
+ 39 - 0
src/assets/json/mind.json


+ 81 - 0
src/assets/json/relation.json

@@ -0,0 +1,81 @@
+{
+  "Id": 0,
+  "EId": "Eq110108000363030e6dd13011e89cc437ba0563ea71",
+  "FloorName": "F1(庞利祥正在编辑)",
+  "EName": "楼控网络控制器-QSR4V",
+  "Sno": "L222",
+  "InLineNo": "",
+  "InLineNo1": "",
+  "Type": "BANC",
+  "Parent": null,
+  "Childrens": [
+    {
+      "Id": 0,
+      "EId": "Eq1101080003c2d3e4b0d12d11e89cc44d5a2530a318",
+      "FloorName": "F1(庞利祥正在编辑)",
+      "EName": "多联机室内机-IA29L",
+      "Sno": "",
+      "InLineNo": "L222",
+      "InLineNo1": "",
+      "Type": "ATVI",
+      "Childrens": [],
+      "Postition": "370,224.5",
+      "Infos": {
+        "create_time": "20181016182510",
+        "location": {
+          "building": "Bd110108000379ac7cf1ab5411e89d941758f2406247"
+        },
+        "id": "Eq1101080003c2d3e4b0d12d11e89cc44d5a2530a318",
+        "category": "ACATVI",
+        "infos": {
+          "EquipName": "多联机室内机-IA29L",
+          "BIMID": "Fl110108000312e12641d10f11e89cc47d1581057a50:3892180",
+          "ctm-MainCtrl": "L222",
+          "EquipID": "Eq1101080003c2d3e4b0d12d11e89cc44d5a2530a318"
+        }
+      }
+    },
+    {
+      "Id": 0,
+      "EId": "Eq1101080003c824fa36d12d11e89cc499538a153f69",
+      "FloorName": "F1(庞利祥正在编辑)",
+      "EName": "多联机室内机-BDGBM",
+      "Sno": "",
+      "InLineNo": "L222",
+      "InLineNo1": "",
+      "Type": "ATVI",
+      "Childrens": [],
+      "Postition": "370,449",
+      "Infos": {
+        "create_time": "20181016182519",
+        "location": {
+          "building": "Bd110108000379ac7cf1ab5411e89d941758f2406247"
+        },
+        "id": "Eq1101080003c824fa36d12d11e89cc499538a153f69",
+        "category": "ACATVI",
+        "infos": {
+          "EquipName": "多联机室内机-BDGBM",
+          "BIMID": "Fl110108000312e12641d10f11e89cc47d1581057a50:3892198",
+          "ctm-MainCtrl": "L222",
+          "EquipID": "Eq1101080003c824fa36d12d11e89cc499538a153f69"
+        }
+      }
+    }
+  ],
+  "Postition": "100,449",
+  "Infos": {
+    "create_time": "20181016184358",
+    "location": {
+      "building": "Bd110108000379ac7cf1ab5411e89d941758f2406247"
+    },
+    "id": "Eq110108000363030e6dd13011e89cc437ba0563ea71",
+    "category": "WEBANC",
+    "infos": {
+      "EquipName": "楼控网络控制器-QSR4V",
+      "BIMID": "Fl110108000312e12641d10f11e89cc47d1581057a50:3963418",
+      "EquipLocalID": "L222",
+      "EquipID": "Eq110108000363030e6dd13011e89cc437ba0563ea71",
+      "EquipQRCode": "43297fa9dd9642198c973e00acaec7d7"
+    }
+  }
+}

+ 424 - 0
src/assets/json/roomCl.json

@@ -0,0 +1,424 @@
+{
+  "LineList": [
+    {
+      "Start": {
+        "X": 0.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 100.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 100.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 200.0,
+        "Y": 225.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 200.0,
+        "Y": 225.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 300.0,
+        "Y": 225.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 300.0,
+        "Y": 225.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 400.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 100.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 200.0,
+        "Y": 175.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 200.0,
+        "Y": 175.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 300.0,
+        "Y": 175.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 300.0,
+        "Y": 175.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 400.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 100.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 200.0,
+        "Y": 125.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 200.0,
+        "Y": 125.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 300.0,
+        "Y": 125.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 300.0,
+        "Y": 125.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 400.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 100.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 200.0,
+        "Y": 75.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 200.0,
+        "Y": 75.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 300.0,
+        "Y": 75.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 300.0,
+        "Y": 75.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 400.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Start": {
+        "X": 400.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "End": {
+        "X": 500.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Id": 0,
+      "Name": "",
+      "ElementType": "Line",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    }
+  ],
+  "VertexList": [
+    {
+      "Location": {
+        "X": 0.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "Z41T-10 - 350 mm",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 500.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "Z41T-10 - 350 mm",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 100.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": false,
+      "Id": 0,
+      "Name": null,
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 400.0,
+        "Y": 150.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": false,
+      "Id": 0,
+      "Name": null,
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 200.0,
+        "Y": 225.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "DHHP-热水水泵",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 300.0,
+        "Y": 225.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "CCAH-螺杆式风冷热泵机组",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 200.0,
+        "Y": 175.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "DHHP-热水水泵",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 300.0,
+        "Y": 175.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "CCAH-螺杆式风冷热泵机组",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 200.0,
+        "Y": 125.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "DHHP-热水水泵",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 300.0,
+        "Y": 125.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "CCAH-螺杆式风冷热泵机组",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 200.0,
+        "Y": 75.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "DHHP-热水水泵",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    },
+    {
+      "Location": {
+        "X": 300.0,
+        "Y": 75.0,
+        "Z": 0.0
+      },
+      "Radius": 1.0,
+      "Thickness": 1.0,
+      "IsSolid": true,
+      "Id": 0,
+      "Name": "CCAH-螺杆式风冷热泵机组",
+      "ElementType": "Vertex",
+      "ElementColor": "#FFFF0000",
+      "RefData": null
+    }
+  ]
+}

File diff suppressed because it is too large
+ 7795 - 0
src/assets/json/space(2).json


File diff suppressed because it is too large
+ 7795 - 0
src/assets/json/space(3).json


File diff suppressed because it is too large
+ 7795 - 0
src/assets/json/space.json


File diff suppressed because it is too large
+ 1 - 0
src/assets/json/test.json


BIN
src/assets/logo.png


+ 44 - 0
src/assets/node-templete/SGraphy/SCanvas.js

@@ -0,0 +1,44 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+/**
+ * Canvas功能扩展
+ *
+ * @author  Andy
+ */
+Object.assign(CanvasRenderingContext2D.prototype, {
+  /**
+   * 绘制线段
+   *
+   * @param   x0    起点x坐标
+   * @param   y0    起点y坐标
+   * @param   x1    终点x坐标
+   * @param   y1    终点y坐标
+   */
+  drawLine (x0, y0, x1, y1) {
+    this.beginPath()
+    this.moveTo(x0, y0)
+    this.lineTo(x1, y1)
+    this.stroke()
+  } // Function drawLine()
+}) // Class CanvasRenderingContext2D

+ 30 - 0
src/assets/node-templete/SGraphy/SGraphyEnums.js

@@ -0,0 +1,30 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+const SGraphyItemFlag = {
+  ItemIsMovable: 1,
+  ItemIsSelectable: 2
+}
+
+if (Object.freeze)
+  Object.freeze(SGraphyItemFlag)

+ 396 - 0
src/assets/node-templete/SGraphy/SGraphyItem.js

@@ -0,0 +1,396 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+import SPoint from './types/SPoint'
+import SRect from './types/SRect'
+import SMouseEvent from './SMouseEvent'
+
+const sortItemZOrder = Symbol('sortItemZOrder')
+const toChildMouseEvent = Symbol('toChildMouseEvent')
+const grabItem = Symbol('grabItem')
+const releaseItem = Symbol('releaseItem')
+
+/**
+ * SGraphyItem
+ *
+ * @author  Andy
+ */
+export default class SGraphyItem {
+    /**
+     * 构造函数
+     */
+    constructor(parent) {
+            this.name = 'item'
+            this._scene = null
+            this._parent = parent
+            this.children = []
+
+            /** Z轴顺序 */
+            this.zOrder = 0
+                /** item位置 */
+            this._pos = new SPoint(0, 0)
+                /** 缩放比例 */
+            this._scale = new SPoint(1, 1)
+                /** 是否可见 */
+            this._isVisible = true
+
+            /** 鼠标按下时位置 */
+            this._mouseDownPos = new SPoint(4, 21)
+            this._isMove = false
+            this.canMove = false
+        } // Function constructor()
+
+    // ===================================================================================================================
+    // 属性
+    /** parent属性存值函数 */
+    get parent() {
+        return this._parent
+    }
+    set parent(value) {
+            if (this._parent === value) {
+                return
+            }
+            if (this._parent != null) { // 如果原parent不为空
+                // 将节点从原parent节点中摘除
+                let i = this._parent.children.indexOf(this)
+                this._parent.children.splice(i, 1)
+            }
+            this._parent = value
+
+            if (this._parent != null) { // 如果新parent不为空
+                // 将节点加入到新parent节点中
+                this._parent.children.push(this)
+                this._parent.children.sort(this[sortItemZOrder])
+            }
+            this._parent = value
+        } // Function set Parent()
+
+    /** scene属性 */
+    get scene() {
+        if (this._parent != null) {
+            return this._parent.scene
+        } else {
+            return this._scene
+        }
+    }
+
+    /** pos属性 */
+    get pos() {
+        return this._pos
+    }
+    set pos(value) {
+        this._pos = value
+    }
+
+    /** scale属性 */
+    get scale() {
+        return this._scale
+    }
+    set scale(value) {
+        this._scale = value
+    }
+
+    /** visible属性 */
+    get visible() {
+        return this._isVisible
+    }
+    set visible(value) {
+        this._isVisible = value
+    }
+
+    // ===================================================================================================================
+    // 函数
+    /**
+     * Item对象边界区域
+     *
+     * @return  SRect
+     */
+    boundingRect() {
+            return new SRect(0, 0, 10, 10)
+        } // Function boundingRect()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas        画布对象
+     * @param   rect          绘制区域
+     */
+    onDraw(canvas, rect) {
+            for (let item of this.children) {
+                // 保存画布状态
+                canvas.save()
+                    // item位移到指定位置绘制
+                canvas.translate(item.pos.x, item.pos.y)
+                    // 设置绘制区域
+                    // canvas.clip(item.boundingRect())
+                    // 绘制item
+                item.onDraw(canvas, rect)
+                    // 恢复画布状态
+                canvas.restore()
+            }
+        } // Function onDraw()
+
+    /**
+     * 更新Item
+     */
+    update() {
+            // TODO: PLX
+            // scene?.update()
+        } // Function update()
+
+    /**
+     * 移动item到指定位置
+     *
+     * @param   x           新位置的x坐标
+     * @param   y           新位置的y坐标
+     */
+    moveTo(x, y) {
+            this.pos = new SPoint(x, y)
+        } // moveTo()
+
+    /**
+     * 判断item是否包含点x,y
+     *
+     * @param   x       横坐标(当前item)
+     * @param   y       纵坐标(当前item)
+     *
+     * @return  boolean
+     */
+    contains(x, y) {
+            return this.boundingRect().contains(x - this.pos.x, y - this.pos.y)
+        } // Function contains()
+
+    /**
+     * 获得item的路径节点列表。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
+     *
+     * @return  *[]
+     */
+    itemPath() {
+            if (this.parent != null) {
+                let list = this.parent.itemPath()
+                list.push(this)
+                return list
+            }
+
+            return [this]
+        } // Function itemPath()
+
+    /**
+     * 将场景中的xy坐标转换成item坐标。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
+     *
+     * @param   x       场景中的横坐标
+     * @param   y       场景中的纵坐标
+     *
+     * @return  在item中的坐标
+     */
+    mapFromScene(x, y) {
+            let list = this.itemPath()
+            let x0 = x
+            let y0 = y
+            for (let item of list) {
+                x0 = (x0 - item.pos.x) / item.scale.x
+                y0 = (y0 - item.pos.y) / item.scale.y
+            }
+
+            return new SPoint(x0, y0)
+        } // Function mapFromScene()
+
+    /**
+     * 将item中的xy坐标转换成场景坐标。(该节点被加载到场景中,如果未被加载到场景中,计算会出错)
+     *
+     * @param   x       item中的横坐标
+     * @param   y       item中的纵坐标
+     *
+     * @return  在场景中的坐标
+     */
+    mapToScene(x, y) {
+            if (this.parent == null) {
+                return new SPoint(x, y)
+            }
+
+            return this.parent.mapToScene(x * this.scale.x + this.pos.x, y * this.scale.y + this.pos.y)
+        } // Function mapToScene()
+
+    // ===================================================================================================================
+    // 事件
+    /**
+     * 鼠标单击事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onClick(e) {
+            for (let item of this.children) {
+                if (!item.visible) { // 如果项目不可见
+                    continue
+                }
+                let ce = this[toChildMouseEvent](item, e)
+                if (item.contains(e.x, e.y) && item.onClick(ce)) { // 如果点在子项目上且子项目处理了事件
+                    return true
+                }
+            }
+
+            return false
+        } // Function onClick()
+
+    /**
+     * 鼠标双击事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onDbClick(e) {
+            for (let item of this.children) {
+                if (!item.visible) { // 如果项目不可见
+                    continue
+                }
+                let ce = this[toChildMouseEvent](item, e)
+                if (item.contains(e.x, e.y) && item.onDbClick(ce)) { // 如果点在子项目上且子项目处理了事件
+                    return true
+                }
+            }
+
+            return false
+        } // Function onClick()
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onMouseDown(e) {
+            // console.log(e)
+
+            for (let item of this.children) {
+                if (!item.visible) { // 如果项目不可见
+                    continue
+                }
+                let ce = this[toChildMouseEvent](item, e)
+                if (item.contains(e.x, e.y) && item.onMouseDown(ce)) { // 如果点在子项目上且子项目处理了事件
+                    return true
+                }
+            }
+
+            if (this.canMove) {
+                this._mouseDownPos = new SPoint(e.x, e.y)
+                this._isMove = true
+                this[grabItem](this)
+                    // console.log(this.scene.grabItem)
+                return true
+            }
+            return false
+        } // Function onMouseDown()
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onMouseMove(e) {
+            for (let item of this.children) {
+                if (!item.visible) { // 如果项目不可见
+                    continue
+                }
+                let ce = this[toChildMouseEvent](item, e)
+                if (item.contains(e.x, e.y) && item.onMouseMove(ce)) { // 如果点在子项目上且子项目处理了事件
+                    return true
+                }
+            }
+
+            if (e.buttons & SMouseEvent.LEFT_BUTTON && this.canMove && this._isMove) {
+                this.moveTo(this.pos.x + e.x - this._mouseDownPos.x, this.pos.y + e.y - this._mouseDownPos.y)
+            }
+
+            return false
+        } // Function onMouseMove()
+
+    /**
+     * 释放鼠标事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onMouseUp(e) {
+            for (let item of this.children) {
+                if (!item.visible) { // 如果项目不可见
+                    continue
+                }
+                let ce = this[toChildMouseEvent](item, e)
+                if (item.contains(e.x, e.y) && item.onMouseUp(ce)) { // 如果点在子项目上且子项目处理了事件
+                    return true
+                }
+            }
+
+            this._isMove = false
+            this[releaseItem]()
+            return false
+        } // Function onMouseUp()
+
+    // ===================================================================================================================
+    // 私有方法
+    /**
+     * 按ZOrder排序
+     *
+     * @param   a   比较元素1
+     * @param   b   比较元素2
+     * @return {number}
+     */
+    [sortItemZOrder](a, b) {
+        return a.zOrder - b.zOrder
+    } // Function sortItemZOrder()
+
+    /**
+     * 鼠标事件转子对象鼠标事件
+     *
+     * @param   child   子对象e
+     * @param   e       事件参数
+     * @return  {}
+     */
+    [toChildMouseEvent](child, e) {
+        let ce = {...e }
+        ce.x = (e.x - child.pos.x) / child.scale.x
+        ce.y = (e.y - child.pos.y) / child.scale.y
+        return ce
+    } // Function toChildMouseEvent()
+
+    /**
+     * 锁定item
+     *
+     * @param   item    被锁定的item
+     */
+    [grabItem](item) {
+        if (this.scene != null) {
+            this.scene.grabItem = item
+        }
+    } // Function grabItem
+
+    /**
+     * 释放被锁定的item
+     */
+    [releaseItem]() {
+        if (this.scene != null) {
+            this.scene.grabItem = null
+        }
+    } // Function grabItem
+} // Class SGraphyItem

+ 201 - 0
src/assets/node-templete/SGraphy/SGraphyScene.js

@@ -0,0 +1,201 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+import SPoint from './types/SPoint'
+import SRect from './types/SRect'
+import SGraphyItem from './SGraphyItem'
+
+const toGrabItemMotionEvent = Symbol('toGrabItemMotionEvent')
+
+/**
+ * SGraphy图形引擎场景类
+ *
+ * @author  Andy
+ */
+export default class SGraphyScene {
+    /**
+     * 构造函数
+     */
+    constructor() {
+            this.view = null
+            console.log(this, 'this')
+            this.root = new SGraphyItem(null)
+            this.root._scene = this
+            this.pos = new SPoint(0, 0)
+            this.scale = new SPoint(1, 1)
+            this.grabItem = null
+        } // Function constructor()
+
+    /**
+     * 添加item对象到场景。
+     *
+     * @param   item        添加的对象
+     */
+    addItem(item) {
+            item.parent = this.root
+        } // Function addItem()
+
+    /**
+     * 从场景中移除Item。
+     *
+     * @param   item        被移除的对象
+     */
+    removeItem(item) {
+            item.parent = null
+        } // Function removeItem()
+
+    /**
+     * 绘制场景
+     *
+     * @param   canvas      画布
+     * @param   rect        更新绘制区域
+     */
+    drawScene(canvas, rect) {
+            this.root.onDraw(canvas, rect)
+        } // Function drawScene()
+
+    /**
+     * 绘制背景
+     *
+     * @param   canvas      画布
+     * @param   rect        更新绘制区域
+     */
+    drawBackground(canvas, rect) {
+            // DO NOTHING
+        } // Function drawBackground()
+
+    /**
+     * 绘制前景
+     *
+     * @param   canvas      画布
+     * @param   rect        更新绘制区域
+     */
+    drawForeground(canvas, rect) {
+            // DO NOTHING
+        } // Function drawForeground()
+
+    /**
+     * 返回场景的item边界。即所有item边界的并集。
+     *
+     * @return  SRect
+     */
+    worldRect() {
+            let rect = null
+
+            for (let item of this.root.children) { // 依次取item列中的所有item。将所有item的边界做并焦处理。
+                if (rect == null) {
+                    rect = item.boundingRect().adjusted(item.pos)
+                } else {
+                    rect.union(item.boundingRect().adjusted(item.pos))
+                }
+            }
+
+            return rect
+        } // Function worldsRect()
+
+    /**
+     * 更新
+     */
+    update() {} // Function update()
+        // ===================================================================================================================
+        // 事件
+        /**
+         * 鼠标单击事件
+         *
+         * @param   e   保存事件参数
+         * @return  boolean
+         */
+    onClick(e) {
+            if (this.grabItem != null) {
+                return this.grabItem.onClick(this[toGrabItemMotionEvent](this.grabItem, e))
+            }
+            return this.root.onClick(e)
+        } // onClick
+
+    /**
+     * 鼠标双击事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onDbClick(e) {
+            if (this.grabItem != null) {
+                return this.grabItem.onDbClick(this[toGrabItemMotionEvent](this.grabItem, e))
+            }
+            return this.root.onDbClick(e)
+        } // onClick
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onMouseDown(e) {
+            if (this.grabItem != null) {
+                return this.grabItem.onMouseDown(this[toGrabItemMotionEvent](this.grabItem, e))
+            }
+            return this.root.onMouseDown(e)
+        } // onMouseDown
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onMouseMove(e) {
+            if (this.grabItem != null) {
+                return this.grabItem.onMouseMove(this[toGrabItemMotionEvent](this.grabItem, e))
+            }
+            return this.root.onMouseMove(e)
+        } // onMouseMove
+
+    /**
+     * 释放鼠标事件
+     *
+     * @param   e   保存事件参数
+     * @return  boolean
+     */
+    onMouseUp(e) {
+            if (this.grabItem != null) {
+                return this.grabItem.onMouseUp(this[toGrabItemMotionEvent](this.grabItem, e))
+            }
+            return this.root.onMouseUp(e)
+        } // onMouseUp
+
+    /**
+     * 转换场景事件坐标到指定Item坐标事件
+     *
+     * @param   item        指定的item对象
+     * @param   e           场景事件
+     * @return  {}
+     */
+    [toGrabItemMotionEvent](item, e) {
+        let se = {...e }
+        let p = item.mapFromScene(e.x, e.y)
+        se.x = p.x
+        se.y = p.y
+        return se
+    } // Function toGrabItemMotionEvent()
+} // Class SGraphyScene

+ 280 - 0
src/assets/node-templete/SGraphy/SGraphyView.js

@@ -0,0 +1,280 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+import './SCanvas'
+import SPoint from './types/SPoint'
+import SMouseEvent from './SMouseEvent'
+
+const bindEvent = Symbol('bindEvent')
+const toSceneMotionEvent = Symbol('toSceneMotionEvent')
+    /**
+     * Graphy图形引擎视图类
+     *
+     * @author  Andy
+     */
+export default class SGraphyView {
+    /**
+     * 构造函数
+     *
+     * @param   id    Canvas对象ID
+     */
+    constructor(id, scene) {
+            this.canvasView = document.getElementById(id)
+            this.canvas = this.canvasView.getContext('2d')
+            this[bindEvent](this.canvasView)
+            this.scene = scene
+            this.pos = new SPoint(10, 0)
+            this.scale = 1
+            this.minScale = 0.004
+            this.maxScale = 0.5
+            this._midKeyX = 0
+            this._midKeyY = 0
+            this.wheelZoom = 1.05
+
+            window.requestAnimationFrame(this.onDraw.bind(this))
+        } // Function constructor()
+
+    /**
+     * 绑定canvas事件
+     *
+     * @param   canvas      canvas对象
+     * @private
+     */
+    [bindEvent](canvasView) {
+        canvasView.onclick = this.onClick.bind(this)
+        canvasView.ondblclick = this.onDbClick.bind(this)
+        canvasView.onmousedown = this.onMouseDown.bind(this)
+        canvasView.onmousemove = this.onMouseMove.bind(this)
+        canvasView.onmouseup = this.onMouseUp.bind(this)
+        canvasView.onmousewheel = this.onMouseWheel.bind(this)
+        canvasView.onresize = this.onResize.bind(this)
+    } // Function [bindEvent]()
+
+    /**
+     * 获取canvas的宽度  
+     */
+
+    get width() {
+        return this.canvasView.width
+    }
+
+    get height() {
+        return this.canvasView.height
+    }
+
+    /**
+     * 将场景中的xy坐标转换成视图坐标。
+     *
+     * @param   x       场景中的横坐标
+     * @param   y       场景中的纵坐标
+     *
+     * @return  SPoint
+     */
+    mapFromScene(x, y = null) {
+            if (typeof(x) === 'object') { // 如果传入的是SPoint对象
+                return new SPoint(x.x * this.scale + this.pos.x, x.y * this.scale + this.pos.y)
+            }
+
+            return new SPoint(x * this.scale + this.pos.x, y * this.scale + this.pos.y)
+        } // Function mapFromScene()
+
+    /**
+     * 将item中的xy坐标转换成场景坐标。
+     *
+     * @param   x       item中的横坐标
+     * @param   y       item中的纵坐标
+     * @return  SPoint
+     */
+    mapToScene(x, y = null) {
+            if (typeof(x) === 'object') { // 如果传入的是SPoint对象
+                return new SPoint((x.x - this.pos.x) / this.scale, (x.y - this.pos.y) / this.scale)
+            }
+
+            return new SPoint((x - this.pos.x) / this.scale, (y - this.pos.y) / this.scale)
+        } // Function mapToScene()
+
+    /**
+     * 缩放视图时计算视图的位置与缩放比例
+     *
+     * @param   zoom        缩放比例
+     * @param   x0          缩放计算的中心点X坐标
+     * @param   y0          缩放计算的中心点Y坐标
+     */
+    scaleByPoint(zoom, x0, y0) {
+            let z = zoom
+                /**
+                 * 缩放比例在最小比例和最大比例范围内
+                 */
+            if (this.scale * zoom >= this.maxScale) { // 大于最大缩放比例
+                z = this.maxScale / this.scale
+                this.scale = this.maxScale
+            } else if (this.scale * zoom <= this.minScale) { // 小于最小绽放比例
+                z = this.minScale / this.scale
+                this.scale = this.minScale
+            } else {
+                this.scale *= zoom
+            }
+
+            this.pos.x = x0 - (x0 - this.pos.x) * z
+            this.pos.y = y0 - (y0 - this.pos.y) * z
+
+            // EventBus.getDefault().post(SGraphyViewZoomEvent(this, scale))
+            // EventBus.getDefault().post(SGraphyViewMoveEvent(this, pos.x, pos.y))
+            // return
+        } // Function scaleByPoint()
+        // ===================================================================================================================
+        // 事件
+    onDraw() {
+            this.canvas.save()
+            this.canvas.clearRect(0, 0, this.canvasView.width, this.canvasView.height)
+            this.canvas.restore()
+
+            if (this.scene != null) {
+                // 绘制背景
+                this.canvas.save()
+                this.scene.drawBackground(this.canvas)
+                this.canvas.restore()
+
+                // 绘制场景
+                this.canvas.save()
+                this.canvas.translate(this.pos.x, this.pos.y)
+                this.canvas.scale(this.scale, this.scale)
+                this.scene.drawScene(this.canvas)
+                this.canvas.restore()
+
+                // 绘制前景
+                this.canvas.save()
+                this.scene.drawForeground(this.canvas)
+                this.canvas.restore()
+            }
+
+            window.requestAnimationFrame(this.onDraw.bind(this))
+        } // Function onDraw()
+
+    /**
+     * 鼠标单击事件
+     *
+     * @param   e   保存事件参数
+     */
+    onClick(e) {
+            if (this.scene != null) {
+                let se = this[toSceneMotionEvent](e)
+                this.scene.onClick(se)
+            }
+        } // Function onClick()
+
+    /**
+     * 鼠标双击事件
+     *
+     * @param   e   保存事件参数
+     */
+    onDbClick(e) {
+            if (this.scene != null) {
+                let ce = this[toSceneMotionEvent](e)
+                this.scene.onDbClick(ce)
+            }
+        } // Function onDbClick()
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param   e   保存事件参数
+     */
+    onMouseDown(e) {
+            let se = new SMouseEvent(e)
+            if (se.buttons & SMouseEvent.MIDDLE_BUTTON) { // 如果按下中键
+                this._midKeyX = e.x
+                this._midKeyY = e.y
+            }
+
+            if (this.scene != null) {
+                let ce = this[toSceneMotionEvent](e)
+                this.scene.onMouseDown(ce)
+            }
+        } // Function onMouseDown()
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param   e   保存事件参数
+     */
+    onMouseMove(e) {
+            let se = new SMouseEvent(e)
+            if (se.buttons & SMouseEvent.MIDDLE_BUTTON) { // 如果按下中键,则移动视图
+                this.pos.x += e.x - this._midKeyX
+                this.pos.y += e.y - this._midKeyY
+                this._midKeyX = e.x
+                this._midKeyY = e.y
+                return
+            }
+            if (this.scene != null) {
+                let ce = this[toSceneMotionEvent](e)
+                this.scene.onMouseMove(ce)
+            }
+        } // Function onMouseMove()
+
+    /**
+     * 释放鼠标事件
+     *
+     * @param   e   保存事件参数
+     */
+    onMouseUp(e) {
+            if (this.scene != null) {
+                let ce = this[toSceneMotionEvent](e)
+                this.scene.onMouseUp(ce)
+            }
+        } // Function onMouseUp()
+
+    /**
+     * 鼠标滚轮事件
+     *
+     * @param   e   保存事件参数
+     */
+    onMouseWheel(e) {
+            let se = new SMouseEvent(e)
+            if (e.wheelDelta < 0) {
+                this.scaleByPoint(1 / this.wheelZoom, se.x, se.y)
+            } else {
+                this.scaleByPoint(this.wheelZoom, se.x, se.y)
+            }
+        } // Function onMouseWheel()
+
+    /**
+     * View大小发生变化事件
+     *
+     * @param   e   保存事件参数
+     */
+    onResize(e) {} // Function onResize()
+
+    /**
+     * MotionEvent转场景对象MotionEvent
+     *
+     * @param   e       MotionEvent
+     * @return  子对象MotionEvent
+     */
+    [toSceneMotionEvent](e) {
+        let se = new SMouseEvent(e)
+        se.x = (se.x - this.pos.x) / this.scale
+        se.y = (se.y - this.pos.y) / this.scale
+        return se
+    } // Function toSceneMotionEvent()
+} // Class SGraphyView

+ 53 - 0
src/assets/node-templete/SGraphy/SMouseEvent.js

@@ -0,0 +1,53 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+/**
+ * 鼠标事件
+ *
+ * @author  Andy
+ */
+export default class SMouseEvent {
+  /**
+   * 构造函数
+   *
+   * @param   e       系统鼠标事件
+   */
+  constructor(e) {
+    let bbox          = e.srcElement.getBoundingClientRect()
+    this.type         = e.type
+    this.x            = e.clientX - bbox.left
+    this.y            = e.clientY - bbox.top
+    this.screenX      = e.screenX
+    this.screenY      = e.screenY
+    this.clientX      = e.clientX
+    this.clientY      = e.clientY
+    this.altKey       = e.altKey
+    this.ctrlKey      = e.ctrlKey
+    this.buttons      = e.buttons
+    this.wheelDelta   = e.wheelDelta
+  } // Function constructor()
+} // Class MouseEvent
+
+SMouseEvent.LEFT_BUTTON   = 0x01
+SMouseEvent.RIGHT_BUTTON  = 0x02
+SMouseEvent.MIDDLE_BUTTON = 0x04

+ 201 - 0
src/assets/node-templete/SGraphy/items/SGraphyClockItem.js

@@ -0,0 +1,201 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../types/SRect'
+
+/** 定义符号,用于定义私有成员变晴儿 */
+const drawScale     = Symbol('drawScale')
+const drawScaleText = Symbol('drawScaleText')
+const drawHour      = Symbol('drawHour')
+const drawMinute    = Symbol('drawMinute')
+const drawSecond    = Symbol('drawSecond')
+
+/**
+ * SGraphy引擎时钟Item
+ *
+ * @author  Andy
+ */
+export default class SGraphyClockItem extends SGraphyItem {
+  /**
+   * 构造函数
+   *
+   * @param   parent    指向父对象
+   */
+  constructor(width, height, parent = null) {
+    super(parent)
+    this.name = 'ClockItem'
+    this.width = width
+    this.height = height
+    /** 是否显示刻度 */
+    this.isShowScale = true
+    /** 刻度颜色 */
+    this.scaleColor = '#000'
+    /** 刻度文本颜色 */
+    this.textColor = '#000'
+    /** 时针颜色 */
+    this.hourColor = '#000'
+    /** 分针颜色 */
+    this.minuteColor = '#000'
+    /** 秒针颜色 */
+    this.secondColor = '#F00'
+    /** 是否显示钞针 */
+    this.isShowSecond = true
+    /** 是否平滑移动秒针 */
+    this.isSmooth = true
+    /** 边缘宽度 */
+    this.padding = 100.0
+  } // Function constructor()
+
+  /**
+   * Item对象边界区域
+   *
+   * @return  SRect
+   */
+  boundingRect() {
+    return new SRect(0, 0, this.width / 2, this.height / 2)
+  } // Function boundingRect()
+
+  /**
+   * 时钟半径,只读属性
+   *
+   * @return  number
+   */
+  get radius() {
+    return Math.min(this.width, this.height) / 2.0
+  } // getter radius()
+
+  /**
+   * 绘制时钟
+   *
+   * @param   canvas      画布
+   * @param   rect        绘制区域
+   */
+  onDraw(canvas, rect) {
+    canvas.translate(this.width / 2, this.height / 2)
+    canvas.arc(0, 0, this.radius, 0, 2 * Math.PI)
+    let t = new Date()
+
+    this[drawScale](canvas)
+    this[drawHour](canvas, t.getHours(), t.getMinutes(), t.getSeconds())
+    this[drawMinute](canvas, t.getMinutes(), t.getSeconds())
+    this[drawSecond](canvas, t.getSeconds() + t.getMilliseconds() / 1000.0)
+  } // Function onDraw()
+
+  /**
+   * 绘制刻度
+   *
+   * @param   canvas      画布
+   */
+  [drawScale](canvas) {
+    let scaleLength = Math.max(this.radius / 10.0, 2.0)
+    let scaleLength1 = scaleLength * 1.2
+    let strokeWidth = Math.max(this.radius / 100.0, 2.0)
+    let strokeWidth1 = strokeWidth * 2.0
+
+    canvas.save()
+    canvas.strokeStyle = this.scaleColor
+
+    for (let i = 1; i <= 12; i++) {          // 12小时刻度
+      canvas.lineWidth = strokeWidth1
+      canvas.drawLine(0, -this.radius, 0, -this.radius + scaleLength1)
+
+      if (this.radius >= 40) {              // 如果半度大于40显示分钟刻度
+        canvas.rotate(6 * Math.PI / 180)
+        for (let j = 1; j <= 4; j++) {       // 分钟刻度
+          canvas.lineWidth = strokeWidth
+          canvas.drawLine(0, -this.radius, 0, -this.radius + scaleLength)
+          canvas.rotate(6 * Math.PI / 180)
+        }
+      } else {
+        canvas.rotate(30 * Math.PI / 180)
+      }
+    }
+
+    canvas.restore()
+  } // Function drawScale()
+
+  /**
+   * 绘制刻度数字
+   *
+   * @param   canvas      画布
+   */
+  [drawScaleText](canvas) {
+
+  } // Function drawScaleText()
+
+  /**
+   * 绘制时针
+   *
+   * @param   canvas      画布
+   * @param   hour        时
+   * @param   minute      分
+   * @param   second      秒
+   */
+  [drawHour](canvas, hour, minute, second) {
+    canvas.save()
+    canvas.lineCap = 'round'
+    canvas.lineWidth = Math.max(this.radius / 30.0, 4.0)
+    canvas.strokeStyle = this.hourColor
+    canvas.rotate((hour * 30.0 + minute * 30.0 / 60 + second * 30.0 / 60 / 60) * Math.PI / 180)
+    canvas.drawLine(0, this.radius / 10.0, 0, -this.radius / 2.0)
+    canvas.restore()
+  } // Function drawHour()
+
+  /**
+   * 绘制分针
+   *
+   * @param   canvas      画布
+   * @param   minute      分
+   * @param   second      秒
+   */
+  [drawMinute](canvas, minute, second) {
+    canvas.save()
+    canvas.lineCap = 'round'
+    canvas.lineWidth = Math.max(this.radius / 40.0, 4.0)
+    canvas.strokeStyle = this.minuteColor
+    canvas.rotate((minute * 6 + second * 6 / 60.0) * Math.PI / 180.0)
+    canvas.drawLine(0, this.radius / 10.0, 0, -this.radius * 2.0 / 3.0)
+    canvas.restore()
+  } // Function drawMinute()
+
+  /**
+   * 绘制秒针
+   *
+   * @param   canvas      画布
+   * @param   second      秒
+   */
+  [drawSecond](canvas, second) {
+    canvas.save()
+    canvas.lineCap = 'round'
+    canvas.lineWidth = Math.max(this.radius / 100.0, 3.0)
+    canvas.strokeStyle = this.secondColor
+    canvas.rotate(second * 6 * Math.PI / 180)
+    canvas.drawLine(0, this.radius / 5.0, 0, -this.radius + this.radius / 10.0)
+    // canvas.drawCircle(0, 0, this.radius / 30.0)
+    // canvas.drawCircle(0, -this.radius + this.radius / 5.0, this.radius / 60.0)
+    // canvas.strokeStyle = Color.YELLOW
+    // canvas.drawCircle(0, 0, this.radius / 100.0)
+    canvas.restore()
+  } // Function drawSecond()
+} // Class SGraphyClockItem

+ 58 - 0
src/assets/node-templete/SGraphy/items/SGraphyLineItem.js

@@ -0,0 +1,58 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from './../types/SRect';
+
+export default class SGraphyLineItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param startX  线的起始x坐标
+     * @param startY  线的起始y坐标
+     * @param endX    线的终止x坐标
+     * @param endY    线的终止y坐标
+     * @param width   线的宽度
+     * 
+     * @param color  线的颜色
+     * @param isVirtual    是否为虚线
+     */
+    constructor(startX, startY, endX, endY, color, width, isVirtual, parent = null) {
+        super(parent)
+        this.startX = startX
+        this.startY = startY
+        this.endX = endX
+        this.endY = endY
+        this.color = color
+        this.width = width
+        this.isVirtual = isVirtual
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(0, 0, this.width, this.height)
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        if (this.isVirtual) {
+            canvas.setLineDash([15, 5])
+        }
+        canvas.lineWidth = this.width || 1
+        canvas.strokeStyle = this.color || '#000'
+        canvas.beginPath();
+        canvas.moveTo(this.startX, this.startY)
+        canvas.lineTo(this.endX, this.endY)
+        canvas.stroke()
+    }
+}

+ 57 - 0
src/assets/node-templete/SGraphy/items/SGraphyPolygonItem.js

@@ -0,0 +1,57 @@
+/**
+ * 不规则多边形,元空间
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from './../types/SRect';
+
+export default class SGraphyPolygonItem extends SGraphyItem {
+    /**
+     * 
+     * 构造函数
+     * 
+     * @param jsonArr  空间线条数组
+     * @param lineWidth    空间线条的宽度
+     * @param color    空间线条的颜色
+     * @param fillColor  空间的填充颜色
+     * 
+     */
+    constructor(jsonArr, lineWidth, color, fillColor, parent = null) {
+            super(parent)
+            this.jsonArr = jsonArr
+            this.lineWidth = lineWidth
+            this.color = color
+            this.fillColor = fillColor
+        } //constructor
+
+    /**
+     * Item的边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(0, 0, this.width, this.height)
+    }
+
+    /**
+     * 绘制不规则多边形
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+    onDraw(canvas, rect) {
+        if (this.jsonArr && this.jsonArr.length) {
+            canvas.beginPath();
+            canvas.lineWidth = this.lineWidth || 1
+            canvas.strokeStyle = this.color || '#000'
+            canvas.fillStyle = this.fillColor || '#fff'
+            canvas.moveTo(this.jsonArr[0].X / 120 * -1, this.jsonArr[0].Y / 120)
+            for (let i = 1; i < this.jsonArr.length - 1; i++) {
+                canvas.lineTo(this.jsonArr[i].X / 120 * -1, this.jsonArr[i].Y / 120)
+            }
+            canvas.lineTo(this.jsonArr[0].X / 120 * -1, this.jsonArr[0].Y / 120)
+            canvas.closePath()
+            canvas.fill()
+            canvas.stroke()
+        }
+    }
+}

+ 64 - 0
src/assets/node-templete/SGraphy/items/SGraphyRectItem.js

@@ -0,0 +1,64 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../types/SRect'
+
+/**
+ * SGraphy引擎时钟Item
+ *
+ * @author  Andy
+ */
+export default class SGraphyRectItem extends SGraphyItem {
+  /**
+   * 构造函数
+   */
+  constructor(width, height, parent) {
+    super(parent)
+    this.name = 'RectItem'
+    this.width = width
+    this.height = height
+    this.style = '#f00'
+    this.canMove = true
+  } // Function constructor()
+
+  /**
+   * Item对象边界区域
+   *
+   * @return  SRect
+   */
+  boundingRect() {
+    return new SRect(0, 0, this.width, this.height)
+  } // Function boundingRect()
+
+  /**
+   * 绘制时钟
+   *
+   * @param   canvas      画布
+   * @param   rect        绘制区域
+   */
+  onDraw(canvas, rect) {
+    canvas.fillStyle = this.style
+    canvas.fillRect(0, 0, this.width, this.height)
+  } // Function onDraw()
+} // Class SGraphyRectItem

+ 61 - 0
src/assets/node-templete/SGraphy/items/SGraphyVirtualItem.js

@@ -0,0 +1,61 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from './../types/SRect';
+
+export default class SGraphyLineItem extends SGraphyItem {
+    /**
+     * 构造函数
+     * 
+     * @param startX  线的起始x坐标
+     * @param startY  线的起始y坐标
+     * @param endX    线的终止x坐标
+     * @param endY    线的终止y坐标
+     * @param width   线的宽度
+     * 
+     * @param color  线的颜色
+     * @param isVirtual    是否为虚线
+     * 
+     * @param canMove  移动
+     */
+    constructor(startX, startY, endX, endY, color, width, isVirtual, canMove, parent = null) {
+        super(parent)
+        this.startX = startX
+        this.startY = startY
+        this.endX = endX
+        this.endY = endY
+        this.color = color
+        this.width = width
+        this.isVirtual = isVirtual
+        this.canMove = canMove
+    }
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect() {
+        return new SRect(0, 0, this.width, this.height)
+    }
+
+    /**
+     * 绘制线条
+     * 
+     * @param canvas 画布
+     * @param rect   绘制区域
+     */
+
+    onDraw(canvas, rect) {
+        if (this.isVirtual) {
+            canvas.setLineDash([15, 5])
+        }
+        canvas.lineWidth = this.width || 1
+        canvas.strokeStyle = this.color || '#000'
+        canvas.beginPath();
+        canvas.moveTo(this.startX, this.startY)
+        canvas.lineTo(this.endX, this.endY)
+        canvas.stroke()
+    }
+}

+ 40 - 0
src/assets/node-templete/SGraphy/types/SPoint.js

@@ -0,0 +1,40 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+/**
+ * 坐标点
+ *
+ * @author  Andy
+ */
+export default class SPoint {
+  /**
+   * 构造函数
+   *
+   * @param   x     X坐标
+   * @param   y     Y坐标
+   */
+  constructor(x, y) {
+    this.x = x
+    this.y = y
+  } // constructor
+} // Class SPoint

+ 169 - 0
src/assets/node-templete/SGraphy/types/SRect.js

@@ -0,0 +1,169 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *               iFHS7.
+ *              ;BBMBMBMc                  rZMBMBR              BMB
+ *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
+ *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
+ *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
+ *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
+ *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
+ *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
+ *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
+ *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
+ *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
+ *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
+ *         i0BM: SWKHKGO  MBDv
+ *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2018.  斯伯坦机器人世界
+ *              ,  XMW  ..
+ *                  r                                                                     All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+/**
+ * 矩形
+ *
+ * @author  Andy
+ */
+export default class SRect {
+  /**
+   * 构造函数
+   *
+   * @param   x       X坐标
+   * @param   y       Y坐标
+   * @param   width   宽度
+   * @param   height  高度
+   */
+  constructor(x = 0, y = 0, width = 0, height = 0) {
+    this._x = x
+    this._y = y
+    this._width = Math.max(width, 0)
+    this._height = Math.max(height, 0)
+  } // constructor
+
+  /**
+   * left属性
+   */
+  get left() {
+    return this._x
+  }
+  set left(value) {
+    this._x = value
+  }
+
+  /**
+   * right属性
+   */
+  get right() {
+    return this._x + this._width
+  }
+  set right(value) {
+    this._width = Math.max(value - this._x, 0)
+  }
+
+  /**
+   * top属性
+   */
+  get top() {
+    return this._y
+  }
+  set top(value) {
+    this._y = value
+  }
+
+  /**
+   * top属性
+   */
+  get bottom() {
+    return this._y + this._height
+  }
+  set bottom(value) {
+    this._height = Math.max(value - this._y, 0)
+  }
+
+  /**
+   * x属性
+   *
+   * @return {*}
+   */
+  get x() {
+    return this._x
+  }
+  set x(value) {
+    this._x = value
+  }
+
+  /**
+   * x属性
+   *
+   * @return {*}
+   */
+  get y() {
+    return this._y
+  }
+  set y(value) {
+    this._y = value
+  }
+
+  /**
+   * width 属性
+   *
+   * @return {number}
+   */
+  get width() {
+    return this._width
+  }
+  set width(value) {
+    this._width = Math.max(value, 0)
+  }
+
+  /**
+   * height 属性
+   * @return {number}
+   */
+  get height() {
+    return this._height
+  }
+  set height(value) {
+    this._height = Math.max(value, 0)
+  }
+
+  /**
+   * 判断矩形空间是否包含点x,y
+   *
+   * @param   x       横坐标(当前item)
+   * @param   y       纵坐标(当前item)
+   * @return  boolean
+   */
+  contains(x, y) {
+    return (x >= this.x && x <= this.right) && (y >= this.top && y <= this.bottom)
+  } // Function contains()
+
+  /**
+   * 调整Rect位置
+   *
+   * @param x
+   * @param y
+   * @return  SRect
+   */
+  adjusted(x, y = null) {
+    if (typeof (x) === 'object') {     // 如果传入的是SPoint对象
+      return new SRect(this.x + x.x, this.y + x.y, this.width, this.height)
+    }
+
+    return new SRect(this.x + x, this.y + y, this.width, this.height)
+  } // Function adjusted()
+
+  /**
+   * 合并rect
+   *
+   * @param   rect
+   */
+  union(rect) {
+    this.left = Math.min(this.left, rect.left)
+    this.top = Math.min(this.top, rect.top)
+    this.right = Math.max(this.right, rect.right)
+    this.bottom = Math.max(this.bottom, rect.bottom)
+  } // Function union()
+} // Class SRect

+ 9 - 0
src/assets/node-templete/index.js

@@ -0,0 +1,9 @@
+import SGraphyView from './SGraphy/SGraphyView'
+import SGraphyScene from './SGraphy/SGraphyScene'
+import SGraphyClockItem from './SGraphy/items/SGraphyClockItem'
+import SGraphyRectItem from './SGraphy/items/SGraphyRectItem'
+// import SGraphyImageItem from './SGraphy/items/SGraphyImageItem'
+import SGraphyLineItem from './SGraphy/items/SGraphyLineItem'
+import SGraphyPolygonItem from './SGraphy/items/SGraphyPolygonItem'
+
+export { SGraphyView, SGraphyScene, SGraphyClockItem, SGraphyRectItem, SGraphyLineItem, SGraphyPolygonItem }

+ 37 - 0
src/assets/pako/pako.js

@@ -0,0 +1,37 @@
+import pako from 'pako'
+
+let funcTo = atob
+console.log(funcTo)
+
+const pakoObj = {
+    unzip: function unzip(b64Data) {
+        // console.log(b64Data)
+        var strData = funcTo(b64Data);
+
+        // Convert binary string to character-number array
+        var charData = strData.split('').map(function(x) { return x.charCodeAt(0); });
+        // console.log("charData", charData)
+
+        // Turn number array into byte-array
+        var binData = new Uint8Array(charData);
+
+
+        // // unzip
+        var data = pako.inflate(binData, { to: 'string' });
+        // console.log(data)
+        // strData = new Uint16Array(data).reduce(function(data, byte) {
+        //     return data + String.fromCharCode(byte);
+        // })
+        // console.log(strData)
+        return eval("(" + data + ")");
+    },
+    // 压缩
+    zip: function(str) {
+        //escape(str)  --->压缩前编码,防止中午乱码
+        var binaryString = pako.gzip(escape(str), { to: 'string' });
+        console.log(binaryString)
+        return binaryString;
+    }
+}
+
+export default pakoObj

+ 36 - 0
src/components/HelloWorld.vue

@@ -0,0 +1,36 @@
+<template>
+  <div class="hello">
+    <h1>{{ msg }}</h1>
+    <h2>Essential Links</h2>
+    
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  data () {
+    return {
+      msg: 'Welcome to Your Vue.js App'
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+h1, h2 {
+  font-weight: normal;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 26 - 0
src/components/buildData/create.js

@@ -0,0 +1,26 @@
+import fetch from '@/api/fetch'
+import { api, physics } from '@/api/config'
+import http from '@/api/httpUtil'
+
+function createBrand(param, success) {
+    let url = `${physics}/venders/manufacturer/brand/create`
+    let data = param
+    console.log(data, "data")
+    http.postJson(url, data, success)
+}
+
+function createManufacturer(param, success) {
+    let url = `${physics}/venders/manufacturer/create`
+    let data = param
+    console.log(data, "data")
+    http.postJson(url, data, success)
+}
+
+export default {
+    Brand: {
+        createFunc: createBrand
+    },
+    Manufacturer: {
+        createFunc: createManufacturer
+    }
+}

+ 121 - 0
src/components/buildData/dataFill.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="saga-fill">
+    <div class="saga-label saga-item">{{renderData.label}}:</div>
+    <div class="saga-input saga-item" style="padding: 0 10px;">
+      <div v-if="renderData.type == 'Str'">
+        <el-input size="small" v-model="value" @keyup.native="change" placeholder="请输入内容">
+          <template slot="append" v-if="renderData.Unit">{{renderData.Unit}}</template>
+        </el-input>
+      </div>
+      <div v-if="renderData.type == 'Num'">
+        <el-input
+          size="small"
+          type="number"
+          @keyup.native="change"
+          v-model="value"
+          placeholder="请输入内容"
+        ></el-input>
+      </div>
+      <div v-if="renderData.type == 'Enum' || renderData.type == 'Bool'">
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+          size="small"
+          @change="change"
+          filterable
+          style="width:100%;padding-left:15px;"
+        >
+          <el-option
+            v-for="item in renderData.dataSource"
+            :key="item.Code"
+            :label="item.Name"
+            :value="item.Code"
+          ></el-option>
+        </el-select>
+      </div>
+    </div>
+    <div class="saga-button saga-item" v-if="!isCreated">
+      <div v-if="!!renderData.oldValue && renderData.oldValue != value">
+        <el-button
+          @click="oldToNew"
+          style="width:100%;"
+          size="small"
+          type="info"
+        >《 更新值为: “{{renderData.oldValue}}”</el-button>
+      </div>
+      <div v-else>{{renderData.oldValue == value ? "资产中的值与厂商库中的值相同" : "无可用的新值"}}</div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    renderData: {
+      type: [Object],
+      default: function () {
+        return {}
+      },
+    },
+    isCreated: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      value: ""
+    }
+  },
+  created() {
+    this.value = this.renderData.value
+  },
+  mounted() { },
+  methods: {
+    change() {
+      this.renderData.value = this.value
+    },
+    oldToNew() {
+      this.renderData.value = this.renderData.oldValue
+      this.value = this.renderData.oldValue
+    }
+  },
+  watch: {
+    renderData: {
+      deep: true,
+      handler: function () {
+        this.value = this.renderData.value
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.saga-fill {
+  display: flex;
+  margin: 10px 0;
+  .saga-item {
+    line-height: 30px;
+  }
+  .saga-label {
+    flex-grow: 5;
+    width: 80px;
+    text-align: right;
+  }
+  .saga-input {
+    flex-grow: 5;
+  }
+  .saga-button {
+    flex-grow: 6;
+    width: 150px;
+  }
+}
+input[type="number"]::-webkit-outer-spin-button,
+input[type="number"]::-webkit-inner-spin-button {
+  -webkit-appearance: none !important;
+  margin: 0;
+}
+
+input[type="number"] {
+  -moz-appearance: textfield;
+}
+</style>

+ 9 - 0
src/components/buildData/findId.js

@@ -0,0 +1,9 @@
+import { physics } from '@/api/config'
+import http from '@/api/httpUtil'
+
+function getVenderRecommend(param, success) {
+    let url = `${physics}/venders/basic/recommend`
+    http.postJson(url, param, success)
+}
+
+export default getVenderRecommend

+ 493 - 0
src/components/buildData/recommend.vue

@@ -0,0 +1,493 @@
+<template>
+  <div class="saga-recommend">
+    <div v-if="hasData">
+      <h4>当前资产:{{fm.FmName}}</h4>
+      <div class="saga-change-name" v-if="!isChangeFor">
+        <h3 class="saga-gray saga-explain">您可能需要快捷改值操作</h3>
+        <!-- 智能推荐按钮 -->
+        <div v-if="isChangeId">
+          <template v-if="changeList.length" v-for="item in changeList">
+            <saga-button @click="getList(item)">修正 "{{getName(key)}}" 为 {{item.value}}</saga-button>
+          </template>
+          <template v-if="!changeList.length">
+            <p>{{changeMsg}}</p>
+          </template>
+        </div>
+        <!-- 修正按钮 -->
+        <div v-else>
+          <saga-button @click="changeToNull">修正 "{{getName(key)}}" 为 {{noIdChangeVal}}</saga-button>
+        </div>
+      </div>
+      <div class="saga-change-name" v-if="!isSameForCreate">
+        <h3 class="saga-gray saga-explain">您可能需要快捷维护厂商库</h3>
+        <template>
+          <saga-button
+            v-if="!isChangeVender"
+            @click="create"
+          >增加 {{obj.name}} “ {{fm.Infos[key] || ""}} ”</saga-button>
+          <saga-button v-if="isChangeVender" @click="changeVender">更新厂商库中此{{obj.name}}对应值</saga-button>
+        </template>
+        <!-- <template v-else>
+          <p>{{ !!message ? message : "请确定该信息点内有值"}}</p>
+        </template>-->
+      </div>
+      <div class="saga-change-name">
+        <h3 class="saga-gray saga-explain">您可能需要其他快捷操作</h3>
+        <!-- <saga-button @click="checkVenders">先维护 xxx 信息点</saga-button> -->
+        <saga-button @click="checkVenders" v-if="showBtn">批量维护 {{!!obj ? obj.name : ""}} 相关信息点</saga-button>
+        <saga-button v-if="!showBtn">先维护 {{!!obj ? obj.name : ""}} 信息点</saga-button>
+        <!-- <saga-button @click="checkVenders"></saga-button> -->
+      </div>
+    </div>
+    <div v-else class="saga-message">
+      <p>{{!!dataMessage ? dataMessage : "请确定该信息点是支持推荐的信息点"}}</p>
+    </div>
+    <venders-change
+      :create="isCreate"
+      v-if="dialog.visible"
+      ref="venders"
+      :dialog="dialog"
+      :infosKey="infosKey"
+      :types="types"
+      :fmData="fm"
+      @change="loadFm"
+      :title="isCreate ? '添加' + obj.name : '修改' + obj.name"
+    ></venders-change>
+  </div>
+</template>
+<script>
+import sagaButton from "./sagaButton"
+import vendersChange from "./vendersChange"
+import getVenderRecommend from "./findId"
+import tools from "@/assets/js/tools"
+import getJson from "@/utils/buildData/vendersUtils"
+import buildJson from "@/utils/buildData/buildJson"
+import cutHeader from "@/utils/cutHeader"
+import {
+  upDateTableMain
+} from "@/api/request"
+export default {
+  components: {
+    sagaButton,
+    vendersChange
+  },
+  data() {
+    return {
+      hasData: false,
+      fm: {},
+      infosKey: null,
+      dialog: {
+        visible: false
+      },
+      createList: [],
+      changeList: [],
+      types: {},
+      headers: [],
+      message: "",
+      obj: {},
+      key: "",
+      isCreate: false,
+      showBtn: false,
+      createShow: false,
+      changeMsg: "", //修改的提示
+      dataMessage: "⬅请点击资产信息点",
+      falg: false,//上级页面传入的数值,用于实时请求
+      val: null,//上级传入的val
+      isSameForCreate: false,
+      isChangeFor: false,
+      isChangeVender: false,
+      isChangeId: true,//是否为修改id
+      noIdChangeVal: ""
+    }
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    //主页面重新加载
+    loadFm() {
+      this.$emit("loadData")
+    },
+    //根据id获得信息点名称
+    getName(code) {
+      if (!!code) {
+        let name = ""
+        this.headers.map(item => {
+          if (item.InfoPointCode == code) {
+            name = item.InfoPointName
+          }
+        })
+        return name
+      } else {
+        return ""
+      }
+    },
+    //修改
+    checkVenders() {
+      this.isCreate = false
+      this.dialog.visible = true
+      this.$nextTick(_ => {
+        this.$refs.venders.getData()
+      })
+    },
+    //获取表头
+    changeObj() {
+      buildJson.map(item => {
+        if (item.name == "型号") {
+          item.options = []
+          item.infosArr = []
+          this.headers.map(child => {
+            if (child.FirstTag == "技术参数" ||
+              child.InfoPointCode == "Specification" ||
+              child.InfoPointCode == "MaintainPeriod" ||
+              child.InfoPointCode == "ServiceLife") {
+              item.infosArr.push(child.InfoPointCode)
+              let option = {
+                key: "contact.infos." + child.InfoPointCode,
+                label: child.InfoPointName,
+                optLabel: child.InfoPointCode,
+                type: child.DataType,
+                dataSource: child.DataSource,
+                FirstTag: child.FirstTag,
+                SecondTag: child.SecondTag
+              }
+              if (child.InfoPointCode == "Specification") {
+                option.key = "content.specificationName"
+              }
+              item.options.push(option)
+            }
+          })
+          item.options = cutHeader(item.options)
+        }
+      })
+    },
+
+    changeToNull() {
+      let param = {
+        FmId: this.fm.FmId,
+        Infos: {
+          [this.key]: null
+        }
+      }
+      this.updateMain(param)
+    },
+
+    //上级页面传输的数据
+    randerData(idData, infosKey, headers, falg = false, val = null) {
+      this.isChangeVender = false
+      this.falg = falg
+      this.val = val
+      this.fm = tools.deepCopyObj(idData)
+      this.headers = headers
+      this.changeObj()
+      this.infosKey = infosKey
+      this.message = ""
+      this.key = infosKey.split(".")[1]
+      this.obj = getJson(this.infosKey.split(".")[1])
+      console.log(this.obj)
+      if (!!this.obj) {
+        this.hasData = true
+        this.getDataForm()
+      } else {
+        this.hasData = false
+      }
+    },
+
+    changeVender() {
+      // 修改厂商库中对应的值
+      console.log("修改厂商库中的值", this.obj, this.key)
+      let webArr = ["SupplierWeb", "InsurerWeb", "MaintainerWeb"],
+        //三大厂商的key
+        keysArr = ["DPInsurerID", "DPSupplierID", "DPMaintainerID"]
+      //如果是三大厂商的网址
+      if (webArr.indexOf(this.key) > -1) {
+        console.log("三大网址")
+        let param = {
+          venderId: this.fm.Infos[this.obj.infosKey],
+          website: this.fm.Infos[this.key]
+        }
+        console.log(param, "param")
+        this.obj.updateVender(param, res => {
+          this.loadFm()
+        })
+        return false
+      } else if (keysArr.indexOf(this.obj.infosKey) > -1) {
+        console.log("三大厂商的联系人")
+        let param = {
+          venderId: this.fm.Infos[this.obj.infosKey],
+          projectId: this.$route.query.projId,
+          [this.getKey(this.obj.options, this.key)]: this.fm.Infos[this.key]
+        }
+        console.log(param, "param")
+        this.obj.update(param, res => {
+          this.loadFm()
+        })
+        return false
+      } else {
+        console.log("型号")
+        let param = {
+          specificationId: this.fm.Infos.DPSpecificationID,
+          infos: {
+            [this.key]: this.fm.Infos[this.key]
+          }
+        }
+        console.log(param, "param")
+        this.obj.updateVenderSpecification(param, res => {
+          this.loadFm()
+        })
+        return false
+      }
+    },
+
+    /**
+     * @param arr 传入的数组
+     * @param key 传入的key
+     * 
+     * @return key 对应的key
+     */
+    getKey(arr, key) {
+      let returnKey = ""
+      arr.map(item => {
+        if (item.optLabel == key) {
+          returnKey = item.key.split(".")[1]
+          console.log(returnKey, item, "item")
+        }
+      })
+      return returnKey
+    },
+
+
+    //有obj的信息时
+    getDataForm() {
+      let idArr = ["DPManufacturerID", "DPSupplierID", "DPInsurerID", "DPMaintainerID", "DPSpecificationID", "DPBrandID", "DPSpecificationID"]
+      //点击以下按钮触发按钮事件
+      let vendersArr = ["Manufacturer", "Supplier", "Maintainer", "Insurer", "Brand", "Specification"]
+      if (!!this.fm.Infos[this.obj.infosKey]) {
+        this.falgChange(true)
+      } else {
+        this.falgChange(false)
+      }
+    },
+    //falg为是否存在id
+    falgChange(falg) {
+      if (!!this.fm.Infos[this.key]) {
+
+        //存在id且单元格存在值
+        if (falg) {
+          if (this.falg) {
+            this.noIdDo()
+          } else {
+            this.getVendersList()
+          }
+
+        } else {
+          // 没有id
+          this.noIdDo()
+        }
+      } else {
+        //不存在值
+        this.changeList = []
+        this.changeMsg = "请确定该单元格内存在值"
+      }
+    },
+
+    //没有id执行
+    noIdDo() {
+      this.createShow = true
+      this.showBtn = false
+      let param = {
+        infoCode: this.key,
+        infoValue: this.val || this.fm.Infos[this.key]
+      }
+      if (this.key == "Brand") {
+        param.manufacturerID = this.fm.Infos.DPManufacturerID
+      }
+      if (this.key == "Specification") {
+        param.manufacturerID = this.fm.Infos.DPManufacturerID
+        param.brandID = this.fm.Infos.DPBrandID
+        param.eqFamily = this.fm.Family
+      }
+      console.log(this.obj.infosArr[0], this.infosKey, "this.infosKey")
+      if (this.obj.infosArr[0] != this.key) {
+        this.isSameForCreate = true
+        this.isChangeFor = true
+        return false
+      }
+
+      getVenderRecommend(param, res => {
+        this.changeList = res.content || []
+        this.isSameForCreate = false
+        this.isChangeFor = false
+        if (!!this.changeList && this.changeList.length == 1) {
+          if (this.changeList[0].value == this.fm.Infos[this.key]
+            && this.changeList[0].id == this.fm.Infos["DP" + this.key + "ID"]) {
+            this.isSameForCreate = true
+            this.isChangeFor = true
+          }
+        }
+        if (this.changeList.length < 0) {
+          this.changeMsg = "该生产商下不存在符合条件的推荐"
+        }
+      })
+    },
+    //当前单元格内存在id且单元格存在值
+    getVendersList() {
+      //四大厂商名称
+      this.isChangeId = true
+      let venderIdArr = ["DPManufacturerID", "DPSupplierID", "DPInsurerID", "DPMaintainerID", "DPBrandID"],
+        vendersArr = ["Manufacturer", "Supplier", "Maintainer", "Insurer", "Brand"],
+        infosKey = this.obj.infosKey
+      this.showBtn = true
+      //获取label
+      let ownLabel = ""
+      this.obj.options.map(item => {
+        if (item.optLabel == this.key) {
+          ownLabel = item.key
+        }
+      })
+      if (venderIdArr.indexOf(infosKey) > -1) {
+        let param = {
+          venderId: this.fm.Infos[infosKey],
+          projectId: this.$route.query.projId
+        }
+        if (infosKey == "DPBrandID") {
+          param = {
+            brandId: this.fm.Infos[infosKey]
+          }
+        }
+        this.obj.getList(param, res => {
+          console.log(this.key, this.obj.options, res, ownLabel, "ownLabel")
+          let optArr = ownLabel.split("."), optContent = ""
+          if (this.obj.infosKey == "DPBrandID") {
+            optContent = res[optArr[0]][optArr[1]]
+          } else {
+            optContent = res.content[optArr[0]][optArr[1]]
+          }
+          console.log(optContent, this.val, this.fm.Infos[this.key])
+          if (optContent == (this.val || this.fm.Infos[this.key])) {
+            //厂商库中的值与现有的值相等
+            this.isChangeFor = true
+            this.isSameForCreate = true
+          } else {
+            if (!optContent) {
+              //如果厂商库中没有值
+              console.log("没有该信息点")
+              this.isChangeFor = false
+            } else {
+              //有值
+              console.log("有值,且值不同")
+              this.isChangeId = false
+              this.hasData = true
+              //修改的值(其实做置空操作)
+              this.noIdChangeVal = optContent
+              this.isChangeFor = false
+              this.isSameForCreate = false
+              this.isChangeVender = true
+            }
+          }
+        })
+      }
+
+      if (infosKey == "DPSpecificationID") {
+        let paramData = {
+          specificationId: this.fm.Infos[infosKey]
+        }
+        this.obj.getList(paramData, res => {
+          let optContent = res.content.infos[this.key]
+          console.log(optContent, "optContent")
+          if (optContent == (this.val || this.fm.Infos.Specification)) {
+            this.isChangeFor = true
+            this.isSameForCreate = true
+          } else {
+            if (!optContent) {
+              //如果厂商库中没有值
+              console.log("没有该信息点")
+              this.isChangeFor = false
+            } else {
+              //有值
+              console.log("有值,且值不同")
+              this.isChangeId = false
+              this.hasData = true
+              //修改的值(其实做置空操作)
+              this.noIdChangeVal = optContent
+              this.isChangeFor = false
+              this.isSameForCreate = false
+              this.isChangeVender = true
+            }
+          }
+        })
+      }
+
+      if (vendersArr.indexOf(this.key) > -1) {
+        this.showBtn = true
+      }
+    },
+    //创建函数
+    create(item) {
+      this.isCreate = true
+      this.dialog.visible = true
+      this.$nextTick(_ => {
+        this.$refs.venders.getCreateData()
+      })
+    },
+    updateMain(param) {
+      upDateTableMain({
+        ProjId: this.$route.query.projId,
+        UserId: this.$route.query.userId
+      }, [param]).then(res => {
+        if (res.data.Result == "success") {
+          this.loadFm()
+        } else {
+          this.$message.error("保存出错")
+        }
+      })
+    },
+    //点击按钮,对表格操作
+    getList(data) {
+      let param = {
+        FmId: this.fm.FmId,
+        Infos: {
+        }
+      }
+      console.log(this.obj, "obj")
+      param.Infos[this.obj.infosKey] = data.id
+      param.Infos[this.obj.options[0].optLabel] = null
+      if (this.obj.infosKey == "DPManufacturerID") {
+        param.Infos.DPSpecificationID = null
+        param.Infos.DPBrandID = null
+        param.Infos[this.key] = null
+      } else if (this.obj.infosKey == "DPBrandID") {
+        param.Infos.DPSpecificationID = null
+        param.Infos.Brand = data.value
+      } else {
+        param.Infos[this.key] = null
+      }
+      console.log(param)
+      this.updateMain(param)
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.saga-recommend {
+  height: 100%;
+  overflow-y: auto; //   background-color: red;
+  .saga-gray {
+    color: #b7c3c8;
+  }
+  .saga-change-name {
+    padding: 8px;
+    min-height: 100px; // background-color: yellow;
+    border-bottom: 1px solid #ccc;
+    .saga-explain {
+      font-size: 17px;
+      font-weight: 600;
+    }
+  }
+}
+.saga-message {
+  height: 100vh;
+  line-height: 100vh;
+  font-size: 20px;
+  color: #b7c3c8;
+}
+</style>

+ 0 - 0
src/components/buildData/sagaButton.vue


Some files were not shown because too many files changed in this diff