Browse Source

adm:fix> 新版数据字典

jxing 4 years ago
commit
8d6fa16e44
100 changed files with 10230 additions and 0 deletions
  1. 12 0
      .babelrc
  2. 9 0
      .editorconfig
  3. 15 0
      .gitignore
  4. 10 0
      .postcssrc.js
  5. 155 0
      README.md
  6. 45 0
      build/build.js
  7. 56 0
      build/check-versions.js
  8. BIN
      build/logo.png
  9. 100 0
      build/utils.js
  10. 20 0
      build/vue-loader.conf.js
  11. 99 0
      build/webpack.base.conf.js
  12. 93 0
      build/webpack.dev.conf.js
  13. 140 0
      build/webpack.prod.conf.js
  14. 20 0
      config/dev.env.js
  15. 351 0
      config/index.js
  16. 15 0
      config/prod.env.js
  17. 19 0
      index.html
  18. 98 0
      package.json
  19. 40 0
      publish.js
  20. 17 0
      src/App.vue
  21. 205 0
      src/api/alarm/alarm.js
  22. 128 0
      src/api/data_admin/buildTaskApi.js
  23. 10 0
      src/api/database/hbase.js
  24. 12 0
      src/api/database/redis.js
  25. 72 0
      src/api/fm/rules.js
  26. 83 0
      src/api/fm/sop.js
  27. 111 0
      src/api/framework.js
  28. 100 0
      src/api/httputils.js
  29. 347 0
      src/api/model/file.js
  30. 29 0
      src/api/model/report.js
  31. 56 0
      src/api/msgsever.js
  32. 177 0
      src/api/relation/api.js
  33. 22 0
      src/api/scan/config.js
  34. 41 0
      src/api/scan/fetch.js
  35. 99 0
      src/api/scan/httpUtil.js
  36. 14 0
      src/api/scan/newRequest.js
  37. 2281 0
      src/api/scan/request.js
  38. 6 0
      src/api/system/admin.js
  39. 21 0
      src/api/system/role.js
  40. 15 0
      src/api/system/user.js
  41. 14 0
      src/api/topo/index.js
  42. 30 0
      src/api/uploader/index.js
  43. BIN
      src/assets/css/chosen-sprite.png
  44. BIN
      src/assets/css/chosen-sprite@2x.png
  45. 492 0
      src/assets/css/chosen.css
  46. 477 0
      src/assets/css/jsmind.css
  47. 44 0
      src/assets/graphy/SGraphy/SCanvas.js
  48. 30 0
      src/assets/graphy/SGraphy/SGraphyEnums.js
  49. 396 0
      src/assets/graphy/SGraphy/SGraphyItem.js
  50. 201 0
      src/assets/graphy/SGraphy/SGraphyScene.js
  51. 280 0
      src/assets/graphy/SGraphy/SGraphyView.js
  52. 53 0
      src/assets/graphy/SGraphy/SMouseEvent.js
  53. 0 0
      src/assets/graphy/SGraphy/dataType.js
  54. 78 0
      src/assets/graphy/SGraphy/dataType.ts
  55. 70 0
      src/assets/graphy/SGraphy/items/SGraphyCircleItem.js
  56. 201 0
      src/assets/graphy/SGraphy/items/SGraphyClockItem.js
  57. 59 0
      src/assets/graphy/SGraphy/items/SGraphyImageItem.js
  58. 66 0
      src/assets/graphy/SGraphy/items/SGraphyLineItem.js
  59. 76 0
      src/assets/graphy/SGraphy/items/SGraphyPillarItems.js
  60. 257 0
      src/assets/graphy/SGraphy/items/SGraphyPolygonItem.js
  61. 100 0
      src/assets/graphy/SGraphy/items/SGraphyRectItem.js
  62. 51 0
      src/assets/graphy/SGraphy/items/SGraphyTextItems.js
  63. 66 0
      src/assets/graphy/SGraphy/items/SGraphyVirtualItem.js
  64. 240 0
      src/assets/graphy/SGraphy/mainScene.js
  65. 228 0
      src/assets/graphy/SGraphy/mainScene.ts
  66. 68 0
      src/assets/graphy/SGraphy/newItems/SGraphyCircleItem.js
  67. 65 0
      src/assets/graphy/SGraphy/newItems/SGraphyCircleItem.ts
  68. 111 0
      src/assets/graphy/SGraphy/newItems/SGraphyImgItem.js
  69. 116 0
      src/assets/graphy/SGraphy/newItems/SGraphyImgItem.ts
  70. 70 0
      src/assets/graphy/SGraphy/newItems/SGraphyPointItem.js
  71. 67 0
      src/assets/graphy/SGraphy/newItems/SGraphyPointItem.ts
  72. 212 0
      src/assets/graphy/SGraphy/newItems/SGraphyPolygonItem.js
  73. 220 0
      src/assets/graphy/SGraphy/newItems/SGraphyPolygonItem.ts
  74. 74 0
      src/assets/graphy/SGraphy/newItems/SGraphyRectItem.js
  75. 76 0
      src/assets/graphy/SGraphy/newItems/SGraphyRectItem.ts
  76. 92 0
      src/assets/graphy/SGraphy/newItems/SGraphyWallItem.js
  77. 89 0
      src/assets/graphy/SGraphy/newItems/SGraphyWallItem.ts
  78. 40 0
      src/assets/graphy/SGraphy/types/SPoint.js
  79. 169 0
      src/assets/graphy/SGraphy/types/SRect.js
  80. 25 0
      src/assets/graphy/SGraphy/until/pako.js
  81. 27 0
      src/assets/graphy/SGraphy/until/pako.ts
  82. 22 0
      src/assets/graphy/SGraphy/until/tool.js
  83. 21 0
      src/assets/graphy/SGraphy/until/tool.ts
  84. 14 0
      src/assets/graphy/index.js
  85. BIN
      src/assets/image/floorBG.png
  86. BIN
      src/assets/image/model/arrowBlue.png
  87. BIN
      src/assets/image/model/arrowGray.png
  88. BIN
      src/assets/image/model/arrowGreen.png
  89. BIN
      src/assets/image/model/columnBlue.png
  90. BIN
      src/assets/image/model/columnGray.png
  91. BIN
      src/assets/image/model/columnGreen.png
  92. BIN
      src/assets/image/model/delModelBlue.png
  93. BIN
      src/assets/image/model/delModelGray.png
  94. BIN
      src/assets/image/model/downJsonBlue.png
  95. BIN
      src/assets/image/model/downJsonGray.png
  96. BIN
      src/assets/image/model/downJsonGreen.png
  97. BIN
      src/assets/image/model/downModelBlue.png
  98. BIN
      src/assets/image/model/downModelGray.png
  99. BIN
      src/assets/image/model/downModelGreen.png
  100. 0 0
      src/assets/image/model/rightDownBlue.png

+ 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

+ 15 - 0
.gitignore

@@ -0,0 +1,15 @@
+.DS_Store
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+package-lock.json*
+
+# 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": {}
+  }
+}

+ 155 - 0
README.md

@@ -0,0 +1,155 @@
+# sagacloud-admin
+
+> A Vue.js project
+
+## Build Setup
+
+```bash
+npm install
+npm install vuex axios element-ui echarts font-awesome
+npm install less less-loader node-sass sass-loader --save-dev
+
+# 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
+```
+
+## 项目结构说明
+
+#### 目录结构
+
+```
+│  .editorconfig                        # 格式化配置,修改缩进为2
+│  index.html                           # 修改页面title
+│  package.json                         # 包
+│  README.md                            # 说明文档
+│
+├─build                                 # 不变
+│
+├─config
+│      dev.env.js                       # 开发环境变量
+│      index.js                         # 设置代理
+│      prod.env.js                      # 生产环境变量
+│
+├─src
+│  ├─api                                # 业务逻辑api, http的请求都放在这里
+│  │  |─framework.js                    # 框架预留接口,实现登录,权限校验等功能
+│  │  └─httputils.js                    # http 工具类
+│  ├─assets                             # 静态资源, 替换logo图片
+│  ├─components                         # 业务相关组件
+│  ├─data                               # 业务相关静态数据
+│  │      menus.js                      # 菜单数据
+│  ├─demo                               # Demo主目录
+│  │  │  demo-menus.js                  # Demo按钮
+│  │  │  demo-routes.js                 # Demo路由
+│  │  └─views                           # Demo页面
+│  ├─framework                          # 框架主目录
+│  │  ├─components                      # 业务无关组件
+│  │  │
+│  │  ├─demo                            # Demo主目录
+│  │  │  │  demo-menus.js               # Demo按钮
+│  │  │  │  demo-routes.js              # Demo路由
+│  │  │  └─views                        # Demo页面
+│  │  │
+│  │  ├─layout                          # 框架主目录
+│  │  │      layout-store.js            # 框架状态定义
+│  │  │      Login.vue                  # 登录页
+│  │  │      Main.vue                   # 框架主页
+│  │  │      PageHeader.vue             # 顶部栏
+│  │  │      PageSidebar.vue            # 左侧菜单栏
+│  │  │
+│  │  ├─plugins                         # 插件,业务无关
+│  │  │      components.js
+│  │  ├─style                           # 样式
+│  │  │
+│  │  ├─template                        # 页面模板
+│  │  │      TablePageTemplate.vue
+│  │  │
+│  │  └─utils                           # 工具类,业务无关
+│  │
+│  ├─router                             # 主路由
+│  │      index.js
+│  │      system.js
+│  │
+│  ├─store                              # vuex
+│  │      index.js
+│  │
+│  └─views                              # 业务页面主路径
+|
+└─static
+        .gitkeep
+```
+
+#### /api/framework.js
+
+必须实现以下方法
+
+```
+export default {
+
+    // 路由拦截
+    routerBeforeEach: async function(to, from, next){},
+
+    // 获取左侧菜单数据
+    getMenus: function(permissions){},
+
+    // 跳转到登录页面
+    toLoginPage: function(){},
+
+    // 登录接口
+    login: function(username, password){}
+
+    // 加载当前登录用户信息
+    loadUserInfo: function(){},
+
+    // 退出登录
+    toLogout: function(){}
+}
+
+```
+
+#### 工具类说明
+
+/src/utils/basicutils.js
+
+```
+    formatDateByPattern(date, pattern) // 日期格式化
+    indexInArray(arr, key, val)        // 找出数组arr中第一个属性key的值等于val的元素的下标
+    itemInArray(arr, key, val)         // 找出数组arr中第一个属性key的值等于val的元素
+    deleteInArray(arr, key, val)       // 从数组中将属性key的值等于val的所有元素删除
+```
+
+/src/api/httputils.js // 一般在服务端接口 API 中使用,不建议在别的地方使用,有授权标记
+
+```
+    getCookie(name)                    // 获取cookie值
+    getJson(url, params)               // 发送GET请求
+    postJson(url, data)                // 发送POST请求
+```
+
+/src/utils/storage.js
+
+```
+    set(key, value, fn)                // 在浏览器缓存中设置数据, 如果value是对象会转化成json
+    get(key, fn)                       // 在浏览器缓存中取出数据, 取出数据后会尝试js对象返回
+    remove(key)                        // 在浏览器缓存中删除数据
+```
+
+#### 设置面包屑方法
+
+```
+在路由router中配置meta.breadcrumbs,在进入路由页面时会自动解析为面包屑
+this.$store.dispatch('setBreadcrumb', [{ label: 'Demo' }, { label: 'Form'  ])
+this.$store.dispatch('setBreadcrumb', [{ label: 'Demo', path: '' }, { label: 'Form' , path: ''}])
+```
+#### 上传管理器调用方法(上传较大文件时使用)
+
+```
+在组件中引入Bus中央时间总线
+    Bus.$emit('openUploader', query, file)    //添加文件到上传管理器中, query为参数, file为H5原生的文件对象
+    Bus.$on('fileAdded', () => {})            //文件选择后的回调
+    Bus.$on('fileSuccess', () => {})          //文件上传成功后的回调
+```

+ 45 - 0
build/build.js

@@ -0,0 +1,45 @@
+'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"
+            )
+        )
+    })
+})

+ 56 - 0
build/check-versions.js

@@ -0,0 +1,56 @@
+'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


+ 100 - 0
build/utils.js

@@ -0,0 +1,100 @@
+'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')
+        })
+    }
+}

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

@@ -0,0 +1,20 @@
+'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'
+    }
+}

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

@@ -0,0 +1,99 @@
+'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: ['.ts', '.js', '.vue', '.json'],
+        alias: {
+            'vue$': 'vue/dist/vue.esm.js',
+            '@': resolve('src'),
+            'jquery': 'jquery',
+        }
+    },
+    // 增加一个plugins
+    plugins: [
+        new webpack.ProvidePlugin({
+            $: "jquery",
+            jQuery: "jquery"
+        })
+    ],
+    module: {
+        rules: [
+            {
+                test: /\.vue$/,
+                loader: 'vue-loader',
+                options: vueLoaderConfig
+            },
+            {
+                test: /\.tsx?$/,
+                loader: 'ts-loader',
+                exclude: /node_modules/,
+                options: {
+                  appendTsSuffixTo: [/\.vue$/],
+                }
+            },
+            {
+                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'
+    }
+}

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

@@ -0,0 +1,93 @@
+'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,
+            favicon: path.resolve(__dirname, '../static/favicon.ico')
+        }),
+        // 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',
+            favicon: path.resolve(__dirname, '../static/favicon.ico')
+        }),
+        // 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

+ 20 - 0
config/dev.env.js

@@ -0,0 +1,20 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+  NODE_ENV: '"development"',
+  BASE_URL: '"http://172.16.44.215"', //测试iframe地址
+  SSO_SERVER: '"http://172.16.44.235:8081"', //测试环境
+  // BASE_URL: '"http://192.168.20.236"', //(新)测试iframe地址
+  // SSO_SERVER: '"http://192.168.20.236:8086"', //(新)测试环境
+  MQTT_SERVICE: '"ws://172.16.42.210:61614/stomp/"' //MQ测试环境地址
+  // SSO_SERVER: '"http://sso.sagacloud.cn"',  //正式环境
+  // BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
+ // MQTT_SERVICE: '"ws://adm.sagacloud.cn/stomp/"' //MQ正式环境地址
+})
+
+
+
+
+

+ 351 - 0
config/index.js

