219 Commits 2098857d48 ... fa49a92197

Author SHA1 Message Date
  LXXXY fa49a92197 整合,采用传入的更改 5 years ago
  LXXXY 1aeb126f90 Merge branch 'apiupdate' of http://39.106.8.246:3003/web/ibms into apiupdate 5 years ago
  LXXXY a0cac4f599 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY c73164ecfb 竖井业务空间类型 5 years ago
  zhangyu 9e4d659805 Merge branch 'msg-sever' of git.sagacloud.cn:web/ibms into msg-sever 5 years ago
  zhangyu 7441035f82 模型验证任务高亮(ing...) 5 years ago
  yangjunjing 728210b822 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  yangjunjing 422204b238 消息中心 5 years ago
  LXXXY 883f4c072d Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY ccf8b23008 竖井台账关联业务空间 5 years ago
  haojianlong 7dd05c0ea1 建筑楼层新增下载json 5 years ago
  haojianlong 501b4bae36 新增下载json 5 years ago
  yangjunjing 3c427bc242 更改button文案 5 years ago
  haojianlong f205eb52e5 业务空间交互修改 5 years ago
  haojianlong 8d3c4d82fd Merge branch 'master' into msg-sever 5 years ago
  haojianlong 092cd7729b 修改业务空间 表号功能号只读模式未展示数据问题 5 years ago
  yangjunjing c082dc2389 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  yangjunjing 15eb00e0bf 现场任务管理,文案,页面传参修改 5 years ago
  haojianlong ce54e31fbd 传参添加query 5 years ago
  haojianlong 3fc4226d22 修改业务空间交互 5 years ago
  haojianlong 6a2bc6ac34 Merge branch 'msg-sever' into zonesp 5 years ago
  haojianlong 044211892c 业务空间交互修改 5 years ago
  LXXXY d89f0af961 空间名超出显示... 5 years ago
  haojianlong 2b6b84791b Merge branch 'msg-sever' into zonesp 5 years ago
  LXXXY 2d0e610ab3 修改选择框间距 5 years ago
  LXXXY 4acec24bf3 系统详情页面调修 5 years ago
  LXXXY 95aaf475d1 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY cce252c7fc 系统详情调修 5 years ago
  haojianlong c12c2d119a 修改业务空间 交互 5 years ago
  zhangyu b192c9359d Merge branch 'msg-sever' of git.sagacloud.cn:web/ibms into msg-sever 5 years ago
  zhangyu 8eca0326f6 健壮性修改 5 years ago
  LXXXY d91f7e7197 系统台账详情页 5 years ago
  LXXXY 563c0b9b7e Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY 57eab9a1fb 系统对业务空间接口调试 5 years ago
  haojianlong b62a520b8b fix conflict 5 years ago
  haojianlong 574b2bb5a6 删除系统台账列表页 关联设备数量 列 5 years ago
  haojianlong 4346151102 修改未关联平面图的业务空间 5 years ago
  LXXXY 5649d6a044 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  haojianlong ce546057cd 未关联平面图的业务空间关联建筑楼层 5 years ago
  LXXXY c6c1833150 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY 909733b547 系统未关联业务空间 5 years ago
  haojianlong ec9d69fdbf x修改设备台账 关联资产 只在编辑模式生效 5 years ago
  haojianlong 6449b14a71 修改业务空间 5 years ago
  zhangyu 69df915483 Merge branch 'master' into msg-sever 5 years ago
  zhangyu b9ba31ec90 Merge branch 'msg-sever' of git.sagacloud.cn:web/ibms into msg-sever 5 years ago
  zhangyu 20908b6d3c 修改文案 5 years ago
  haojianlong ee21d33e50 修改请求超时时间 5 years ago
  haojianlong cf72948bbe 业务空间逻辑修改 5 years ago
  LXXXY e565f3ecc9 Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY 444312e8f9 系统删除竖井接口调试 5 years ago
  zhangyu c74fcfd78e Merge branch 'msg-sever' of git.sagacloud.cn:web/ibms into msg-sever 5 years ago
  zhangyu e846580d6e 接口调试 5 years ago
  LXXXY 8c7c6c3261 系统未关联设备,竖井,业务空间接口,关联设备,删除设备接口调试 5 years ago
  LXXXY f6e093963e Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  zhangyu a91dff8a16 解决冲突 5 years ago
  zhangyu 97992d555e Merge branch 'systz' of git.sagacloud.cn:web/ibms into systz 5 years ago
  zhangyu f56b2adeb9 详情调试(未完成) 5 years ago
  haojianlong 42643bfaf8 Merge branch 'zonesp' into systz 5 years ago
  haojianlong b862656ae6 业务空间平面图操作修改 5 years ago
  haojianlong 82cca8c3a4 建筑楼层平面图划分 5 years ago
  LXXXY 59afdebf97 系统台账详情页,所属建筑楼层关联 5 years ago
  haojianlong ab176ebd6c Merge branch 'zonesp' 5 years ago
  zhangyu cb7f654105 删除无用代理 5 years ago
  zhangyu d97352bc72 下载地址修改 5 years ago
  haojianlong 65c81ef572 空间iframe只读编辑路径修改 5 years ago
  zhangyu e2159312c1 Merge branch 'task-manage' into msg-sever 5 years ago
  zhangyu 9623cc4ad1 接口调试 5 years ago
  haojianlong 7f844cab62 修改提示 5 years ago
  zhangyu a1bce743d0 接口调试 5 years ago
  LXXXY ac172255eb 返回系统台账添加回参 5 years ago
  haojianlong cbcd1af5e5 取消设备台账 修改资产彩蛋 5 years ago
  LXXXY 4c91d8b03d Merge branch 'systz' of http://39.106.8.246:3003/web/ibms into systz 5 years ago
  LXXXY f5b6f28d52 详情页删除系统 5 years ago
  haojianlong 4a8ebd3265 业务空间修改建筑楼层功能添加;删除工具栏移动按钮 5 years ago
  zhangyu bfc3480f53 接口调试 5 years ago
  zhangyu 71cd0eb15f 接口调试 5 years ago
  haojianlong e10b608ee9 Merge branch 'master' into zonesp 5 years ago
  haojianlong 1bebefcb75 修改业务空间添加空间内设备查询报错问题 5 years ago
  zhangyu b663a31c93 消息通知相关修改 5 years ago
  zhangyu b2bbc81e7c 调试消息中心 5 years ago
  haojianlong 093ab46e72 修改工具类 高度/1000 5 years ago
  zhangyu 1e81b537ff 消息通知 5 years ago
  haojianlong 29cab5a924 修改无数据 默认高度0 5 years ago
  haojianlong 8e5bdfaa23 Merge branch 'dktest' 5 years ago
  haojianlong b209071f2e 系统集成功能第三部 以及 配置动参 自动匹配 业务空间工具修改 5 years ago
  LXXXY 292bdd916f 资产详情和任务详情 5 years ago
  LXXXY 3cfac4cd4c Merge branch 'msg-sever' of http://39.106.8.246:3003/web/ibms into msg-sever 5 years ago
  LXXXY 5dab816405 任务详情页面 5 years ago
  LXXXY b368d96a1e Merge branch 'task-manage' of http://39.106.8.246:3003/web/ibms into task-manage 5 years ago
  zhangyu 296d974bdd 任务页面调试 5 years ago
  LXXXY b866dc5768 修改date2Stringbug 5 years ago
  haojianlong e5e8c880e3 修改业务空间平面图重复加载问题 5 years ago
  zhangyu 35963650b6 接口调试 5 years ago
  haojianlong 92081a495d 添加系统所属建筑楼层 5 years ago
  haojianlong 45583b0c37 业务空间可修改建筑楼层 5 years ago
  haojianlong 05173aa29d Merge branch 'master' into zonesp 5 years ago
  zhangyu a35677e9b7 模型验证任务联调 5 years ago
  haojianlong 0772bb8b62 Merge branch 'master' into systz 5 years ago
  haojianlong 071d71a57e 添加大图功能 修改部分图片无法显示bug 5 years ago
  LXXXY 0c29221f9d 添加设备设备类别设为该系统子类别 5 years ago
  LXXXY fcb2a4c0d6 系统详情加上参数SysType,设备类别为系统的子类别 5 years ago
  haojianlong 9308c3660e 添加传参系统类型 5 years ago
  haojianlong 1a3646ab6e 修改 5 years ago
  haojianlong 9dba33e9fb 业务空间切分 5 years ago
  haojianlong d8fa925835 Merge branch 'master' into systz 5 years ago
  haojianlong cda365f055 Merge branch 'device' 5 years ago
  haojianlong d73e8ff7b4 Merge branch 'dktest' into device 5 years ago
  haojianlong f412f95cc2 修改线上子系统点位接入级联报错问题 5 years ago
  zhangyu 176a1c84b5 接口调试 5 years ago
  LXXXY 97563d59eb 给刷新按钮一个默认的块 5 years ago
  LXXXY fb8c1f8079 对应值-获取时间列调整 5 years ago
  LXXXY 1e46c3dbd0 删除1对多上面的线 5 years ago
  LXXXY 5ef14819c9 修改添加业务空间表头 5 years ago
  LXXXY 4248ed5414 系统台账添加页面【设备,竖井,空间】 5 years ago
  haojianlong d60aee8f33 Merge branch 'dktest' into device 5 years ago
  LXXXY 0e22878b6a 对象实例打开时,canvas填满剩余宽度 5 years ago
  LXXXY fe7dc1c15f 1:环形图数字变大 2:1对多多对一信息位置变更,表格按钮改成hover显示 5 years ago
  haojianlong 4aa4c6ccc1 modify clear position 5 years ago
  haojianlong 37ca97f7e3 fix clear data 5 years ago
  haojianlong 9b316f6c2e fix update si outline fix online groupcreatezone 5 years ago
  zhangyu 409f20370a 接口调试 5 years ago
  haojianlong 9f9f868dd0 delete nouse code 5 years ago
  haojianlong a063872c64 fix replace floormap bug 5 years ago
  haojianlong ee1ff8f74a Merge branch 'master' of http://39.106.8.246:3003/web/ibms 5 years ago
  haojianlong ba95bf09d5 modify canvas showtype 5 years ago
  zhangyu f1c0910581 MQ正式环境地址修改 5 years ago
  zhangyu fb97ffff80 Merge branch 'master' of git.sagacloud.cn:web/ibms 5 years ago
  zhangyu 3893f2eea6 增加显示数量 5 years ago
  haojianlong 30cfbe3bab Merge branch 'master' of http://39.106.8.246:3003/web/ibms 5 years ago
  haojianlong db39bc1168 modify canvas tools css 5 years ago
  zhangyu 3b3e4807c9 Merge branch 'master' of git.sagacloud.cn:web/ibms 5 years ago
  zhangyu b22e71ed94 建筑楼层和模型文件管理暂时隐藏 5 years ago
  haojianlong 8d8784ac96 modify change zoneSpace selection 5 years ago
  zhangyu 7274d56ce4 Merge branch 'master' of git.sagacloud.cn:web/ibms 5 years ago
  zhangyu a0d99e5d05 修改子系统点位接入问题 5 years ago
  haojianlong 2687cb810c hide zoneSpace Outline 5 years ago
  haojianlong 468bd03019 update engine version 5 years ago
  haojianlong d91fb56ebd Merge branch 'master' of http://39.106.8.246:3003/web/ibms 5 years ago
  haojianlong 1961bba673 update cad-engine version 5 years ago
  zhangyu c71822a9f8 Merge branch 'master' of git.sagacloud.cn:web/ibms 5 years ago
  zhangyu ba50b4ea77 配置线上MQ内网代理 5 years ago
  haojianlong f9fd4de3c8 update canvas package 5 years ago
  zhangyu f313538247 添加现场任务接口 5 years ago
  haojianlong 290345f83e modify data format 5 years ago
  haojianlong e9a5c4670a Merge branch 'device' 5 years ago
  haojianlong f7849da38b Merge branch 'dktest' into device 5 years ago
  haojianlong f203088bd3 add successs toast 5 years ago
  haojianlong 3b9b7af7b1 Merge branch 'master' of http://39.106.8.246:3003/web/ibms 5 years ago
  haojianlong 2674554f4d fix import zonespace outline 5 years ago
  zhangyu d0e5e12223 添加mq线上地址 5 years ago
  haojianlong 80cfc6354b Merge branch 'device' 5 years ago
  haojianlong 98fdb0c91c add import data outline 5 years ago
  zhangyu 4f85327eff 修改添加其他数据源产生的一些逻辑修改 5 years ago
  zhangyu 9ec2776d93 详情页样式布局 5 years ago
  zhangyu f4588a1650 详情页开发 5 years ago
  haojianlong 1a92c97cfa add error catch and modify bind data 5 years ago
  LXXXY 8614046a3c Merge branch 'systz' of http://39.106.8.246:3003/web/ibms into systz 5 years ago
  haojianlong c283705f1f modify system ledger 5 years ago
  zhangyu 682fe60c29 子系统点位接入添加其他数据源 5 years ago
  LXXXY 6b0a3d6f2a 系统集成统计样式微调 5 years ago
  LXXXY 32d9f81e9c 解决环形图被压缩和字体颜色问题 5 years ago
  haojianlong 40ea0565b4 modify npm package and add catch error 5 years ago
  haojianlong a03dc40c8c add space scenemark 5 years ago
  LXXXY 722c305082 Merge branch 'dktest' of http://39.106.8.246:3003/web/ibms into dktest 5 years ago
  LXXXY c8cf7da812 环形图颜色,弹出框调整 5 years ago
  haojianlong 5135dd87d1 merge device 5 years ago
  haojianlong e960a75b69 add zone location 5 years ago
  zhangyu 64273dc22f 添加详情页 5 years ago
  zhangyu 00335c2293 添加其他数据源 5 years ago
  LXXXY 81d0f91883 样式调整 5 years ago
  zhangyu c6cba22aa0 修改 5 years ago
  zhangyu baeec18e6a 添加模型表格监听条件的变化 5 years ago
  LXXXY c792f84f77 替换canvas画图引用 5 years ago
  haojianlong af45123385 add new canvas package 5 years ago
  haojianlong ff6e6b3d47 add floor orders 5 years ago
  haojianlong 3f86aa87b6 fix order bug 5 years ago
  zhangyu 0130076ad8 修改查询表号功能号不同状态时显示的文案 5 years ago
  zhangyu 81c08524fb 切换任务类型条件变更 5 years ago
  zhangyu b31c635093 添加模型文件筛选 5 years ago
  LXXXY cf7ee1d367 数据源接口调整 5 years ago
  LXXXY 83b8a6e29d 原始点位总数修改 5 years ago
  LXXXY 175042a41c 标号功能号总览样式调整 5 years ago
  zhangyu a7c1a1a062 对象类型排序修改 5 years ago
  zhangyu cafa516788 现场验证任务页面开发 5 years ago
  LXXXY a8ba8de44d 数据为空时处理 5 years ago
  LXXXY f336b94e33 解决刷新系统集成成果页面js报错bug 5 years ago
  LXXXY c545243eeb 代码优化 5 years ago
  LXXXY 95f6da40fe Merge branch 'dktest' of http://39.106.8.246:3003/web/ibms into dktest 5 years ago
  LXXXY 9e3d76e552 代码优化 5 years ago
  haojianlong 0cd933cb12 merge device 5 years ago
  zhangyu bd14493f6c 添加字体图标 5 years ago
  zhangyu 79c1333ec0 合并 5 years ago
  zhangyu 1af29b99b1 现场任务管理开发 5 years ago
  LXXXY ff08b1efc9 代码优化 5 years ago
  LXXXY 25984a2749 修改objectInstance.vue 5 years ago
  LXXXY 6afa7e635f 代码优化 5 years ago
  LXXXY 67e5dd0058 修改图表颜色 5 years ago
  LXXXY bc15ba3de1 新建完成,重载整个页面 5 years ago
  LXXXY 34be72337e 修改canvas绘制 5 years ago
  LXXXY f486cb6877 Merge branch 'dktest' of http://39.106.8.246:3003/web/ibms into dktest 5 years ago
  LXXXY f8f8ad33f2 接口完善,实例canvas绘制 5 years ago
  haojianlong 454fddefcb Merge branch 'device' into dktest 5 years ago
  LXXXY 96fab14dcd 更改默认页数,总览Data为空处理,新建成功关闭弹窗 5 years ago
  LXXXY fba8aa99dc 修改总览中断数图标错位 5 years ago
  LXXXY 44fe0d268c 系统集成成果管理接口调整及完善 5 years ago
  LXXXY f51d4c82c8 点位,实例,加入查询时loading,表号功能号断数显示,弹出层高度调整 5 years ago
  LXXXY f96986db27 表号功能号总览,原始点位,总览,点查询,实例查询接口对接, 5 years ago
  LXXXY c04b6cc2ff Merge branch 'device' of http://39.106.8.246:3003/web/ibms into device 5 years ago
  LXXXY 321901aadd 接口 5 years ago
  zhangyu 623c4bcc05 现场验证任务首页开发 5 years ago
  LXXXY 73bdc608e6 系统集成成果管理页面 5 years ago
  LXXXY 0a119c8ee9 Merge remote-tracking branch 'origin/spaceup' into dktest 5 years ago
  LXXXY f63a431cbc 系统集成报告页面 5 years ago
  zhangyu 4ede727dc2 添加选择弹窗 5 years ago
  zhangyu d4f0a194f7 Merge branch 'taskmanage' into task-manage 5 years ago
  zhangyu 72dfb7f28c 添加 5 years ago
  LXXXY 42af0bcf9a 无关 5 years ago
  zhangyu 8c1f0b4768 合并任务类型 5 years ago
  zhangyu 0a3b65e291 添加现场任务管理统计卡片组件 5 years ago
100 changed files with 8366 additions and 605 deletions
  1. 2 2
      config/dev.env.js
  2. 1 1
      config/index.js
  3. 2 2
      config/prod.env.js
  4. 7 0
      package.json
  5. 109 0
      src/api/data_admin/buildTaskApi.js
  6. 1 1
      src/api/httputils.js
  7. 3 0
      src/api/model/file.js
  8. 56 0
      src/api/msgsever.js
  9. 71 12
      src/api/scan/request.js
  10. BIN
      src/assets/house.jpg
  11. 99 7
      src/assets/style/iconfont/iconfont.css
  12. BIN
      src/assets/style/iconfont/iconfont.eot
  13. 130 61
      src/assets/style/iconfont/iconfont.svg
  14. BIN
      src/assets/style/iconfont/iconfont.ttf
  15. BIN
      src/assets/style/iconfont/iconfont.woff
  16. 93 11
      src/components/business_space/business/handsontable.vue
  17. 1 9
      src/components/business_space/dialogs/list/uploadImgDialog.vue
  18. 13 27
      src/components/business_space/lib/detailsDia.vue
  19. 3 3
      src/components/business_space/lib/uploadImgs.vue
  20. 1 1
      src/components/business_space/lib/uploadImgsName.vue
  21. 2 0
      src/components/business_space/newAddDialogs/addEquipDialog.vue
  22. 50 15
      src/components/business_space/newGraphy/canvasFun.vue
  23. 352 175
      src/components/business_space/newGraphy/graphy.vue
  24. 137 27
      src/components/business_space/newGraphy/unRelateBSP.vue
  25. 1 0
      src/components/common/myPagination.vue
  26. 24 8
      src/components/config_point/dictionaryCascader.vue
  27. 2 2
      src/components/config_point/examine_main.vue
  28. 0 2
      src/components/config_point/find_keyword.vue
  29. 18 2
      src/components/config_point/select_one.vue
  30. 17 17
      src/components/config_point/step3_edit/index.vue
  31. 9 2
      src/components/config_point/step3_point/3_identify.vue
  32. 129 40
      src/components/config_point/step3_point/3_temps.vue
  33. 9 2
      src/components/config_point/step3_point/dialog_main.vue
  34. 20 8
      src/components/config_point/step3_point/steps3_main.vue
  35. 184 0
      src/components/data_admin/buildTask/detail/assetsDetail.vue
  36. 219 0
      src/components/data_admin/buildTask/detail/deviceDetail.vue
  37. 97 0
      src/components/data_admin/buildTask/dialog/addTaskDialog.vue
  38. 253 0
      src/components/data_admin/buildTask/dialog/modelTaskDialog.vue
  39. 181 0
      src/components/data_admin/buildTask/draw/drawModel.vue
  40. 70 0
      src/components/data_admin/buildTask/lib/assetsCascader.vue
  41. 70 0
      src/components/data_admin/buildTask/lib/deviceCascader.vue
  42. 70 0
      src/components/data_admin/buildTask/lib/modelCascader.vue
  43. 81 0
      src/components/data_admin/buildTask/lib/modelFile.vue
  44. 53 0
      src/components/data_admin/buildTask/lib/taskState.vue
  45. 220 0
      src/components/data_admin/buildTask/table/assetsTable.vue
  46. 248 0
      src/components/data_admin/buildTask/table/deviceTable.vue
  47. 238 0
      src/components/data_admin/buildTask/table/modelTable.vue
  48. 202 0
      src/components/data_admin/buildTask/table/replaceTable.vue
  49. 202 0
      src/components/data_admin/buildTask/table/tearTable.vue
  50. 160 0
      src/components/data_admin/buildTask/taskStatistics.vue
  51. 1 9
      src/components/dialogs/list/uploadImgDialog.vue
  52. 225 0
      src/components/ledger/cenote/dialog/addSpaceDialog.vue
  53. 5 4
      src/components/ledger/handsontables/assets.vue
  54. 18 18
      src/components/ledger/handsontables/device.vue
  55. 45 49
      src/components/ledger/handsontables/system.vue
  56. 1 1
      src/components/ledger/lib/assets.vue
  57. 1 1
      src/components/ledger/lib/cascader.vue
  58. 83 0
      src/components/ledger/lib/editSysFloor.vue
  59. 6 5
      src/components/ledger/lib/floorCascader.vue
  60. 65 0
      src/components/ledger/lib/spaceSelect.vue
  61. 17 4
      src/components/ledger/lib/uploadImgs.vue
  62. 1 1
      src/components/ledger/lib/uploadImgsName.vue
  63. 180 0
      src/components/ledger/system/dialog/addCenoteDialog.vue
  64. 209 0
      src/components/ledger/system/dialog/addEquipDialog.vue
  65. 225 0
      src/components/ledger/system/dialog/addSpaceDialog.vue
  66. 140 0
      src/components/ledger/system/lib/equipType.vue
  67. 156 0
      src/components/ledger/system/table/cenoteTable.vue
  68. 144 0
      src/components/ledger/system/table/deviceTable.vue
  69. 156 0
      src/components/ledger/system/table/spaceTable.vue
  70. 1 1
      src/components/point/dynamicdata/applyRulesDialog.vue
  71. 66 0
      src/components/point/dynamicdata/autoGroupRelaDialog.vue
  72. 4 4
      src/components/point/dynamicdata/delRelationDialog.vue
  73. 21 8
      src/components/point/dynamicdata/equipRules.vue
  74. 4 4
      src/components/point/dynamicdata/historyDialog.vue
  75. 11 2
      src/components/point/dynamicdata/partsRules.vue
  76. 11 2
      src/components/point/dynamicdata/spaceRules.vue
  77. 11 2
      src/components/point/dynamicdata/systemRules.vue
  78. 120 0
      src/components/point/report/addTabFunNum.vue
  79. 79 0
      src/components/point/report/dataSource.vue
  80. 189 0
      src/components/point/report/historyChart.vue
  81. 288 0
      src/components/point/report/integrateStatistics.vue
  82. 198 0
      src/components/point/report/objectInstance.vue
  83. 82 0
      src/components/point/report/pointTabOverview.vue
  84. 228 0
      src/components/point/report/tabFunNumOverview.vue
  85. 2 1
      src/components/ready/buildfloor/buildfloorCascader.vue
  86. 107 0
      src/components/ready/buildfloor/modelFile.vue
  87. 83 0
      src/components/ready/buildfloor/modelFolder.vue
  88. 1 1
      src/fetch/fetch.js
  89. 284 25
      src/framework/components/messagesever/index.vue
  90. 172 0
      src/framework/components/messagesever/msgAllDetails.vue
  91. 29 10
      src/framework/components/messagesever/msmq.js
  92. 64 11
      src/router/system.js
  93. 5 2
      src/utils/handsontable/fillterField.js
  94. 33 1
      src/utils/handsontable/mainText.js
  95. 1 1
      src/utils/httputils.js
  96. 8 1
      src/utils/point_edit/handson_header.js
  97. 26 0
      src/utils/scan/directive.js
  98. 27 0
      src/utils/tools.js
  99. 623 0
      src/views/business_space/dataUtil/index.vue
  100. 0 0
      src/views/data_admin/buildTask/addTask/addAssetsTask.vue

+ 2 - 2
config/dev.env.js

@@ -6,8 +6,8 @@ module.exports = merge(prodEnv, {
     NODE_ENV: '"development"',
     BASE_URL: '"http://192.168.20.215"', //测试iframe地址
     SSO_SERVER: '"http://192.168.20.102:8080"', //(新)测试环境
-    MQTT_SERVICE: '"ws://192.168.20.225:61614/stomp"' //MQ测试环境地址
+    MQTT_SERVICE: '"ws://192.168.20.225:61614/stomp/"' //MQ测试环境地址
     // SSO_SERVER: '"http://sso.sagacloud.cn"',  //正式环境
     // BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
-    // MQTT_SERVICE: '""' //MQ正式环境地址
+    // MQTT_SERVICE: '"ws://adm.sagacloud.cn/stomp/"' //MQ正式环境地址
 })

+ 1 - 1
config/index.js

@@ -94,7 +94,7 @@ module.exports = {
                 pathRewrite: {
                     "^/modelapi": "/"
                 }
-            },
+            }
         },
 
         // Various Dev Server settings

+ 2 - 2
config/prod.env.js

@@ -3,8 +3,8 @@ module.exports = {
     NODE_ENV: '"production"',
     BASE_URL: '"http://192.168.20.215"', //测试iframe地址
     SSO_SERVER: '"http://192.168.20.102:8080"', //(新)测试环境
-    MQTT_SERVICE: '"ws://192.168.20.225:61614/stomp"' //MQ测试环境地址
+    MQTT_SERVICE: '"ws://192.168.20.225:61614/stomp/"' //MQ测试环境地址
     // BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
     // SSO_SERVER: '"http://sso.sagacloud.cn"',  //正式环境
-    // MQTT_SERVICE: '""' //MQ正式环境地址
+    // MQTT_SERVICE: '"ws://adm.sagacloud.cn/stomp/"' //MQ正式环境地址
 }

+ 7 - 0
package.json

@@ -25,10 +25,17 @@
         "vue-router": "^3.0.1",
         "vuex": "^3.1.0",
         "cad-engine": "2.0.250",
+<<<<<<< HEAD
+        "@saga-web/base": "2.1.9",
+        "@saga-web/draw": "2.1.58",
+        "@saga-web/graphy": "2.1.30",
+        "@saga-web/cad-engine": "2.0.366"
+=======
         "@saga-web/base": "2.1.8",
         "@saga-web/draw": "2.1.56",
         "@saga-web/graphy": "2.1.28",
         "@saga-web/cad-engine": "2.0.275"
+>>>>>>> 2098857d48253e551fdc444edf39d3fa5a9fd69c
     },
     "devDependencies": {
         "ajv": "^6.9.1",

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

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

+ 1 - 1
src/api/httputils.js

@@ -7,7 +7,7 @@ var cancel
 
 // 创建axios实例
 const axiosservice = axios.create({
-    timeout: 30000, // 请求超时时间
+    timeout: 3000000, // 请求超时时间
     retry: 4, //重新请求次数
     retryDelay: 1000, //重新请求的间隔
     credentials: true, // 接口每次请求会跨域携带cookie

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

@@ -81,6 +81,9 @@ let api = {
         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
         }

+ 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)
+}

+ 71 - 12
src/api/scan/request.js

@@ -4,7 +4,7 @@ import http from './httpUtil'
 let arithmetic = '/arithmetic'
 
 var Comming = 'revit'
-//获取打印标签模板test
+    //获取打印标签模板test
 export function getTest() {
     return fetch({ method: 'GET', url: `${api}/service/template/note_template` })
 }
@@ -393,11 +393,11 @@ export function setHeader(param) {
 //获取头部接口
 export function getHeader(param) {
     let data = {
-        "AppType": Comming,
-        "Code": param.code,
-        "ProjId": param.perjectId
-    }
-    // return fetch({ method: 'POST', url: `${api}/service/dict/equipment_family_info_header`, data })
+            "AppType": Comming,
+            "Code": param.code,
+            "ProjId": param.perjectId
+        }
+        // return fetch({ method: 'POST', url: `${api}/service/dict/equipment_family_info_header`, data })
     return fetch({ method: 'POST', url: `${api}/service/dict/infocode_query_header`, data })
 }
 
@@ -446,7 +446,7 @@ export function getSpaceFloor(param) {
 export function createBusiness(param) {
     let data = param.data
     return fetch({ method: "POST", url: `${physics}/space/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
-    // return fetch({ method: "POST", url: `/test/space/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
+        // return fetch({ method: "POST", url: `/test/space/create?projectId=${param.ProjId}&secret=${param.secret}`, data })
 }
 
 //批量创建业务空间
@@ -496,7 +496,7 @@ export function getGraphyId(param) {
 export function getBussines(param) {
     let data = param.data
     return fetch({ method: "POST", url: `${physics}/object/outside_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
-    // return fetch({ method: "POST", url: `/test/object/outside_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
+        // return fetch({ method: "POST", url: `/test/object/outside_query?projectId=${param.ProjId}&secret=${param.secret}`, data })
 }
 
 //替代前一个接口
@@ -929,7 +929,7 @@ export function equipLinkSys(param, success) {
 export function sysLinkEquip(param, success) {
     let url = `${baseUrl}/datacenter/sy-in-eq/link-sy-eq`;
     http.postJson(url, param, success)
-} 
+}
 
 //设备清单 - 根据对象删除系统和设备的关系
 export function sysUnlinkEquip(param, success) {
@@ -994,7 +994,7 @@ export function queryPartsDie(param, success) {
 }
 
 //查询项目下设备或部件的类别、以及名称
-export function TypePartsDie( success) {
+export function TypePartsDie(success) {
     let url = `${baseUrl}/equip-component/equip-query/equip-compon-category`;
     http.getJson(url, {}, success)
 }
@@ -1072,7 +1072,7 @@ export function queryPhysicsAllType(param, success) {
 }
 
 //查询所有设备族信息
-export function queryFamilyAll( success) {
+export function queryFamilyAll(success) {
     let url = `${baseUrl}/datacenter/data-dictionary/family-query-All`;
     http.getJson(url, {}, success)
 }
@@ -1089,6 +1089,12 @@ export function dynamicClashConfirm(param, success) {
     http.postJson(url, param, success)
 }
 
+//子系统点位接入-第三部步骤3保存
+export function groupCreatePointRelation(param, success) {
+    let url = `${baseUrl}/pointconfig/relation/group-create`;
+    http.postJson(url, param, success)
+}
+
 //动态数据关联-查询数据源列表(P1&2)
 export function dynamicDataSource(param, success) {
     let url = `${baseUrl}/pointconfig/dynamic/datasource-list`;
@@ -1179,6 +1185,12 @@ export function dynamicPointTypeList(param, success) {
     http.postJson(url, param, success)
 }
 
+//动态数据关联-自动关联
+export function dynamicAutoRelate(param, success) {
+    let url = `${baseUrl}/pointconfig/dynamic/auto-relate`;
+    http.postJson(url, param, success)
+}
+
 //查询楼层信息
 export function floorQuery(param, success) {
     let url = `${baseUrl}/datacenter/floor/query`;
@@ -1311,6 +1323,24 @@ export function shthroughshUnlink(param, success) {
     let url = `${baseUrl}/datacenter/sh-through-sh/unlink`;
     http.postJson(url, param, success)
 }
+//查询没有和当前系统关联的设备
+export function unSysEq(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/datacenter/general—system/un-sys-equip?sysId=${param.sysId}`;
+    http.postJson(url, data, success)
+}
+//查询没有和当前系统关联的竖井
+export function unSysShaft(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/datacenter/general—system/un-sys-shaft?sysId=${param.sysId}`;
+    http.postJson(url, data, success)
+}
+//查询没有和当前系统关联的业务空间
+export function unSysZoneSpace(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/datacenter/general—system/un-sys-zoneSpaceBaseTable?sysId=${param.sysId}`;
+    http.postJson(url, data, success)
+}
 //查询没有和当前竖井绑定的设备
 export function unshaftInEq(param, success) {
     let data = param.data
@@ -1334,6 +1364,11 @@ export function linkEqSh(param, success) {
     let url = `${baseUrl}/datacenter/eq-in-sh/link-eq-sh`;
     http.postJson(url, param, success)
 }
+//创建系统下的设备关系
+export function linkSysEq(param, success) {
+    let url = `${baseUrl}/datacenter/general—system/link-equip`;
+    http.postJson(url, param, success)
+}
 //竖井的贯通,竖井一对多,此方法不会覆盖以前的记录
 export function linkShaft(param, success) {
     let url = `${baseUrl}/datacenter/sh-through-sh/link-shaft`;
@@ -1344,7 +1379,31 @@ export function linkSySh(param, success) {
     let url = `${baseUrl}/datacenter/sy-in-sh/link-sy-sh`;
     http.postJson(url, param, success)
 }
-
+//创建系统所在业务空间关系
+export function linkSysSp(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sp-base/link-list`;
+    http.postJson(url, param, success)
+}
+//系统所在竖井,系统一对多,此方法会覆盖以前的记录
+export function linkSh(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sh/link-sh`;
+    http.postJson(url, param, success)
+}
+//系统所在竖井,系统一对多,此方法不会覆盖以前的记录
+export function linkSysSh(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sh/link-sy-shs`;
+    http.postJson(url, param, success)
+}
+//根据对象删除系统和设备的关系,只针对一个对象
+export function eqInSysUnlink(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-eq/unlink`;
+    http.postJson(url, param, success)
+}
+//根据对象删除系统所在业务空间关系
+export function spaceInSysUnlink(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sp-base/unlink-list?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
 //关系-----设备所在业务空间--删除关系
 export function eqInSpaceDelete(param, success) {
     let url = `${baseUrl}/datacenter/eq-in-sp-base/unlink-list?type=${param.type}`;

BIN
src/assets/house.jpg


File diff suppressed because it is too large
+ 99 - 7
src/assets/style/iconfont/iconfont.css


BIN
src/assets/style/iconfont/iconfont.eot


File diff suppressed because it is too large
+ 130 - 61
src/assets/style/iconfont/iconfont.svg


BIN
src/assets/style/iconfont/iconfont.ttf


BIN
src/assets/style/iconfont/iconfont.woff


+ 93 - 11
src/components/business_space/business/handsontable.vue

@@ -38,10 +38,11 @@ import addBusiness from "@/components/business_space/dialogs/addDialog/businessD
 import showTools from "@/utils/handsontable/notShow"
 import handsonUtils from "@/utils/hasontableUtils"
 import Handsontable from "handsontable-pro"
+import buildFloor from '@/utils/handsontable/buildFloorData'
 import 'handsontable-pro/dist/handsontable.full.css'
 import zhCN from 'handsontable-pro/languages/zh-CN';
 import qrcode from "@/components/ledger/lib/qrcode";
-import { queryZone, updateZone, deleteZone, createZone, BeatchQueryParam } from "@/api/scan/request";
+import { queryZone, updateZone, deleteZone, createZone, BeatchQueryParam, updateRelateInSpAndBuild } from "@/api/scan/request";
 import { mapGetters, mapActions } from "vuex";
 export default {
   props: {
@@ -95,10 +96,12 @@ export default {
       buildMess: null,
       filtersArr: [], //表格数据被过滤后的下标
       copyMain: [], //深拷贝数组
+      buildFloorData: [], //楼层数据
     };
   },
   created() {
     this.setData()
+    buildFloor.getData(this.buildFloorData)
   },
   mounted() { },
   methods: {
@@ -107,7 +110,7 @@ export default {
       this.param.UserId = this.userId
       this.param.secret = this.secret
     },
-    //获取表
+    //获取表格数据
     getHeader(headers, buildFloorSelectd) {
       this.headers = headers
       this.buildFloorSelectd = buildFloorSelectd
@@ -124,9 +127,24 @@ export default {
           PageSize: this.page.pageSize
         }
       }
-      if (this.buildFloorSelectd.length && this.buildFloorSelectd[0] && this.buildFloorSelectd[1]) {
-        params.data.Filters = `BuildingId='${this.buildFloorSelectd[0]}';FloorId='${this.buildFloorSelectd[1]}'`
+      if (this.buildFloorSelectd[0] == "noKnow") {
+        params.data.Filters += `buildingId isNull`
+      } else if (this.buildFloorSelectd[0] && this.buildFloorSelectd[0] != "all") {
+        params.data.Filters += `buildingId='${this.buildFloorSelectd[0]}'`
       }
+      if (this.buildFloorSelectd.length > 1) {
+        if (this.buildFloorSelectd[1] == "noKnow") {
+          params.data.Filters += `;floorId isNull`
+        } else if (this.buildFloorSelectd[1] && this.buildFloorSelectd[1] != "all") {
+          params.data.Filters += `;floorId='${this.buildFloorSelectd[1]}'`
+        }
+      }
+      if (!params.data.Filters) {
+        delete params.data.Filters
+      }
+      // if (this.buildFloorSelectd.length && this.buildFloorSelectd[0] && this.buildFloorSelectd[1]) {
+      //   params.data.Filters = `BuildingId='${this.buildFloorSelectd[0]}';FloorId='${this.buildFloorSelectd[1]}'`
+      // }
       // else if (buildFloorSelectd.length && buildFloorSelectd[0] && !buildFloorSelectd[1]) {
       //   params.data.Filters = `BuildingId='${buildFloorSelectd[0]}'`
       // } else {
@@ -134,9 +152,19 @@ export default {
       // }
       queryZone(params, res => {
         this.page.total = res.Total
-        this.main = res.Content
+        this.main = res.Content.map((item) => {
+          if (item.hasOwnProperty("BuildingId") && item.hasOwnProperty("FloorId")) {
+            item.flowBuild = item.BuildingId + "-" + item.FloorId
+          } else if (item.hasOwnProperty("BuildingId") && !item.hasOwnProperty("FloorId")) {
+            item.flowBuild = item.BuildingId
+          }
+          return item
+        });
         if (this.main && this.main.length && this.main[0].RoomID) {
           this.copyMain = tools.deepCopy(this.main);
+          if (this.onlyRead) {
+            this.getBatch(this.main)
+          }
         }
         this.isLoading = false
         this.getMain()
@@ -168,6 +196,7 @@ export default {
         sortIndicator: true, //添加排序
         renderAllRows: true,
         autoColumnSize: true,
+        observeChanges: false,
         language: "zh-CN",
         manualColumnResize: true,
         manualColumnMove: true,
@@ -339,6 +368,10 @@ export default {
       //生成要修改字段列表
       change.map((item) => {
         let key = item[1].split(".")[0]
+        if (key == "flowBuild" && keyList.indexOf(key) == -1) {
+          keyList.push("BuildingId", "FloorId")
+          param.data.Projection.push("BuildingId", "FloorId")
+        }
         if (item[1] && keyList.indexOf(key) == -1) {
           keyList.push(key)
         }
@@ -349,13 +382,44 @@ export default {
       //生成对应修改数据
       data.map((item, index) => {
         keyList.map(value => {
-          let itemData = tools.dataForKey(item, value)
-          tools.setDataForKey(item, value, itemData == "" ? null : itemData)
+          if (value == "BuildingId") {
+            let itemData = tools.dataForKey(item, "flowBuild")
+            if (itemData == "") {
+              tools.setDataForKey(item, "BuildingId", null)
+              tools.setDataForKey(item, "FloorId", null)
+            } else {
+              let BuildingId = itemData.split("-")[0]
+              let FloorId = itemData.split("-")[1]
+              if (BuildingId && FloorId) {
+                tools.setDataForKey(item, "BuildingId", BuildingId)
+                tools.setDataForKey(item, "FloorId", FloorId)
+              } else if (BuildingId && !FloorId) {
+                tools.setDataForKey(item, "BuildingId", BuildingId)
+                tools.setDataForKey(item, "FloorId", null)
+              }
+            }
+          } else {
+            let itemData = tools.dataForKey(item, value)
+            tools.setDataForKey(item, value, itemData == "" ? null : itemData)
+          }
         })
         param.data.Content.push(item);
       })
-      param.Projection = []
-      updateZone(param, (res) => { })
+      if (param.data.Projection.indexOf('BuildingId') > -1) {
+        let pa = param.data.Content.map(t => {
+          return {
+            type: this.zoneCode,
+            spaceId: t.RoomID,
+            id: t.FloorId || t.BuildingId || null,
+          }
+        })
+        updateRelateInSpAndBuild(pa, res => {
+          this.$message.success('修改成功')
+        })
+      } else {
+        param.data.Projection = []
+        updateZone(param, (res) => { })
+      }
     },
     //获取被筛选掉的行号
     trimmedRows() {
@@ -420,6 +484,9 @@ export default {
       });
       if (param.data.criterias.length) {
         BeatchQueryParam(param, res => {
+          if (!this.onlyRead) {
+            return false
+          }
           this.main = data.map(item => {
             res.Content.map(child => {
               if (item.RoomID == child.id) {
@@ -435,7 +502,8 @@ export default {
                       tools.setDataForKey(
                         item,
                         head.Path,
-                        child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        // child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        child.error ? child.value ? "表号功能号格式错误" : "表号功能号不存在" : "暂未采集到实时数据"
                       );
                     }
                   });
@@ -458,6 +526,9 @@ export default {
       let arr = tools.copyArr(list)
       let data = showTools.headerTextFilter(arr, "space", this.onlyRead, this.showType)
       data.unshift("是否关联平面图", "与空间相关联的设备");
+      if (this.showType == "all") {
+        data.splice(4, 0, "所属建筑楼层")
+      }
       return data;
     },
     /**
@@ -478,10 +549,21 @@ export default {
         renderer: this.facilityRender,
         readOnly: true
       });
+      if (this.showType == "all") {
+        data.splice(4, 0, {
+          data: "flowBuild",
+          renderer: tools.customDropdownRenderer,
+          editor: "chosen",
+          chosenOptions: {
+            data: this.buildFloorData
+          },
+          readOnly: this.onlyRead
+        })
+      }
       return data;
     },
     myRenderer(instance, td, row, col, prop, value, cellProperties) {
-      if (value && value.length) {
+      if (value && value.length && value[0]) {
         td.innerHTML = "已关联"
       } else {
         td.innerHTML = "未关联"

+ 1 - 9
src/components/business_space/dialogs/list/uploadImgDialog.vue

@@ -43,16 +43,8 @@ export default {
   mounted() { },
   methods: {
     deepcopy(obj) {
-      //   var out = [],
-      //     i = 0,
-      //     len = obj.length;
-      //   for (; i < len; i++) {
-      //     if (obj[i] instanceof Array) {
-      //       out[i] = this.deepcopy(obj[i]);
-      //     } else out[i] = obj[i];
-      //   }
       console.log(obj, "out")
-      return obj;
+      return JSON.parse(JSON.stringify(obj));
     },
     changeItem(file) {
       console.log(file, "changed")

+ 13 - 27
src/components/business_space/lib/detailsDia.vue

@@ -1,31 +1,17 @@
 <template>
-  <el-dialog
-    :title="title"
-    append-to-body
-    class="iframe"
-    :visible.sync="dialog.details"
-    width="500px"
-  >
-    <iframe
-      id="google_ads_frame2"
-      name="google_ads_frame2"
-      frameborder="0"
-      width="100%"
-      height="600px"
-      :src="iframeSrc"
-      marginwidth="0"
-      marginheight="0"
-      vspace="0"
-      hspace="0"
-      allowtransparency="true"
-      scrolling="no"
-      allowfullscreen="true"
-    ></iframe>
+  <el-dialog :title="title" append-to-body class="iframe" :visible.sync="dialog.details" width="500px">
+    <iframe :id="id" name="google_ads_frame2" frameborder="0" width="100%" height="300px" :src="iframeSrc" marginwidth="0" marginheight="0" vspace="0"
+      hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true"></iframe>
   </el-dialog>
 </template>
 
 <script>
 export default {
+  data() {
+    return {
+      id: 'google_ads_frame2' + new Date().getTime()
+    }
+  },
   props: {
     iframeSrc: {
       type: String,
@@ -53,7 +39,7 @@ export default {
   methods: {
     setMess() {
       this.$nextTick(_ => {
-        let iframe = document.getElementById("google_ads_frame2")
+        let iframe = document.getElementById(this.id)
         iframe.onload = () => {
           iframe.contentWindow.postMessage(this.setData, "*")
         }
@@ -73,9 +59,9 @@ export default {
 }
 </script>
 <style lang="less" scoped>
-    #google_ads_frame2 {
-        height: 300px;
-        overflow: auto;
-    }
+#google_ads_frame2 {
+  height: 300px;
+  overflow: auto;
+}
 </style>
 

+ 3 - 3
src/components/business_space/lib/uploadImgs.vue

@@ -9,14 +9,14 @@
     <div class="saga-upload-images">
       <div v-if="type != 'video'" class="point-image" v-for="(item,index) in imagesArr">
         <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
-        <img :src="imageGetUrl + '&key=' +item" alt v-load>
+        <img :src="imageGetUrl + '&key=' +item.key" alt v-load>
       </div>
       <div v-if="type == 'video'" class="point-image" v-for="(item,index) in imagesArr">
         <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
         <video
           width="100%"
           height="100%;"
-          :src="imageGetUrl + '&key=' +item"
+          :src="imageGetUrl + '&key=' +item.key"
           controls="controls"
         >您的浏览器不支持 video 标签。</video>
       </div>
@@ -304,7 +304,7 @@ export default {
     margin-bottom: 10px;
     border: 1px solid #ccc;
     overflow: hidden;
-    image {
+    img {
       z-index: 11;
     }
     i {

+ 1 - 1
src/components/business_space/lib/uploadImgsName.vue

@@ -348,7 +348,7 @@ export default {
     position: relative;
     border: 1px solid #ccc;
     overflow: hidden;
-    image {
+    img {
       z-index: 11;
     }
     i {

+ 2 - 0
src/components/business_space/newAddDialogs/addEquipDialog.vue

@@ -156,6 +156,8 @@ export default {
       if (this.keycode != '') {
         pa.data.Filters += `;EquipName contain "${this.keycode}" or EquipLocalName contain "${this.keycode}" or EquipLocalID contain "${this.keycode}"`
       }
+      // 删除首尾分号
+      pa.data.Filters = pa.data.Filters.replace(/(^;)|(;$)/g,'');
       if (pa.data.Filters == '') {
         delete pa.data.Filters
       }

+ 50 - 15
src/components/business_space/newGraphy/canvasFun.vue

@@ -1,30 +1,41 @@
 <template>
-  <el-row id="canvas-actions-box" :class="{'isEdit':isEdit}">
-    <div :class="{'active':active=='move'}">
+  <el-row id="canvas-actions-box" :class="{'isEdit':config.isEdit}">
+    <!-- <div :class="{'active':active=='move'}">
       <i class="iconfont icon-move" @click="moveCanvas"></i>
+    </div> -->
+    <div v-if="config.isEdit&&config.groupSelect" :class="{'active':active=='groupSelect'}">
+      <i class="iconfont icon-shuxingxuanze" @click="groupSelect"></i>
     </div>
     <div>
       <i class="iconfont icon-maximize" @click="fitToWindow"></i>
     </div>
-    <div>
+    <div v-if="!config.isEdit">
       <el-dropdown size="mini" placement="top-start" @command="handleCommand">
         <i class="el-icon-download" style="font-size:20px;color:#fff;"></i>
         <el-dropdown-menu slot='dropdown'>
           <el-dropdown-item command="savePng">保存为png</el-dropdown-item>
           <el-dropdown-item command="saveSvg">保存为svg</el-dropdown-item>
+          <el-dropdown-item command="saveJson">保存为Json</el-dropdown-item>
         </el-dropdown-menu>
       </el-dropdown>
     </div>
-    <div v-if="isEdit" :class="{'active':active=='divide'}">
-      <i class="iconfont icon-edit1" @click="divide"></i>
+    <div v-if="config.isEdit&&config.divide" :class="{'active':active=='divide'}">
+      <el-dropdown size="mini" placement="top-start" @command="handleDivideCommand" :hide-on-click="false">
+        <i class="iconfont icon-edit1" @click="divide"></i>
+        <el-dropdown-menu slot='dropdown'>
+          <el-dropdown-item command="savePng">
+            吸附<el-switch v-model="isSwitch"></el-switch>
+          </el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
     </div>
-    <div v-if="isEdit">
+    <div v-if="config.isEdit&&config.divide">
       <i class="iconfont icon-Erase" @click="clearDivide"></i>
     </div>
-    <div v-if="isEdit">
+    <div v-if="config.isEdit">
       <i class="iconfont icon-Cancel" @click="undo"></i>
     </div>
-    <div v-if="isEdit">
+    <div v-if="config.isEdit">
       <i class="iconfont icon-Anti-cancel" @click="redo"></i>
     </div>
     <div>
@@ -46,21 +57,32 @@ export default {
       active: '',
       min: 1,
       everyScale: 1, // 每份的放大倍数
+      isSwitch: false, // 是否开启吸附
     }
   },
   props: {
-    isEdit: {
-      default: false
+    config: {
+      type: Object,
+      default: {
+        isEdit: false,
+        divide: true,
+        groupSelect: false
+      }
     }
   },
-  computed:{
+  computed: {
 
   },
   methods: {
     // 移动画布
-    moveCanvas() {
-      this.active = this.active != "move" ? "move" : '';
-      this.$emit('move', this.active == 'move');
+    // moveCanvas() {
+    //   this.active = this.active != "move" ? "move" : '';
+    //   this.$emit('move', this.active == 'move');
+    // },
+    //
+    groupSelect() {
+      this.active = 'groupSelect';
+      this.$emit('groupSelect');
     },
     // 适配大小
     fitToWindow() {
@@ -70,6 +92,10 @@ export default {
     handleCommand(command) {
       this.$emit(command)
     },
+    // 是否开启吸附
+    handleDivideCommand(commond) {
+      this.$emit('changeAbsorb', this.isSwitch);
+    },
     // 切割编辑
     divide() {
       this.active = 'divide';
@@ -124,14 +150,21 @@ export default {
     background-color: #6da60f;
     i {
       cursor: pointer;
+      color: #fff;
     }
   }
+  & > div:active {
+    background-color: #4b7902;
+  }
   & > div.active {
     background-color: #4b7902;
   }
   &.isEdit > div {
     background-color: #02a7f0;
   }
+  &.isEdit > div:active {
+    background-color: #027db4;
+  }
   &.isEdit > div.active {
     background-color: #027db4;
   }
@@ -140,9 +173,11 @@ export default {
     height: 40px;
     padding: 0;
     /deep/.el-slider__runway {
-      margin: 17px 0;
+      margin: 18px 0;
+      height: 4px;
       .el-slider__bar {
         background-color: #fff;
+        height: 4px;
       }
     }
   }

+ 352 - 175
src/components/business_space/newGraphy/graphy.vue

@@ -16,7 +16,7 @@
             <i class="el-icon-search el-input__icon" slot="suffix" @click="handleSelect"></i>
             <template slot-scope="{ item }">
               <div class="name" style="position: relative;">
-                {{ item.RoomLocalName | cutString(8) }}
+                {{ item.data.RoomLocalName | cutString(8) }}
                 <span class="addr" style="position: absolute;right:10px;color:#409EFF;">定位</span>
               </div>
             </template>
@@ -25,7 +25,12 @@
         <div class="button-group">
           <!-- 默认操作模式 -->
           <div v-show="type==1">
-            <el-button @click="editGraphy">编辑平面图</el-button>
+            <el-dropdown split-button type="primary" @click="editGraphy" @command="handleCommand">
+              创建业务空间
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item command="groupCreateBSpace">批量创建业务空间</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
           </div>
           <!-- 点击已经关联的业务空间 -->
           <div v-show="type==2">
@@ -35,8 +40,8 @@
           </div>
           <!-- 点击未关联的业务空间 -->
           <div v-show="type==3">
-            <el-button plain @click="createNewZone">创建新的业务空间</el-button>
-            <el-button type="primary" @click="lookUnrelatBSpace(true)">从未关联平面图的业务空间中选择</el-button>
+            <el-button plain @click="createNewZone">创建单个全新的业务空间</el-button>
+            <el-button plain @click="lookUnrelatBSpace(true)">从未关联平面图的业务空间中选择</el-button>
             <el-button plain @click="cancelGraphy">取 消</el-button>
           </div>
           <!-- 重新划分业务空间 -->
@@ -44,6 +49,11 @@
             <el-button plain @click="cancelGraphy">取 消</el-button>
             <el-button type="primary" @click="saveRefactorBSP">保存</el-button>
           </div>
+          <!-- 批量创建所选业务空间 -->
+          <div v-show="type==5">
+            <el-button type="primary" @click="groupCreateZone">批量创建所选业务空间</el-button>
+            <el-button plain @click="cancelGraphy">取 消</el-button>
+          </div>
         </div>
         <div style="position: absolute;right: 0;">
           <el-button type="text" @click="lookUnrelatBSpace(false)">未关联平面图的业务空间 {{num}} 条</el-button>
@@ -51,32 +61,47 @@
       </el-row>
       <!-- 底部操作按钮 -->
       <el-row class="canvas-actions-box">
-        <canvasFun @move="moveCanvas" @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @divide="divide" @clearDivide="clearDivide" @undo="undo"
-          @redo="redo" @scale="scale" :isEdit="isEdit" ref="canvasFun"></canvasFun>
+        <canvasFun @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @divide="divide" @clearDivide="clearDivide" @undo="undo" @redo="redo"
+          @changeAbsorb="changeAbsorb" @scale="scale" @groupSelect="groupSelect" :config="config" ref="canvasFun" @saveJson="saveJson"></canvasFun>
       </el-row>
     </div>
     <!--  -->
     <!-- 未关联元空间的业务空间 -->
-    <unRelateBSP ref="unRelateBSP" :tableData="BSPUnrelaISPList" :isAction="isAction" @createFromUnrelated="createFromUnrelated"></unRelateBSP>
+    <unRelateBSP ref="unRelateBSP" :isAction="isAction" @createFromUnrelated="createFromUnrelated" :code="tab.code"></unRelateBSP>
     <!-- 创建新的业务空间 -->
     <createBSP ref="createBSP" @createRoom="createRoom"></createBSP>
+    <!-- 批量创建选择弹窗 -->
+    <el-dialog title="提示" :visible.sync="groupCreateDialogVis" width="30%">
+      <div id="autoRelate">
+        <p>请选择批量创建方式:</p>
+        <p>
+          <el-radio v-model="groupCreateType" :label="1">批量将所有的空白空间创建业务空间</el-radio>
+        </p>
+        <p>
+          <el-radio v-model="groupCreateType" :label="2">批量选择空白空间创建业务空间</el-radio>
+        </p>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button size="small" @click="groupCreateDialogVis=false">取消</el-button>
+        <el-button size="small" type="primary" @click="confirm">确认</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 <script>
 import canvasFun from "./canvasFun"
 import { mapGetters, mapActions } from "vuex";
-import { SGraphyView } from "@sybotan-web/graphy/lib";
-import { DivideFloorScene, } from "cad-engine"
-import { SColor, SPoint } from "@sybotan-web/draw/lib";
-import { SpaceItem } from "cad-engine/lib/items/SpaceItem";
-import { ZoneItem } from "cad-engine/lib/items/ZoneItem";
+import { SColor, SPoint } from "@saga-web/draw/lib";
+import { DivideFloorScene, SpaceItem, ZoneItem } from "@saga-web/cad-engine/lib";
+import { FloorView } from "@saga-web/cad-engine/lib/FloorView";
 import unRelateBSP from "./unRelateBSP";
 import createBSP from "./createBSP";
 import {
-  countZone,
+  buildingQuery,
   queryZone,
   updateZone,
   createZone,
+  countZone,
   getIspNotInSpace,
   createRelateInZoneAndISp,
   groupCreRelaZoneAndISp
@@ -106,17 +131,21 @@ export default {
       canvasHeight: 600,
       type: 1, // 默认操作模式
       search: '',//搜索
-      num: 0, // 未关联空间的业务空间条数
-      buildFloor: [],
-      FloorMap: '',
+      buildFloor: ['', ''],
+      FloorObj: {}, //楼层对象
+      FloorMap: '', //楼层底图
       tab: {},
-      isEdit: false,
+      config: {
+        isEdit: false,
+        divide: true,
+        groupSelect: true
+      },
       canvasLoading: false,
       view: null,
       scene: null,
       Outline: [], // 当前选中的多个空间组成的轮廓线->三维数组
       businessSpaceList: [], // 所有业务空间
-      BSPUnrelaISPList: [], // 未关联元空间的业务空间
+      num: 0, // 未关联元空间的业务空间统计
       BSPRelaISPList: [], // 已关联元空间的业务空间
       // 未关联元空间的业务空间弹窗
       isAction: false,
@@ -124,6 +153,9 @@ export default {
       BIMIDToSID: {}, //bimid映射元空间id
       curZoneItem: {}, //当前选中的业务空间item
       allUnRelatISP: [], //
+      zoneList: [], // 业务空间-canvas图中
+      groupCreateDialogVis: false, //批量创建业务空间弹窗
+      groupCreateType: 1, //批量创建方式
     }
   },
   computed: {
@@ -137,16 +169,35 @@ export default {
   },
   methods: {
     // 初始化
-    init() {
+    init(initType) {
       this.type = 1;
-      // 获取当前分区下的业务空间
-      this.getBusinessSpace();
-      // 获取未关联平面图的业务空间统计
-      this.getUnrelateCount();
+      if (this.scene) {
+        this.scene.isZoneSelectable = true;
+        this.scene.isSpaceSelectable = true;
+        this.scene.clearSpaceSelection();
+        this.scene.clearZoneSelection();
+      }
+      if (this.buildFloor.indexOf('all') > -1 || this.buildFloor.indexOf('noKnow') > -1) {
+        return;
+      }
+      if (initType == 1) {
+        // 底图
+        this.getGraphy();
+      } else {
+        // 业务空间
+        this.getBusinessSpace();
+      }
+      this.config = {
+        isEdit: false,
+        divide: true,
+        groupSelect: true
+      }
       // 获取当前楼层的元空间
       this.getFloorISpace();
       // 查询未关联业务空间的元空间
-      this.getISPSPUnrelaBSP()
+      this.getISPSPUnrelaBSP();
+      // 查询未关联平面图的业务空间
+      this.getBSPunrelaISP();
     },
     // 获取当前楼层的元空间
     getFloorISpace() {
@@ -166,8 +217,8 @@ export default {
     },
     // 搜索
     querySearch(queryString, cb) {
-      var restaurants = this.BSPRelaISPList;
-      var results = queryString ?
+      let restaurants = this.zoneList;
+      let results = queryString ?
         restaurants.filter(this.createFilter(queryString)) :
         restaurants;
       // 调用 callback 返回建议列表的数据
@@ -176,32 +227,32 @@ export default {
     // 过滤器
     createFilter(queryString) {
       return restaurant => {
-        return restaurant.RoomLocalName.indexOf(queryString) > -1;
+        return restaurant.data.RoomLocalName.indexOf(queryString) > -1;
       };
     },
-    // 查询选中
-    handleSelect(BSP) {
-      console.log(arguments)
+    // 查询选中,定位
+    handleSelect(zone) {
+      // 清空选中
+      this.scene.clearSpaceSelection();
+      this.scene.clearZoneSelection();
+      // 选中当前
+      zone.selected = true;
+      this.curZoneItem = zone;
+      this.type = 2;
+      this.view.fitSelectedToView();
     },
     // 父组件调用
-    getData(buildFloor, FloorMap, tab) {
+    getData(buildFloor, FloorObj, tab) {
+      let initType = 1;
+      if (FloorObj.FloorID == this.FloorObj.FloorID) {
+        initType = 2;
+      }
       this.buildFloor = buildFloor;
-      this.FloorMap = FloorMap;
+      this.FloorObj = FloorObj;
+      this.FloorMap = FloorObj.StructureInfo ? FloorObj.StructureInfo.FloorMap : ''
       this.tab = tab;
       console.log(arguments)
-      this.init();
-    },
-    // 获取未关联平面图的业务空间统计
-    getUnrelateCount() {
-      let pa = {
-        data: {
-          Filters: `BuildingId='${this.buildFloor[0]}';FloorId='${this.buildFloor[1]}';Outline isNull`
-        },
-        zone: this.tab.code
-      }
-      countZone(pa, res => {
-        this.num = res.Count
-      })
+      this.init(initType);
     },
     // 获取未绑定业务空间的元空间
     getISPSPUnrelaBSP() {
@@ -223,80 +274,113 @@ export default {
       that.clearGraphy()
       that.scene = new DivideFloorScene();
       that.canvasLoading = true;
-      that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.FloorMap}`).then(() => {
+      that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.FloorMap}`).then(res => {
         that.canvasLoading = false;
+        if (res == 'error') {
+          this.FloorMap = '';
+          this.$message.warning('数据解析异常');
+          return;
+        }
         that.view.scene = that.scene;
-        let tempArr = this.BSPRelaISPList.map((t, i) => {
-          return {
-            RoomLocalName: t.RoomLocalName,
-            OutLine: t.Outline,
-            RoomID: t.RoomID,
-            Color: new SColor(colorArr[i % colorArr.length]),
-          }
-        })
-        that.scene.addZoneList(tempArr);
-        that.scene.click(that, that.canvasClick)
+        // 蒙版
+        if (this.FloorObj.Outline) {
+          let newArr = this.FloorObj.Outline.map(t => {
+            return new SPoint(t.X, t.Y);
+          })
+          this.scene.addSceneMark(newArr)
+        }
+        // 绘制业务空间
+        that.getBusinessSpace();
         that.view.fitSceneToView();
         that.view.maxScale = that.view.scale * 10;
         that.view.minScale = that.view.scale;
-        that.$refs.canvasFun.everyScale = that.view.scale;
+        if (that.$refs.canvasFun) {
+          that.$refs.canvasFun.everyScale = that.view.scale;
+        }
+      })
+    },
+    // 清空绘制业务空间
+    clearZoneCanvas() {
+      this.zoneList.map(t => {
+        this.scene.removeItem(t);
       })
     },
     // 获取当前分区下的业务空间
     getBusinessSpace() {
-      this.isLoading = true
+      this.canvasLoading = true
       let pa = {
         zone: this.tab.code,
         data: {
           Filters: ``,
           Orders: "createTime desc, RoomID asc",
-          PageSize: 500
+          PageSize: 1000
         }
       }
       if (this.buildFloor.length && this.buildFloor.length > 1) {
         pa.data.Filters = `BuildingId='${this.buildFloor[0]}';FloorId='${this.buildFloor[1]}'`
       }
+      this.clearZoneCanvas();
       queryZone(pa, res => {
         // 所有业务空间
         this.businessSpaceList = res.Content;
-        // 未关联元空间的业务空间
-        this.BSPUnrelaISPList = [];
         // 已关联元空间的业务空间
         this.BSPRelaISPList = [];
         res.Content.map(t => {
           if (t.Outline && t.Outline.length) {
             this.BSPRelaISPList.push(t)
-          } else {
-            this.BSPUnrelaISPList.push(t)
           }
         })
-        // 获取底图
-        this.getGraphy();
-        this.isLoading = false;
+        // 绘制业务空间
+        let tempArr = this.BSPRelaISPList.map((t, i) => {
+          return {
+            RoomLocalName: t.RoomLocalName,
+            OutLine: t.Outline,
+            RoomID: t.RoomID,
+            Color: new SColor(colorArr[i % colorArr.length]),
+          }
+        })
+        this.scene.zoneList = [];
+        this.scene.addZoneList(tempArr);
+        this.scene.click(this, this.canvasClick);
+        this.zoneList = this.scene.zoneList;
+        this.canvasLoading = false;
       })
     },
     // canvas点击事件
     canvasClick(item, event) {
-      this.scene.setSpaceSelectable(true);
-      this.scene.setZoneSelectable(true);
-      if (this.type == 4) {
+      console.log(item)
+      console.log(event)
+      if (this.type == 4) {//重新划分
+
+      } else if (this.type == 5) {//批量
 
       } else {
-        if (item instanceof SpaceItem) {
+        if (item instanceof SpaceItem && item.selectable) {
+          if (this.type == 2) {
+            this.scene.clearZoneSelection();
+          }
           this.type = 3;
           this.curZoneItem = {};
-          this.scene.setZoneSelectable(false);
         }
-        if (item instanceof ZoneItem) {
+        if (item instanceof ZoneItem && item.selectable) {
+          if (this.type == 3) {
+            this.scene.clearSpaceSelection();
+          }
           this.type = 2;
           this.curZoneItem = item;
-          this.scene.setSpaceSelectable(false);
+          this.scene.clearZoneSelection();
+          item.selected = true;
         }
       }
     },
     // 编辑平面图
     editGraphy() {
       this.type = 3;
+      this.config.isEdit = true;
+      this.config.groupSelect = false;
+      this.config.divide = true;
+      // 设置业务空间不可选
+      this.scene.isZoneSelectable = false
     },
     // 查看未关联的业务空间--flag--查看-or-选择
     lookUnrelatBSpace(flag) {
@@ -310,69 +394,74 @@ export default {
     },
     // 取消(所有取消公用)
     cancelGraphy() {
-      this.type = 1;
-      this.init();
+      this.init(2);
+    },
+    // 批量创建业务空间弹窗
+    handleCommand(command) {
+      this.groupCreateDialogVis = true;
+    },
+    // 创建弹窗确认
+    confirm() {
+      if (this.groupCreateType == 1) {
+        this.groupCreateBSpace()
+      } else if (this.groupCreateType == 2) {
+        this.type = 5;
+        this.config.isEdit = true;
+        this.config.groupSelect = true;
+        this.config.divide = false;
+        this.groupCreateDialogVis = false;
+        // 清空选中空间
+        this.scene.clearSpaceSelection();
+        // 设置空间可选
+        this.scene.isSpaceSelectable = true;
+        // 设置业务空间不可选
+        this.scene.isZoneSelectable = false;
+      }
     },
     // 批量创建业务空间
     groupCreateBSpace() {
       let text = []
       let Spaces = this.allUnRelatISP.map(t => {
-        text.push(t.RoomLocalName || t.RoomName)
-        return {
-          IspaceId: t.RoomID,
-          RoomLocalName: t.RoomLocalName || t.RoomName,
-          Outline: [t.Outline],
-          BuildingId: this.buildFloor[0],
-          FloorId: this.buildFloor[1]
-        }
-      });
-      this.$confirm(
-        "<p>确定根据未关联业务空间的空间批量创建业务空间</p>" +
-        "<p>涉及的空间:</p>" +
-        "<p style='line-height:20px;max-height:60px;overflow-y:auto;'>" +
-        text.toString() +
-        "</p>",
-        "提示", {
-        dangerouslyUseHTMLString: true,
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }
-      ).then(() => {
-        let pa = {
-          zone: this.tab.code,
-          data: {
-            Content: Spaces
+        if (t.Outline) {
+          text.push(t.RoomLocalName || t.RoomName)
+          return {
+            IspaceId: t.RoomID,
+            RoomLocalName: t.RoomLocalName || t.RoomName,
+            Outline: [t.Outline],
+            BuildingId: this.buildFloor[0],
+            FloorId: this.buildFloor[1],
+            Height: t.Height || 0
           }
+        } else {
+          return undefined
         }
-        this.canvasLoading = true;
-        createZone(pa, res => {
-          res.EntityList.map(t => {
-            Spaces = Spaces.map(item => {
-              if (t.RoomLocalName == item.RoomLocalName) {
-                item.SpaceId = t.RoomID
-              }
-              return item;
-            })
-          })
-          let param = {
-            data: {
-              Content: Spaces
-            },
-            type: this.tab.code
-          }
-          groupCreRelaZoneAndISp(param, res => {
-            this.$message.success('创建成功')
-            this.canvasLoading = false;
-            this.init()
-          })
-        })
-      }).catch(() => {
-        this.$message({
-          type: "info",
-          message: "已取消批量创建"
+      }).filter(item => item);
+      if (Spaces.length) {
+        this.$confirm(
+          "<p>确定根据未关联业务空间的空间批量创建业务空间</p>" +
+          "<p>涉及的空间:</p>" +
+          "<p style='line-height:20px;max-height:60px;overflow-y:auto;'>" +
+          text.toString() +
+          "</p>",
+          "提示", {
+          dangerouslyUseHTMLString: true,
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }
+        ).then(() => {
+          this.groupCreateDialogVis = false;
+          this.canvasLoading = true;
+          this.groupCreateBSP(Spaces)
+        }).catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消批量创建"
+          });
         });
-      });
+      } else {
+        this.$message('没有未关联的元空间')
+      }
     },
     // 创建新的业务空间
     createNewZone() {
@@ -390,42 +479,33 @@ export default {
     // 创建新的业务空间-弹窗返回确认创建
     createRoom(val) {
       let arr = this.scene.getSelectedSpaces();
-      let zoneObj = { Outline: [] }, IspaceIdList = [];
+      let zoneObj = { Outline: [], Height: 0 }, IspaceIdList = [];
       arr.map(t => {
         zoneObj.Outline.push(t.data.OutLine);
-        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId])
+        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        console.log(zoneObj.Height)
+        if (t.data.Height && (zoneObj.Height == 0 || t.data.Height < zoneObj.Height)) {
+          zoneObj.Height = t.data.Height;
+        }
       })
       zoneObj.RoomLocalName = val;
       zoneObj.BuildingId = this.buildFloor[0];
       zoneObj.FloorId = this.buildFloor[1];
-      let pa = {
-        zone: this.tab.code,
-        data: {
-          Content: [zoneObj]
-        }
-      }
-      createZone(pa, res => {
-        this.relationInBSPandISP(res.EntityList[0].RoomID, IspaceIdList)
-      })
+      this.createSingleBSP(zoneObj, IspaceIdList)
     },
     // 从未关联平面图的业务空间中选择--按钮返回关联信号
     createFromUnrelated(BSP) {
-      BSP.Outline = []
-      let arr = this.scene.getSelectedSpaces();
+      BSP.Outline = [];
+      BSP.Height = 0;
+      let arr = this.scene.getSelectedSpaces(), IspaceIdList = [];
       arr.map(t => {
         BSP.Outline.push(t.data.OutLine);
-      })
-      let pa = {
-        zone: BSP.ObjectType,
-        data: {
-          Content: [BSP],
-          Projection: ['Outline']
+        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        if (t.Height && (BSP.Height == 0 || t.Height < BSP.Height)) {
+          BSP.Height = t.Height;
         }
-      }
-      updateZone(pa, res => {
-        this.$message.success('更新成功');
-        this.init();
       })
+      this.updateBSPOutline(BSP, IspaceIdList)
     },
     // 编辑空间详情
     editeSpaceDetail() {
@@ -438,24 +518,111 @@ export default {
     // 重新划分业务空间
     refactorBSP() {
       this.type = 4;
+      // 清空选中空间
+      this.scene.clearSpaceSelection();
       // 设置空间可选
-      this.scene.setSpaceSelectable(true);
+      this.scene.isSpaceSelectable = true;
       // 将已关联的设置不可选,并将当前选的隐藏
-      this.scene.changeSelectZone(this.curZoneItem);
+      this.scene.isZoneSelectable = false;
+      this.curZoneItem.visible = false;
     },
     // 重新划分--保存
     saveRefactorBSP() {
       let arr = this.scene.getSelectedSpaces();
       //更新业务空间
-      let zoneObj = { Outline: [] }, IspaceIdList = [];
+      let zoneObj = { Outline: [], Height: 0 }, IspaceIdList = [];
       arr.map(t => {
         zoneObj.Outline.push(t.data.OutLine);
-        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId])
+        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        if (t.Height && (zoneObj.Height == 0 || t.Height < zoneObj.Height)) {
+          zoneObj.Height = t.Height;
+        }
       })
       zoneObj.RoomID = this.curZoneItem.data.RoomID;
       if (!zoneObj.Outline.length) {
         zoneObj.Outline = null;
       }
+      this.updateBSPOutline(zoneObj, IspaceIdList)
+    },
+    // 批量创建所选业务空间
+    groupCreateZone() {
+      let arr = this.scene.getSelectedSpaces();
+      let spaces = arr.map(t => {
+        return {
+          IspaceId: this.BIMIDToSID[t.data.SourceId],
+          RoomLocalName: t.data.Name,
+          Outline: [t.data.OutLine],
+          BuildingId: this.buildFloor[0],
+          FloorId: this.buildFloor[1],
+          Height: t.data.Height || 0
+        }
+      })
+      if (spaces.length) {
+        this.canvasLoading = true;
+        this.groupCreateBSP(spaces)
+      } else {
+        this.$message.warning('未选择空间');
+      }
+    },
+    // 更新业务空间和元空间的关系
+    relationInBSPandISP(SpaceId, IspaceIdList) {
+      let pa = {
+        data: { SpaceId: SpaceId, IspaceIdList: IspaceIdList },
+        type: this.tab.code
+      }
+      createRelateInZoneAndISp(pa, res => {
+        this.$message.success('创建成功');
+        this.init(2);
+      })
+    },
+    // 批量更新业务空间和元空间的关系
+    groupCreRelaZoneAndISp(Spaces) {
+      let param = {
+        data: {
+          Content: Spaces
+        },
+        type: this.tab.code
+      }
+      groupCreRelaZoneAndISp(param, res => {
+        this.$message.success('创建成功')
+        this.canvasLoading = false;
+        this.init(2)
+      })
+    },
+    // 批量创建
+    groupCreateBSP(spaces) {
+      let pa = {
+        zone: this.tab.code,
+        data: {
+          Content: spaces
+        }
+      }
+      createZone(pa, res => {
+        res.EntityList.map(t => {
+          spaces = spaces.map(item => {
+            if (t.RoomLocalName == item.RoomLocalName) {
+              item.SpaceId = t.RoomID
+            }
+            return item;
+          })
+        })
+        this.groupCreRelaZoneAndISp(spaces)
+      })
+    },
+    // 单个创建
+    createSingleBSP(space, IspaceIdList) {
+      let pa = {
+        zone: this.tab.code,
+        data: {
+          Content: [space]
+        }
+      }
+      createZone(pa, res => {
+        this.relationInBSPandISP(res.EntityList[0].RoomID, IspaceIdList)
+      })
+    },
+    // 更新业务空间区域
+    updateBSPOutline(zoneObj, IspaceIdList) {
       let pa = {
         zone: this.tab.code,
         data: {
@@ -467,15 +634,16 @@ export default {
         this.relationInBSPandISP(zoneObj.RoomID, IspaceIdList)
       })
     },
-    // 更新业务空间和元空间的关系
-    relationInBSPandISP(SpaceId, IspaceIdList) {
+    // 查询未关联平面图的业务空间(项目下+当前分区)
+    getBSPunrelaISP() {
       let pa = {
-        data: { SpaceId: SpaceId, IspaceIdList: IspaceIdList },
-        type: this.tab.code
+        zone: this.tab.code,
+        data: {
+          Filters: `Outline isNull`
+        }
       }
-      createRelateInZoneAndISp(pa, res => {
-        this.$message.success('创建成功');
-        this.init();
+      countZone(pa, res => {
+        this.num = res.Count;
       })
     },
     // canvas 获取焦点
@@ -484,22 +652,20 @@ export default {
     },
     // 清除canvas
     clearGraphy() {
-      if (this.view) {
+      if (this.view && this.view.scene) {
         this.view.scene = null;
         return
       }
-      this.view = new SGraphyView('floorCanvas')
+      this.view = new FloorView('floorCanvas')
     },
     // 工具栏操作
-    // 移动底图
-    moveCanvas(move) {
-      // todo
-      let canvas = document.getElementById(`floorCanvas`);
-      if (move) {
-        canvas.style.cursor = 'move';
-      } else {
-        canvas.style.cursor = 'default';
-      }
+    // 吸附
+    changeAbsorb(isAbsorbing) {
+      this.scene.isAbsorbing = isAbsorbing;
+    },
+    // 框选
+    groupSelect() {
+      this.scene.isRectSelection = true;
     },
     // 适配底图到窗口
     fit() {
@@ -513,13 +679,21 @@ export default {
     saveSvg() {
       this.view.saveSceneSvg(`${this.buildFloor[1]}.svg`, 6400, 4800);
     },
+    // 保存为svg
+    saveSvg() {
+      this.view.saveSceneSvg(`${this.buildFloor[1]}.svg`, 6400, 4800);
+    },
+    // 保存json
+    saveJson() {
+      this.view.saveFloorJson(`${this.buildFloor[1]}.json`)
+    },
     // 切割划分
     divide() {
-      this.drawMainScene.isMarking = true;
+      this.scene.isMarking = true;
     },
     // 清除切割划分
     clearDivide() {
-      this.drawMainScene.clearSceneMark()
+      this.scene.clearSceneMark()
     },
     // 撤销
     undo() {
@@ -529,6 +703,9 @@ export default {
     redo() { },
     // 缩放
     scale(val) {
+      if (!this.view) {
+        return;
+      }
       let scale = this.view.scale;
       this.view.scaleByPoint(val / scale, this.canvasWidth / 2, this.canvasHeight / 2);
     },

+ 137 - 27
src/components/business_space/newGraphy/unRelateBSP.vue

@@ -1,27 +1,52 @@
 <template>
-  <el-dialog :title="title" :visible.sync="dialogVisible" width="600px" id="lookUnrelatBSpace">
-    <el-input :placeholder="`请输入业务空间名称`" v-model="queryString" @keyup.enter.native="queryTableData">
-      <i slot="suffix" class="el-input__icon el-icon-search" @click="queryTableData"></i>
-    </el-input>
-    <div style="margin-top:10px;height:300px;">
-      <el-table :data="data" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
-        <el-table-column prop="RoomLocalName" label="业务空间名称" show-overflow-tooltip min-width="200"></el-table-column>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="unRelateBSP">
+    <el-row class="filters">
+      <el-col :span="9">
+        <el-input placeholder="输入业务空间名称进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="15">
+        <span style="margin-left:10px;">所属楼层</span>
+        <el-cascader @change="getTableData" v-model="floor" :options="options" :props="props"></el-cascader>
+      </el-col>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.RoomLocalName||scope.row.RoomName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="BNAME" label="所属建筑" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="FNAME" label="所属楼层" show-overflow-tooltip min-width="100"></el-table-column>
         <el-table-column prop="action" label="操作" min-width="100" v-if="isAction">
           <template slot-scope="scope">
-            <el-button @click="createRelation(scope.row)">关联平面图</el-button>
+            <el-button size="mini" @click="createRelation(scope.row)" type="primary" plain>关联平面图</el-button>
           </template>
         </el-table-column>
       </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
     </div>
   </el-dialog>
 </template>
 
 <script>
+import {
+  buildingQuery,
+  queryZone
+} from "@/api/scan/request"
 export default {
   name: "unRelateBSP",
   data() {
     return {
       title: '未关联平面图的业务空间',
+      inSpaceType: '业务空间',
       dialogVisible: false,
       loading: false,
       headerStyle: {
@@ -29,39 +54,124 @@ export default {
         color: '#2b2b2b',
         lineHeight: '30px'
       },
-      queryString: '',
-      data: []
+      keycode: '',
+      tableData: [],
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      floor: ['all'], // 级联建筑楼层
+      props: { //自定义字段
+        value: "BuildID",
+        label: "BuildLocalName",
+        children: "Floor"
+      },
+      bfData: {}, //建筑楼层id =>名称
+      options: [], //级联
     };
   },
   props: {
-    tableData: {
-      default: []
-    }, //列表数据
     isAction: false, //是否显示操作按钮
+    code: String
+  },
+  created() {
+    this.getBuilding()
   },
   methods: {
     // 显示弹窗
     showDialog() {
-      this.data = this.tableData;
       this.dialogVisible = true;
-    },
-    // 搜索
-    queryTableData() {
-      var restaurants = this.tableData;
-      this.data = this.queryString ?
-        restaurants.filter(this.createFilter(this.queryString)) :
-        restaurants;
-    },
-    createFilter(queryString) {
-      return restaurant => {
-        return restaurant.RoomLocalName.indexOf(queryString) > -1;
-      };
+      this.getTableData();
     },
     // 关联平面图
     createRelation(row) {
       this.$emit('createFromUnrelated', row);
       this.dialogVisible = false;
+    },
+    // 分页条数
+    handleSizeChange(val) {
+      this.page.pageSize = val;
+      this.page.pageNumber = 1;
+      this.getTableData();
+    },
+    // 页码
+    handleCurrentChange(val) { 
+      this.page.pageNumber = val;
+      this.getTableData();
+    },
+    // 获取项目下建筑
+    getBuilding() {
+      let pa = {
+        Cascade: [{ name: 'floor', Orders: 'SequenceId desc' }],
+        Orders: "BuildLocalName asc",
+      }
+      buildingQuery(pa, res => {
+        this.options = res.Content.map(t => {
+          this.bfData[t.BuildID] = t.BuildLocalName;
+          if (t.Floor) {
+            t.Floor = t.Floor.map(item => {
+              this.bfData[item.FloorID] = item.FloorLocalName;
+              item.BuildID = item.FloorID;
+              item.BuildLocalName = item.FloorLocalName;
+              return item;
+            })
+          } else {
+            t.Floor = []
+          }
+          t.Floor.unshift({ BuildID: 'all', BuildLocalName: '全部' }, { BuildID: 'isNull', BuildLocalName: '未明确楼层' })
+          return t;
+        })
+        this.options.unshift({ BuildID: 'all', BuildLocalName: '全部' }, { BuildID: 'isNull', BuildLocalName: '未明确楼层' })
+      })
+    },
+    // 查询未关联平面图的业务空间(项目下+当前分区)
+    getTableData() {
+      let pa = {
+        zone: this.code,
+        data: {
+          Filters: `Outline isNull`,
+          Orders: "createTime desc, RoomID asc",
+          PageSize: this.page.pageSize,
+          pageNumber: this.page.pageNumber
+        }
+      }
+      if (this.floor[0] == 'isNull') {
+        pa.data.Filters += `;BuildingId isNull`
+      } else if (this.floor[0] && this.floor[0] != 'all') {
+        pa.data.Filters += `;BuildingId='${this.floor[0]}'`
+      }
+      if (this.floor[1] == 'isNull') {
+        pa.data.Filters += `;FloorId isNull`
+      } else if (this.floor[1] && this.floor[1] != 'all') {
+        pa.data.Filters += `;FloorId='${this.floor[1]}'`
+      }
+      if (this.keycode != '') {
+        pa.data.Filters += `;RoomLocalName contain "${this.keycode}" or RoomName contain "${this.keycode}"`
+      }
+      queryZone(pa, res => {
+        this.page.total = res.Total;
+        this.tableData = res.Content.map(t => {
+          t.BNAME = this.bfData[t.BuildingId];
+          t.FNAME = this.bfData[t.FloorId];
+          return t;
+        })
+      })
     }
   },
 };
-</script>
+</script>
+<style lang="less" scoped>
+#unRelateBSP {
+  .filters {
+    margin-bottom: 10px;
+    /deep/ .el-input__inner {
+      vertical-align: baseline;
+    }
+  }
+  .table-box {
+    height: 350px;
+  }
+}
+</style>

+ 1 - 0
src/components/common/myPagination.vue

@@ -36,6 +36,7 @@ export default {
     //当前条数发生改变
     handleSizeChange(val) {
       this.page.size = val;
+      this.page.currentPage = 1;
       this.change()
     },
     //当前页发生改变

+ 24 - 8
src/components/config_point/dictionaryCascader.vue

@@ -71,7 +71,8 @@ export default {
         Bd: 'Building',
         Fl: 'Floor',
         VOTn: 'Tenant',
-      }
+      },
+      timer: null
     }
   },
   created() {
@@ -127,7 +128,6 @@ export default {
     },
     //请求信息点
     getDataPoint(type) {
-      let that = this;
       let param = {
         data: {
           Filters: "InputMode='M' or InputMode='L'",
@@ -144,17 +144,31 @@ export default {
             Name: item.InfoPointName
           }
         })
-        this.pushPoints(this.options, tempArr, type);
         this.pointDataSource = {}
         res.Content.map(item => {
           let code = item.InfoPointCode
           this.pointDataSource[code] = item
         })
-        this.$nextTick(() => {
-          this.changeSelect(this.form.dict)
-        })
+        this.timer = setTimeout(() => {
+          if (this.interval()) {
+            this.pushPoints(this.options, tempArr, type);
+            this.changeSelect(this.form.dict);
+            clearTimeout(this.timer);
+            this.timer = null;
+            return
+          }
+          this.timer()
+        }, 100);
       })
     },
+    interval() {
+      for (let i = 0; i < this.options.length; i++) {
+        if (this.options[i].children.length > 0) {
+          return true;
+        }
+      }
+      return false;
+    },
     //根据返回数据拼接options
     pushPoints(options, arr, Code) {
       options.map(option => {
@@ -168,8 +182,10 @@ export default {
       })
     },
     changeSelect(val) {
-      let labels = this.$refs.dictCas.getCheckedNodes()[0].pathLabels
-      this.$emit('change', { val: val, labels: labels })
+      if (this.$refs.dictCas.getCheckedNodes()[0]) {
+        let labels = this.$refs.dictCas.getCheckedNodes()[0].pathLabels
+        this.$emit('change', { val: val, labels: labels })
+      }
     },
     //减少请求次数
     hasChildren(Code) {

+ 2 - 2
src/components/config_point/examine_main.vue

@@ -138,12 +138,13 @@
                         data: {
                             Filters: {
                                 DataSourceId: this.datasourceId,
-                                ProjectId: this.projectId,
                                 KeyEquipmentParameter: this.EquipmentParameter,
                                 KeyEquipmentType: this.EquipmentType,
                                 Used: true
                             }
                         },
+                        PageNumber: 1,
+                        PageSize: 1000,
                         type: this.protocolType
                     },
                     width, settings
@@ -169,7 +170,6 @@
                     type: this.protocolType,
                     data: {
                         DataSourceId: this.datasourceId,
-                        ProjectId: this.projectId,
                         KeyEquipmentType: this.EquipmentType
                     }
                 }, res => {

+ 0 - 2
src/components/config_point/find_keyword.vue

@@ -209,7 +209,6 @@
                 queryFun({
                     data: {
                         DataSourceId: this.datasourceId,
-                        ProjectId: this.projectId,
                         Ai: this.isSwitch
                     },
                     type: this.protocolType
@@ -273,7 +272,6 @@
                 // console.log(getListFetch)
                 getListFetch({
                     data: {
-                        ProjectId: this.projectId,
                         DataSourceId: this.datasourceId
                     },
                     type: this.protocolType

+ 18 - 2
src/components/config_point/select_one.vue

@@ -10,11 +10,11 @@
         <p>{{name}}</p>
         <ul v-if="renderData.length">
             <li v-for="(item,index) in renderData" :key="index">
-                <div @click="checkItem(item,index)" :class="index == active ? 'saga-active-select': ''" class="select-item border-bottom pointer">
+                <div @click="checkItem(item,index)" :class="{'saga-active-select': index == active,'disabled':item.RelationStatus=='Waiting'||item.RelationStatus=='Pending'}" class="select-item border-bottom pointer">
                     <!-- <span v-if="isSelected" :class="{'is-checked': item[isCheckInfo]}" class="el-checkbox__input">
                         <span class="el-checkbox__inner"></span>
                     </span> -->
-                    <span v-if="isSelected" :class="item[isCheckInfo] ? 'el-icon-success' : 'el-icon-error'" style="color:#409EFF;">
+                    <span v-if="isSelected" :class="item.RelationStatus=='Waiting'||item.RelationStatus=='Pending'?'iconfont icon-shenglvehao load-color':item[isCheckInfo] ? 'el-icon-success success-color' : 'el-icon-error error-color'">
                     </span>
                     {{overString(item[infosKey])}}
                     <i v-if="isDel" @click.stop="delItem(item)" class="el-icon-error saga-delete pointer"></i>
@@ -60,6 +60,10 @@
         mounted() {},
         methods: {
             checkItem(item, index) {
+                if(item.RelationStatus=='Waiting'||item.RelationStatus=='Pending'){
+                    this.$message('正在执行')
+                    return
+                }
                 this.$emit("check", item)
                 this.active = index
             },
@@ -123,6 +127,18 @@
     .select-item {
         height: 30px;
         line-height: 30px;
+        &.disabled{
+            background-color: #ccc;
+        }
+        .success-color{
+            color: #409EFF;
+        }
+        .error-color{
+            color: #F56C6C;
+        }
+        .load-color{
+            color: #909399;
+        }
     }
     .saga-delete {
         display: none;

+ 17 - 17
src/components/config_point/step3_edit/index.vue

@@ -458,24 +458,24 @@ export default {
           this.$refs.dictionaryCas.setCascaderVal(tempArr)
         })
 
-        this.handleItemChange(dict, () => {
           this.form.DataRuleType = data.DataRuleType
-          this.unitObj = this.infoDict[data.InfomationPointCode]
-          this.InfomationPoint = this.unitObj.infoPointName || '--'
-          if (typeof this.unitObj.dataSource == 'string') {
-            if (this.unitObj.dataSource.length) {
-              this.ValueDescription = this.unitObj.dataSource
-            } else {
-              this.ValueDescription = '无信息点单位及值说明'
-            }
-          } else {
-            let str = ''
-            this.unitObj.dataSource.forEach(ele => {
-              str += ele.code + '.' + ele.name + ' '
-            })
-            this.ValueDescription = str
-          }
-        })
+        // this.handleItemChange(dict, () => {
+          // this.unitObj = this.infoDict[data.InfomationPointCode]
+          // this.InfomationPoint = this.unitObj.infoPointName || '--'
+          // if (typeof this.unitObj.dataSource == 'string') {
+          //   if (this.unitObj.dataSource.length) {
+          //     this.ValueDescription = this.unitObj.dataSource
+          //   } else {
+          //     this.ValueDescription = '无信息点单位及值说明'
+          //   }
+          // } else {
+          //   let str = ''
+          //   this.unitObj.dataSource.forEach(ele => {
+          //     str += ele.code + '.' + ele.name + ' '
+          //   })
+          //   this.ValueDescription = str
+          // }
+        // })
         if (length == 1) {
           let flag = data.DataRuleType
           var dataRules = null

+ 9 - 2
src/components/config_point/step3_point/3_identify.vue

@@ -4,7 +4,7 @@
             <el-collapse v-model="activeName" @change="handleChange" accordion>
                 <el-collapse-item v-for="(item,index) in renderData" :key="index" :name="index+1">
                     <template slot="title">
-                        <span style="padding-left:10px;box-sizing:border-box;">
+                        <span :title="item.Group" style="padding-left:10px;box-sizing:border-box;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
                             {{item.Group}}
                         </span>
                     </template>
@@ -276,7 +276,14 @@
                             Visible: true,
                             FirstTag: ""
                         }
-                    ]
+                    ],
+                    "common": [{
+                        InfoPointName: "*地址详情",
+                        InfoPointCode: "JoinedInfo",
+                        InputMode: "B1",
+                        Visible: true,
+                        FirstTag: ""
+                    }],
                 }
                 let allData = this.renderData[this.activeName - 1].PointList,
                     data = {

+ 129 - 40
src/components/config_point/step3_point/3_temps.vue

@@ -56,11 +56,14 @@
     </div>
     <div class="collapse-item" v-if="activeName == 2">
       <div v-if="renderData.length" style="height:258px;">
-        <handsontable-component ref="handsontable"></handsontable-component>
+        <handsontable-component ref="handsontable" @change="changeTable"></handsontable-component>
       </div>
       <div v-if="!renderData.length" class="center" style="padding: 50px 0;box-sizing:border-box;">
         <i class="icon-wushuju iconfont"></i> 暂无数据
       </div>
+      <div v-if="pages.total>pages.size" class="right">
+        <pagination :page="pages" @change="changePage"></pagination>
+      </div>
       <div class="center">
         <el-button @click="undo">上一步</el-button>
         <el-button v-show="renderData.length" @click="save">保存</el-button>
@@ -77,6 +80,11 @@ import formulaHandle from '@/components/config_point/step3_edit/formula_handle'
 import splitHandle from '@/components/config_point/step3_edit/split_handle'
 import handsontableComponent from "@/components/common/handsontable"
 import dictionaryCas from '@/components/config_point/dictionaryCascader'
+import pagination from "@/components/common/myPagination"
+import handsonUtils from "@/utils/hasontableUtils"
+import {
+  groupCreatePointRelation
+} from "@/api/scan/request";
 import {
   mapGetters,
   mapActions
@@ -107,7 +115,9 @@ export default {
       default: function () {
         return []
       }
-    }
+    },
+    pages: Object,
+    queryParam: Object
   },
   data() {
     return {
@@ -168,21 +178,24 @@ export default {
     formulaHandle,
     splitHandle,
     handsontableComponent,
-    dictionaryCas
+    dictionaryCas,
+    pagination
   },
   methods: {
-    getMain(param) {
-      this.activeName = 0
-      this.dealType = {}
-      this.form1 = {
-        dict: 1
-      }
-      this.$refs.dictionaryCas.setCascaderVal([])
-      this.form2 = {
-        ValueDescription: '',
-        DataRuleType: '无需处理,直接使用'
+    getMain(param, pagechange) {
+      if (!pagechange) {
+        this.activeName = 0
+        this.dealType = {}
+        this.form1 = {
+          dict: 1
+        }
+        this.$refs.dictionaryCas.setCascaderVal([])
+        this.form2 = {
+          ValueDescription: '',
+          DataRuleType: '无需处理,直接使用'
+        }
+        this.unitObj = {}
       }
-      this.unitObj = {}
       let params = {
         data: {
           DataSourceId: this.datasourceId,
@@ -197,32 +210,41 @@ export default {
     },
     //保存
     save() {
-      let data = this.hot.getSourceData()
-      let params = data.map(item => {
-        let obj = Object.assign({}, {
-          DataSourceId: this.datasourceId,
-          PointId: item.Id,
-          EquipmentMark: item.EquipmentMark
-        })
-        return Object.assign(obj, this.dealType)
-      }),
-        sameFalg = false,
-        magFalg = false;
-      params.map((item, index) => {
-        if (!item.EquipmentMark) {
-          magFalg = true
-        }
-        params.map((child, childIndex) => {
-          if (childIndex != index && child.EquipmentMark == item.EquipmentMark) {
-            sameFalg = true
-          }
-        })
+      // let data = this.hot.getSourceData()
+      // let params = data.map(item => {
+      //   let obj = Object.assign({}, {
+      //     DataSourceId: this.datasourceId,
+      //     PointId: item.Id,
+      //     EquipmentMark: item.EquipmentMark
+      //   })
+      //   return Object.assign(obj, this.dealType)
+      // }),
+      //   sameFalg = false,
+      //   magFalg = false;
+      // params.map((item, index) => {
+      //   if (!item.EquipmentMark) {
+      //     magFalg = true
+      //   }
+      //   params.map((child, childIndex) => {
+      //     if (childIndex != index && child.EquipmentMark == item.EquipmentMark) {
+      //       sameFalg = true
+      //     }
+      //   })
+      // })
+      // if (sameFalg) {
+      //   this.confirm("点位中存在对象标识相同的点位,确认保存吗?", params)
+      // } else {
+      //   this.createParam(params)
+      // }
+      let pa = Object.assign({
+        DataSourceId: this.queryParam.DataSourceId,
+        KeyEquipmentParameter: this.queryParam.EquipmentParameter,
+        KeyEquipmentType: this.queryParam.EquipmentType,
+      }, this.dealType);
+      groupCreatePointRelation(pa, res => {
+        this.$message.success("处理成功")
+        this.$emit("changed")
       })
-      if (sameFalg) {
-        this.confirm("点位中存在对象标识相同的点位,确认保存吗?", params)
-      } else {
-        this.createParam(params)
-      }
     },
     confirm(assage, params) {
       this.$confirm(assage, { type: 'warning' }).then(_ => {
@@ -322,7 +344,7 @@ export default {
               this.activeName += 1
               let setting = {
                 data: this.renderData,
-                maxRows: this.renderData.length,
+                maxRows: 1000,
                 colHeaders: ['对象标识', '原始点位描述', '位置标签', '备注'],
                 columns: [{
                   data: 'EquipmentMark'
@@ -583,6 +605,73 @@ export default {
       this.infoDict = this.$refs.dictionaryCas.pointDataSource
       this.unitObj = this.infoDict[val[val.length - 1]]
       this.InfomationPoint = this.unitObj.InfoPointName || ''
+    },
+    //分页发生更改
+    changePage() {
+      this.$emit('changePage', this.queryParam);
+    },
+    // 修改table
+    changeTable(changeData, source) {
+      console.log(source)
+      if (source == 'edit' || source == 'Autofill.fill') {
+        let trimmedArr = this.trimmedRows();
+        let param = handsonUtils.getParam(changeData, source, this.hot, trimmedArr);
+        let updateParams = {
+          data: {
+            Content: []
+          },
+          type: this.protocolType
+        }
+        updateParams.data.Content = param.map(t => {
+          return {
+            Id: t.Id,
+            EquipmentMark: t.EquipmentMark
+          }
+        })
+        console.log(updateParams)
+        updatePoint(updateParams, data => {
+          this.$message.success("修改成功")
+        })
+      }
+    },
+    //获取被筛选掉的行号
+    trimmedRows() {
+      var plugin = this.hot.getPlugin("trimRows").trimmedRows;
+      let dataLength = this.renderData.length;
+      let dataArr = new Array();
+      for (let i = 0; i < dataLength; i++) {
+        dataArr.push(i);
+      }
+      if (plugin.length <= 0) {
+        dataArr = undefined;
+      } else {
+        dataArr = this.array_diff(dataArr, plugin);
+      }
+      return dataArr || [];
+    },
+    //去除数组中相同的元素
+    array_diff(a, b) {
+      for (var i = 0; i < b.length; i++) {
+        for (var j = 0; j < a.length; j++) {
+          if (a[j] == b[i]) {
+            a.splice(j, 1);
+            j = j - 1;
+          }
+        }
+      }
+      return a;
+    },
+  },
+  watch: {
+    'renderData': {
+      handler(n, o) {
+        if (n.length && this.hot) {
+          this.hot.loadData(n);
+          console.log('load')
+        }
+      },
+      immediate: true,
+      deep: true
     }
   }
 }

+ 9 - 2
src/components/config_point/step3_point/dialog_main.vue

@@ -105,7 +105,7 @@
                                 Used: true
                             },
                             PageNumber: 1,
-                            PageSize: 100
+                            PageSize: 1000
                         },
                         type: this.protocolType
                     }, res => {
@@ -264,7 +264,14 @@
                                     Visible: true,
                                     FirstTag: ""
                                 }
-                            ]
+                            ],
+                            "common": [{
+                                InfoPointName: "*地址详情",
+                                InfoPointCode: "JoinedInfo",
+                                InputMode: "B1",
+                                Visible: true,
+                                FirstTag: ""
+                            }],
                         }
                         let allData = this.identDataArr,
                             data = {

+ 20 - 8
src/components/config_point/step3_point/steps3_main.vue

@@ -4,7 +4,7 @@
         <select-one @check="typeCheck" :renderData="typeArr" :isSelected="true" isCheckInfo="PhysicalRelated" infosKey="EquipmentType" :name="'原始点位描述中识别的对象类型'"></select-one>
         <select-one @check="paramCheck" :isDel="true" @deleteItem="deleteItem" :renderData="identifyArr" :isSelected="true" isCheckInfo="PhysicalRelated" infosKey="ownMess" :name="'原始点位描述中识别的对象参数'"></select-one>
         <div class="own-collape">
-            <temp-collape ref="ident" :renderData="identDataArr" @changed="changed"></temp-collape>
+            <temp-collape ref="ident" :renderData="identDataArr" @changed="changed" :pages="pages" @changePage="changePage" :queryParam="queryParam"></temp-collape>
         </div>
     </div>
 </template>
@@ -33,7 +33,14 @@
                 typeArr: [],
                 identifyArr: [],
                 KeyEquipmentType: "",
-                identDataArr: []
+                identDataArr: [],
+                pages: {
+                    size: 100,
+                    sizes: [50, 100, 200, 500],
+                    total: 0,
+                    currentPage: 0
+                },
+                queryParam:{}
             }
         },
         computed: {
@@ -105,8 +112,9 @@
                     this.typeArr = res.Content
                 })
             },
-            paramCheck(param) {
+            paramCheck(param,pagechange) {
                 console.log(param,'param')
+                this.queryParam = param
                 if(!!param &&!!param.PhysicalRelated){
                     this.$message("已完成设置,您可以重新设置")
                 }
@@ -120,7 +128,8 @@
                         type: this.protocolType
                     }, res => {
                         this.identDataArr = res.Content
-                        this.$refs.ident.getMain(param)
+                        this.pages.total = res.Total || 0;
+                        this.$refs.ident.getMain(param,pagechange)
                     })
                 } else {
                     //不是空的情况查询点位列表
@@ -132,19 +141,19 @@
                                 Filters: {
                                     KeyEquipmentParameter: param.EquipmentParameter,
                                     KeyEquipmentType: param.EquipmentType,
-                                    DataSourceId: this.datasourceId,
                                     Used: true
                                     // KeyEquipmentParameter: '温度',
                                     // KeyEquipmentType: '冷机'
                                 },
-                                PageNumber: 1,
-                                PageSize: 100
+                                PageNumber: this.pages.currentPage,
+                                PageSize: this.pages.size
                             },
                             type: this.protocolType
                         }, res => {
                             console.log(res, "reslist")
                             this.identDataArr = res.Content
-                            this.$refs.ident.getMain(param)
+                            this.pages.total = res.Total || 0
+                            this.$refs.ident.getMain(param,pagechange)
                         })
                     }
                 }
@@ -166,6 +175,9 @@
                         })
                     })
                 }
+            },
+            changePage(){
+                this.paramCheck(this.queryParam,'pagechange')
             }
         },
         components: {

+ 184 - 0
src/components/data_admin/buildTask/detail/assetsDetail.vue

@@ -0,0 +1,184 @@
+<template>
+  <div class="detail-box">
+    <el-scrollbar style="height:100%;">
+      <div class="attribute-detail detail-item">
+        <el-form :model="detail" label-width="150px">
+          <el-form-item label="资产基本信息"></el-form-item>
+          <el-form-item label="任务创建时间:">{{ detail.CreateTime || '--' }}</el-form-item>
+          <el-form-item label="任务当前状态:">{{ detail.TaskState || '--' }}</el-form-item>
+          <el-form-item label="任务执行方案:">{{ detail.ScanScheme?detail.ScanScheme.SchemeName?detail.ScanScheme.SchemeName:'--':'--' }}</el-form-item>
+          <el-form-item label="设备族:">{{ detail.EquipFamily?detail.EquipFamily.FamilyName?detail.EquipFamily.FamilyName:'--':'--' }}</el-form-item>
+          <el-form-item label="全局名称:">{{ detail.EquipName || '--' }}</el-form-item>
+          <el-form-item label="资产本地名称:">{{ detail.EquipLocalName || '--' }}</el-form-item>
+          <el-form-item label="资产本地编码:">{{ detail.EquipLocalID || '--' }}</el-form-item>
+          <el-form-item label="设计图纸中编码:">{{ detail.CadId || '--' }}</el-form-item>
+          <el-form-item label="安装位置:">{{ detail.InstallLocation || '--' }}</el-form-item>
+          <el-form-item label="生产厂家:">{{ detail.Manufacturer || '--' }}</el-form-item>
+          <el-form-item label="型号:">{{ detail.Specification || '--' }}</el-form-item>
+          <el-form-item label="供应商:">{{ detail.Supplier || '--' }}</el-form-item>
+        </el-form>
+      </div>
+      <div class="implement-detail detail-item" v-if="detail.TaskState == '未找到'">
+        <el-form :model="detail" label-width="150px">
+          <el-form-item label="执行任务人:">{{ detail.WorkerName || '--' }}</el-form-item>
+          <el-form-item label="执行时间:">{{ detail.ProcessTime || '--' }}</el-form-item>
+          <el-form-item label="未找到对象信息"></el-form-item>
+          <el-form-item label="资产名称:">{{ detail.EquipLocalName || detail.EquipName || '--' }}</el-form-item>
+          <el-form-item label="全景图:" v-show="panoramaList && panoramaList.length">
+            <div class="img-item" @click="dialogVisible = true"  v-for="item in panoramaList" :key="item.Key">
+              <img :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`" style="width:100%;" :alt="item.Name">
+            </div>
+          </el-form-item>
+          <el-form-item label="资产照片:" v-show="imgList && imgList.length">
+            <div class="img-item">
+              <div class="demo-image__preview">
+                <el-image style="width:100%;" v-for="item in imgList"
+                 :key="item.Key" :title="item.Name"
+                 @click="nowUrl = item.Key" 
+                 :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}&width=400`" 
+                 :preview-src-list="srcList">
+                </el-image>
+              </div>
+            </div>
+          </el-form-item>
+          <el-form-item label="现场视频:" v-show="videoList && videoList.length">
+            <video controls style="width:100%;" v-for="item in videoList" :key="item.Key" :title="item.Name">
+              <source :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`" type="video/mp4">
+              您的浏览器不支持 HTML5 video ,暂无法播放。
+            </video>
+          </el-form-item>
+          <el-form-item label="备注信息:">{{ detail.Note || '--' }}</el-form-item>
+        </el-form>
+      </div>
+      <div class="operation-detail detail-item">
+        <el-form>
+          <el-form-item label="操作信息:"></el-form-item>
+          <div class="block">
+            <el-timeline>
+              <el-timeline-item timestamp="2018/4/12" placement="top">
+                <el-card>
+                  <h4>更新 Github 模板</h4>
+                  <p>王小虎 提交于 2018/4/12 20:46</p>
+                </el-card>
+              </el-timeline-item>
+              <el-timeline-item timestamp="2018/4/3" placement="top">
+                <el-card>
+                  <h4>更新 Github 模板</h4>
+                  <p>王小虎 提交于 2018/4/3 20:46</p>
+                </el-card>
+              </el-timeline-item>
+              <el-timeline-item timestamp="2018/4/2" placement="top">
+                <el-card>
+                  <h4>更新 Github 模板</h4>
+                  <p>王小虎 提交于 2018/4/2 20:46</p>
+                </el-card>
+              </el-timeline-item>
+            </el-timeline>
+          </div>
+        </el-form>
+      </div>
+    </el-scrollbar>
+    <el-dialog title="全景图" :visible.sync="dialogVisible" width="70%" append-to-body>
+      一张图
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { } from "@/api/scan/request"
+import { mapGetters } from "vuex"
+export default {
+  components: {
+
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    panoramaList(){
+      if(this.detail && this.detail.TaskPicList && this.detail.TaskPicList.length){
+        return this.detail.TaskPicList.filter(item => {
+          return item.Type == 'panorama'
+        })
+      } else {
+        return []
+      }
+    },
+    imgList(){
+      if(this.detail && this.detail.TaskPicList && this.detail.TaskPicList.length){
+        return this.detail.TaskPicList.filter(item => {
+          return item.Type == 'image'
+        })
+      } else {
+        return []
+      }
+    },
+    videoList(){
+      if(this.detail && this.detail.TaskPicList && this.detail.TaskPicList.length){
+        return this.detail.TaskPicList.filter(item => {
+          return item.Type == 'video'
+        })
+      } else {
+        return []
+      }
+    },
+    srcList(){
+      let nowIndex = this.imgList.findIndex(item => {return item.Key == this.nowUrl})
+      let index = nowIndex >= 1 ? nowIndex : 0;
+      let tempArr1 = this.imgList.slice(0, index);
+      let tempArr2 = this.imgList.slice(index, this.imgList.length);
+
+      let res = tempArr2.concat(tempArr1).map(item => {
+        return `/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`
+      });
+      return res;
+    }
+  },
+  props: {
+    detail: Object
+  },
+  data() {
+    return {
+      dialogVisible: false,//全景图弹出框
+      nowUrl: ''//当前正在显示的图
+    };
+  },
+  methods: {
+  },
+  watch: {
+    'detail.TaskId'() {
+      console.log(this.detail)
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+.detail-box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  /deep/ .el-scrollbar__wrap {
+    overflow-x: hidden;
+  }
+  /deep/ .el-icon-circle-close {
+    color: white;
+  }
+
+  /deep/ .el-form-item__content {
+    text-overflow: ellipsis;
+    overflow: hidden;
+  }
+
+  .detail-item {
+    width: calc(100% - 30px);
+    margin: 15px 15px 10px;
+    padding: 10px;
+    box-sizing: border-box;
+    border-left: 1px solid #eee;
+    box-shadow: 0px 1px 5px 0px rgba(59, 66, 84, 0.15);
+  }
+
+  .img-item {
+    position: relative;
+    cursor: pointer;
+  }
+}
+</style>

+ 219 - 0
src/components/data_admin/buildTask/detail/deviceDetail.vue

@@ -0,0 +1,219 @@
+<template>
+  <div class="detail-box">
+    <el-scrollbar style="height:100%;">
+      <div class="attribute-detail detail-item">
+        <el-form :model="detail" label-width="150px">
+          <el-form-item label="设备基本信息"></el-form-item>
+          <el-form-item label="任务创建时间:">{{ detail.CreateTime || '--' }}</el-form-item>
+          <el-form-item label="任务当前状态:">{{ detail.TaskState || '--' }}</el-form-item>
+          <el-form-item label="任务执行方案:">{{ detail.ScanScheme?detail.ScanScheme.SchemeName?detail.ScanScheme.SchemeName:'--':'--' }}</el-form-item>
+          <el-form-item label="设备类:">{{ detail.EquipCategory?detail.EquipCategory.EquipName?detail.EquipCategory.EquipName:'--':'--' }}</el-form-item>
+          <el-form-item label="全局名称:">{{ detail.EquipName || '--' }}</el-form-item>
+          <el-form-item label="设备本地名称:">{{ detail.EquipLocalName || '--' }}</el-form-item>
+          <el-form-item label="设备本地编码:">{{ detail.EquipLocalID || '--' }}</el-form-item>
+          <el-form-item label="设计图纸中编码:">{{ detail.CadId || '--' }}</el-form-item>
+          <el-form-item label="安装位置:">{{ detail.InstallLocation || '--' }}</el-form-item>
+          <el-form-item label="生产厂家:">{{ detail.Manufacturer || '--' }}</el-form-item>
+          <el-form-item label="型号:">{{ detail.Specification || '--' }}</el-form-item>
+          <el-form-item label="供应商:">{{ detail.Supplier || '--' }}</el-form-item>
+          <el-form-item label="包含部件:">
+            <div v-if="detail.Component && detail.Component.length">
+              <p v-for="(item, index) in detail.Component?detail.Component:[]" :key="index" show-overflow-tooltip>
+               {{ item.EquipName }}
+              </p>
+            </div>
+            <div v-else>--</div>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="implement-detail detail-item" v-if="detail.TaskState == '未找到'">
+        <el-form :model="detail" label-width="150px">
+          <el-form-item label="执行任务人:">{{ detail.WorkerName || '--' }}</el-form-item>
+          <el-form-item label="执行时间:">{{ detail.ProcessTime || '--' }}</el-form-item>
+          <el-form-item label="未找到对象信息"></el-form-item>
+          <el-form-item label="设备信息:" v-if="!detail.isComponent">{{ detail.EquipLocalName || detail.EquipName ||'--' }}</el-form-item>
+          <el-form-item label="部件信息:" v-else>
+            <div v-if="detail.Component && detail.Component.length">
+              <p v-for="item in detail.Component?detail.Component:[]" :key="item.TaskId" show-overflow-tooltip>
+               {{ item.EquipLocalName || item.EquipName }}
+              </p>
+            </div>
+            <div v-else>--</div>
+          </el-form-item>
+          <el-form-item label="全景图:" v-show="panoramaList && panoramaList.length">
+            <div class="img-item" @click="dialogVisible = true"  v-for="item in panoramaList" :key="item.Key">
+              <img :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`" style="width:100%;" :alt="item.Name">
+            </div>
+          </el-form-item>
+          <el-form-item label="资产照片:" v-show="imgList && imgList.length">
+            <div class="img-item">
+              <div class="demo-image__preview">
+                <el-image style="width:100%;" v-for="item in imgList"
+                 :key="item.Key" :title="item.Name"
+                 @click="nowUrl = item.Key" 
+                 :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}&width=400`" 
+                 :preview-src-list="srcList">
+                </el-image>
+              </div>
+            </div>
+          </el-form-item>
+          <el-form-item label="现场视频:" v-show="videoList && videoList.length">
+            <video controls style="width:100%;" v-for="item in videoList" :key="item.Key" :title="item.Name">
+              <source :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`" type="video/mp4">
+              您的浏览器不支持 HTML5 video ,暂无法播放。
+            </video>
+          </el-form-item>
+          <el-form-item label="备注信息:">{{ detail.Note || '--' }}</el-form-item>
+        </el-form>
+      </div>
+      <div class="operation-detail detail-item">
+        <el-form>
+          <el-form-item label="操作信息:"></el-form-item>
+          <div class="block">
+            <el-timeline>
+              <el-timeline-item timestamp="2018/4/12" placement="top">
+                <el-card>
+                  <h4>更新 Github 模板</h4>
+                  <p>王小虎 提交于 2018/4/12 20:46</p>
+                </el-card>
+              </el-timeline-item>
+              <el-timeline-item timestamp="2018/4/3" placement="top">
+                <el-card>
+                  <h4>更新 Github 模板</h4>
+                  <p>王小虎 提交于 2018/4/3 20:46</p>
+                </el-card>
+              </el-timeline-item>
+              <el-timeline-item timestamp="2018/4/2" placement="top">
+                <el-card>
+                  <h4>更新 Github 模板</h4>
+                  <p>王小虎 提交于 2018/4/2 20:46</p>
+                </el-card>
+              </el-timeline-item>
+            </el-timeline>
+          </div>
+        </el-form>
+      </div>
+    </el-scrollbar>
+    <el-dialog title="全景图" :visible.sync="dialogVisible" width="70%" append-to-body>
+      一张图
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { } from "@/api/scan/request"
+import { mapGetters } from "vuex"
+export default {
+  components: {
+
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    notFoundList(){
+      if(this.detail && this.detail.Component && this.detail.Component.length){//是否存在部件
+        let index = this.detail.Component.findIndex(item => {return item.TaskState == -1})
+        if(index != -1){//部件中存在未找到的对象
+          this.detail.isComponent = true
+          return this.detail.Component[index].TaskPicList?this.detail.Component[index].TaskPicList:[]
+        } else {//部件全部找到
+          this.detail.isComponent = false
+          return this.detail.TaskPicList?this.detail.TaskPicList:[]
+        }
+      } else {
+        this.detail.isComponent = false
+        if(this.detail && this.detail.TaskPicList && this.detail.TaskPicList.length){
+          return this.detail.TaskPicList
+        } else {
+          return []
+        }
+      }
+    },
+    panoramaList(){
+      if(this.notFoundList && this.notFoundList.length){
+        return this.notFoundList.filter(item => {
+          return item.Type == 'panorama'
+        })
+      } else {
+        return []
+      }
+    },
+    imgList(){
+      if(this.notFoundList && this.notFoundList.length){
+        return this.notFoundList.filter(item => {
+          return item.Type == 'image'
+        })
+      } else {
+        return []
+      }
+    },
+    videoList(){
+      if(this.notFoundList && this.notFoundList.length){
+        return this.notFoundList.filter(item => {
+          return item.Type == 'video'
+        })
+      } else {
+        return []
+      }
+    },
+    srcList(){
+      let nowIndex = this.imgList.findIndex(item => {return item.Key == this.nowUrl})
+      let index = nowIndex >= 1 ? nowIndex : 0;
+      let tempArr1 = this.imgList.slice(0, index);
+      let tempArr2 = this.imgList.slice(index, this.imgList.length);
+
+      let res = tempArr2.concat(tempArr1).map(item => {
+        return `/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`
+      });
+      return res;
+    }
+  },
+  props: {
+    detail: Object
+  },
+  data() {
+    return {
+      dialogVisible: false,//全景图弹出框
+      nowUrl: '',//当前正在显示的图
+    };
+  },
+  methods: {
+  },
+  watch: {
+    'detail.TaskId'() {
+      console.log(this.detail)
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+.detail-box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  /deep/ .el-scrollbar__wrap {
+    overflow-x: hidden;
+  }
+  /deep/ .el-icon-circle-close {
+    color: white;
+  }
+
+  /deep/ .el-form-item__content {
+    text-overflow: ellipsis;
+    overflow: hidden;
+  }
+
+  .detail-item {
+    width: calc(100% - 30px);
+    margin: 15px 15px 10px;
+    padding: 10px;
+    box-sizing: border-box;
+    border-left: 1px solid #eee;
+    box-shadow: 0px 1px 5px 0px rgba(59, 66, 84, 0.15);
+  }
+
+  .img-item {
+    position: relative;
+    cursor: pointer;
+  }
+}
+</style>

+ 97 - 0
src/components/data_admin/buildTask/dialog/addTaskDialog.vue

@@ -0,0 +1,97 @@
+<template>
+  <el-dialog :title="title" :visible.sync="addTaskDialog" :before-close="handleClose" width="500px">
+    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="110px">
+      <el-form-item label="未验证任务" prop="isVerification">
+        <el-switch v-model="ruleForm.isVerification"></el-switch>
+      </el-form-item>
+      <el-form-item label="任务类型" prop="taskType">
+        <div>
+          <el-radio v-model="ruleForm.taskType" label="model">现场验证模型</el-radio>
+        </div>
+        <div>
+          <el-radio v-model="ruleForm.taskType" label="device">现场验证设备台账</el-radio>
+        </div>
+        <div>
+          <el-radio v-model="ruleForm.taskType" label="assets">现场验证资产台账</el-radio>
+        </div>
+      </el-form-item>
+    </el-form>
+    <!-- <el-row>
+      请选择新建现场验证任务的数据源:
+      <el-checkbox v-model="ruleForm.isVerification">只选择未验证的</el-checkbox>
+    </el-row>
+    <el-row style="margin-top:15px;padding-left:15px;">
+      <div><el-radio v-model="ruleForm.taskType" label="model">现场验证模型</el-radio></div>
+      <div><el-radio v-model="ruleForm.taskType" label="device">现场验证设备台账</el-radio></div>
+      <div><el-radio v-model="ruleForm.taskType" label="assets">现场验证资产台账</el-radio></div>
+    </el-row>-->
+    <span slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="$emit('update:addTaskDialog',false)">取 消</el-button>
+      <el-button type="primary" @click="toAddTask()">确 认</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import {} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+export default {
+  components: {},
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加验证任务",
+      dialogVisible: false,
+      ruleForm: {
+        isVerification: true,
+        taskType: ""
+      },
+      rules: {
+        taskType: [
+          { required: true, message: "请选择任务类型", trigger: "change" }
+        ]
+      }
+    };
+  },
+  created() {},
+  props: {
+    addTaskDialog: Boolean, //是否显示弹窗
+    newTaskTypes: Array
+  },
+  methods: {
+    toAddTask() {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.ruleForm.newTaskTypes = this.newTaskTypes;
+          if (this.ruleForm.taskType == "model") {
+            this.$router.push({
+              path: "/floor/addModelTask",
+              query: this.ruleForm
+            });
+          } else if (this.ruleForm.taskType == "device") {
+            this.$router.push({
+              path: "/floor/addDeviceTask",
+              query: this.ruleForm
+            });
+          } else if (this.ruleForm.taskType == "assets") {
+            this.$router.push({
+              path: "/floor/addAssetsTask",
+              query: this.ruleForm
+            });
+          }
+        } else {
+          console.log("error submit!!");
+          return false;
+        }
+      });
+    },
+    handleClose() {
+      this.$emit("update:addTaskDialog", this.dialogVisible);
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+</style>

+ 253 - 0
src/components/data_admin/buildTask/dialog/modelTaskDialog.vue

@@ -0,0 +1,253 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" :before-close="handleClose" width="900px" id="addEqDialog">
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="350" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column type="expand">
+          <template slot-scope="props">
+            <p v-if="props.row.ComponentCount && props.row.ComponentCount.length" style="color:#99a9bf;line-height:32px;font-size:14px;">包含的部件:</p>
+            <el-form label-position="left" label-width="auto" inline class="demo-table-expand"
+              v-if="props.row.ComponentCount && props.row.ComponentCount.length">
+              <el-form-item v-for="item in props.row.ComponentCount?props.row.ComponentCount:[]" :key="item.code" :label="`${item.name}:`">
+                <span>{{ item.count }}</span>
+              </el-form-item>
+            </el-form>
+          </template>
+        </el-table-column>
+        <el-table-column prop="FolderName" label="所属模型文件夹" width="110" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="FileName" label="模型文件名" width="80" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="EquipLocalName" label="设备本地名称" show-overflow-tooltip width="100"></el-table-column>
+        <el-table-column prop="EquipLocalID" label="设备本地编码" show-overflow-tooltip width="100"></el-table-column>
+        <el-table-column prop="EquipCategory.EquipName" label="设备类" show-overflow-tooltip width="120"></el-table-column>
+        <el-table-column prop="BimId" label="BIM Id" show-overflow-tooltip width="80"></el-table-column>
+        <el-table-column prop="type" label="现场验证操作规定" width="150">
+          <template slot-scope="scope">
+            <el-select style="width:100px;" v-model="scope.row.SchemeId" placeholder="请选择">
+              <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+            </el-select>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            数据暂无
+          </div>
+        </template>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="$emit('update:dialogVisible',false)">返回重选</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确认创建</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { queryEquip } from "@/api/scan/request"
+import { createModelTask, queryModelDiglog } from "@/api/data_admin/buildTaskApi"
+import { mapGetters } from "vuex"
+export default {
+  components: {
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "确认创建任务",
+      options: [{//方案
+        value: '1',
+        label: '标准'
+      }],
+      tableData: [],
+      loading: false,
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      } // 列表样式
+    };
+  },
+  props: {
+    dialogVisible: Boolean,//是否显示弹窗
+    params: Object, //模型和设备的信息
+    newTaskTypes: Array
+  },
+  created() {
+
+  },
+  methods: {
+    getTableData() {
+      let params = {
+        Cascade: [
+          {
+            Name: "equipCategory",
+            Projection: ["EquipCode", "EquipName"]
+          },
+          {
+            Name: "component",
+            Cascade: [{ Name: "equipCategory" }]
+          },
+          {
+            Name: "building",
+            Projection: ["BuildLocalName", "BuildName", "BuildID"]
+          },
+          {
+            Name: "floor",
+            Projection: ["FloorLocalName", "FloorName", "FloorID"]
+          }
+        ],
+        Filters: `ProjectId='${this.projectId}'`,
+        Orders: "CreateTime desc, EquipID asc",
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+
+      if (this.params.isVerification) {
+        params.Filters += `;TaskState isNull`
+      }
+
+      if (this.params.device) {
+        params.Filters += `;Category='${this.params.category}'`
+      }
+
+      if (this.params.spaceList && this.params.spaceList.length) {
+        //通过平面图区域查询(接口未支持)paramsQuery:{listId:[]}
+        params.IdList = this.params.spaceList
+        queryModelDiglog(params, res => {
+          this.dataFormatter(res)
+        })
+      } else {
+        params.Filters += `;ModelId='${this.params.CurrentModelId}'`
+        queryEquip(params, res => {
+          this.dataFormatter(res)
+        })
+      }
+
+    },
+    // 表格数据格式化
+    dataFormatter(res) {
+      this.tableData = res.Content.map(item => {
+        if (item.Component && item.Component.length) {
+          item.ComponentCount = []
+          item.Component.map(parts => {
+            if (parts.EquipCategory && parts.EquipCategory.EquipCode && parts.EquipCategory.EquipName) {
+              let index = item.ComponentCount.findIndex(c => { return c.code == parts.EquipCategory.EquipCode })
+              if (index != -1) {
+                item.ComponentCount[index].count++
+              } else {
+                item.ComponentCount.push({
+                  name: parts.EquipCategory.EquipName,
+                  code: parts.EquipCategory.EquipCode,
+                  count: 1
+                })
+              }
+            }
+          })
+        }
+        item.FolderName = this.params.modelFolderName
+        item.FolderId = this.params.modelFolderId
+        item.FileName = this.params.modelFileName
+        item.FileId = this.params.CurrentModelId
+        item.SchemeId = "1"
+        return item
+      })
+      this.page.total = res.Total
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    savaRelation() {
+      if (this.selections.length) {
+        let list = this.selections.map((item) => {
+          return {
+            EquipId: item.EquipID,
+            FileId: item.FileId,
+            FileName: item.FileName,
+            FolderId: item.FolderId,
+            FolderName: item.FolderName
+          }
+        })
+        let params = {
+          Content: list
+        }
+        createModelTask(params, res => {
+          this.$emit('update:dialogVisible', false)
+          this.$message.success('创建成功!')
+          this.$router.push({ name: 'buildTask', query: { newTaskTypes: this.newTaskTypes } })//跳转回首页
+        })
+      } else {
+        this.$message('请选择要创建的任务!')
+      }
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = 1
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    handleClose() {//关闭弹窗
+      this.$emit('update:dialogVisible', false);
+    }
+  },
+  watch: {
+    dialogVisible(newData, oldData) {
+      if (newData) {
+        this.tableData = []
+        this.page.pageNumber = 1
+        this.getTableData()
+      }
+    }
+  },
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin-bottom: 10px;
+    /deep/ .el-input__inner {
+      vertical-align: baseline;
+    }
+  }
+  .table-box {
+    height: 370px;
+    .fr {
+      margin-top: 10px;
+    }
+  }
+}
+</style>
+
+<style>
+.demo-table-expand {
+  font-size: 0;
+}
+.demo-table-expand label {
+  width: 90px;
+  color: #99a9bf;
+}
+.demo-table-expand .el-form-item {
+  margin-right: 0;
+  margin-bottom: 0;
+  margin-left: 120px;
+  width: 100%;
+}
+</style>

+ 181 - 0
src/components/data_admin/buildTask/draw/drawModel.vue

@@ -0,0 +1,181 @@
+<template>
+  <div :id="`drawFloor${id}`" class="drawFloor" v-loading="canvasLoading">
+    <canvas :id="`floorCanvas${id}`" :width="cadWidth" :height="cadHeight" ref="canvas" tabindex="0"></canvas>
+    <div class="operate" v-show="showTools">
+      <canvasFun @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @scale="scale" :config="config" ref="canvasFun"></canvasFun>
+    </div>
+  </div>
+</template>
+
+<script>
+import { DivideFloorScene, FloorView } from "@saga-web/cad-engine/lib"
+import { SColor, SPoint } from "@sybotan-web/draw/lib";
+import canvasFun from "@/components/business_space/newGraphy/canvasFun"
+import { floorQuery } from "@/api/scan/request";
+export default {
+  components: {
+    canvasFun
+  },
+  data() {
+    return {
+      drawMainScene: null,
+      view: null,
+      dataKey: '',
+      cadWidth: 800,
+      cadHeight: 600,
+      canvasLoading: false,
+      modelId: '',
+      FloorID: '',
+      Outline: [],
+      buttonContent: "",
+      showTools: false,
+      config: {
+        isEdit: false
+      }
+    };
+  },
+  props: {
+    isEdit: {
+      default: false
+    },
+    id: {
+      default: 0
+    },
+    dialog: {
+      default: false
+    },
+    CurrentModelId: String
+  },
+  created() { },
+  mounted() {
+    this.cadWidth = document.getElementById(`drawFloor${this.id}`).offsetWidth;
+    this.cadHeight = document.getElementById(`drawFloor${this.id}`).offsetHeight;
+  },
+  methods: {
+    initGraphy(ModelId) {
+      this.modelId = ModelId;
+      this.clearGraphy()
+      this.drawMainScene = new DivideFloorScene();
+      this.canvasLoading = true;
+      this.drawMainScene.getFloorData('/modelapi/base-graph/query', { ModelId: ModelId }).then(res => {
+        console.log(this)
+        this.getGraphtSuc(res);
+      })
+    },
+    getFloorData() {
+      let pa = {
+        Filters: `FloorID='${this.FloorID}'`
+      }
+      floorQuery(pa, res => {
+        let newArr = res.Content[0].Outline.map(t => {
+          return new SPoint(t.X, t.Y);
+        })
+        this.drawMainScene.addSceneMark(newArr)
+      })
+    },
+    getSelectedSpaces() {//获取选中区域
+      if (this.view && this.view.scene) {
+        let list = this.view.scene.getSelectedSpaces();
+        if (list.length) {
+          return list
+        } else {
+          return []
+        }
+      } else {
+        return []
+      }
+    },
+    // 清空平面图
+    clearGraphy() {
+      if (this.view) {
+        this.view.scene = null;
+        return
+      }
+      let id = `floorCanvas${this.id}`;
+      this.view = new FloorView(id)
+    },
+    canvasClick(item, eventObj) {//点击平面图事件 
+      this.$emit("changeButtonContent",this.drawMainScene.getSelectedSpaces().length?"通过模型空间创建":"通过模型创建") 
+    },
+    getGraphtSuc(res) {
+      this.showTools = true;
+      this.canvasLoading = false;
+      if (res.Result == 'failure') {
+        this.showTools = false;
+        this.$message.warning(res.Message);
+        return;
+      }
+      this.view.scene = this.drawMainScene;
+      this.view.fitSceneToView();
+      this.drawMainScene.click(this, this.canvasClick);
+
+      if (this.$refs.canvasFun) {
+        this.view.maxScale = this.view.scale * 10;
+        this.view.minScale = this.view.scale;
+        this.$refs.canvasFun.everyScale = this.view.scale;
+      }
+    },
+    // canvas 获取焦点
+    focus() {
+      document.getElementById(`floorCanvas${this.id}`).focus()
+    },
+    // 工具栏操作
+    // 适配底图到窗口
+    fit() {
+      this.view.fitSceneToView()
+    },
+    // 保存为png
+    savePng() {
+      this.view.saveImage(`${this.floor}.png`, 'png');
+    },
+    // 保存为svg
+    saveSvg() {
+      this.view.saveSceneSvg(`${this.floor}.svg`, 6400, 4800);
+    },
+    // 缩放
+    scale(val) {
+      if (!this.view) {
+        return;
+      }
+      let scale = this.view.scale;
+      this.view.scaleByPoint(val / scale, this.cadWidth / 2, this.cadHeight / 2);
+    }
+  },
+  watch: {
+    CurrentModelId: {
+      handler(newName, oldName) {
+        if (newName) {
+          this.initGraphy(newName)
+        }
+      },
+      immediate: true,
+    },
+    "view.scale": {
+      handler(n) {
+        if (this.$refs.canvasFun) {
+          this.$refs.canvasFun.sliderVal = n * 10 / this.view.minScale;
+        }
+      }
+    },
+    "isEdit": {
+      handler(n) {
+        this.config.isEdit = n;
+      }
+    }
+  }
+};
+</script>
+<style scoped lang="less">
+.drawFloor {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  .operate {
+    position: absolute;
+    left: 50%;
+    bottom: 20px;
+    transform: translateX(-50%);
+    z-index: 99;
+  }
+}
+</style>

+ 70 - 0
src/components/data_admin/buildTask/lib/assetsCascader.vue

@@ -0,0 +1,70 @@
+<template>
+  <div id="cascaderMap">
+    <span class="buildFloor" style="margin-right: 12px;">设备族</span>
+    <el-select v-model="value" placeholder="请选择" clearable filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+      <el-option  v-for="item in options" :key="item.Code" :label="item.Name" :value="item.Code"></el-option>
+    </el-select>
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+import { queryAssetsFamily } from "@/api/data_admin/buildTaskApi"
+export default {
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      value: "",
+      options: []
+    };
+  },
+  created() {
+    this.getData();
+  },
+  watch: {
+    projectId() {
+      this.value = '';
+      this.getData();
+    }
+  },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      let value = {}
+      this.options.map(item => {
+        if (item.Code == val) {
+          value = item
+        }
+      })
+      this.value = val
+      this.$emit("change", value)
+    },
+    //获取当前项目下的资产任务-设备族
+    getData() {
+      queryAssetsFamily('', res => {
+        this.options = res.Content
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 70 - 0
src/components/data_admin/buildTask/lib/deviceCascader.vue

@@ -0,0 +1,70 @@
+<template>
+  <div id="cascaderMap">
+    <span class="buildFloor" style="margin-right: 12px;">设备类别</span>
+    <el-select v-model="value" placeholder="请选择" clearable filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+      <el-option  v-for="item in options" :key="item.Code" :label="item.Name" :value="item.Code"></el-option>
+    </el-select>
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+import { queryDeviceCategory } from "@/api/data_admin/buildTaskApi"
+export default {
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      value: "",
+      options: []
+    };
+  },
+  created() {
+    this.getData();
+  },
+  watch: {
+    projectId() {
+      this.value = '';
+      this.getData();
+    }
+  },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      let value = {}
+      this.options.map(item => {
+        if (item.Code == val) {
+          value = item
+        }
+      })
+      this.value = val
+      this.$emit("change", value)
+    },
+    //获取当前项目下的设备任务-设备类型
+    getData() {
+      queryDeviceCategory('', res => {
+        this.options = res.Content
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 70 - 0
src/components/data_admin/buildTask/lib/modelCascader.vue

@@ -0,0 +1,70 @@
+<template>
+  <div id="cascaderMap">
+    <span class="buildFloor" style="margin-right: 12px;">设备类别</span>
+    <el-select v-model="value" placeholder="请选择" clearable filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+      <el-option  v-for="item in options" :key="item.Code" :label="item.Name" :value="item.Code"></el-option>
+    </el-select>
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+import { queryModelCategory } from "@/api/data_admin/buildTaskApi"
+export default {
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      value: "",
+      options: []
+    };
+  },
+  created() {
+    this.getData();
+  },
+  watch: {
+    projectId() {
+      this.value = '';
+      this.getData();
+    }
+  },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      let value = {}
+      this.options.map(item => {
+        if (item.Code == val) {
+          value = item
+        }
+      })
+      this.value = val
+      this.$emit("change", value)
+    },
+    //获取当前项目下的模型任务-设备类型
+    getData() {
+      queryModelCategory('', res => {
+        this.options = res.Content
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 81 - 0
src/components/data_admin/buildTask/lib/modelFile.vue

@@ -0,0 +1,81 @@
+<template>
+    <div id="modelFile">
+        <span class="modelFile" style="margin-right: 12px;">模型文件</span>
+        <el-cascader :options="options" :props="props" :show-all-levels="false" @change="handleChange" style="width:160px;"
+        clearable placeholder="请选择模型文件" v-model="casVal"></el-cascader>
+    </div>
+</template>
+<script>
+import tools from "@/utils/scan/tools"
+import { queryModelFile } from "@/api/data_admin/buildTaskApi"
+import { mapGetters, mapActions } from "vuex"
+
+export default {
+  computed: {
+    ...mapGetters("layout", [ "projectId", "secret", "userId" ])
+  },
+  data() {
+    return {
+      casVal: [],
+      options: [],
+      modelIdToFloorId: {},
+      props: {
+        value: "FileId",
+        label: "FileName",
+        children: "FileList"
+      },
+    };
+  },
+  created() {
+    this.init()
+  },
+  watch: {
+    projectId() {
+      this.casVal =[]
+      this.options = []
+      this.init()
+    }
+  },
+  methods: {
+    //设置默认选项
+    setValue(val) {
+        if (val && val.length) {
+          this.casVal = val
+        }
+    },
+    //获取数据
+    init() {
+      this.getDirectory()
+    },
+    // 获取文件夹
+    getDirectory() {
+      queryModelFile("", res => {
+        this.options = res.Content.map(item => {
+          item.FileId = item.FolderId
+          item.FileName = item.FolderName
+          return item
+        })
+      });
+    },
+    //改变item
+    handleChange(value) {
+      this.$emit("change", value)
+    }
+  }
+};
+</script>
+<style lang="less">
+    .el-cascader .el-input .el-input__inner {
+        vertical-align: bottom;
+    }
+</style>
+<style lang="less" scoped>
+    #modelFile {
+        margin-left: 10px;
+        float: left;
+        .modelFile {
+            color: #999999;
+            font-size: 14px;
+        }
+    }
+</style>

+ 53 - 0
src/components/data_admin/buildTask/lib/taskState.vue

@@ -0,0 +1,53 @@
+<template>
+  <div id="cascaderMap">
+    <span class="task-state" style="margin-right: 12px;">任务执行情况</span>
+    <el-select v-model="taskState" placeholder="请选择" filterable style="width:120px;" size="small" @change="changeState">
+      <el-option  v-for="item in taskStateList" :key="item.code" :label="item.label" :value="item.value"></el-option>
+    </el-select>
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+export default {
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      taskStateList: [{
+				value: '',
+				label: '全部'
+			}, {
+				value: 1,
+				label: '待验证'
+			}, {
+				value: 0,
+				label: '已完成'
+			}, {
+				value: -1,
+				label: '未找到'
+			}],
+			taskState: '',//任务执行情况
+    };
+  },
+  methods: {
+    setValue(val) {
+      this.taskState = val
+    },
+    //修改val
+    changeState(val) {
+      this.$emit("change", val)
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .task-state {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 220 - 0
src/components/data_admin/buildTask/table/assetsTable.vue

@@ -0,0 +1,220 @@
+<template>
+  <div class="table-container">
+    <div class="table-list" :style="tableData && tableData.length?'height:calc(100% - 50px);':'height:100%;'">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column label="所属建筑楼层" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.Building?scope.row.Building.BuildLocalName?scope.row.Building.BuildLocalName:'':''}} -
+              {{scope.row.Floor?scope.row.Floor.FloorLocalName?scope.row.Floor.FloorLocalName:'':''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipLocalName" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipFamily.FamilyName" label="设备族" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="InstallLocation" label="安装位置" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="TaskState" label="任务执行情况" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <i v-if="scope.row.TaskState == '待验证' || scope.row.TaskState == '未找到'" title="查看详情" class="iconfont icon-xiangqing table-button" @click="handleDetail(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="重新生成任务" class="iconfont icon-Update table-button" @click="handleRegenerate(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '待验证'" title="删除任务" class="iconfont icon-delete table-button" @click="handleDelete(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="认可此任务执行情况" class="iconfont icon-lijiqueren table-button" @click="handleConfirm(scope.$index, scope.row)"></i>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            数据暂无
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <el-pagination class="right" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNumber"
+     :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.total">
+    </el-pagination>
+    <el-drawer title="任务详情" :visible.sync="drawer" direction="rtl" size="600px">
+      <assets-detail :detail="detailAssets"></assets-detail>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { queryAssetsTask, deleteAssetsTask, createAssetsTask, updateAssetsTask } from "@/api/data_admin/buildTaskApi"
+import tools from "@/utils/tools"
+import { mapGetters } from "vuex"
+import assetsDetail from '../detail/assetsDetail'
+export default {
+  components: {
+    assetsDetail
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  props: {
+    paramsData: Object,
+  },
+  data() {
+    return {
+      inSpaceType: '资产',
+      loading: false, // loading
+      drawer: false, // 详情侧弹窗
+      detailAssets: {},
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      taskStateMap: {
+        '-1': '未找到',
+        '0': '已完成',
+        '1': '待验证'
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+    };
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `ProjectId='${this.projectId}'`,
+        Cascade: [
+          {
+            Name: 'equipFamily'
+          }, {
+            Name: 'scanScheme'
+          }, {
+            Name: 'building',
+          }, {
+            Name: 'floor',
+          }
+        ],
+        Orders: "CreateTime desc, TaskId asc",
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      if (this.paramsData.buildfloor[0] == "noKnow") {
+        params.Filters += `;BuildingId isNull`
+      } else if (this.paramsData.buildfloor[0] && this.paramsData.buildfloor[0] != "all") {
+        params.Filters += `;BuildingId='${this.paramsData.buildfloor[0]}'`
+        if (this.paramsData.buildfloor[1] == "noKnow") {
+          params.Filters += `;FloorId isNull`
+        } else if (this.paramsData.buildfloor[1] && this.paramsData.buildfloor[1] != "all") {
+          params.Filters += `;FloorId='${this.paramsData.buildfloor[1]}'`
+        }
+      }
+      if(this.paramsData.taskState !== ''){
+        params.Filters += `;TaskState=${this.paramsData.taskState}`
+      }
+      if(this.paramsData.family){
+        params.Filters += `;Category='${this.paramsData.family}'`
+      }
+      queryAssetsTask(params, res => {
+        this.page.total = res.Total;
+        this.tableData = res.Content.map(item => {
+          item.TaskState = this.taskStateMap[item.TaskState]
+          return item
+        })
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该任务?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = [{TaskId: row.TaskId}]
+        deleteAssetsTask(params, res => {
+          this.$message.success('删除成功')
+          this.getTableData()
+        })
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    //重新生成任务
+    handleRegenerate(index, row){
+      let params = {
+        Content: [{
+          EquipId: row.EquipId,
+          TaskState: -1
+        }]
+      }
+      createAssetsTask(params, res => {
+        this.$message.success('重新生成任务成功!')
+        this.getTableData()
+      })
+    },
+    //认可此任务执行情况
+    handleConfirm(index, row){
+      let params = {
+        Content: [{
+          TaskId: row.TaskId,
+          TaskState: 0
+        }]
+      }
+      updateAssetsTask(params, res => {
+        this.$message.success('更新成功!')
+        this.getTableData()
+      })
+    },
+    //查看任务详情
+    handleDetail(index, row) {
+      this.drawer = true
+      this.detailAssets = row
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageNumber = 1
+      this.page.pageSize = pageSize;
+      this.getTableData()
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData()
+    },
+    projectId() {
+      this.page.pageNumber = 1
+      this.getTableData()
+    }
+  },
+  watch: {
+    paramsData: {
+      handler(newName, oldName) {
+        if(!tools.isSimilarly(newName, oldName)){
+          this.page.pageNumber = 1
+          this.getTableData()
+        }
+      },
+      immediate: true,
+      deep: true
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+/deep/ .el-drawer__body {
+  height: calc(100% - 80px);
+  border-top: 1px solid #c9c9c9;
+}
+/deep/ .el-drawer__header {
+  margin-bottom: 12px;
+}
+.table-container {
+  height: 100%;
+  background: #fff;
+  .table-button{
+    cursor: pointer;
+    margin-right: 15px;
+  }
+}
+</style>

+ 248 - 0
src/components/data_admin/buildTask/table/deviceTable.vue

@@ -0,0 +1,248 @@
+<template>
+  <div class="table-container">
+    <div class="table-list" :style="tableData && tableData.length?'height:calc(100% - 50px);':'height:100%;'">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column label="所属建筑楼层" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.Building?scope.row.Building.BuildLocalName?scope.row.Building.BuildLocalName:'':''}} -
+              {{scope.row.Floor?scope.row.Floor.FloorLocalName?scope.row.Floor.FloorLocalName:'':''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.EquipLocalName}}
+              <el-badge v-if="scope.row.Equipment?scope.row.Equipment.Component?scope.row.Equipment.Component.length:false:false" 
+                :value="scope.row.Equipment?scope.row.Equipment.Component?scope.row.Equipment.Component.length:0:0" class="item" type="warning">
+              </el-badge>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipCategory.EquipName" :label="`${inSpaceType}类型`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="InstallLocation" label="安装位置" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="TaskState" label="任务执行情况" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <i v-if="scope.row.TaskState == '待验证' || scope.row.TaskState == '未找到'" title="查看详情" class="iconfont icon-xiangqing table-button" @click="handleDetail(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="重新生成任务" class="iconfont icon-Update table-button" @click="handleRegenerate(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '待验证'" title="删除任务" class="iconfont icon-delete table-button" @click="handleDelete(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="认可此任务执行情况" class="iconfont icon-lijiqueren table-button" @click="handleConfirm(scope.$index, scope.row)"></i>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            数据暂无
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <el-pagination class="right" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNumber"
+     :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.total">
+    </el-pagination>
+    <el-drawer title="任务详情" :visible.sync="drawer" direction="rtl" size="600px">
+      <device-detail :detail="detailDevice"></device-detail>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { queryDeviceTask, deleteDeviceTask, createDeviceTask, updateDeviceTask } from "@/api/data_admin/buildTaskApi"
+import tools from "@/utils/tools"
+import { mapGetters } from "vuex"
+import deviceDetail from '../detail/deviceDetail'
+export default {
+  components: {
+    deviceDetail
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  props: {
+    paramsData: Object,
+  },
+  data() {
+    return {
+      inSpaceType: '设备',
+      loading: false, // loading
+      drawer: false, // 详情侧弹窗
+      detailDevice: {},
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      taskStateMap: {
+        '-1': '未找到',
+        '0': '已完成',
+        '1': '待验证'
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+    };
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `ProjectId='${this.projectId}'`,
+        Cascade: [
+          {
+            Name: 'component'
+          }, {
+            Name: 'scanScheme'
+          }, {
+            Name: 'building',
+          }, {
+            Name: 'floor',
+          }, {
+            Name: 'equipCategory'
+          }
+        ],
+        Orders: "CreateTime desc, TaskId asc",
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      if (this.paramsData.buildfloor[0] == "noKnow") {
+        params.Filters += `;BuildingId isNull`
+      } else if (this.paramsData.buildfloor[0] && this.paramsData.buildfloor[0] != "all") {
+        params.Filters += `;BuildingId='${this.paramsData.buildfloor[0]}'`
+        if (this.paramsData.buildfloor[1] == "noKnow") {
+          params.Filters += `;FloorId isNull`
+        } else if (this.paramsData.buildfloor[1] && this.paramsData.buildfloor[1] != "all") {
+          params.Filters += `;FloorId='${this.paramsData.buildfloor[1]}'`
+        }
+      }
+      if(this.paramsData.taskState !== ''){
+        params.Filters += `;TaskState=${this.paramsData.taskState}`
+      }
+      if(this.paramsData.deviceCategory){
+        params.Filters += `;Category='${this.paramsData.deviceCategory}'`
+      }
+      queryDeviceTask(params, res => {
+        this.page.total = res.Total;
+        this.tableData = res.Content.map(item => {
+          if(item.Component && item.Component.length){
+            item.ComponentCount = []
+            item.Component.map(parts => {
+              if(parts.EquipCategory && parts.EquipCategory.EquipCode && parts.EquipCategory.EquipName){
+                let index = item.ComponentCount.findIndex(c => {return c.code == parts.EquipCategory.EquipCode})
+                if(index != -1){
+                  item.ComponentCount[index].count++
+                } else {
+                  item.ComponentCount.push({
+                    name: parts.EquipCategory.EquipName,
+                    code: parts.EquipCategory.EquipCode,
+                    count: 1
+                  })
+                }
+              }
+            })
+          }
+          item.TaskState = this.taskStateMap[item.TaskState]
+          return item
+        })
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该任务?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = [{TaskId: row.TaskId}]
+        deleteDeviceTask(params, res => {
+          this.$message.success('删除成功')
+          this.getTableData()
+        })
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    //重新生成任务
+    handleRegenerate(index, row){
+      let params = {
+        Content: [{
+          EquipId: row.EquipId,
+          TaskState: -1
+        }]
+      }
+      createDeviceTask(params, res => {
+        this.$message.success('重新生成任务成功!')
+        this.getTableData()
+      })
+    },
+    //认可此任务执行情况
+    handleConfirm(index, row){
+      let params = {
+        Content: [{
+          TaskId: row.TaskId,
+          TaskState: 0
+        }]
+      }
+      updateDeviceTask(params, res => {
+        this.$message.success('更新成功!')
+        this.getTableData()
+      })
+    },
+    //查看任务详情
+    handleDetail(index, row) {
+      this.drawer = true
+      this.detailDevice = row
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageNumber = 1
+      this.page.pageSize = pageSize;
+      this.getTableData()
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData()
+    }
+  },
+  watch: {
+    paramsData: {
+      handler(newName, oldName) {
+        if(!tools.isSimilarly(newName, oldName)){
+          this.page.pageNumber = 1
+          this.getTableData()
+        }
+      },
+      immediate: true,
+      deep: true
+    },
+    projectId() {
+      this.page.pageNumber = 1
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+/deep/ .el-drawer__body {
+  height: calc(100% - 80px);
+  border-top: 1px solid #c9c9c9;
+}
+/deep/ .el-drawer__header {
+  margin-bottom: 12px;
+}
+.table-container {
+  height: 100%;
+  background: #fff;
+  .table-button{
+    cursor: pointer;
+    margin-right: 15px;
+  }
+}
+</style>

+ 238 - 0
src/components/data_admin/buildTask/table/modelTable.vue

@@ -0,0 +1,238 @@
+<template>
+  <div class="table-container">
+    <div class="table-list" :style="tableData && tableData.length?'height:calc(100% - 50px);':'height:100%;'">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column prop="FolderName" label="所属模型文件夹" show-overflow-tooltip min-width="80"></el-table-column>
+        <el-table-column prop="FileName" label="模型文件名" show-overflow-tooltip min-width="80"></el-table-column>
+        <el-table-column :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.EquipLocalName}}
+              <el-badge v-if="scope.row.Equipment?scope.row.Equipment.Component?scope.row.Equipment.Component.length:false:false" 
+                :value="scope.row.Equipment?scope.row.Equipment.Component?scope.row.Equipment.Component.length:0:0" class="item" type="warning">
+              </el-badge>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipCategory.EquipName" :label="`${inSpaceType}类型`" show-overflow-tooltip min-width="80"></el-table-column>
+        <el-table-column prop="BIMID" label="BIM ID" show-overflow-tooltip min-width="220"></el-table-column>
+        <el-table-column prop="TaskState" label="任务执行情况" show-overflow-tooltip min-width="60"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <i v-if="scope.row.TaskState == '待验证' || scope.row.TaskState == '未找到'" title="查看详情" class="iconfont icon-xiangqing table-button" @click="handleDetail(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="重新生成任务" class="iconfont icon-Update table-button" @click="handleRegenerate(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '待验证'" title="删除任务" class="iconfont icon-delete table-button" @click="handleDelete(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="认可此任务执行情况" class="iconfont icon-lijiqueren table-button" @click="handleConfirm(scope.$index, scope.row)"></i>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            数据暂无
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <el-pagination class="right" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNumber"
+     :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.total">
+    </el-pagination>
+    <el-drawer title="任务详情" :visible.sync="drawer" direction="rtl" size="600px">
+      <device-detail :detail="detailModel"></device-detail>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { queryModelTask, deleteModelTask, updateModelTask, createModelTask } from "@/api/data_admin/buildTaskApi"
+import tools from "@/utils/tools"
+import { mapGetters } from "vuex"
+import deviceDetail from '../detail/deviceDetail'
+export default {
+  components: {
+    deviceDetail
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  props: {
+    paramsData: Object,
+  },
+  data() {
+    return {
+      inSpaceType: '设备',
+      loading: false, // loading
+      drawer: false, // 详情侧弹窗
+      detailModel: {},
+      tableData: [], //列表数据
+      taskStateMap: {
+        '-1': '未找到',
+        '0': '已完成',
+        '1': '待验证'
+      },
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+    };
+  },
+  created() {
+    // this.getTableData()
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `ProjectId='${this.projectId}'`,
+        Cascade: [
+          {
+            Name: 'component'
+          }, {
+            Name: 'scanScheme'
+          }, {
+            Name: 'equipCategory'
+          }
+        ],
+        Orders: "CreateTime desc, TaskId asc",
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      if(this.paramsData.taskState !== ''){
+        params.Filters += `;TaskState=${this.paramsData.taskState}`
+      }
+      if(this.paramsData.modelFile){
+        params.Filters += `;FileId='${this.paramsData.modelFile}'`
+      }
+      if(this.paramsData.modelCategory){
+        params.Filters += `;Category='${this.paramsData.modelCategory}'`
+      }
+      queryModelTask(params, res => {
+        this.page.total = res.Total;
+        this.tableData = res.Content.map(item => {
+          if(item.Component && item.Component.length){
+            item.ComponentCount = []
+            item.Component.map(parts => {
+              if(parts.EquipCategory && parts.EquipCategory.EquipCode && parts.EquipCategory.EquipName){
+                let index = item.ComponentCount.findIndex(c => {return c.code == parts.EquipCategory.EquipCode})
+                if(index != -1){
+                  item.ComponentCount[index].count++
+                } else {
+                  item.ComponentCount.push({
+                    name: parts.EquipCategory.EquipName,
+                    code: parts.EquipCategory.EquipCode,
+                    count: 1
+                  })
+                }
+              }
+            })
+          }
+          item.TaskState = this.taskStateMap[item.TaskState]
+          return item
+        })
+      })
+    },
+    // 删除任务
+    handleDelete(index, row) {
+      this.$confirm("确认删除该任务?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = [{TaskId: row.TaskId}]
+        deleteModelTask(params, res => {
+          this.$message.success('删除成功')
+          this.getTableData()
+        })
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    //重新生成任务
+    handleRegenerate(index, row){
+      let params = {
+        Content: [{
+          EquipId: row.EquipId,
+          FileId: row.FileId,
+          FileName: row.FileName,
+          FolderId: row.FolderId,
+          FolderName: row.FolderName,
+          TaskState: -1
+        }]
+      }
+      createModelTask(params, res => {
+        this.$message.success('重新生成任务成功!')
+        this.getTableData()
+      })
+    },
+    //认可此任务执行情况
+    handleConfirm(index, row){
+      let params = {
+        Content: [{
+          TaskId: row.TaskId,
+          TaskState: 0
+        }]
+      }
+      updateModelTask(params, res => {
+        this.$message.success('更新成功!')
+        this.getTableData()
+      })
+    },
+    //查看任务详情
+    handleDetail(index, row) {
+      this.drawer = true
+      this.detailModel = row
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageNumber = 1
+      this.page.pageSize = pageSize;
+      this.getTableData()
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData()
+    }
+  },
+  watch: {
+    paramsData: {
+      handler(newName, oldName) {
+        if(!tools.isSimilarly(newName, oldName)){
+          this.page.pageNumber = 1
+          this.getTableData()
+        }
+      },
+      immediate: true,
+      deep: true
+    },
+    projectId() {
+      this.page.pageNumber = 1
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+/deep/ .el-drawer__body {
+  height: calc(100% - 80px);
+  border-top: 1px solid #c9c9c9;
+}
+/deep/ .el-drawer__header {
+  margin-bottom: 12px;
+}
+.table-container {
+  height: 100%;
+  background: #fff;
+  .table-button{
+    cursor: pointer;
+    margin-right: 15px;
+  }
+}
+</style>

+ 202 - 0
src/components/data_admin/buildTask/table/replaceTable.vue

@@ -0,0 +1,202 @@
+<template>
+  <div class="table-container">
+    <div class="table-list" :style="tableData && tableData.length?'height:calc(100% - 50px);':'height:100%;'">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column label="所属建筑楼层" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.Building?scope.row.Building.BuildLocalName?scope.row.Building.BuildLocalName:'':''}} -
+              {{scope.row.Floor?scope.row.Floor.FloorLocalName?scope.row.Floor.FloorLocalName:'':''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipLocalName" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipFamily.FamilyName" label="设备族" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="InstallLocation" label="安装位置" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="TaskType" label="任务执行情况" show-overflow-tooltip min-width="100"></el-table-column>
+        <!-- <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <i v-if="scope.row.TaskState == '待验证' || scope.row.TaskState == '未找到'" title="查看详情" class="iconfont icon-xiangqing table-button" @click="handleDetail(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="重新生成任务" class="iconfont icon-Update table-button" @click="handleRegenerate(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '待验证'" title="删除任务" class="iconfont icon-delete table-button" @click="handleDelete(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="认可此任务执行情况" class="iconfont icon-lijiqueren table-button" @click="handleConfirm(scope.$index, scope.row)"></i>
+          </template>
+        </el-table-column> -->
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            数据暂无
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <el-pagination class="right" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNumber"
+     :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.total">
+    </el-pagination>
+    <el-drawer title="任务详情" :visible.sync="drawer" direction="rtl" size="600px">
+      <assets-detail :id="detailId"></assets-detail>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { queryAssetsTask, deleteAssetsTask } from "@/api/data_admin/buildTaskApi"
+import tools from "@/utils/tools"
+import { mapGetters } from "vuex"
+import assetsDetail from '../detail/assetsDetail'
+export default {
+  components: {
+    assetsDetail
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  props: {
+    paramsData: Object,
+  },
+  data() {
+    return {
+      inSpaceType: '资产',
+      loading: false, // loading
+      drawer: false, // 详情侧弹窗
+      detailId: '',
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      taskTypeMap: {//待撕码,待换码
+        '-5': '已撕码',
+        '3': '待撕码',
+        '2': '待换码',
+        '0': '正常贴码'
+      },
+      taskStateMap: {
+        '-1': '未找到',
+        '0': '已完成',
+        '1': '待验证'
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+    };
+  },
+  created() {
+    this.getTableData()
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `ProjectId='${this.projectId}';TaskType in ['2']`,
+        Cascade: [
+          {
+            Name: 'equipFamily'
+          }, {
+            Name: 'building',
+          }, {
+            Name: 'floor',
+          }
+        ],
+        Orders: "CreateTime desc, TaskId asc",
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      // if (this.paramsData.buildfloor[0] == "noKnow") {
+      //   params.Filters += `;BuildingId isNull`
+      // } else if (this.paramsData.buildfloor[0] && this.paramsData.buildfloor[0] != "all") {
+      //   params.Filters += `;BuildingId='${this.paramsData.buildfloor[0]}'`
+      //   if (this.paramsData.buildfloor[1] == "noKnow") {
+      //     params.Filters += `;FloorId isNull`
+      //   } else if (this.paramsData.buildfloor[1] && this.paramsData.buildfloor[1] != "all") {
+      //     params.Filters += `;FloorId='${this.paramsData.buildfloor[1]}'`
+      //   }
+      // }
+      // if(this.paramsData.taskState !== ''){
+      //   params.Filters += `;TaskState=${this.paramsData.taskState}`
+      // }
+      // if(this.paramsData.family){
+      //   params.Filters += `;Family='${this.paramsData.family}'`
+      // }
+      queryAssetsTask(params, res => {
+        this.page.total = res.Total;
+        this.tableData = res.Content.map(item => {
+          item.TaskState = this.taskStateMap[item.TaskState]
+          item.TaskType = this.taskTypeMap[item.TaskType]
+          return item
+        })
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该任务?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = [{TaskId: row.TaskId}]
+        deleteAssetsTask(params, res => {
+          this.$message.success('删除成功')
+          this.getTableData()
+        })
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    //查看任务详情
+    handleDetail() {
+      this.drawer = true
+      this.detailId = row.TaskId
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageNumber = 1
+      this.page.pageSize = pageSize;
+      this.getTableData()
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData()
+    }
+  },
+  watch: {
+    paramsData: {
+      handler(newName, oldName) {
+        if(!tools.isSimilarly(newName, oldName)){
+          this.page.pageNumber = 1
+          this.getTableData()
+        }
+      },
+      immediate: true,
+      deep: true
+    },
+    projectId() {
+      this.page.pageNumber = 1
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+/deep/ .el-drawer__body {
+  height: calc(100% - 80px);
+  border-top: 1px solid #c9c9c9;
+}
+/deep/ .el-drawer__header {
+  margin-bottom: 12px;
+}
+.table-container {
+  height: 100%;
+  background: #fff;
+  .table-button{
+    cursor: pointer;
+    margin-right: 15px;
+  }
+}
+</style>

+ 202 - 0
src/components/data_admin/buildTask/table/tearTable.vue

@@ -0,0 +1,202 @@
+<template>
+  <div class="table-container">
+    <div class="table-list" :style="tableData && tableData.length?'height:calc(100% - 50px);':'height:100%;'">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column label="所属建筑楼层" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.Building?scope.row.Building.BuildLocalName?scope.row.Building.BuildLocalName:'':''}} -
+              {{scope.row.Floor?scope.row.Floor.FloorLocalName?scope.row.Floor.FloorLocalName:'':''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipLocalName" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipFamily.FamilyName" label="设备族" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="InstallLocation" label="安装位置" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="TaskType" label="任务执行情况" show-overflow-tooltip min-width="100"></el-table-column>
+        <!-- <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <i v-if="scope.row.TaskState == '待验证' || scope.row.TaskState == '未找到'" title="查看详情" class="iconfont icon-xiangqing table-button" @click="handleDetail(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="重新生成任务" class="iconfont icon-Update table-button" @click="handleRegenerate(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '待验证'" title="删除任务" class="iconfont icon-delete table-button" @click="handleDelete(scope.$index, scope.row)"></i>
+            <i v-if="scope.row.TaskState == '未找到'" title="认可此任务执行情况" class="iconfont icon-lijiqueren table-button" @click="handleConfirm(scope.$index, scope.row)"></i>
+          </template>
+        </el-table-column> -->
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            数据暂无
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <el-pagination class="right" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNumber"
+     :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.total">
+    </el-pagination>
+    <el-drawer title="任务详情" :visible.sync="drawer" direction="rtl" size="600px">
+      <assets-detail :id="detailId"></assets-detail>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { queryAssetsTask, deleteAssetsTask } from "@/api/data_admin/buildTaskApi"
+import tools from "@/utils/tools"
+import { mapGetters } from "vuex"
+import assetsDetail from '../detail/assetsDetail'
+export default {
+  components: {
+    assetsDetail
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  props: {
+    paramsData: Object,
+  },
+  data() {
+    return {
+      inSpaceType: '资产',
+      loading: false, // loading
+      drawer: false, // 详情侧弹窗
+      detailId: '',
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      taskTypeMap: {//待撕码,待换码
+        '-5': '已撕码',
+        '3': '待撕码',
+        '2': '待换码',
+        '0': '正常贴码'
+      },
+      taskStateMap: {
+        '-1': '未找到',
+        '0': '已完成',
+        '1': '待验证'
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+    };
+  },
+  created() {
+    this.getTableData()
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `ProjectId='${this.projectId}';TaskType in ['3','-5']`,
+        Cascade: [
+          {
+            Name: 'equipFamily'
+          }, {
+            Name: 'building',
+          }, {
+            Name: 'floor',
+          }
+        ],
+        Orders: "CreateTime desc, TaskId asc",
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      // if (this.paramsData.buildfloor[0] == "noKnow") {
+      //   params.Filters += `;BuildingId isNull`
+      // } else if (this.paramsData.buildfloor[0] && this.paramsData.buildfloor[0] != "all") {
+      //   params.Filters += `;BuildingId='${this.paramsData.buildfloor[0]}'`
+      //   if (this.paramsData.buildfloor[1] == "noKnow") {
+      //     params.Filters += `;FloorId isNull`
+      //   } else if (this.paramsData.buildfloor[1] && this.paramsData.buildfloor[1] != "all") {
+      //     params.Filters += `;FloorId='${this.paramsData.buildfloor[1]}'`
+      //   }
+      // }
+      // if(this.paramsData.taskState !== ''){
+      //   params.Filters += `;TaskState=${this.paramsData.taskState}`
+      // }
+      // if(this.paramsData.family){
+      //   params.Filters += `;Family='${this.paramsData.family}'`
+      // }
+      queryAssetsTask(params, res => {
+        this.page.total = res.Total;
+        this.tableData = res.Content.map(item => {
+          item.TaskState = this.taskStateMap[item.TaskState]
+          item.TaskType = this.taskTypeMap[item.TaskType]
+          return item
+        })
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该任务?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = [{TaskId: row.TaskId}]
+        deleteAssetsTask(params, res => {
+          this.$message.success('删除成功')
+          this.getTableData()
+        })
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    //查看任务详情
+    handleDetail() {
+      this.drawer = true
+      this.detailId = row.TaskId
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageNumber = 1
+      this.page.pageSize = pageSize;
+      this.getTableData()
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData()
+    }
+  },
+  watch: {
+    paramsData: {
+      handler(newName, oldName) {
+        if(!tools.isSimilarly(newName, oldName)){
+          this.page.pageNumber = 1
+          this.getTableData()
+        }
+      },
+      immediate: true,
+      deep: true
+    },
+    projectId() {
+      this.page.pageNumber = 1
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+/deep/ .el-drawer__body {
+  height: calc(100% - 80px);
+  border-top: 1px solid #c9c9c9;
+}
+/deep/ .el-drawer__header {
+  margin-bottom: 12px;
+}
+.table-container {
+  height: 100%;
+  background: #fff;
+  .table-button{
+    cursor: pointer;
+    margin-right: 15px;
+  }
+}
+</style>

+ 160 - 0
src/components/data_admin/buildTask/taskStatistics.vue

@@ -0,0 +1,160 @@
+<template>
+  <div class="statistics-box flex-row">
+		<div class="statistics-all flex-row">
+      <div class="statistics-progress">
+        <div class="statistics-progress-num">
+          <p>{{taskProgress?taskProgress:0 + '%'}}</p>
+          <p>完成情况</p>
+        </div>
+        <el-progress :width="90" type="circle" :percentage="taskProgress?taskProgress:0" :show-text="false"></el-progress>
+      </div>
+      <div class="statistics-all-box flex-col">
+        <span>总任务:<b>{{allCount}}</b></span>
+        <span>已完成:<b>{{alreadyCount}}</b></span>
+      </div>
+    </div>
+		<ul class="statistics-list flex-row">
+      <li>
+        <p class="statistics-list-text">现场未找到(需人工确认):</p>
+        <p class="statistics-list-num">{{notFoundCount}}</p>
+      </li>
+      <li>
+        <p class="statistics-list-text">待验证任务:</p>
+        <p class="statistics-list-num">{{waitCount}}</p>
+      </li>
+      <li>
+        <p class="statistics-list-text">待撕码任务:</p>
+        <p class="statistics-list-num">{{waitTearCount}}</p>
+      </li>
+      <li>
+        <p class="statistics-list-text">待换码任务:</p>
+        <p class="statistics-list-num">{{waitReplaceCount}}</p>
+      </li>
+    </ul>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from "vuex"
+import { queryTaskCount, countAssetsTask } from "@/api/data_admin/buildTaskApi"
+export default {
+  components: {
+    
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId" ]),
+    taskProgress(){
+      if(typeof this.alreadyCount == 'number' && typeof this.allCount == 'number'){
+        return Math.round(this.alreadyCount/this.allCount*100)
+      }
+    }
+  },
+  data() {
+    return {
+      allCount: '',//总任务
+      alreadyCount: '',//已完成
+      notFoundCount: '',//未找到
+      waitCount: '',//未完成验证
+      waitTearCount: '',//未完成撕码任务
+      waitReplaceCount: ''//未完成换码任务
+    }
+  },
+  created() {
+    this.getTaskCount();
+  },
+  methods: {
+    getTaskCount(){
+      queryTaskCount({},(res) => {
+        this.allCount = res.Count
+      })
+      queryTaskCount({Filters: `TaskState=0`},(res) => {
+        this.alreadyCount = res.Count
+      })
+      queryTaskCount({Filters: `TaskState=-1`},(res) => {
+        this.notFoundCount = res.Count
+      })
+      queryTaskCount({Filters: `TaskState=1`},(res) => {
+        this.waitCount = res.Count
+      })
+      countAssetsTask({Filters: `TaskState=1&&TaskType='3'`},(res) => {
+        this.waitTearCount = res.Count
+      })
+      countAssetsTask({Filters: `TaskState=1&&TaskType='2'`},(res) => {
+        this.waitReplaceCount = res.Count
+      })
+    }
+  },
+  watch: {
+    projectId() {
+      this.getTaskCount();
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+	.statistics-box {
+		height: 120px;
+    color: #333;
+    .statistics-all{
+      flex: 2;
+      border: 1px solid #c9c9c9;
+      margin-right: 10px;
+      background: #fff;
+      .statistics-progress{
+        flex: 1;
+        position: relative;
+        height: 120px;
+        box-sizing: border-box;
+        text-align: center;
+        padding: 15px 0;
+        .statistics-progress-num{
+          font-size: 12px;
+          line-height: 18px;
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+        }
+      }
+      .statistics-all-box{
+        flex: 1;
+        font-weight: bold;
+        padding: 25px 0;
+        >span{
+          flex: 1;
+          font-size: 15px;
+          line-height: 35px;
+        } 
+      }
+    }
+    .statistics-list{
+      flex: 7;
+      >li{
+        flex: 1;
+        border: 1px solid #c9c9c9;
+        padding: 10px;
+        margin-left: 10px;
+        background: #fff;
+        .statistics-list-text{
+          font-size: 15px;
+          line-height: 30px;
+          font-weight: bold;
+        }
+        .statistics-list-num{
+          text-align: center;
+          font-size: 20px;
+          line-height: 50px;
+          font-weight: bold;
+        }
+      }
+    }
+	}
+  .flex-row{
+    display: flex;
+		flex-direction: row;
+  }
+  .flex-col{
+    display: flex;
+		flex-direction: column;
+  }
+</style>

+ 1 - 9
src/components/dialogs/list/uploadImgDialog.vue

@@ -42,16 +42,8 @@ export default {
   mounted() { },
   methods: {
     deepcopy(obj) {
-      //   var out = [],
-      //     i = 0,
-      //     len = obj.length;
-      //   for (; i < len; i++) {
-      //     if (obj[i] instanceof Array) {
-      //       out[i] = this.deepcopy(obj[i]);
-      //     } else out[i] = obj[i];
-      //   }
       console.log(obj, "out")
-      return obj;
+      return JSON.parse(JSON.stringify(obj));
     },
     changeItem(file) {
       console.log(file, "changed")

+ 225 - 0
src/components/ledger/cenote/dialog/addSpaceDialog.vue

@@ -0,0 +1,225 @@
+
+<template>
+  <el-dialog :title="title" :visible.sync="dialog" :before-close="handleClose" width="900px" id="addEqDialog">
+    <el-row class="filters">
+      <el-col :span="7" style="width:268px;padding:0px;">
+        <el-input style placeholder="输入业务空间名称、本地编码进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="8.5" style="padding:0 0;margin-left:-2px">
+        <floor-cascader ref="floorcas" @change="changeFloor"></floor-cascader>
+      </el-col>
+      <el-col :span="7.5" style="padding:0 0;">
+        <space-select ref="spacesel" @change="changeSpace"></space-select>
+      </el-col>
+    </el-row>
+    <el-row class="filters" :gutter="20"></el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="350" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            {{scope.row.RoomLocalName||scope.row.RoomName||''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="RoomLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop :label="`所属建筑楼层`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            {{ scope.row.BuildingId && floorType[scope.row.BuildingId]? ((floorType[scope.row.BuildingId] || '') + (scope.row.FloorId && floorType[scope.row.FloorId] ? (' - ' + floorType[scope.row.FloorId] || '') : '')) : ''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="ObjectType" :label="`空间类型`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            {{spaceType[scope.row.ObjectType] || ''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="toDetail(scope.$index, scope.row)" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="handleClose">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  unSysZoneSpace,
+  linkSysSp,
+  queryDictionaryHead
+} from "@/api/scan/request";
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import dictionaryCas from "@/components/config_point/dictionaryCascader";
+import spaceSelect from "@/components/ledger/lib/spaceSelect";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+    floorCascader,
+    dictionaryCas,
+    spaceSelect
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    dialog() {
+      return this.dialogVisible;
+    }
+  },
+  data() {
+    return {
+      title: "添加系统所在业务空间",
+      keycode: "", //输入查询条件
+      inSpaceType: "业务空间",
+      Buildfloor: ["all"], // 选中的建筑楼层
+      Spacecategory: null, // 选中的业务空间类型
+      tableData: [],
+      floorData: {}, //楼层
+      spaceData: {}, //业务空间分区
+      loading: false,
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: "#e1e4e5",
+        color: "#2b2b2b",
+        lineHeight: "30px"
+      } // 列表样式
+    };
+  },
+  props: {
+    params: Object, //查看的竖井关系信息
+    spaceType: Object,
+    dialogVisible: Boolean,
+    floorType: Object
+  },
+  mounted() { },
+  methods: {
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true;
+    },
+    //修改建筑楼层
+    changeFloor(value) {
+      this.Buildfloor = value;
+      this.getTableData();
+    },
+    //修改空间类型
+    changeSpace(value) {
+      this.Spacecategory = value;
+      this.getTableData();
+    },
+    getTableData() {
+      let params = {
+        data: {
+          Filters: "not RoomID isNull",
+          Orders: "RoomLocalName desc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize
+        },
+        shaftId: this.params.ShaftID,
+        sysId: this.$route.query.SysID
+      };
+      if (this.Buildfloor[0] == "noKnow") {
+        params.data.Filters += `;buildingId isNull`;
+      } else if (this.Buildfloor[0] && this.Buildfloor[0] != "all") {
+        params.data.Filters += `;buildingId='${this.Buildfloor[0]}'`;
+      }
+      if (this.Buildfloor[1] == "noKnow") {
+        params.data.Filters += `;floorId isNull`;
+      } else if (this.Buildfloor[1] && this.Buildfloor[1] != "all") {
+        params.data.Filters += `;floorId='${this.Buildfloor[1]}'`;
+      }
+      if (this.Spacecategory) {
+        params.data.Filters += `;ObjectType='${this.Spacecategory}'`;
+      }
+      if (this.keycode != "") {
+        params.data.Filters += `;RoomName contain '${this.keycode}' or RoomLocalName contain '${this.keycode}'`;
+      }
+
+      unSysZoneSpace(params, res => {
+        this.tableData = res.Content;
+        this.page.total = res.Total;
+      });
+    },
+    handleClose() {
+      this.$emit("update:dialogVisible", false);
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    savaRelation() {
+      if (this.selections.length) {
+        let params = {
+          Content: this.selections.map(item => {
+            return {
+              SpaceID: item.RoomID,
+              SysID: this.$route.query.SysID,
+              ObjectType: item.ObjectType
+            };
+          })
+        };
+        linkSysSp(params, res => {
+          this.$message.success("关联成功!");
+          this.$emit("refresh");
+        });
+      } else {
+        this.$message("请选择要关联的设备");
+      }
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 查看详情
+    toDetail() {
+      this.$message("开发中");
+    }
+  },
+  watch: {
+    dialogVisible: {
+      handler() {
+        if (this.dialogVisible) {
+          this.page.pageNumber = 1;
+          this.tableData = [];
+          this.getTableData();
+        }
+      },
+      immediate: true
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin: 0 0 10px 0;
+  }
+  .table-box {
+    height: 370px;
+    .fr {
+      margin-top: 10px;
+    }
+  }
+}
+</style>

+ 5 - 4
src/components/ledger/handsontables/assets.vue

@@ -45,7 +45,7 @@
       <my-pagination @change="getTableData" :page="page"></my-pagination>
     </div>
     <!-- <dialog-assets :assetType="[this.mess.deviceId]"  @close="closeDialog" ref="assets" v-if="myDialog.addDevice" :dialog="myDialog" ></dialog-assets> -->
-    <details-dialog :iframeSrc="iframeSrc" v-if="myDialog.details" :dialog="myDialog"></details-dialog>
+    <!-- <details-dialog :iframeSrc="iframeSrc" v-if="myDialog.details" :dialog="myDialog"></details-dialog> -->
     <look-pic :dialog="myDialog" :keysArr="picsArr"></look-pic>
     <!-- 不支持的输入方式 -->
     <el-dialog title="临时维护信息点" :visible.sync="myDialog.update" @close="handleCloseUpdate" width="670px">
@@ -97,7 +97,7 @@ import insurerDialog from "@/components/business_space/dialogs/list/insurerDialo
 import guaranteeDialog from "@/components/business_space/dialogs/list/guaranteeDialog"
 import uploadFilesDialog from "@/components/business_space/dialogs/list/filesDialog"
 import uploadImgDialog from "@/components/business_space/dialogs/list/uploadImgDialog"
-import detailsDialog from "@/components/business_space/lib/detailsDia"
+// import detailsDialog from "@/components/business_space/lib/detailsDia"
 import picDialog from "@/components/business_space/dialogs/list/picDialog"
 import myPagination from "@/components/common/myPagination"
 import dialogAssets from "@/components/ledger/addDialog/dialogAssets"
@@ -131,7 +131,7 @@ export default {
     myCascader,
     floorCascader,
     dieCascader,
-    detailsDialog,
+    // detailsDialog,
     lookPic
   },
   created() {
@@ -329,7 +329,8 @@ export default {
                       tools.setDataForKey(
                         item,
                         head.Path,
-                        child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        // child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        child.error ? child.value? "表号功能号格式错误" : "表号功能号不存在" : "暂未采集到实时数据"
                       );
                     }
                   });

+ 18 - 18
src/components/ledger/handsontables/device.vue

@@ -2,9 +2,9 @@
   <div style="height: calc(100% - 44.5px);padding: 0px 10px 10px;box-sizing: border-box;">
     <div class="hanson-bar">
       <div style="float:right;overflow:hidden;">
-        <span style="width:20px;float:left;display:block;height:20px;cursor: pointer;" @click="changeAssetsFalg">
+        <!-- <span style="width:20px;float:left;display:block;height:20px;cursor: pointer;" @click="changeAssetsFalg">
           <i v-show="!onlyRead" class="el-icon-fa  el-icon-fa-compass"></i>
-        </span>
+        </span> -->
         <span>当前筛选条件下共{{page.total || '--'}}设备</span>
       </div>
       <el-select v-model="onlyRead" @change="getHeaderData(mess)" style="width:100px;margin-right:20px;vertical-align:bottom;">
@@ -149,7 +149,7 @@ export default {
     lookPic,
     myCascader
   },
-  created() { 
+  created() {
     buildFloor.getData(this.buildFloorData)
   },
   computed: {
@@ -208,7 +208,7 @@ export default {
       id: 0,
       onlyRead: true,
       showType: 'Visible',
-      linkNameFalg: false,
+      linkNameFalg: true,
       qrcodeUrl: "", //二维码图片地址
       loading: false,
       deviceType: {}, //族3位编码及名称
@@ -241,7 +241,7 @@ export default {
         getDataDictionary(params, res => {
           this.tableHeader = res.Content;
           this.tableHeader.forEach(item => {
-            if(item.Path && item.InputMode){
+            if (item.Path && item.InputMode) {
               this.inputMap[item.Path] = item.InputMode
             }
           })
@@ -341,7 +341,7 @@ export default {
                       tools.setDataForKey(
                         item,
                         head.Path,
-                        child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        child.error ? child.value ? "表号功能号格式错误" : "表号功能号不存在" : "暂未采集到实时数据"
                       );
                     }
                   });
@@ -441,14 +441,14 @@ export default {
           readOnly: true,
           renderer: tools.LinkEquipLocalName
         }, {
-          data: "LinkSystem",
-          renderer: text.systemList,
-          readOnly: true
-        }, {
-          data: "Count",
-          readOnly: true,
-          renderer: tools.lookDetails
-        }
+        data: "LinkSystem",
+        renderer: text.systemList,
+        readOnly: true
+      }, {
+        data: "Count",
+        readOnly: true,
+        renderer: tools.lookDetails
+      }
       );
       if (this.showType == "all") {
         data.splice(6, 0, {
@@ -601,8 +601,8 @@ export default {
       change.map(item => {
         let key = item[1].split(".")[0]
         if (key == "flowBuild" && keyList.indexOf(key) == -1) {
-          keyList.push("BuildingId","FloorId")
-          param.Projection.push("BuildingId","FloorId")
+          keyList.push("BuildingId", "FloorId")
+          param.Projection.push("BuildingId", "FloorId")
         }
         if (item[1] && keyList.indexOf(key) == -1 && item[1] != 'PropertyId') {
           keyList.push(key);
@@ -688,7 +688,7 @@ export default {
           return false
         //关联资产
         case 'LinkEquipLocalName':
-          if (this.linkNameFalg) {
+          if (!this.onlyRead) {
             this.myDialog.changeRea = true;
           }
           return false
@@ -795,7 +795,7 @@ export default {
       this.updateInput = ''
     },
     //更新临时维护信息点
-    handleClickUpdate(){
+    handleClickUpdate() {
       tools.setDataForKey(this.tableData[this.row], this.updateInfoPoint, this.updateInput)
       this.handleUpdataTable([[this.row, this.updateInfoPoint, null, this.updateInput]], "edit")
       this.updateInputShow = false

+ 45 - 49
src/components/ledger/handsontables/system.vue

@@ -32,18 +32,7 @@
     <details-dialog :iframeSrc="iframeSrc" v-if="myDialog.details" :dialog="myDialog"></details-dialog>
     <system-relevance @close="reset" :id="systemId" :dialog="myDialog"></system-relevance>
     <!-- 不支持的输入方式 -->
-    <el-dialog title="临时维护信息点" :visible.sync="myDialog.update" @close="handleCloseUpdate" width="670px">
-      <el-row>
-        该信息点未定义对应组件,现在维护数据不确定后续是否可用。如确实需要维护,请点击<el-link @click="updateInputShow = true" type="primary" :underline="false">继续维护</el-link>。
-      </el-row>
-      <el-row style="margin-top:20px;" v-show="updateInputShow">
-        <el-input type="textarea" :autosize="{ minRows: 4, maxRows: 8}" placeholder="请输入内容" v-model="updateInput"></el-input>
-      </el-row>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="myDialog.update = false">取 消</el-button>
-        <el-button type="primary" @click="handleClickUpdate">确 认</el-button>
-      </span>
-    </el-dialog>
+    <editSysfloor ref="editFloor" @handleClickUpdate="handleClickUpdate"></editSysfloor>
     <!-- 新增系统 -->
     <el-dialog title="确定新增系统的类型" :visible.sync="myDialog.addDevice" width="30%">
       <el-row>
@@ -57,11 +46,7 @@
 </template>
 <script>
 import {
-  getTableHeader,
-  getBillSystemList,
-  updateBusiness,
   BeatchQueryParam,
-  delBatchList,
   getDataDictionary,
   queryLinkSys,
   updateGeneralSys,
@@ -80,13 +65,11 @@ import dialogAssets from "@/components/ledger/addDialog/dialogSystem"
 import detailsDialog from "@/components/business_space/lib/detailsDia"
 import systemRelevance from "@/components/ledger/tableTransfers"
 import Handsontable from "handsontable-pro"
+import text from "@/utils/handsontable/mainText"
 import 'handsontable-pro/dist/handsontable.full.css'
-import zhCN from 'handsontable-pro/languages/zh-CN'
+import editSysfloor from "@/components/ledger/lib/editSysFloor";
 
-import {
-  mapGetters,
-  mapActions
-} from "vuex";
+import { mapGetters } from "vuex";
 export default {
   components: {
     qrcode, //二维码页面
@@ -97,7 +80,8 @@ export default {
     dialogAssets,
     detailsDialog,
     systemRelevance,
-    myCascader
+    myCascader,
+    editSysfloor
   },
   computed: {
     ...mapGetters("layout", ["projectId", "secret", "userId"]),
@@ -187,7 +171,7 @@ export default {
         getDataDictionary(params, res => {
           this.tableHeader = res.Content;
           this.tableHeader.forEach(item => {
-            if(item.Path && item.InputMode){
+            if (item.Path && item.InputMode) {
               this.inputMap[item.Path] = item.InputMode
             }
           })
@@ -271,7 +255,10 @@ export default {
     formatHeaderData(list) {
       let arr = tools.copyArr(list)
       let data = showTools.headerTextFilter(arr, 'system', this.onlyRead, this.showType)
-      data.unshift("操作", "关联设备数量");
+      data.unshift("操作");
+      if (this.showType == "all") {
+        data.splice(3, 0, "所属建筑楼层")
+      }
       return data;
     },
     //格式化表内容
@@ -284,17 +271,24 @@ export default {
           renderer: tools.lookDetails,
           readOnly: true
         },
-        {
-          data: "Count",
-          renderer: tools.num,
-          readOnly: true
-        }
+        // {
+        //   data: "Count",
+        //   renderer: tools.num,
+        //   readOnly: true
+        // }
       );
       if (this.onlyRead) {
         data.map(item => {
           item.readOnly = true
         })
       }
+      if (this.showType == "all") {
+        data.splice(3, 0, {
+          data: "sysInBuildFloor",
+          renderer: text.sysInBuildFloor,
+          readOnly: this.onlyRead
+        })
+      }
       return data;
     },
     //获取动态参数
@@ -346,7 +340,8 @@ export default {
                       tools.setDataForKey(
                         item,
                         head.Path,
-                        child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        // child.error ? "表号功能号格式错误" : "表号功能号不存在"
+                        child.error ? child.value? "表号功能号格式错误" : "表号功能号不存在" : "暂未采集到实时数据"
                       );
                     }
                   });
@@ -369,7 +364,7 @@ export default {
       }
       this.hot = new Handsontable(container, {
         data: this.tableData,
-        fixedColumnsLeft: 4,
+        fixedColumnsLeft: 3,
         colHeaders: this.formatHeaderData(this.tableHeader), //表头文案
         columns: this.formatHeaderType(this.tableHeader), //数据显示格式
         filters: true,
@@ -477,7 +472,7 @@ export default {
     async removeSys(param) {
       await deleteGeneralSys(param, res => {
         this.$message.success("删除成功")
-        this.$emit('close','')
+        this.$emit('close', '')
         this.getTableData()
       })
     },
@@ -487,7 +482,7 @@ export default {
         Content: [],
         Projection: []
       }, keyList = [];
-       //生成要修改字段列表
+      //生成要修改字段列表
       change.map(item => {
         let key = item[1].split(".")[0]
         if (item[1] && keyList.indexOf(key) == -1) {
@@ -519,7 +514,11 @@ export default {
         //操作
         case 'caozuo':
           // window.open(`http://adm.sagacloud.cn:8058/system?id=${infos.id}&pid=${this.projectId}&secret=${this.secret}`,"_blank")
-          this.$message("开发中...")
+          // this.$message("开发中...")
+          this.$router.push({
+            path: "/ledger/systemDetail",
+            query: { SysID: infos.SysID, Name: infos.SysLocalName || infos.SysName, SysType:infos.Category }
+          })
           return false
         //设备二维码图片
         case 'EquipQRCode':
@@ -540,24 +539,21 @@ export default {
           break;
       }
       if (!this.onlyRead && showTools.InputModeArr.indexOf(inputMode) == '-1') {
-        this.updateInfoPoint = val
-        this.updateInput = tools.dataForKey(this.tableData[row.row], val)
-        this.myDialog.update = true
+        // this.updateInfoPoint = val
+        // this.updateInput = tools.dataForKey(this.tableData[row.row], val)
+        // console.log("this is ",this.tableData[row.row])
+        // let floor = tools.dataForKey(this.tableData[row.row], val);
+        this.$refs.editFloor.showDialog(this.tableData[row.row]);
       }
     },
-    //关闭临时维护弹窗回调
-    handleCloseUpdate() {
-      this.updateInputShow = false
-      this.updateInfoPoint = ''
-      this.updateInput = ''
-    },
     //更新临时维护信息点
-    handleClickUpdate(){
-      tools.setDataForKey(this.tableData[this.row], this.updateInfoPoint, this.updateInput)
-      this.handleUpdataTable([[this.row, this.updateInfoPoint, null, this.updateInput]], "edit")
-      this.updateInputShow = false
-      this.myDialog.update = false
-      this.updateInput = ''
+    handleClickUpdate() {
+      // this.$message("更新成功");
+      // tools.setDataForKey(this.tableData[this.row], this.updateInfoPoint, this.updateInput)
+      // this.handleUpdataTable([[this.row, this.updateInfoPoint, null, this.updateInput]], "edit")
+      // this.updateInputShow = false
+      // this.myDialog.update = false
+      // this.updateInput = ''
     },
     //获取被筛选掉的行号
     trimmedRows() {

+ 1 - 1
src/components/ledger/lib/assets.vue

@@ -1,7 +1,7 @@
 <template>
   <div id="cascaderMap">
     <span class="buildFloor" style="padding-right: 12px;">设备族</span>
-    <el-select v-model="value" placeholder="请选择" :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+    <el-select v-model="value" placeholder="请选择" clearable :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
       <el-option  v-for="item in options" :key="item.code" :label="item.facility" :value="item.code"></el-option>
     </el-select>
     <!-- <el-cascader

+ 1 - 1
src/components/ledger/lib/cascader.vue

@@ -1,7 +1,7 @@
 <template>
   <div id="cascaderMap">
     <span class="buildFloor" style="margin-right: 12px;">设备类别</span>
-    <el-select v-model="value" placeholder="请选择" :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+    <el-select v-model="value" placeholder="请选择" clearable :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
       <el-option  v-for="item in options" :key="item.code" :label="item.facility" :value="item.code"></el-option>
     </el-select>
     <!-- <el-cascader placeholder="请选择" :options="options" v-model="value" :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small"

+ 83 - 0
src/components/ledger/lib/editSysFloor.vue

@@ -0,0 +1,83 @@
+<template>
+  <el-dialog title="所属建筑楼层" :visible.sync="connectDialogVis" width="50%" id="messageDialog">
+    <el-row>
+      <div style="line-height:32px;">添加{{floor.SysLocalName}}所属建筑楼层 : </div>
+      <div style="width:70%">
+        <bfCascader ref="bfCascader" :FloorID="floor.FloorID"></bfCascader>
+      </div>
+    </el-row>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="connectDialogVis=false">取消</el-button>
+      <el-button size="small" type="primary" @click="save">确认</el-button>
+    </span>
+  </el-dialog>
+</template>
+<script>
+import bfCascader from '@/components/ready/buildfloor/buildfloorCascader'
+import { createRelationInFloor } from "@/api/scan/request";
+export default {
+  data() {
+    return {
+      buildName: '',
+      connectDialogVis: false,
+      floor: {}
+    }
+  },
+  components: {
+    bfCascader
+  },
+  methods: {
+    showDialog(floor=null) {
+      if(floor){
+        this.floor = floor
+      }
+      this.connectDialogVis = true
+      this.$nextTick(() => {
+        this.$refs.bfCascader.getCascader()
+        let arr = this.floor.FloorThroughList || [];
+        let value = []
+        if (arr.length) {
+          arr.map(t => {
+            value.push([t.BuildID, t.FloorID])
+          })
+        }
+        this.$refs.bfCascader.value = value
+      })
+    },
+    save() {
+      let arr = this.$refs.bfCascader.value;
+      let param = {
+        FloorId: this.floor.FloorID,
+        FloorOtherIdList: []
+      }
+      arr.map(t => {
+        param.FloorOtherIdList.push(t[1])
+      })
+      // createRelationInFloor(param, res => {
+        this.connectDialogVis = false;
+        this.$message.success('关联成功');
+        this.$emit('handleClickUpdate')
+      // })
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#messageDialog {
+  .el-row{
+    height: 50px;
+    max-height: 200px;
+    overflow-y: auto;
+    overflow-x: hidden;
+  }
+  .el-row > div {
+    float: left;
+  }
+  .el-row > div + div {
+    margin-left: 10px;
+  }
+  /deep/ .el-input__inner {
+    vertical-align: baseline;
+  }
+}
+</style>

+ 6 - 5
src/components/ledger/lib/floorCascader.vue

@@ -1,6 +1,6 @@
 <template>
     <div id="buildFloor">
-        <span class="buildFloor" style="margin-right: 12px;">建筑楼层</span>
+        <span class="buildFloor">建筑楼层</span>
         <el-cascader placeholder="请选择建筑楼层" :options="options" v-model="value" filterable size="small" :style="isWidth ? '' : 'width:160px;'" @change="changeCascader"></el-cascader>
     </div>
 </template>
@@ -149,9 +149,10 @@
     #buildFloor {
         margin-left: 10px;
         float: left;
-        .buildFloor {
-            color: #999999;
-            font-size: 14px;
-        }
+    }
+    .buildFloor {
+        color: #999999;
+        font-size: 14px;
+        margin-right: 12px;
     }
 </style>

+ 65 - 0
src/components/ledger/lib/spaceSelect.vue

@@ -0,0 +1,65 @@
+<template>
+  <div id="spaceSelect">
+    <span class="buildFloor" style="padding-right:12px">业务空间</span>
+    <el-select v-model="value" placeholder="请选择" :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+      <el-option v-for="(item, key) in options" :key="key" :label="item.Name" :value="item.Code"></el-option>
+    </el-select>
+  </div>
+</template>
+
+<script>
+import { queryDictionaryHead } from '@/api/scan/request';
+export default {
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      value:null,
+      spaceVal: null,//值
+      options: [],
+      props: {
+        isWidth:false
+      }
+    }
+  },
+  methods: {
+    //获取下拉框数据
+    getOptionData() {
+      let pa = {
+        Filters: `parentId = 'Space'`
+      }
+      queryDictionaryHead(pa, res => {
+        this.options = res.Content.map(t => {
+          if (t.Name == "元空间") {
+            return undefined;
+          }
+          return t;
+        }).filter(item => item);
+        this.options.unshift({Code:null, CreateTime:null, LastUpdate:null, Name:'全部', ObjectType: null, ParentId: null, Statistics: {}});
+      })
+    },
+    //改变空间
+    changeVal(value) {
+      this.$emit('change', value)
+    }
+  },
+  created() {
+    this.getOptionData();
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#spaceSelect {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 17 - 4
src/components/ledger/lib/uploadImgs.vue

@@ -9,14 +9,14 @@
     <div class="saga-upload-images">
       <div v-if="type != 'video'" class="point-image" v-for="(item,index) in imagesArr">
         <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
-        <img :src="imageGetUrl + '&key=' +item" alt v-load>
+        <img :src="imageGetUrl + '&key=' +item.key" @click="lookImg" alt v-load>
       </div>
       <div v-if="type == 'video'" class="point-image" v-for="(item,index) in imagesArr">
         <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
         <video
           width="100%"
           height="100%;"
-          :src="imageGetUrl + '&key=' +item"
+          :src="imageGetUrl + '&key=' +item.key"
           controls="controls"
         >您的浏览器不支持 video 标签。</video>
       </div>
@@ -35,11 +35,16 @@
         <video style="display:none;" id="video" controls/>
       </div>
     </div>
+    <details-dialog :title="'图片'" :iframeSrc="iframeSrc" :dialog="dialog" :setData="imagesArr"></details-dialog>
   </div>
 </template>
 <script>
 import tools from "@/utils/scan/tools";
+import detailsDialog from "@/components/business_space/lib/detailsDia"
 export default {
+  components: {
+    detailsDialog
+  },
   props: {
     keysArr: {
       type: [Array, String]
@@ -73,7 +78,11 @@ export default {
       baseUrl: "",
       imageGetUrl: "/image-service/common/image_get?systemId=dataPlatform",
       imageUploadUrl: "/image-service/common/image_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true",
-      imagesArr: []
+      imagesArr: [],
+      iframeSrc: "",
+      dialog: {
+        details: false
+      }
     };
   },
   created() {
@@ -94,7 +103,11 @@ export default {
         this.imagesArr = [];
       }
     },
-
+    //查看图片
+    lookImg() {
+      this.dialog.details = true
+      this.iframeSrc = process.env.BASE_URL + ":8890/photo-View.html"
+    },
     //删除图片
     delImage(i, key) {
       if (this.type == "video") {

+ 1 - 1
src/components/ledger/lib/uploadImgsName.vue

@@ -347,7 +347,7 @@ export default {
     position: relative;
     border: 1px solid #ccc;
     overflow: hidden;
-    image {
+    img {
       z-index: 11;
     }
     i {

+ 180 - 0
src/components/ledger/system/dialog/addCenoteDialog.vue

@@ -0,0 +1,180 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="addEqDialog">
+    <el-row class="filters">
+      <el-col :span="7" style="width:268px">
+        <el-input placeholder="输入竖井名称或竖井本地编码进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="7.5">
+        <cenote-type @change="changeCenote"></cenote-type>
+      </el-col>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="350" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.ShaftLocalName||scope.row.ShaftName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="ShaftLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="StructureInfo.ShaftFuncType" :label="`${inSpaceType}类`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="toDetail(scope.$index, scope.row)" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { unSysShaft, queryShaftType, linkSysSh } from "@/api/scan/request";
+import cenoteType from "@/components/ledger/lib/cenoteType";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+    cenoteType
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加系统所在竖井",
+      keycode: '', //输入查询条件
+      cenoteType: '', // 选中的竖井类型
+      shaftType: {}, //全部竖井类型
+      inSpaceType: '竖井',
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      } // 列表样式
+    };
+  },
+  props: {
+    type: String, //选中的tab页
+    params: Object //查看的竖井关系信息
+  },
+  created() {
+    queryShaftType(res => {
+      res.Content.forEach(item => {
+        this.shaftType[item.Code] = item.Name
+      })
+    })
+  },
+  methods: {
+    //修改竖井类型
+    changeCenote(value) {
+      this.cenoteType = value.Id
+      this.getTableData()
+    },
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true
+      this.page.pageNumber = 1
+      this.tableData = []
+      this.getTableData()
+    },
+    getTableData() {
+      let params = {
+        data: {
+          Filters: this.cenoteType ? `ProjectId='${this.projectId}';structureInfo.ShaftFuncType='${this.cenoteType}'` : `ProjectId='${this.projectId}'`,
+          Orders: "createTime desc, ShaftID asc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize,
+        },
+        shaftId: this.params.ShaftID,
+        sysId: this.$route.query.SysID
+      }
+      if (this.keycode != '') {
+        params.data.Filters += `;ShaftName contain '${this.keycode}' or ShaftLocalName contain '${this.keycode}' or ShaftLocalID contain '${this.keycode}'`
+      }
+      unSysShaft(params, res => {
+        this.tableData = res.Content
+        this.tableData.forEach(item => {
+          if (item.StructureInfo && item.StructureInfo.ShaftFuncType) {
+            item.StructureInfo.ShaftFuncType = this.shaftType[item.StructureInfo.ShaftFuncType]
+          }
+        })
+        this.page.total = res.Total
+      })
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    savaRelation() {
+      if (this.selections.length) {
+        let params = {
+          SysId: this.$route.query.SysID,
+          ShaftIdList: this.selections.map(item => {
+            return item.ShaftID
+          })
+        }
+        linkSysSh(params, res => {
+          this.dialogVisible = false
+          this.$message.success('关联成功!')
+          this.$emit('refresh')
+        })
+      } else {
+        this.$message('请选择要关联的设备')
+      }
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 查看详情
+    toDetail() {
+      this.$message('开发中')
+    }
+  },
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin-bottom: 10px;
+    /deep/ .el-input__inner {
+      vertical-align: baseline;
+    }
+  }
+  .table-box {
+    height: 370px;
+    .fr {
+      margin-top: 10px;
+    }
+  }
+}
+</style>

+ 209 - 0
src/components/ledger/system/dialog/addEquipDialog.vue

@@ -0,0 +1,209 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="addEqDialog">
+    <el-row class="filters">
+      <el-col :span="7" style="width:268px">
+        <el-input placeholder="输入设备名称或设备本地编码进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="8.5" style="padding:0 0;">
+        <floor-cascader @change="changeFloor" style="margin-left:5px;"></floor-cascader>
+      </el-col>
+      <el-col :span="8.5" style="padding-right:0;">
+        <myCascader @change="changeDevice" :all="true" :params="childParams"></myCascader>
+      </el-col>
+    </el-row>
+
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="350" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>{{scope.row.EquipLocalName||scope.row.EquipName||''}}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="EquipCategory.EquipName" :label="`${inSpaceType}类`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="toDetail(scope.$index, scope.row)" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { sysLinkEquip, unSysEq } from "@/api/scan/request";
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import myCascader from "@/components/ledger/system/lib/equipType";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+    floorCascader,
+    myCascader
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加系统内设备",
+      keycode: "", //输入查询条件
+      Buildfloor: ["all"], // 选中的建筑楼层
+      Equipcategory: null, // 选中的设备类型
+      inSpaceType: "设备",
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: "#e1e4e5",
+        color: "#2b2b2b",
+        lineHeight: "30px"
+      } // 列表样式,
+    };
+  },
+  computed: {
+    childParams() {
+      let temp = JSON.parse(JSON.stringify(this.params));
+      temp.SysType = null;
+      return temp;
+    }
+  },
+  props: {
+    type: String, //选中的tab页
+    params: Object //查看的竖井关系信息
+  },
+  created() { },
+  methods: {
+    //修改建筑楼层
+    changeFloor(value) {
+      this.Buildfloor = value;
+      this.getTableData();
+    },
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true;
+      this.page.pageNumber = 1;
+      this.tableData = [];
+      this.getTableData();
+    },
+    getTableData() {
+      let params = {
+        data: {
+          Filters: `not EquipID isNull`,
+          Cascade: [{ Name: "equipCategory" }],
+          Orders: "createTime desc, EquipID desc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize
+        },
+        shaftId: this.params.ShaftID,
+        sysId: this.$route.query.SysID
+      };
+      if (this.Buildfloor[0] == "noKnow") {
+        params.data.Filters += `;buildingId isNull`;
+      } else if (this.Buildfloor[0] && this.Buildfloor[0] != "all") {
+        params.data.Filters += `;buildingId='${this.Buildfloor[0]}'`;
+      }
+      if (this.Buildfloor[1] == "noKnow") {
+        params.data.Filters += `;floorId isNull`;
+      } else if (this.Buildfloor[1] && this.Buildfloor[1] != "all") {
+        params.data.Filters += `;floorId='${this.Buildfloor[1]}'`;
+      }
+      if (this.keycode != "") {
+        params.data.Filters += `;EquipName contain '${this.keycode}' or EquipLocalName contain '${this.keycode}' or EquipLocalID contain '${this.keycode}'`;
+      }
+      if (this.Equipcategory) {
+        params.data.Filters += `;category='${this.Equipcategory}'`;
+      }
+      unSysEq(params, res => {
+        res.Content.forEach(item => {
+          item.ShaftListName = "";
+          if (item.ShaftList && item.ShaftList.length) {
+            item.ShaftListName = item.ShaftList.map(shaft => {
+              return shaft.ShaftLocalName
+                ? shaft.ShaftLocalName
+                : shaft.ShaftName;
+            }).join("、");
+          }
+        });
+        this.tableData = res.Content;
+        this.page.total = res.Total;
+      });
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    savaRelation() {
+      if (this.selections.length) {
+        let params = {
+          SysId: this.$route.query.SysID,
+          EquipIdList: this.selections.map(item => {
+            return item.EquipID;
+          })
+        };
+        sysLinkEquip(params, res => {
+          this.dialogVisible = false;
+          this.$message.success("关联成功!");
+          this.$emit("refresh");
+        });
+      } else {
+        this.$message("请选择要关联的设备");
+      }
+    },
+    //修改设备类别
+    changeDevice(value) {
+      this.Equipcategory = value.code;
+      this.getTableData();
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 查看详情
+    toDetail() {
+      this.$message("开发中");
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin-bottom: 10px;
+  }
+  .table-box {
+    height: 370px;
+    .fr {
+      margin-top: 10px;
+    }
+  }
+}
+/deep/ #buildFloor .buildFloor {
+  margin: 0 5px 0 5px;
+}
+</style>

+ 225 - 0
src/components/ledger/system/dialog/addSpaceDialog.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialog" :before-close="handleClose" width="900px" id="addEqDialog">
+    <el-row class="filters">
+      <el-col :span="7" style="width:268px;padding:0px;">
+        <el-input style placeholder="输入业务空间名称、本地编码进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="8.5" style="padding:0 0;margin-left:-2px">
+        <floor-cascader ref="floorcas" @change="changeFloor"></floor-cascader>
+      </el-col>
+      <el-col :span="7.5" style="padding:0 0;">
+        <space-select ref="spacesel" @change="changeSpace"></space-select>
+      </el-col>
+    </el-row>
+    <el-row class="filters" :gutter="20"></el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="350" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column :label="`${inSpaceType}本地名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            {{scope.row.RoomLocalName||scope.row.RoomName||''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="RoomLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop :label="`所属建筑楼层`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            {{ scope.row.BuildingId && floorType[scope.row.BuildingId]? ((floorType[scope.row.BuildingId] || '') + (scope.row.FloorId && floorType[scope.row.FloorId] ? (' - ' + floorType[scope.row.FloorId] || '') : '')) : ''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="ObjectType" :label="`空间类型`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            {{spaceType[scope.row.ObjectType] || ''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="toDetail(scope.$index, scope.row)" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="handleClose">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  unSysZoneSpace,
+  linkSysSp,
+  queryDictionaryHead
+} from "@/api/scan/request";
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import dictionaryCas from "@/components/config_point/dictionaryCascader";
+import spaceSelect from "@/components/ledger/lib/spaceSelect";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+    floorCascader,
+    dictionaryCas,
+    spaceSelect
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    dialog() {
+      return this.dialogVisible;
+    }
+  },
+  data() {
+    return {
+      title: "添加系统所在业务空间",
+      keycode: "", //输入查询条件
+      inSpaceType: "业务空间",
+      Buildfloor: ["all"], // 选中的建筑楼层
+      Spacecategory: null, // 选中的业务空间类型
+      tableData: [],
+      floorData: {}, //楼层
+      spaceData: {}, //业务空间分区
+      loading: false,
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: "#e1e4e5",
+        color: "#2b2b2b",
+        lineHeight: "30px"
+      } // 列表样式
+    };
+  },
+  props: {
+    type: String, //选中的tab页
+    params: Object, //查看的竖井关系信息
+    spaceType: Object,
+    dialogVisible: Boolean,
+    floorType: Object
+  },
+  mounted() { },
+  methods: {
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true;
+    },
+    //修改建筑楼层
+    changeFloor(value) {
+      this.Buildfloor = value;
+      this.getTableData();
+    },
+    //修改空间类型
+    changeSpace(value) {
+      this.Spacecategory = value;
+      this.getTableData();
+    },
+    getTableData() {
+      let params = {
+        data: {
+          Filters: "not RoomID isNull",
+          Orders: "RoomLocalName desc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize
+        },
+        shaftId: this.params.ShaftID,
+        sysId: this.$route.query.SysID
+      };
+      if (this.Buildfloor[0] == "noKnow") {
+        params.data.Filters += `;buildingId isNull`;
+      } else if (this.Buildfloor[0] && this.Buildfloor[0] != "all") {
+        params.data.Filters += `;buildingId='${this.Buildfloor[0]}'`;
+      }
+      if (this.Buildfloor[1] == "noKnow") {
+        params.data.Filters += `;floorId isNull`;
+      } else if (this.Buildfloor[1] && this.Buildfloor[1] != "all") {
+        params.data.Filters += `;floorId='${this.Buildfloor[1]}'`;
+      }
+      if (this.Spacecategory) {
+        params.data.Filters += `;ObjectType='${this.Spacecategory}'`;
+      }
+      if (this.keycode != "") {
+        params.data.Filters += `;RoomName contain '${this.keycode}' or RoomLocalName contain '${this.keycode}'`;
+      }
+
+      unSysZoneSpace(params, res => {
+        this.tableData = res.Content;
+        this.page.total = res.Total;
+      });
+    },
+    handleClose() {
+      this.$emit("update:dialogVisible", false);
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    savaRelation() {
+      if (this.selections.length) {
+        let params = {
+          Content: this.selections.map(item => {
+            return {
+              SpaceID: item.RoomID,
+              SysID: this.$route.query.SysID,
+              ObjectType: item.ObjectType
+            };
+          })
+        };
+        linkSysSp(params, res => {
+          this.$message.success("关联成功!");
+          this.$emit("refresh");
+        });
+      } else {
+        this.$message("请选择要关联的设备");
+      }
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 查看详情
+    toDetail() {
+      this.$message("开发中");
+    }
+  },
+  watch: {
+    dialogVisible: {
+      handler() {
+        if (this.dialogVisible) {
+          this.page.pageNumber = 1;
+          this.tableData = [];
+          this.getTableData();
+        }
+      },
+      immediate: true
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin: 0 0 10px 0;
+  }
+  .table-box {
+    height: 370px;
+    .fr {
+      margin-top: 10px;
+    }
+  }
+}
+</style>

+ 140 - 0
src/components/ledger/system/lib/equipType.vue

@@ -0,0 +1,140 @@
+<template>
+  <div id="cascaderMap">
+    <span class="buildFloor" style="margin-right: 12px;">设备类别</span>
+    <el-select v-model="value" placeholder="请选择" :props="props" filterable :style="isWidth ? '' : 'width:160px;'" size="small" @change="changeVal">
+      <el-option v-for="item in options" :key="item.code" :label="item.facility" :value="item.code"></el-option>
+    </el-select>
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+import { queryPhysicsAllType, queryEquip } from "@/api/scan/request";
+export default {
+  name: "getCode",
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    },
+    all: {
+      type: Boolean,
+      default: false,
+    },
+    //系统
+    params: Object
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      value: "",
+      options: [],
+      props: {
+        value: "code",
+        label: "facility"
+      },
+      falg: true,
+      content: []
+    };
+  },
+  created() {
+    this.getData();
+  },
+  watch: {
+    projectId() {
+      this.value = '';
+      this.getData();
+    }
+  },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      let value = {}
+      this.options.map(item => {
+        if (item.code == val) {
+          value = item
+        }
+      })
+      this.value = val
+      this.$emit("change", value)
+    },
+    //获取当前项目下的设备类型(只拿到编码-需要过滤)
+    getData() {
+      let param2 = {
+        Distinct: true,
+        PageNumber: 1,
+        PageSize: 500,
+        Projection: [
+          "Category"
+        ]
+      }
+      let param1 = 'Equipment'
+      let promise2 = new Promise((resolve, reject) => {
+        queryEquip(param2, res => {
+          resolve(res)
+        })
+      })
+      let promise1 = new Promise((resolve, reject) => {
+        queryPhysicsAllType(param1, res => {
+          let tempArr = res.Content;
+          if (this.params.SysType) {
+            tempArr = res.Content.filter(t => {
+              return t.ParentId == `${this.params.SysType}`
+            })
+          }
+          resolve(tempArr)
+        })
+      })
+      Promise.all([promise1, promise2]).then((res) => {
+        let allData = res[0], data = res[1]
+        this.options = this.formatOptions(allData)
+        if (this.value) {
+          this.changeVal(this.value)
+        }
+        if (!this.all) {
+          this.content = data.Content.map(t => {
+            return t.Category
+          });
+          this.filterForOptions();
+          if (this.value) {
+            this.changeVal(this.value)
+          }
+        }
+      })
+    },
+    //格式化options数据
+    formatOptions(arr) {
+      let data = [];
+      arr.map(t => {
+        let temp = {};
+        temp.code = t.Code;
+        temp.facility = t.Name;
+        data.push(temp)
+      })
+      return data;
+    },
+    //过滤
+    filterForOptions() {
+      this.options = this.options.filter(item => {
+        if (this.content.indexOf(item.code) > -1) {
+          return item
+        }
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 156 - 0
src/components/ledger/system/table/cenoteTable.vue

@@ -0,0 +1,156 @@
+<template>
+  <div id="eqInSp">
+    <el-row>
+      <el-button type="primary" @click="add">添加{{inSpaceType}}</el-button>
+      <el-tooltip class="item" effect="dark" content="可前往“全部关系总览”中,按系统内包含的设备与竖井关系计算" placement="right">
+        <el-button>按系统内设备与竖井关系计算</el-button>
+      </el-tooltip>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.ShaftLocalName||scope.row.ShaftName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="ShaftLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column :label="`${inSpaceType}类型`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.StructureInfo.ShaftFuncType}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="删除关系" placement="left">
+              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            可前往“全部关系总览”中计算连通的其它竖井
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <!-- 添加设备弹窗 -->
+    <addCenoteDialog ref="addCenoteDialog" @refresh="getTableData" :type="type" :params="params"></addCenoteDialog>
+  </div>
+</template>
+
+<script>
+import { queryLinkSys, queryShaftType, syinshUnlink } from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addCenoteDialog from "@/components/ledger/system/dialog/addCenoteDialog"
+export default {
+  components: {
+    addCenoteDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: '竖井',
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [], //列表数据
+      shaftType: {} //竖井类型
+    };
+  },
+  props: {
+    params: Object,
+    type: String
+  },
+  created() {
+    queryShaftType(res => {
+      res.Content.forEach(item => {
+        this.shaftType[item.Code] = item.Name
+      })
+      this.getTableData()
+    })
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `SysID='${this.params.SysID}'`,
+        Cascade: [
+          {
+            Name: 'shaftList',
+          }
+        ]
+      }
+      queryLinkSys(params, res => {
+        this.tableData = res.Content[0].Shaft || []
+        this.tableData.forEach(item => {
+          if (item.StructureInfo && item.StructureInfo.ShaftFuncType) {
+            item.StructureInfo.ShaftFuncType = this.shaftType[item.StructureInfo.ShaftFuncType]
+          }
+        })
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      let sysId = this.$route.query.SysID
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = {
+          ShaftId: row.ShaftID,
+          SysId: sysId
+        }
+        this.deleteShThroughSh(params);
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除设备所在空间关系
+    deleteShThroughSh(params) {
+      syinshUnlink(params, res => {
+        this.$message.success('删除成功')
+        this.getTableData()
+      })
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 添加设备
+    add() {
+      this.$refs.addCenoteDialog.showDialog()
+    }
+  },
+  watch: {
+    type() {
+      // this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#eqInSp {
+  height: 100%;
+  .table-box {
+    margin-top: 10px;
+    height: calc(100% - 50px);
+  }
+}
+</style>

+ 144 - 0
src/components/ledger/system/table/deviceTable.vue

@@ -0,0 +1,144 @@
+<template>
+  <div id="eqInSp">
+    <el-row>
+      <el-button type="primary" @click="add">添加{{inSpaceType}}</el-button>
+      <!-- <el-tooltip class="item" effect="dark" content="可前往“全部关系总览”中计算竖井内设备" placement="right">
+        <el-button>按空间计算</el-button>
+      </el-tooltip> -->
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.EquipLocalName||scope.row.EquipName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="EquipLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column :label="`${inSpaceType}类型`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.EquipCategory.EquipName}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button title="删除关系" size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            可前往“全部关系总览”中计算竖井内设备
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <!-- 添加设备弹窗 -->
+    <addEquipDialog ref="addEqDialog" @refresh="getTableData" :type="type" :params="params"></addEquipDialog>
+  </div>
+</template>
+
+<script>
+import { queryLinkSys, eqInSysUnlink } from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addEquipDialog from "@/components/ledger/system/dialog/addEquipDialog"
+export default {
+  components: {
+    addEquipDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: '设备',
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [] //列表数据
+    };
+  },
+  props: {
+    params: Object,
+    type: String
+  },
+  created() {
+    this.getTableData()
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `SysID='${this.params.SysID}'`,
+        Cascade: [
+          {
+            Name: 'equipmentList',
+            Cascade: [{ Name: 'equipCategory' }]
+          }
+        ]
+      }
+      queryLinkSys(params, res => {
+        this.tableData = res.Content[0].Equipment || []
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      let sysId = this.$route.query.SysID
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = {
+          EquipId: row.EquipID,
+          SysId: sysId
+        }
+        this.deleteEqInSh(params);
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除设备所在竖井关系
+    deleteEqInSh(params) {
+      eqInSysUnlink(params, res => {
+        this.$message.success('删除成功')
+        this.getTableData()
+      })
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 添加设备
+    add() {
+      this.$refs.addEqDialog.showDialog()
+    }
+  },
+  watch: {
+    type() {
+      // this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#eqInSp {
+  height: 100%;
+  .table-box {
+    margin-top: 10px;
+    height: calc(100% - 50px);
+  }
+}
+</style>

+ 156 - 0
src/components/ledger/system/table/spaceTable.vue

@@ -0,0 +1,156 @@
+<template>
+  <div id="eqInSp">
+    <el-row>
+      <el-button type="primary" @click="add">添加{{inSpaceType}}</el-button>
+      <el-tooltip class="item" effect="dark" content="可前往“全部关系总览”中,按系统内包含的设备与空间关系计算" placement="right">
+        <el-button>按系统内设备与业务空间关系计算</el-button>
+      </el-tooltip>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>{{ scope.row.RoomLocalName || scope.row.RoomName||''}}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="RoomLocalID" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column :label="`${inSpaceType}类型`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>{{ spaceType[scope.row.ObjectType]}}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="删除关系" placement="left">
+              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);">
+            <i class="icon-wushuju iconfont"></i>
+            可前往“全部关系总览”中计算竖井内系统
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <!-- 添加空间弹窗 -->
+    <addSpaceDialog :dialogVisible.sync="dialogVisible" ref="addSpaceDialog" @refresh="refresh" :params="params" :spaceType="spaceType"
+      :floorType="floorType"></addSpaceDialog>
+  </div>
+</template>
+
+<script>
+import { queryLinkSys, spaceInSysUnlink } from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addSpaceDialog from "@/components/ledger/system/dialog/addSpaceDialog";
+export default {
+  components: {
+    addSpaceDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: "业务空间",
+      dialogVisible: false,
+      headerStyle: {
+        backgroundColor: "#e1e4e5",
+        color: "#2b2b2b",
+        lineHeight: "30px"
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [] //列表数据
+    };
+  },
+  props: {
+    params: Object,
+    type: String,
+    spaceType: Object,
+    floorType: {}
+  },
+  created() {
+    this.getTableData();
+  },
+  methods: {
+    // 获取列表数据
+    getTableData() {
+      let params = {
+        Filters: `SysID='${this.params.SysID}'`,
+        Cascade: [
+          {
+            Name: "zoneSpaceBaseTableList"
+          }
+        ]
+      };
+      queryLinkSys(params, res => {
+        this.tableData = res.Content[0].ZoneSpaceBaseTable || [];
+      });
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          let params = {
+            data: [
+              {
+                SysId: this.params.SysID,
+                SpaceId: row.RoomID
+              }
+            ],
+            type: row.ObjectType
+          };
+          this.deleteSyInSh(params);
+        })
+        .catch(() => {
+          this.$message("取消删除");
+        });
+    },
+    // 删除系统所在竖井关系
+    deleteSyInSh(params) {
+      spaceInSysUnlink(params, res => {
+        this.$message.success("删除成功");
+        this.getTableData();
+      });
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 添加设备
+    add() {
+      this.dialogVisible = true;
+    },
+    //刷新
+    refresh() {
+      this.dialogVisible = false;
+      this.getTableData()
+    }
+  },
+  watch: {
+    type() {
+      // this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#eqInSp {
+  height: 100%;
+  .table-box {
+    margin-top: 10px;
+    height: calc(100% - 50px);
+  }
+}
+</style>

+ 1 - 1
src/components/point/dynamicdata/applyRulesDialog.vue

@@ -38,7 +38,7 @@
       </el-table-column>
       <el-table-column label="设备实例本地名(本地编码)" class-name="bgf5" align="center">
         <template slot-scope="scope">
-          {{scope.row.ObjectLocalName}}({{scope.row.ObjectID}})
+          {{scope.row.ObjectLocalName}}({{scope.row.ObjectLocalCode}})
         </template>
       </el-table-column>
       <el-table-column label="信息点" prop="InfomationPoint" align="center"></el-table-column>

+ 66 - 0
src/components/point/dynamicdata/autoGroupRelaDialog.vue

@@ -0,0 +1,66 @@
+<template>
+  <el-dialog title="提示" :visible.sync="autoDialog" width="30%" @close="autoRelateClose">
+    <div id="autoRelate">
+      <p>请选择使用哪个信息点对应原始点位的设备标识:</p>
+      <p>
+        <el-radio v-model="autoType" label="objectLocalName">{{TypeName}}实本地名称</el-radio>
+      </p>
+      <p>
+        <el-radio v-model="autoType" label="objectLocalCode">{{TypeName}}本地编码</el-radio>
+      </p>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="autoRelateClose">取消</el-button>
+      <el-button size="small" type="primary" @click="confirm">确认</el-button>
+    </span>
+  </el-dialog>
+</template>
+<script>
+import {
+  dynamicAutoRelate
+} from "@/api/scan/request"
+export default {
+  data() {
+    return {
+      autoDialog: false,
+      autoType: "objectLocalName",
+      TypeName: '',
+      TypeCode: ''
+    }
+  },
+  methods: {
+    showDialog(TypeName, TypeCode) {
+      this.TypeName = TypeName;
+      this.TypeCode = TypeCode;
+      this.autoDialog = true;
+    },
+    autoRelateClose() {
+      this.autoDialog = false;
+    },
+    confirm() {
+      let pa = {
+        MatchKey: this.autoType,
+        TypeName: this.TypeName
+      }
+      this.autoDialog = false;
+      this.$message('正在执行');
+      this.$emit('autoRelateSuc', this.TypeCode);
+      dynamicAutoRelate(pa, res => {
+        this.$message.success('匹配成功');
+      })
+    }
+  },
+}
+</script>
+<style lang="scss" scoped>
+#autoRelate {
+  /deep/ .el-radio__input.is-checked + .el-radio__label {
+    color: #000;
+  }
+  p {
+    font-size: 12px;
+    margin-bottom: 8px;
+    padding-left: 24px;
+  }
+}
+</style>

+ 4 - 4
src/components/point/dynamicdata/delRelationDialog.vue

@@ -91,24 +91,24 @@ export default {
       allHeaderData: {
         equip: [
           { label: '对象实例名称', prop: "ObjectLocalName" },
-          { label: '对象实例编码', prop: "ObjectID" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
           { label: '所在建筑楼层', prop: "BuildLocalName" },
           { label: '所在业务空间', prop: "RoomLocalName" },
         ],
         parts: [
           { label: '对象实例名称', prop: "ObjectLocalName" },
-          { label: '对象实例编码', prop: "ObjectID" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
           { label: '所在建筑楼层', prop: "BuildLocalName" },
           { label: '所在业务空间', prop: "RoomLocalName" },
           { label: '所属设备实例', prop: "CascadeEquipLocalName" },
         ],
         system: [
           { label: '对象实例名称', prop: "ObjectLocalName" },
-          { label: '对象实例编码', prop: "ObjectID" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
         ],
         space: [
           { label: '对象实例名称', prop: "ObjectLocalName" },
-          { label: '对象实例编码', prop: "ObjectID" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
           { label: '所在建筑楼层', prop: "BuildLocalName" },
         ]
       },

+ 21 - 8
src/components/point/dynamicdata/equipRules.vue

@@ -4,7 +4,7 @@
     <!-- 查询条件 -->
     <div class="query-area">
       <el-row>
-        <el-col :span="23">
+        <el-col :span="22">
           <el-form ref="form" :model="form" :inline="true">
             <el-row>
               <div class="query-item special">
@@ -26,9 +26,14 @@
             </el-row>
           </el-form>
         </el-col>
-        <el-col :span="1">
+        <el-col :span="2">
           <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
-            <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending"></el-button>
+            <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending">
+            </el-button>
+          </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
           </el-tooltip>
         </el-col>
       </el-row>
@@ -50,12 +55,15 @@
         </el-table-column>
         <el-table-column prop="Datasource" label="数据源" show-overflow-tooltip min-width="100"></el-table-column>
         <el-table-column prop="SubTypeName" :label="`数字字典${typeName}类型`" show-overflow-tooltip min-width="100"></el-table-column>
-        <el-table-column prop="ObjectLocalName" :label="`对应的${typeName}实例`" show-overflow-tooltip min-width="100" class-name="td-bl"></el-table-column>
+        <el-table-column prop="ObjectLocalName" :label="`对应的${typeName}实例`" show-overflow-tooltip min-width="100" class-name="td-bl">
+        </el-table-column>
         <el-table-column label="实例所在建筑楼层" min-width="100">
           <template slot-scope="scope">
-            <el-tooltip :content="scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''"
+            <el-tooltip
+              :content="scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''"
               placement="top">
-              <div class="tool-tip">{{scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''}}
+              <div class="tool-tip">
+                {{scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''}}
               </div>
             </el-tooltip>
           </template>
@@ -64,8 +72,8 @@
         <el-table-column prop="action" label="操作" min-width="100">
           <template slot-scope="scope">
             <el-tooltip class="item" effect="dark" content="清除对应规则" placement="left">
-              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain :disabled="isPending||scope.row.Related=='False'"
-                icon="el-icon-delete"></el-button>
+              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain
+                :disabled="isPending||scope.row.Related=='False'" icon="el-icon-delete"></el-button>
             </el-tooltip>
           </template>
         </el-table-column>
@@ -123,6 +131,7 @@ export default {
         Datasource: [] //数据源
       }, //查询条件
       loading: false, //列表loading
+      autoLoading: false, //自动对应实例
     };
   },
   components: {
@@ -221,6 +230,10 @@ export default {
     queryTableData() {
       this.page.pageNumber = 1;
       this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela','equip');
     }
   },
   watch: {

+ 4 - 4
src/components/point/dynamicdata/historyDialog.vue

@@ -67,24 +67,24 @@ export default {
       tableHeader: {
         equip: [
           { label: '对象实例名称', prop: 'ObjectLocalName' },
-          { label: '对象实例编码', prop: 'ObjectID' },
+          { label: '对象本地编码', prop: 'ObjectLocalCode' },
           { label: '所在建筑楼层', prop: 'BuildLocalName' },
           { label: '所在业务空间', prop: 'RoomLocalName' },
         ],
         parts: [
           { label: '对象实例名称', prop: 'ObjectLocalName' },
-          { label: '对象实例编码', prop: 'ObjectID' },
+          { label: '对象本地编码', prop: 'ObjectLocalCode' },
           { label: '对象所属设备', prop: 'CascadeEquipLocalName' },
           { label: '所在建筑楼层', prop: 'BuildLocalName' },
           { label: '所在业务空间', prop: 'RoomLocalName' },
         ],
         system: [
           { label: '对象实例名称', prop: 'ObjectLocalName' },
-          { label: '对象实例编码', prop: 'ObjectID' }
+          { label: '对象本地编码', prop: 'ObjectLocalCode' }
         ],
         space:[
           { label: '对象实例名称', prop: "ObjectLocalName" },
-          { label: '对象实例编码', prop: "ObjectID" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
           { label: '所在建筑楼层', prop: "BuildLocalName" },
         ]
       }, //所有类型列表头部

+ 11 - 2
src/components/point/dynamicdata/partsRules.vue

@@ -4,7 +4,7 @@
     <!-- 查询条件 -->
     <div class="query-area">
       <el-row>
-        <el-col :span="23">
+        <el-col :span="22">
           <el-form ref="form" :model="form" :inline="true">
             <el-row>
               <div class="query-item special">
@@ -26,10 +26,14 @@
             </el-row>
           </el-form>
         </el-col>
-        <el-col :span="1">
+        <el-col :span="2">
           <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
             <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending"></el-button>
           </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip>
         </el-col>
       </el-row>
     </div>
@@ -124,6 +128,7 @@ export default {
         Datasource: [] //数据源
       }, //查询条件
       loading: false, //列表loading
+      autoLoading: false, //自动对应实例
     };
   },
   components: {
@@ -222,6 +227,10 @@ export default {
     queryTableData() {
       this.page.pageNumber = 1;
       this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela','parts');
     }
   },
   watch: {

+ 11 - 2
src/components/point/dynamicdata/spaceRules.vue

@@ -4,7 +4,7 @@
     <!-- 查询条件 -->
     <div class="query-area">
       <el-row>
-        <el-col :span="23">
+        <el-col :span="22">
           <el-form ref="form" :model="form" :inline="true">
             <el-row>
               <div class="query-item special">
@@ -26,10 +26,14 @@
             </el-row>
           </el-form>
         </el-col>
-        <el-col :span="1">
+        <el-col :span="2">
           <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
             <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending"></el-button>
           </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip>
         </el-col>
       </el-row>
     </div>
@@ -124,6 +128,7 @@ export default {
         Datasource: [] //数据源
       }, //查询条件
       loading: false, //列表loading
+      autoLoading: false, //自动对应实例
     };
   },
   components: {
@@ -222,6 +227,10 @@ export default {
     queryTableData() {
       this.page.pageNumber = 1;
       this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela','space');
     }
   },
   watch: {

+ 11 - 2
src/components/point/dynamicdata/systemRules.vue

@@ -4,7 +4,7 @@
     <!-- 查询条件 -->
     <div class="query-area">
       <el-row>
-        <el-col :span="23">
+        <el-col :span="22">
           <el-form ref="form" :model="form" :inline="true">
             <el-row>
               <div class="query-item special">
@@ -26,10 +26,14 @@
             </el-row>
           </el-form>
         </el-col>
-        <el-col :span="1">
+        <el-col :span="2">
           <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
             <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending"></el-button>
           </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip>
         </el-col>
       </el-row>
     </div>
@@ -124,6 +128,7 @@ export default {
         Datasource: [] //数据源
       }, //查询条件
       loading: false, //列表loading
+      autoLoading: false, //自动对应实例
     };
   },
   components: {
@@ -222,6 +227,10 @@ export default {
     queryTableData() {
       this.page.pageNumber = 1;
       this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela','system');
     }
   },
   watch: {

+ 120 - 0
src/components/point/report/addTabFunNum.vue

@@ -0,0 +1,120 @@
+<template>
+  <!-- 新增表号-功能号 -->
+  <div id="addTabFunNum">
+    <el-form :model='form' label-width="150px" ref="ruleForm" :rules="rules" style="overflow:auto;">
+      <el-form-item label="表号-功能号" prop="MeterFunc">
+        <el-input v-model="form.MeterFunc" placeholder="请输入表号-功能号"></el-input>
+      </el-form-item>
+      <el-form-item label="设定采集间隔时间" prop="CollectInterval">
+        <el-input v-model="form.CollectInterval" placeholder="设定时间不能小于10s"></el-input>
+      </el-form-item>
+      <el-form-item label="值单位" prop="Unit">
+        <el-cascader :options='options' v-model='form.Unit'></el-cascader>
+      </el-form-item>
+      <el-form-item label="取值公式" prop="DataRuleContent">
+        <el-input type="textarea" placeholder="请输入取值公式" v-model="form.DataRuleContent"></el-input>
+      </el-form-item>
+      <el-form-item label="" style="text-align:right;margin-bottom:0px">
+        <el-button @click="$emit('closeDrawer')">取消</el-button>
+        <el-button type="primary" @click="add()">新增</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { Message } from 'element-ui';
+import {
+  addTabFunNum
+} from '@/api/scan/request'
+import { batchQueryUnit } from '@/fetch/point_http'
+export default {
+  data() {
+    return {
+      form: {
+        MeterFunc: '',//表号-功能号
+        CollectInterval: '',//采集间隔时间
+        DataRuleContent: '',//取值公式
+        Unit: '',//值单位
+      },
+      //下拉框选项
+      options: [
+      ],
+      //验证规则
+      rules: {
+        MeterFunc: [
+          { required: true, message: '请输入表号-功能号', trigger: 'blur' }
+        ],
+        CollectInterval: [
+          { required: true, message: '请输入采集间隔时间', trigger: 'blur' }
+        ],
+        Unit: [
+          { required: true, message: '请选择值单位', trigger: 'change' }
+        ],
+        DataRuleContent: [
+          { required: true, message: '请填写取直公式', trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  methods: {
+    //添加
+    add() {
+      //验证参数
+      this.$refs.ruleForm.validate((valid) => {
+        if (valid) {
+          this.form.Unit = this.form.Unit.toString();
+          addTabFunNum(this.form, res => {
+            //成功提示
+            Message.success('添加成功');
+            //清楚当前表单数据,500ms后关闭
+            let that = this;
+            that.$emit('reloadData');
+            setTimeout(() => {
+              that.$emit('closeDrawer');
+              that.form = {
+                MeterFunc: '',
+                CollectInterval: '',
+                DataRuleContent: '',
+                Unit: '',
+              }
+            }, 500);
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+    //加载下拉框
+    initSelect() {
+      batchQueryUnit({}, res => {
+        let data = res.Content
+        let arr = []
+        data.forEach(item => {
+          let first = {
+            value: item.Type,
+            label: item.Type,
+            children: []
+          }
+          item.Units.forEach(ele => {
+            let second = {}
+            second = {
+              value: ele.Name,
+              label: ele.Name
+            }
+            first.children.push(second)
+          })
+          arr.push(first)
+        })
+        this.options = arr
+      })
+    }
+  },
+  mounted() {
+    this.initSelect();
+  }
+}
+</script>
+
+<style lang="less" scoped>
+</style>

+ 79 - 0
src/components/point/report/dataSource.vue

@@ -0,0 +1,79 @@
+<template>
+  <!-- 子系统点位(数据来源) -->
+  <div id="dataSource" v-loading="loading">
+    <div class="data-item" v-for="form in forms" :key="form.id">
+      <el-form :model="form" label-width="150px">
+        <el-form-item label="数据源名称:">
+          {{form.Name || '--'}}
+        </el-form-item>
+        <el-form-item label="值单位说明:">
+          {{form.ValueDescription || '--'}}
+        </el-form-item>
+        <el-form-item label="原始点位值:">
+          {{form.Data || '--'}}
+        </el-form-item>
+        <el-form-item label="原始点位描述:">
+          {{form.Description || '--'}}
+        </el-form-item>
+        <el-form-item label="位置标签:">
+          {{form.LocationFlag.toString() || '--'}}
+        </el-form-item>
+        <el-form-item label="原始值处理规则详情:">
+          {{form.DataRuleContent  || '--'}}
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  getTabFunNumSourceData
+} from '@/api/scan/request'
+export default {
+  data() {
+    return {
+      forms: [
+      ],
+      loading: true
+    }
+  },
+  methods: {
+    //加载数据
+    loadDataSource() {
+      this.loading = true;
+      let pa = {
+        Filters: "Infos='" + this.tabFunNum + "'"
+      };
+      getTabFunNumSourceData(pa, res => {
+        this.forms = res.Content;
+        this.loading = false;
+      });
+    }
+  },
+  props: {
+    tabFunNum: String
+  },
+  mounted() {
+    this.loadDataSource();
+  },
+  watch: {
+    tabFunNum() {
+      this.loadDataSource();
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#dataSource {
+  height: 100%;
+  overflow: auto;
+}
+.data-item {
+  margin: 15px 10px;
+  box-shadow: 0px 4px 10px 0px rgba(0,0,0,0.2);
+  background-color: white;
+  padding: 10px 10px;
+}
+</style>

+ 189 - 0
src/components/point/report/historyChart.vue

@@ -0,0 +1,189 @@
+<template>
+  <!-- 历史数据 -->
+  <div id="historyChart">
+    <!-- 精度选择 -->
+    <div class="query-area">
+      <span>当下分精度下采集数量:{{ chartData.length }}</span>
+      <el-select v-model="selectValue" style="float:right;margin-right:10px;" @change='loadTable()'>
+        <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+      </el-select>
+    </div>
+    <!-- 图表 -->
+    <div class="chart-area" ref="chart">
+
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import {
+  getHistoryData
+} from '@/api/scan/request'
+import echarts from 'echarts'
+
+export default {
+  data() {
+    return {
+      lineChart: null,//折线表
+      selectValue: '5min',//下拉框默认值
+      options: [//精度
+        { value: '1min', label: '1分钟' },
+        { value: '5min', label: '5分钟' },
+        { value: '15min', label: '15分钟' },
+        { value: '30min', label: '30分钟' },
+        { value: '1hour', label: '1小时' },
+        { value: '1day', label: '1天' },
+      ],
+      //数据表
+      chartData: []
+    }
+  },
+  props: {
+    tabFunNum: String//表号功能号
+  },
+  methods: {
+    //加载表格
+    loadTable() {
+      let query = {
+        secret: this.secret,
+        projectId: this.projectId,
+        userInfo: this.userInfo
+      };
+      //时间处理
+      let nowDate = new Date().getTime();
+      let gteDate = 0;
+      if (this.selectValue == '1min' || this.selectValue == '5min') {
+        gteDate = nowDate - 3600 * 1000;
+      }
+      else if (this.selectValue == '15min' || this.selectValue == '30min') {
+        gteDate = nowDate - 24 * 3600 * 1000;
+      }
+      else {
+        gteDate = nowDate - 30 * 24 * 3600 * 1000;
+      }
+      let pa = {
+        criterias: [
+          {
+            "met_fun": this.tabFunNum,      //表号功能号
+            "period": this.selectValue,
+            "receivetime": {
+              "$gte": this.date2String(gteDate),
+              "$lt": this.date2String(nowDate)
+            }
+          }
+        ]
+      };
+      //获取历史数据
+      getHistoryData(query, pa, res => {
+        this.chartData = res[`${this.tabFunNum}`].Content;
+        //折线图参数
+        let lineChartOption = {
+          tooltip: {
+            trigger: 'axis',
+            position: function (pt) {
+              return [pt[0], '10%'];
+            }
+          },
+          xAxis: {
+            type: 'category',
+            boundaryGap: false,
+            data: this.chartData.map(item => item.data_time)
+          },
+          yAxis: {
+            type: 'value',
+            boundaryGap: [0, '100%']
+          },
+          dataZoom: [{
+            type: 'inside',
+            start: 80,
+            end: 100
+          }, {
+            start: 0,
+            end: 10,
+            handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
+            handleSize: '80%',
+            handleStyle: {
+              color: '#fff',
+              shadowBlur: 3,
+              shadowColor: 'rgb(144, 147, 153)',
+              shadowOffsetX: 2,
+              shadowOffsetY: 2
+            }
+          }],
+          series: [
+            {
+              name: '数值',
+              type: 'line',
+              smooth: true,
+              symbol: 'none',
+              sampling: 'average',
+              itemStyle: {
+                color: 'rgb(103, 194, 58)'
+              },
+              areaStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: 'rgb(225, 243, 216)'
+                }, {
+                  offset: 1,
+                  color: 'rgb(225, 243, 216)'
+                }])
+              },
+              data: this.chartData.map(item => item.data_value)
+            }
+          ]
+        };
+        this.lineChart.setOption(lineChartOption);
+      });
+    },
+    //时间戳转string 例:标准时间 => 20190929120000
+    date2String(d) {
+      let localeString = new Date(d).toLocaleString();
+      let timeString = new Date(d).toTimeString();
+      let localArr = localeString.match(/(\d\d|\/\d+)/g).slice(0, 4);
+      let timeArr = timeString.match(/(\d\d)/g).slice(0, 3);
+      localArr[2] = localArr[2].length == 2 ? `0${localArr[2].substring(1, 2)}` : localArr[2].substring(1, 3);
+      localArr[3] = localArr[3].length == 2 ? `0${localArr[3].substring(1, 2)}` : localArr[3].substring(1, 3);
+      return localArr.concat(timeArr).join('');
+    },
+    init() {
+      this.lineChart = echarts.init(this.$refs.chart);
+      this.loadTable();
+    },
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId', 'secret', 'userInfo'])
+  },
+  mounted() {
+    //实例化
+    this.init();
+    let that = this;
+    //图表大小随窗口变化
+    window.onresize = () => {
+      that.lineChart.resize();
+    }
+  },
+  watch: {
+    //切换时更新数据
+    tabFunNum() {
+      this.loadTable();
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#historyChart {
+  height: 100%;
+  width: 100%;
+  padding: 10px 5px;
+}
+.query-area {
+  height: 40px;
+  line-height: 40px;
+}
+.chart-area {
+  height: 450px;
+}
+</style>

+ 288 - 0
src/components/point/report/integrateStatistics.vue

@@ -0,0 +1,288 @@
+<template>
+  <div id="integrateStatistics">
+    <!-- 环形表 -->
+    <div class="statistics-chart">
+      <div class="chart-title">表号功能号总数量:{{ pointData.tabFuncNumSum }} <span style="float:right">目前可能断数的数量:{{ pointData.disConn }}</span></div>
+      <hr style="width:90%" />
+      <div ref="loopchart" class="chart" id="loopchart"></div>
+    </div>
+    <!-- 图形图 -->
+    <div class="statistics-chart" style="border-top:5px solid #eee;min-height: calc(65% - 3px);">
+      <div class="chart-title">共包含原始点位:{{ originalPoint }} 个</div>
+      <div style="padding:15px 10%;line-height:2;">
+        1点位对多表号功能号:{{ pointData.oneToM }}
+        <br />
+        多点位对1表号功能号:{{ pointData.mToOne }}
+        <!-- 查看表号功能号一对多多对一总览 -->
+        <el-button @click="showOverview" type="info" icon="el-icon-arrow-right" circle
+          style="margin:-25px 0 0 50px;background:rgb(121, 187, 255);color:rgb(225, 228, 229);border:none;"></el-button>
+      </div>
+      <hr style="width:90%;margin-top: 1px;" />
+      <div ref="barchart" class="chart" id="barchart" :style="{height:barChartData.length * 120 + 'px'}"></div>
+    </div>
+    <!-- 点位/表号共更好对应总览 -->
+    <pointTabOverview ref="overviewDialog"></pointTabOverview>
+  </div>
+</template>
+
+<script>
+//echarts
+import echarts from "echarts";
+import "echarts/lib/chart/bar";
+import "echarts/lib/component/tooltip";
+import "echarts/lib/component/title";
+
+import {
+  getIntegrateStatisticsToLoop,
+  getIntegrateStatisticsToBar
+} from "@/api/scan/request";
+import pointTabOverview from "./pointTabOverview";
+
+export default {
+  data() {
+    return {
+      //环形图
+      loopChart: null,
+      //条形图
+      barChart: null,
+      //环形图数据
+      loopChartData: [],
+      //条形图数据
+      barChartData: [],
+      //点位-标号功能号数据
+      pointData: {
+        tabFuncNumSum: 0,//总数
+        oneToM: 0,//一对多
+        mToOne: 0,//多对一
+        disConn: 0//可能断数数量
+      },
+      //原始点数量
+      originalPoint: null
+    };
+  },
+  methods: {
+    //加载图表数据
+    loadChart() {
+      //获取环形图数据
+      getIntegrateStatisticsToLoop({}, res => {
+        //设置点位-表号功能号数据
+        this.pointData = {
+          tabFuncNumSum: res.Content[0].Sum,
+          oneToM: res.Content[0].OtoM,
+          mToOne: res.Content[0].MtoO,
+          disConn: res.Content[0].Disconn
+        };
+        //设置环形表数据
+        this.loopChartData = [
+          { value: res.Content[0].RelatedCount, name: "已对实例数量" },
+          { value: res.Content[0].Sum - res.Content[0].RelatedCount, name: "未对应实例数量" }
+        ];
+
+        let that = this;
+        //环形图参数
+        let loopOption = {
+          tooltip: {
+            trigger: "item",
+            formatter: "{a} <br/>{b}: {c} ({d}%)"
+          },
+          color: ['rgb(121, 187, 255)', 'rgb(225, 228, 229)'],
+          graphic: {
+            elements: [
+              {
+                type: "text",
+                left: "center",
+                top: "center",
+                style: {
+                  text: (() => {
+                    let s = 0;
+                    that.loopChartData.map(item => {
+                      s += item["value"];
+                    });
+                    return s;
+                  })(),
+                  textAlign: "center",
+                  fontSize: 32,
+                  fontWeight: 300
+                }
+              },
+              {
+                type: "text",
+                left: "center",
+                top: "center",
+                style: {
+                  text: (() => {
+                    let s = 0;
+                    that.loopChartData.map(item => {
+                      s += item["value"];
+                    });
+                    return "\n\n\n总数";
+                  })(),
+                  textAlign: "center",
+                  fontSize: 16,
+                  fontWeight: 300
+                }
+              }
+            ]
+          },
+          series: [
+            {
+              name: "实例总数",
+              type: "pie",
+              radius: ["50%", "70%"],
+              avoidLabelOverlap: false,
+              legendHoverLink: false,
+              selectedOffset: 0,
+              label:{
+                  color:'rgb(121, 187, 255)',
+              },
+              emphasis: {
+                itemStyle: {
+                  // 高亮时点的颜色。
+                  color: undefined
+                }
+              },
+              data: this.loopChartData
+            }
+          ]
+        };
+
+        setTimeout(() => {
+          //实例化
+          that.loopChart = echarts.init(document.getElementById("loopchart"));
+          //设置参数并加载
+          that.loopChart.setOption(loopOption);
+          //消除高亮
+          that.loopChart.on('mouseover', function (param) {
+            if (param.dataIndex == 1) {
+              loopOption.series[0].emphasis.itemStyle.color = 'rgb(225, 228, 229)';
+              that.loopChart.setOption(loopOption);
+            }
+            else {
+              loopOption.series[0].emphasis.itemStyle.color = 'rgb(121, 187, 255)';
+              that.loopChart.setOption(loopOption);
+            }
+          });
+        }, 100);
+
+      })
+
+      //获取条形图数据
+      getIntegrateStatisticsToBar({}, res => {
+        this.barChartData = res.Content;
+        this.originalPoint = (() => {
+          let sum = 0;
+          this.barChartData.map(item => {
+            sum += item["Sum"];
+          });
+          return sum;
+        })();
+
+        //条形图参数
+        let barOption = {
+          tooltip: {
+            trigger: "axis",
+            axisPointer: {
+              // 坐标轴指示器,坐标轴触发有效
+              type: "shadow" // 默认为直线,可选为:'line' | 'shadow'
+            }
+          },
+          color: ['rgb(121, 187, 255)', 'rgb(225, 228, 229)'],
+          legend: {
+            data: ["已接入", "未接入"]
+          },
+          grid: {
+            left: "3%",
+            right: "4%",
+            bottom: "3%",
+            containLabel: true
+          },
+          xAxis: [
+            {
+              type: "value",
+              position: "top"
+            }
+          ],
+          yAxis: [
+            {
+              type: "category",
+              axisTick: { show: false },
+              data: this.barChartData.map(item => item.Name)
+            }
+          ],
+          series: [
+            {
+              name: "已接入",
+              type: "bar",
+              label: {
+                normal: {
+                  show: true,
+                  position: "inside"
+                }
+              },
+              data: this.barChartData.map(item => item.Relatedall)
+            },
+            {
+              name: "未接入",
+              type: "bar",
+              stack: "总量",
+              label: {
+                normal: {
+                  show: true
+                }
+              },
+              data: this.barChartData.map(item => item.Notrelatedall)
+            }
+          ]
+        };
+
+        /* 条形图高度随数量变化,延时初始化 */
+        let that = this;
+        setTimeout(() => {
+          that.barChart = echarts.init(document.getElementById("barchart"));
+          that.barChart.setOption(barOption);
+        }, 100);
+      });
+    },
+    //点位/表号
+    showOverview() {
+      this.$refs.overviewDialog.loadOverviewData();
+    },
+    init() {
+      this.loadChart();
+    }
+  },
+  mounted() {
+    this.init();
+    //图表随窗口变化
+    let that = this;
+    window.onresize = () => {
+      if (that.loopChart != null)
+        that.loopChart.resize();
+      if (that.barChart != null)
+        that.barChart.resize();
+    };
+  },
+  components: {
+    pointTabOverview
+  }
+};
+</script>
+
+<style lang="less" scoped>
+#integrateStatistics {
+  border-top: 5px solid #eee;
+}
+.statistics-chart {
+  min-height: calc(35% - 3px);
+}
+.chart-title {
+  padding: 5px 5%;
+  font-size: 16px;
+  font-weight: 500;
+}
+.chart {
+  min-height: 200px;
+  height: auto;
+  width: 100%;
+}
+</style>

+ 198 - 0
src/components/point/report/objectInstance.vue

@@ -0,0 +1,198 @@
+<template>
+  <!-- 对象实例 -->
+  <div id="objectInstance" v-loading="loading">
+    <div class="obj-item" v-for="form in forms" :key="form.id" :style="{height:drawCanvas? '600px' : '350px'}">
+      <el-form :model="form" label-width="150px">
+        <el-form-item label="对象类型:">
+          {{form.TypeName || '--'}}
+        </el-form-item>
+        <el-form-item label="对象实例本地名称:">
+          {{form.ObjectLocalName || '--'}}
+        </el-form-item>
+        <el-form-item label="对象实例本地编码:">
+          {{form.ObjectLocalCode || '--'}}
+        </el-form-item>
+        <el-form-item label="对象实例ID:">
+          {{form.ObjectID || '--'}}
+        </el-form-item>
+        <el-form-item label="信息点名称:">
+          {{form.InfomationPointName || '--'}}
+        </el-form-item>
+        <el-form-item label="对应值:">
+          {{ reValue || '--'}}
+        </el-form-item>
+        <el-form-item label="对象实例位置图:">
+          <span v-show="!drawCanvas">--</span>
+          <div v-show="drawCanvas" style="border:1px solid rgba(0, 0, 0, 0.2);height:300px;">
+            <canvas v-show="drawCanvas" height="300" :width="canvasWidth" class="instanceMap" :id="form.instanceId" :k="refreshCanvas"></canvas>
+          </div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { SGraphyView } from "@saga-web/graphy/lib";
+import { LocationPointScene, DivideFloorScene } from "@saga-web/cad-engine"
+import { SColor } from "@saga-web/draw/lib";
+
+import {
+  getTabFunNumObjInstance, getEquipByEqID, getFloorMsgByFloorID, queryZone
+} from '@/api/scan/request'
+
+export default {
+  data() {
+    return {
+      forms: [],//实例数据
+      views: [],//canvas view
+      scenes: [],//canvas scene
+      loading: true,
+      refreshCanvas: '',//重载canvas组件
+      drawCanvas: false,//是否画canvas,
+      canvasWidth:450
+    }
+  },
+  methods: {
+    //加载对象实例
+    loadObjectInstance() {
+      this.loading = true;
+      let pa = {
+        Filters: `MeterFuncid='${this.tabFunNum}';Related='true'`//
+      };
+      let that = this;
+      //获取所有实例信息
+      getTabFunNumObjInstance(pa, res => {
+        that.loading = false;
+        that.forms = res.Content;
+        res.Content.map((item, key) => {
+          //存在实例ID
+          if (item.ObjectID) {
+            that.forms[key].instanceId = item.ObjectID;
+            //设备或者组件
+            if (item.TypeCode == 'Eq' || item.TypeCode == 'Ec') {
+              let pa = {
+                Filters: `EquipID='${item.TypeCode + this.projectId.substring(2) + item.ObjectID}'`
+              }
+              //获取设备信息
+              getEquipByEqID(pa, equipMsg => {
+                if (equipMsg.Content[0] && equipMsg.Content[0].LocationJson && equipMsg.Content[0].FloorId) {
+                  let canvasOption = {
+                    /** 标记的id  */
+                    Id: equipMsg.Content[0].EquipID,
+                    /** 标记的名称  */
+                    Name: equipMsg.Content[0].EquipName,
+                    /** X坐标 */
+                    X: equipMsg.Content[0].LocationJson.X,
+                    /** Y坐标 */
+                    Y: -equipMsg.Content[0].LocationJson.Y
+                  }
+                  this.loadDataToInstanceByFloorID(equipMsg.Content[0].FloorId, key, item.TypeCode, canvasOption);
+                }
+              })
+            }
+            //空间
+            else if (item.TypeCode == 'Sp') {
+              let pa = {
+                data: {
+                  Filters: `RoomID='${item.TypeCode + this.projectId.substring(2) + item.ObjectID}'`
+                },
+                zone: item.SubTypeCode
+              }
+              //获取空间信息
+              queryZone(pa, zoneMsg => {
+                if (zoneMsg.Content[0] && zoneMsg.Content[0].Outline) {
+                  let canvasOption = {
+                    RoomLocalName: zoneMsg.Content[0].RoomLocalName,
+                    OutLine: zoneMsg.Content[0].Outline,
+                    RoomID: zoneMsg.Content[0].RoomID,
+                    Color: new SColor('#F9C3C3')
+                  }
+                  this.loadDataToInstanceByFloorID(zoneMsg.Content[0].FloorId, key, item.TypeCode, canvasOption);
+                }
+              });
+            }
+          }
+        });
+      })
+    },
+    //通过floorid获取信息,后通过floormap获取数据后绘制canvas
+    loadDataToInstanceByFloorID(floorId, key, typecode, options) {
+      let param = {
+        Filters: `FloorId='${floorId}'`
+      }
+      let that = this;
+      //获取楼层信息
+      getFloorMsgByFloorID(param, floorMsg => {
+        //刷新canvas
+        that.refreshCanvas = new Date().getTime();
+        if (!that.views[key]) {
+          that.views[key] = new SGraphyView(`${that.forms[key].instanceId}`)
+        }
+        that.views[key].scene = null;
+        that.scenes[key] = null;
+        //类型
+        if (typecode == 'Eq' || typecode == 'Ec') {
+          that.scenes[key] = new LocationPointScene();
+        }
+        else if (typecode == 'Sp') {
+          that.scenes[key] = new DivideFloorScene();
+        }
+        if (floorMsg.Content[0] && floorMsg.Content[0].StructureInfo && floorMsg.Content[0].StructureInfo.FloorMap) {
+          //获取数据,并加载canvas
+          that.scenes[key].loadUrl(`/image-service/common/file_get?systemId=revit&key=${floorMsg.Content[0].StructureInfo.FloorMap}`).then(() => {
+            that.drawCanvas = true;
+            that.views[key].scene = that.scenes[key];
+            that.scenes[key].isSpaceSelectable = false;
+            if (typecode == 'Eq' || typecode == 'Ec') {
+              that.scenes[key].addMarker(options);
+            }
+            else if (typecode == 'Sp') {
+              that.scenes[key].addZone(options);
+            }
+            that.views[key].fitSceneToView();
+          })
+        }
+        else{
+          that.drawCanvas = false;
+        }
+      });
+    }
+  },
+  mounted() {
+    this.canvasWidth = document.getElementById("objectInstance").offsetWidth - 200
+    this.loadObjectInstance();
+  },
+  props: {
+    tabFunNum: String,//表号功能号,
+    reValue: String//对应值
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId'])
+  },
+  watch: {
+    //切换时更新数据
+    tabFunNum() {
+      this.loadObjectInstance();
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#objectInstance {
+  height: 100%;
+  overflow: auto;
+}
+.instanceMap {
+  min-height: 100px;
+}
+.obj-item {
+  margin: 15px 10px;
+  box-shadow: 0px 4px 10px 0px rgba(0,0,0,0.2);
+  background-color: white;
+  padding: 10px 10px;
+  height: 600px;
+}
+</style>

+ 82 - 0
src/components/point/report/pointTabOverview.vue

@@ -0,0 +1,82 @@
+<template>
+  <!-- 点位/表号共更好对应总览 -->
+  <div id="pointTabOverview">
+    <!-- 对话框 -->
+    <el-dialog title="点位/表号共更好对应总览" :visible.sync="dialogVisiable">
+      <el-tabs v-model="activeName" style="height:600px;overflow:auto;">
+        <!-- 一对多数据 -->
+        <el-tab-pane label="一对多" name="otm">
+          <el-table :data="oTMData" style="width: 100%">
+            <el-table-column prop="Description" label="点位名称" show-overflow-tooltip min-width="100"></el-table-column>
+            <el-table-column prop="Name" label="数据源" show-overflow-tooltip min-width="100"></el-table-column>
+            <el-table-column prop="MeterList" label="表号功能号" show-overflow-tooltip min-width="100">
+              <template slot-scope="scope">
+                <div v-for="(item, index) in scope.row.MeterList" :key="index">{{ item }}</div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-tab-pane>
+        <!-- 多对一数据 -->
+        <el-tab-pane label="多对一" name="mto">
+          <el-table :data="mTOData" style="width: 100%">
+            <el-table-column prop="Data" label="点位名称" show-overflow-tooltip min-width="100">
+              <template slot-scope="scope">
+                <div v-for="(item, index) in scope.row.Data" :key="index">{{ item.Description }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column prop="Data" label="数据源" show-overflow-tooltip min-width="100">
+              <template slot-scope="scope">
+                <div v-for="(item, index) in scope.row.Data" :key="index">{{ item.Name }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column prop="MeterFunc" label="表号功能号" show-overflow-tooltip min-width="100"></el-table-column>
+          </el-table>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { tableFuncRelatedOverview } from '@/api/scan/request'
+export default {
+  data() {
+    return {
+      activeName: "otm", //默认展示一对多
+      dialogVisiable: false, //显示对话
+      mTOData: [], //多对一数据
+      oTMData: [] //一对多数据
+    };
+  },
+  methods: {
+    //加载数据
+    loadOverviewData() {
+      tableFuncRelatedOverview({}, res => {
+        this.dialogVisiable = true;
+        //去掉非多对一数据
+        let mD = res.Content[0].MtoO;
+        this.mTOData = [];
+        for (let k in mD) {
+          if (mD[k].length > 1) {
+            this.mTOData.push({
+              "MeterFunc": k,
+              "Data": mD[k]
+            })
+          }
+        };
+        //去掉非一对多数据
+        this.oTMData = [];
+        let oD = res.Content[0].OtoM;
+        for (let k in oD) {
+          if (oD[k].MeterList.length > 1) {
+            this.oTMData.push(oD[k]);
+          }
+        }
+      });
+    }
+  }
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 228 - 0
src/components/point/report/tabFunNumOverview.vue

@@ -0,0 +1,228 @@
+<template>
+  <div id="tabFunNumOverview">
+    <!-- 查询 新增 -->
+    <div class="query-area" style="padding:10px;">
+      <el-input :placeholder="`请输入表号功能号`" v-model="tabFunNum" @keyup.enter.native="getOverViewList()" style="width:240px;">
+        <i slot="suffix" class="el-input__icon el-icon-search" @click="getOverViewList()"></i>
+      </el-input>
+      <p style="overflow: hidden;float:right;">
+        <el-button style="height:32px" @click='handleDrawer({},3)'>新增自定义</el-button>
+      </p>
+    </div>
+    <!-- 数据表格 -->
+    <div class="table-area">
+      <el-table :data="tableData" style="width: 100%" height="calc(100% - 32px)" v-loading="loading" :header-cell-style="headerStyle" >
+        <el-table-column prop='' label='' show-overflow-tooltip width="35" header-align='center'>
+          <template slot-scope="scope">
+            <el-tooltip v-if="scope.row.DataQuality!=0" content="已断数,请检查" effect="dark" placement="top">
+              <i class="el-icon-warning-outline" style="float:left;margin: 0 5px;color: red;font-size:18px;"></i>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column prop='MeterFunc' label='表号-功能号' show-overflow-tooltip min-width="100" header-align='left'></el-table-column>
+        <el-table-column prop='Data.Data' label='查看分精度' show-overflow-tooltip min-width="90" header-align='center' align='center'>
+          <template slot-scope="scope">
+            <el-button style="padding:7px 15px;" @click="handleDrawer(scope.row, 0)"><i class="el-icon-s-data" style="font-size:15px;"></i></el-button>
+          </template>
+        </el-table-column>
+        <el-table-column prop='Data.Time' label='对应值 - 获取时间' show-overflow-tooltip min-width="270" header-align='center' align='center' style="position:relative;">
+          <template slot-scope="scope">
+            <div style="width:175px;display:inline-block;">
+              <span style="line-height:29px;">{{ scope.row.Data? (scope.row.Data.Data  || '--'): '--' }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+              <span style="line-height:29px;">{{ scope.row.Data? scope.row.Data.Time : '' }}</span>
+            </div>
+            <span style="width:55.33px;display:inline-block;padding-left:10px;">
+            <el-button class="dialog-btn" @click="refreshThisRow(scope.row)"><i class="el-icon-refresh"></i></el-button>
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop='RelatedPoint' label='涉及子系统点位(数据来源)' show-overflow-tooltip min-width="150" align='center'>
+          <template slot-scope="scope">
+            <span style="display:inline-block;width:16px;line-height:29px;">{{ scope.row.RelatedPoint }}</span>
+            <span style="width:55.33px;display:inline-block;padding-left:10px;">
+              <el-button class="dialog-btn" v-if="scope.row.RelatedPoint" @click="handleDrawer(scope.row, 1)"><i class="el-icon-coin"></i></el-button>
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop='RelatedInstance' label='涉及的对象实例(应用到)' show-overflow-tooltip min-width="150" align='center'>
+          <template slot-scope="scope">
+            <span style="display:inline-block;width:16px;line-height:29px;">{{ scope.row.RelatedInstance }}</span>
+            <span style="width:55.33px;display:inline-block;padding-left:10px;">
+              <el-button class="dialog-btn" v-if="scope.row.RelatedInstance" @click="handleDrawer(scope.row, 2)"><i class="el-icon-coin"></i></el-button>
+            </span>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="pageSizes"
+        :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="allTableData.length"
+        style="float:right;margin-top:10px;padding:2px 5px;">
+      </el-pagination>
+    </div>
+    <!-- 对话框和抽屉统一放在drawers中 -->
+    <!-- 对话框 -->
+    <el-dialog :title="'< ' + drawers[0].objId + ' > 的历史数据'" :visible.sync="drawers[0].drawer">
+      <historyChart :tabFunNum='drawers[0].objId'></historyChart>
+    </el-dialog>
+    <!-- 抽屉 -->
+    <el-drawer :title="'< ' + drawers[1].objId + ' > 的子系统点位'" :visible.sync="drawers[1].drawer" :direction="drawers[1].direction" size="35%">
+      <dataSource :tabFunNum='drawers[1].objId'></dataSource>
+    </el-drawer>
+    <el-drawer :title="'< ' + drawers[2].objId + ' > 的对象实例'" :visible.sync="drawers[2].drawer" :direction="drawers[2].direction" size="35%">
+      <objectInstance :tabFunNum='drawers[2].objId' :reValue='drawers[2].value'></objectInstance>
+    </el-drawer>
+    <el-dialog title="新增表号功能号" :visible.sync="drawers[3].drawer">
+      <addTabFunNum @closeDrawer="closeDrawer()" @reloadData="reloadData()"></addTabFunNum>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { Message } from 'element-ui';
+import {
+  getTabFunNumOverview
+} from '@/api/scan/request'
+import historyChart from './historyChart'
+import dataSource from './dataSource'
+import objectInstance from './objectInstance'
+import addTabFunNum from './addTabFunNum'
+export default {
+  data() {
+    return {
+      //表格头样式
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      allTableData: [],//所有表格数据
+      pageSizes: [10, 20, 50, 100],
+      pageSize: 50,
+      currentPage: 1,
+      loading: false,//加载
+      tabFunNum: null,//表号功能号
+      //抽屉
+      drawers: [
+        { drawer: false, direction: 'rtl', objId: '' },
+        { drawer: false, direction: 'rtl', objId: '' },
+        { drawer: false, direction: 'rtl', objId: '', value: '' },
+        { drawer: false, direction: 'rtl', objId: '' }
+      ]
+    }
+  },
+  methods: {
+    //抽屉处理
+    handleDrawer(row, index) {
+      if (index == 2 || index == 1) {
+        //实例数量大于0才能打开
+        if ((row.RelatedInstance > 0 && index == 2) || (row.RelatedPoint > 0 && index == 1)) {
+          this.drawers[index].value = row.Data ? row.Data.Data : '';
+          this.drawers[index].objId = row.MeterFunc;
+          this.drawers[index].drawer = true;
+        }
+      }
+      else {
+        if (index != 3)
+          this.drawers[index].objId = row.MeterFunc;
+        this.drawers[index].drawer = true;
+      }
+    },
+    //获取统计数据
+    getOverViewList() {
+      this.loading = true;
+      getTabFunNumOverview({ MeterFunc: this.tabFunNum }, res => {
+        this.allTableData = res.Content;
+        this.loading = false;
+      });
+    },
+    //刷新当前行数据
+    refreshThisRow(row) {
+      let index = this.tableData.indexOf(row);
+      let pa = {
+        MeterFunc: row.MeterFunc
+      }
+      getTabFunNumOverview(pa, res => {
+        if (res.Content[0].Data) {
+          this.tableData[index].Data.Data = res.Content[0].Data.Data;
+          this.tableData[index].Data.Time = res.Content[0].Data.Time;
+        }
+        this.tableData[index].DataQuality = res.Content[0].DataQuality;
+        this.tableData[index].RelatedInstance = res.Content[0].RelatedInstance;
+        this.tableData[index].RelatedPoint = res.Content[0].RelatedPoint;
+        Message.success('已刷新');
+      });
+    },
+    //分页更换size
+    handleSizeChange(val) {
+      this.pageSize = val;
+    },
+    //分页更换页
+    handleCurrentChange(val) {
+      this.currentPage = val;
+    },
+    //子组件关闭抽屉
+    closeDrawer() {
+      this.drawers[3].drawer = false;
+    },
+    //新建自定义后重载页面
+    reloadData() {
+      this.$emit('reloadData');
+    },
+    init() {
+      this.getOverViewList();
+    }
+  },
+  mounted() {
+    this.init();
+  },
+  computed: {
+    //根据分页,获取要展示的tableData
+    tableData: function () {
+      return this.allTableData.slice(
+        (this.currentPage - 1) * this.pageSize,
+        (this.currentPage * this.pageSize < this.allTableData.length) ? this.currentPage * this.pageSize : this.allTableData.length);
+
+    }
+  },
+  components: {
+    historyChart,
+    dataSource,
+    objectInstance,
+    addTabFunNum
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#tabFunNumOverview {
+  border-top: 5px solid #eee;
+  height: calc(100% - 5px);
+  width: 100%;
+  overflow: hidden;
+}
+.table-area {
+  height: calc(100% - 72px);
+  padding: 0px 10px 10px 10px;
+}
+.table-area i {
+  text-align: right;
+  font-size: 12px;
+  cursor: pointer;
+  float: right;
+}
+.dialog-btn{
+  display:none;
+  height:29px;
+}
+/deep/ .el-drawer__body {
+  height: 90%;
+}
+/deep/ .el-table__body-wrapper tr:hover{
+  .dialog-btn{
+    display:inline;
+  }
+}
+/deep/ .el-dialog__body {
+  padding-bottom:20px;
+}
+</style>

+ 2 - 1
src/components/ready/buildfloor/buildfloorCascader.vue

@@ -26,8 +26,9 @@ export default {
     getCascader() {
       let param = {
         Cascade: [
-          { Name: "floor" }
+          { Name: "floor", Orders: "FloorSequenceID desc" }
         ],
+        Orders: "BuildLocalName asc",
         PageNumber: 1,
         PageSize: 50
       }

+ 107 - 0
src/components/ready/buildfloor/modelFile.vue

@@ -0,0 +1,107 @@
+<template>
+    <div id="modelFile">
+        <span class="modelFile" style="margin-right: 12px;">模型文件</span>
+        <el-cascader :options="options" :show-all-levels="false" @change="handleChange" style="width:160px;"
+        @active-item-change='handleItemChange' clearable placeholder="请选择模型文件" v-model="casVal"></el-cascader>
+    </div>
+</template>
+<script>
+import tools from "@/utils/scan/tools"
+import request from "@/api/model/file.js";
+import { mapGetters, mapActions } from "vuex"
+
+export default {
+  computed: {
+    ...mapGetters("layout", [ "projectId", "secret", "userId" ])
+  },
+  data() {
+    return {
+      casVal: [],
+      options: [],
+      modelIdToFloorId: {}
+    };
+  },
+  created() {
+    this.init()
+  },
+  watch: {
+    projectId() {
+      this.casVal =[]
+      this.options = []
+      this.init()
+    }
+  },
+  methods: {
+    //设置默认选项
+    setValue(val) {
+        if (val && val.length) {
+          this.casVal = val
+        }
+    },
+    //获取数据
+    init() {
+      this.getDirectory()
+    },
+    // 获取文件夹
+    getDirectory() {
+      request.queryModel("", res => {
+        this.options = res.Content.map(t => {
+          return {
+            value: t.Id,
+            label: t.Name,
+            children: []
+          }
+        })
+      });
+    },
+    // 通过id查询文件夹下模型文件
+    handleItemChange(val) {
+      let data = {
+        FolderId: val[0],
+        ProjectId: this.projectId
+      };
+      request.queryFloorList(data, res => {
+        let tempArr = res.Content.map(t => {
+          this.modelIdToFloorId[t.CurrentModelId] = t.Id;
+          return {
+            value: t.CurrentModelId,
+            label: t.FloorName
+          }
+        })
+        this.pushChild(this.options, tempArr, val[0])
+      })
+    },
+    // 将模型文件list填到相应的文件夹下
+    pushChild(options, arr, Code) {
+      options.map(option => {
+        if (option.value == Code) {
+          option.children = arr;
+        } else {
+          if (option.children) {
+            this.pushChild(option.children, arr, Code)
+          }
+        }
+      })    
+    },
+    //改变item
+    handleChange(value) {
+      this.$emit("change", value)
+    }
+  }
+};
+</script>
+<style lang="less">
+    .el-cascader .el-input .el-input__inner {
+        vertical-align: bottom;
+    }
+</style>
+<style lang="less" scoped>
+    #modelFile {
+        margin-left: 10px;
+        float: left;
+        .modelFile {
+            color: #999999;
+            font-size: 14px;
+        }
+    }
+</style>

+ 83 - 0
src/components/ready/buildfloor/modelFolder.vue

@@ -0,0 +1,83 @@
+<template>
+  <div id="modelFile">
+    <span class="modelFile" style="margin-right: 12px;">模型文件夹</span>
+    <el-select v-model="casVal" filterable clearable placeholder="请选择模型文件夹" style="width:160px;" @change="handleChange">
+      <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+    </el-select>
+  </div>
+</template>
+<script>
+import tools from "@/utils/scan/tools"
+import request from "@/api/model/file.js";
+import { mapGetters, mapActions } from "vuex"
+
+export default {
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"])
+  },
+  data() {
+    return {
+      casVal: '',
+      options: []
+    };
+  },
+  created() {
+    this.init()
+  },
+  watch: {
+    projectId() {
+      this.casVal = ''
+      this.options = []
+      this.init()
+    }
+  },
+  methods: {
+    //设置默认选项
+    setValue(val) {
+      if (val && val.length) {
+        this.casVal = val
+      }
+    },
+    //获取数据
+    init() {
+      this.getDirectory()
+    },
+    // 获取文件夹
+    getDirectory() {
+      request.queryModel("", res => {
+        this.options = res.Content.map(t => {
+          return {
+            value: t.Id,
+            label: t.Name
+          }
+        })
+      });
+    },
+    //改变item
+    handleChange(value) {
+      this.options.map(item =>{
+        if (item.value == value) {
+          value = item
+        }
+      })
+      value = value?value:{value:''}
+      this.$emit("change", value)
+    }
+  }
+};
+</script>
+<style lang="less">
+.el-cascader .el-input .el-input__inner {
+  vertical-align: bottom;
+}
+</style>
+<style lang="less" scoped>
+#modelFile {
+  margin-left: 10px;
+  float: left;
+  .modelFile {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 1 - 1
src/fetch/fetch.js

@@ -6,7 +6,7 @@ const instance = axios.create({
     headers: {
         "Content-Type": "application/json"
     },
-    timeout: 30000,
+    timeout: 3000000,
     retry: 4, //重新请求次数
     retryDelay: 1000, //重新请求的间隔
 })

+ 284 - 25
src/framework/components/messagesever/index.vue

@@ -2,13 +2,44 @@
  * @Author: zhangyu
  * @Date: 2019-08-26 15:22:13
  * @Info: 
- * @LastEditTime: 2019-09-26 20:16:41
+ * @LastEditTime: 2019-10-31 14:38:27
  -->
 <template>
-  <div class="notification-box" @click="handleClickRead">
+  <div class="notification-box" v-clickOutside="handleClose" @click="handleClickRead">
     <el-badge :value="unreadNum" :hidden="!unreadNum" :max="99">
       <i class="el-icon-message-solid"></i>
     </el-badge>
+    <transition name="el-fade-in-linear">
+      <div v-show="noticeListShow" @click.stop="" class="noticeBox">
+        <ul class="noticeTab">
+          <li class="noticeTab_item">消息通知<!-- <span class="unread_num">1</span> --></li>
+        </ul>
+        <div class="noticeList_scroll">
+          <el-scrollbar style="height:100%;">
+            <ul class="noticeList">
+              <li class="noticeList_item" v-for="item in messageList" :key="item.Id" :title="item.Content.Message?item.Content.Message:''">
+                <div class="noticeItem_box">
+                  <div class="noticeItem_text">
+                    <i :class="iconClassMap[item.Type]?iconClassMap[item.Type]:'msg-icon el-icon-info info-color'"></i>
+                    <p><span>{{`【${moduleMap[item.Module]?moduleMap[item.Module]:item.Module}】 `}}</span>{{item.Title?item.Title:""}}</p>
+                  </div>
+                  <div class="noticeItem_time">{{item.CreateTime}}
+                    <el-link v-for="(btn, index) in item.Content.ButtonList?item.Content.ButtonList:[]" style="float:right;font-size:12px;margin-left:5px;" type="primary"
+                    :key="index"
+                    :href="`/image-service/common/file_get?systemId=revit&key=${btn.Url}`"
+                    :download="btn.FileName?btn.FileName:''">{{btn.Name?btn.Name:""}}</el-link>
+                  </div>
+                </div>
+              </li>
+            </ul>
+          </el-scrollbar>
+        </div>
+        <div class="notice_operate">
+          <!-- <div class="readAll">全部标为已读</div> -->
+          <div class="seeAll" @click="allDetails">查看全部<i class="iconfont icon-right"></i></div>
+        </div>
+      </div>
+    </transition>
     <!-- <el-button type="primary" @click="handleClickConnectMQ">连接MQ</el-button>
     <el-button type="primary" @click="handleClickDisconnectMQ">断开MQ</el-button>
     <el-button type="primary" @click="handleClickUnsubscribe">停止接收消息</el-button><br><br>
@@ -30,39 +61,83 @@
 import { mapGetters } from 'vuex'
 import Stomp from 'stompjs'
 import Msmq from './msmq'
+import Bus from '@/utils/bus.js'
 import { MQTT_SERVICE, MQTT_USERNAME, MQTT_PASSWORD } from './mqSetting'
+import { messgeCount, messgeQuery, messgeUpdateState } from '@/api/msgsever'
 
 export default {
+  components:{
+    
+  },
   data() {
     return {
       client: Stomp.client(MQTT_SERVICE),
       unreadNum: 0,
+      noticeListShow: false,//是否显示消息列表
       sendMessage: '',
       messageList: [], // 历史消息
       subList: [], // 订阅的消息实例
-      topics: ["/topic/model.manage"] // 订阅的消息名称
+      topics: ["/topic/message.manage"], // 订阅的消息名称
+      messageList: [],
+      moduleMap: {//消息模块映射
+        "Model": "模型文件管理"
+      },
+      iconClassMap: { //消息类型图标映射
+        "Success": "msg-icon el-icon-success success-color",
+        "Error": "msg-icon el-icon-error error-color",
+        "Warning": "msg-icon el-icon-warning warning-color",
+        "Info": "msg-icon el-icon-info info-color",
+      },
+      showTools: false
     }
   },
   created () {
     this.connect()
-    // let url = "ws://192.168.20.225:61614/stomp";
-    // let login = "admin";
-    // let passcode = "admin";
-    // let destination = "/topic/datacenter.broadcast";
-    // let client = Stomp.client(url)
-    // console.log('钩子:',client)
-    // var onconnect = function(frame) {
-    //   client.subscribe(destination, function(message) {
-    //     console.log(message.body);
-    //     alert(message.body);        
-    //   });
-    // };
-    // client.connect(login, passcode, onconnect)
+  },
+  mounted() {
+    this.getUnreadCount()
+    this.getMessageList()//获取消息列表
+    Bus.$on('messageListUpdate', message => {
+      this.getMessageList()
+    })
   },
   computed: {
-    ...mapGetters('layout', ['userInfo', 'projectId', 'projects'])
+    ...mapGetters('layout', ['userInfo', 'projectId', 'projects', 'userId'])
   },
   methods:{
+    getMessageList(){//获取消息列表(最新10条)
+      let params = {
+        Filters: `UserId='${this.userId}'`,
+        Orders: "CreateTime desc, Id asc",
+        PageNumber: 1,
+        PageSize: 10
+      }
+      messgeQuery(params, res => {
+        this.messageList = res.Content
+      })
+    },
+    getUnreadCount(){//获取未读消息的数量
+      let params = {
+        Filters: `Read=false;UserId='${this.userId}'`
+      }
+      messgeCount(params, res => {
+        this.unreadNum = res.Count
+      })
+    },
+    setAllRead(){//将当前角色消息全部置为已读
+      if(this.userId){
+        messgeUpdateState({Read:true,UserId:this.userId}, res => {this.unreadNum = 0})
+      }
+    },
+    handleClose(e){//关闭消息列表
+      this.noticeListShow = false
+    },
+    handleClickRead() {//点击消息铃铛
+      this.noticeListShow?this.noticeListShow=false:this.noticeListShow=true
+      if(this.noticeListShow){
+        this.setAllRead()//将当前角色消息全部置为已读
+      }
+    },
     connect() {
       this.client = Stomp.client(MQTT_SERVICE)
       this.client.reconnect_delay = 5000
@@ -85,7 +160,7 @@ export default {
     },
     //接收到消息的回调
     onmessage(message) {
-      this.unreadNum = Msmq.handleMsg(message, this.projects, this.unreadNum);
+      this.unreadNum = Msmq.handleMsg(message, this.projects, this.userId, this.unreadNum);
     },
     // 接收消息失败回调
     onFailed(frame) {
@@ -108,20 +183,22 @@ export default {
       this.client.send(destination, headers, JSON.stringify(message))
     },
     
-    handleClickConnectMQ() {
+    handleClickConnectMQ() {//连接MQ
       this.connect()
     },
-    handleClickDisconnectMQ() {
+    handleClickDisconnectMQ() {//断开MQ
       this.disconnect()
     },
-    handleClickUnsubscribe() {
+    handleClickUnsubscribe() {//停止接收消息
       this.unsubscribe()
     },
-    handleClickSendMessage() {
+    handleClickSendMessage() {//发送消息
       this.send('/topic/datacenter.broadcast',this.sendMessage)
-    }, 
-    handleClickRead() {
-      this.unreadNum = 0;
+    },
+    allDetails(){
+      console.log(493498384938)
+      this.noticeListShow = false;
+      this.$router.push({path:"/message/allDetails"});
     }
   }
 }
@@ -131,10 +208,180 @@ export default {
   .notification-box{
     width: 100%;
     height: 100%;
+    position: relative;
     padding: 16px 10px 10px;
     box-sizing: border-box;
     color: #79869a;
     cursor: pointer;
+    .noticeBox{
+      position: absolute;
+      top: 50px;
+      left: 50%;
+      margin-left: -220px;
+      cursor: auto;
+      z-index: 1000;
+      text-align: left;
+      width: 272px;
+      height: 362px;
+      box-shadow: 0 1px 6px 0 #ccc;
+      color: #333;
+      background: #fff;
+      overflow: visible!important;
+    }
+    .noticeBox::before {
+      content: '';
+      border: solid 7px transparent;
+      border-bottom-color: #fff;
+      display: block;
+      position: absolute;
+      width: 2px;
+      top: -14px;
+      left: 50%;
+      margin-left: 77px;
+      z-index: 0;
+    }
+    .noticeTab {
+      padding: 8px 16px 0;
+      z-index: 10;
+      height: 32px;
+      zoom: 1;
+      box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.1) inset;
+      .noticeTab_item {
+        float: left;
+        position: relative;
+        width: 240px;
+        height: 32px;
+        line-height: 32px;
+        padding: 0;
+        margin-right: 0;
+        font-weight: 700;
+        text-align: left;
+        cursor: pointer;
+        -webkit-transition: all 0.2s ease-in-out;
+        -o-transition: all 0.2s ease-in-out;
+        transition: all 0.2s ease-in-out;
+        .unread_num {
+          display: inline-block;
+          color: #fff;
+          background-color: #5182E4;
+          height: 14px;
+          padding: 0 2px;
+          line-height: 14px;
+          text-align: center;
+          border-radius: 2px;
+          font-size: 12px;
+          padding: 0 3px;
+          font-family: Arial;
+          -webkit-transform: scale(0.85);
+          -ms-transform: scale(0.85);
+          -o-transform: scale(0.85);
+          transform: scale(0.85);
+        }
+      }
+      .active {
+        box-shadow: 0 -2px 0 0 #5182E4 inset;
+      }
+    }
+    .noticeList_scroll {
+      height: 282px;
+      /deep/ .el-scrollbar__wrap {
+        overflow-x: hidden;
+      }
+      .noticeList_item {
+        width: 100%;
+        height: auto;
+        position: relative;
+        cursor: pointer;
+        box-sizing: border-box;
+        padding: 12px 16px;
+        -webkit-transition: all 0.2s ease-in-out;
+        -o-transition: all 0.2s ease-in-out;
+        transition: all 0.2s ease-in-out;
+        zoom: 1;
+        .noticeItem_box {
+          float: left;
+          position: relative;
+          width: 100%;
+          .noticeItem_text {
+            color: rgba(10, 18, 32, 0.87);
+            font-weight: 700;
+            padding-left: 18px;
+            text-indent: -6px;
+            position: relative;
+            font-size: 12px;
+            line-height: 17px;
+            -webkit-transition: all 0.2s ease-in-out;
+            -o-transition: all 0.2s ease-in-out;
+            transition: all 0.2s ease-in-out;
+            .msg-icon{
+              position: absolute;
+              top: 2.5px;
+              left: 6px;
+            }
+            p {
+              word-break: break-all;
+            }
+          }
+          .noticeItem_time {
+            font-size: 12px;
+            height: 19px;
+            line-height: 19px;
+            color: rgba(10, 18, 32, 0.46);
+            margin-top: 4px;
+            padding-left: 18px;
+          }
+        }
+      }
+      .noticeList_item:hover {
+        background-color: #F5F7F7;
+      }
+      .noticeList_item:after {
+        content: "";
+        display: block;
+        height: 0;
+        clear:both;
+        visibility: hidden;
+      }
+      .noticeList_item:before {
+        position: absolute;
+        right: 0;
+        bottom: 0;
+        left: 0;
+        height: 1px;
+        padding: 0 16px;
+        background-color: #ebebeb;
+        content: "";
+        background-clip: content-box;
+      }
+    }
+    .notice_operate {
+      height: 40px;
+      line-height: 20px;
+      padding: 10px 16px;
+      box-sizing: border-box;
+      background-color: rgba(242, 243, 245, 0.48);
+      box-shadow: inset 0 1px 0 0 rgba(10, 18, 32, 0.06);
+      zoom: 1;
+      .readAll {
+        float: left;
+        cursor: pointer;
+        -webkit-transition: all 0.2s ease-in-out;
+        -o-transition: all 0.2s ease-in-out;
+        transition: all 0.2s ease-in-out;
+      }
+      .readAll:hover {
+        text-decoration: underline;
+      }
+      .seeAll {
+        float: right;
+        color: #5182e4;
+        cursor: pointer;
+        font-weight: 700;
+      }
+      .seeAll:hover {
+        text-decoration: underline;
+      }
+    }
     .el-icon-message-solid{
       font-size: 22px;
     }
@@ -148,4 +395,16 @@ export default {
     color: #d3d8e2;
     background-color: #3f4f62;
   }
+  .success-color{
+    color: #67C23A;
+  }
+  .error-color{
+    color: #F56C6C;
+  }
+  .warning-color{
+    color: #E6A23C;
+  }
+  .info-color{
+    color: #909399;
+  }
 </style>

+ 172 - 0
src/framework/components/messagesever/msgAllDetails.vue

@@ -0,0 +1,172 @@
+<template>
+  <div class="box">
+    <div class="condition">
+      <div class="main" :style="tableData && tableData.length?'height: calc(100% - 96px);':'height: calc(100% - 46px);'">
+        <!-- <el-table ref="multipleTable" :data="tableData" v-loading='loading' stripe height="100%" :header-cell-style="headerStyle"> -->
+        <el-table ref="multipleTable" v-loading='loading' stripe :header-cell-style="headerStyle" :data="tableData">
+          <el-table-column type="selection" width="55"></el-table-column>
+          <el-table-column prop="messageModule" label="模块" width="200"></el-table-column>
+          <el-table-column prop="messageContent" label="消息内容" width="600"></el-table-column>
+          <el-table-column prop="messageTime" label="消息时间">
+          </el-table-column>
+          <el-table-column label="消息类型">
+            <template slot-scope="scope">
+       <i :class="iconClassMap[scope.row.messageType]?iconClassMap[scope.row.messageType]:'msg-icon el-icon-info info-color'"></i>
+      </template>
+            
+          </el-table-column>
+            <el-table-column type="expand">
+            <!-- <template slot-scope="props">
+              <el-form label-position="left" label-width="auto" inline class="demo-table-expand" v-if="props.row.ComponentCount && props.row.ComponentCount.length">
+                <el-form-item v-for="item in props.row.ComponentCount?props.row.ComponentCount:[]" :key="item.code" :label="`${item.name}:`">
+                  <span>{{ item.count }}</span>
+                </el-form-item>
+              </el-form>
+            </template> -->
+          </el-table-column>
+          <template slot="empty">
+            <div style="height: 60%;transform: translateY(50%);">
+              <i class="icon-wushuju iconfont"></i>
+              数据暂无
+            </div>
+          </template>
+        </el-table>
+      </div>
+      <div class=footer>
+        <el-pagination class="right">
+        </el-pagination>
+        <!-- <el-pagination
+          class="right"
+          v-show="tableData && tableData.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.pageNumber"
+          :page-sizes="page.pageSizes"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { messgeCount, messgeQuery, messgeUpdateState } from '@/api/msgsever'
+import Bus from '@/utils/bus.js'
+
+export default {
+  data() {
+    return {
+      tableData:[],
+      loading: false,
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      moduleMap: {//消息模块映射
+        "Model": "模型文件管理"
+      },
+      iconClassMap: { //消息类型图标映射
+        "Success": "msg-icon el-icon-success success-color",
+        "Error": "msg-icon el-icon-error error-color",
+        "Warning": "msg-icon el-icon-warning warning-color",
+        "Info": "msg-icon el-icon-info info-color",
+      }
+    }
+  },
+  computed: {
+    ...mapGetters('layout', ['userInfo', 'projectId', 'projects', 'userId'])
+  },
+  created() {
+
+  },
+  mounted() {
+    this.getMessageList()//获取消息列表
+    Bus.$on('messageListUpdate', message => {
+      this.getMessageList()
+    })
+  },
+  watch: {
+    projectId() {
+      this.page.pageNumber = 1
+      this.multipleSelection = []
+    }
+  },
+  methods: {
+    getMessageList(){//获取消息列表
+      let params = {
+        Filters: `UserId='${this.userId}'`,
+        Orders: "CreateTime desc, Id asc",
+        PageNumber: 1,
+        PageSize: 50
+      }
+      messgeQuery(params, res => {
+        this.messageList = res.Content
+        this.messageList.map((item)=>{
+          console.log(item,234232)
+          this.tableData.push({
+            messageModule: this.moduleMap[item.Module],// 模块
+            messageTime: item.CreateTime,// 时间
+            messageType: item.Type,// 类型
+            messageContent: item.Title,// title
+            messageButton: item.ButtonList?item.ButtonList.Name:''// 按钮
+          })
+        })
+      })
+    }
+  }
+};
+</script>
+
+<style scoped lang='less'>
+.box {
+  .condition {
+    padding: 10px;
+    display: flex;
+    height: 100%;
+    flex-direction: column;
+    border: 1px solid #dfe6ec;
+    background: #fff;
+    .main{
+      margin-top: 10px;
+    }
+  }
+}
+</style>
+
+<style>
+  .demo-table-expand {
+    font-size: 0;
+  }
+  .demo-table-expand label {
+    width: 90px;
+    color: #99a9bf;
+  }
+  .demo-table-expand .el-form-item {
+    margin-right: 0;
+    margin-bottom: 0;
+    margin-left: 120px;
+    width: 100%;
+  }
+    .success-color{
+    color: #67C23A;
+  }
+  .error-color{
+    color: #F56C6C;
+  }
+  .warning-color{
+    color: #E6A23C;
+  }
+  .info-color{
+    color: #909399;
+  }
+</style>

+ 29 - 10
src/framework/components/messagesever/msmq.js

@@ -2,20 +2,39 @@ import { Notification } from 'element-ui';
 import Bus from '@/utils/bus.js'
 
 const MSMQ = {
-  handleMsg (message, projects, unreadNum ) {
+  msgTypeMap: {
+    "Success": "success",
+    "Error": "error",
+    "Warning": "warning",
+    "Info": "info",
+  },
+  moduleMap: {//消息模块映射
+    "Model": "模型文件管理"
+  },
+  handleMsg (message, projects, userId, unreadNum ) {
     let data
     try {
       data = JSON.parse(message.body)
-    } catch (err) {}
-    // if(projects.some((item) => {return item.id == data.projectId})) { //判断消息是否是当前用户拥有的项目
-      unreadNum++
-      if(message.headers.destination == '/topic/model.manage'){ //模型文件的消息触发模型文件列表刷新事件
-        Bus.$emit('modelStatusChange', data)
+    } catch (err) {
+      return false
+    }
+    if(data.ProjectId && projects.some((item) => {return item.id == data.ProjectId})) { //判断消息是否是当前用户拥有的项目
+      if(!data.UserList || (userId && data.UserList && data.UserList.includes(userId))){//判断消息接收人是否是当前用户
+        if(data.Module && data.Module == 'Model'){ //模型文件的消息触发模型文件列表刷新事件
+          Bus.$emit('modelStatusChange', data)
+        }
+        Notification({ 
+          title: `${data.Title?data.Title:''}`, 
+          dangerouslyUseHTMLString: true, 
+          message: `【${this.moduleMap[data.Module]?this.moduleMap[data.Module]:data.Module}】${data.Content?data.Content.Message?data.Content.Message:'':''}`,
+          type: this.msgTypeMap[data.Type]?this.msgTypeMap[data.Type]:'info'
+        })
+        // Notification.info({ title: '消息',dangerouslyUseHTMLString: true, message: `项目编号:${data.projectId}<br>消息类型:${data.type}<br>描述信息:${data.description}<br>` })
+        unreadNum++
+        Bus.$emit('messageListUpdate', data)//消息驱动消息列表刷新
+        return unreadNum
       }
-      // Notification.info({ title: '消息',dangerouslyUseHTMLString: true, message: `项目编号:${data.projectId}<br>消息类型:${data.type}<br>描述信息:${data.description}<br>` })
-      Notification.info({ title: '消息', dangerouslyUseHTMLString: true, message: `${JSON.stringify(data)}` })
-      return unreadNum
-    // }
+    }
   }
 }
 

+ 64 - 11
src/router/system.js

@@ -1,4 +1,5 @@
 import LayoutMain from '@/framework/layout/Main'
+import MsgAllDetails from "@/framework/components/messagesever/msgAllDetails"
 
 import Login from '@/framework/layout/Login'
 import Dasboard from '@/views/dasboard'
@@ -36,6 +37,9 @@ import spaceRela from '@/views/point/dynamicdata/addRelation/spaceRela'
 
 /** 扫楼作业 */
 import buildTask from '@/views/data_admin/buildTask'
+import addDeviceTask from '@/views/data_admin/buildTask/addTask/addDeviceTask'
+import addAssetsTask from '@/views/data_admin/buildTask/addTask/addAssetsTask'
+import addModelTask from '@/views/data_admin/buildTask/addTask/addModelTask'
 import buildAssets from '@/views/data_admin/buildAssets'
 import buildLog from '@/views/data_admin/buildLog'
 import buildData from '@/views/data_admin/buildData'
@@ -44,6 +48,7 @@ import buildGraphy from '@/views/data_admin/buildGraphy'
 /**  台账管理 */
 import systemLedger from '@/views/ledger/system'
 import systemadd from '@/views/ledger/system/addsystem'
+import systemDetail from '@/views/ledger/system/systemDetail'
 import facilityLedger from '@/views/ledger/facility'
 import partsLedger from '@/views/ledger/facility/parts'
 import partsmanageLedger from '@/views/ledger/facility/partsmanage'
@@ -51,8 +56,8 @@ import partsadd from '@/views/ledger/facility/partsmanage/addparts'
 import deviceadd from '@/views/ledger/facility/addfacility'
 import propertyadd from '@/views/ledger/property/addproperty'
 import propertyLedger from '@/views/ledger/property'
-import spacelist from '@/views/ledger/spacelist'//业务空间台账
-import addPropertys from '@/views/ledger/property/addpropertys'//根据未关联资产的设备或部件批量创建设备
+import spacelist from '@/views/ledger/spacelist' //业务空间台账
+import addPropertys from '@/views/ledger/property/addpropertys' //根据未关联资产的设备或部件批量创建设备
 import batchlinkAssets from '@/views/ledger/facility/batchlink' //批量关联资产
 import cenotelist from '@/views/ledger/cenotelist' //竖井清单
 import cenoteadd from '@/views/ledger/cenotelist/cenoteadd' //添加竖井
@@ -63,6 +68,7 @@ import dataReport from '@/views/ledger/report'
 import auth from '@/views/system/auth'
 import noUser from '@/views/system/nouser'
 import spaceDetail from '@/views/ledger/spacelist/spaceDetail'
+import relatedSpace from '@/views/ledger/cenotelist/relatedSpace'
 
 /**  关系维护并计算 */
 import maintain from '@/views/relation/maintain'
@@ -71,15 +77,33 @@ import overView from '@/views/relation/overview'
 /**  厂家库 */
 import supplier from '@/views/manufactor/supplier'
 
+/**  业务空间数据导入工具 */
+import dataUtil from '@/views/business_space/dataUtil'
+
 /**市场及商务 */
 const OwnerManage = () =>
-    import('@/views/market/owner/manage')
+    import ('@/views/market/owner/manage')
 
 export default [
     { path: '/', name: '', component: LayoutMain, children: [{ path: '', name: 'blank', component: Dasboard }] },
     //{ path: '/login', name: 'Login', component: Login },
     { path: '/auth', name: 'auth', component: auth },
     { path: '/noUser', name: 'noUser', component: noUser },
+    // {
+    //     path: '/msgAllDetails',
+    //     name: 'LayoutMain',
+    //     component: MsgAllDetails,
+    // },
+    // 业务空间数据导入工具
+    {
+        path: '/message',
+        name: 'LayoutMain',
+        component: LayoutMain,
+        children: [
+            { path: 'allDetails', name: "allDetails", component: MsgAllDetails, meta: { keepAlive: false, breadcrumbs: [{ label: '消息中心' }] } }
+        ]
+    },
+    { path: '/dataUtil', name: 'dataUtil', component: LayoutMain, children: [{ path: 'index', component: dataUtil }] },
     // 平台管理
     {
         path: '/platform',
@@ -101,7 +125,7 @@ export default [
             // { path: 'buildfloor', name: 'buildFloor', component: Dasboard, meta: { keepAlive: false, breadcrumbs: [{ label: '建筑楼层管理' }] } },
             { path: 'collectsetting', name: 'collectsetting', component: collectsetting, meta: { keepAlive: false, breadcrumbs: [{ label: '需采集的信息点' }] } },
             { path: 'appuser', name: 'buildUser', component: buildUser, meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼App用户管理' }] } },
-            { path: 'repetitionGraphy', name: 'repetitionGraphy', component: repetitionGraphy, meta: { keepAlive: false, breadcrumbs: [{ label: '建筑楼层管理', path: '/ready/buildfloor' }, { label:'平面图维护' }] }}
+            { path: 'repetitionGraphy', name: 'repetitionGraphy', component: repetitionGraphy, meta: { keepAlive: false, breadcrumbs: [{ label: '建筑楼层管理', path: '/ready/buildfloor' }, { label: '平面图维护' }] } }
         ]
     },
     //模型管理
@@ -191,36 +215,54 @@ export default [
         name: 'LayoutMain',
         component: LayoutMain,
         children: [
-            { path: '', name: 'buildData', component: buildData },
+            { path: '', name: 'buildTask', component: buildTask },
             {
                 path: 'task',
                 name: 'buildTask',
                 component: buildTask,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor/task' }, { label: '现场任务管理' }] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场任务管理' }] }
+            },
+            {
+                path: 'addDeviceTask',
+                name: 'addDeviceTask',
+                component: addDeviceTask,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场任务管理', path: '/floor/task' }, { label: '现场验证设备台账' }] }
+            },
+            {
+                path: 'addAssetsTask',
+                name: 'addAssetsTask',
+                component: addAssetsTask,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场任务管理', path: '/floor/task' }, { label: '现场验证资产台账' }] }
+            },
+            {
+                path: 'addModelTask',
+                name: 'addModelTask',
+                component: addModelTask,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场任务管理', path: '/floor/task' }, { label: '现场验证模型' }] }
             },
             {
                 path: 'data',
                 name: 'buildData',
                 component: buildData,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor/task' }, { label: '现场数据整理', path: '/floor/data' }, { label: '信息点整理' }] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场数据整理', path: '/floor/data' }, { label: '信息点整理' }] }
             },
             {
                 path: 'plan',
                 name: 'buildGraphy',
                 component: buildGraphy,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor/task' }, { label: '现场数据整理', path: '/floor/data' }, { label: '位置标签整理' }] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场数据整理', path: '/floor/data' }, { label: '位置标签整理' }] }
             },
             {
                 path: 'abnormalprop',
                 name: 'buildAssets',
                 component: buildAssets,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor/task' }, { label: '扫楼报告' }] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '扫楼报告' }] }
             },
             {
                 path: 'log',
                 name: 'buildLog',
                 component: buildLog,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor/task' }, { label: '扫楼日志查看' }] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '扫楼日志查看' }] }
             }
         ]
     },
@@ -292,6 +334,12 @@ export default [
                 meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '系统台账' }] }
             },
             {
+                path: 'systemDetail',
+                name: 'systemDetail',
+                component: systemDetail,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '系统台账', path: '/ledger/facility' }, { label: '系统详情' }] }
+            },
+            {
                 path: 'systemadd',
                 name: 'systemadd',
                 component: systemadd,
@@ -307,7 +355,7 @@ export default [
                 path: 'spaceDetail',
                 name: 'spaceDetail',
                 component: spaceDetail,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '业务空间台账',path: '/ledger/spacelist' }, {label:'业务空间详情'}] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '业务空间台账', path: '/ledger/spacelist' }, { label: '业务空间详情' }] }
             },
             {
                 path: 'cenotelist',
@@ -326,6 +374,11 @@ export default [
                 name: 'cenoteDetail',
                 component: cenoteDetail,
                 meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '竖井台账', path: '/ledger/cenotelist' }, { label: '竖井关系详情' }] }
+            }, {
+                path: 'relatedSpace',
+                name: 'relatedSpace',
+                component: relatedSpace,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '竖井台账', path: '/ledger/cenotelist' }, { label: '竖井关联的元空间' }] }
             },
             {
                 path: 'rentlist',

+ 5 - 2
src/utils/handsontable/fillterField.js

@@ -58,12 +58,15 @@ const data = {
     ]
   },
   space:{//业务空间
-    onlyRead: [],
+    onlyRead: [
+      "Outline"
+    ],
     edit: [
       "RoomID",
       "RoomName",
       "BIMID",
-      "BIMLocation"
+      "BIMLocation",
+      "Outline"
     ]
   }
 }

+ 33 - 1
src/utils/handsontable/mainText.js

@@ -95,7 +95,39 @@ const text = {
         td.style.cursor = "pointer";
         td.innerHTML = "查看二维码"
         return td
-    }
+    },
+
+    //系统所属建筑楼层
+    sysInBuildFloor: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (value instanceof Array && value.length > 0) {
+            if (value.length == 1) {
+                td.innerHTML = !!value[0].infos ? (value[0].infos.SysLocalName || value[0].infos.SysName) : (value[0].SysLocalName || value[0].SysName)
+            } else {
+                let text = ""
+                for (let i = 0; i < value.length; i++) {
+                    if (!!value[i].SysLocalName || !!value[i].SysName) {
+                        if (i == value.length) {
+                            text += value[i].SysLocalName || value[i].SysName
+                        } else {
+                            text = value[i].SysLocalName || value[i].SysName + "、" + text
+                        }
+                    } else {
+                        if (i == value.length) {
+                            text += value[i].infos.SysLocalName || value[i].infos.SysName
+                        } else {
+                            text = value[i].infos.SysLocalName || value[i].infos.SysName + "、" + text
+                        }
+                    }
+                }
+                td.innerHTML = text.substring(0, 40) + "..."
+            }
+        } else {
+            td.innerHTML = "无所属建筑楼层"
+        }
+        return td;
+    },
 }
 
 export default text

+ 1 - 1
src/utils/httputils.js

@@ -7,7 +7,7 @@ var cancel
 
 // 创建axios实例
 const axiosservice = axios.create({
-    timeout: 30000, // 请求超时时间
+    timeout: 3000000, // 请求超时时间
     retry: 4, //重新请求次数
     retryDelay: 1000, //重新请求的间隔
     credentials: true, // 接口每次请求会跨域携带cookie

+ 8 - 1
src/utils/point_edit/handson_header.js

@@ -151,7 +151,14 @@ const headers = {
             Visible: true,
             FirstTag: ""
         }
-    ]
+    ],
+    "common": [{
+        InfoPointName: "*地址详情",
+        InfoPointCode: "JoinedInfo",
+        InputMode: "B1",
+        Visible: true,
+        FirstTag: ""
+    }],
 }
 
 let common = [{

+ 26 - 0
src/utils/scan/directive.js

@@ -62,4 +62,30 @@ Vue.directive('load', function(el, binding) {
         // }
         el.src = imgDom.src
     }
+})
+//点击空白处隐藏div指令
+Vue.directive('clickOutside', {
+    // 初始化指令
+    bind(el, binding, vnode) {
+        function documentHandler(e) {
+            // 这里判断点击的元素是否是本身,是本身,则返回
+            if (el.contains(e.target)) {
+                return false;
+            }
+            // 判断指令中是否绑定了函数
+            if (binding.expression) {
+                // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
+                binding.value(e);
+            }
+        }
+        // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
+        el.__vueClickOutside__ = documentHandler;
+        document.addEventListener('click', documentHandler);
+    },
+    update() {},
+    unbind(el, binding) {
+        // 解除事件监听
+        document.removeEventListener('click', el.__vueClickOutside__);
+        delete el.__vueClickOutside__;
+    },
 })

+ 27 - 0
src/utils/tools.js

@@ -34,4 +34,31 @@ tools.deepCopy = (obj) => {
     return temp
 }
 
+//判断watch监听的值是否相同
+tools.isSimilarly = (newValue, oldValue) => {
+    if(typeof newValue === typeof oldValue){
+        if(newValue === oldValue){
+            return true
+        } else {
+            let flag = false
+            try {
+                Object.keys(newValue).forEach((item, index, arr) => {
+                    if(oldValue.hasOwnProperty(item) && newValue[item] === oldValue[item]){
+                        if(index == arr.length-1){
+                            flag = true
+                        }
+                    } else {
+                        throw new Error()
+                    }
+                })
+            } catch (error) {
+                return false
+            }
+            return flag
+        }
+    } else {
+        return false
+    }
+}
+
 export default tools

+ 623 - 0
src/views/business_space/dataUtil/index.vue

@@ -0,0 +1,623 @@
+<template>
+  <div class="main-box">
+    <div class="saga-build-mess">
+      <span style="padding-right:12px;color:#999999;">建筑楼层</span>
+      <el-cascader :options="options" v-model="buildFloorSelectd" :props="props" @change="changeCascader"></el-cascader>
+      <el-button @click="updateSpOutline">导入业务空间Outline</el-button>
+      <el-button @click="updateSiOutline" v-show="0">更新元空间Outline,Height</el-button>
+    </div>
+  </div>
+</template>
+<script>
+import {
+  getDataDictionary,
+  getAllbusiness,
+  getSpaceFloor,
+  queryDictionaryHead,
+  buildingQuery, //数据中心-建筑查询
+  queryZone,
+  updateZone,
+  getGraphyId, // 物理世界获取图实例关系
+  getRelation, // 物理世界获取业务空间与元空间关系
+  getBussines2, //
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import pako from '@/assets/pako/pako'
+import axios from "axios";
+export default {
+  data() {
+    return {
+      buildFloorSelectd: [],
+      props: { //自定义字段
+        value: "BuildID",
+        label: "BuildLocalName",
+        children: "Floor"
+      },
+      floorIdToMap: {}, //楼层id->楼层图
+      options: [],
+      tabsList: [
+        {
+          "Code": "GeneralZone",
+          "Name": "默认分区",
+          "Rel_type": "99"
+        },
+        {
+          "Name": "供电分区",
+          "Rel_type": "1",
+          "Code": "PowerSupplyZone"
+        },
+        {
+          "Name": "照明分区",
+          "Rel_type": "2",
+          "Code": "LightingZone"
+        },
+        {
+          "Name": "网络分区",
+          "Rel_type": "3",
+          "Code": "NetworkZone"
+        },
+        {
+          "Code": "AirConditioningZone",
+          "Name": "空调分区",
+          "Rel_type": "4"
+        },
+        {
+          "Name": "采暖分区",
+          "Rel_type": "5",
+          "Code": "HeatingZone"
+        },
+        {
+          "Name": "洁净分区",
+          "Rel_type": "6",
+          "Code": "CleanZone"
+        },
+        {
+          "Name": "生活给水分区",
+          "Rel_type": "7",
+          "Code": "DomesticWaterSupplyZone"
+        },
+        {
+          "Code": "FireZone",
+          "Name": "防火分区",
+          "Rel_type": "8"
+        },
+        {
+          "Name": "安防分区",
+          "Rel_type": "9",
+          "Code": "SecurityZone"
+        },
+        {
+          "Name": "租户分区",
+          "Rel_type": "10",
+          "Code": "TenantZone"
+        },
+        {
+          "Name": '功能分区',
+          'Rel_type': '11',
+          "Code": 'FunctionZone'
+        }
+      ],
+      allSiListMap: {}, //Si id ->sourceid
+      sourceIdToOutline: {}, //sourceid -> outline
+      sourceIdToHeight: {}, //sourceid -> height
+      graphyId: '',
+      allABC: [
+        'Fl11010500011b85b9eeff8211e8b8b087ac5144d0ef20191010145313bim.jsonz',
+        'Fl110105000181b22b1608b911e9acbca78c1b4e10a620191011181833bim.jsonz',
+        'Fl1101050001072a8b6cff8211e8b8b0015f957e8c7f20191010145327bim.jsonz',
+        'Fl11010500011007d4edff8211e8b8b0ab7044c4281120191010145320bim.jsonz',
+        'Fl11010500012a0741ffff8211e8b8b057c9c998394220191010152132bim.jsonz',
+        'Fl1101050001fb55faebff8111e8b8b07995537bf28720191011143329bim.jsonz',
+        'Fl11010500012c9b2aeb5ffa11e9a618397d1467f28020191011104423bim.jsonz',
+        'Fl11010500018aff2ad35ff711e9a6182f2301e72e6020190909174638bim.jsonz',
+        'Fl110105000150fa91315ff711e9a618c9724397ed0720191010152112bim.jsonz',
+        'Fl1101050001183b6fde5ff711e9a618071bdac223fe20191011143315bim.jsonz',
+        'Fl1101050001723c0e525ff711e9a618cbf5042c40d120191010152106bim.jsonz',
+        'Fl11010500013e6974505ff711e9a618e15213be8b4820191010161301bim.jsonz',
+        'Fl110105000130c1d17f5ff711e9a618c7fff3f2463720190829142855bim.jsonz',
+        'Fl11010500019bd7ae53b36611e9989b6b5aa64fce0020191011143304bim.jsonz',
+        'Fl110105000107cd29a4b36711e9989b833dd102d9f620190909180620bim.jsonz',
+        'Fl1101050001c62588265ff711e9a6180390acf0fbab20191010161242bim.jsonz',
+        'Fl1101050001ed4873e85ff711e9a618b9a20cddb21320191010161233bim.jsonz',
+        'Fl1101050001fc75cc595ff711e9a6184b0a58d23d4b20191011180342bim.jsonz',
+        'Fl1101050001b83236555ff711e9a6187be56804052e20191010161246bim.jsonz',
+        'Fl1101050001d8621c675ff711e9a61867e9c4c4e7ed20191010161238bim.jsonz',
+        'Fl1101050001a62034845ff711e9a6187d378045931b20191010161256bim.jsonz',
+        'Fl1101050001417e9293877811e9ad1f9727a4cb9ff920191008182236bim.jsonz',
+        'Fl110105001393a9aafcdf6d11e99e5477f4fe220c4820190929200808bim.jsonz',
+        'Fl1101050013866991b5df6f11e99e548f7fb48601bc20190929200729bim.jsonz',
+        'Fl1101050013fae74390df6d11e99e54d5561aa01bd520190929200817bim.jsonz',
+        'Fl1101050013c3da061adf6f11e99e54c7d23ab4172a20190929200700bim.jsonz',
+        'Fl11010500139faa5f21df6e11e99e546bdd7272e66c20190929200825bim.jsonz',
+        'Fl1101050013937cbcb6df6f11e99e543d85d7068bdf20190929200724bim.jsonz',
+        'Fl1101050013db95d69fdf6d11e99e5429a50115d5a420190929223016bim.jsonz',
+        'Fl1101050013e4bae212df6e11e99e54b7ff375e245d20190929200841bim.jsonz',
+        'Fl1101050013a075a8f7df6f11e99e54adca7466d03c20190929200719bim.jsonz',
+        'Fl1101050013ac0986f8df6f11e99e54fdce5ae59e1e20190929200712bim.jsonz',
+        'Fl1101050013b977f159df6f11e99e54b1c8cff9906a20190929200706bim.jsonz',
+        'Fl1101050013ce04c90edf6d11e99e54f9e2920216e220190929200752bim.jsonz',
+        'Fl110105001359d5d373df6f11e99e54b7e95468964e20190929200740bim.jsonz',
+        'Fl110105001374ad7814df6f11e99e545f0fb9fea1c520190929200735bim.jsonz',
+        'Fl1101050013c019dbaddf6d11e99e54bd8e15b3817720190929200801bim.jsonz',
+        'Fl1101050013a307b155a6e611e9af72f99ee18c8c9320190929200849bim.jsonz',
+        'Fl110105001382cc80a2a6e611e9af72f5982a28cf3420190929200858bim.jsonz',
+        'Fl11010500135cae0c8fa6e611e9af722bfdfa84dab620190929200911bim.jsonz',
+        'Fl1101050013750e96b1a6e611e9af721b1d998988a820190929200902bim.jsonz',
+        'Fl11010500134fb34b8ea6e611e9af7283fc80c9cbb120190929200915bim.jsonz',
+        'Fl1101050013437068dda6e611e9af72cde0e896ab3d20190929200920bim.jsonz',
+        'Fl1101050013af27a2b6a6e611e9af72a3a381eb49f520190929200845bim.jsonz',
+        'Fl11010500138ee916a3a6e611e9af7219302358433020190929200854bim.jsonz',
+        'Fl1101050013349a582ca6e611e9af72f38a28243be020190929200924bim.jsonz',
+        'Fl1101050013ebcbe2daa6e511e9af72535c0db8e49420190929200928bim.jsonz',
+        'Fl110105001367b00ad0a6e611e9af72391f1a6981f320190929200907bim.jsonz',
+        'Fl11010500135ced8275e0f111e99542a554062b3c7920190929201135bim.jsonz',
+        'Fl1101050013619b3967a6cd11e9af727dca2b35db2320190929201149bim.jsonz',
+        'Fl110105001392f3f029a6cc11e9af727dda4b57623320190929201048bim.jsonz',
+        'Fl1101050013647048c7a6cc11e9af72273d51e4947220190929201101bim.jsonz',
+        'Fl1101050013d269353ea6cc11e9af728fc5d00b2f0a20190929201023bim.jsonz',
+        'Fl11010500133665f9b5a6cd11e9af726fad221345ff20190929201130bim.jsonz',
+        'Fl110105001326ee9ff4a6cd11e9af72c73df1895e7720190929200935bim.jsonz',
+        'Fl110105001318587e73a6cd11e9af722f27783c843620190929200943bim.jsonz',
+        'Fl11010500134ce29f05a6cc11e9af7279570e0d569620190929201108bim.jsonz',
+        'Fl1101050013c6574d9da6cc11e9af72814bd704fa4820190929201033bim.jsonz',
+        'Fl1101050013866b03c8a6cc11e9af7267ca9836c13820190929201052bim.jsonz',
+        'Fl110105001373245d34cec611e9ba1805fb011b0dfb20190929201056bim.jsonz',
+        'Fl1101050013ba5f569ca6cc11e9af729b3a5696c34b20190929201038bim.jsonz',
+        'Fl11010500131f8ca234a6cc11e9af726b1c42a58f6d20190929201113bim.jsonz',
+        'Fl1101050013fd91c9c1a6cc11e9af7209967911472120190929201009bim.jsonz',
+        'Fl1101050013ab47d01ba6cc11e9af72c5020a93d09a20190929201043bim.jsonz',
+        'Fl1101050013e5eb8fefa6cc11e9af72f7e04830b73820190929201019bim.jsonz',
+        'Fl11010500130b3dd962a6cd11e9af723b4fff1de76c20190929200948bim.jsonz',
+        'Fl1101050013f0e5c500a6cc11e9af72ff5f8a3c54ec20190929201013bim.jsonz',
+        'Fl1101050027b6b6aeeebffc11e9878df3336d9ea69e20190902174737bim.jsonz',
+        'Fl1101050027f0987e4fbffc11e9878d853ef4ec937120190902174729bim.jsonz',
+        'Fl11010500276984c300bffd11e9878daf61c33e94da20190902174726bim.jsonz',
+        'Fl11010500278764c5a1bffd11e9878dff1cbcff2a8c20190902174719bim.jsonz',
+        'Fl11010500270e9c1032cd2a11e980674dea463014f320190902174707bim.jsonz',
+        'Fl110105002724295613cd2a11e9806727431a8ae35120190902174701bim.jsonz',
+        'Fl11010500279a0795c2bffd11e9878d21f91e2f7f0320190902174656bim.jsonz',
+        'Fl11010500272fb9e795ebf811e99ae435ea4d30ba4420191011153552bim.jsonz',
+        'Fl1101050027169fd510bfff11e9878d93526a68d7f520190828114146bim.jsonz',
+        'Fl1101050027fec855d9c97111e9878db36977c4803420190830162151bim.jsonz',
+        'Fl11010500273fc2ba11c00011e9878d8b124890032f20190828114140bim.jsonz',
+        'Fl1101050027cff41526cad711e9878d51b041ce6c1420190830160305bim.jsonz',
+        'Fl11010500275ca2b1d2c00011e9878df9f6e301bb0020190830160300bim.jsonz',
+        'Fl1101050027c941e8f4ebf711e99ae419b18488406120191011153543bim.jsonz',
+        'Fl11010500272815663fbffe11e9878db3dfe1b036f620190828114149bim.jsonz',
+        'Fl11010500277a169a48c00211e9878d4992c207a3fb20190903115048bim.jsonz',
+        'Fl11010500270c2d96ecc00311e9878d3f65b38832eb20190830142026bim.jsonz',
+        'Fl1101050027c594c649c00211e9878d4958f9e57f9220190903115038bim.jsonz',
+        'Fl1101050027f904cdebc00211e9878d3fc39b79fc7620190903115027bim.jsonz',
+        'Fl11010500270d0cbe35c00111e9878d612869b5adf720190903115053bim.jsonz',
+        'Fl1101050027a9f1f454c00011e9878d3d62ff2fd7d120190903115104bim.jsonz',
+        'Fl1101050027da8704aac00211e9878de504b8a990b820190903115033bim.jsonz',
+        'Fl11010500276f8ca7a7c00111e9878df574b1a855ee20190903115126bim.jsonz',
+        'Fl11010500274c7f4426c00111e9878d0fcd7948fe4720191011181832bim.jsonz',
+        'Fl110106000484c7cba9a1f011e9af72d1172b07188c20190917182902bim.jsonz',
+        'Fl11010600043f284548a1ef11e9af724d13fb54915920190906141306bim.jsonz',
+        'Fl110106000495c67edba1ef11e9af72ef904d1149c920190815150042bim.jsonz',
+        'Fl11010600044ba809e9a1ef11e9af7227433ebfb24b20190806101248bim.jsonz',
+        'Fl110106000427e698a6a1ef11e9af7245df9000e89720190906141322bim.jsonz',
+        'Fl1101060004a9672c63a1ee11e9af72311fab83533320190906141338bim.jsonz',
+        'Fl1101060004edd4f170a1ec11e9af72337886122cde20190917182934bim.jsonz',
+        'Fl110106000495197d15a1ec11e9af723104dc167b8b20190918175434bim.jsonz',
+        'Fl1101060004770c6551a1ee11e9af7265d7fcda7fec20190805175421bim.jsonz',
+        'Fl1101060004eca29690a1ed11e9af72411038923a1620190906102538bim.jsonz',
+        'Fl1101060004144a69c2a1ee11e9af72cb8e03b3179120190806101414bim.jsonz',
+        'Fl1101060004d6912c8da1ed11e9af721742ebc5a8e720190906102550bim.jsonz',
+        'Fl1101060004bd91552ca1ed11e9af7229b5746d0be420190906102601bim.jsonz',
+        'Fl11010600049cb9e47aa1ed11e9af72b7f53d9fd31c20190906102613bim.jsonz',
+        'Fl1101060004859d9a28a1ed11e9af722795f30acb1e20190906102624bim.jsonz',
+        'Fl11010600046b0dfb06a1ed11e9af72095d00257b8320190906102636bim.jsonz',
+        'Fl110106000454df4505a1ed11e9af725993924d36af20190906102647bim.jsonz',
+        'Fl1101060004a2b8d0d2a1ee11e9af72cf69abe1f44c20190830172626bim.jsonz',
+        'Fl11010600049728cdfda1ef11e9af722b0e3c2ead1a20190906141233bim.jsonz',
+        'Fl11010600049401dd4ba1ea11e9af7217861d0891ec20190919101549bim.jsonz',
+        'Fl1101060004481d2ad5a1ee11e9af7217d19632185220190906102502bim.jsonz',
+        'Fl110106000453353e84a1ed11e9af729581dac7689720190918175156bim.jsonz',
+        'Fl110106000476457d84a1ec11e9af72615d90b9bace20190905115756bim.jsonz',
+        'Fl110106000420829e13a1ee11e9af727b0bba623f7b20190906102514bim.jsonz',
+        'Fl110106000427accdd4a1f011e9af726b0152b4b9c620190929194726bim.jsonz',
+        'Fl1101060004fc037a2ea1f011e9af728bfeb54243cc20190906114418bim.jsonz',
+        'Fl110106000439d43700a1f111e9af72e19a95c6fbb820190909162505bim.jsonz',
+        'Fl1101060004d58ad82da1f011e9af72ef37cac520f920190918174923bim.jsonz',
+        'Fl1101060004fe4aa030a1ef11e9af72890f877b061520190929194745bim.jsonz',
+        'Fl1101060004240b4503a1ed11e9af726774a6bf470620190906102658bim.jsonz',
+        'Fl1101060004f9d47331a1f511e9af7289f01e05fb2c20190806101048bim.jsonz',
+        'Fl110106000473aaead0a1ee11e9af72ad49804d0c8f20190905163621bim.jsonz',
+        'Fl1101060004601ce4c6a1f011e9af72cf69dc1b598a20190918175009bim.jsonz',
+        'Fl11010600041747409ca1ec11e9af720fa2b741a00520190918175404bim.jsonz',
+        'Fl1101060004df80ec9ea1ed11e9af7277bc2af6e9c020190918175110bim.jsonz',
+        'Fl1101060004d6911abea1ef11e9af722b4776bc3d0e20190906141217bim.jsonz',
+        'Fl110106000458a53beaa1ef11e9af72fff3e1767ce920190906141250bim.jsonz',
+        'Fl11010600041c8a0912a1ed11e9af72c9b7bfceff0d20190909155405bim.jsonz',
+        'Fl11010600042b9521b7a1ef11e9af7279797025390a20190806101302bim.jsonz',
+        'Fl1101060004d30d8eb5a1ee11e9af72bfe0e47b193920190806101316bim.jsonz',
+        'Fl11010600040586cfa1a1ee11e9af722bb32265eadd20190906102527bim.jsonz',
+        'Fl110106000431b95b14a1ee11e9af727d00803ef8d620190806180123bim.jsonz',
+        'Fl11010600047253dba7a1ed11e9af72ff3602d8e82320190918175134bim.jsonz',
+        'Fl110106000448d6812ca2ad11e9af727d118e25aa6e20190806101526bim.jsonz',
+        'Fl1101060004e22b615fa1ef11e9af7247e952fac96320190806101219bim.jsonz',
+        'Fl11010600043bcc2bd5a1f011e9af72291c81eb8ae020190918175036bim.jsonz',
+        'Fl1101060004b4734e76a1ec11e9af722dd03355db1220190918175217bim.jsonz',
+        'Fl110106000420b6c57fa1f111e9af72012c927f3f4f20190906141134bim.jsonz',
+        'Fl1101060004aea831aba1ed11e9af72dfa8683aa4f720190802175313bim.jsonz',
+        'Fl1101060004a6eccafca1f011e9af7267472ea15a9620190918174948bim.jsonz',
+        'Fl110108000408a83beea2ee11e9af7259d2f787ab1620190830153737bim.jsonz',
+        'Fl11010800043f73a6877cfb11e9b795d3adf149642620191009195306bim.jsonz',
+        'Fl1101080004946844cc4ac311e99acc8b6cd31791d320190920154722bim.jsonz',
+        'Fl11010800043637f04b70834f2dbe0b82eb39068a0420191009200946bim.jsonz',
+        'Fl11010800062954591caec311e99dcfaf5a8be870d220190726122330bim.jsonz',
+        'Fl110108000672c3bbfeb1e811e9989bbd47a0e3272e20190729181028bim.jsonz',
+        'Fl1101080006d99973bfb1da11e9989b79ad9f9909f120190729170849bim.jsonz',
+        'Fl110108000602683ac0b1db11e9989b790e8880072b20190729170815bim.jsonz',
+        'Fl11010800069dcb169eb1da11e9989bc5597d8ba85920190729171022bim.jsonz',
+        'Fl11010800069fee982cb1a311e98d09d94cc66ae83520190729095659bim.jsonz',
+        'Fl1101080006b4019a1db1a311e98d093b33ddef2c3320190729095658bim.jsonz',
+        'Fl1101080006b18ac731b0d711e99dcf0f0ecc4ec38320190728095102bim.jsonz',
+        'Fl1101080006deb6f4e2b0d711e99dcfaf78f8a28ef720190728095012bim.jsonz',
+        'Fl11010800062bd07555b1cb11e9989b9751358f824620190729152437bim.jsonz',
+        'Fl11010800063c933ad6b1cb11e9989b1f3944fc1f0320190729152317bim.jsonz',
+        'Fl11010800064bdddf47b1cb11e9989b6713fdfea4de20190729152224bim.jsonz',
+        'Fl110108000610ea51c4b1cb11e9989be5322a94201220190729152547bim.jsonz',
+        'Fl11022900023e5a6bf514b511e9bf82f555b5e8b9ef20190419193227bim.jsonz',
+        'Fl110229000227d3f90414b511e9bf82bb63fa6a645a20190628142041bim.jsonz',
+        'Fl11022900020feb5e0314b511e9bf82c9cf158b9d1d20190628142043bim.jsonz',
+        'Fl110229000251f844f730f011e9b57c69e5186dd31b20190419193222bim.jsonz',
+        'Fl1102290002f78b220214b411e9bf82d9c41152624520190628142046bim.jsonz',
+        'Fl1102290002c54c958014b411e9bf82990dde33286d20190419193245bim.jsonz',
+        'Fl1102290002ae932baf14b411e9bf82d95e5f5d242a20190419193249bim.jsonz',
+        'Fl110229000248580efd14b411e9bf82e3a8a0e2a89e20190628120557bim.jsonz',
+        'Fl110229000217341a3c14b411e9bf82b76a9822ffb720190612121043bim.jsonz',
+        'Fl1102290002415d2275156a11e9bf8299370a1e2bae20190529164411bim.jsonz',
+        'Fl11022900027d6114935b7b11e9a5293d97a8a829ec20190612115403bim.jsonz',
+        'Fl110229000280f3ab26156a11e9bf82f9931ac7a65e20190529164406bim.jsonz',
+        'Fl1102290002e04c6878303e11e98edb07eab392dc6f20190419193209bim.jsonz',
+        'Fl11022900027a15c8e15b7511e9a52949dda85af39520190529164353bim.jsonz',
+        'Fl11022900023faffc705b7511e9a5298ff666bb187320190529164400bim.jsonz',
+        'Fl1102290002994137425b7511e9a529e917c82b6f3b20190419193155bim.jsonz',
+        'Fl3202130001f7a87a77e02b11e99542576d04b778bd20190930133829bim.jsonz',
+        'Fl3202130001c0c2fb23e02b11e995428577eec7921f20190930133918bim.jsonz',
+        'Fl32021300011194d4b9e02c11e99542bd8a4e0763ed20190926170827bim.jsonz',
+        'Fl32021300015df8ccdbe02c11e995427d500ee9f7e020190926170802bim.jsonz',
+        'Fl32021300016b71be8ce02c11e995426f7774395d0220190930135557bim.jsonz',
+        'Fl32021300018565fd6fe02b11e9954225a51157c39520190930133927bim.jsonz',
+        'Fl32021300015193bc2ae02c11e995427d46e123456120190926170815bim.jsonz',
+        'Fl3202130001e480e9f6e02b11e99542093b12ca666c20190930133841bim.jsonz',
+        'Fl3202130001b39cbd52e02b11e99542e108d97173bf20190926160644bim.jsonz',
+        'Fl3202130001d795e065e02b11e99542efd320197a1120190930133854bim.jsonz',
+        'Fl3202130001cd8e6ec4e02b11e9954285c1898e19ee20190930133904bim.jsonz',
+        'Fl3202130001a8e360d1e02b11e995421b39d0ace4ba20190927163237bim.jsonz',
+        'Fl320213000102b80d48e02c11e99542a716c237371720190926170838bim.jsonz',
+        'Fl32021300017033cfdee02b11e995425b075e3067b920190927163247bim.jsonz',
+        'Fl320302000133a87d5fb82d11e9b911b16d2dc3905220191011212048bim.jsonz',
+        'Fl32030200012b206aa6b82b11e9b9115d2e5ebb7c5320191011231520bim.jsonz',
+        'Fl3203020001412bd428e43d11e995428303078b495420191011194108bim.jsonz',
+        'Fl3203020001224834c9b82c11e9b911213bd490e29120191011231238bim.jsonz',
+        'Fl32030200014b32730bb82c11e9b911e70ac73db3d520191001021358bim.jsonz',
+        'Fl3203020001a29af72ee44211e9954245190612ff2120191011184403bim.jsonz',
+        'Fl3203020001110346f8b82c11e9b91193bb5caf414f20191011231407bim.jsonz',
+        'Fl32030200011c74da7db82d11e9b911153be4336a1320191011193846bim.jsonz',
+        'Fl3203020001ea88d037b82b11e9b91165a8f4d67d7f20191011184556bim.jsonz',
+        'Fl3203020001f19ae48be38b11e995427107eaf662ac20191009084145bim.jsonz',
+        'Fl32030200010e5874e3e97e11e99ae48398da7062f220191008120205bim.jsonz',
+        'Fl321023000111978428ddcc11e99e54178307d0c26720190924114916bim.jsonz',
+        'Fl32102300012906d079ddcc11e99e54ed7a9709490320190923170801bim.jsonz',
+        'Fl3210230001e2e44147ddcb11e99e54859c4c487f7220190923170824bim.jsonz',
+        'Fl330108000103044151bed44f7598d0e442f2f97c2e20181205121637bim.jsonz',
+        'Fl3301080001d660e6513bf241efbf0039a38d41959320181205121634bim.jsonz',
+        'Fl330108000132de58189884406e87c67054015b8ed020181205121650bim.jsonz',
+        'Fl33010800013fbaeba32e3843a48f9483c89f9e92e120181206034333bim.jsonz',
+        'Fl33010800013f801891979f4c15becd5eebf5eae9cd20181205121647bim.jsonz',
+        'Fl42010500013ed500a0dce811e8a553553e376f6dfe20190803114640bim.jsonz',
+        'Fl42010500012ca5c61ddcf511e8a5535bb85ffaee3b20190910175845bim.jsonz',
+        'Fl4201050001cb2aa6fbdced11e8a55303170283ca2920190912170100bim.jsonz',
+        'Fl4201050001b947f615dcf111e8a553b7cf52cf35af20190912170028bim.jsonz',
+        'Fl420105000110be38e9dcf511e8a5532b791a1ee2c420190910175947bim.jsonz',
+        'Fl42010500018e478ab3dcd811e88790bdbb92e7fee120190603191648bim.jsonz',
+        'Fl4201050001077f36addce111e8a5534ded040d5d7c20190603191658bim.jsonz',
+        'Fl420105000152e79b7adce211e8a55337c9cf1e3bdf20190717152852bim.jsonz',
+        'Fl42010500010495727bdce311e8a5539d686e463b9120190717152934bim.jsonz',
+        'Fl42010500012298db9cdce311e8a5534d128a2b354f20190803114429bim.jsonz',
+        'Fl4201050001cf1cad1ddce311e8a553934d1b04c91820190803114512bim.jsonz',
+        'Fl4201050001d4f1ea8fdce711e8a55335c5dd75d7b320190803114559bim.jsonz',
+        'Fl42010500015ecaeaf1dce811e8a553ab01e573104520190803114726bim.jsonz',
+        'Fl420105000189c43312dce811e8a5530301735c51a020190803114808bim.jsonz',
+        'Fl4201050001afd0f3e3dce811e8a553f5b22da96b1b20190803114831bim.jsonz',
+        'Fl420105000103457586dcf211e8a553531a211276f820190910175633bim.jsonz',
+        'Fl42010500017108cf60dcee11e8a55391554ae262a520190912170227bim.jsonz',
+        'Fl420105000119b7c08edcee11e8a553abe8a598be9320190912170132bim.jsonz',
+        'Fl42010500016dc07b43dcf111e8a553e7c23f5c005c20190803114853bim.jsonz',
+        'Fl42010500018b580334dcf111e8a553db1eadfac99320190803114958bim.jsonz',
+        'Fl42010500013b806f0fdcee11e8a553edb14706cbae20190912170155bim.jsonz',
+        'Fl42010500015f8ce4eddcf411e8a5532f436ae9c16120190910175756bim.jsonz',
+        'Fl420105000187b9a94fdcf511e8a553f74f3c6c70e020190910175919bim.jsonz',
+        'Fl420105000127246764dcf711e8a55349b04e56bcfc20190715180639bim.jsonz',
+        'Fl420105000189701916dda411e8a553593d715bd0c020190726104402bim.jsonz',
+        'Fl4201050001b3a83417dda411e8a5536fdeea00e31920190529111322bim.jsonz',
+        'Fl4201050001cbec83a8dda411e8a553e9d5e46989b220190708172234bim.jsonz',
+        'Fl42010500011ce3d777626a11e9b1b401e6e3ff79df20190529111305bim.jsonz',
+        'Fl4201050001d82483b0dcf511e8a553356fcf1dd57720190910175713bim.jsonz',
+        'Fl4403040012c38b2d7981b611e9a64d2f8df58163fa20190823180122bim.jsonz',
+        'Fl4403040012ef96cffb81b611e9a64d0552bb0a85ab20190924101419bim.jsonz',
+        'Fl4403040012d9485cfa81b611e9a64d11ceb052822320190718175437bim.jsonz',
+        'Fl4403040012a3c5a1f881b611e9a64d2d7ef600a17b20190823180142bim.jsonz',
+        'Fl440304001239f96f4581b611e9a64d43a752acf96c20190905154149bim.jsonz',
+        'Fl44030400122e5e48de81b711e9a64dbbdec755c07c20190815142831bim.jsonz',
+        'Fl44030400125ba87b4681b611e9a64dbf3a1838393b20190823180229bim.jsonz',
+        'Fl44030400124f295d7f81b711e9a64d0314bee18a1720190817152204bim.jsonz',
+        'Fl44030400120337881c81b711e9a64d5908c65ec0ab20190823142759bim.jsonz',
+        'Fl44030400127b7a466181b711e9a64d558931e17c6e20190712120444bim.jsonz',
+        'Fl44030400121842578d81b711e9a64dad63b66e0c2f20190823142746bim.jsonz',
+        'Fl440304001261be991081b711e9a64d5f6f04bcc34e20190823142737bim.jsonz',
+        'Fl44030400127ab7880781b611e9a64d0d6ad5abbd1520190920162746bim.jsonz',
+        'Fl441900000531d1a578b82e48a1b6a4dcfced63bdc020191001101716bim.jsonz',
+        'Fl44190000058cf94fefd42648609c305693f88e076620190930175443bim.jsonz',
+        'Fl4419000005b98bb7a9d85840b39f56a8fe69e2741620190930175456bim.jsonz',
+        'Fl4419000005d99cddf5561e4ffc942e5a7428cad9c120191001101653bim.jsonz',
+        'Fl44190000058ed0b0e0964549e4aa9c2f75e71537e820191011145844bim.jsonz',
+        'Fl4419000005eef95195db6c4531b410974040cf5f4a20191001101610bim.jsonz',
+        'Fl4419000005fcd5559503354eb19b84cbc71187f99c20191001101729bim.jsonz',
+        'Fl110108000100100320190228022700bim.jsonz',
+        'Fl110108000100100620190228022706bim.jsonz',
+        'Fl110108000100100720190228022708bim.jsonz',
+        'Fl110108000100100820190228022709bim.jsonz',
+        'Fl110108000100100220190228022658bim.jsonz',
+        'Fl110108000100100120190228022656bim.jsonz',
+        'Fl110108000100100420190228022702bim.jsonz',
+        'Fl110108000100100520190301095138bim.jsonz'
+      ]
+    }
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId', 'userId', 'secret'])
+  },
+  methods: {
+    // 初始化
+    init() {
+      this.getBuilding();
+      // this.getTypes()
+    },
+    // 获取图实例关系
+    getGraphy() {
+      getGraphyId({
+        type: "ElementSptoSpace",
+        ProjId: this.projectId,
+        secret: this.secret
+      }).then(res => {
+        if (res.data.Result == "success") {
+          this.graphyId = res.data.graph_id;
+          this.tabsList.map(t => {
+            this.getHasSpace(t.Code, t.Rel_type);
+          })
+        }
+      })
+    },
+    // 查询元空间
+    querySi() {
+      let pa = {
+        data: {
+          Filters: `FloorId='${this.buildFloorSelectd[1]}'`,
+          PageSize: 1000
+        },
+        zone: 'Ispace'
+      }
+      queryZone(pa, res => {
+        this.allSiListMap = {}
+        res.Content.map(t => {
+          let arr = t.BIMID.split(":");
+          this.allSiListMap[t.RoomID] = arr[1];
+        })
+        console.log(this.allSiListMap)
+        this.updateSiOutline();
+      })
+    },
+    // 获取业务空间与元空间的关系
+    getRelationInSpSi(Code, Reltype, list) {
+      let pa = {
+        criterias: { criterias: [] },
+        ProjId: this.projectId,
+        secret: this.secret
+      }
+      list.map(t => {
+        pa.criterias.criterias.push({
+          to_id: t,
+          graph_id: this.graphyId,
+          rel_type: Reltype
+        })
+      })
+      getRelation(pa).then(res => {
+        let relList = []
+        list.map((item, index) => {
+          let children = res.data.Content[index].Content.map(i => {
+            if (!!i) {
+              return i.from_id;
+            } else {
+              return undefined;
+            }
+          });
+          relList.push({
+            id: item,
+            children: children
+          });
+        });
+        this.importOutline(Code, relList)
+      })
+    },
+    // 获取项目下建筑
+    getBuilding() {
+      let pa = {
+        Cascade: [{ name: 'floor', Orders: 'SequenceId desc' }],
+        Orders: "BuildLocalName asc",
+      }
+      buildingQuery(pa, res => {
+        this.options = res.Content.map(t => {
+          if (t.Floor) {
+            t.Floor = t.Floor.map(item => {
+              item.BuildID = item.FloorID;
+              item.BuildLocalName = item.FloorLocalName;
+              this.floorIdToMap[item.FloorID] = item.StructureInfo ? item.StructureInfo.FloorMap : ''
+              return item;
+            })
+            console.log(this.floorIdToMap)
+          } else {
+            t.Floor = []
+          }
+          return t;
+        })
+      })
+    },
+    // 切换楼层
+    changeCascader() {
+      this.getJson(this.floorIdToMap[this.buildFloorSelectd[1]])
+    },
+    // 获取tabs的列表
+    getTypes() {
+      let pa = {
+        Filters: `parentId = 'Space'`
+      }
+      queryDictionaryHead(pa, res => {
+        this.tabsList = res.Content.map(t => {
+          if (t.Name == "元空间") {
+            return undefined;
+          }
+          return t;
+        }).filter(item => item);
+      })
+    },
+    // 更新业务空间的轮廓线
+    importOutline(Code, relList) {
+      let pa = {
+        data: {
+          Content: [],
+          Projection: ['Outline', 'Height']
+        },
+        zone: Code
+      }
+      relList.map(t => {
+        let obj = {
+          RoomID: t.id,
+          Height: 0,
+          Outline: []
+        }
+        t.children.map(item => {
+          if (this.sourceIdToOutline[this.allSiListMap[item]]) {
+            obj.Outline.push(this.sourceIdToOutline[this.allSiListMap[item]]);
+            if (this.sourceIdToHeight[this.allSiListMap[item]] && (obj.Height == 0 || this.sourceIdToHeight[this.allSiListMap[item]] < obj.Height)) {
+              obj.Height = this.sourceIdToHeight[this.allSiListMap[item]] / 1000;
+            }
+          }
+        })
+        pa.data.Content.push(obj);
+      })
+      updateZone(pa, res => {
+        this.$message.success(`success-----${Code}`)
+      })
+    },
+    // 查询绑定了元空间的业务空间
+    getHasSpace(Code, Reltype) {
+      let param = {
+        data: {
+          criteria: {
+            id: this.buildFloorSelectd[1],
+            type: [Code],
+            "include": [ // 可选, 只查询指定图/关系中的对象
+              {
+                "graphId": this.graphyId,
+                "graphType": Code,
+                "relType": Reltype,
+                "side": "toId",
+              }
+            ]
+          },
+        },
+        ProjId: this.projectId,
+        secret: this.secret
+      }
+      getBussines2(param).then(res => {
+        if (res.data.Result == "success") {
+          if (res.data.Content && res.data.Content.length) {
+            let relationList = res.data.Content.map(item => {
+              return item.id;
+            });
+            this.getRelationInSpSi(Code, Reltype, relationList);
+          }
+        }
+      })
+    },
+    // 获取底图
+    getJson(jsonId) {
+      axios({
+        method: 'get',
+        url: `/image-service/common/file_get?systemId=revit&key=${jsonId}`,
+        data: {},
+        responseType: 'blob',
+      }).then(res => {
+        let data = null
+        let blob = res.data;
+        let reader = new FileReader();
+        reader.readAsBinaryString(blob)
+        let _this = this
+        reader.onload = function (readerEvt) {
+          let binaryString = readerEvt.target.result;
+          let base64Data = btoa(binaryString)
+          let unGzipData = pako.unzip(base64Data)
+          // data = unGzipData
+          data = unGzipData.entityList ? unGzipData.entityList[0].Elements : unGzipData.EntityList[0].Elements
+          if (data.Spaces && data.Spaces.length) {
+            data.Spaces.map(t => {
+              _this.sourceIdToOutline[t.SourceId] = t.OutLine;
+              _this.sourceIdToHeight[t.SourceId] = t.Height;
+            })
+            // }
+            // if (data.SpaceList && data.SpaceList.length) {
+            //   data.SpaceList.map(items => {
+            //     _this.sourceIdToOutline[items.BimId] = items.Paths;
+            //   });
+          } else {
+            _this.$message("没有元空间数据")
+          }
+          console.log(_this.sourceIdToOutline)
+          _this.querySi();
+        };
+      });
+    },
+    updateSpOutline() {
+      this.getGraphy();
+    },
+    updateSiOutline() {
+      let pa = {
+        data: {
+          Content: [],
+          Projection: ['Outline', 'Height']
+        },
+        zone: 'Ispace'
+      }
+      for (let key in this.allSiListMap) {
+        let obj = {
+          RoomID: key,
+          Outline: []
+        }
+        if (this.sourceIdToOutline[this.allSiListMap[key]]) {
+          obj.Outline = this.sourceIdToOutline[this.allSiListMap[key]];
+          obj.Height = this.sourceIdToHeight[this.allSiListMap[key]] / 1000 || 0;
+          pa.data.Content.push(obj);
+        }
+      }
+      if (pa.data.Content.length) {
+        updateZone(pa, res => {
+          this.$message.success(`success-----Ispace`)
+        })
+      }
+    }
+  },
+  created() {
+    this.init()
+  },
+  watch: {
+    projectId() {
+      this.init()
+    }
+  }
+}
+</script>

+ 0 - 0
src/views/data_admin/buildTask/addTask/addAssetsTask.vue


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