@@ -0,0 +1,351 @@
+'use strict'
+// Template version: 1.3.1
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+module.exports = {
+  dev: {
+    // Paths
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+
+    // proxyTable: {//正式环境
+    //   '/admin': {
+    //     target: 'http://mbi.sagacloud.cn:8080',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/admin": "/"
+    //     }
+    //   },
+    //   '/api': {
+    //     target: 'http://mbi.sagacloud.cn:8080',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/api": "/"
+    //     }
+    //   },
+    //   '/data-platform-3': {
+    //     // 目标 API 地址
+    //     target: 'http://api.sagacloud.cn/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/business-space': {
+    //     // 目标 API 地址
+    //     target: 'http://api.sagacloud.cn',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/business-space": "/dp-auxiliary/business-space/"
+    //     }
+    //   },
+    //   '/pointconfig': {
+    //     // 目标 API 地址
+    //     target: 'http://mbi.sagacloud.cn:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/venders-dp': {
+    //     // 目标 API 地址
+    //     target: 'http://api.sagacloud.cn',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/venders-dp": "/dp-auxiliary/venders-dp/"
+    //     }
+    //   },
+    //   '/venders': {
+    //     // 目标 API 地址
+    //     target: 'http://api.sagacloud.cn',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/venders": "/dp-auxiliary/venders/"
+    //     }
+    //   },
+    //   '/ScanBuilding': {
+    //     // 目标 API 地址
+    //     target: 'http://mbi.sagacloud.cn:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/scanbuilding-2': {
+    //     // 目标 API 地址
+    //     target: 'http://mbi.sagacloud.cn:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/image-service': {
+    //     // 目标 API 地址
+    //     target: 'http://api.sagacloud.cn',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/image-service": "/dp-auxiliary/image-service/"
+    //     }
+    //   },
+    //   '/modelapi': {
+    //     target: 'http://mbi.sagacloud.cn:8080',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/modelapi": "/revit-algorithm/"
+    //     }
+    //   },
+    //   '/schedulerapi': {
+    //     target: 'http://mbi.sagacloud.cn:8080',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //         "^/schedulerapi": "/scheduler/"
+    //     }
+    //   },
+    // },
+
+    // proxyTable: {  //235测试环境
+    //   '/admin': {
+    //     target: 'http://172.16.44.235:8080',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/admin": "/"
+    //     }
+    //   },
+    //   '/api': {
+    //     target: 'http://172.16.44.235:8080',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/api": "/"
+    //     }
+    //   },
+    //   '/data-platform-3': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.42.210:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/business-space': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.42.210:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/pointconfig': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.44.235:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/venders-dp': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.42.210:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/venders': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.42.210:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/ScanBuilding': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.44.235:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/scanbuilding-2': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.44.235:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/image-service': {
+    //     // 目标 API 地址
+    //     target: 'http://172.16.42.210:8080/',
+    //     // 如果要代理 websockets
+    //     ws: true,
+    //     // 将主机标头的原点更改为目标URL
+    //     changeOrigin: false
+    //   },
+    //   '/modelapi': {
+    //     target: 'http://172.16.42.210:8082',
+    //     // target: 'http://192.168.20.218:8082',//景灏
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/modelapi": "/"
+    //     }
+    //   },
+    //   '/schedulerapi': {
+    //     target: 'http://172.16.42.210:8081',
+    //     changeOrigin: true,
+    //     pathRewrite: {
+    //       "^/schedulerapi": "/"
+    //     }
+    //   },
+    // },
+    proxyTable: { // 新版数据字典
+      '/admin': {
+        target: 'http://172.16.44.235:8080',
+        changeOrigin: true,
+        pathRewrite: {
+          "^/admin": "/"
+        }
+      },
+      '/api': {
+        target: 'http://39.102.40.239:8080',
+        changeOrigin: true,
+        pathRewrite: {
+          "^/api": "/"
+        }
+      },
+      '/data-platform-3': {
+        // 目标 API 地址
+        target: 'http://172.16.42.210:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/business-space': {
+        // 目标 API 地址
+        target: 'http://172.16.42.210:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/pointconfig': {
+        // 目标 API 地址
+        target: 'http://172.16.44.235:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/venders-dp': {
+        // 目标 API 地址
+        target: 'http://172.16.42.210:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/venders': {
+        // 目标 API 地址
+        target: 'http://172.16.42.210:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/ScanBuilding': {
+        // 目标 API 地址
+        target: 'http://172.16.44.235:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/scanbuilding-2': {
+        // 目标 API 地址
+        target: 'http://172.16.44.235:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/image-service': {
+        // 目标 API 地址
+        target: 'http://172.16.42.210:8080/',
+        // 如果要代理 websockets
+        ws: true,
+        // 将主机标头的原点更改为目标URL
+        changeOrigin: false
+      },
+      '/modelapi': {
+        target: 'http://172.16.42.210:8082',
+        // target: 'http://192.168.20.218:8082',//景灏
+        changeOrigin: true,
+        pathRewrite: {
+          "^/modelapi": "/"
+        }
+      },
+      '/schedulerapi': {
+        target: 'http://172.16.42.210:8081',
+        changeOrigin: true,
+        pathRewrite: {
+          "^/schedulerapi": "/"
+        }
+      },
+    },
+    // Various Dev Server settings
+    host: '0.0.0.0', // can be overwritten by process.env.HOST
+    port: 28080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    autoOpenBrowser: false,
+    errorOverlay: true,
+    notifyOnErrors: true,
+    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+    /**
+     * Source Maps
+     */
+
+    // 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: false,
+    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
+  }
+}

+ 15 - 0
config/prod.env.js

@@ -0,0 +1,15 @@
+'use strict'
+module.exports = {
+  NODE_ENV: '"production"',
+  BASE_URL: '"http://172.16.44.215"', //测试iframe地址
+  SSO_SERVER: '"http://172.16.44.235:8081"', //测试环境
+  // BASE_URL: '"http://192.168.20.236"', //(新)测试iframe地址
+  // SSO_SERVER: '"http://192.168.20.236:8086"', //(新)测试环境
+  MQTT_SERVICE: '"ws://172.16.42.210:61614/stomp/"' //MQ测试环境地址
+  // BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
+  // SSO_SERVER: '"http://sso.sagacloud.cn"',  //正式环境
+  //  MQTT_SERVICE: '"ws://adm.sagacloud.cn/stomp/"' //MQ正式环境地址
+  // BASE_URL: '"http://182.92.126.202"', //线上iframe地址(龙湖)
+  // SSO_SERVER: '"http://182.92.126.202:8889"',  //正式环境(龙湖)
+  // MQTT_SERVICE: '"ws://182.92.126.202:61614/stomp/"' //MQ正式环境地址(龙湖)
+}

+ 19 - 0
index.html

@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <meta charset="utf-8"/>
+  <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
+  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
+  <meta http-equiv="Cache" content="no-cache">
+  <meta http-equiv="Pragma" content="no-cache"/>
+  <meta http-equiv="Expires" content="0"/>
+  <link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_1318214_i7toym6dora.css">
+  <title>sagacloud-admin</title>
+</head>
+
+<body>
+    <div id="app"></div>
+</body>
+
+</html>

+ 98 - 0
package.json

@@ -0,0 +1,98 @@
+{
+  "name": "sagacloud-admin",
+  "version": "1.0.0",
+  "description": "A Vue.js project",
+  "author": "yaoll <yaolinlin@sagacloud.cn>",
+  "private": true,
+  "remote": {
+    "host": "192.168.20.236",
+    "path": "/opt/nginx/ibms/dist",
+    "user": "root",
+    "password": "saga",
+    "local": "dist"
+  },
+  "scripts": {
+    "i": "npm install",
+    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+    "start": "npm run dev",
+    "build": "node build/build.js",
+    "publish": "node publish.js"
+  },
+  "dependencies": {
+    "@saga-web/base": "2.1.9",
+    "@saga-web/cad-engine": "2.0.567",
+    "@saga-web/draw": "2.1.80",
+    "@saga-web/graphy": "2.1.52",
+    "@saga-web/topology": "1.0.83",
+    "axios": "^0.18.0",
+    "echarts": "^4.1.0",
+    "el-cascader-multi": "^1.1.8",
+    "element-ui": "^2.13.2",
+    "font-awesome": "^4.7.0",
+    "handsontable-pro": "^3.0.0",
+    "jquery": "^3.3.1",
+    "vue": "^2.5.2",
+    "vue-axios": "^2.1.4",
+    "vue-router": "^3.0.1",
+    "vuex": "^3.1.0"
+  },
+  "devDependencies": {
+    "ajv": "^6.9.1",
+    "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",
+    "copy-webpack-plugin": "^4.0.1",
+    "css-loader": "^0.28.0",
+    "extract-text-webpack-plugin": "^3.0.0",
+    "file-loader": "^1.1.4",
+    "file-saver": "^2.0.2",
+    "friendly-errors-webpack-plugin": "^1.6.1",
+    "html-webpack-plugin": "^2.30.1",
+    "less": "^3.9.0",
+    "less-loader": "^4.1.0",
+    "moment": "^2.29.0",
+    "node-notifier": "^5.1.2",
+    "node-sass": "^4.14.1",
+    "node-ssh": "^6.0.0",
+    "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",
+    "sass-loader": "^7.1.0",
+    "semver": "^5.3.0",
+    "shelljs": "^0.7.6",
+    "spark-md5": "^3.0.0",
+    "stompjs": "^2.3.3",
+    "swiper": "^4.0.0",
+    "uglifyjs-webpack-plugin": "^1.1.1",
+    "url-loader": "^0.5.8",
+    "vue-loader": "^13.3.0",
+    "vue-simple-uploader": "^0.7.4",
+    "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",
+    "xlsx": "^0.15.1"
+  },
+  "engines": {
+    "node": ">= 6.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 40 - 0
publish.js

@@ -0,0 +1,40 @@
+/*
+ * @Author: zhangyu
+ * @Date: 2019-12-18 16:18:30
+ * @Info: 自动化部署
+ * @LastEditTime : 2020-02-11 17:47:56
+ */
+
+const Client = require("node-ssh");
+const ssh = new Client(); 
+
+ssh.connect({
+  host: process.env.npm_package_remote_host,
+  port: "22",
+  // privateKey: `${process.env.HOME}\\.ssh\\id_rsa_2048`,
+  username: process.env.npm_package_remote_user,
+  password: process.env.npm_package_remote_password
+}).then(() => {
+  const failedList = [];
+  ssh.putDirectory(
+    process.env.npm_package_remote_local,
+    process.env.npm_package_remote_path,
+    {
+      recursive: true,
+      concurrency: 1,
+      tick: function(localPath, remotePath, error) {
+        if (error) {
+          failedList.push(localPath);
+        }
+      }
+    }
+  ).then(status => {
+    if (failedList.length > 0) {
+      console.log("发布失败");
+      console.log("failed transfers", failedList.join(", "));
+    } else {
+      console.log(status ? "发布成功" : "发布失败");
+    }
+    ssh.dispose();
+  });
+});

+ 17 - 0
src/App.vue

@@ -0,0 +1,17 @@
+<template>
+    <div id='app'>
+        <router-view/>
+        <global-uploader></global-uploader>
+    </div>
+</template>
+
+<script>
+import globalUploader from '@/components/globaluploader'
+
+export default {
+    name: 'App',
+    components: {
+        globalUploader
+    },
+}
+</script>

+ 205 - 0
src/api/alarm/alarm.js

@@ -0,0 +1,205 @@
+/**
+@author:fugy
+@date:2019.1.10
+@info:alarm-api
+ */
+import httputils from '@/utils/httputils'
+
+const api = {
+    //获取对象类型
+    getObjectType() {
+        return new Promise((resolve, reject) => {
+            httputils.getJson(
+                '/server/dataplatform/dict/query/equipment_all',
+                null,
+                res => {
+                    if (res.result === 'success') {
+                        let dataArr = res.data
+                        objTypeArr = []
+                        let sysArr = []
+                        let devArr = []
+                        dataArr.forEach(item => {
+                            objTypeArr.push(item)
+                            let sysObj = {
+                                label: item.name,
+                                value: item.code,
+                                type: item.type
+                            }
+                            let devObj = {
+                                label: item.name,
+                                value: item.code,
+                                type: item.type
+                            }
+                            if (item.content) {
+                                sysObj.children = []
+                                devObj.children = []
+                                item.content.forEach(ele => {
+                                    objTypeArr.push(ele)
+                                    let sysObj1 = {
+                                        label: ele.name,
+                                        value: ele.code,
+                                        type: ele.type
+                                    }
+                                    let devObj1 = {
+                                        label: ele.name,
+                                        value: ele.code,
+                                        type: ele.type
+                                    }
+                                    if (ele.content) {
+                                        devObj1.children = []
+                                        ele.content.forEach(strip => {
+                                            objTypeArr.push(strip)
+                                            let devObj2 = {
+                                                label: strip.name,
+                                                value: strip.code,
+                                                type: strip.type
+                                            }
+                                            devObj1.children.push(devObj2)
+                                        })
+                                    } else {
+                                        devObj1 = {
+                                            label: ele.name,
+                                            value: ele.code,
+                                            type: ele.type,
+                                            disabled: true
+                                        }
+                                    }
+                                    sysObj.children.push(sysObj1)
+                                    devObj.children.push(devObj1)
+                                })
+                            }
+                            sysArr.push(sysObj)
+                            devArr.push(devObj)
+                        })
+                        let resObj = {
+                            sysArr,
+                            devArr
+                        }
+                        objTypeDevArr = devArr
+                        resolve(resObj)
+                    } else {
+                        reject('fail')
+                    }
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 获取对象类的改造成一个整的数组
+    getObjTypeNameFromCode(objType, category, spaceNameObj) {
+        if (objType == 'building') {
+            return { name: '建筑' }
+        } else if (objType == 'floor') {
+            return { name: '楼层' }
+        } else if (objType == 'space') {
+            let name
+            if (category) {
+                name = spaceNameObj[category]
+            } else {
+                name = '空间'
+            }
+
+            return { name: name }
+        } else {
+            let arr = objTypeArr.filter((ele, index) => {
+                return ele.code == category
+            })
+            if (arr.length) {
+                return arr[0]
+            } else {
+                return { name: '---' }
+            }
+        }
+    },
+    // 获取对象类中的空间级联
+    getObjTypeSpace() {
+        return new Promise((resolve, reject) => {
+            httputils.getJson('/server/dataplatform/dict/query/space', {}, res => {
+                if (res.result == "success") {
+                    resolve(res.data)
+                } else {
+                    resolve([])
+                }
+            })
+        })
+    },
+    // 获取固定和项目报警的list数据
+    getListData(params) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson(
+                '/server/alarm/config/queryConfig',
+                params,
+                res => {
+                    resolve(res)
+                },
+                fail => {
+                    reject(fail)
+                },
+                err => {
+                    reject(err)
+                }
+            )
+        })
+    },
+    // 通过根据Id批量获取各物理实体
+    getApplyObjInfo(projectId, data) {
+        return new Promise((resolve, reject) => {
+            httputils.postJson('/server/dataplatform/object/batchquery?projectId=' + projectId, data, res => {
+                if (res.Result === "success") {
+                    resolve(res.Content || []);
+                }
+            }, fail => {
+                reject(fail);
+            }, err => {
+                reject(err);
+            })
+        })
+    },
+  //查询报警分类
+  alarmClassList(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/config/category/query', params, resp => {
+        if (resp.result == 'success' && resp.count) {
+          resolve(resp.content)
+        } else {
+          resolve([])
+        }
+      })
+    })
+  },
+  //创建报警分类
+  createAlarmClass(params) {
+    return new Promise(resolve => {
+      httputils.postJson('/server/alarm/config/category/create', params, resp => {
+        resolve(resp)
+      })
+    })
+  },
+  /***************断数报警*************************************************** */
+  //获取断数报警通知人员
+  getNumUserNotice(params) {
+    return new Promise(resolve => {
+        httputils.postJson('/server/alarm/notifyuser/queryBrokenAlarmNotifyUser', params, resp => {
+            if(resp.result == 'success' && resp.count) {
+                resolve(resp.content)
+            } else {
+                resolve([])
+            }
+        })
+    })
+  },
+  //更新断数报警的通知方式
+  updateNumUserNotice(params) {
+    return new Promise(resolve => {
+        httputils.postJson('/server/alarm/brokenalarmnotifyuser/update', params, resp => {
+            resolve(resp)
+        })
+    })
+  }
+}
+export default api

+ 128 - 0
src/api/data_admin/buildTaskApi.js

@@ -0,0 +1,128 @@
+import http from '../scan/httpUtil'
+
+const baseUrl = '/api';
+
+/**
+ * info: 查询统计数量(查询总数量不传参数,查询已完成数量TaskState=0,查询未找到TaskState=-1,查询未验证TaskState=1)
+ * @param {Filters:string} param 查询参数
+ * @param {*} success  成功的回调函数
+ *
+ */
+export function queryTaskCount(param, success) {
+    let url = `${baseUrl}/datacenter/scan-task-base/count`;
+    http.postJson(url, param, success)
+}
+
+/*************************模型任务接口****************************/
+//创建模型任务
+export function createModelTask(param, success) {
+    let url = `${baseUrl}/datacenter/model-scan-task/create`;
+    http.postJson(url, param, success)
+}
+//根据id删除模型任务
+export function deleteModelTask(param, success) {
+    let url = `${baseUrl}/datacenter/model-scan-task/delete`;
+    http.postJson(url, param, success)
+}
+//查询:根据模型空间ID查询设备信息
+export function queryModelDiglog(param, success) {
+    let url = `${baseUrl}/datacenter/model-scan-task/equip-query`;
+    http.postJson(url, param, success)
+}
+//查询模型任务
+export function queryModelTask(param, success) {
+    let url = `${baseUrl}/datacenter/model-scan-task/page-query`;
+    http.postJson(url, param, success)
+}
+//更新模型任务
+export function updateModelTask(param, success) {
+    let url = `${baseUrl}/datacenter/model-scan-task/update`;
+    http.postJson(url, param, success)
+}
+
+//查询设备分类
+export function queryModelCategory(param, success) {
+  let url = `${baseUrl}/datacenter/model-scan-task/model-category-query`;
+  http.postJson(url, param, success)
+}
+
+//查询模型文件夹和文件
+export function queryModelFile(param, success) {
+  let url = `${baseUrl}/datacenter/model-scan-task/model-file-query`;
+  http.postJson(url, param, success)
+}
+
+//查询模型任务下的部件类型及数量
+export function modelCategoryCount(param, success) {
+  let url = `${baseUrl}/datacenter/model-scan-task/category-count`;
+  http.postJson(url, param, success)
+}
+
+/*************************设备台账任务接口****************************/
+//创建设备台账任务
+export function createDeviceTask(param, success) {
+  let url = `${baseUrl}/datacenter/equip-scan-task/create`;
+  http.postJson(url, param, success)
+}
+
+//根据id删除设备台账任务
+export function deleteDeviceTask(param, success) {
+  let url = `${baseUrl}/datacenter/equip-scan-task/delete`;
+  http.postJson(url, param, success)
+}
+//查询设备台账任务
+export function queryDeviceTask(param, success) {
+    let url = `${baseUrl}/datacenter/equip-scan-task/page-query`;
+    http.postJson(url, param, success)
+}
+
+//更新设备台账任务
+export function updateDeviceTask(param, success) {
+  let url = `${baseUrl}/datacenter/equip-scan-task/update`;
+  http.postJson(url, param, success)
+}
+
+//查询设备分类
+export function queryDeviceCategory(param, success) {
+  let url = `${baseUrl}/datacenter/equip-scan-task/equip-category-query`;
+  http.postJson(url, param, success)
+}
+
+//查询设备任务下的部件类型及数量
+export function categoryCount(param, success) {
+  let url = `${baseUrl}/datacenter/equip-scan-task/category-count`
+  http.postJson(url, param, success)
+}
+
+/*************************资产台账任务接口****************************/
+//统计数量
+export function countAssetsTask(param, success) {
+  let url = `${baseUrl}/datacenter/property-scan-task/count`;
+  http.postJson(url, param, success)
+}
+
+//创建设备台账任务
+export function createAssetsTask(param, success) {
+  let url = `${baseUrl}/datacenter/property-scan-task/create`;
+    http.postJson(url, param, success)
+}
+//根据id删除设备台账任务
+export function deleteAssetsTask(param, success) {
+    let url = `${baseUrl}/datacenter/property-scan-task/delete`;
+    http.postJson(url, param, success)
+}
+//查询设备台账任务
+export function queryAssetsTask(param, success) {
+    let url = `${baseUrl}/datacenter/property-scan-task/page-query`;
+    http.postJson(url, param, success)
+}
+//更新设备台账任务
+export function updateAssetsTask(param, success) {
+    let url = `${baseUrl}/datacenter/property-scan-task/update`;
+    http.postJson(url, param, success)
+}
+//查询设备族
+export function queryAssetsFamily(param, success) {
+    let url = `${baseUrl}/datacenter/property-scan-task/property-category-query`;
+    http.postJson(url, param, success)
+}

+ 10 - 0
src/api/database/hbase.js

@@ -0,0 +1,10 @@
+import httputils from '@/utils/httputils'
+export default {
+    tables() {
+        return httputils.getJson('/admin/hbase/tables')
+    },
+
+    query(criteria) {
+        return httputils.postJson('/admin/hbase/query', criteria)
+    }
+}

+ 12 - 0
src/api/database/redis.js

@@ -0,0 +1,12 @@
+import httputils from '@/utils/httputils'
+export default {
+    query(criteria) {
+        return httputils.postJson('/admin/redis/query', criteria)
+    },
+    save(redisData) {
+        return httputils.postJson('/admin/redis/save', redisData)
+    },
+    delete(redisData) {
+        return httputils.postJson('/admin/redis/delete', redisData)
+    }
+}

+ 72 - 0
src/api/fm/rules.js

@@ -0,0 +1,72 @@
+/**
+@author:fugy
+@date:2019.1.16
+@info:项目抢单规则设定=project-rule-api
+ */
+const planHz = [
+    { id: 'd', name: '每日' },
+    { id: 'w', name: '每周' },
+    { id: 'm', name: '每月' },
+    { id: 'y', name: '每年' }
+]
+import httputils from '@/utils/httputils'
+const api = {
+    getLevelDef() {
+        return { value: 'id', label: 'name', children: 'content' }
+    },
+    //获取级别列表
+    getLevelList() {
+        return new Promise((resolve, reject) => {
+            httputils.getJson('/server/workorder/engineer/level/def/list', null, resp => {
+                let result = []
+                resp.content.forEach(item => {
+                    let temp = { id: item.skillId, name: item.name, content: [] }
+                    if (item.content) {
+                        item.content.forEach(level => {
+                            temp.content.push({ id: level.levelId, name: level.name })
+                        })
+                    }
+                    result.push(temp)
+                })
+                resolve(result)
+            })
+        })
+    },
+    // 获取工单类型列表
+    getOrderType() {
+        return new Promise(resolve => {
+            httputils.getJson('/server/workorder/rule/queryWoTypeList', {}, resp => {
+                if (resp.result == 'success' && resp.count) {
+                    resolve(resp.content)
+                } else {
+                    resolve([])
+                }
+            })
+        })
+    },
+    //获取计划频率
+    getPlanHz() {
+        return planHz
+    },
+    //获取项目抢单规则的列表数据
+    getListData(params) {
+        return new Promise(resolve => {
+            httputils.postJson('/server/workorder/rule/query', params, resp => {
+                if (resp.result == 'success' && resp.content.length) {
+                    resolve(resp.content)
+                } else {
+                    resolve([])
+                }
+            })
+        })
+    },
+    //配置当前的工单的规则
+    updateWorkOrder(params) {
+        return new Promise(resolve => {
+            httputils.postJson('/server/workorder/rule/createOrUpdate', params, resp => {
+                resolve(resp)
+            })
+        })
+    }
+}
+export default api

+ 83 - 0
src/api/fm/sop.js

@@ -0,0 +1,83 @@
+/**
+@author:fugy
+@date:2018.10.22
+@info:通用问题对应集团的sop的api
+ */
+import httputils from '@/utils/httputils';
+let priorityArr = [
+    //优先级数组
+    {
+        label: 'S',
+        value: 'S'
+    },
+    {
+        label: 'A',
+        value: 'A'
+    },
+    {
+        label: 'B',
+        value: 'B'
+    },
+    {
+        label: 'C',
+        value: 'C'
+    },
+    {
+        label: 'D',
+        value: 'D'
+    }
+];
+let problemArr = [
+    //问题级别数组
+    {
+        label: '电器',
+        value: '电器'
+    },
+    {
+        label: '建筑',
+        value: '建筑'
+    },
+    {
+        label: '家具',
+        value: '家具'
+    },
+    {
+        label: '其他',
+        value: '其他'
+    }
+]
+const api = {
+    // 获取sop的列表
+    getListData: function(params) {
+        return new Promise((resolve, reject) => {
+			httputils.postJson('/server/workorder/generalProblem/problem/query', params, res => {
+                resolve(res)
+			})
+		})
+    },
+    // 获取sop问题的列表数据
+    getSopList(params) {
+        return new Promise((resolve, reject) => {
+			httputils.postJson('/server/workorder/generalProblem/sop/list', params, res => {
+                resolve(res)
+			})
+		})
+    },
+    // 保存配置sop
+    setSop(params) {
+        return new Promise((resolve, reject) => {
+			httputils.postJson('/server/workorder/generalProblem/sop/set', params, res => {
+                resolve(res)
+			})
+		})
+    },
+    // 优先级数组
+    getPriorityArr: function () {
+        return priorityArr
+    },
+    // 获取问题类型
+    getProblemArr: function () {
+        return problemArr
+    },
+}
+export default api;

+ 111 - 0
src/api/framework.js

@@ -0,0 +1,111 @@
+import store from '@/store'
+import demoMenus from '@/demo/demo-menus'
+import menus from '@/data/menus'
+import router from '@/router'
+import httputils from '@/utils/httputils'
+// const userInfo = { username: 'admin', permissions: ['demo'] }
+
+const userInfo = null
+function toLogin() {
+    router.push('/login')
+}
+
+function checkMenu(menu, ps) {
+    let result = { name: menu.name, icon: menu.icon, path: menu.path, disabled: menu.disabled }
+    if (menu.children) {
+        // 如果有下级菜单权限,则自动拥有上级菜单权限
+        result.children = []
+        menu.children.forEach(child => {
+            let submenu = checkMenu(child, ps)
+            if (submenu) {
+                result.children.push(submenu)
+            }
+        })
+        return result.children.length > 0 ? result : null
+    } else if (menu.opts) {
+        return menu.opts.some(opt => ps[opt.permission]) ? result : null
+    } else {
+        // 如果没有下级菜单且没有opts属性, 菜单可以直接访问,不需要权限
+        return result
+    }
+}
+
+export default {
+    /**
+     *  路由守卫, 每次路由跳转时验证登录
+     * @param {*} to
+     * @param {*} from
+     * @param {*} next
+     */
+    routerBeforeEach: async function(to, from, next) {
+        console.log('router before ', to)
+        if (to.path == '/auth' || to.path == '/login') {
+            next()
+        } else {
+            if (to.meta.breadcrumbs) {
+                store.dispatch('setBreadcrumb', to.meta.breadcrumbs)
+            } else {
+                store.dispatch('setBreadcrumb', [])
+            }
+            // next()
+            let userInfo = store.getters['layout/userInfo']
+            if (!userInfo) {
+                // 本地是未登录状态, 保存目标页面地址, 去登录
+                let lastRoute = { path: to.path, params: to.params, query: to.query }
+                store.commit('setLastRoute', lastRoute)
+                toLogin()
+            } else {
+                if (to.meta.breadcrumbs) {
+                    store.dispatch('setBreadcrumb', to.meta.breadcrumbs)
+                }
+                next()
+            }
+            return true
+        }
+    },
+
+    getMenus(permissions) {
+        let result = []
+        let allMenus = []
+        // 开发环境下展示demo页面
+        // if (process.env.NODE_ENV === 'development') {
+        //     allMenus = demoMenus
+        // }
+        allMenus = allMenus.concat(menus)
+        let ps = !permissions ? {} : permissions
+        console.log(ps)
+        allMenus.forEach(item => {
+            let menu = checkMenu(item, ps)
+            if (menu) {
+                result.push(menu)
+            }
+        })
+        return result
+    },
+
+    login(username, password) {
+        return new Promise((resolve, reject) => {
+            if (username == 'admin') {
+                resolve({ result: 'success', ssoToken: 'admin-token' })
+            } else {
+                resolve({ result: 'fail', message: 'username or password error' })
+            }
+        })
+    },
+
+    loadUserInfo() {
+        // return new Promise((resolve, reject) => resolve({ result: 'success', ...userInfo }))
+        return httputils.getJson(`/admin/ibms/user/userInfo`)
+    },
+
+    toLogout() {
+        // TODO
+        router.push('/auth')
+        store.commit('setSsoToken', null)
+        let ssoServer = process.env.SSO_SERVER
+        let redirectUrl = window.location.protocol + '//' + window.location.host + '/'
+        window.location.href = `${ssoServer}/logout?redirectUrl=${redirectUrl}`
+    },
+
+    toLoginPage: toLogin
+}

+ 100 - 0
src/api/httputils.js

@@ -0,0 +1,100 @@
+import axios from 'axios'
+import store from '@/store'
+import { MessageBox } from 'element-ui'
+
+var CancelToken = axios.CancelToken
+var cancel
+
+// 创建axios实例
+const axiosservice = axios.create({
+    timeout: 3000000, // 请求超时时间
+    retry: 4, //重新请求次数
+    retryDelay: 1000, //重新请求的间隔
+    credentials: true, // 接口每次请求会跨域携带cookie
+    cancelToken: new CancelToken(function executor(c) {
+        // executor 函数接收一个 cancel 函数作为参数
+        cancel = c
+    })
+})
+
+axiosservice.interceptors.request.use(
+    config => {
+        config.withCredentials = true // 允许携带token ,这个是解决跨域产生的相关问题
+        let token = store.getters['ssoToken']
+        if (token) {
+            config.headers = {
+                'sso-token': token
+            }
+        }
+        return config
+    },
+    error => {
+        return Promise.reject(error)
+    }
+)
+
+axiosservice.interceptors.response.use(
+    function(res) {
+        //在这里对返回的数据进行处理
+        let resp = res.data
+        if (resp.result === 'unauthc') {
+            store.commit('logined', false)
+            MessageBox.confirm('未登陆或登陆信息已失效, 是否重新登陆?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'error'
+            })
+                .then(resp => {
+                    window.location.reload()
+                })
+                .catch(error => {
+                    console.log('')
+                })
+        }
+        return res
+    },
+    function(err) {
+        console.log('axios interceptors err = ', err)
+        return Promise.reject(err)
+    }
+)
+
+export default {
+    //获取cookie
+    getCookie(name) {
+        var arr,
+            reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
+        if ((arr = document.cookie.match(reg))) {
+            return unescape(arr[2])
+        } else {
+            /* 如果没有参数,那么就获取本域下的所有cookie */
+            return document.cookie
+        }
+    },
+
+    async getJson(url, params) {
+        try {
+            let response = await axiosservice({
+                url,
+                params,
+                method: 'get'
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    async postJson(url, data) {
+        try {
+            let response = await axiosservice({
+                url,
+                data,
+                method: 'post'
+            })
+            return response.data
+        } catch (err) {
+            throw err
+        }
+    },
+    axios: axiosservice
+}

+ 347 - 0
src/api/model/file.js

@@ -0,0 +1,347 @@
+import httputils from '@/api/scan/httpUtil'
+import { Message } from 'element-ui';
+import axios from 'axios'
+const baseUrl = '/modelapi';
+const revitUrl = '/schedulerapi';
+
+let api = {
+    // 新建模型文件夹
+    /**
+     * 
+     * @param {Name:string,ProjectId:string} params 
+     */
+    createModel(params, success) {
+        let Name = params.Name;
+        this.queryModel(Name, (res) => {
+            if (res.Total == 0) {
+                let data = {
+                    Content: [params]
+                };
+                // 查询是否有该模型文件夹
+                // 创建
+                httputils.postJson(`${baseUrl}/model-folder/create`, data, success)
+            } else {
+                Message.error({ message: '该文件夹已经存在!' });
+            }
+        })
+    },
+    //删除模型文件夹
+    /**
+     * 
+     * @param {Id:string} params 
+     */
+    deleteModel(params, success) {
+        let Content = [params];
+        httputils.postJson(`${baseUrl}/model-folder/delete`, Content, success)
+    },
+    //修改模型文件夹名称
+    /**
+    * 
+    * @param {Name:string,ProjectId:string} params 
+    */
+    updateModelName(params, success) {
+        let Name = params.Name;
+        this.queryModel(Name, (res) => {
+            if (res.Total == 0) {
+                let data = {
+                    Content: [params]
+                };
+                // 更改文件夹名称
+                httputils.postJson(`${baseUrl}/model-folder/update`, data, success)
+            } else {
+                Message.error({ message: '该文件夹已经存在!' });
+            }
+        })
+    },
+    //查询模型文件夹
+    /** 
+     * @param Name string  注:查询多个 Name = '' 
+    */
+    queryModel(Name, success) {
+        let data = null;
+        if (Name) {
+            // 单个查询
+            data = {
+                Filters: `Name='${Name}'`,
+                Orders: "Name asc"
+            }
+        } else {
+            // 多个查询
+            data = {
+                Orders: "Name asc"
+            }
+        }
+        return httputils.postJson(`${baseUrl}/model-folder/query`, data, success)
+    },
+
+
+
+    //以下是楼层文件接口
+
+    // 查询模型文件夹下的所有模型文件
+    queryFloorList(data, success) {
+
+        let Filters = `FolderId='${data.FolderId}'`;
+        if (data.FloorName) {
+            Filters = `FolderId='${data.FolderId}';FloorName='${data.FloorName}';ProjectId='${data.ProjectId}'`;
+        }
+        if (data.Status) {
+            Filters += `;Status in [${data.Status}]`
+        }
+        let params = {
+            Filters: Filters,
+            PageNumber: 1,
+            PageSize: 500
+        }
+        return httputils.postJson(`${baseUrl}/model-floor/query-list`, params, success)
+    },
+    // 查询模型文件夹下的单个模型文件
+    queryFloorItem(data, success) {
+
+        let Filters = `FolderId='${data.FolderId}'`;
+        if (data.FloorName) {
+            Filters = `FolderId='${data.FolderId}';FloorName='${data.FloorName}';ProjectId='${data.ProjectId}'`;
+        }
+        let params = {
+            Filters: Filters
+        }
+        return httputils.postJson(`${baseUrl}/model-floor/query`, params, success)
+    },
+    // 创建楼层
+    // createFloor(params) {
+    //     // 判断该楼层是否存在
+
+    //     let data = {
+    //         Content: [{
+    //             FolderId: params.FolderId,
+    //             FloorName: params.FloorName,
+    //             ProjectId: params.ProjectId,      //项目id
+    //         }]
+    //     };
+    //     return new Promise((resolve, preject) => {
+    //         this.queryFloorItem(params, (res) => {
+    //             if (res.Total == 0) {
+    //                 // 创建楼层
+    //                 httputils.postJson(`${baseUrl}/model-floor/create`, data, (res) => {
+    //                     let modelFile = {
+    //                         Content: [{
+    //                             // ProjectId: params.ProjectId,      //项目id
+    //                             FloorModelId: res.EntityList[0].Id, //模型所属楼层(FloorModel外键)
+    //                             ModelName: params.Form.file.name,        //模型文件名
+    //                             UserName: params.userName,
+    //                             UserId: params.userId,
+    //                             Note: params.Form.desc
+    //                             // ReplaceReason: 0
+    //                         }]
+    //                     }
+    //                     //创建模型文件
+    //                     this.createModelFile(modelFile, (createModelRes) => {
+    //                         // 与此楼文件进行绑定
+    //                         let upDateModelData = {
+    //                             Content: [{
+    //                                 Id: res.EntityList[0].Id, //id
+    //                                 CurrentModelId: createModelRes.EntityList[0].Id //该楼层当前的模型id
+    //                             }]
+    //                         }
+    //                         this.updateFloorName(upDateModelData, (upDateModelSucess) => {
+    //                             if (upDateModelSucess.Result == "success") {
+    //                                 resolve({
+    //                                     Result: 'success',
+    //                                     FloorModelId: res.EntityList[0].Id,   //楼层模型文件
+    //                                     CurrentModelId: createModelRes.EntityList[0].Id //模型文件id
+    //                                 })
+    //                             }
+    //                         })
+    //                     })
+    //                 })
+    //             } else {
+    //                 let modelFile = {
+    //                     Content: [{
+    //                         // ProjectId: params.ProjectId,      //项目id
+    //                         FloorModelId: res.Content[0].Id, //模型所属楼层(FloorModel外键)
+    //                         ModelName: params.Form.file.name,        //模型文件名
+    //                         UserName: params.userName,
+    //                         UserId: params.userId,
+    //                         Note: params.Form.desc
+    //                         // ReplaceReason: 0
+    //                     }]
+    //                 }
+    //                 //创建模型文件
+    //                 this.createModelFile(modelFile, (createModelRes) => {
+    //                     // 与此楼文件进行绑定
+    //                     let upDateModelData = {
+    //                         Content: [{
+    //                             Id: res.Content[0].Id, //id
+    //                             CurrentModelId: createModelRes.EntityList[0].Id //该楼层当前的模型id
+    //                         }]
+    //                     }
+    //                     this.updateFloorName(upDateModelData, (upDateModelSucess) => {
+    //                         if (upDateModelSucess.Result == "success") {
+    //                             resolve({
+    //                                 Result: 'success',
+    //                                 FloorModelId: res.Content[0].Id,   //楼层模型文件
+    //                                 CurrentModelId: createModelRes.EntityList[0].Id //模型文件id
+    //                             })
+    //                         }
+    //                     })
+    //                 })
+    //             }
+    //         })
+    //     })
+    // },
+    // 删除楼层文件
+    deleteFloor(data) {
+        return httputils.postJson(`${baseUrl}/model-floor/delete`, data)
+    },
+    //编辑楼层文件的名字
+    updateFloorName(data, success) {
+        return httputils.postJson(`${baseUrl}/model-floor/update`, data, success)
+    },
+
+
+    //以下是楼层文件接口
+
+    // 创建模型文件
+    createModelFile(data, success) {
+        return httputils.postJson(`${baseUrl}/model-file/create`, data, success)
+    },
+    //删除模型文件(只有记录,文件不动)
+    deleteModelFile(data, success) {
+        return httputils.postJson(`${baseUrl}/model-file/delete`, data, success)
+    },
+    /**
+     * info: 删除模型文件
+     * @param {*} params string 模型文件的id 
+     * @param {*} success  成功的回调函数
+     */
+    deleteModelFileList(params, success) {
+        let data = {
+            Id:params.Id,
+            Force: params.Force?params.Force:false
+        } 
+        return httputils.postJson(`${baseUrl}/model-file/delete-file`, data, success)
+    },
+    //查询模型文件 
+    queryModelFile(FloorModelId, success) {
+        let params = {
+            Distince: true,
+            Filters: `FloorModelId='${FloorModelId}';Removed=false`
+        }
+        return httputils.postJson(`${baseUrl}/model-file/query`, params, success)
+    },
+    // 上传模型文件
+    // uploadModelFile(payload, ProjectId,callback1, callback2) {
+    //     axios({
+    //         url: baseUrl + '/model-file/upload',
+    //         method: 'post',
+    //         headers: {
+    //             ProjectId: ProjectId
+    //         },
+    //         onUploadProgress: function (progressEvent) { //原生获取上传进度的事件
+    //             if (progressEvent.lengthComputable) {
+    //                 //属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
+    //                 //如果lengthComputable为false,就获取不到progressEvent.total和progressEvent.loaded
+    //                 callback1(progressEvent);
+    //             }
+    //         },
+    //         data: payload
+    //     }).then(res => {
+    //         callback2(res);
+    //     }).catch(error => {
+    //         console.log('this is a catch')
+    //         console.log(error)
+    //     })
+    // },
+
+    //准备分片上传模型文件接口
+    modelFileUpload(data, success) {
+        return httputils.postJson(`${baseUrl}/model-file/upload`, data, success)
+    },
+
+    mergeModelFile(data, success) {
+        return httputils.postJson(`${baseUrl}/model-file/merge`, data, success)
+    }
+
+    // 更新模型文件
+    // upDateModelFile(data, ProjectId, UserName, UserId, callback1, callback2) {
+    //     let modelFile = {
+    //         Content: [{
+    //             FloorModelId:data.replaceModelItem.Id, //模型id
+    //             ModelName: data.Form.file.name,        //模型名字
+    //             UserName: UserName,
+    //             UserId: UserId,
+    //             Note: data.replaceModelItem.Note,
+    //             ReplaceReason: data.Form.ReplaceReason
+    //         }]
+    //     }
+    //     // //创建模型文件
+    //     this.createModelFile(modelFile, (createModelRes) => {
+    //         // 与此楼文件进行绑定
+    //         let upDateModelData = {
+    //             Content: [{
+    //                 Id:data.replaceModelItem.Id, //楼层
+    //                 CurrentModelId: createModelRes.EntityList[0].Id
+    //             }]
+    //         }
+    //         this.updateFloorName(upDateModelData, (upDateModelSucess) => {
+    //             if (upDateModelSucess.Result == "success") {
+    //                 // 处理数据
+    //                 let formData = new FormData();
+    //                 formData.append(
+    //                   "model",
+    //                   JSON.stringify({
+    //                     FloorModelId: data.replaceModelItem.Id,
+    //                     Id:createModelRes.EntityList[0].Id
+    //                   })
+    //                 );
+    //                 formData.append("file", data.Form.file.raw);
+    //                 this.uploadModelFile(formData,ProjectId,callback1,callback2)
+    //             }
+    //         })
+    //     })
+    // }
+
+}
+export default api
+
+//楼层与平面图绑定
+export function bindFloorModel(param, success) {
+    let url = `${baseUrl}/model-floor/bind`;
+    httputils.postJson(url, param, success)
+}
+
+//根据模型id 获取模型文件夹及文件名
+export function getFileNameById(param, success) {
+    let url = `${baseUrl}/model-folder/get-name`;
+    httputils.postJson(url, param, success)
+}
+
+// 根据条件查询统计数量
+export function countSyncLogCount(param, success) {
+    let url = `${baseUrl}/sync-log/count`;
+    httputils.postJson(url, param, success)
+}
+
+// 查询同步日志
+export function querySyncLogCount(param, success) {
+    let url = `${baseUrl}/sync-log/query`;
+    httputils.postJson(url, param, success)
+}
+
+// 查询模型文件
+export function queryFileByModelId(param, success) {
+    let url = `${baseUrl}/model-file/query`;
+    httputils.postJson(url, param, success)
+}
+
+// 模型流程监控
+export function modelPathControl(param, success) {
+    let url = `${baseUrl}/model-monitor/query`;
+    httputils.postJson(url, param, success)
+}
+
+// 模型流程监控-获取待分配模型数量
+export function unassignQuery(param, success) {
+    let url = `${revitUrl}/task/query`;
+    httputils.postJson(url, param, success)
+}

+ 29 - 0
src/api/model/report.js

@@ -0,0 +1,29 @@
+import httputils from '@/api/scan/httpUtil'
+import { Message } from 'element-ui';
+import axios from 'axios'
+const baseUrl = '/modelapi';
+
+// 导出模型问题报告
+// export function exportReport(params, success) {
+//     httputils.postJson(`${baseUrl}/report/non-blocking`, params, success)
+// }
+
+// 查询楼层列表
+export function queryFloorList(params, success) {
+    return httputils.postJson(`${baseUrl}/model-floor/query-list`, params, success)
+}
+
+// 获取项目下所有模型文件夹
+export function queryModel(params, success) {
+    return httputils.postJson(`${baseUrl}/model-folder/query`, params, success)
+}
+
+// 查询文件夹下的所有楼层
+export function queryReportList(params, success) {
+    return httputils.postJson(`${baseUrl}/report/list/non-blocking`, params, success)
+}
+
+// 查询文件夹下的所有楼层(包含缺失楼层)
+export function queryLostReportList(params, success) {
+    return httputils.postJson(`${baseUrl}/model-floor/query-list-missing`, params, success)
+}

+ 56 - 0
src/api/msgsever.js

@@ -0,0 +1,56 @@
+import http from './scan/httpUtil'
+const baseUrl = '/api';
+
+/*************************消息中心接口****************************/
+
+/**
+ * title: 统计数量
+ * info: 查询总数量不传参数,查询 已读Read = true,未读 Read = false
+ */
+export function messgeCount(param, success) {
+    let url = `${baseUrl}/message-center/message/count`;
+    http.postJson(url, param, success)
+}
+
+/**
+ * title: 创建消息
+ * info: 消息类型:提示(Info)、警告(Warning)、错误(Error)、成功(Success)
+ */
+export function messgeCreate(param, success) {
+    let url = `${baseUrl}/message-center/message/create`;
+    http.postJson(url, param, success)
+}
+
+/**
+ * title: 删除消息
+ */
+export function messgeDelete(param, success) {
+    let url = `${baseUrl}/message-center/message/delete`;
+    http.postJson(url, param, success)
+}
+
+/**
+ * title: 查询消息列表
+ */
+export function messgeQuery(param, success) {
+    let url = `${baseUrl}/message-center/message/page-query`;
+    http.postJson(url, param, success)
+}
+
+/**
+ * title: 更新消息状态
+ * info: 是否读过:未读(f)、已读(t)
+ */
+export function messgeUpdate(param, success) {
+    let url = `${baseUrl}/message-center/message/update`;
+    http.postJson(url, param, success)
+}
+
+/**
+ * title: 根据接收人将消息置为已读
+ * info: 已读Read = true,*UserId
+ */
+export function messgeUpdateState(param, success) {
+    let url = `${baseUrl}/message-center/message/update-state`;
+    http.postJson(url, param, success)
+}

+ 177 - 0
src/api/relation/api.js

@@ -0,0 +1,177 @@
+import httpUtil from "../scan/httpUtil";
+import fetch from "../scan/fetch";
+import storage from '@/framework/utils/storage'
+
+
+//查询总览
+export function graphic(param, success) {
+  let url = '/api/datacenter/graphic/overview'
+  httpUtil.postJson(url, param, success)
+}
+
+// 查询总览数量
+export function graphicNumber(param, success) {
+  let url = '/api/datacenter/graphic/query-count'
+  httpUtil.postJson(url, param, success)
+
+}
+
+//导入excel
+export function graphicUpload(param, success) {
+  let url = '/api/datacenter/graphic/import'
+  httpUtil.postJson(url, param, success)
+}
+
+// 下载报告
+export function reportDownload(param, success) {
+  let url = '/api/datacenter/graphic/report-downloads'
+  httpUtil.getJson(url, param, success)
+}
+
+// 下载模板
+export function templateDownloads(param, success) {
+  let url = '/api/datacenter/graphic/template-downloads'
+  httpUtil.getJson(url, param, success)
+}
+
+
+//    建筑下的业务空间
+export function buildSpace(param, success) {
+  let url = '/api/datacenter/calc_building/space'
+  httpUtil.postJson(url, param, success)
+}
+
+
+// 管网系统设备分块 1
+// export function calcSpecial(param, success) {
+//   let url = ` /api/datacenter/calc_special/sys-block?Domain=${param.Domain}&SystemName=${param.SystemName}`
+//   httpUtil.postJson(url, param, success)
+// }
+export function calcSpecial(param, success) {
+  let url = ` /api/datacenter/calc_special/sys-block?relationType=${param.RelationType}`
+  httpUtil.postJson(url, param, success)
+}
+
+
+//    获取源末端 2
+export function blockQuery(param, success) {
+  let url = '/api/datacenter/graphic/connected-block-query'
+  httpUtil.postJson(url, param, success)
+}
+
+
+// 覆盖源末端 3
+export function blockSource(param, success) {
+  let url = '/api/datacenter/graphic/replace-connected-block-source'
+  httpUtil.postJson(url, param, success)
+}
+
+//    管网系统确定流向 4
+export function sysDirection(param, success) {
+  let buildId = param.BuildingId ? `BuildingId=${param.BuildingId}&` : ''
+  let url = `/api/datacenter/calc_special/sys-direction?BlockId=${param.BlockId}&${buildId}Domain=${param.Domain}&SystemName=${param.SystemName}&isSource=${param.isSource}`
+  httpUtil.postJson(url, param, success)
+}
+
+//************************无需配置源末端关系计算15种********************************//
+// 建筑下的业务空间
+export function businessSpaceAll(param) {
+  let {relation_type, zone_type, proId} = param
+  let userName = storage.get("user_name")
+  let ProjectId = localStorage.getItem("projectId")
+  let objectTypes = zone_type ? "?objectTypes=" + zone_type : ''
+  return fetch({
+    method: 'POST',
+    url: "/api/datacenter/relation-calc/" + relation_type + objectTypes,
+    data: proId,
+    headers: {'ProjectId': ProjectId, 'Comming': 'adm', 'Account': userName}
+  })
+}
+
+//************************数据转换********************************//
+
+// 项目化字典-统计数量
+export function dictCount(param, success) {
+  let url = '/api/equip-component/dict-custom/project-dict-count'
+  httpUtil.postJson(url, param, success)
+}
+
+// 项目化字典-需补充转换规则数量
+export function dictSwitchCount(param, success) {
+  let url = '/api/equip-component/dict-custom/project-dict-switch-count'
+  httpUtil.postJson(url, param, success)
+}
+
+//项目化字典 - 内容
+export function dectInfo(param) {
+  let data = param
+  let userName = storage.get("user_name")
+  let ProjectId = localStorage.getItem("projectId")
+  return fetch({
+    method: 'POST',
+    url: `/api/equip-component/dict-custom/project-dict-info`,
+    data,
+    headers: {'ProjectId': ProjectId, 'Comming': 'adm', 'Account': userName}
+  })
+}
+
+//数据中心-物理世界数据转换
+export function dictDataCenter(param, success) {
+  let url = '/api/equip-component/dict-custom/project-dict-datacenter'
+  httpUtil.postJson(url, param, success)
+}
+
+//物理世界-数据中心数据转换
+export function dictDataPlatFrom(param, success) {
+  let url = '/api/equip-component/dict-custom/project-dict-dataplatfrom'
+  httpUtil.postJson(url, param, success)
+}
+
+// 同步设备
+export function createEquip(param, success) {
+  let url = `/api/dataplatform-sync/project-sync/create-equip?projectId=${param.projectId}`
+  httpUtil.postJson(url, {}, success)
+}
+
+//更新自定义自定脚本
+export function dictUpdate(param, success) {
+  let url = '/api/equip-component/dict-custom/update'
+  httpUtil.postJson(url, param, success)
+}
+
+// 查询关系数据
+export function relQuery(param,success) {
+  let url = '/api/datacenter/relation-manual-calc/rel-query'
+  httpUtil.postJson(url,param,success)
+}
+//添加关系数据
+export function relAdd(data) {
+  let userName = storage.get("user_name")
+  let ProjectId = localStorage.getItem("projectId")
+  return fetch({
+    method: 'POST',
+    url: `/api/datacenter/relation-manual-calc/rel-add`,
+    data,
+    headers: {'ProjectId': ProjectId, 'Comming': 'adm', 'Account': userName}
+  })
+}
+
+//删除关系
+export function relDelete(param, success) {
+  let url = '/api/datacenter/relation-manual-calc/rel-del'
+  httpUtil.postJson(url, param, success)
+}
+
+
+// 添加源设备
+export function addSource(param, success) {
+  let url = '/api/datacenter/mep-system-calc/source/add'
+  httpUtil.postJson(url, param, success)
+}
+
+//查看源设备
+export function sourceQuery(param, success) {
+  let url = '/api/datacenter/mep-system-calc/source/query'
+  httpUtil.postJson(url, param, success)
+
+}

+ 22 - 0
src/api/scan/config.js

@@ -0,0 +1,22 @@
+export const baseUrl = '/api';
+export const api = '/ScanBuilding';
+export const api1 = '/scanbuilding-2';
+export const sass = 'sass';
+export const physics = '/data-platform-3';
+export const business = '/business-space'
+export const venders = '/venders'
+export const zone = {
+  GeneralZone: 'zone-general', //默认分区
+  PowerSupplyZone: 'zone-power-supply', //供电分区
+  LightingZone: 'zone-lighting', //照明分区
+  AirConditioningZone: 'metaspace', //空调分区
+  TenantZone: 'zone-tenant', //租赁分区
+  HeatingZone:'zone-heating', //采暖分区
+  CleanZone:'zone-clean', //洁净分区
+  DomesticWaterSupplyZone:'zone-domestic-water', //生活给水分区
+  NetworkZone:'zone-network', //网络分区
+  FunctionZone:'zone-function', //功能分区
+  FireZone:'zone-fire', //防火分区
+  SecurityZone:'zone-security', //安防分区
+  Ispace:'ispace', //元空间
+}

+ 41 - 0
src/api/scan/fetch.js

@@ -0,0 +1,41 @@
+import Vue from 'vue'
+import axios from 'axios'
+import vueAxios from 'vue-axios'
+import { Message } from 'element-ui';
+
+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 => {
+    // let resp = response.data;
+    // let result = resp.result || resp.Result
+    return response
+    // if (result == 'success' || result == 'Success') {
+    //     return response
+    // } else {
+    //     let msg = resp.message ? resp.message : resp.ResultMsg? resp.ResultMsg: resp.Message;
+    //     Message.error({ message: msg });
+    // }
+  },
+  error => {
+    console.log('err' + error)
+    return Promise.reject(error)
+  }
+)
+
+export default service

+ 99 - 0
src/api/scan/httpUtil.js

@@ -0,0 +1,99 @@
+import {Message} from 'element-ui';
+import fetch from './fetch'
+import storage from '@/framework/utils/storage'
+
+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 || resp.Message;
+    Message.error({ message: msg });
+    if (failed) {
+      failed(resp);
+    }
+  }
+
+}
+
+function errorResponse(vm, response, err) {
+  let json = JSON.parse(JSON.stringify(response))
+  console.error(response)
+  if (json.response) {
+    Message.error({ message: `接口:${json.response.config.url}请求错误,错误状态为:${json.response.status}` })
+  } else {
+    console.error(vm, response, err)
+    Message.error({ message: '请求错误' });
+  }
+}
+function downFile(blob, fileName) {
+  // 非IE下载
+  if ('download' in document.createElement('a')) {
+      let link = document.createElement('a')
+      link.href = window.URL.createObjectURL(blob) // 创建下载的链接
+      link.download = fileName // 下载后文件名
+      link.style.display = 'none'
+      document.body.appendChild(link)
+      link.click() // 点击下载
+      window.URL.revokeObjectURL(link.href) // 释放掉blob对象
+      document.body.removeChild(link) // 下载完成移除元素
+  } else {
+      // IE10+下载
+      window.navigator.msSaveBlob(blob, fileName)
+  }
+}
+export default {
+  getJson: function(url, data, success, failed, err) {
+    let ProjectId = localStorage.getItem("projectId")
+    let userName = storage.get("user_name")
+    let vm = this;
+    fetch({ url: url, method: 'get', params: data, headers: {'ProjectId': ProjectId, 'Comming': 'adm' ,'Account': userName}}).then((response) => {
+      successResponse(vm, response, success, failed)
+    }).catch(error => {
+      errorResponse(vm, error, err);
+    });
+  },
+  postJson: function(url, data, success, failed, err) {
+    // let ProjectId = localStorage.getItem("projectId")
+    let ProjectId = "Pj1101050029"
+    let userName = storage.get("user_name")
+    let vm = this;
+    fetch({ url: url, method: 'post', data: data, headers: {'ProjectId': ProjectId, 'Comming': 'adm' ,'Account': userName} }).then((response) => {
+      successResponse(vm, response, success, failed)
+    }).catch(error => {
+      errorResponse(vm, error, err);
+    });
+  },
+  download(url, requestData) {
+    // 响应类型:arraybuffer, blob
+    fetch
+        .post(url, requestData, { responseType: 'blob' })
+        .then(resp => {
+            let headers = resp.headers
+            let contentType = headers['content-type']
+
+            console.log('响应头信息', headers)
+            if (!resp.data) {
+                console.error('响应异常:', resp)
+                return false
+            } else {
+                console.log('下载文件:', resp)
+                const blob = new Blob([resp.data], { type: contentType })
+
+                const contentDisposition = resp.headers['content-disposition']
+                let fileName = 'unknown'
+                if (contentDisposition) {
+                    fileName = window.decodeURI(resp.headers['content-disposition'].split('=')[1])
+                }
+                console.log('文件名称:', fileName)
+                downFile(blob, fileName)
+            }
+        })
+        .catch(function(error) {
+            console.log(error)
+        })
+},
+}

+ 14 - 0
src/api/scan/newRequest.js

@@ -0,0 +1,14 @@
+import {baseUrl} from "./config";
+import http from "./httpUtil";
+
+//头部信息查询(查询所有设备类型-所有部件类型-所有系统类型-所有专业类型)
+export function queryPhysicsAllType(param, success) {
+  let url = `${baseUrl}/datacenter/dict/category`;
+  http.postJson(url, param, success)
+}
+
+//查询项目下类型的信息点
+export function getDataDictionary(param, success) {
+  let url = `${baseUrl}/datacenter/dict/query`;
+  http.postJson(url, param, success)
+}

File diff suppressed because it is too large
+ 2281 - 0
src/api/scan/request.js


+ 6 - 0
src/api/system/admin.js

@@ -0,0 +1,6 @@
+import httputils from '@/utils/httputils'
+export default {
+    loadUserInfo() {
+        return httputils.getJson('/admin/ibms/user/userInfo')
+    }
+}

+ 21 - 0
src/api/system/role.js

@@ -0,0 +1,21 @@
+import httputils from '@/utils/httputils'
+export default {
+    query(criteria) {
+        return httputils.postJson('/admin/role/query', criteria)
+    },
+    create(role) {
+        return httputils.postJson('/admin/role/create', role)
+    },
+    update(role) {
+        return httputils.postJson('/admin/role/update', role)
+    },
+    delete(role) {
+        return httputils.postJson('/admin/role/delete', role)
+    },
+    getOperations(id) {
+        return httputils.getJson('/admin/role/getOperations?id=' + id)
+    },
+    setOperations(data) {
+        return httputils.postJson('/admin/role/setOperations', data)
+    }
+}

+ 15 - 0
src/api/system/user.js

@@ -0,0 +1,15 @@
+import httputils from '@/utils/httputils'
+export default {
+  query(criteria) {
+    return httputils.postJson('/admin/user/query', criteria)
+  },
+  create(user) {
+    return httputils.postJson('/admin/user/create', user)
+  },
+  update(user) {
+    return httputils.postJson('/admin/user/update', user)
+  },
+  delete(user) {
+    return httputils.postJson('/admin/user/delete', user)
+  }
+}

+ 14 - 0
src/api/topo/index.js

@@ -0,0 +1,14 @@
+import httputils from '@/api/scan/httpUtil'
+const baseUrl = '/api';
+
+// 创建拓扑图
+export function topoCreate(param, success) {
+  let url = `${baseUrl}/datacenter/topo/create`;
+  httputils.postJson(url, param, success)
+}
+
+// 查询拓扑图
+export function topoQuery(param, success) {
+  let url = `${baseUrl}/datacenter/topo/query?type=${param.type}`;
+  httputils.postJson(url, param.data||{}, success)
+}

+ 30 - 0
src/api/uploader/index.js

@@ -0,0 +1,30 @@
+import http from '../scan/httpUtil'
+
+const baseUrl = '/image-service'
+
+//分片上传文件接口
+
+/**
+ * info: 申请分片上传接口(获取上传UploadId)
+ * @param {systemId:string} param 系统的名称
+ * @param {secret:string} param 系统的密码
+ * @param {key:string} param  成功的回上传的文件名(可以包含文件路径)
+ * @param {overwrite:boolean} param 表示是否覆盖已有的文件(如果存在) 注:overwrite有一定风险, 只在注册分片时校验, 合并时候如果key被占用, 会覆盖掉之前文件
+ * 
+ */
+export function getUploadId(param, success) {
+  let url = ` ${baseUrl}/common/register_multipart_upload?systemId=${param.systemId}&secret=${param.secret}&key=${param.key}&overwrite=${param.overwrite}`
+  http.postJson(url, {}, success)
+}
+
+/**
+ * info: 合并分片的接口
+ * @param {systemId:string} param 系统的名称
+ * @param {secret:string} param 系统的密码
+ * @param {uploadId:string} param  需要合并的上传文件的uploadId
+ * 
+ */
+export function mergeMultipart(param, success) {
+  let url = ` ${baseUrl}/common/merge_multipart?systemId=${param.systemId}&secret=${param.secret}&uploadId=${param.uploadId}`
+  http.postJson(url, {}, success)
+}

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


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


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

@@ -0,0 +1,492 @@
+/*!
+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;
+    box-sizing: border-box;
+}
+
+.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;
+    box-sizing: border-box;
+}
+
+.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 {}

+ 44 - 0
src/assets/graphy/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/graphy/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/graphy/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/graphy/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/graphy/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/graphy/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

+ 0 - 0
src/assets/graphy/SGraphy/dataType.js


+ 78 - 0
src/assets/graphy/SGraphy/dataType.ts

@@ -0,0 +1,78 @@
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+import SGraphyPolygonItem from './newItems/SGraphyPolygonItem'
+/**
+ * 接口类型
+ * @param
+ * 传入绘制地图参数的数据类型
+ */
+//path 和paths 的接口类型
+interface dataItemPath {
+    X: number,
+    Y: number,
+    Z: number
+}
+// 一个空间item中的数据类型 
+//包括ColumnList EquipmentList,VirtualWallList,WallList
+interface dataItem {
+    Id: string,
+    Path?: dataItemPath[],
+    PointList: dataItemPath[],
+    BimId?: string,
+    LocationPoint?: dataItemPath,
+    Name?: string,
+    Paths?: dataItemPath[][],
+}
+// 一个空间item中的接口类型 
+// 包括SpaceList
+interface dataSpaceItem {
+    Id: string,
+    // PointList: dataItemPath[],
+    BimId: string,
+    LocationPoint: dataItemPath,
+    Name: string,
+    Paths: dataItemPath[][],
+    id: string,
+    type: number,                  //item类型
+    businessId?: string | null,  //绑定的业务id
+    isBusiness?: number,        //业务类型
+    fillColor?: SColor,         //填充颜色
+    color?: SColor,             //边框颜色
+    businessName?: string | null,  //业务名称
+    width?: number
+}
+// 传入的data 的接口类型 
+interface dataInterface {
+    ColumnList: dataItem[],  //柱体
+    EquipmentList: dataItem[], //设备
+    SpaceList: dataSpaceItem[], //空间
+    VirtualWallList: dataItem[], //虚拟墙
+    WallList: dataItem[],    //墙
+    images: ImgItemInterface[],  //图片
+}
+//获取绑定空间的接口
+interface businessDataInterface {
+    id: string,
+    name: string,
+    children: string[],
+    isAdjacent: boolean,
+    isAbut: boolean
+}
+// 多边形传入的参数接口
+interface PolygonItemInterface {
+    parent: SGraphyPolygonItem | null //父类
+    space: dataSpaceItem,       //传入的item 参数
+    businessType?: string
+}
+// 图片传入的参数接口
+interface ImgItemInterface {
+    parent: SGraphyPolygonItem | null //父类
+    X: number;
+    Y: number;
+    width: number;
+    height: number;
+    img: string;
+    id?: string;
+    name: string;
+}
+
+export { dataItemPath, dataItem, dataSpaceItem, dataInterface, businessDataInterface, PolygonItemInterface, ImgItemInterface }

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

@@ -0,0 +1,70 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../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);
+        }
+    }
+}

+ 201 - 0
src/assets/graphy/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

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

@@ -0,0 +1,59 @@
+/**
+ * 图片
+ * 
+ * 
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../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/graphy/SGraphy/items/SGraphyLineItem.js

@@ -0,0 +1,66 @@
+/**
+ * 线条
+ */
+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
+        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/graphy/SGraphy/items/SGraphyPillarItems.js

@@ -0,0 +1,76 @@
+/**
+ * 不规则多边形,元空间
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../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/graphy/SGraphy/items/SGraphyPolygonItem.js

@@ -0,0 +1,257 @@
+/**
+ * 不规则多边形,元空间
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../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/graphy/SGraphy/items/SGraphyRectItem.js

@@ -0,0 +1,100 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../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/graphy/SGraphy/items/SGraphyTextItems.js

@@ -0,0 +1,51 @@
+/**
+ * 线条
+ */
+import SGraphyItem from '../SGraphyItem'
+import SRect from '../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/graphy/SGraphy/items/SGraphyVirtualItem.js

@@ -0,0 +1,66 @@
+/**
+ * 线条
+ */
+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.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()
+    }
+}

+ 240 - 0
src/assets/graphy/SGraphy/mainScene.js

@@ -0,0 +1,240 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import SGraphyPolygonItem from './newItems/SGraphyPolygonItem.js';
+import { SGraphyImgItem } from './newItems/SGraphyImgItem.js';
+import { SGraphyScene } from "@sybotan-web/graphy";
+import Axios from 'axios';
+import pako from "./until/pako.js";
+import tools from "./until/tool.js";
+/**
+ * @name mainScene
+ * @time 2019-07.07;
+ * 添加所有item的场景到scene中
+ */
+var mainScene = /** @class */ (function (_super) {
+    __extends(mainScene, _super);
+    /**
+     * @param data 绘制空间地图得所有参数
+     */
+    function mainScene(data) {
+        var _this_1 = _super.call(this) || this;
+        _this_1._isShowSpace = true; // 是否显示空间;
+        _this_1._isShowWallList = true; //是否展示墙体;
+        _this_1._isShowEquipmentList = true; //是否展示设备;
+        _this_1._isShowVrtualWallList = true; //是否展示虚拟墙
+        _this_1.data = data;
+        if (_this_1.data != null) {
+            _this_1.addAllItemList(_this_1.data);
+        }
+        return _this_1;
+    }
+    Object.defineProperty(mainScene.prototype, "isShowSpace", {
+        // 设置是否显示空间
+        get: function () {
+            return this._isShowSpace;
+        },
+        set: function (b) {
+            this._isShowSpace = b;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(mainScene.prototype, "isShowWallList", {
+        // 设置是否显示墙
+        get: function () {
+            return this._isShowWallList;
+        },
+        set: function (b) {
+            this._isShowWallList = b;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(mainScene.prototype, "isShowEquipmentList", {
+        // 设置是否显示设备
+        get: function () {
+            return this._isShowEquipmentList;
+        },
+        set: function (b) {
+            this._isShowEquipmentList = b;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(mainScene.prototype, "isShowVrtualWallList", {
+        // 设置是否显示虚拟墙
+        get: function () {
+            return this._isShowVrtualWallList;
+        },
+        set: function (b) {
+            this._isShowVrtualWallList = b;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    //获取参数
+    mainScene.prototype.urlGetData = function (url) {
+        var _this_1 = this;
+        var that = this;
+        return new Promise(function (relove, reject) {
+            Axios({
+                method: 'get',
+                url: url,
+                data: {},
+                responseType: 'blob',
+            }).then(function (res) {
+                var blob = res.data;
+                _this_1.zipToJson(blob).then(function (jsonData) {
+                    that.addAllItemList(jsonData);
+                    relove();
+                }).catch(function (error) {
+                    console.log(error);
+                });
+                // console.log(reader)
+            }).catch(function (res) {
+                console.log(res);
+            });
+        });
+    };
+    // 压缩包变为json格式数据
+    mainScene.prototype.zipToJson = function (blob) {
+        var data = null;
+        var reader = new FileReader();
+        reader.readAsBinaryString(blob);
+        var _this = this;
+        return new Promise(function (resolve) {
+            reader.onload = function (readerEvt) {
+                var binaryString = readerEvt.target.result;
+                //解压数据
+                var base64Data = btoa(binaryString);
+                var unGzipData = pako.unzip(base64Data);
+                data = unGzipData;
+                if (data.WallList && data.WallList.length) {
+                    tools.changeMap(data.WallList, -1, "PointList");
+                }
+                if (data.SpaceList && data.SpaceList.length) {
+                    tools.changeMap(data.SpaceList, -1, "Paths");
+                }
+                if (data.ColumnList && data.ColumnList.length) {
+                    tools.changeMap(data.ColumnList, -1, "Path");
+                }
+                if (data.VirtualWallList && data.VirtualWallList.length) {
+                    tools.changeMap(data.VirtualWallList, -1, "PointList");
+                }
+                if (data.EquipmentList && data.EquipmentList.length) {
+                    tools.changeMap(data.EquipmentList, -1, "PointList");
+                }
+                resolve(data);
+            };
+        });
+    };
+    // 以下是绘制方法
+    /**
+     * 增添所有绘制item(地图);
+    */
+    mainScene.prototype.addAllItemList = function (data) {
+        var space = data.SpaceList;
+        // let wall:
+        this.addSpaceList(space); //绘制空间
+        this.addWallList(); //绘制墙
+        var images = data.images;
+        this.addImageList(images);
+    };
+    /**
+     * 添加所有空间到scene 中
+     * @param space 空间list
+     */
+    mainScene.prototype.addSpaceList = function (space) {
+        if (space && space.length) {
+            for (var i = 0; i < space.length; i++) {
+                if (space[i].Paths[1] && space[i].Paths[1].length >= 2) {
+                    this.addItem(this.constructeItem({
+                        parent: null,
+                        space: space[i],
+                        businessType: 'space'
+                    }));
+                }
+            }
+            for (var i = 0; i < space.length; i++) {
+                if (space[i].Paths[0] && space[i].Paths[0].length >= 2 && !space[i].Paths[1]) {
+                    this.addItem(this.constructeItem({
+                        parent: null,
+                        space: space[i],
+                        businessType: 'space'
+                    }));
+                }
+            }
+        }
+    };
+    // 绘制墙体
+    mainScene.prototype.addWallList = function () {
+    };
+    // 绘制设备
+    mainScene.prototype.addEquipmentList = function () {
+    };
+    // 绘制柱体
+    mainScene.prototype.addColumnListList = function () {
+    };
+    // 绘制虚拟墙
+    mainScene.prototype.addVrtualWallList = function () {
+    };
+    // 绘制图片
+    mainScene.prototype.addImageList = function (imageList) {
+        var _this_1 = this;
+        if (imageList && imageList.length) {
+            imageList.map(function (t) {
+                _this_1.addItem(new SGraphyImgItem(null, t.img, t.X, t.Y, t.width, t.height));
+            });
+        }
+    };
+    /**
+     * 产生item实例
+     */
+    mainScene.prototype.constructeItem = function (PolygonItemInterfaceData) {
+        return new SGraphyPolygonItem(PolygonItemInterfaceData);
+    };
+    // 鼠标交互类事件
+    // 点击
+    mainScene.prototype.click = function (_this, fn) {
+        this.root.children.forEach(function (item) {
+            item.connect("click", _this, fn);
+        });
+    };
+    // 双击
+    mainScene.prototype.dbclick = function (_this, fn) {
+        this.root.children.forEach(function (item) {
+            item.connect("doubleClick", _this, fn);
+        });
+    };
+    // 按下
+    mainScene.prototype.mouseDown = function (_this, fn) {
+        this.root.children.forEach(function (item) {
+            item.connect("mouseDown", _this, fn);
+        });
+    };
+    //移动
+    mainScene.prototype.mouseMove = function (_this, fn) {
+        this.root.children.forEach(function (item) {
+            item.connect("mouseMove", _this, fn);
+        });
+    };
+    // 点解结束
+    mainScene.prototype.mouseUp = function (_this, fn) {
+        this.root.children.forEach(function (item) {
+            item.connect("mouseUp", _this, fn);
+        });
+    };
+    return mainScene;
+}(SGraphyScene));
+export default mainScene;

+ 228 - 0
src/assets/graphy/SGraphy/mainScene.ts

@@ -0,0 +1,228 @@
+
+import { SRect, SSize, SPoint } from "@sybotan-web/base";
+import SGraphyPolygonItem from './newItems/SGraphyPolygonItem.js'
+import { SGraphyImgItem } from './newItems/SGraphyImgItem.js'
+import { SGraphyScene, SMouseEvent } from "@sybotan-web/graphy";
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+import { dataItemPath, dataItem, dataSpaceItem, dataInterface, PolygonItemInterface, ImgItemInterface } from './dataType'   //传入参数的参数接口类型
+import Axios from 'axios';
+import pako from "./until/pako.js"
+import tools from "./until/tool.js"
+/**
+ * @name mainScene
+ * @time 2019-07.07;
+ * 添加所有item的场景到scene中
+ */
+
+export default class mainScene extends SGraphyScene {
+
+    data: dataInterface | null;
+
+    private _isShowSpace: boolean = true;  // 是否显示空间;
+    private _isShowWallList: boolean = true;  //是否展示墙体;
+    private _isShowEquipmentList: boolean = true; //是否展示设备;
+    private _isShowVrtualWallList: boolean = true; //是否展示虚拟墙
+
+    // 设置是否显示空间
+    get isShowSpace(): boolean {
+        return this._isShowSpace
+    }
+    set isShowSpace(b: boolean) {
+        this._isShowSpace = b
+    }
+
+    // 设置是否显示墙
+    get isShowWallList(): boolean {
+        return this._isShowWallList
+    }
+    set isShowWallList(b: boolean) {
+        this._isShowWallList = b
+    }
+
+    // 设置是否显示设备
+    get isShowEquipmentList(): boolean {
+        return this._isShowEquipmentList
+    }
+    set isShowEquipmentList(b: boolean) {
+        this._isShowEquipmentList = b
+    }
+
+    // 设置是否显示虚拟墙
+    get isShowVrtualWallList(): boolean {
+        return this._isShowVrtualWallList
+    }
+    set isShowVrtualWallList(b: boolean) {
+        this._isShowVrtualWallList = b
+    }
+
+    /**
+     * @param data 绘制空间地图得所有参数
+     */
+
+    constructor(data: dataInterface | null) {
+        super()
+        this.data = data;
+        if (this.data != null) {
+            this.addAllItemList(this.data);
+        }
+    }
+    //获取参数
+    urlGetData(url: string) {
+        let that = this;
+        return new Promise((relove, reject) => {
+            Axios({
+                method: 'get',
+                url: url,
+                data: {},
+                responseType: 'blob',
+                // contentType: "charset=utf-8"
+            }).then(res => {
+                var blob = res.data;
+                this.zipToJson(blob).then((jsonData: any) => {
+                    that.addAllItemList(jsonData)
+                    relove()
+                }).catch((error: any) => {
+                    console.log(error)
+                });
+                // console.log(reader)
+            }).catch(res => {
+                console.log(res)
+            })
+        })
+
+    }
+    // 压缩包变为json格式数据
+    zipToJson(blob: any): any {
+        let data = null;
+        var reader = new FileReader();
+        reader.readAsBinaryString(blob);
+        let _this = this;
+        return new Promise((resolve) => {
+            reader.onload = function (readerEvt: any) {
+                var binaryString = readerEvt.target.result;
+                //解压数据
+                let base64Data = btoa(binaryString)
+                let unGzipData = pako.unzip(base64Data)
+                data = unGzipData;
+                if (data.WallList && data.WallList.length) {
+                    tools.changeMap(data.WallList, -1, "PointList");
+                }
+                if (data.SpaceList && data.SpaceList.length) {
+                    tools.changeMap(data.SpaceList, -1, "Paths");
+                }
+                if (data.ColumnList && data.ColumnList.length) {
+                    tools.changeMap(data.ColumnList, -1, "Path");
+                }
+                if (data.VirtualWallList && data.VirtualWallList.length) {
+                    tools.changeMap(data.VirtualWallList, -1, "PointList");
+                }
+                if (data.EquipmentList && data.EquipmentList.length) {
+                    tools.changeMap(data.EquipmentList, -1, "PointList");
+                }
+                resolve(data)
+            };
+        })
+    }
+    // 以下是绘制方法
+
+    /** 
+     * 增添所有绘制item(地图);
+    */
+    addAllItemList(data: dataInterface) {
+        let space: dataSpaceItem[] = data.SpaceList;
+        // let wall:
+        this.addSpaceList(space) //绘制空间
+        this.addWallList()       //绘制墙
+        let images: ImgItemInterface[] = data.images
+        this.addImageList(images)
+    }
+
+    /**
+     * 添加所有空间到scene 中
+     * @param space 空间list
+     */
+    addSpaceList(space: dataSpaceItem[]): void {
+        if (space && space.length) {
+            for (let i = 0; i < space.length; i++) {
+                if (space[i].Paths[1] && space[i].Paths[1].length >= 2) {
+                    this.addItem(this.constructeItem(
+                        {
+                            parent: null,
+                            space: space[i],
+                            businessType: 'space'
+                        }));
+                }
+            }
+            for (let i = 0; i < space.length; i++) {
+                if (space[i].Paths[0] && space[i].Paths[0].length >= 2 && !space[i].Paths[1]) {
+                    this.addItem(this.constructeItem(
+                        {
+                            parent: null,
+                            space: space[i],
+                            businessType: 'space'
+                        }));
+                }
+            }
+        }
+    }
+    // 绘制墙体
+    addWallList(): void {
+
+    }
+    // 绘制设备
+    addEquipmentList() {
+    }
+    // 绘制柱体
+    addColumnListList(): void {
+    }
+    // 绘制虚拟墙
+    addVrtualWallList(): void {
+    }
+    // 绘制图片
+    addImageList(imageList: ImgItemInterface[]): void {
+        if (imageList && imageList.length) {
+            imageList.map(t => {
+                this.addItem(new SGraphyImgItem(null, t.img, t.X, t.Y, t.width, t.height))
+            })
+        }
+    }
+    /**
+     * 产生item实例
+     */
+    constructeItem(PolygonItemInterfaceData: PolygonItemInterface): SGraphyPolygonItem {
+        return new SGraphyPolygonItem(PolygonItemInterfaceData)
+    }
+    // 鼠标交互类事件
+
+    // 点击
+    click(_this: any, fn: any): void {
+        this.root.children.forEach(item => {
+            item.connect("click", _this, fn);
+        });
+    }
+    // 双击
+    dbclick(_this: any, fn: any): void {
+        this.root.children.forEach(item => {
+            item.connect("doubleClick", _this, fn);
+        });
+    }
+    // 按下
+    mouseDown(_this: any, fn: any) {
+        this.root.children.forEach(item => {
+            item.connect("mouseDown", _this, fn);
+        });
+    }
+    //移动
+    mouseMove(_this: any, fn: any) {
+        this.root.children.forEach(item => {
+            item.connect("mouseMove", _this, fn);
+        });
+    }
+    // 点解结束
+    mouseUp(_this: any, fn: any) {
+        this.root.children.forEach(item => {
+            item.connect("mouseUp", _this, fn);
+        });
+    }
+
+} 

+ 68 - 0
src/assets/graphy/SGraphy/newItems/SGraphyCircleItem.js

@@ -0,0 +1,68 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect } from "@sybotan-web/base";
+import { SColor } from "@sybotan-web/draw";
+/**
+ * 圆Item类
+ *
+ */
+var SGraphyCircleItem = /** @class */ (function (_super) {
+    __extends(SGraphyCircleItem, _super);
+    /**
+     * 构造函数
+     *
+     * @param r          圆半径
+     * @param width      圆线的宽度
+     * @param color      圆线的颜色
+     * @param fillColor  圆填充的颜色
+     * @param parent
+     */
+    function SGraphyCircleItem(parent, r, fillColor, color, width) {
+        if (fillColor === void 0) { fillColor = SColor.White; }
+        if (color === void 0) { color = SColor.Black; }
+        if (width === void 0) { width = 1; }
+        var _this = _super.call(this, parent) || this;
+        _this.fillColor = SColor.White;
+        _this.color = SColor.Black;
+        _this.width = 1;
+        _this.r = r;
+        _this.color = color;
+        _this.fillColor = fillColor;
+        _this.width = width;
+        return _this;
+    } // Constructor()
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    SGraphyCircleItem.prototype.boundingRect = function () {
+        return new SRect(-this.r, -this.r, 2 * this.r, 2 * this.r);
+    }; // Function boundingRect()
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    SGraphyCircleItem.prototype.onDraw = function (painter, rect) {
+        // painter.pen = new SPen(new SColor("#FF0000"), 22);
+        painter.pen.color = this.color;
+        painter.brush.color = this.fillColor;
+        painter.drawCircle(500, 500, this.r);
+    };
+    return SGraphyCircleItem;
+}(SGraphyItem)); // Class SGraphyCircleItem
+export default SGraphyCircleItem;

+ 65 - 0
src/assets/graphy/SGraphy/newItems/SGraphyCircleItem.ts

@@ -0,0 +1,65 @@
+
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect, SSize } from "@sybotan-web/base";
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+
+/**
+ * 圆Item类
+ *
+ */
+export default class SGraphyCircleItem extends SGraphyItem {
+    r: number;
+    fillColor: SColor = SColor.White;
+    color: SColor = SColor.Black;
+    width: number = 1;
+
+    /**
+     * 构造函数
+     *
+     * @param r          圆半径
+     * @param width      圆线的宽度
+     * @param color      圆线的颜色
+     * @param fillColor  圆填充的颜色
+     * @param parent    
+     */
+    constructor(
+        parent: SGraphyItem | null,
+        r: number,
+        fillColor: SColor = SColor.White,
+        color: SColor = SColor.Black,
+        width: number = 1
+    ) {
+        super(parent);
+        this.r = r;
+        this.color = color;
+        this.fillColor = fillColor;
+        this.width = width;
+    } // Constructor()
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect(): SRect {
+        return new SRect(
+            -this.r,
+            -this.r,
+            2 * this.r,
+            2 * this.r
+        );
+    } // Function boundingRect()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    onDraw(painter: SPainter, rect?: SRect): void {
+        // painter.pen = new SPen(new SColor("#FF0000"), 22);
+        painter.pen.color = this.color;
+        painter.brush.color = this.fillColor;
+        painter.drawCircle(500, 500, this.r);
+    }
+} // Class SGraphyCircleItem

+ 111 - 0
src/assets/graphy/SGraphy/newItems/SGraphyImgItem.js

@@ -0,0 +1,111 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect } from "@sybotan-web/base";
+/**
+ * 图形Item类  todo
+ *
+ */
+var SGraphyImgItem = /** @class */ (function (_super) {
+    __extends(SGraphyImgItem, _super);
+    /**
+     * 构造函数
+     *
+     * @param width        		图片宽度
+     * @param height   				图片高度
+     * @param imgSource     	图片源
+     * @param X        				图片向x轴的偏移量
+     * @param Y        				图片向y轴的偏移量
+     * @param parent   				指向父元素
+     */
+    function SGraphyImgItem(parent, imgSource, X, Y, width, height) {
+        var _this = _super.call(this, parent) || this;
+        _this.width = 0;
+        _this.height = 0;
+        _this.imgSource = imgSource;
+        _this.X = X;
+        _this.Y = Y;
+        _this.width = width;
+        _this.height = height;
+        _this.img = new Image();
+        _this.img.src = _this.imgSource;
+        return _this;
+    } // Constructor()
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    SGraphyImgItem.prototype.boundingRect = function () {
+        return new SRect(this.X, this.Y, this.width, this.height);
+    }; // Function boundingRect()
+    // contains(x: number, y: number): boolean {
+    // 	return this.boundingRect().contains(x - this.X, y - this.Y);
+    // }
+    SGraphyImgItem.prototype.onClick = function (event) {
+        this.$emit('click', event);
+        return true;
+    }; // Function onClick()
+    /**
+  * 鼠标双击事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+    SGraphyImgItem.prototype.onDoubleClick = function (event) {
+        this.$emit('doubleClick', event);
+        return true;
+    };
+    /**
+  * 鼠标按下事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+    SGraphyImgItem.prototype.onMouseDown = function (event) {
+        this.$emit('mouseDown', event);
+        return true;
+    }; // Function onMouseDown()
+    /**
+     * 鼠标移动事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    SGraphyImgItem.prototype.onMouseMove = function (event) {
+        this.$emit('mouseMove', event);
+        return true;
+    }; // Function onMouseMove()
+    /**
+     * 释放鼠标事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    SGraphyImgItem.prototype.onMouseUp = function (event) {
+        this.$emit('mouseUp', event);
+        return true;
+    };
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    SGraphyImgItem.prototype.onDraw = function (painter, rect) {
+        painter.drawImage(this.img, this.X, this.Y, this.width, this.height);
+    };
+    return SGraphyImgItem;
+}(SGraphyItem)); // Class SGraphyImgItem
+export { SGraphyImgItem };

+ 116 - 0
src/assets/graphy/SGraphy/newItems/SGraphyImgItem.ts

@@ -0,0 +1,116 @@
+import { SGraphyItem, SMouseEvent } from '@sybotan-web/graphy'
+import { SRect, SSize } from "@sybotan-web/base";
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+
+/**
+ * 图形Item类  todo
+ *
+ */
+export class SGraphyImgItem extends SGraphyItem {
+	imgSource: string; //可以为url,base64
+	X: number;
+	Y: number;
+	width: number = 0;
+	height: number = 0;
+	img: CanvasImageSource
+
+	/**
+	 * 构造函数
+	 * 
+	 * @param width        		图片宽度
+	 * @param height   				图片高度
+	 * @param imgSource     	图片源
+	 * @param X        				图片向x轴的偏移量
+	 * @param Y        				图片向y轴的偏移量
+	 * @param parent   				指向父元素
+	 */
+	constructor(
+		parent: SGraphyItem | null,
+		imgSource: string,
+		X: number,
+		Y: number,
+		width: number,
+		height: number,
+	) {
+		super(parent);
+		this.imgSource = imgSource;
+		this.X = X;
+		this.Y = Y;
+		this.width = width;
+		this.height = height;
+		this.img = new Image();
+		this.img.src = this.imgSource;
+	} // Constructor()
+
+	/**
+	 * Item对象边界区域
+	 * 
+	 * @return SRect
+	 */
+	boundingRect(): SRect {
+		return new SRect(
+			this.X,
+			this.Y,
+			this.width,
+			this.height
+		);
+	} // Function boundingRect()
+	// contains(x: number, y: number): boolean {
+	// 	return this.boundingRect().contains(x - this.X, y - this.Y);
+	// }
+	onClick(event: SMouseEvent): boolean {
+		this.$emit('click', event);
+		return true;
+	} // Function onClick()
+	/**
+  * 鼠标双击事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+	onDoubleClick(event: SMouseEvent): boolean {
+		this.$emit('doubleClick', event);
+		return true;
+	}
+	/**
+  * 鼠标按下事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+	onMouseDown(event: SMouseEvent): boolean {
+		this.$emit('mouseDown', event);
+		return true;
+	} // Function onMouseDown()
+
+	/**
+	 * 鼠标移动事件
+	 *
+	 * @param   event   保存事件参数
+	 * @return  boolean
+	 */
+	onMouseMove(event: SMouseEvent): boolean {
+		this.$emit('mouseMove', event);
+		return true;
+	} // Function onMouseMove()
+
+	/**
+	 * 释放鼠标事件
+	 *
+	 * @param   event   保存事件参数
+	 * @return  boolean
+	 */
+	onMouseUp(event: SMouseEvent): boolean {
+		this.$emit('mouseUp', event);
+		return true;
+	}
+	/**
+	 * Item绘制操作
+	 *
+	 * @param   painter       painter对象
+	 * @param   rect          绘制区域
+	 */
+	onDraw(painter: SPainter, rect?: SRect): void {
+		painter.drawImage(this.img, this.X, this.Y, this.width, this.height);
+	}
+} // Class SGraphyImgItem

+ 70 - 0
src/assets/graphy/SGraphy/newItems/SGraphyPointItem.js

@@ -0,0 +1,70 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect, SPoint } from "@sybotan-web/base";
+import { SColor } from "@sybotan-web/draw";
+/**
+ * 坐标点
+ *
+ */
+var SGraphyPointItem = /** @class */ (function (_super) {
+    __extends(SGraphyPointItem, _super);
+    /**
+     * 构造函数
+     *
+     * @param r          圆半径
+     * @param width      圆线的宽度
+     * @param color      圆线的颜色
+     * @param fillColor  圆填充的颜色
+     * @param parent
+     */
+    function SGraphyPointItem(parent, width, point, color, fillColor) {
+        if (width === void 0) { width = 100; }
+        if (point === void 0) { point = new SPoint(0, 0); }
+        if (color === void 0) { color = new SColor('#F56C6C'); }
+        if (fillColor === void 0) { fillColor = new SColor('#F56C6C'); }
+        var _this = _super.call(this, parent) || this;
+        _this.width = 100;
+        _this.width = width;
+        _this.point = point;
+        _this.color = color;
+        _this.fillColor = fillColor;
+        return _this;
+    } // Constructor()
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    SGraphyPointItem.prototype.boundingRect = function () {
+        var minX = this.point.x;
+        var miny = this.point.y;
+        var maxX = this.point.x + this.width;
+        var maxY = this.point.y + this.width;
+        return new SRect(minX, miny, maxX, maxY);
+    }; // Function boundingRect()
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    SGraphyPointItem.prototype.onDraw = function (painter, rect) {
+        painter.pen.color = this.color;
+        painter.brush.color = this.fillColor;
+        painter.drawRect(this.point.x, this.point.y, this.width, this.width);
+    };
+    return SGraphyPointItem;
+}(SGraphyItem)); // Class SGraphyCircleItem
+export default SGraphyPointItem;

+ 67 - 0
src/assets/graphy/SGraphy/newItems/SGraphyPointItem.ts

@@ -0,0 +1,67 @@
+
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect, SSize, SPoint } from "@sybotan-web/base";
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+/**
+ * 坐标点
+ *
+ */
+export default class SGraphyPointItem extends SGraphyItem {
+    width: number = 100;
+    point: SPoint;
+    color: SColor;
+    fillColor: SColor;
+
+    /**
+     * 构造函数
+     *
+     * @param r          圆半径
+     * @param width      圆线的宽度
+     * @param color      圆线的颜色
+     * @param fillColor  圆填充的颜色
+     * @param parent    
+     */
+    constructor(
+        parent: SGraphyItem | null,
+        width: number = 100,
+        point: SPoint = new SPoint(0, 0),
+        color: SColor = new SColor('#F56C6C'),
+        fillColor: SColor = new SColor('#F56C6C')
+    ) {
+        super(parent);
+        this.width = width;
+        this.point = point;
+        this.color = color;
+        this.fillColor = fillColor;
+   
+    } // Constructor()
+
+    /**
+     * Item对象边界区域
+     * 
+     * @return SRect
+     */
+    boundingRect(): SRect {
+        let minX = this.point.x;
+        let miny = this.point.y;
+        let maxX = this.point.x + this.width;
+        let maxY = this.point.y + this.width;
+        return new SRect(
+            minX,
+            miny,
+            maxX, maxY
+        );
+    } // Function boundingRect()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    onDraw(painter: SPainter, rect?: SRect): void {
+        painter.pen.color = this.color;
+        painter.brush.color = this.fillColor;
+        painter.drawRect(this.point.x,this.point.y,this.width,this.width)
+    }
+} // Class SGraphyCircleItem

+ 212 - 0
src/assets/graphy/SGraphy/newItems/SGraphyPolygonItem.js

@@ -0,0 +1,212 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect, SPoint } from "@sybotan-web/base";
+import { SColor } from "@sybotan-web/draw";
+/**
+ * 不规则多边形Item类
+ *
+ */
+var SGraphyPolygonItem = /** @class */ (function (_super) {
+    __extends(SGraphyPolygonItem, _super);
+    // actived: boolean = false; 				//是否激活
+    /**
+     * 构造函数
+     *
+     * @param pointArr									点坐标list
+     * @param width											边框的宽度
+     * @param color											边框的颜色
+     * @param fillColor   							多边形填充的颜色
+     * @param businessId								空间id
+     * @param businessName							空间名称
+     * @param centerOfGravityPoint			中心点
+     * @param isBusiness								状态
+     * @param parent
+     */
+    function SGraphyPolygonItem(PolygonItemData) {
+        var _this = _super.call(this, PolygonItemData.parent) || this;
+        _this.fillColor = new SColor('#F2F6FC');
+        _this.color = SColor.Black;
+        _this.width = 200;
+        _this.viewText = ''; //绘出的文案
+        _this.isBusiness = 1;
+        _this.cacheColor = SColor.Black; //需要缓存的边框
+        _this.cacheFillColor = new SColor('#F2F6FC'); //需要缓存的填充色
+        _this.cacheWidth = 100;
+        _this.businessType = ''; //类型
+        // 修改绘制路径格式
+        var newSpacePaths = PolygonItemData.space.Paths[0].map(function (item) {
+            return new SPoint(item.X, item.Y);
+        });
+        _this.pointArr = newSpacePaths;
+        // 填充色
+        _this.fillColor = PolygonItemData.space.fillColor ? PolygonItemData.space.fillColor : new SColor('#F2F6FC');
+        // 边框色
+        _this.color = PolygonItemData.space.color ? PolygonItemData.space.color : SColor.Black;
+        //边框宽度
+        _this.width = PolygonItemData.space.width ? PolygonItemData.space.width : 100;
+        //中心点
+        _this.centerOfGravityPoint = {
+            x: PolygonItemData.space.LocationPoint.X,
+            y: -PolygonItemData.space.LocationPoint.Y
+        };
+        //业务空间类型
+        _this.isBusiness = PolygonItemData.space.isBusiness ? PolygonItemData.space.isBusiness : 1;
+        //业务空间id
+        _this.businessId = PolygonItemData.space.businessId ? PolygonItemData.space.businessId : null;
+        //业务空间名称
+        _this.businessName = PolygonItemData.space.Name;
+        _this.initName = PolygonItemData.space.Name;
+        // 空间id
+        _this.id = PolygonItemData.space.id;
+        _this.viewText = PolygonItemData.space.Name;
+        //类型
+        _this.businessType = PolygonItemData.businessType ? PolygonItemData.businessType : '';
+        return _this;
+    }
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    SGraphyPolygonItem.prototype.boundingRect = function () {
+        var minX = this.pointArr[0].x;
+        var maxX = minX;
+        var minY = this.pointArr[0].y;
+        var maxY = minY;
+        for (var i = 1; i < this.pointArr.length; i++) {
+            if (this.pointArr[i].x < minX) {
+                minX = this.pointArr[i].x;
+            }
+            if (this.pointArr[i].y < minY) {
+                minY = this.pointArr[i].y;
+            }
+            if (this.pointArr[i].x > maxX) {
+                maxX = this.pointArr[i].x;
+            }
+            if (this.pointArr[i].y > maxY) {
+                maxY = this.pointArr[i].y;
+            }
+        }
+        return new SRect(minX, minY, maxX - minX, maxY - minY);
+    }; // Function boundingRect()
+    /**
+     * 判断点是否在区域内
+     *
+     * @param x
+     * @param y
+     */
+    SGraphyPolygonItem.prototype.contains = function (x, y) {
+        var nCross = 0, point = [x, y], APoints = this.pointArr, 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.x, p2.x) &&
+                point[0] <= Math.max(p1.x, p2.x)) {
+                if (point[1] <= Math.max(p1.y, p2.y)) {
+                    if (p1.x != p2.x) {
+                        //计算位置信息
+                        xinters = (point[0] - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
+                        if (p1.y == p2.y || point[1] <= xinters) {
+                            nCross++;
+                        }
+                    }
+                }
+            }
+            p1 = p2;
+        }
+        return nCross % 2 === 1;
+    };
+    /**
+     *
+     * @param text 修改的文字
+     * @param centerOfGravityPoint 文字的坐标
+     */
+    SGraphyPolygonItem.prototype.addText = function (text, centerOfGravityPoint) {
+        this.viewText = text;
+        if (centerOfGravityPoint) {
+            this.centerOfGravityPoint = centerOfGravityPoint;
+        }
+    };
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    SGraphyPolygonItem.prototype.onDraw = function (painter, rect) {
+        if (this.pointArr.length) {
+            painter.pen.color = this.color;
+            painter.brush.color = this.fillColor;
+            painter.pen.lineWidth = this.width;
+            painter.drawPolygon(this.pointArr);
+            // let text = ''
+            // if (this.businessName || this.businessId) {
+            // 	text = '👇   ' + this.businessName
+            // } else {
+            // 	text = '⬇️   ' + this.initName
+            // }
+            painter.font.size = this.scale * 200;
+            painter.brush.color = SColor.Black;
+            // painter.drawText(text,this.centerOfGravityPoint.x,this.centerOfGravityPoint.y)
+            painter.drawText(this.viewText, this.centerOfGravityPoint.x, this.centerOfGravityPoint.y);
+        }
+    };
+    SGraphyPolygonItem.prototype.onClick = function (event) {
+        this.$emit('click', { item: this, event: event });
+        return true;
+    }; // Function onClick()
+    /**
+  * 鼠标双击事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+    SGraphyPolygonItem.prototype.onDoubleClick = function (event) {
+        this.$emit('doubleClick', event);
+        return true;
+    };
+    /**
+  * 鼠标按下事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+    SGraphyPolygonItem.prototype.onMouseDown = function (event) {
+        this.$emit('mouseDown', event);
+        return true;
+    }; // Function onMouseDown()
+    /**
+     * 鼠标移动事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    SGraphyPolygonItem.prototype.onMouseMove = function (event) {
+        this.$emit('mouseMove', event);
+        return true;
+    }; // Function onMouseMove()
+    /**
+     * 释放鼠标事件
+     *
+     * @param   event   保存事件参数
+     * @return  boolean
+     */
+    SGraphyPolygonItem.prototype.onMouseUp = function (event) {
+        this.$emit('mouseUp', event);
+        return true;
+    };
+    return SGraphyPolygonItem;
+}(SGraphyItem)); // Class SGraphyPolygonItem
+export default SGraphyPolygonItem;

+ 220 - 0
src/assets/graphy/SGraphy/newItems/SGraphyPolygonItem.ts

@@ -0,0 +1,220 @@
+
+import { SGraphyItem, SMouseEvent } from '@sybotan-web/graphy'
+import { SRect, SSize, SPoint } from "@sybotan-web/base";
+import { SPen, SPainter, SColor, SFont } from "@sybotan-web/draw";
+import { dataItemPath, dataItem, dataSpaceItem, dataInterface, PolygonItemInterface } from './../dataType'   //传入参数的参数接口类型
+/**
+ * 不规则多边形Item类
+ *
+ */
+export default class SGraphyPolygonItem extends SGraphyItem {
+	pointArr: SPoint[];
+	fillColor: SColor = new SColor('#F2F6FC');
+	color: SColor = SColor.Black;
+	width: number = 200;
+	businessId: string | null;
+	id: string | null;
+	centerOfGravityPoint: { x: number, y: number };
+	businessName: null | string | undefined;    //业务空间名字
+	initName: null | string | undefined;        //空间名字
+	viewText: string = ''                        //绘出的文案
+	isBusiness: number = 1;
+	cacheColor: SColor = SColor.Black             //需要缓存的边框
+	cacheFillColor: SColor = new SColor('#F2F6FC');        //需要缓存的填充色
+	cacheWidth: number = 100;
+	businessType: string = ''													//类型
+	// actived: boolean = false; 				//是否激活
+	/**
+	 * 构造函数
+	 *
+	 * @param pointArr									点坐标list
+	 * @param width											边框的宽度
+	 * @param color											边框的颜色
+	 * @param fillColor   							多边形填充的颜色 
+	 * @param businessId								空间id
+	 * @param businessName							空间名称
+	 * @param centerOfGravityPoint			中心点
+	 * @param isBusiness								状态
+	 * @param parent    
+	 */
+	constructor(PolygonItemData: PolygonItemInterface) {
+		super(PolygonItemData.parent);
+		// 修改绘制路径格式
+		let newSpacePaths: SPoint[] = PolygonItemData.space.Paths[0].map(item => {
+			return new SPoint(item.X, item.Y)
+		});
+		this.pointArr = newSpacePaths;
+		// 填充色
+		this.fillColor = PolygonItemData.space.fillColor ? PolygonItemData.space.fillColor : new SColor('#F2F6FC');
+		// 边框色
+		this.color = PolygonItemData.space.color ? PolygonItemData.space.color : SColor.Black;
+		//边框宽度
+		this.width = PolygonItemData.space.width ? PolygonItemData.space.width : 100;
+		//中心点
+		this.centerOfGravityPoint = {
+			x: PolygonItemData.space.LocationPoint.X,
+			y: -PolygonItemData.space.LocationPoint.Y
+		};
+		//业务空间类型
+		this.isBusiness = PolygonItemData.space.isBusiness ? PolygonItemData.space.isBusiness : 1;
+		//业务空间id
+		this.businessId = PolygonItemData.space.businessId ? PolygonItemData.space.businessId : null
+		//业务空间名称
+		this.businessName = PolygonItemData.space.Name;
+		this.initName = PolygonItemData.space.Name;
+		// 空间id
+		this.id = PolygonItemData.space.id;
+		this.viewText = PolygonItemData.space.Name;
+		//类型
+		this.businessType = PolygonItemData.businessType ? PolygonItemData.businessType : ''
+	}
+
+	/**
+	 * Item对象边界区域
+	 * 
+	 * @return SRect
+	 */
+	boundingRect(): SRect {
+		let minX = this.pointArr[0].x;
+		let maxX = minX;
+		let minY = this.pointArr[0].y;
+		let maxY = minY;
+		for (let i = 1; i < this.pointArr.length; i++) {
+			if (this.pointArr[i].x < minX) {
+				minX = this.pointArr[i].x
+			}
+			if (this.pointArr[i].y < minY) {
+				minY = this.pointArr[i].y
+			}
+			if (this.pointArr[i].x > maxX) {
+				maxX = this.pointArr[i].x
+			}
+			if (this.pointArr[i].y > maxY) {
+				maxY = this.pointArr[i].y
+			}
+		}
+
+		return new SRect(
+			minX,
+			minY,
+			maxX - minX,
+			maxY - minY
+		);
+	} // Function boundingRect()
+
+	/**
+	 * 判断点是否在区域内
+	 * 
+	 * @param x 
+	 * @param y 
+	 */
+	contains(x: number, y: number): boolean {
+		let nCross = 0,
+			point = [x, y],
+			APoints = this.pointArr,
+			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.x, p2.x) &&
+				point[0] <= Math.max(p1.x, p2.x)
+			) {
+				if (point[1] <= Math.max(p1.y, p2.y)) {
+					if (p1.x != p2.x) {
+						//计算位置信息
+						xinters = (point[0] - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
+						if (p1.y == p2.y || point[1] <= xinters) {
+							nCross++
+						}
+					}
+				}
+			}
+			p1 = p2;
+		}
+		return nCross % 2 === 1
+	}
+	/**
+	 * 
+	 * @param text 修改的文字
+	 * @param centerOfGravityPoint 文字的坐标
+	 */
+	addText(text: string, centerOfGravityPoint?: { x: number, y: number }) {
+		this.viewText = text;
+		if (centerOfGravityPoint) {
+			this.centerOfGravityPoint = centerOfGravityPoint
+		}
+	}
+	/**
+	 * Item绘制操作
+	 *
+	 * @param   painter       painter对象
+	 * @param   rect          绘制区域
+	 */
+	onDraw(painter: SPainter, rect?: SRect): void {
+		if (this.pointArr.length) {
+			painter.pen.color = this.color;
+			painter.brush.color = this.fillColor;
+			painter.pen.lineWidth = this.width;
+			painter.drawPolygon(this.pointArr)
+			// let text = ''
+			// if (this.businessName || this.businessId) {
+			// 	text = '👇   ' + this.businessName
+			// } else {
+			// 	text = '⬇️   ' + this.initName
+			// }
+			painter.font.size = this.scale * 200;
+			painter.brush.color = SColor.Black;
+			// painter.drawText(text,this.centerOfGravityPoint.x,this.centerOfGravityPoint.y)
+			painter.drawText(this.viewText, this.centerOfGravityPoint.x, this.centerOfGravityPoint.y)
+		}
+	}
+	onClick(event: SMouseEvent): boolean {
+		this.$emit('click', { item: this, event: event });
+		return true;
+	} // Function onClick()
+	/**
+  * 鼠标双击事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+	onDoubleClick(event: SMouseEvent): boolean {
+		this.$emit('doubleClick', event);
+		return true;
+	}
+	/**
+  * 鼠标按下事件
+  *
+  * @param   event   保存事件参数
+  * @return  boolean
+  */
+	onMouseDown(event: SMouseEvent): boolean {
+		this.$emit('mouseDown', event);
+		return true;
+	} // Function onMouseDown()
+
+	/**
+	 * 鼠标移动事件
+	 *
+	 * @param   event   保存事件参数
+	 * @return  boolean
+	 */
+	onMouseMove(event: SMouseEvent): boolean {
+		this.$emit('mouseMove', event);
+		return true;
+	} // Function onMouseMove()
+
+	/**
+	 * 释放鼠标事件
+	 *
+	 * @param   event   保存事件参数
+	 * @return  boolean
+	 */
+	onMouseUp(event: SMouseEvent): boolean {
+		this.$emit('mouseUp', event);
+		return true;
+	}
+
+} // Class SGraphyPolygonItem

+ 74 - 0
src/assets/graphy/SGraphy/newItems/SGraphyRectItem.js

@@ -0,0 +1,74 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect } from "@sybotan-web/base";
+import { SColor } from "@sybotan-web/draw";
+/**
+ * 矩形Item类
+ *
+ */
+var SGraphyRectItem = /** @class */ (function (_super) {
+    __extends(SGraphyRectItem, _super);
+    /**
+     * 构造函数
+     *
+     * @param startX      线的起始x坐标
+   * @param startY      线的起始y坐标
+   * @param width       矩形的宽度
+   * @param height      矩形的宽度
+     * @param color       矩形边框的颜色
+     * @param fillColor   矩形填充的颜色
+     * @param parent
+   * @param isVirtual   是否为虚线
+     */
+    function SGraphyRectItem(parent, startX, startY, width, height, fillColor, color, isVirtual) {
+        if (fillColor === void 0) { fillColor = SColor.White; }
+        if (color === void 0) { color = SColor.Black; }
+        if (isVirtual === void 0) { isVirtual = false; }
+        var _this = _super.call(this, parent) || this;
+        _this.fillColor = SColor.White;
+        _this.color = SColor.Black;
+        _this.isVirtual = false;
+        _this.startX = startX;
+        _this.startY = startY;
+        _this.width = width;
+        _this.height = height;
+        _this.color = color;
+        _this.fillColor = fillColor;
+        _this.isVirtual = isVirtual;
+        return _this;
+    } // Constructor()
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    SGraphyRectItem.prototype.boundingRect = function () {
+        return new SRect(this.startX, this.startY, this.width, this.height);
+    }; // Function boundingRect()
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    SGraphyRectItem.prototype.onDraw = function (painter, rect) {
+        // painter.pen = new SPen(this.color, this.width);
+        painter.pen.color = this.color;
+        painter.brush.color = this.fillColor;
+        painter.drawRect(this.startX, this.startY, this.width, this.height);
+    };
+    return SGraphyRectItem;
+}(SGraphyItem)); // Class SGraphyRectItem
+export default SGraphyRectItem;

+ 76 - 0
src/assets/graphy/SGraphy/newItems/SGraphyRectItem.ts

@@ -0,0 +1,76 @@
+
+import { SGraphyItem } from '@sybotan-web/graphy'
+import { SRect, SSize, SPoint } from "@sybotan-web/base";
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+
+/**
+ * 矩形Item类
+ *
+ */
+export default class SGraphyRectItem extends SGraphyItem {
+  startX: number;
+  startY: number;
+  width: number;
+  height: number;
+  fillColor: SColor = SColor.White;
+  color: SColor = SColor.Black;
+  isVirtual: boolean = false;
+	/**
+	 * 构造函数
+	 *
+	 * @param startX      线的起始x坐标
+   * @param startY      线的起始y坐标
+   * @param width       矩形的宽度
+   * @param height      矩形的宽度
+	 * @param color       矩形边框的颜色 
+	 * @param fillColor   矩形填充的颜色 
+	 * @param parent    
+   * @param isVirtual   是否为虚线
+	 */
+  constructor(
+    parent: SGraphyItem | null,
+    startX: number,
+    startY: number,
+    width: number,
+    height: number,
+    fillColor: SColor = SColor.White,
+    color: SColor = SColor.Black,
+    isVirtual: boolean = false
+  ) {
+    super(parent);
+    this.startX = startX
+    this.startY = startY
+    this.width = width;
+    this.height = height
+    this.color = color;
+    this.fillColor = fillColor;
+    this.isVirtual = isVirtual;
+  } // Constructor()
+
+	/**
+	 * Item对象边界区域
+	 * 
+	 * @return SRect
+	 */
+  boundingRect(): SRect {
+    return new SRect(
+      this.startX,
+      this.startY,
+      this.width,
+      this.height
+    );
+  } // Function boundingRect()
+
+	/**
+	 * Item绘制操作
+	 *
+	 * @param   painter       painter对象
+	 * @param   rect          绘制区域
+	 */
+  onDraw(painter: SPainter, rect?: SRect): void {
+    // painter.pen = new SPen(this.color, this.width);
+    painter.pen.color = this.color;
+    painter.brush.color = this.fillColor;
+    painter.drawRect(this.startX, this.startY, this.width, this.height)
+  }
+} // Class SGraphyRectItem

+ 92 - 0
src/assets/graphy/SGraphy/newItems/SGraphyWallItem.js

@@ -0,0 +1,92 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+import { SGraphyItem } from '@sybotan-web/graphy';
+import { SRect } from "@sybotan-web/base";
+import { SColor } from "@sybotan-web/draw";
+/**
+ * 墙Item类
+ *
+ */
+var SGraphyWallItem = /** @class */ (function (_super) {
+    __extends(SGraphyWallItem, _super);
+    /**
+     * 构造函数
+     *
+     * @param pointArr  		点坐标list
+     * @param isVirtual 		墙类型(实体墙-虚拟墙)
+     * @param color  				墙的颜色
+     * @param fillColor  		墙的填充颜色
+     * @param width   			墙的宽度
+     * @param parent
+     */
+    function SGraphyWallItem(parent, pointArr, isVirtual, fillColor, color, width) {
+        if (isVirtual === void 0) { isVirtual = false; }
+        if (fillColor === void 0) { fillColor = SColor.White; }
+        if (color === void 0) { color = SColor.Black; }
+        if (width === void 0) { width = 1; }
+        var _this = _super.call(this, parent) || this;
+        _this.isVirtual = false;
+        _this.fillColor = SColor.White;
+        _this.color = SColor.Black;
+        _this.width = 1;
+        _this.isVirtual = isVirtual;
+        _this.pointArr = pointArr;
+        _this.color = color;
+        _this.fillColor = fillColor;
+        _this.width = width;
+        return _this;
+    } // Constructor()
+    /**
+     * Item对象边界区域
+     *
+     * @return SRect
+     */
+    SGraphyWallItem.prototype.boundingRect = function () {
+        var minX = this.pointArr[0].x;
+        var maxX = minX;
+        var minY = this.pointArr[0].y;
+        var maxY = minY;
+        for (var i = 1; i < this.pointArr.length; i++) {
+            if (this.pointArr[i].x < minX) {
+                minX = this.pointArr[i].x;
+            }
+            if (this.pointArr[i].y < minY) {
+                minY = this.pointArr[i].y;
+            }
+            if (this.pointArr[i].x > maxX) {
+                maxX = this.pointArr[i].x;
+            }
+            if (this.pointArr[i].y > maxY) {
+                maxY = this.pointArr[i].y;
+            }
+        }
+        return new SRect(minX, minY, maxX - minX, maxY - minY);
+    }; // Function boundingRect()
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     * @param   rect          绘制区域
+     */
+    SGraphyWallItem.prototype.onDraw = function (painter, rect) {
+        if (this.pointArr.length) {
+            // painter.pen = new SPen(this.color, this.width);
+            painter.pen.color = this.color;
+            painter.brush.color = this.fillColor;
+            painter.drawPolyline(this.pointArr);
+        }
+    };
+    return SGraphyWallItem;
+}(SGraphyItem)); // Class SGraphyPolygonItem
+export default SGraphyWallItem;

+ 89 - 0
src/assets/graphy/SGraphy/newItems/SGraphyWallItem.ts

@@ -0,0 +1,89 @@
+
+import { SGraphyItem } from '@sybotan-web/graphy'
+import { SRect, SSize, SPoint } from "@sybotan-web/base";
+import { SPen, SPainter, SColor } from "@sybotan-web/draw";
+
+/**
+ * 墙Item类
+ *
+ */
+export default class SGraphyWallItem extends SGraphyItem {
+	pointArr: SPoint[];
+	isVirtual: boolean = false;
+	fillColor: SColor = SColor.White;
+	color: SColor = SColor.Black;
+	width: number = 1;
+	/**
+	 * 构造函数
+	 *
+	 * @param pointArr  		点坐标list
+	 * @param isVirtual 		墙类型(实体墙-虚拟墙)
+	 * @param color  				墙的颜色
+	 * @param fillColor  		墙的填充颜色
+	 * @param width   			墙的宽度
+	 * @param parent    
+	 */
+	constructor(
+		parent: SGraphyItem | null,
+		pointArr: SPoint[],
+		isVirtual: boolean = false,
+		fillColor: SColor = SColor.White,
+		color: SColor = SColor.Black,
+		width: number = 1,
+	) {
+		super(parent);
+		this.isVirtual = isVirtual;
+		this.pointArr = pointArr;
+		this.color = color;
+		this.fillColor = fillColor;
+		this.width = width;
+	} // Constructor()
+
+	/**
+	 * Item对象边界区域
+	 * 
+	 * @return SRect
+	 */
+	boundingRect(): SRect {
+		let minX = this.pointArr[0].x;
+		let maxX = minX;
+		let minY = this.pointArr[0].y;
+		let maxY = minY;
+		for (let i = 1; i < this.pointArr.length; i++) {
+			if (this.pointArr[i].x < minX) {
+				minX = this.pointArr[i].x
+			}
+			if (this.pointArr[i].y < minY) {
+				minY = this.pointArr[i].y
+			}
+			if (this.pointArr[i].x > maxX) {
+				maxX = this.pointArr[i].x
+			}
+			if (this.pointArr[i].y > maxY) {
+				maxY = this.pointArr[i].y
+			}
+		}
+
+		return new SRect(
+			minX,
+			minY,
+			maxX - minX,
+			maxY - minY
+		);
+	} // Function boundingRect()
+
+	/**
+	 * Item绘制操作
+	 *
+	 * @param   painter       painter对象
+	 * @param   rect          绘制区域
+	 */
+	onDraw(painter: SPainter, rect?: SRect): void {
+		if (this.pointArr.length) {
+			// painter.pen = new SPen(this.color, this.width);
+			painter.pen.color = this.color;
+			painter.brush.color = this.fillColor;
+			painter.drawPolyline(this.pointArr)
+		}
+	}
+} // Class SGraphyPolygonItem

+ 40 - 0
src/assets/graphy/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/graphy/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

+ 25 - 0
src/assets/graphy/SGraphy/until/pako.js

@@ -0,0 +1,25 @@
+// import pako from 'pako'
+var pako = require('pako');
+var funcTo = atob;
+console.log(funcTo);
+var 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' });
+        return eval("(" + data + ")");
+    },
+    // 压缩
+    zip: function (str) {
+        //escape(str)  --->压缩前编码,防止中午乱码
+        var binaryString = pako.gzip(escape(str), { to: 'string' });
+        return binaryString;
+    }
+};
+export default pakoObj;

+ 27 - 0
src/assets/graphy/SGraphy/until/pako.ts

@@ -0,0 +1,27 @@
+// import pako from 'pako'
+let pako = require('pako');
+let funcTo = atob
+console.log(funcTo)
+
+const pakoObj = {
+    unzip: function unzip(b64Data:any) {
+        // 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' });
+        return eval("(" + data + ")");
+    },
+    // 压缩
+    zip: function(str:any) {
+        //escape(str)  --->压缩前编码,防止中午乱码
+        var binaryString = pako.gzip(escape(str), { to: 'string' });
+        return binaryString;
+    }
+}
+
+export default pakoObj

+ 22 - 0
src/assets/graphy/SGraphy/until/tool.js

@@ -0,0 +1,22 @@
+var tools = {
+    changeMap: function (arr, k, name) {
+        var data = arr.map(function (items) {
+            if (items[name] && items[name].length) {
+                items[name].map(function (children) {
+                    if (Array.isArray(children)) {
+                        return children.map(function (res) {
+                            res.Y = res.Y * k;
+                            return res;
+                        });
+                    }
+                    else {
+                        children.Y = children.Y * k;
+                        return children;
+                    }
+                });
+            }
+        });
+        return data;
+    }
+};
+export default tools;

+ 21 - 0
src/assets/graphy/SGraphy/until/tool.ts

@@ -0,0 +1,21 @@
+let tools = {
+    changeMap(arr: any, k: any, name: any) {
+        let data = arr.map((items: any) => {
+            if (items[name] && items[name].length) {
+                items[name].map((children: any) => {
+                    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
+    }
+}
+export default tools

+ 14 - 0
src/assets/graphy/index.js

@@ -0,0 +1,14 @@
+
+import SGraphyPolygonItem from './SGraphy/newItems/SGraphyPolygonItem.js'
+import SGraphyCircleItem from './SGraphy/items/SGraphyCircleItem'
+import SGraphyImageItem from './SGraphy/items/SGraphyImageItem'
+import SGraphyPillarItems from './SGraphy/items/SGraphyPillarItems'
+import SGraphyTextItems from './SGraphy/items/SGraphyTextItems'
+import SGraphyVirtualItem from './SGraphy/items/SGraphyVirtualItem'
+import mainScene from './SGraphy/mainScene.js'
+import SGraphyRectItem from './SGraphy/newItems/SGraphyRectItem.js' 
+
+import SGraphyView from './SGraphy/SGraphyView';
+import SGraphyScene from './SGraphy/SGraphyScene'
+import SGraphyLineItem from './SGraphy/items/SGraphyLineItem'
+export {SGraphyView,SGraphyScene,SGraphyLineItem,mainScene,SGraphyRectItem, SGraphyPolygonItem, SGraphyCircleItem, SGraphyImageItem, SGraphyPillarItems, SGraphyTextItems, SGraphyVirtualItem }

BIN
src/assets/image/floorBG.png


BIN
src/assets/image/model/arrowBlue.png


BIN
src/assets/image/model/arrowGray.png


BIN
src/assets/image/model/arrowGreen.png


BIN
src/assets/image/model/columnBlue.png


BIN
src/assets/image/model/columnGray.png


BIN
src/assets/image/model/columnGreen.png


BIN
src/assets/image/model/delModelBlue.png


BIN
src/assets/image/model/delModelGray.png


BIN
src/assets/image/model/downJsonBlue.png


BIN
src/assets/image/model/downJsonGray.png


BIN
src/assets/image/model/downJsonGreen.png


BIN
src/assets/image/model/downModelBlue.png


BIN
src/assets/image/model/downModelGray.png


BIN
src/assets/image/model/downModelGreen.png


+ 0 - 0
src/assets/image/model/rightDownBlue.png


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