zhangyu 5 lat temu
rodzic
commit
79c1333ec0
76 zmienionych plików z 4951 dodań i 1604 usunięć
  1. 4 2
      config/dev.env.js
  2. 6 4
      config/prod.env.js
  3. 6 4
      package.json
  4. 13 3
      src/api/model/file.js
  5. 9 1
      src/api/scan/config.js
  6. 169 0
      src/api/scan/request.js
  7. 5 1
      src/assets/scss/point/point_config/reset.scss
  8. 0 261
      src/assets/style/iconfont/iconfont.css
  9. BIN
      src/assets/style/iconfont/iconfont.eot
  10. 0 209
      src/assets/style/iconfont/iconfont.svg
  11. BIN
      src/assets/style/iconfont/iconfont.ttf
  12. BIN
      src/assets/style/iconfont/iconfont.woff
  13. 6 0
      src/assets/style/style.scss
  14. 96 99
      src/components/business_space/business/handsontable.vue
  15. 272 0
      src/components/business_space/newAddDialogs/addEquipDialog.vue
  16. 111 0
      src/components/business_space/newAddDialogs/addSystemDialog.vue
  17. 150 0
      src/components/business_space/newGraphy/canvasFun.vue
  18. 34 0
      src/components/business_space/newGraphy/createBSP.vue
  19. 613 0
      src/components/business_space/newGraphy/graphy.vue
  20. 67 0
      src/components/business_space/newGraphy/unRelateBSP.vue
  21. 172 0
      src/components/business_space/newTables/eqToSpaceTable.vue
  22. 135 0
      src/components/business_space/newTables/syInSpaceTable.vue
  23. 1 1
      src/components/business_space/table/addEquip.vue
  24. 1 1
      src/components/business_space/table/businessTable.vue
  25. 179 0
      src/components/ledger/cenote/dialog/addCenoteDialog.vue
  26. 187 0
      src/components/ledger/cenote/dialog/addEquipDialog.vue
  27. 147 0
      src/components/ledger/cenote/dialog/addSystemDialog.vue
  28. 155 0
      src/components/ledger/cenote/table/cenoteTable.vue
  29. 143 0
      src/components/ledger/cenote/table/deviceTable.vue
  30. 145 0
      src/components/ledger/cenote/table/systemTable.vue
  31. 61 16
      src/components/ledger/handsontables/assets.vue
  32. 128 41
      src/components/ledger/handsontables/device.vue
  33. 49 4
      src/components/ledger/handsontables/system.vue
  34. 319 0
      src/components/ledger/lib/linkassets.vue
  35. 2 1
      src/components/model/file/addFloorDialog.vue
  36. 45 69
      src/components/model/file/floorTable.vue
  37. 1 1
      src/components/point/dynamicdata/equipRules.vue
  38. 1 1
      src/components/point/dynamicdata/partsRules.vue
  39. 1 1
      src/components/point/dynamicdata/spaceRules.vue
  40. 1 1
      src/components/point/dynamicdata/systemRules.vue
  41. 1 1
      src/components/ready/buildfloor/formItems.vue
  42. 151 0
      src/framework/components/messagesever/index.vue
  43. 9 0
      src/framework/components/messagesever/mqSetting.js
  44. 22 0
      src/framework/components/messagesever/msmq.js
  45. 14 6
      src/framework/layout/PageHeader.vue
  46. 8 28
      src/framework/layout/layout-store.js
  47. 10 0
      src/framework/style/layout.scss
  48. 27 6
      src/router/system.js
  49. 0 2
      src/store/index.js
  50. 3 3
      src/store/modules/alarm.js
  51. 0 29
      src/store/modules/proMess.js
  52. 2 0
      src/utils/bus.js
  53. 12 2
      src/utils/handsontable/fillterField.js
  54. 3 6
      src/utils/handsontable/notShow.js
  55. 3 3
      src/views/data_admin/buildAssets/index.vue
  56. 140 0
      src/views/ledger/cenotelist/cenoteDetail/index.vue
  57. 6 6
      src/views/ledger/cenotelist/cenoteadd/index.vue
  58. 69 3
      src/views/ledger/cenotelist/index.vue
  59. 7 9
      src/views/ledger/facility/addfacility.vue
  60. 294 0
      src/views/ledger/facility/batchlink.vue
  61. 21 8
      src/views/ledger/facility/index.vue
  62. 7 9
      src/views/ledger/property/addproperty.vue
  63. 54 5
      src/views/ledger/rentlist/index.vue
  64. 6 6
      src/views/ledger/rentlist/rentadd/index.vue
  65. 161 332
      src/views/ledger/spacelist/index.vue
  66. 174 0
      src/views/ledger/spacelist/spaceDetail/index.vue
  67. 7 9
      src/views/ledger/system/addsystem.vue
  68. 59 91
      src/views/model/file/index.vue
  69. 1 1
      src/views/point/dynamicdata/index.vue
  70. 8 4
      src/views/ready/buildfloor/addFloor/index.vue
  71. 13 15
      src/views/ready/buildfloor/drawGraphy/checkGraphy.vue
  72. 136 75
      src/views/ready/buildfloor/drawGraphy/drawFloor.vue
  73. 0 112
      src/views/ready/buildfloor/drawGraphy/operateGraphyItem.vue
  74. 0 60
      src/views/ready/buildfloor/drawGraphy/repetitionGraphy.vue
  75. 18 18
      src/views/ready/buildfloor/index.vue
  76. 71 34
      src/views/ready/buildfloor/repetitionGraphy.vue

+ 4 - 2
config/dev.env.js

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

+ 6 - 4
config/prod.env.js

@@ -1,8 +1,10 @@
 'use strict'
 module.exports = {
     NODE_ENV: '"production"',
-    // BASE_URL: '"http://192.168.20.215"', //测试iframe地址
-    // SSO_SERVER: '"http://192.168.20.102:8080"' //(新)测试环境
-    BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
-    SSO_SERVER: '"http://sso.sagacloud.cn"'  //正式环境
+    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测试环境地址
+    // BASE_URL: '"http://mbi.sagacloud.cn"', //线上iframe地址
+    // SSO_SERVER: '"http://sso.sagacloud.cn"',  //正式环境
+    // MQTT_SERVICE: '""' //MQ正式环境地址
 }

+ 6 - 4
package.json

@@ -5,14 +5,15 @@
     "author": "yaoll <yaolinlin@sagacloud.cn>",
     "private": true,
     "scripts": {
+        "i": "npm install",
         "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
         "start": "npm run dev",
         "build": "node build/build.js"
     },
     "dependencies": {
-        "@sybotan-web/base": "2.0.54",
-        "@sybotan-web/draw": "2.0.128",
-        "@sybotan-web/graphy": "2.0.93",
+        "@sybotan-web/base": "2.1.5",
+        "@sybotan-web/draw": "2.1.56",
+        "@sybotan-web/graphy": "2.1.27",
         "axios": "^0.18.0",
         "echarts": "^4.1.0",
         "element-ui": "^2.11.0",
@@ -23,7 +24,7 @@
         "vue-axios": "^2.1.4",
         "vue-router": "^3.0.1",
         "vuex": "^3.1.0",
-        "cad-engine": "2.0.56"
+        "cad-engine": "2.0.250"
     },
     "devDependencies": {
         "ajv": "^6.9.1",
@@ -58,6 +59,7 @@
         "sass-loader": "^7.1.0",
         "semver": "^5.3.0",
         "shelljs": "^0.7.6",
+        "stompjs": "^2.3.3",
         "swiper": "^4.0.0",
         "uglifyjs-webpack-plugin": "^1.1.1",
         "url-loader": "^0.5.8",

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

@@ -1,7 +1,8 @@
 import httputils from '@/api/scan/httpUtil'
 import { Message } from 'element-ui';
-const baseUrl = '/modelapi';
 import axios from 'axios'
+const baseUrl = '/modelapi';
+
 let api = {
     // 新建模型文件夹
     /**
@@ -119,6 +120,7 @@ let api = {
                                 FloorModelId: res.EntityList[0].Id, //模型所属楼层(FloorModel外键)
                                 ModelName: params.Form.file.name,        //模型文件名
                                 UserName: params.userName,
+                                UserId: params.userId,
                                 Note: params.Form.desc
                                 // ReplaceReason: 0
                             }]
@@ -150,6 +152,7 @@ let api = {
                             FloorModelId: res.Content[0].Id, //模型所属楼层(FloorModel外键)
                             ModelName: params.Form.file.name,        //模型文件名
                             UserName: params.userName,
+                            UserId: params.userId,
                             Note: params.Form.desc
                             // ReplaceReason: 0
                         }]
@@ -240,12 +243,13 @@ let api = {
         })
     },
     // 更新模型文件
-    upDateModelFile(data, ProjectId,UserName, callback1, callback2) {
+    upDateModelFile(data, ProjectId, UserName, UserId, callback1, callback2) {
         let modelFile = {
             Content: [{
                 FloorModelId:data.replaceModelItem.Id, //模型id
                 ModelName: data.Form.file.name,        //模型名字
                 UserName: UserName,
+                UserId: UserId,
                 Note: data.replaceModelItem.Note,
                 ReplaceReason: data.Form.ReplaceReason
             }]
@@ -278,4 +282,10 @@ let api = {
     }
 
 }
-export default api
+export default api
+
+//楼层与平面图绑定
+export function bindFloorModel(param, success) {
+    let url = `${baseUrl}/model-floor/bind`;
+    httputils.postJson(url, param, success)
+}

+ 9 - 1
src/api/scan/config.js

@@ -9,5 +9,13 @@ export const zone = {
   PowerSupplyZone: 'zone-power-supply', //供电分区
   LightingZone: 'zone-lighting', //照明分区
   AirConditioningZone: 'metaspace', //空调分区
-  TenantZone: 'zone-tenant' //租赁分区
+  TenantZone: 'zone-tenant', //租赁分区
+  HeatingZone:'zone-heating', //采暖分区
+  CleanZone:'zone-clean', //洁净分区
+  DomesticWaterSupplyZone:'zone-domestic-water', //生活给水分区
+  NetworkZone:'zone-network', //网络分区
+  FunctionZone:'zone-function', //功能分区
+  FireZone:'zone-fire', //防火分区
+  SecurityZone:'zone-security', //安防分区
+  Ispace:'ispace', //元空间
 }

+ 169 - 0
src/api/scan/request.js

@@ -735,6 +735,12 @@ export function getCenoteTableData(param, success) {
     http.postJson(url, param, success)
 }
 
+//查询竖井信息
+export function queryCenoteTableData(param, success) {
+    let url = `${baseUrl}/datacenter/shaft/query`
+    http.postJson(url, param, success)
+}
+
 //添加竖井信息
 export function createCenoteTableData(param, success) {
     let url = `${baseUrl}/datacenter/shaft/create`
@@ -943,6 +949,19 @@ export function queryEquip(param, success) {
     http.postJson(url, param, success)
 }
 
+//查询项目下的设备或部件-根据项目、建筑、楼层、设备或部件分类、业务空间实例筛选设备 然后通过计算匹配资产
+export function equipCategoryProperty(param, success) {
+    let url = `${baseUrl}/equip-component/equip-query/equip-category-property?category=${param.category}${param.spaceIdList?param.spaceIdList:''}`;
+    let data = param.data;
+    http.postJson(url, data, success)
+}
+
+//批量添加设备和资产的关系
+export function equipRproperty(param, success) {
+    let url = `${baseUrl}/equip-component/equip-query/equip-r-property`;
+    http.postJson(url, param, success)
+}
+
 //创建资产所需(Family族id3位编码)-根据设备类型(4位编码)或部件类型(6位编码)查询
 export function getEquipBelongs(param, success) {
     let url = `${baseUrl}/datacenter/data-dictionary/family-query`;
@@ -974,6 +993,12 @@ export function queryPartsDie(param, success) {
     http.postJson(url, param, success)
 }
 
+//查询项目下设备或部件的类别、以及名称
+export function TypePartsDie( success) {
+    let url = `${baseUrl}/equip-component/equip-query/equip-compon-category`;
+    http.getJson(url, {}, success)
+}
+
 //根据条件查询项目下设备部件数量
 export function countPartsDie(param, success) {
     let url = `${baseUrl}/equip-component/equip-query/count`;
@@ -1160,12 +1185,24 @@ export function floorQuery(param, success) {
     http.postJson(url, param, success)
 }
 
+//查询楼层信息+sign
+export function floorQueryAndSign(param, success) {
+    let url = `${baseUrl}/equip-component/floor/query`;
+    http.postJson(url, param, success)
+}
+
 //查询建筑信息
 export function buildingQuery(param, success) {
     let url = `${baseUrl}/datacenter/building/query`;
     http.postJson(url, param, success)
 }
 
+//查询建筑信息+count
+export function buildingQueryAndCount(param, success) {
+    let url = `${baseUrl}/equip-component/building/query`;
+    http.postJson(url, param, success)
+}
+
 //创建分区信息
 export function createZone(param, success) {
     let data = param.data
@@ -1194,6 +1231,13 @@ export function updateZone(param, success) {
     http.postJson(url, data, success)
 }
 
+//根据条件查询统计数量
+export function countZone(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/datacenter/${zone[param.zone]}/count`;
+    http.postJson(url, data, success)
+}
+
 //动态数据关联-查询对应关系(删除提示页)
 export function dynamicQueryPrompt(param, success) {
     let url = `${baseUrl}/pointconfig/dynamic/query-prompt`;
@@ -1246,3 +1290,128 @@ export function floorUpdate(param, success) {
     http.postJson(url, param, success)
 }
 
+/****关系-竖井****/
+//字典查询接口 竖井所有类型
+export function queryShaftType(success) {
+    let url = `${baseUrl}/datacenter/data-dictionary/query-shaft-type`;
+    http.getJson(url, {}, success)
+}
+//根据对象删除设备所在竖井关系,只针对一个对象
+export function eqinshUnlink(param, success) {
+    let url = `${baseUrl}/datacenter/eq-in-sh/unlink`;
+    http.postJson(url, param, success)
+}
+//根据对象删除系统所在竖井关系,只针对一个对象
+export function syinshUnlink(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sh/unlink`;
+    http.postJson(url, param, success)
+}
+//根据对象删除竖井的贯通关系,只针对一个对象
+export function shthroughshUnlink(param, success) {
+    let url = `${baseUrl}/datacenter/sh-through-sh/unlink`;
+    http.postJson(url, param, success)
+}
+//查询没有和当前竖井绑定的设备
+export function unshaftInEq(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/equip-component/shaft/unshaft-in-eq?shaftId=${param.shaftId}`;
+    http.postJson(url, data, success)
+}
+//查询没有和当前竖井贯通的其它竖井
+export function unshaftThroughShaft(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/equip-component/shaft/unshaft-through-shaft?shaftId=${param.shaftId}`;
+    http.postJson(url, data, success)
+}
+//查询没有和当前竖井绑定的系统
+export function unshaftInSys(param, success) {
+    let data = param.data
+    let url = `${baseUrl}/equip-component/shaft/unshaft-in-sys?shaftId=${param.shaftId}`;
+    http.postJson(url, data, success)
+}
+//设备所在的竖井,竖井一对多,此方不会覆盖以前的记录,累计添加
+export function linkEqSh(param, success) {
+    let url = `${baseUrl}/datacenter/eq-in-sh/link-eq-sh`;
+    http.postJson(url, param, success)
+}
+//竖井的贯通,竖井一对多,此方法不会覆盖以前的记录
+export function linkShaft(param, success) {
+    let url = `${baseUrl}/datacenter/sh-through-sh/link-shaft`;
+    http.postJson(url, param, success)
+}
+//系统所在的竖井,竖井一对多,累计添加,此方法不会覆盖以前记录
+export function linkSySh(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sh/link-sy-sh`;
+    http.postJson(url, param, success)
+}
+
+//关系-----设备所在业务空间--删除关系
+export function eqInSpaceDelete(param, success) {
+    let url = `${baseUrl}/datacenter/eq-in-sp-base/unlink-list?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----设备所在业务空间--创建关系
+export function eqInSpaceCreate(param, success) {
+    let url = `${baseUrl}/datacenter/eq-in-sp-base/link-eq-sp?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----设备服务业务空间--删除关系
+export function eqForSpaceDelete(param, success) {
+    let url = `${baseUrl}/datacenter/eq-for-sp-base/unlink-list?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----设备服务业务空间--创建关系
+export function eqForSpaceCreate(param, success) {
+    let url = `${baseUrl}/datacenter/eq-for-sp-base/link-eq-sp?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----系统所在业务空间--删除关系
+export function syInSpaceDelete(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sp-base/unlink-list?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----系统所在业务空间--创建关系
+export function syInSpaceCreate(param, success) {
+    let url = `${baseUrl}/datacenter/sy-in-sp-base/link-sp-sys?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----没有和当前空间绑定的设备
+export function notEqInSpaceQuery(param, success) {
+    let url = `${baseUrl}/equip-component/space/unspace-in-eq?type=${param.type}&spaceId=${param.spaceId}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----未服务当前空间的设备
+export function notEqForSpaceQuery(param, success) {
+    let url = `${baseUrl}/equip-component/space/unspace-for-eq?type=${param.type}&spaceId=${param.spaceId}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----没有和当前空间绑定的系统
+export function notSyInSpaceQuery(param, success) {
+    let url = `${baseUrl}/equip-component/space/unspace-in-sys?type=${param.type}&spaceId=${param.spaceId}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----空间内没有和空间关联的设备 根据坐标计算(专用接口)
+export function getEqNotInSpace(param, success) {
+    let url = `${baseUrl}/equip-component/space/unspace-fIn-eq-point?spaceId=${param.spaceId}&type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----空间内没有服务空间的设备 根据坐标计算(专用接口)
+export function getEqNotForSpace(param, success) {
+    let url = `${baseUrl}/equip-component/space/unspace-for-eq-point?spaceId=${param.spaceId}&type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----未关联业务空间的元空间
+export function getIspNotInSpace(param, success) {
+    let url = `${baseUrl}/equip-component/space/unspace-ispace?objectType=${param.objectType}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----业务空间内的元空间,业务空间一对多,累计添加会覆盖以前记录
+export function createRelateInZoneAndISp(param, success) {
+    let url = `${baseUrl}/datacenter/si-in-sp-base/link-sp?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}
+//关系-----业务空间内的元空间,创建业务空间内的元空间关系, 累计添加不会覆盖-批量关联
+export function groupCreRelaZoneAndISp(param, success) {
+    let url = `${baseUrl}/datacenter/si-in-sp-base/link-list?type=${param.type}`;
+    http.postJson(url, param.data, success)
+}

+ 5 - 1
src/assets/scss/point/point_config/reset.scss

@@ -365,7 +365,7 @@ button,
 input,
 select,
 textarea {
-    font-family: tahoma, Helvetica, Arial, "\5FAE\8F6F\96C5\9ED1";
+    font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif, "\5FAE\8F6F\96C5\9ED1";
     *font-family: "\5FAE\8F6F\96C5\9ED1";
 }
 
@@ -478,4 +478,8 @@ input::-webkit-inner-spin-button {
 }
 input[type="number"]{
     -moz-appearance: textfield;
+}
+
+canvas:focus{
+    outline: none;
 }

Plik diff jest za duży
+ 0 - 261
src/assets/style/iconfont/iconfont.css


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


Plik diff jest za duży
+ 0 - 209
src/assets/style/iconfont/iconfont.svg


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


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


+ 6 - 0
src/assets/style/style.scss

@@ -1,3 +1,9 @@
+body{
+    /deep/ .el-notification.right{
+        text-align: left;
+    }
+}
+
 .icon-wushuju {
     display: block;
     width: 100px;

+ 96 - 99
src/components/business_space/business/handsontable.vue

@@ -1,6 +1,6 @@
 <template>
   <div id="handsontable" v-loading="isLoading">
-		<el-row class="left">
+    <el-row class="left">
       <el-select v-model="onlyRead" @change="getData(false)" style="width:100px;margin-right:20px;vertical-align:bottom;">
         <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
       </el-select>
@@ -8,8 +8,8 @@
         <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
       </el-select>
       <el-button v-show="!onlyRead" @click="addSp">添加</el-button>
-			<el-button @click="reset">刷新</el-button>
-			<el-button v-show="!onlyRead" @click="undo">撤销</el-button>
+      <el-button @click="reset">刷新</el-button>
+      <el-button v-show="!onlyRead" @click="undo">撤销</el-button>
     </el-row>
     <div v-show="main &&main.length" :id="id"></div>
     <div class="center" v-show="!main || !main.length" style="height: 400px;padding-top:140px;box-sizing:border-box;">
@@ -17,9 +17,9 @@
       暂无数据
     </div>
     <!-- <add-business :buildMess="buildMess" :dialog="dialog"></add-business> -->
-    <el-pagination class="right" v-show="main && main.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 class="right" v-show="main && main.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 class="right" v-show="main && main.length">
       <my-pagination :page="page" @change="pageChange"></my-pagination>
@@ -45,12 +45,8 @@ import { queryZone, updateZone, deleteZone, createZone, BeatchQueryParam } from
 import { mapGetters, mapActions } from "vuex";
 export default {
   props: {
-    id: {
-      type: String
-		},
-		zoneObj: {
-			type: Object
-		}
+    id: {},
+    zoneCode: {}
   },
   components: {
     qrcode, //二维码页面
@@ -58,11 +54,11 @@ export default {
     addBusiness
   },
   computed: {
-		...mapGetters("layout", ["projectId", "secret", "userId"]),
-		showTypes () {
-      return this.onlyRead?
-        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]: 
-        [{value: "partInfo", label: '隐藏信息点'}, {value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'} ]
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+    showTypes() {
+      return this.onlyRead ?
+        [{ value: "Visible", label: '只看采集信息' }, { value: "all", label: '全部' }] :
+        [{ value: "partInfo", label: '隐藏信息点' }, { value: "all", label: '全部' }]
     }
   },
   data() {
@@ -76,15 +72,15 @@ export default {
       main: [],
       hot: null,
       isLoading: true,
-			options: [{
+      options: [{
         value: true,
         label: '只读模式'
       }, {
         value: false,
         label: '编辑模式'
       }],
-			onlyRead: true,
-			showType: "",
+      onlyRead: true,
+      showType: "",
       page: {
         pageSize: 50,
         pageSizes: [10, 20, 50, 100],
@@ -99,7 +95,6 @@ export default {
       buildMess: null,
       filtersArr: [], //表格数据被过滤后的下标
       copyMain: [], //深拷贝数组
-      activeType: {}
     };
   },
   created() {
@@ -113,43 +108,39 @@ export default {
       this.param.secret = this.secret
     },
     //获取表头
-    getHeader(headers, activeTabType) {
+    getHeader(headers, buildFloorSelectd) {
       this.headers = headers
-      this.activeType = activeTabType
+      this.buildFloorSelectd = buildFloorSelectd
+      this.getData()
     },
-    getData(buildMess) {
+    getData() {
       this.isLoading = true
-      if (buildMess) {
-        this.buildMess = buildMess
-			}
       let params = {
-				zone: this.zoneObj.code,
-				data: {
-					Filters: ``,
-					Orders: "createTime desc, RoomID asc",
-					PageNumber: this.page.pageNumber,
-					PageSize: this.page.pageSize
-				}
-			}
-			if (this.buildMess.selectd && this.buildMess.selectd[0] && this.buildMess.selectd[1]) {
-				params.data.Filters = `BuildingId='${this.buildMess.selectd[0]}';FloorId='${this.buildMess.selectd[1]}'`
-			} else if (this.buildMess.selectd && this.buildMess.selectd[0] && !this.buildMess.selectd[1]) {
-				params.data.Filters = `BuildingId='${this.buildMess.selectd[0]}'`
-			} else {
-				params.data.Filters = `BuildingId='';FloorId=''`
-			}
-			queryZone(params, res => {
-				this.page.total = res.Total
-				this.main = res.Content
-				if (this.main && this.main.length && this.main[0].RoomID) {
+        zone: this.zoneCode,
+        data: {
+          Filters: ``,
+          Orders: "createTime desc, RoomID asc",
+          PageNumber: this.page.pageNumber,
+          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]}'`
+      }
+      // else if (buildFloorSelectd.length && buildFloorSelectd[0] && !buildFloorSelectd[1]) {
+      //   params.data.Filters = `BuildingId='${buildFloorSelectd[0]}'`
+      // } else {
+      //   params.data.Filters = `BuildingId='';FloorId=''`
+      // }
+      queryZone(params, res => {
+        this.page.total = res.Total
+        this.main = res.Content
+        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()
-			})
+        this.getMain()
+      })
     },
     //获取表格主体内容
     getMain() {
@@ -163,7 +154,6 @@ export default {
     },
     //初始化handsontable组件
     initHot() {
-      let id = this.id
       var container = document.getElementById(this.id);
       let winHeight = document.documentElement.clientHeight;
       this.hot = new Handsontable(container, {
@@ -171,6 +161,7 @@ export default {
         colHeaders: this.delHeader(this.headers), //表头文案
         columns: this.getType(this.headers), //数据显示格式
         filters: true,
+        fixedColumnsLeft: 4,
         maxRows: this.main.length,
         height: winHeight - 100 - 50 - 176,
         columnSorting: true, //添加排序
@@ -232,7 +223,10 @@ export default {
     getInfors(infos, row) {
       let val = this.hot.colToProp(row.col);
       if (val == "point") {
-        this.$emit("lookEqu", infos);
+        this.$router.push({
+          path: "/ledger/spaceDetail",
+          query: { RoomID: infos.RoomID, zone: this.zoneCode, isMyTab: 2 }
+        })
       } else if (val == "RoomQRCode") {
         this.qrcodeUrl = this.main[row.row].RoomQRCode
         if (!!this.qrcodeUrl) {
@@ -246,7 +240,7 @@ export default {
     },
     //表格发生更改
     tdChange(changeData, source) {
-			if (!this.onlyRead) {
+      if (!this.onlyRead) {
         if (changeData) {
           let trimmedArr = this.trimmedRows();
           let param = handsonUtils.getParam(changeData, source, this.hot, trimmedArr);
@@ -272,17 +266,17 @@ export default {
     },
     //右键删除
     romoveFm() {
-			let params = tools.differenceArr(this.main, this.copyMain)
+      let params = tools.differenceArr(this.main, this.copyMain)
       if (params.length < 1 || this.main > this.copyMain) {
         return
       }
       let param = {
-				data: [],
-				zone: this.zoneObj.code
-			}
+        data: [],
+        zone: this.zoneCode
+      }
       params.map(item => {
-        if(item.RoomID)
-        param.data.push({RoomID: item.RoomID})
+        if (item.RoomID)
+          param.data.push({ RoomID: item.RoomID })
       })
       this.$confirm("此操作将删除业务空间,是否继续?", "提示", {
         confirmButtonText: '确定',
@@ -290,9 +284,9 @@ export default {
         type: 'warning'
       }).then(() => {
         deleteZone(param, res => {
-					this.$message.success("删除成功!")
-        	this.getData()
-				})
+          this.$message.success("删除成功!")
+          this.getData()
+        })
       }).catch(() => {
         this.getData()
         this.$message("取消删除")
@@ -302,7 +296,7 @@ export default {
     handleCreateZone(param) {
       let keys = Object.keys(param)
       keys.map((key) => { //将值为空字符串的属性删除
-        if(param[key] == "") {
+        if (param[key] == "") {
           delete param[key]
         }
       })
@@ -314,39 +308,41 @@ export default {
         this.$message("新添加业务空间内容不能为空!")
         return
       }
-      if (this.buildMess.selectd && this.buildMess.selectd[0] && this.buildMess.selectd[1]) {
-        param.BuildingId = this.buildMess.selectd[0]
-        param.FloorId = this.buildMess.selectd[1]
-			} else if (this.buildMess.selectd && this.buildMess.selectd[0] && !this.buildMess.selectd[1]) {
-				param.BuildingId = this.buildMess.selectd[0]
-			}
+      if (this.buildFloorSelectd && this.buildFloorSelectd[0] && this.buildFloorSelectd[1]) {
+        param.BuildingId = this.buildFloorSelectd[0]
+        param.FloorId = this.buildFloorSelectd[1]
+      }
+      //  else if (this.buildMess.selectd && this.buildMess.selectd[0] && !this.buildMess.selectd[1]) {
+      //   param.BuildingId = this.buildMess.selectd[0]
+      // }
       let params = {
-        zone: this.zoneObj.code,
+        zone: this.zoneCode,
         data: {
           Content: [param]
         }
       }
-      createZone(params,(res) => {
+      createZone(params, res => {
         this.$message.success("添加成功!")
         this.getData()
       })
     },
     // 修改
     updateBusiness(data, change) {
-			let param = {
-				data: {
-					Content: [],
-        	Projection: []
-				},
-        zone: this.zoneObj.code
-      }, keyList = [];
+      let param = {
+        data: {
+          Content: [],
+          Projection: []
+        },
+        zone: this.zoneCode
+      };
+      let keyList = [];
       //生成要修改字段列表
       change.map((item) => {
         let key = item[1].split(".")[0]
-        if(item[1] && keyList.indexOf(key) == -1) {
+        if (item[1] && keyList.indexOf(key) == -1) {
           keyList.push(key)
         }
-        if(item[1] && item[3] == "" && param.data.Projection.indexOf(key) == -1) {
+        if (item[1] && item[3] == "" && param.data.Projection.indexOf(key) == -1) {
           param.data.Projection.push(key)
         }
       })
@@ -357,8 +353,9 @@ export default {
           tools.setDataForKey(item, value, itemData == "" ? null : itemData)
         })
         param.data.Content.push(item);
-			})
-			updateZone(param, (res) => {})
+      })
+      param.Projection = []
+      updateZone(param, (res) => { })
     },
     //获取被筛选掉的行号
     trimmedRows() {
@@ -470,21 +467,21 @@ export default {
      * @return 处理好的数据格式
      */
     getType(list) {
-			let arr = tools.copyArr(list)
-			let data = showTools.headerTypeFilter(arr, "space", this.onlyRead, this.showType)
+      let arr = tools.copyArr(list)
+      let data = showTools.headerTypeFilter(arr, "space", this.onlyRead, this.showType)
       data.unshift({
-        data: "hasSi",
+        data: "Outline",
         renderer: this.myRenderer,
         readOnly: true
       }, {
-				data: "point",
-				renderer: this.facilityRender,
-				readOnly: true
-			});
+        data: "point",
+        renderer: this.facilityRender,
+        readOnly: true
+      });
       return data;
     },
     myRenderer(instance, td, row, col, prop, value, cellProperties) {
-      if (value) {
+      if (value && value.length) {
         td.innerHTML = "已关联"
       } else {
         td.innerHTML = "未关联"
@@ -521,8 +518,8 @@ export default {
     undo() {
       this.hot.undo()
     },
-		/**  分页事件------------------------ */
-		//切换每页显示多少条数据
+    /**  分页事件------------------------ */
+    //切换每页显示多少条数据
     handleSizeChange(val) {
       this.page.pageSize = val
       this.getData()
@@ -537,8 +534,8 @@ export default {
     projectId() {
       this.setData()
       this.main = null
-		},
-		showTypes: {
+    },
+    showTypes: {
       handler(newName, oldName) {
         if (newName && newName[0] && newName[0].value) {
           this.showType = newName[0].value
@@ -554,10 +551,10 @@ export default {
 </script>
 <style lang="less" scoped>
 #handsontable {
-	.left{
-		padding-top: 0;
-		padding-bottom: 10px;
-	}
+  .left {
+    padding-top: 0;
+    padding-bottom: 10px;
+  }
   .no-data {
     height: 150px;
     line-height: 150px;

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

@@ -0,0 +1,272 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="addEqDialog">
+    <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-checkbox style="margin-left:10px;" @change="getTableData" v-model="showType" label="只显示在当前业务空间中的设备"></el-checkbox>
+      </el-col>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" 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="linkOtherSpace" label="已关联其他业务空间" 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)" 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>
+    <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 {
+  getSpaceEquip,
+  buildingQuery, //数据中心-建筑查询
+  notEqInSpaceQuery, //没有和当前空间绑定的设备
+  notEqForSpaceQuery, //未服务当前空间的设备
+  eqInSpaceCreate, //设备所在业务空间--创建关系
+  eqForSpaceCreate, //设备服务业务空间--创建关系
+  getEqNotInSpace, //空间内没有和空间关联的设备
+  getEqNotForSpace, //空间内没有服务空间的设备
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加设备",
+      keycode: '', //输入查询条件
+      options: [], //建筑楼层级联
+      floor: [], // 选中的建筑楼层
+      showType: false, //是否只显示在当前业务空间中的设备
+      inSpaceType: '设备',
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      props: { //自定义字段
+        value: "BuildID",
+        label: "BuildLocalName",
+        children: "Floor"
+      },
+    };
+  },
+  props: {
+    type: {}, //Equipment--EquipmentFor
+    spaceId: {},
+    zone: {}, //分区类型 
+  },
+  created() {
+    this.getBuilding();
+  },
+  methods: {
+    // 获取项目下建筑
+    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;
+              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: '未明确楼层' })
+      })
+    },
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true;
+      this.tableData = [];
+      this.getTableData();
+    },
+    // 获取列表数据
+    getTableData() {
+      let pa = {
+        data: {
+          Cascade: [{ Name: "equipCategory" }],
+          Filters: '',
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize,
+        },
+        type: this.zone,
+        spaceId: this.spaceId
+      }
+      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 += `;EquipName contain "${this.keycode}" or EquipLocalName contain "${this.keycode}" or EquipLocalID contain "${this.keycode}"`
+      }
+      if (pa.data.Filters == '') {
+        delete pa.data.Filters
+      }
+      console.log(this.showType)
+      if (this.showType) {
+        if (this.type == "Equipment") {
+          // pa.data.Cascade.push({ Name: "zoneSpaceInBase" })
+          delete pa.data.Cascade;
+          getEqNotInSpace(pa, res => {
+            this.getDataSuc(res, 'ZoneSpaceBaseIn')
+          })
+        } else {
+          // pa.data.Cascade.push({ Name: "zoneSpaceForBase" })
+          delete pa.data.Cascade;
+          getEqNotForSpace(pa, res => {
+            this.getDataSuc(res, 'ZoneSpaceBaseFor')
+          })
+        }
+      } else {
+        if (this.type == "Equipment") {
+          pa.data.Cascade.push({ Name: "zoneSpaceInBase" })
+          notEqInSpaceQuery(pa, res => {
+            this.getDataSuc(res, 'ZoneSpaceBaseIn')
+          })
+        } else {
+          pa.data.Cascade.push({ Name: "zoneSpaceForBase" })
+          notEqForSpaceQuery(pa, res => {
+            this.getDataSuc(res, 'ZoneSpaceBaseFor')
+          })
+        }
+      }
+    },
+    // 获取列表成功回调
+    getDataSuc(res, zonespacebase) {
+      let response = res.Content.map(t => {
+        let otherSpace = [];
+        if (t[zonespacebase] && t[zonespacebase].length) {
+          t[zonespacebase].map(item => {
+            otherSpace.push(item.RoomLocalName || item.RoomName)
+          })
+        }
+        t.linkOtherSpace = otherSpace.join(',');
+        return t;
+      })
+      this.tableData = res.Content;
+      this.page.total = res.Total;
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    // 确认 保存关系
+    savaRelation() {
+      let pa = {
+        data: {
+          SpaceId: this.spaceId,
+          EquipIdList: []
+        },
+        type: this.zone
+      }
+      this.selections.map(t => {
+        pa.data.EquipIdList.push(t.EquipID)
+      })
+      if (this.type == "Equipment") {
+        eqInSpaceCreate(pa, res => {
+          this.successCallback()
+        })
+      } else {
+        eqForSpaceCreate(pa, res => {
+          this.successCallback()
+        })
+      }
+    },
+    // 关联成功回调
+    successCallback() {
+      this.$message.success('关联成功');
+      this.$emit('refresh');
+      this.dialogVisible = false;
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 查看详情
+    toDetail() {
+      this.$message('开发中')
+    }
+  },
+  watch: {
+    showType(n) {
+
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin-bottom: 10px;
+    /deep/ .el-input__inner {
+      vertical-align: baseline;
+    }
+  }
+  .table-box {
+    height: 350px;
+  }
+}
+</style>

+ 111 - 0
src/components/business_space/newAddDialogs/addSystemDialog.vue

@@ -0,0 +1,111 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="800px" id="addSyDialog">
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" 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.SysLocalName||scope.row.SysName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="SysLocalID" :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)" type="primary" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </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 {
+  notSyInSpaceQuery, //没有和当前空间绑定的系统
+  syInSpaceCreate, //系统所在业务空间--创建关系
+} from "@/api/scan/request";
+export default {
+  data() {
+    return {
+      title: '添加空间内的系统',
+      inSpaceType: '系统',
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      selections: [], // 选中项
+    }
+  },
+  props: {
+    type: {}, //equipment--equipmentFor
+    spaceId: {},
+    zone: {}, //分区类型 
+  },
+  methods: {
+    // 显示
+    showDialog() {
+      this.dialogVisible = true;
+      this.tableData = [];
+      this.getTableData();
+    },
+    // 选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    // 确认
+    savaRelation() {
+      let pa = {
+        data: {
+          SpaceId: this.spaceId,
+          SysIdList: []
+        },
+        type: this.zone
+      }
+      this.selections.map(t => {
+        pa.data.SysIdList.push(t.SysID)
+      })
+      syInSpaceCreate(pa, res => {
+        this.$message.success('关联成功');
+        this.$emit('refresh');
+        this.dialogVisible = false;
+      })
+    },
+    // 获取表格数据
+    getTableData() {
+      let pa = {
+        data: {
+          PageSize: 200,
+        },
+        type: this.zone,
+        spaceId: this.spaceId
+      }
+      notSyInSpaceQuery(pa, res => {
+        this.tableData = res.Content;
+      })
+    },
+    // 查看详情
+    toDetail() {
+      this.$message('开发中')
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#addSyDialog {
+  .table-box {
+    height: 350px;
+  }
+}
+</style>

+ 150 - 0
src/components/business_space/newGraphy/canvasFun.vue

@@ -0,0 +1,150 @@
+<template>
+  <el-row id="canvas-actions-box" :class="{'isEdit':isEdit}">
+    <div :class="{'active':active=='move'}">
+      <i class="iconfont icon-move" @click="moveCanvas"></i>
+    </div>
+    <div>
+      <i class="iconfont icon-maximize" @click="fitToWindow"></i>
+    </div>
+    <div>
+      <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-menu>
+      </el-dropdown>
+    </div>
+    <div v-if="isEdit" :class="{'active':active=='divide'}">
+      <i class="iconfont icon-edit1" @click="divide"></i>
+    </div>
+    <div v-if="isEdit">
+      <i class="iconfont icon-Erase" @click="clearDivide"></i>
+    </div>
+    <div v-if="isEdit">
+      <i class="iconfont icon-Cancel" @click="undo"></i>
+    </div>
+    <div v-if="isEdit">
+      <i class="iconfont icon-Anti-cancel" @click="redo"></i>
+    </div>
+    <div>
+      <i class="iconfont icon-narrow" @click="reduce"></i>
+    </div>
+    <div class="line">
+      <el-slider tooltip-class="tooltip-class" :min="min" v-model="sliderVal" :show-tooltip="false" @input="scale"></el-slider>
+    </div>
+    <div>
+      <i class="iconfont icon-zoom" @click="plus"></i>
+    </div>
+  </el-row>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      sliderVal: 1, // 滑块值
+      active: '',
+      min: 1,
+      everyScale: 1, // 每份的放大倍数
+    }
+  },
+  props: {
+    isEdit: {
+      default: false
+    }
+  },
+  computed:{
+
+  },
+  methods: {
+    // 移动画布
+    moveCanvas() {
+      this.active = this.active != "move" ? "move" : '';
+      this.$emit('move', this.active == 'move');
+    },
+    // 适配大小
+    fitToWindow() {
+      this.$emit('fit');
+    },
+    // 下拉菜单
+    handleCommand(command) {
+      this.$emit(command)
+    },
+    // 切割编辑
+    divide() {
+      this.active = 'divide';
+      this.$emit('divide');
+    },
+    // 清除编辑
+    clearDivide() {
+      this.active = '';
+      this.$emit('clearDivide');
+    },
+    // 撤销
+    undo() {
+      this.$emit('undo');
+    },
+    // 反撤销
+    redo() {
+      this.$emit('redo');
+    },
+    // 减
+    reduce() {
+      this.sliderVal /= 1.1;
+      if (this.sliderVal < this.min) {
+        this.sliderVal = this.min;
+      }
+      this.scale(this.sliderVal);
+    },
+    // 缩放
+    scale(val) {
+      // 换算
+      let scale = val * this.everyScale / 10;
+      this.$emit('scale', scale);
+    },
+    // 加
+    plus() {
+      this.sliderVal *= 1.1;
+      if (this.sliderVal > this.maxScale) {
+        this.sliderVal = this.maxScale;
+      }
+      this.scale(this.sliderVal);
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#canvas-actions-box {
+  min-width: 542px;
+  & > div {
+    float: left;
+    font-size: 20px;
+    padding: 0 10px;
+    color: #fff;
+    background-color: #6da60f;
+    i {
+      cursor: pointer;
+    }
+  }
+  & > div.active {
+    background-color: #4b7902;
+  }
+  &.isEdit > div {
+    background-color: #02a7f0;
+  }
+  &.isEdit > div.active {
+    background-color: #027db4;
+  }
+  & > div.line {
+    width: 200px;
+    height: 40px;
+    padding: 0;
+    /deep/.el-slider__runway {
+      margin: 17px 0;
+      .el-slider__bar {
+        background-color: #fff;
+      }
+    }
+  }
+}
+</style>

+ 34 - 0
src/components/business_space/newGraphy/createBSP.vue

@@ -0,0 +1,34 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="400px" id="createBSP">
+    <div>请输入创建的业务空间名:</div>
+    <el-input :placeholder="`请输入业务空间名称`" v-model="roomName"></el-input>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible=false">取 消</el-button>
+      <el-button size="small" type="primary" @click="confirm">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      title: '提示',
+      dialogVisible: false,
+      roomName: '',
+    };
+  },
+  methods: {
+    // 显示弹窗
+    showDialog(val) {
+      this.roomName = val;
+      this.dialogVisible = true;
+    },
+    // 确认
+    confirm() {
+      this.$emit('createRoom', this.roomName);
+      this.dialogVisible = false;
+    }
+  },
+};
+</script>

+ 613 - 0
src/components/business_space/newGraphy/graphy.vue

@@ -0,0 +1,613 @@
+<template>
+  <div id="graphy" ref="graphy">
+    <div v-show="!FloorMap">
+      <div class="center" style="height: 400px;padding-top:182px;box-sizing:border-box;">
+        <i class="icon-wushuju iconfont"></i>
+        暂无数据
+      </div>
+    </div>
+    <div class="canvas-box" v-show="FloorMap" v-loading="canvasLoading">
+      <canvas id="floorCanvas" :width="canvasWidth" :height="canvasHeight" ref="canvas" tabindex="0"></canvas>
+      <!-- 初始两个按钮 -->
+      <el-row class="buttons-box">
+        <div>
+          <el-autocomplete popper-class="my-autocomplete" v-model="search" :fetch-suggestions="querySearch" placeholder="输入平面图中已有的业务空间名称进行查找"
+            width="180px" @select="handleSelect">
+            <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) }}
+                <span class="addr" style="position: absolute;right:10px;color:#409EFF;">定位</span>
+              </div>
+            </template>
+          </el-autocomplete>
+        </div>
+        <div class="button-group">
+          <!-- 默认操作模式 -->
+          <div v-show="type==1">
+            <el-button @click="editGraphy">编辑平面图</el-button>
+          </div>
+          <!-- 点击已经关联的业务空间 -->
+          <div v-show="type==2">
+            <el-button type="primary" plain @click="refactorBSP">重新划分业务空间</el-button>
+            <el-button type="primary" @click="editeSpaceDetail">编辑空间详情</el-button>
+            <el-button plain @click="cancelGraphy">取 消</el-button>
+          </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="cancelGraphy">取 消</el-button>
+          </div>
+          <!-- 重新划分业务空间 -->
+          <div v-show="type==4">
+            <el-button plain @click="cancelGraphy">取 消</el-button>
+            <el-button type="primary" @click="saveRefactorBSP">保存</el-button>
+          </div>
+        </div>
+        <div style="position: absolute;right: 0;">
+          <el-button type="text" @click="lookUnrelatBSpace(false)">未关联平面图的业务空间 {{num}} 条</el-button>
+        </div>
+      </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>
+      </el-row>
+    </div>
+    <!--  -->
+    <!-- 未关联元空间的业务空间 -->
+    <unRelateBSP ref="unRelateBSP" :tableData="BSPUnrelaISPList" :isAction="isAction" @createFromUnrelated="createFromUnrelated"></unRelateBSP>
+    <!-- 创建新的业务空间 -->
+    <createBSP ref="createBSP" @createRoom="createRoom"></createBSP>
+  </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 unRelateBSP from "./unRelateBSP";
+import createBSP from "./createBSP";
+import {
+  countZone,
+  queryZone,
+  updateZone,
+  createZone,
+  getIspNotInSpace,
+  createRelateInZoneAndISp,
+  groupCreRelaZoneAndISp
+} from "@/api/scan/request"
+const colorArr = [
+  "#F9C3C3",
+  "#FFD1BF",
+  "#FFF3BF",
+  "#D8F7C6",
+  "#C6F2F6",
+  "#DCE3C0",
+  "#FAE6C9",
+  "#E3D7F7",
+  "#C4CBF8",
+  "#DEC3F6"
+];
+//  BSP => 业务空间
+export default {
+  components: {
+    canvasFun,
+    unRelateBSP,
+    createBSP
+  },
+  data() {
+    return {
+      canvasWidth: 800,
+      canvasHeight: 600,
+      type: 1, // 默认操作模式
+      search: '',//搜索
+      num: 0, // 未关联空间的业务空间条数
+      buildFloor: [],
+      FloorMap: '',
+      tab: {},
+      isEdit: false,
+      canvasLoading: false,
+      view: null,
+      scene: null,
+      Outline: [], // 当前选中的多个空间组成的轮廓线->三维数组
+      businessSpaceList: [], // 所有业务空间
+      BSPUnrelaISPList: [], // 未关联元空间的业务空间
+      BSPRelaISPList: [], // 已关联元空间的业务空间
+      // 未关联元空间的业务空间弹窗
+      isAction: false,
+      curOutline: [],
+      BIMIDToSID: {}, //bimid映射元空间id
+      curZoneItem: {}, //当前选中的业务空间item
+      allUnRelatISP: [], //
+    }
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId'])
+  },
+  created() {
+  },
+  mounted() {
+    this.canvasWidth = this.$refs.graphy.offsetWidth;
+    this.canvasHeight = this.$refs.graphy.offsetHeight;
+  },
+  methods: {
+    // 初始化
+    init() {
+      this.type = 1;
+      // 获取当前分区下的业务空间
+      this.getBusinessSpace();
+      // 获取未关联平面图的业务空间统计
+      this.getUnrelateCount();
+      // 获取当前楼层的元空间
+      this.getFloorISpace();
+      // 查询未关联业务空间的元空间
+      this.getISPSPUnrelaBSP()
+    },
+    // 获取当前楼层的元空间
+    getFloorISpace() {
+      let pa = {
+        zone: 'Ispace',
+        data: {
+          Filters: `FloorId='${this.buildFloor[1]}'`,
+          PageSize: 1000
+        }
+      }
+      queryZone(pa, res => {
+        this.BIMIDToSID = {}
+        res.Content.map(t => {
+          this.BIMIDToSID[t.BIMID.split(":")[1]] = t.RoomID;
+        })
+      })
+    },
+    // 搜索
+    querySearch(queryString, cb) {
+      var restaurants = this.BSPRelaISPList;
+      var results = queryString ?
+        restaurants.filter(this.createFilter(queryString)) :
+        restaurants;
+      // 调用 callback 返回建议列表的数据
+      cb(results);
+    },
+    // 过滤器
+    createFilter(queryString) {
+      return restaurant => {
+        return restaurant.RoomLocalName.indexOf(queryString) > -1;
+      };
+    },
+    // 查询选中
+    handleSelect(BSP) {
+      console.log(arguments)
+    },
+    // 父组件调用
+    getData(buildFloor, FloorMap, tab) {
+      this.buildFloor = buildFloor;
+      this.FloorMap = 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
+      })
+    },
+    // 获取未绑定业务空间的元空间
+    getISPSPUnrelaBSP() {
+      let pa = {
+        data: {
+          Filters: `FloorId='${this.buildFloor[1]}'`,
+          PageSize: 1000
+        },
+        objectType: this.tab.code
+      }
+      this.allUnRelatISP = []
+      getIspNotInSpace(pa, res => {
+        this.allUnRelatISP = res.Content;
+      })
+    },
+    // 获取底图
+    getGraphy() {
+      let that = this;
+      that.clearGraphy()
+      that.scene = new DivideFloorScene();
+      that.canvasLoading = true;
+      that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.FloorMap}`).then(() => {
+        that.canvasLoading = false;
+        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)
+        that.view.fitSceneToView();
+        that.view.maxScale = that.view.scale * 10;
+        that.view.minScale = that.view.scale;
+        that.$refs.canvasFun.everyScale = that.view.scale;
+      })
+    },
+    // 获取当前分区下的业务空间
+    getBusinessSpace() {
+      this.isLoading = true
+      let pa = {
+        zone: this.tab.code,
+        data: {
+          Filters: ``,
+          Orders: "createTime desc, RoomID asc",
+          PageSize: 500
+        }
+      }
+      if (this.buildFloor.length && this.buildFloor.length > 1) {
+        pa.data.Filters = `BuildingId='${this.buildFloor[0]}';FloorId='${this.buildFloor[1]}'`
+      }
+      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;
+      })
+    },
+    // canvas点击事件
+    canvasClick(item, event) {
+      this.scene.setSpaceSelectable(true);
+      this.scene.setZoneSelectable(true);
+      if (this.type == 4) {
+
+      } else {
+        if (item instanceof SpaceItem) {
+          this.type = 3;
+          this.curZoneItem = {};
+          this.scene.setZoneSelectable(false);
+        }
+        if (item instanceof ZoneItem) {
+          this.type = 2;
+          this.curZoneItem = item;
+          this.scene.setSpaceSelectable(false);
+        }
+      }
+    },
+    // 编辑平面图
+    editGraphy() {
+      this.type = 3;
+    },
+    // 查看未关联的业务空间--flag--查看-or-选择
+    lookUnrelatBSpace(flag) {
+      this.isAction = flag;
+      let arr = this.scene.getSelectedSpaces();
+      if (flag && !arr.length) {
+        this.$message.warning('请至少选择一个空间');
+        return;
+      }
+      this.$refs.unRelateBSP.showDialog();
+    },
+    // 取消(所有取消公用)
+    cancelGraphy() {
+      this.type = 1;
+      this.init();
+    },
+    // 批量创建业务空间
+    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
+          }
+        }
+        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: "已取消批量创建"
+        });
+      });
+    },
+    // 创建新的业务空间
+    createNewZone() {
+      let arr = this.scene.getSelectedSpaces();
+      if (arr.length) {
+        let tempArr = [];
+        arr.map(t => {
+          tempArr.push(t.data.Name);
+        })
+        this.$refs.createBSP.showDialog(tempArr.toString());
+      } else {
+        this.$message.warning('请至少选择一个空间');
+      }
+    },
+    // 创建新的业务空间-弹窗返回确认创建
+    createRoom(val) {
+      let arr = this.scene.getSelectedSpaces();
+      let zoneObj = { Outline: [] }, IspaceIdList = [];
+      arr.map(t => {
+        zoneObj.Outline.push(t.data.OutLine);
+        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId])
+      })
+      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)
+      })
+    },
+    // 从未关联平面图的业务空间中选择--按钮返回关联信号
+    createFromUnrelated(BSP) {
+      BSP.Outline = []
+      let arr = this.scene.getSelectedSpaces();
+      arr.map(t => {
+        BSP.Outline.push(t.data.OutLine);
+      })
+      let pa = {
+        zone: BSP.ObjectType,
+        data: {
+          Content: [BSP],
+          Projection: ['Outline']
+        }
+      }
+      updateZone(pa, res => {
+        this.$message.success('更新成功');
+        this.init();
+      })
+    },
+    // 编辑空间详情
+    editeSpaceDetail() {
+      let item = this.curZoneItem.data;
+      this.$router.push({
+        path: "/ledger/spaceDetail",
+        query: { RoomID: item.RoomID, zone: this.tab.code, isMyTab: 1 }
+      })
+    },
+    // 重新划分业务空间
+    refactorBSP() {
+      this.type = 4;
+      // 设置空间可选
+      this.scene.setSpaceSelectable(true);
+      // 将已关联的设置不可选,并将当前选的隐藏
+      this.scene.changeSelectZone(this.curZoneItem);
+    },
+    // 重新划分--保存
+    saveRefactorBSP() {
+      let arr = this.scene.getSelectedSpaces();
+      //更新业务空间
+      let zoneObj = { Outline: [] }, IspaceIdList = [];
+      arr.map(t => {
+        zoneObj.Outline.push(t.data.OutLine);
+        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId])
+      })
+      zoneObj.RoomID = this.curZoneItem.data.RoomID;
+      if (!zoneObj.Outline.length) {
+        zoneObj.Outline = null;
+      }
+      let pa = {
+        zone: this.tab.code,
+        data: {
+          Content: [zoneObj],
+          Projection: ['Outline']
+        },
+      }
+      updateZone(pa, res => {
+        this.relationInBSPandISP(zoneObj.RoomID, IspaceIdList)
+      })
+    },
+    // 更新业务空间和元空间的关系
+    relationInBSPandISP(SpaceId, IspaceIdList) {
+      let pa = {
+        data: { SpaceId: SpaceId, IspaceIdList: IspaceIdList },
+        type: this.tab.code
+      }
+      createRelateInZoneAndISp(pa, res => {
+        this.$message.success('创建成功');
+        this.init();
+      })
+    },
+    // canvas 获取焦点
+    focus() {
+      document.getElementById(`floorCanvas`).focus()
+    },
+    // 清除canvas
+    clearGraphy() {
+      if (this.view) {
+        this.view.scene = null;
+        return
+      }
+      this.view = new SGraphyView('floorCanvas')
+    },
+    // 工具栏操作
+    // 移动底图
+    moveCanvas(move) {
+      // todo
+      let canvas = document.getElementById(`floorCanvas`);
+      if (move) {
+        canvas.style.cursor = 'move';
+      } else {
+        canvas.style.cursor = 'default';
+      }
+    },
+    // 适配底图到窗口
+    fit() {
+      this.view.fitSceneToView()
+    },
+    // 保存为png
+    savePng() {
+      this.view.saveImage(`${this.buildFloor[1]}.png`, 'png');
+    },
+    // 保存为svg
+    saveSvg() {
+      this.view.saveSceneSvg(`${this.buildFloor[1]}.svg`, 6400, 4800);
+    },
+    // 切割划分
+    divide() {
+      this.drawMainScene.isMarking = true;
+    },
+    // 清除切割划分
+    clearDivide() {
+      this.drawMainScene.clearSceneMark()
+    },
+    // 撤销
+    undo() {
+
+    },
+    // 反撤销
+    redo() { },
+    // 缩放
+    scale(val) {
+      let scale = this.view.scale;
+      this.view.scaleByPoint(val / scale, this.canvasWidth / 2, this.canvasHeight / 2);
+    },
+  },
+  filters: {
+    cutString: function (str, len) {
+      //length属性读出来的汉字长度为1
+      if (!!str && typeof str == "string" && str.length > len) {
+        return str.substring(0, len) + "...";
+      } else {
+        return str || "--";
+      }
+    }
+  },
+  watch: {
+    projectId() {
+      this.FloorMap = '';
+      this.tab = {};
+    },
+    "view.scale": {
+      handler(n) {
+        if (this.$refs.canvasFun) {
+          this.$refs.canvasFun.sliderVal = n * 10 / this.view.minScale;
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#graphy {
+  position: relative;
+  width: 100%;
+  height: calc(100% - 56px);
+  .canvas-box {
+    width: 100%;
+    height: 100%;
+  }
+  .buttons-box {
+    position: absolute;
+    top: 0;
+    width: 100%;
+    z-index: 999;
+    & > div {
+      float: left;
+    }
+    /deep/ .el-autocomplete {
+      display: block;
+      width: 320px;
+      margin-right: 10px;
+    }
+    .button-group button {
+      display: block;
+      float: left;
+    }
+    .my-autocomplete {
+      li {
+        line-height: normal;
+        padding: 7px;
+        .name {
+          text-overflow: ellipsis;
+          overflow: hidden;
+        }
+        .addr {
+          font-size: 12px;
+          color: #b4b4b4;
+        }
+        .highlighted .addr {
+          color: #ddd;
+        }
+      }
+    }
+  }
+  .canvas-actions-box {
+    position: absolute;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    z-index: 999;
+  }
+}
+</style>

+ 67 - 0
src/components/business_space/newGraphy/unRelateBSP.vue

@@ -0,0 +1,67 @@
+<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-table-column prop="action" label="操作" min-width="100" v-if="isAction">
+          <template slot-scope="scope">
+            <el-button @click="createRelation(scope.row)">关联平面图</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: "unRelateBSP",
+  data() {
+    return {
+      title: '未关联平面图的业务空间',
+      dialogVisible: false,
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      queryString: '',
+      data: []
+    };
+  },
+  props: {
+    tableData: {
+      default: []
+    }, //列表数据
+    isAction: false, //是否显示操作按钮
+  },
+  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;
+      };
+    },
+    // 关联平面图
+    createRelation(row) {
+      this.$emit('createFromUnrelated', row);
+      this.dialogVisible = false;
+    }
+  },
+};
+</script>

+ 172 - 0
src/components/business_space/newTables/eqToSpaceTable.vue

@@ -0,0 +1,172 @@
+<template>
+  <div id="eqInSp">
+    <el-row>
+      <el-button type="primary" @click="add">添加{{inSpaceType}}</el-button>
+      <el-tooltip class="item" effect="dark" :content="`可前往“全部关系总览”中,按坐标计算${typeToTips[type]}`" 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-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>
+            可前往“全部关系总览”中,按坐标计算{{typeToTips[type]}}
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <!-- 添加设备弹窗 -->
+    <addEquipDialog ref="addEqDialog" :type="type" :spaceId="params.RoomID" :zone="params.zone" @refresh='getTableData'></addEquipDialog>
+  </div>
+</template>
+
+<script>
+import {
+  queryZone,
+  eqInSpaceDelete, //设备所在业务空间--删除关系
+  eqForSpaceDelete, //设备服务业务空间--删除关系
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addEquipDialog from "@/components/business_space/newAddDialogs/addEquipDialog"
+export default {
+  components: {
+    addEquipDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: '设备',
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [], //列表数据
+      typeToTips: {
+        Equipment: '空间内的设备',
+        EquipmentFor: '服务于空间的设备',
+      }
+    };
+  },
+  props: {
+    params: {},
+    type: {}
+  },
+  created() {
+    this.getTableData()
+  },
+  methods: {
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let pa = {
+          data: [row],
+          type: this.params.zone
+        }
+        if (this.type == 'Equipment') {
+          this.deleteEqInSpace(pa);
+        } else {
+          this.deleteEqForSpace(pa);
+        }
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除设备所在空间关系
+    deleteEqInSpace(pa) {
+      eqInSpaceDelete(pa, res => {
+        this.$message.success('删除成功')
+        this.getTableData()
+      })
+    },
+    // 删除设备服务空间关系
+    deleteEqForSpace(pa) {
+      eqForSpaceDelete(pa, res => {
+        this.$message.success('删除成功')
+        this.getTableData()
+      })
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 获取列表数据
+    getTableData() {
+      let pa = {
+        data: {
+          Filters: `RoomID='${this.params.RoomID}'`,
+          Cascade: [
+            {
+              Name: this.type.replace(this.type[0], this.type[0].toLowerCase()),
+              Cascade: [{ Name: 'equipCategory' }]
+            }
+          ]
+        },
+        zone: this.params.zone
+      }
+      queryZone(pa, res => {
+        this.tableData = res.Content[0][this.type] || []
+        this.tableData.map(t => {
+          t.SpaceId = res.Content[0].RoomID
+          return t;
+        })
+      })
+    },
+    // 添加设备
+    add() {
+      this.$refs.addEqDialog.floor = [this.params.BuildingId, this.params.FloorId];
+      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>

+ 135 - 0
src/components/business_space/newTables/syInSpaceTable.vue

@@ -0,0 +1,135 @@
+<template>
+  <div id="eqInSp">
+    <el-row>
+      <el-button type="primary" @click="add">添加{{inSpaceType}}</el-button>
+      <el-tooltip class="item" effect="dark" :content="`可前往“全部关系总览”中,按坐标计算${typeToTips[type]}`" 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.SysLocalName||scope.row.SysName}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="SysLocalID" :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-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>
+            可前往“全部关系总览”中,按坐标计算{{typeToTips[type]}}
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <addSystemDialog ref="addSyDialog" :type="type" :spaceId="params.RoomID" :zone="params.zone" @refresh='getTableData'></addSystemDialog>
+  </div>
+</template>
+
+<script>
+import {
+  queryZone,
+  syInSpaceDelete
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addSystemDialog from "@/components/business_space/newAddDialogs/addSystemDialog";
+export default {
+  components: {
+    addSystemDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: '系统',
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [], //列表数据
+      typeToTips: {
+        generalSystem: '空间内的系统',
+      }
+    };
+  },
+  props: {
+    params: {},
+    type: {}
+  },
+  created() {
+    this.getTableData()
+  },
+  methods: {
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let pa = {
+          data: [row],
+          type: this.params.zone
+        }
+        this.deleteSyInSpace(pa)
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除关系
+    deleteSyInSpace(pa){
+      syInSpaceDelete(pa, res => {
+        this.$message.success('删除成功');
+        this.getTableData();
+      })
+    },
+    // 获取列表数据
+    getTableData() {
+      let pa = {
+        data: {
+          Cascade: [{ Name: "generalSystem" }],
+          Filters: `RoomID="${this.params.RoomID}"`,
+        },
+        zone: this.params.zone
+      }
+      queryZone(pa, res => {
+        this.tableData = res.Content[0].GeneralSystem || [];
+        this.tableData.map(t => {
+          t.SpaceId = res.Content[0].RoomID;
+          return t;
+        })
+      })
+    },
+    // 添加系统
+    add() {
+      this.$refs.addSyDialog.showDialog()
+    }
+  },
+  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/business_space/table/addEquip.vue

@@ -3,7 +3,7 @@
     <div class="search" style="margin-bottom:10px;">
       <div>
         <el-input
-          placeholder="输入设备名称或设备本地编码查询进行查询"
+          placeholder="输入设备名称或设备本地编码进行查询"
           style="width:300px;float:left;margin-right:10px;"
           v-model="search.filter"
           clearable

+ 1 - 1
src/components/business_space/table/businessTable.vue

@@ -72,7 +72,7 @@ export default {
     return {
       page: {
         size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
+        sizes: [50, 100, 150, 200],
         total: 1,
         currentPage: 1
       },

+ 179 - 0
src/components/ledger/cenote/dialog/addCenoteDialog.vue

@@ -0,0 +1,179 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="addEqDialog">
+    <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">
+        <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 { unshaftThroughShaft, queryShaftType, linkShaft } 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
+      }
+      if(this.keycode!=''){
+        params.data.Filters += `;ShaftName contain '${this.keycode}' or ShaftLocalName contain '${this.keycode}' or ShaftLocalID contain '${this.keycode}'`
+      }
+      unshaftThroughShaft(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 = {
+          ShaftId: this.params.ShaftID,
+          ShaftOtherIdList: this.selections.map(item => {
+            return item.ShaftID
+          })
+        }
+        linkShaft(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>

+ 187 - 0
src/components/ledger/cenote/dialog/addEquipDialog.vue

@@ -0,0 +1,187 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="addEqDialog">
+    <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">
+        <floor-cascader @change="changeFloor"></floor-cascader>
+      </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="ShaftListName" label="已关联其他竖井" show-overflow-tooltip min-width="100" max-width="200"></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 { unshaftInEq, linkEqSh } from "@/api/scan/request";
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+    floorCascader
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加竖井内的设备",
+      keycode: '', //输入查询条件
+      Buildfloor: ['all'], // 选中的建筑楼层
+      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() { },
+  methods: {
+    //修改建筑楼层
+    changeFloor(value) {
+      this.Buildfloor = value
+      this.getTableData()
+    },
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true
+      this.page.pageNumber = 1
+      this.tableData = []
+      this.getTableData()
+    },
+    getTableData() {
+      let params = {
+        data: {
+          Cascade: [{ Name: 'equipCategory' }, {Name: 'shaftList'}],
+          Filters:`not EquipID isNull`,
+          Orders: "createTime desc, EquipID desc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize,
+        },
+        shaftId: this.params.ShaftID
+      }
+      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}'`
+      }
+      unshaftInEq(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 = {
+          ShaftId: this.params.ShaftID,
+          EquipIdList: this.selections.map(item => {
+            return item.EquipID
+          })
+        }
+        linkEqSh(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>

+ 147 - 0
src/components/ledger/cenote/dialog/addSystemDialog.vue

@@ -0,0 +1,147 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" 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 :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.SysLocalName||scope.row.SysName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="SysLocalId" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="CategoryNames.CategoryName" :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 { unshaftInSys, linkSySh } from "@/api/scan/request";
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import { mapGetters } from "vuex";
+export default {
+  components: {
+    floorCascader
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加竖井内的系统",
+      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() { },
+  methods: {
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true
+      this.page.pageNumber = 1
+      this.tableData = []
+      this.getTableData()
+    },
+    getTableData() {
+      let params = {
+        data: {
+          Cascade: [{ Name: 'categoryNames' }],
+          Orders: "createTime desc, SysID desc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize,
+        },
+        shaftId: this.params.ShaftID
+      }
+      unshaftInSys(params, res => {
+        this.tableData = res.Content
+        this.page.total = res.Total
+      })
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    savaRelation() {
+      if(this.selections.length){
+        let params = {
+          ShaftId: this.params.ShaftID,
+          SysIdList: this.selections.map(item => {
+            return item.SysID
+          })
+        }
+        linkSySh(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>

+ 155 - 0
src/components/ledger/cenote/table/cenoteTable.vue

@@ -0,0 +1,155 @@
+<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 { queryCenoteTableData, queryShaftType, shthroughshUnlink } from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addCenoteDialog from "@/components/ledger/cenote/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: `ShaftID='${this.params.ShaftID}'`,
+        Cascade: [
+          {
+            Name: 'shaftThroughList'
+          }
+        ]
+      }
+      queryCenoteTableData(params, res => {
+        this.tableData = res.Content[0].ShaftThroughList || []
+        this.tableData.forEach(item => {
+          if(item.StructureInfo && item.StructureInfo.ShaftFuncType){
+            item.StructureInfo.ShaftFuncType = this.shaftType[item.StructureInfo.ShaftFuncType]
+          }
+        })
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = {
+          ShaftOtherId: row.ShaftID,
+          ShaftId: this.params.ShaftID
+        }
+        this.deleteShThroughSh(params);
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除设备所在空间关系
+    deleteShThroughSh(params) {
+      shthroughshUnlink(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>

+ 143 - 0
src/components/ledger/cenote/table/deviceTable.vue

@@ -0,0 +1,143 @@
+<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 { queryCenoteTableData, eqinshUnlink } from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addEquipDialog from "@/components/ledger/cenote/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: `ShaftID='${this.params.ShaftID}'`,
+        Cascade: [
+          {
+            Name: 'equipmentList',
+            Cascade: [{ Name: 'equipCategory' }]
+          }
+        ]
+      }
+      queryCenoteTableData(params, res => {
+        this.tableData = res.Content[0].EquipmentList || []
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = {
+          EquipId: row.EquipID,
+          ShaftId: this.params.ShaftID
+        }
+        this.deleteEqInSh(params);
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除设备所在竖井关系
+    deleteEqInSh(params) {
+      eqinshUnlink(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>

+ 145 - 0
src/components/ledger/cenote/table/systemTable.vue

@@ -0,0 +1,145 @@
+<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.SysLocalName||scope.row.SysName||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="SysLocalID" :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.CategoryNames.CategoryName}}
+            </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>
+    <!-- 添加设备弹窗 -->
+    <addSystemDialog ref="addEqDialog" @refresh="getTableData" :type="type" :params="params"></addSystemDialog>
+  </div>
+</template>
+
+<script>
+import { queryCenoteTableData, syinshUnlink } from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addSystemDialog from "@/components/ledger/cenote/dialog/addSystemDialog"
+export default {
+  components: {
+    addSystemDialog
+  },
+  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: `ShaftID='${this.params.ShaftID}'`,
+        Cascade: [
+          {
+            Name: 'systemList',
+            Cascade: [{ Name: 'categoryNames' }]
+          }
+        ]
+      }
+      queryCenoteTableData(params, res => {
+        this.tableData = res.Content[0].SystemList || []
+      })
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let params = {
+          SysId: row.SysID,
+          ShaftId: this.params.ShaftID
+        }
+        this.deleteSyInSh(params);
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除系统所在竖井关系
+    deleteSyInSh(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.addEqDialog.showDialog()
+    }
+  },
+  watch: {
+    type() {
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#eqInSp {
+  height: 100%;
+  .table-box {
+    margin-top: 10px;
+    height: calc(100% - 50px);
+  }
+}
+</style>

+ 61 - 16
src/components/ledger/handsontables/assets.vue

@@ -47,6 +47,19 @@
     <!-- <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>
     <look-pic :dialog="myDialog" :keysArr="picsArr"></look-pic>
+    <!-- 不支持的输入方式 -->
+    <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>
     <!-- 新增资产 -->
     <el-dialog class="add-assets" :title="showAddByDie?'未关联资产的设备批量创建资产':'确定新增资产类型'" @close="showAddByDie = false" :visible.sync="myDialog.addDevice"
       width="670px">
@@ -167,6 +180,7 @@ export default {
         details: false,//详情页
         changeRea: false,//关联资产
         lookPic: false,//图片查看
+        update: false,//临时维护信息点
       },
       row: null, //被修改的row
       filesArr: [], //保存临时的文件key
@@ -179,7 +193,7 @@ export default {
       iframeSrc: "",
       id: 0,
       onlyRead: true,
-      showType: 'all',
+      showType: 'Visible',
       linkNameFalg: false,
       qrcodeUrl: "", //二维码图片地址
       loading: false,
@@ -194,7 +208,13 @@ export default {
         floorId: '',
         Family: ''
       },
-      dieNum: 0 // 查询设备部件数量
+      dieNum: 0, // 查询设备部件数量
+      inputMap: {
+        flowBuild: 'D1'
+      }, //信息点和输入方式映射表
+      updateInputShow: false, //是否显示临时维护输入框
+      updateInfoPoint: '',//临时维护信息点
+      updateInput: '', //临时维护信息点值
     };
   },
   methods: {
@@ -213,6 +233,11 @@ export default {
         };
         getDataDictionary(params, res => {
           this.tableHeader = res.Content;
+          this.tableHeader.forEach(item => {
+            if(item.Path && item.InputMode){
+              this.inputMap[item.Path] = item.InputMode
+            }
+          })
           this.getTableData()
         });
       }
@@ -677,6 +702,7 @@ export default {
     //获取到了正确的信息
     getInfors(infos, row, el) {
       let val = this.hot.colToProp(row.col);
+      let inputMode = this.inputMap[val];
       this.row = row.row;
       this.messKey = val;
       switch (val) {
@@ -684,7 +710,7 @@ export default {
         case 'caozuo':
           // window.open(`http://adm.sagacloud.cn:8058/spread?id=${infos.EquipID}&pid=${this.projectId}&secret=${this.secret}`,"_blank")
           this.$message("开发中...")
-          break;
+          return false
         //资产二维码图片
         case 'EquipQRCode':
           this.qrcodeUrl = this.tableData[row.row].EquipQRCode;
@@ -693,7 +719,7 @@ export default {
           } else {
             this.$message("此资产没有资产二维码");
           }
-          break;
+          return false
         //关联系统
         case 'LinkSystem':
           if (!this.onlyRead) {
@@ -701,37 +727,37 @@ export default {
             this.systemList = this.tableData[row.row].LinkSystem || [];
             this.myDialog.systemType = true;
           }
-          break;
+          return false
         //关联资产
         case 'LinkEquipLocalName':
           if (this.linkNameFalg) {
             this.myDialog.changeRea = true;
           }
-          break;
+          return false
         //品牌型号弹窗
         case 'DPManufacturerID':
           if (!this.onlyRead) {
             this.myDialog.firm = true;
           }
-          break;
+          return false
         //供应商信息弹窗
         case 'DPSupplierID':
           if (!this.onlyRead) {
             this.myDialog.supplier = true;
           }
-          break;
+          return false
         //维修商信息弹窗
         case 'DPMaintainerID':
           if (!this.onlyRead) {
             this.myDialog.maintainer = true;
           }
-          break;
+          return false
         //保险公司信息
         case 'DPInsurerID':
           if (!this.onlyRead) {
             this.myDialog.insurer = true;
           }
-          break;
+          return false
         //供应合同编号
         case 'LedgerParam.SupplyPurchase.SupplierContractID':
           if (!this.onlyRead) {
@@ -747,7 +773,7 @@ export default {
               this.$message("请先选择供应商");
             }
           }
-          break;
+          return false
         //保险单号
         case 'LedgerParam.InsuranceDoc.InsuranceNum':
           if (!this.onlyRead) {
@@ -763,7 +789,7 @@ export default {
               this.$message("请先选择保险商");
             }
           }
-          break;
+          return false
         //保险文件--资产文档--安装质检报告
         case 'LedgerParam.InsuranceDoc.InsuranceFile':
         case 'LedgerParam.PhotoDoc.Archive':
@@ -771,7 +797,7 @@ export default {
           let IPSdata = tools.dataForKey(this.tableData[row.row], val);
           this.filesArr = IPSdata ? IPSdata : [];
           this.myDialog.uploadFiles = true;
-          break;
+          return false
         //安装照片--安装图纸--资产铭牌照片--资产图纸
         case 'LedgerParam.Siteinstall.InstallPic':
         case 'LedgerParam.Siteinstall.InstallDrawing':
@@ -780,13 +806,13 @@ export default {
           let SSPPdata = tools.dataForKey(this.tableData[row.row], val);
           this.imgsArr = SSPPdata ? SSPPdata : [];
           this.myDialog.uploadImgs = true;
-          break;
+          return false
         //资产照片
         case 'LedgerParam.PhotoDoc.Pic':
           let Pdata = tools.dataForKey(this.tableData[row.row], val);
           this.picsArr = Pdata ? Pdata : [];
           this.myDialog.pic = true;
-          break;
+          return false
         //包含的部件字段
         case 'Count':
           if (this.onlyRead) {
@@ -794,10 +820,29 @@ export default {
           } else {
             this.$router.push({ path: '/ledger/partsmanage', query: { deviceId: infos.EquipID, typeId: this.mess.deviceId } });
           }
-          break;
+          return false
         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
+      }
+    },
+    //关闭临时维护弹窗回调
+    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 = ''
     },
     //获取被筛选掉的行号
     trimmedRows() {

+ 128 - 41
src/components/ledger/handsontables/device.vue

@@ -14,9 +14,9 @@
         <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
       </el-select>
       <!-- <el-button size="small" style='width: 80px;' @click="download" icon="iconfont icon-xiazai">下载</el-button> -->
-      <el-button size="small" style='width: 80px;' @click="addDevice" icon="iconfont icon-tianjia">添加设备</el-button>
-      <el-button size="small" style='width: 80px;' @click="reset" icon="iconfont icon-shuaxin">刷新</el-button>
-      <el-button size="small" style='width: 80px;' v-show="!onlyRead" @click="undo" icon="iconfont icon-undo">撤销</el-button>
+      <el-button size="small" style='width: 80px;' @click="addDevice">添加设备</el-button>
+      <el-button size="small" style='width: 80px;' @click="reset">刷新</el-button>
+      <el-button size="small" style='width: 80px;' v-show="!onlyRead" @click="undo">撤销</el-button>
     </div>
     <!-- 二维码弹窗 -->
     <qrcode :dialog="myDialog" :qrcodeUrl="qrcodeUrl" :addBody="true" ref="qrcode"></qrcode>
@@ -59,6 +59,19 @@
     <!-- 关联资产 -->
     <change-rea @changeProperty="changeProperty" :dialog="myDialog" :category="deviceType"></change-rea>
     <look-pic :dialog="myDialog" :keysArr="picsArr"></look-pic>
+    <!-- 不支持的输入方式 -->
+    <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>
     <!-- 新增设备 -->
     <el-dialog title="确定新增设备的类型" :visible.sync="myDialog.addDevice" width="670px">
       <el-row>
@@ -85,32 +98,33 @@ import {
 } from "@/api/scan/request";
 
 
-import tools from "@/utils/scan/tools";
+import tools from "@/utils/scan/tools"
 import handsonUtils from "@/utils/hasontableUtils"
 import showTools from "@/utils/handsontable/notShow"
 import text from "@/utils/handsontable/mainText"
-import myCascader from "@/components/ledger/lib/cascader";
+import myCascader from "@/components/ledger/lib/cascader"
+import buildFloor from '@/utils/handsontable/buildFloorData'
 
-import qrcode from "@/components/ledger/lib/qrcode";
-import firm from "@/components/dialogs/list/firm";
-import supplyDialog from "@/components/dialogs/list/supplyDialog";
-import supplierDialog from "@/components/dialogs/list/supplierDialog";
-import maintainerDialog from "@/components/dialogs/list/maintainerDialog";
-import insurerDialog from "@/components/dialogs/list/insurerDialog";
-import guaranteeDialog from "@/components/dialogs/list/guaranteeDialog";
-import uploadFilesDialog from "@/components/dialogs/list/filesDialog";
-import uploadImgDialog from "@/components/dialogs/list/uploadImgDialog";
+import qrcode from "@/components/ledger/lib/qrcode"
+import firm from "@/components/dialogs/list/firm"
+import supplyDialog from "@/components/dialogs/list/supplyDialog"
+import supplierDialog from "@/components/dialogs/list/supplierDialog"
+import maintainerDialog from "@/components/dialogs/list/maintainerDialog"
+import insurerDialog from "@/components/dialogs/list/insurerDialog"
+import guaranteeDialog from "@/components/dialogs/list/guaranteeDialog"
+import uploadFilesDialog from "@/components/dialogs/list/filesDialog"
+import uploadImgDialog from "@/components/dialogs/list/uploadImgDialog"
 import picDialog from "@/components/dialogs/list/picDialog"
 import systemType from "@/components/dialogs/list/systemType"
-import myPagination from "@/components/ledger/lib/myPagination";
+import myPagination from "@/components/ledger/lib/myPagination"
 import detailsDialog from "@/components/ledger/lib/detailsDia"
 import changeRea from "@/components/dialogs/changeRea"
-import { mapGetters, mapActions } from "vuex";
+import { mapGetters, mapActions } from "vuex"
 //图片查看
 import lookPic from "@/components/ledger/lib/lookImages"
 import Handsontable from "handsontable-pro"
 import 'handsontable-pro/dist/handsontable.full.css'
-import zhCN from 'handsontable-pro/languages/zh-CN';
+import zhCN from 'handsontable-pro/languages/zh-CN'
 //下拉插件
 // import "@/assets/js/chosen.jquery.min";
 // import "@/assets/js/handsontable-chosen-editor";
@@ -135,12 +149,14 @@ export default {
     lookPic,
     myCascader
   },
-  created() { },
+  created() { 
+    buildFloor.getData(this.buildFloorData)
+  },
   computed: {
     ...mapGetters("layout", ["projectId", "secret", "userId"]),
     showTypes() {
       return this.onlyRead ?
-        [{ value: "all", label: '全部' }, { value: "Visible", label: '只看采集信息' }] :
+        [{ value: "Visible", label: '只看采集信息' }, { value: "all", label: '全部' }] :
         [{ value: "partInfo", label: '隐藏信息点' }, { value: "all", label: '全部' }, { value: "Visible", label: '只看采集信息' }]
     }
   },
@@ -153,6 +169,7 @@ export default {
         value: false,
         label: '编辑模式'
       }],
+      buildFloorData: [], //楼层数据
       tableData: [],
       mess: {},
       tableHeader: null,
@@ -178,6 +195,7 @@ export default {
         details: false,//详情页
         changeRea: false,//关联资产
         lookPic: false,//图片查看
+        update: false,//临时维护信息点
       },
       row: null, //被修改的row
       filesArr: [], //保存临时的文件key
@@ -189,7 +207,7 @@ export default {
       iframeSrc: "",
       id: 0,
       onlyRead: true,
-      showType: 'all',
+      showType: 'Visible',
       linkNameFalg: false,
       qrcodeUrl: "", //二维码图片地址
       loading: false,
@@ -197,6 +215,12 @@ export default {
       floorData: [],
       curDevice: '',//当前点击的设备id
       addData: {}, //添加设备选择的设备类型
+      inputMap: {
+        flowBuild: 'D1'
+      }, //信息点和输入方式映射表
+      updateInputShow: false, //是否显示临时维护输入框
+      updateInfoPoint: '',//临时维护信息点
+      updateInput: '', //临时维护信息点值
     };
   },
   methods: {
@@ -210,12 +234,17 @@ export default {
           data: {
             Orders: "sort asc",
             PageNumber: 1,
-            PageSize: 500
+            PageSize: 1000
           },
           type: this.mess.deviceId
         };
         getDataDictionary(params, res => {
           this.tableHeader = res.Content;
+          this.tableHeader.forEach(item => {
+            if(item.Path && item.InputMode){
+              this.inputMap[item.Path] = item.InputMode
+            }
+          })
           this.getTableData()
         });
       }
@@ -244,7 +273,14 @@ export default {
         }
         getEquipTableCon(param, res => {
           this.loading = false;
-          this.tableData = res.Content;
+          this.tableData = 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
+          });
           this.copyMain = tools.deepCopy(this.tableData);
           this.page.total = res.Total;
           if (this.tableData && this.tableData.length) {
@@ -385,6 +421,9 @@ export default {
       let arr = tools.copyArr(list)
       let data = showTools.headerTextFilter(arr, 'equipment', this.onlyRead, this.showType, true)
       data.unshift("操作", "当前关联的资产", "所属系统实例", "包含的部件");
+      if (this.showType == "all") {
+        data.splice(6, 0, "所属建筑楼层")
+      }
       return data;
     },
     //格式化表内容
@@ -411,9 +450,15 @@ export default {
           renderer: tools.lookDetails
         }
       );
-      if (this.onlyRead) {
-        data.map(item => {
-          item.readOnly = true
+      if (this.showType == "all") {
+        data.splice(6, 0, {
+          data: "flowBuild",
+          renderer: tools.customDropdownRenderer,
+          editor: "chosen",
+          chosenOptions: {
+            data: this.buildFloorData
+          },
+          readOnly: this.onlyRead
         })
       }
       return data;
@@ -555,6 +600,10 @@ 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")
+        }
         if (item[1] && keyList.indexOf(key) == -1 && item[1] != 'PropertyId') {
           keyList.push(key);
         }
@@ -565,8 +614,26 @@ 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.Content.push(item);
       });
@@ -593,6 +660,7 @@ export default {
     //获取到了正确的信息
     getInfors(infos, row, el) {
       let val = this.hot.colToProp(row.col);
+      let inputMode = this.inputMap[val];
       this.row = row.row;
       this.messKey = val;
       switch (val) {
@@ -600,7 +668,7 @@ export default {
         case 'caozuo':
           // window.open(`http://adm.sagacloud.cn:8058/spread?id=${infos.EquipID}&pid=${this.projectId}&secret=${this.secret}`,"_blank")
           this.$message("开发中...")
-          break;
+          return false
         //设备二维码图片
         case 'EquipQRCode':
           this.qrcodeUrl = this.tableData[row.row].EquipQRCode;
@@ -609,7 +677,7 @@ export default {
           } else {
             this.$message("此设备没有设备二维码");
           }
-          break;
+          return false
         //关联系统
         case 'LinkSystem':
           if (!this.onlyRead) {
@@ -617,37 +685,37 @@ export default {
             this.systemList = this.tableData[row.row].LinkSystem || [];
             this.myDialog.systemType = true;
           }
-          break;
+          return false
         //关联资产
         case 'LinkEquipLocalName':
           if (this.linkNameFalg) {
             this.myDialog.changeRea = true;
           }
-          break;
+          return false
         //品牌型号弹窗
         case 'DPManufacturerID':
           if (!this.onlyRead) {
             this.myDialog.firm = true;
           }
-          break;
+          return false
         //供应商信息弹窗
         case 'DPSupplierID':
           if (!this.onlyRead) {
             this.myDialog.supplier = true;
           }
-          break;
+          return false
         //维修商信息弹窗
         case 'DPMaintainerID':
           if (!this.onlyRead) {
             this.myDialog.maintainer = true;
           }
-          break;
+          return false
         //保险公司信息
         case 'DPInsurerID':
           if (!this.onlyRead) {
             this.myDialog.insurer = true;
           }
-          break;
+          return false
         //供应合同编号
         case 'LedgerParam.SupplyPurchase.SupplierContractID':
           if (!this.onlyRead) {
@@ -663,7 +731,7 @@ export default {
               this.$message("请先选择供应商");
             }
           }
-          break;
+          return false
         //保险单号
         case 'LedgerParam.InsuranceDoc.InsuranceNum':
           if (!this.onlyRead) {
@@ -679,7 +747,7 @@ export default {
               this.$message("请先选择保险商");
             }
           }
-          break;
+          return false
         //保险文件--设备文档--安装质检报告
         case 'LedgerParam.InsuranceDoc.InsuranceFile':
         case 'LedgerParam.PhotoDoc.Archive':
@@ -687,7 +755,7 @@ export default {
           let IPSdata = tools.dataForKey(this.tableData[row.row], val);
           this.filesArr = IPSdata ? IPSdata : [];
           this.myDialog.uploadFiles = true;
-          break;
+          return false
         //安装照片--安装图纸--设备铭牌照片--设备图纸
         case 'LedgerParam.Siteinstall.InstallPic':
         case 'LedgerParam.Siteinstall.InstallDrawing':
@@ -696,13 +764,13 @@ export default {
           let SSPPdata = tools.dataForKey(this.tableData[row.row], val);
           this.imgsArr = SSPPdata ? SSPPdata : [];
           this.myDialog.uploadImgs = true;
-          break;
+          return false
         //设备照片
         case 'LedgerParam.PhotoDoc.Pic':
           let Pdata = tools.dataForKey(this.tableData[row.row], val);
           this.picsArr = Pdata ? Pdata : [];
           this.myDialog.pic = true;
-          break;
+          return false
         //包含的部件字段
         case 'Count':
           if (this.onlyRead) {
@@ -710,10 +778,29 @@ export default {
           } else {
             this.$router.push({ path: '/ledger/partsmanage', query: { deviceId: infos.EquipID, typeId: this.mess.deviceId } });
           }
-          break;
+          return false
         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
+      }
+    },
+    //关闭临时维护弹窗回调
+    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 = ''
     },
     //获取被筛选掉的行号
     trimmedRows() {

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

@@ -31,6 +31,19 @@
     <!-- <dialog-assets :assetType="[this.mess.deviceId]" @close="getClose" v-if="myDialog.addDevice" ref="assets" :dialog="myDialog"></dialog-assets> -->
     <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>
     <!-- 新增系统 -->
     <el-dialog title="确定新增系统的类型" :visible.sync="myDialog.addDevice" width="30%">
       <el-row>
@@ -126,6 +139,7 @@ export default {
         addDevice: false,
         details: false,//详情页
         relevance: false,//关联设备
+        update: false,//临时维护信息点
       },
       row: null,//被修改的row
       filesArr: [],//保存临时的文件key
@@ -137,11 +151,17 @@ export default {
       iframeSrc: "",
       systemId: "",
       onlyRead: true,
-      showType: 'all',
+      showType: 'Visible',
       linkNameFalg: false,
       qrcodeUrl: "",//二维码图片地址
       loading: false,
       addData: {}, //添加设备选择的设备类型
+      inputMap: {
+        flowBuild: 'D1'
+      }, //信息点和输入方式映射表
+      updateInputShow: false, //是否显示临时维护输入框
+      updateInfoPoint: '',//临时维护信息点
+      updateInput: '', //临时维护信息点值
     };
   },
   created() {
@@ -166,6 +186,11 @@ export default {
         }
         getDataDictionary(params, res => {
           this.tableHeader = res.Content;
+          this.tableHeader.forEach(item => {
+            if(item.Path && item.InputMode){
+              this.inputMap[item.Path] = item.InputMode
+            }
+          })
           this.getTableData()
         });
       }
@@ -486,6 +511,7 @@ export default {
     getInfors(infos, row) {
       //其他的开始判断
       let val = this.hot.colToProp(row.col);
+      let inputMode = this.inputMap[val];
       this.systemId = infos.SysID
       this.row = row.row
       this.messKey = val
@@ -494,7 +520,7 @@ export default {
         case 'caozuo':
           // window.open(`http://adm.sagacloud.cn:8058/system?id=${infos.id}&pid=${this.projectId}&secret=${this.secret}`,"_blank")
           this.$message("开发中...")
-          break;
+          return false
         //设备二维码图片
         case 'EquipQRCode':
           this.qrcodeUrl = this.tableData[row.row].EquipQRCode;
@@ -503,16 +529,35 @@ export default {
           } else {
             this.$message("此设备没有设备二维码");
           }
-          break;
+          return false
         //关联设备数量
         case 'Count':
           if (!this.onlyRead) {
             this.myDialog.relevance = true
           }
-          break;
+          return false
         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
+      }
+    },
+    //关闭临时维护弹窗回调
+    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 = ''
     },
     //获取被筛选掉的行号
     trimmedRows() {

+ 319 - 0
src/components/ledger/lib/linkassets.vue

@@ -0,0 +1,319 @@
+<template>
+  <el-dialog title="批量关联资产" :visible.sync="dialog.linkAssets" @open="handleOpenReset" width="700px">
+    <el-row>
+      <span class="condition-title">设备类型:</span>
+      <el-select v-model="deviceType" filterable size="small" @change="handleChangeDevice" style="width:350px;">
+        <el-option  v-for="item in deviceTypeList" :key="item.Category" :label="item.CategoryName" :value="item.Category"></el-option>
+      </el-select>
+    </el-row>
+    <el-row style="margin-top:30px;">
+      <span class="condition-title">建筑楼层:</span>
+      <el-cascader :options="bfoptions" v-model="buildFloor" filterable size="small" @change="handleChangeBf" style="width:350px;"></el-cascader>
+    </el-row>
+    <el-row style="margin-top:30px;"  v-show="spaceShow">
+      <span class="condition-title">分区类型:</span>
+      <el-select v-model="zone" filterable size="small" @change="handleChangeZone" style="width:350px;">
+        <el-option  v-for="item in zoneList" :key="item.Code" :label="item.Name" :value="item.Code"></el-option>
+      </el-select>
+    </el-row>
+    <el-row style="margin-top:30px;" v-show="spaceShow && zone != 'all' && zone != 'noKnow'">
+      <span class="condition-title">空间实例:</span>
+      <el-select v-model="space" multiple filterable collapse-tags style="width:350px;" placeholder="请选择">
+        <el-option v-for="item in spaceList" :key="item.value" :label="item.label" :value="item.value">
+        </el-option>
+      </el-select>
+    </el-row>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="handleClickClose">取 消</el-button>
+      <el-button type="primary" @click="toLinkAssets">确 认</el-button>
+    </span>
+  </el-dialog>
+</template>
+<script>
+
+import { floorQuery, buildingQuery, queryDictionaryHead, queryZone, TypePartsDie } from '@/api/scan/request'
+
+import { mapGetters } from "vuex"
+export default {
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          linkAssets: false
+        };
+      }
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"])
+  },
+  data() {
+    return {
+      bfoptions: [], //建筑楼层列表
+      buildFloor: ['all'], //选择的建筑楼层
+      deviceTypeList: [], //未关联资产的设备或部件列表
+      deviceType: '', //选择的设备类型
+      zone: 'all', //空间分区
+      zoneList: [], //空间分区列表
+      spaceList: [], //空间实例列表
+      space: [], //选择的空间实例
+      spaceShow: false
+    };
+  },
+  created() {
+    this.getPartsDieType() //获取未关联资产的设备或部件类型
+    this.getBuildFloorData() //获取建筑楼层数据
+    this.getSpaceData() //获取分区类型数据
+  },
+  mounted() { },
+  methods: {
+    //打开弹窗回调,初始化选择
+    handleOpenReset(){
+      this.deviceType = ''
+      this.buildFloor = ['all']
+      this.zone = 'all'
+      this.space = []
+      this.spaceShow = false
+    },
+    //获取未关联资产的设备或部件类型
+    getPartsDieType() {
+      TypePartsDie(res => {
+        this.deviceTypeList = res.Content.filter(item => {
+          return item.CategoryName
+        })
+      })
+    },
+    //获取建筑楼层数据
+    getBuildFloorData() {
+      let data, buildParams = {
+        PageNumber: 1,
+        PageSize: 1000,
+        Projection: [
+          "BuildID",
+          "BuildLocalName"
+        ]
+      }, floorParams = {
+        Orders: "FloorSequenceID desc",
+        PageNumber: 1,
+        PageSize: 1000,
+        Projection: [
+          "BuildID",
+          "FloorID",
+          "FloorLocalName",
+          "FloorSequenceID"
+        ]
+      }
+      let promise1 = new Promise((resolve, reject) => {
+        buildingQuery(buildParams, res => {
+          resolve(res)
+        })
+      })
+      let promise2 = new Promise((resolve, reject) => {
+        floorQuery(floorParams, res => {
+          resolve(res)
+        })
+      })
+      Promise.all([promise1, promise2]).then(values => {
+        let builData = values[0].Content, floorData = values[1].Content
+        data = builData.map(build => {
+          return {
+            value: build.BuildID,
+            label: build.BuildLocalName
+          }
+        })
+        data.unshift({
+          value: "all",
+          label: "全部"
+        }, {
+            value: "noKnow",
+            label: "不在建筑内"
+          })
+        data.forEach(build => {
+          floorData.forEach(floor => {
+            if (build.value == floor.BuildID && floor.FloorID && floor.FloorLocalName) {
+              if (build.children) {
+                build.children.push({
+                  value: floor.FloorID,
+                  label: floor.FloorLocalName,
+                  FloorSequenceID: floor.FloorSequenceID
+                })
+              } else {
+                build.children = []
+                build.children.push({
+                  value: "all",
+                  label: "全部"
+                }, {
+                    value: 'noKnow',
+                    label: "不在楼层内"
+                  }, {
+                    value: floor.FloorID,
+                    label: floor.FloorLocalName,
+                    FloorSequenceID: floor.FloorSequenceID
+                  })
+              }
+            }
+          })
+        })
+        this.bfoptions = data
+      })
+    },
+    //获取空间分区数据
+    getSpaceData(){
+      let params = {
+        Filters: "parentId = 'Space'",
+        PageNumber: 1,
+        PageSize: 1000,
+        Projection: [ "Code", "Name" ]
+      }
+      queryDictionaryHead(params, res => {
+        this.zoneList = res.Content.filter(item => {
+          if(item.Code != 'Ispace'){
+            return item
+          }
+        })
+        this.zoneList.unshift({
+          Name: '全部',
+          Code: 'all'
+        })
+        this.zoneList.push({
+          Name: '不在任何业务空间内',
+          Code: 'noKnow'
+        })
+      })
+    },
+    // 修改设备类型
+    handleChangeDevice(val) {
+      this.zoneListIsShow()
+    },
+    // 修改建筑楼层
+    handleChangeBf(val) {
+      this.zoneListIsShow()
+      // 重置空间实例选择
+      this.space = []
+      this.spaceList = []
+      this.handleChangeSpaceItem()
+    },
+    //判断是否显示空间分区选择
+    zoneListIsShow(){
+      let lastVal = this.buildFloor.slice(-1)[0]
+      if(!lastVal || lastVal == 'noKnow' || this.buildFloor[0] == 'all' || this.deviceType.length != 4) {
+        this.spaceShow = false
+      } else {
+        this.spaceShow = true
+      }
+    },
+    //修改分区类型
+    handleChangeZone() {
+      // 重置空间实例选择
+      this.space = []
+      this.spaceList = []
+      this.handleChangeSpaceItem()
+    },
+    // 获取空间实例
+    handleChangeSpaceItem() {
+      if(this.zone != 'all' && this.zone != 'noKnow') {
+        let nodes = []
+        let recursionGetData = (pageNum, zone) => {
+          pageNum = pageNum ? pageNum : 1
+          let params = {
+            zone: zone,
+            data: {
+              Orders: "CreateTime desc, RoomID asc",
+              PageNumber: pageNum,
+              PageSize: 1000,
+              Projection: ["RoomID", "RoomName", "RoomLocalName", "CreateTime"]
+            },
+          }
+          if(this.spaceShow) {
+            if(this.buildFloor.length == 2 && this.buildFloor[1] != 'all') {
+              params.data.Filters = `buildingId='${this.buildFloor[0]}';floorId='${this.buildFloor[1]}'`
+            } else {
+              params.data.Filters = `buildingId='${this.buildFloor[0]}'`
+            }
+          }
+          queryZone(params, res => {
+            nodes = nodes.concat(res.Content.map(item => ({
+              value: item.RoomID,
+              label: item.RoomLocalName?item.RoomLocalName:item.RoomName
+            })))
+            if (res.Total / (res.PageSize * res.PageNumber) > 1) {
+              recursionGetData(res.PageNumber + 1, zone)
+            } else {
+              this.spaceList = nodes
+            }
+          })
+        }
+        recursionGetData(1, this.zone)
+      }
+    },
+    // 点击取消关闭弹窗
+    handleClickClose() {
+      this.dialog.linkAssets = false
+    },
+    // 批量关联资产详情页
+    toLinkAssets() {
+      let query = {}
+      // 校验必填项
+      if(!this.deviceType) {
+        this.$message.info('请选择设备类型!')
+        return false
+      } else if (!this.buildFloor.length) {
+        this.$message.info('请选择建筑楼层!')
+        return false
+      }
+      if(this.spaceShow) { //选择了空间
+        if(this.zone == 'all'){//全部空间
+          query = {
+            deviceType: this.deviceType,
+            buildFloor: this.buildFloor
+          }
+        } else {
+          if(this.space.length){//选择了具体的空间实例
+            query = {
+              deviceType: this.deviceType,
+              buildFloor: this.buildFloor,
+              spaceList: this.space
+            }
+          } else {
+            query = {
+              deviceType: this.deviceType,
+              buildFloor: this.buildFloor,
+              spaceList: this.zone //(包含具体的业务空间分区和不在任何分区两种情况)
+            }
+          }
+        }
+      } else {
+        query = {
+          deviceType: this.deviceType,
+          buildFloor: this.buildFloor
+        }
+      }
+      this.$router.push({
+        name: "batchlinkAssets",
+        params: query
+      })
+    }
+  },
+  watch: {
+    
+  }
+};
+</script>
+
+<style lang="less" scoped>
+  .condition-title{
+    width: 100px;
+    display: inline-block;
+    text-align: right;
+    margin-left: 10px;
+    margin-right: 12px;
+    color: #999999;
+    font-size: 14px;
+    vertical-align: top;
+  }
+  /deep/ .el-dialog__body {
+    max-height: 420px;
+    overflow-y: auto;
+  }
+</style>

+ 2 - 1
src/components/model/file/addFloorDialog.vue

@@ -162,7 +162,8 @@ export default {
             FolderId: this.FolderId,
             FloorName: FloorName,
             Form: this.form,
-            userName:this.userInfo.username
+            userName: this.userInfo.userName,
+            userId: this.userInfo.userId
           };
           request.createFloor(data).then(res => {
             if (res.Result == "success") {

+ 45 - 69
src/components/model/file/floorTable.vue

@@ -1,72 +1,50 @@
 <template>
-  <el-table
-    ref="filterTable"
-    :data="tableData"
-    style="width: 100%"
-    :height="maxHeight"
-    :header-cell-style="{background:'#d9d9d9',color:'#2b2b2b'}"
-  >
-    <el-table-column prop="FloorName" label="模型文件" width="180">
-      <template slot-scope="scope">
-        <i class="el-icon-document-checked icon_font"></i>
-        <span style="margin-left: 10px">{{ scope.row.FloorName }}</span>
-      </template>
-    </el-table-column>
-    <el-table-column prop="Note" label="备注" width="180"></el-table-column>
-    <el-table-column prop="Version" label="版本号"></el-table-column>
-    <el-table-column prop="AcceptTime" label="上传时间"></el-table-column>
-    <el-table-column prop="UserName" label="上传人"></el-table-column>
-    <el-table-column prop="address" align="center" label="操作"  width="240">
-      <template slot-scope="scope">
-        <div class="operate" v-show="!scope.row.isDown">
-          <el-button
-            type="primary"
-            size="mini"
-            class="iconfont icon-download"
-            @click="downloadModel(scope.row)"
-          ></el-button>
-          <el-button
-            type="primary"
-            size="mini"
-            class="iconfont icon-replace"
-            @click="repliaceModel(scope.row)"
-          ></el-button>
-          <el-button
-            type="primary"
-            size="mini"
-            class="iconfont icon-Log"
-            @click="queryModelLog(scope.row)"
-          ></el-button>
-        </div>
-        <div
-          :class="[scope.row.Status == 1 || scope.row.Status == 10 || scope.row.Status == 11 || (!scope.row.Status && scope.row.precent == 100)? 'upLoad-loading':'','upLoad']"
-          v-show="scope.row.isDown"
-        >
-          <div class="progress">
-            <el-progress
-              :text-inside="scope.row.Status == 1 || scope.row.Status == 10 || scope.row.Status == 11 || (!scope.row.Status && scope.row.precent == 100)?false:true"
-              :stroke-width="20"
-              :percentage="scope.row.precent"
-              :color="scope.row.Status == 1 || scope.row.Status == 10 || scope.row.Status == 11?'#909399':'#67C23A'"
-            ></el-progress>
+  <div class="filterTable-container">
+    <el-table ref="filterTable" :data="tableData" style="width: 100%" height="100%" :header-cell-style="{background:'#d9d9d9',color:'#2b2b2b'}">
+      <el-table-column prop="FloorName" label="模型文件" width="180">
+        <template slot-scope="scope">
+          <i class="el-icon-document-checked icon_font"></i>
+          <span style="margin-left: 10px">{{ scope.row.FloorName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="Note" label="备注" width="180"></el-table-column>
+      <el-table-column prop="Version" label="版本号"></el-table-column>
+      <el-table-column prop="AcceptTime" label="上传时间"></el-table-column>
+      <el-table-column prop="UserName" label="上传人"></el-table-column>
+      <el-table-column prop="address" align="center" label="操作" width="240">
+        <template slot-scope="scope">
+          <div class="operate" v-show="!scope.row.isDown">
+            <el-button type="primary" size="mini" class="iconfont icon-download" @click="downloadModel(scope.row)"></el-button>
+            <el-button type="primary" size="mini" class="iconfont icon-replace" @click="repliaceModel(scope.row)"></el-button>
+            <el-button type="primary" size="mini" class="iconfont icon-Log" @click="queryModelLog(scope.row)"></el-button>
           </div>
-          <div class="progress-right">
-            <!-- <el-button
+          <div
+            :class="[scope.row.Status == 1 || scope.row.Status == 10 || scope.row.Status == 11 || (!scope.row.Status && scope.row.precent == 100)? 'upLoad-loading':'','upLoad']"
+            v-show="scope.row.isDown">
+            <div class="progress">
+              <el-progress
+                :text-inside="scope.row.Status == 1 || scope.row.Status == 10 || scope.row.Status == 11 || (!scope.row.Status && scope.row.precent == 100)?false:true"
+                :stroke-width="20" :percentage="scope.row.precent"
+                :color="scope.row.Status == 1 || scope.row.Status == 10 || scope.row.Status == 11?'#909399':'#67C23A'"></el-progress>
+            </div>
+            <div class="progress-right">
+              <!-- <el-button
               v-show="!scope.row.Status"
               type="danger"
               class="iconfont icon-termination"
               @click="closeUpdate(scope.row)"
               circle
             ></el-button>-->
-            <span v-show="!scope.row.Status && scope.row.precent == 100">上传中</span>
-            <span v-show="scope.row.Status == 1">等待检查...</span>
-            <span v-show="scope.row.Status == 10">模型检查中</span>
-            <span v-show="scope.row.Status == 11">未通过检查</span>
+              <span v-show="!scope.row.Status && scope.row.precent == 100">上传中</span>
+              <span v-show="scope.row.Status == 1">等待检查...</span>
+              <span v-show="scope.row.Status == 10">模型检查中</span>
+              <span v-show="scope.row.Status == 11">未通过检查</span>
+            </div>
           </div>
-        </div>
-      </template>
-    </el-table-column>
-  </el-table>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
 </template>
 <script>
 import { mapGetters } from "vuex";
@@ -91,7 +69,7 @@ export default {
     },
     // 替换日志
     repliaceModel(item) {
-      if (item.Status != 4) {
+      if (item.Status != 4 && item.Status != 21) {
         this.$alert("正在识别模型对象,请稍后再替换。", "替换模型", {
           confirmButtonText: "确定",
           callback: action => {
@@ -126,7 +104,7 @@ export default {
       if (item.Url) {
         let a = document.createElement("a");
         a.href = item.Url;
-        a.download =`${this.modelFolderName}${item.FloorName}模型文件v${item.Version}.rvt`;
+        a.download = `${this.modelFolderName}${item.FloorName}模型文件v${item.Version}.rvt`;
         a.click();
       } else {
         this.$message({
@@ -137,7 +115,7 @@ export default {
     },
     // 停止上传
     closeUpdate(item) {
-      if (this.userInfo.username == item.UserName) {
+      if (this.userInfo.userName == item.UserName) {
         this.$emit("closeUpdateFile", item);
       } else {
         this.$message({
@@ -151,7 +129,7 @@ export default {
     persentList: {
       immediate: true,
       deep: true,
-      handler: function(val, oldVal) {
+      handler: function (val, oldVal) {
         if (val.length != 0) {
           val.map(item => {
             if (item.precent != 0) {
@@ -161,17 +139,15 @@ export default {
         }
       }
     }
-  },
-  mounted() {
-    this.$nextTick(function() {
-      this.maxHeight = $("#file_moddle_manage").height() - 60; // 获取最外层的高度
-    });
   }
 };
 </script>
 <style scoped lang="less">
 .box-card {
   height: 100%;
+  .filterTable-container {
+    height: calc(100% - 80px);
+  }
   .operate {
     .iconfont {
       font-size: 12px;

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

@@ -247,7 +247,7 @@ export default {
   }
   /deep/ .table-area {
     width: 100%;
-    height: calc(100% - 125px);
+    height: calc(100% - 71px);
     margin-bottom: 10px;
     td div {
       white-space: nowrap;

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

@@ -248,7 +248,7 @@ export default {
   }
   /deep/ .table-area {
     width: 100%;
-    height: calc(100% - 125px);
+    height: calc(100% - 71px);
     margin-bottom: 10px;
     td div {
       white-space: nowrap;

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

@@ -248,7 +248,7 @@ export default {
   }
   /deep/ .table-area {
     width: 100%;
-    height: calc(100% - 125px);
+    height: calc(100% - 71px);
     margin-bottom: 10px;
     td div {
       white-space: nowrap;

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

@@ -248,7 +248,7 @@ export default {
   }
   /deep/ .table-area {
     width: 100%;
-    height: calc(100% - 125px);
+    height: calc(100% - 71px);
     margin-bottom: 10px;
     td div {
       white-space: nowrap;

+ 1 - 1
src/components/ready/buildfloor/formItems.vue

@@ -88,7 +88,7 @@ export default {
     }
   }
   /deep/ .FloorTypeSelect .el-form-item__content {
-    width: 178px;
+    width: 200px;
   }
 }
 </style>

+ 151 - 0
src/framework/components/messagesever/index.vue

@@ -0,0 +1,151 @@
+<!--
+ * @Author: zhangyu
+ * @Date: 2019-08-26 15:22:13
+ * @Info: 
+ * @LastEditTime: 2019-09-26 20:16:41
+ -->
+<template>
+  <div class="notification-box" @click="handleClickRead">
+    <el-badge :value="unreadNum" :hidden="!unreadNum" :max="99">
+      <i class="el-icon-message-solid"></i>
+    </el-badge>
+    <!-- <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>
+    <el-input type="textarea" :autosize="{ minRows: 6, maxRows: 6}" v-model="sendMessage" placeholder="请输入要发送的内容"></el-input>
+    <br><br>
+    <el-button type="primary" @click="handleClickSendMessage">发送消息</el-button>
+    <el-card style="margin-top:20px;text-align:left;">
+      <div slot="header" class="clearfix">
+        <span>消息历史</span>
+      </div>
+      <div v-for="(message, index) in messageList" :key="index" class="text item">
+        {{ message }}
+      </div>
+    </el-card> -->
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import Stomp from 'stompjs'
+import Msmq from './msmq'
+import { MQTT_SERVICE, MQTT_USERNAME, MQTT_PASSWORD } from './mqSetting'
+
+export default {
+  data() {
+    return {
+      client: Stomp.client(MQTT_SERVICE),
+      unreadNum: 0,
+      sendMessage: '',
+      messageList: [], // 历史消息
+      subList: [], // 订阅的消息实例
+      topics: ["/topic/model.manage"] // 订阅的消息名称
+    }
+  },
+  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)
+  },
+  computed: {
+    ...mapGetters('layout', ['userInfo', 'projectId', 'projects'])
+  },
+  methods:{
+    connect() {
+      this.client = Stomp.client(MQTT_SERVICE)
+      this.client.reconnect_delay = 5000
+      var clientid = `sagaMQ-${this.userInfo.userName}`
+      var headers = {
+        'login': MQTT_USERNAME,
+        'passcode': MQTT_PASSWORD,
+        'client-id': clientid
+      }
+      this.client.connect(headers, this.onConnected, this.onFailed)
+    },
+    onConnected(frame) {
+      console.log('Connected: ' + frame)
+      //订阅多个消息
+      this.topics.forEach(item => {
+        let sub = this.client.subscribe(item, this.onmessage, this.onFailed)
+        this.subList.push(sub)
+      })
+      // this.client.subscribe(topic, this.onmessage, this.onFailed) 
+    },
+    //接收到消息的回调
+    onmessage(message) {
+      this.unreadNum = Msmq.handleMsg(message, this.projects, this.unreadNum);
+    },
+    // 接收消息失败回调
+    onFailed(frame) {
+      console.log('Failed: ' + frame)
+    },
+    //停止接收消息
+    unsubscribe() {
+      this.subList.forEach((item) => {
+        item.unsubscribe()
+      })
+    },
+    //断开连接
+    disconnect() {
+      this.client.disconnect(function() {
+        console.log("连接已断开!");
+      })
+    },
+    //发送消息
+    send(destination, message, headers = {}) {
+      this.client.send(destination, headers, JSON.stringify(message))
+    },
+    
+    handleClickConnectMQ() {
+      this.connect()
+    },
+    handleClickDisconnectMQ() {
+      this.disconnect()
+    },
+    handleClickUnsubscribe() {
+      this.unsubscribe()
+    },
+    handleClickSendMessage() {
+      this.send('/topic/datacenter.broadcast',this.sendMessage)
+    }, 
+    handleClickRead() {
+      this.unreadNum = 0;
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .notification-box{
+    width: 100%;
+    height: 100%;
+    padding: 16px 10px 10px;
+    box-sizing: border-box;
+    color: #79869a;
+    cursor: pointer;
+    .el-icon-message-solid{
+      font-size: 22px;
+    }
+    /deep/ .el-badge__content{
+      height: 16px;
+      line-height: 16px;
+      border: 1px solid transparent;
+    }
+  }
+  .notification-box:hover{
+    color: #d3d8e2;
+    background-color: #3f4f62;
+  }
+</style>

+ 9 - 0
src/framework/components/messagesever/mqSetting.js

@@ -0,0 +1,9 @@
+/*
+ * @Author: zhangyu
+ * @Date: 2019-08-26 16:03:46
+ * @Info: 
+ * @LastEditTime: 2019-09-05 14:46:30
+ */
+export const MQTT_SERVICE = process.env.MQTT_SERVICE // mq服务地址
+export const MQTT_USERNAME = 'admin' // mq连接用户名
+export const MQTT_PASSWORD = 'admin' // mq连接密码

+ 22 - 0
src/framework/components/messagesever/msmq.js

@@ -0,0 +1,22 @@
+import { Notification } from 'element-ui';
+import Bus from '@/utils/bus.js'
+
+const MSMQ = {
+  handleMsg (message, projects, 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)
+      }
+      // 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
+    // }
+  }
+}
+
+export default MSMQ

+ 14 - 6
src/framework/layout/PageHeader.vue

@@ -18,7 +18,7 @@
         <div id='page-header-user-menu' class='user-menu'>
             <el-dropdown trigger='hover' class='user-menu-dropdown' @command='userMenuCommand'>
                 <span class='el-dropdown-link'>
-                    {{userInfo.username}}
+                    {{userInfo.userName}}
                     <i class='el-icon-fa-user el-icon--right'></i>
                 </span>
                 <el-dropdown-menu slot='dropdown'>
@@ -26,12 +26,18 @@
                     <el-dropdown-item icon='el-icon-circle-plus'>修改密码</el-dropdown-item>
                 </el-dropdown-menu>
             </el-dropdown>
+            <ul class="header-nav">
+                <li class="header-nav-notification">
+                    <message-sever></message-sever>
+                </li>
+            </ul>
         </div>
     </div>
 </template>
 <script>
 import frameworkApi from '@/api/framework'
 import { mapGetters, mapMutations } from 'vuex'
+import MessageSever from '../components/messagesever/index'
 export default {
     name: 'PageHeader',
     props: [],
@@ -67,16 +73,18 @@ export default {
     },
     created() {
         let cacheInfo = JSON.parse(localStorage.getItem('_sagacloud_admin_store_cacheInfo'))?JSON.parse(localStorage.getItem('_sagacloud_admin_store_cacheInfo')):{}
-        if(cacheInfo[this.userInfo.username] && 
-            cacheInfo[this.userInfo.username].projectId && 
-            this.projects.some((item) => {return item.id == cacheInfo[this.userInfo.username].projectId})
+        if(cacheInfo[this.userInfo.userName] && 
+            cacheInfo[this.userInfo.userName].projectId && 
+            this.projects.some((item) => {return item.id == cacheInfo[this.userInfo.userName].projectId})
         ){
-            this.selectedProjectId = cacheInfo[this.userInfo.username].projectId
+            this.selectedProjectId = cacheInfo[this.userInfo.userName].projectId
         } else {
             this.selectedProjectId = this.projectId
         }
     },
     mounted() {},
-    components: {}
+    components: {
+        MessageSever
+    }
 }
 </script>

+ 8 - 28
src/framework/layout/layout-store.js

@@ -17,8 +17,8 @@ export default {
         projectId: '',
         projects: [],
         breadcrumb: [],
-        secret: "", //密码
-        userId: "test", //用户id
+        secret: "", //项目密码
+        userId: "", //用户id
     },
     getters: {
         sidebarClosed: state => state.sidebarClosed,
@@ -66,11 +66,11 @@ export default {
             let cacheInfo = JSON.parse(localStorage.getItem('_sagacloud_admin_store_cacheInfo'))?JSON.parse(localStorage.getItem('_sagacloud_admin_store_cacheInfo')):{}
             state.projectId = val
             localStorage.setItem('projectId', val)
-            if(cacheInfo[state.userInfo.username]){
-                cacheInfo[state.userInfo.username].projectId = val
+            if(cacheInfo[state.userInfo.userName]){
+                cacheInfo[state.userInfo.userName].projectId = val
                 localStorage.setItem('_sagacloud_admin_store_cacheInfo', JSON.stringify(cacheInfo))
             } else {
-                cacheInfo[state.userInfo.username] = {projectId: val}
+                cacheInfo[state.userInfo.userName] = {projectId: val}
                 localStorage.setItem('_sagacloud_admin_store_cacheInfo', JSON.stringify(cacheInfo))
             }
             storage.set(KEY_PROJECT_SELECTED, val)
@@ -87,31 +87,11 @@ export default {
             return new Promise((resolve, reject) => {
                 frameworkApi.loadUserInfo().then(resp => {
                     console.log(resp)
-                    // if (resp.result == 'success') {
-                    //     state.userInfo = { username: resp.username }
-                    //     storage.set('user_name', resp.username)
-                    //     state.permissions = {}
-                    //     if (resp.permissions) {
-                    //         resp.permissions.forEach(p => (state.permissions[p] = true))
-                    //     }
-                    //     state.projects = []
-                    //     if (resp.projects) {
-                    //         if(resp.projects[0] && resp.projects[0].projId) {
-                    //             state.projectId = resp.projects[0].projId
-                    //             state.secret = resp.projects[0].secret?resp.projects[0].secret:""
-                    //         }
-                    //         resp.projects.forEach(proj =>
-                    //             state.projects.push({
-                    //                 id: proj.projId,
-                    //                 name: proj.projLocalName,
-                    //                 pwd: proj.secret?proj.secret:""
-                    //             })
-                    //         )
-                    //     }
-                    // } else {
                     if (resp.Result == 'success') {
-                        state.userInfo = { username: resp.Username }
+                        state.userInfo = { userName: resp.Username, userId: resp.UserId }
+                        state.userId = resp.UserId
                         storage.set('user_name', resp.Username)
+                        storage.set('user_id', resp.UserId)
                         state.permissions = {}
                         if (resp.Permissions) {
                             resp.Permissions.forEach(p => (state.permissions[p] = true))

+ 10 - 0
src/framework/style/layout.scss

@@ -114,6 +114,16 @@ body {
         height: 100%;
         display: inline-flex;
         flex-direction: row-reverse;
+        .header-nav{
+            margin-right: 10px;
+            >li{
+                float: left;
+                width: 50px;
+                height: 50px;
+                padding: 0 4px;
+                box-sizing: border-box;
+            }
+        }
         .user-menu-dropdown {
             height: 100%;
             line-height: $pageHeaderHeight;

+ 27 - 6
src/router/system.js

@@ -56,13 +56,16 @@ 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 batchlinkAssets from '@/views/ledger/facility/batchlink' //批量关联资产
 import cenotelist from '@/views/ledger/cenotelist' //竖井清单
 import cenoteadd from '@/views/ledger/cenotelist/cenoteadd' //添加竖井
+import cenoteDetail from '@/views/ledger/cenotelist/cenoteDetail' //竖井关系详情
 import rentlist from '@/views/ledger/rentlist' //租户清单
-import rentadd from '@/views/ledger/rentlist/rentadd' //竖井清单
+import rentadd from '@/views/ledger/rentlist/rentadd' //租户清单
 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 maintain from '@/views/relation/maintain'
@@ -97,11 +100,11 @@ export default [
         name: 'LayoutMain',
         component: LayoutMain,
         children: [
-            // { path: 'buildfloor', name: 'buildFloor', component: buildFloor, meta: { keepAlive: false, breadcrumbs: [{ label: '建筑楼层管理' }] } },
-            { path: 'buildfloor', name: 'buildFloor', component: Dasboard, meta: { keepAlive: false, breadcrumbs: [{ label: '建筑楼层管理' }] } },
+            { path: 'buildfloor', name: 'buildFloor', component: buildFloor, meta: { keepAlive: false, breadcrumbs: [{ label: '建筑楼层管理' }] } },
+            // { 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: 'buildfloor/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:'平面图维护' }] }}
         ]
     },
     //模型管理
@@ -114,8 +117,8 @@ export default [
             {
                 path: 'file',
                 name: 'modelFile',
-                component: Dasboard,
-                // component: modelFile,
+                // component: Dasboard,
+                component: modelFile,
                 meta: { keepAlive: false, breadcrumbs: [{ label: '模型管理', path: '/model/file' }, { label: '模型文件管理' }] }
             },
             {
@@ -280,6 +283,12 @@ export default [
                 meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '设备台账', path: '/ledger/facility' }, { label: '添加设备' }] }
             },
             {
+                path: 'batchlinkAssets',
+                name: 'batchlinkAssets',
+                component: batchlinkAssets,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '设备台账', path: '/ledger/facility' }, { label: '批量关联资产' }] }
+            },
+            {
                 path: 'property',
                 name: 'propertyLedger',
                 component: propertyLedger,
@@ -316,6 +325,12 @@ export default [
                 meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '业务空间台账' }] }
             },
             {
+                path: 'spaceDetail',
+                name: 'spaceDetail',
+                component: spaceDetail,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '业务空间台账',path: '/ledger/spacelist' }, {label:'业务空间详情'}] }
+            },
+            {
                 path: 'cenotelist',
                 name: 'cenotelist',
                 component: cenotelist,
@@ -328,6 +343,12 @@ export default [
                 meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '竖井台账', path: '/ledger/cenotelist' }, { label: '添加竖井' }] }
             },
             {
+                path: 'cenoteDetail',
+                name: 'cenoteDetail',
+                component: cenoteDetail,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '竖井台账', path: '/ledger/cenotelist' }, { label: '竖井关系详情' }] }
+            },
+            {
                 path: 'rentlist',
                 name: 'rentlist',
                 component: rentlist,

+ 0 - 2
src/store/index.js

@@ -3,7 +3,6 @@ import Vuex from 'vuex'
 import storage from '@/framework/utils/storage'
 import layout from '@/framework/layout/layout-store'
 import project from "./modules/project"
-import peojMess from "./modules/proMess"
 import alarm from './modules/alarm'
 Vue.use(Vuex)
 const KEY_LAST_ROUTE = 'last_route'
@@ -38,7 +37,6 @@ export default new Vuex.Store({
     modules: {
         layout,
         project,
-        peojMess,
         alarm
     }
 })

+ 3 - 3
src/store/modules/alarm.js

@@ -20,9 +20,9 @@ const alarm = {
           state.spaceNameObj = spaceNameObj
       },
     //   空间code值dict
-        SPACE_CODE_OBJ(state, spaceCodeObj) {
-            state.spaceCodeObj = spaceCodeObj
-        }
+      SPACE_CODE_OBJ(state, spaceCodeObj) {
+          state.spaceCodeObj = spaceCodeObj
+      }
   }
 }
 export default alarm;

+ 0 - 29
src/store/modules/proMess.js

@@ -1,29 +0,0 @@
-const project_mess = {
-    namespaced: true,
-    state: {
-        projectId: "", //项目id
-        secret: "", //数据源id
-        userId: "test", //数据源类型
-    },
-    mutations: {
-        set_project(state, val) {
-            state.projectId = val
-        },
-        set_secret(state, val) {
-            state.secret = val
-        },
-        set_userId(state, val) {
-            state.userId = val
-        }
-    },
-    actions: {
-
-    },
-    getters: {
-        projectId: state => state.projectId,
-        userId: state => state.userId,
-        secret: state => state.secret
-    }
-}
-
-export default project_mess

+ 2 - 0
src/utils/bus.js

@@ -0,0 +1,2 @@
+import Vue from 'vue'
+export default new Vue

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

@@ -11,11 +11,21 @@ const data = {
   },
   tenant: { //租户
     onlyRead: [],
-    edit: []
+    edit: [
+      "TenantID",
+      "TenantName",
+      "BIMID",
+      "BIMLocation"
+    ]
   },
   shaft: { //竖井
     onlyRead: [],
-    edit: []
+    edit: [
+      "ShaftID",
+      "ShaftName",
+      "BIMID",
+      "BIMLocation"
+    ]
   },
   parts: { //部件
     onlyRead: [],

+ 3 - 6
src/utils/handsontable/notShow.js

@@ -139,6 +139,7 @@ let partsAddNoShow = [
     "InsurerFax",
 ]
 const showTools = {
+    InputModeArr: ["A1", "A2", "B1", "B2", "C5", "D1", "D1L", "D2", "E1", "E2", "L", "L1", "L2", "F1", "F2", "M"],
     addArr: () => {
         return cutArr
     },
@@ -1055,9 +1056,7 @@ const showTools = {
                 readOnly: onlyRead,
                 correctFormat: true
             };
-        } else if (item.InputMode == "A3" ||
-            item.InputMode == "A4" ||
-            item.InputMode == "B1" ||
+        } else if (item.InputMode == "B1" ||
             item.InputMode == "B2" ||
             item.InputMode == "F1" ||
             item.InputMode == "F2" ||
@@ -1166,9 +1165,7 @@ const showTools = {
                 readOnly: !item.Editable,
                 correctFormat: true
             };
-        } else if (item.InputMode == "A3" ||
-            item.InputMode == "A4" ||
-            item.InputMode == "B1" ||
+        } else if (item.InputMode == "B1" ||
             item.InputMode == "B2" ||
             item.InputMode == "F1" ||
             item.InputMode == "F2" ||

+ 3 - 3
src/views/data_admin/buildAssets/index.vue

@@ -145,9 +145,9 @@ export default {
         background:#fff;
         margin-bottom: 10px;
     }
+    /deep/ .el-tabs__nav{
+        margin-left: 10px;
+    }
 }
 </style>
-<style>
-.box .el-tabs__nav {margin-left: 10px;}
-</style>
 

+ 140 - 0
src/views/ledger/cenotelist/cenoteDetail/index.vue

@@ -0,0 +1,140 @@
+<template>
+  <div class="box">
+    <div class="condition">
+      <div class="header">
+        <el-button style="float:left;" size="small" type="default" icon="el-icon-back" @click="goBack"></el-button>
+        <span>{{params.name||''}}</span>
+      </div>
+      <el-row class="spaceTypes">
+        <div class="types">
+          <el-tabs v-model="activeTab" type='card'>
+            <template v-for="(item,index) in tabsList">
+              <el-tab-pane :name="item.Code" :key="index" :label="item.Name"></el-tab-pane>
+            </template>
+          </el-tabs>
+        </div>
+        <div class="deleBtn">
+          <el-button size="small" @click="deleteCenote">删除竖井</el-button>
+        </div>
+      </el-row>
+      <!-- 竖井内的设备 -->
+      <device-table v-if="activeTab=='device'" :params="params" :type="activeTab"></device-table>
+      <!-- 连通的其他竖井 -->
+      <cenote-table v-else-if="activeTab=='cenote'" :params="params" :type="activeTab"></cenote-table>
+      <!-- 竖井内系统 -->
+      <system-table v-else-if="activeTab=='system'" :params="params" :type="activeTab"></system-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex"
+import { deleteCenoteTableData } from '@/api/scan/request'
+import cenoteTable from '@/components/ledger/cenote/table/cenoteTable'
+import deviceTable from '@/components/ledger/cenote/table/deviceTable'
+import systemTable from '@/components/ledger/cenote/table/systemTable'
+export default {
+  data() {
+    return {
+      params: {},
+      tabsList: [
+        { Code: 'device', Name: '竖井内的设备' },
+        { Code: 'cenote', Name: '连通的其它竖井' },
+        { Code: 'system', Name: '竖井内系统' },
+      ], //tab页
+      activeTab: 'device' //当前选中的tab
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "userId", "secret"])
+  },
+  components: {
+    cenoteTable,
+    deviceTable,
+    systemTable
+  },
+  created() {
+    this.params = this.$route.query;
+  },
+  mounted() { },
+  watch: {
+    projectId() { }
+  },
+  methods: {
+    // 返回
+    goBack() {
+      this.$router.push({ name: "cenotelist" })
+    },
+    // 删除业务空间
+    deleteCenote() {
+      this.$confirm("此操作将删除竖井,是否继续?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        deleteCenoteTableData([{ShaftID: this.params.ShaftID}], res => {
+          this.$message.success('删除成功')
+          this.goBack()
+        })
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    }
+  }
+};
+</script>
+
+<style scoped lang='less'>
+.box {
+  .condition {
+    padding: 10px;
+    display: flex;
+    height: 100%;
+    flex-direction: column;
+    border: 1px solid #dfe6ec;
+    background: #fff;
+    margin-bottom: 10px;
+    .header {
+      padding-bottom: 10px;
+      span {
+        line-height: 33px;
+        margin-left: 15px;
+      }
+    }
+    .spaceTypes {
+      .types {
+        float: left;
+        width: calc(100% - 200px);
+        /deep/ .el-tabs__item.is-top {
+          border-top: 2px solid transparent;
+          &.is-active {
+            border-top: 2px solid #409eff;
+          }
+        }
+      }
+      .deleBtn {
+        float: left;
+        width: 200px;
+        text-align: right;
+        height: 40px;
+        border-bottom: 1px solid #e4e7ed;
+      }
+    }
+    .main {
+      margin-top: 10px;
+      height: calc(100% - 96px);
+    }
+    .footer {
+      margin-bottom: 10px;
+    }
+  }
+}
+</style>
+
+<style lang="less">
+.el-table th {
+  background-color: #d9d9d9;
+  color: #000;
+}
+</style>
+

+ 6 - 6
src/views/ledger/cenotelist/cenoteadd/index.vue

@@ -2,6 +2,9 @@
   <div id="deviceList">
     <el-row class="right">
       <!-- <span style="float:left;">当前选择的部件类型:{{page.total || '--'}}</span> -->
+      <el-select v-model="showType" @change="initTable" style="width:125px;margin-right:10px;vertical-align:bottom;">
+        <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
+      </el-select>
       <span>增加</span>
       <el-input v-model="addNum" style="width:50px;" size="small"></el-input>
       <span>个竖井</span>
@@ -44,18 +47,15 @@ export default {
       isTableRightShow: false,
       relationids: "",
       onlyRead: false,
-      showType: "all",
+      showTypes: [{ value: "Visible", label: '只看采集信息' }, { value: "all", label: '全部' }],
+      showType: "Visible",
       tableHeader: [],
       tableData: session.get("cenoteAddData")? session.get("cenoteAddData").length? session.get("cenoteAddData"): [{}]: [{}],
       copyTableData: []
     };
   },
   computed: {
-    ...mapGetters("layout", [
-        "projectId",
-        "secret",
-        "userId"
-    ])
+    ...mapGetters("layout", [ "projectId", "secret", "userId" ])
   },
   created() {
     this.getTableHeader()

+ 69 - 3
src/views/ledger/cenotelist/index.vue

@@ -55,6 +55,19 @@
       layout="total, sizes, prev, pager, next, jumper"
       :total="page.total">
     </el-pagination>
+    <!-- 不支持的输入方式 -->
+    <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>
   </div>
 </template>
 <script>
@@ -97,7 +110,14 @@ export default {
       },
       tableData: [],
       copyTableData: [],
-      tableExample:null
+      tableExample:null,
+      myDialog: {
+        update: false,//临时维护信息点
+      },
+      inputMap: { }, //信息点和输入方式映射表
+      updateInputShow: false, //是否显示临时维护输入框
+      updateInfoPoint: '',//临时维护信息点
+      updateInput: '', //临时维护信息点值
     };
   },
   computed: {
@@ -109,7 +129,7 @@ export default {
     showTypes () {
       return this.onlyRead?
         [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]: 
-        [{value: "partInfo", label: '隐藏信息点'}, {value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]
+        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]
     }
   },
   created() {
@@ -141,6 +161,11 @@ export default {
       }
       await getDataDictionary(param, res => {
         this.tableHeader = res.Content;
+        this.tableHeader.forEach(item => {
+          if(item.Path && item.InputMode){
+            this.inputMap[item.Path] = item.InputMode
+          }
+        })
         this.getTableData()
       })
     },
@@ -290,7 +315,7 @@ export default {
     formatHeaderData(list) {//格式化表头显示的数据
       let arr = tools.copyArr(list)
       let data = showTools.headerTextFilter(arr, "shaft", this.onlyRead, this.showType)
-      data.unshift("关联的元空间");
+      data.unshift("关联的元空间", "其他关系");
       return data;
     },
     formatHeaderType(list) {//格式化表头头映射的数据
@@ -300,12 +325,22 @@ export default {
         data: "SpaceCount",
         renderer: tools.num,
         readOnly: true
+      },{
+        data: "OtheRelations",
+        renderer: (instance, td, row, col, prop, value, cellProperties) => {
+          td.style.color = "#409EFF";
+          td.style.cursor = "pointer";
+          td.innerHTML = "查看";
+          return td;
+        },
+        readOnly: true
       })
       return data;
     },
     initTable() {//实例化表格
       let settings = {
         data: this.tableData,
+        fixedColumnsLeft: 4,
         colHeaders: this.formatHeaderData(this.tableHeader),
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
@@ -332,13 +367,44 @@ export default {
     getInfors(infos, row) {
       //其他的开始判断
       let val = this.tableExample.colToProp(row.col)
+      let inputMode = this.inputMap[val]
+      let name = infos.ShaftLocalName?infos.ShaftLocalName:infos.ShaftName
       this.shaftId = infos.ShaftID //要操作的数据id
       //点击关联的元空间
       if (val === "SpaceCount") {
         this.spaceList = infos.SpaceList
         this.isTableRightShow = true
+        return false
+      } else if (val === "OtheRelations") {
+        this.$router.push({
+          path: "/ledger/cenoteDetail",
+          query: {
+            ShaftID: this.shaftId,
+            name: name
+          }
+        })
+        return false
+      }
+      if (!this.onlyRead && showTools.InputModeArr.indexOf(inputMode) == '-1') {
+        this.updateInfoPoint = val
+        this.updateInput = tools.dataForKey(this.tableData[row.row], val)
+        this.myDialog.update = true
       }
     },
+    //关闭临时维护弹窗回调
+    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 = ''
+    },
     //表格点击事件
     handleTdClick(el, rowArr) {
       //点击的是表头

+ 7 - 9
src/views/ledger/facility/addfacility.vue

@@ -5,10 +5,9 @@
         <i class="el-icon-fa  el-icon-fa-compass"></i>
       </span>
       <span style="float:left;">当前选择的设备类型:{{category.name}}</span>
-      <div style="width:200px;display:inline-block;text-align:left;color:gray;">
-        <span>隐藏自动填充的信息</span>
-        <el-checkbox v-model="showTypeFlag" @change="getTableHeader"></el-checkbox>
-      </div>
+      <el-select v-model="showType" @change="initTable" style="width:125px;margin-right:10px;vertical-align:bottom;">
+        <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
+      </el-select>
       <span>增加</span>
       <el-input v-model="addNum" style="width:50px;" size="small"></el-input>
       <span>个{{category.name}}</span>
@@ -95,6 +94,7 @@ export default {
     return {
       addNum: 1,
       onlyRead: false,
+      showTypes: [{ value: "partInfo", label: '隐藏信息点' }, { value: "all", label: '全部' }, { value: "Visible", label: '只看采集信息' }],
       tableHeader: [],
       tableData: session.get("deviceAddData")
         ? session.get("deviceAddData").length
@@ -128,7 +128,7 @@ export default {
       systemId: null,
       graphyId: null,
       id: 0,
-      showTypeFlag: true,
+      showType: 'partInfo',
       EquipmentList: [],
       firmId: "", //品牌型号所需字段--族id三位编码(传设备类id或部件类id)
       buildFloorData: [],
@@ -342,8 +342,7 @@ export default {
     //格式化表头显示的数据
     formatHeaderData(list) {
       let arr = tools.copyArr(list);
-      let showType = this.showTypeFlag ? 'partInfo' : 'all';
-      let data = showTools.headerTextFilter(arr, 'equipment', this.onlyRead, showType, true);
+      let data = showTools.headerTextFilter(arr, 'equipment', this.onlyRead, this.showType, true);
       data.unshift("同时创建资产", "所属系统实例");
       if (this.floorFlag) {
         data.splice(1, 0, "所属建筑楼层")
@@ -353,8 +352,7 @@ export default {
     formatHeaderType(list) {
       //格式化表头头映射的数据
       let arr = tools.copyArr(list);
-      let showType = this.showTypeFlag ? 'partInfo' : 'all';
-      let data = showTools.headerTypeFilter(arr, 'equipment', this.onlyRead, showType, true);
+      let data = showTools.headerTypeFilter(arr, 'equipment', this.onlyRead, this.showType, true);
       data.unshift({
         type: "checkbox",
         checkedTemplate: 1,

+ 294 - 0
src/views/ledger/facility/batchlink.vue

@@ -0,0 +1,294 @@
+<template>
+  <div class="box">
+    <div class="condition">
+      <div class="header">
+        <el-button style="float:left;" size="small" type="default" icon="el-icon-back" @click="goBack"></el-button>
+        <span class="statistics-title">发现未关联资产的设备:<b>{{unlinkNumber}}</b></span>
+        <span class="statistics-title">可在此功能中批量关联的:<b>{{linkNumber}}</b></span>
+        <el-button style="float:right;margin-top:1px;" @click="handleClickCreate">保存选定的设备资产关联关系</el-button>
+        <el-button v-show="Object.keys(radio).length" style="float:right;margin-top:1px;margin-right:15px;" @click="handleClickReset">重置</el-button>
+      </div>
+      <div class="main">
+        <el-table ref="multipleTable" :data="tableData" v-loading='loading' stripe height="100%" :span-method="objectSpanMethod" :header-cell-style="headerStyle">
+          <el-table-column prop="EquipLocalName" label="设备本地名称" show-overflow-tooltip max-width="150">
+            <!-- <template slot-scope="scope">{{ scope.row.EquipLocalName?scope.row.EquipLocalName:scope.row.EquipName }}</template> -->
+          </el-table-column>
+          <el-table-column prop="EquipLocalID" label="设备本地编码" show-overflow-tooltip max-width="150">
+            <!-- <template slot-scope="scope">{{ scope.row.EquipLocalID?scope.row.EquipLocalID:scope.row.EquipID }}</template> -->
+          </el-table-column>
+          <el-table-column prop="EquipCategory.EquipName" label="设备类" show-overflow-tooltip width="100"></el-table-column>
+          <el-table-column prop="CADID" label="设计图纸中编码" show-overflow-tooltip max-width="150"></el-table-column>
+          <el-table-column label="所属建筑楼层">
+            <template slot-scope="scope">
+              {{ scope.row.Building?scope.row.Building.BuildLocalName:'' }}-{{ scope.row.Floor?scope.row.Floor.FloorLocalName:'' }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="PropertyItem.EquipLocalName" label="资产本地名称" show-overflow-tooltip max-width="150">
+            <!-- <template slot-scope="scope">{{ scope.row.AssetsLocalName }}</template> -->
+          </el-table-column>
+          <el-table-column prop="PropertyItem.EquipLocalID" label="资产本地编码" show-overflow-tooltip max-width="150">
+            <!-- <template slot-scope="scope">{{ scope.row.AssetsLocalId }}</template> -->
+          </el-table-column>
+          <el-table-column prop="PropertyItem.FamilyName.Name" label="设备族" show-overflow-tooltip width="100"></el-table-column>
+          <el-table-column prop="PropertyItem.CADID" label="设计图纸中编码" show-overflow-tooltip max-width="150"></el-table-column>
+          <el-table-column label="所属建筑楼层" show-overflow-tooltip width="200">
+            <template slot-scope="scope">
+              {{ scope.row.PropertyItem.Building?scope.row.PropertyItem.Building.BuildLocalName:'' }}-{{ scope.row.PropertyItem.Floor?scope.row.PropertyItem.Floor.FloorLocalName:'' }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="address" label="操作" width="100">
+            <template slot-scope="scope">
+              <el-radio v-model="radio[scope.row.EquipID]" :label="scope.row.PropertyItem.EquipID" :disabled="scope.row.disabled" @change="handleChangeLink(scope.row)">&nbsp;</el-radio>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!-- <div class=footer>
+        <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"
+//api
+import { countEquip, equipCategoryProperty, equipRproperty } from "@/api/scan/request";
+
+export default {
+  components: {
+    
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "userId", "secret"])
+  },
+  created() {
+    this.params = this.$route.params
+    this.getTableData()
+  },
+  data() {
+    return {
+      params: {},
+      loading: false,
+      unlinkNumber: 0,
+      linkNumber: 0,
+      // page: {
+      //   pageSize: 50,
+      //   pageSizes: [10, 20, 50, 100],
+      //   pageNumber: 1,
+      //   total: 0
+      // },
+      radio: {},
+      contentData: [],
+      tableData: [],
+      mergeCol: [],
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+    }
+  },
+  methods: {
+    //获取表格数据
+    getTableData(pageNum) {
+      this.loading = true
+      let param = this.formatFilter(pageNum)
+      equipCategoryProperty(param, res => {
+        this.unlinkNumber = res.Total
+        this.linkNumber += res.Content.length
+        // this.page.total = res.Total
+        this.contentData = this.contentData.concat(res.Content)
+        if (res.Total / (res.PageSize * res.PageNumber) > 1) {
+          this.getTableData(res.PageNumber + 1)
+        } else {
+          this.contentData.forEach(item =>{
+            if(item.PropertyList && item.PropertyList.length){
+              item.PropertyList.forEach((Assets, index) => {
+                let obj = JSON.parse(JSON.stringify(Object.assign(item, {PropertyItem: Assets, disabled: false})))
+                delete obj.PropertyList
+                this.tableData.push(obj)
+                if(index == 0){
+                  this.mergeCol.push(item.PropertyList.length)
+                } else {
+                  this.mergeCol.push(false)
+                }
+              })
+            }
+          })
+          this.loading = false
+        }
+      })
+    },
+    //格式化条件
+    formatFilter(pageNum) {
+      pageNum = pageNum ? pageNum : 1
+      let param = {
+          data: {
+          //   Cascade: [
+          //   {
+          //     Name: "equipCategory",
+          //     Projection: ["EquipCode", "EquipName"]
+          //   },
+          //   {
+          //     Name: "building",
+          //     Projection: [ "BuildLocalName", "BuildName", "BuildID" ]
+          //   },
+          //   {
+          //     Name: "floor",
+          //     Projection: [ "FloorLocalName", "FloorName", "FloorID" ]
+          //   }
+          // ],
+          Orders: "createTime desc, EquipID asc",
+          PageNumber: pageNum,
+          PageSize: 1000
+        },
+        category: this.params.deviceType
+      }
+
+      if (this.params.buildFloor[0] == "noKnow") {
+        param.data.Filters = `buildingId isNull`
+      } else if (this.params.buildFloor[0] && this.params.buildFloor[0] != "all") {
+        param.data.Filters = `buildingId='${this.params.buildFloor[0]}'`
+        if (this.params.buildFloor[1] == "noKnow") {
+          param.data.Filters += `;floorId isNull`
+        } else if (this.params.buildFloor[1] && this.params.buildFloor[1] != "all") {
+          param.data.Filters += `;floorId='${this.params.buildFloor[1]}'`
+        }
+      }
+      if(this.params.hasOwnProperty('spaceList')){
+        if(typeof this.params.spaceList == 'string'){
+          param.spaceIdList = `&spacrType=${this.params.spaceList}`
+        } else {
+          let spaceIdList = ''
+          this.params.spaceList.forEach(item => {
+            spaceIdList += `&spaceIdList=${item}`
+          })
+          param.spaceIdList = spaceIdList
+        }
+      }
+      return param
+    },
+    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      if (columnIndex < 5) {
+        if (this.mergeCol[rowIndex]) {
+          return {
+            rowspan: this.mergeCol[rowIndex],
+            colspan: 1
+          };
+        } else {
+          return {
+            rowspan: 0,
+            colspan: 1
+          };
+        }
+      }
+    },
+    //切换关联
+    handleChangeLink(row) {
+      this.tableData.forEach(item => {
+        item.disabled = false
+        if(Object.keys(this.radio).length){
+          for(let key in this.radio){
+            if(item.EquipID != key && item.PropertyItem.EquipID == this.radio[key]){
+              item.disabled = true
+            }
+          }
+        }
+      })
+    },
+    //重置关联选择
+    handleClickReset() {
+      this.tableData.forEach(item => {
+        item.disabled = false
+      })
+      this.radio = {}
+    },
+    //创建已选
+    handleClickCreate() {
+      let params = {
+        Content: []
+      }
+      if(Object.keys(this.radio).length){
+        for(let key in this.radio){
+          params.Content.push({
+            EquipId: this.radio[key],
+            EquipmentId: key
+          })
+        }
+        equipRproperty(params, res => {
+          this.radio = {}
+          this.linkNumber = 0
+          this.contentData = []
+          this.tableData = []
+          this.getTableData()
+          this.$message.success('关联成功!')
+        })
+      } else {
+        this.$message.info('请选择要关联的关系!')
+      }
+    },
+    //切换每页显示多少条数据
+    // handleSizeChange(val) {
+    //   this.page.pageSize = val
+    //   this.getTableData()
+    // },
+    //切换页数
+    // handleCurrentChange(val) {
+    //   this.page.pageNumber = val
+    //   this.getTableData()
+    // },
+    //返回
+    goBack() {
+      this.$router.push({ name: "facilityLedger" })
+    }
+  },
+  watch: {
+    projectId() {
+      this.$router.push({ name: "facilityLedger" })
+    }
+  }
+};
+</script>
+
+<style scoped lang='less'>
+.box {
+  .condition {
+    padding: 10px;
+    display: flex;
+    height: 100%;
+    flex-direction: column;
+    border: 1px solid #dfe6ec;
+    background: #fff;
+    .header{
+      padding-bottom: 10px;
+      border-bottom: 1px solid #bcbcbc;
+      .statistics-title{
+        margin-left: 20px;
+        line-height: 32px;
+      }
+    }
+    .main{
+      margin-top: 10px;
+      height: calc(100% - 46px);
+    }
+  }
+}
+</style>
+
+<style lang="less">
+.el-table th {
+  background-color: #d9d9d9;
+  color: #000;
+}
+</style>

+ 21 - 8
src/views/ledger/facility/index.vue

@@ -7,10 +7,12 @@
       <div class="search-header">
         <floor-cascader @change="changeFloor"></floor-cascader>
         <my-cascader ref="cascader" @change="changeDevice"></my-cascader>
+        <el-button size="small" @click="handleLinkAssets" class="iconfont icon-batchassociation">批量关联资产</el-button>
       </div>
       <hanson-table @close="close" :graphyId="graphyId" ref="tableMain"></hanson-table>
     </div>
     <!-- <table-transfers></table-transfers> -->
+    <linkassets-dialog :dialog="dialog"></linkassets-dialog>
   </div>
 </template>
 <script>
@@ -19,6 +21,7 @@ import floorCascader from "@/components/ledger/lib/floorCascader";
 import myCascader from "@/components/ledger/lib/cascader";
 import hansonTable from "@/components/ledger/handsontables/device";
 import tableTransfers from "@/components/ledger/tableTransfers";
+import linkassetsDialog from "@/components/ledger/lib/linkassets";
 import {
   getSpaceName,
   getGraphyId,
@@ -35,7 +38,8 @@ export default {
     floorCascader,
     myCascader,
     hansonTable,
-    tableTransfers
+    tableTransfers,
+    linkassetsDialog
   },
   data() {
     return {
@@ -60,16 +64,14 @@ export default {
         secret: ""
       },
       assetGroupList: [],
-      graphyId: null
+      graphyId: null,
+      dialog: {
+        linkAssets: false
+      }
     };
   },
   computed: {
-    ...mapGetters("layout", [
-      "projectId",
-      "projects",
-      "secret",
-      "userId"
-    ])
+    ...mapGetters("layout", [ "projectId", "projects", "secret", "userId" ])
   },
   created() {
     this.param.ProjId = this.projectId
@@ -169,6 +171,10 @@ export default {
         if (this.$refs.tableMain)
           this.$refs.tableMain.getHeaderData(this.param);
       }
+    },
+    // 批量关联资产
+    handleLinkAssets() {
+      this.dialog.linkAssets = true
     }
   }
 };
@@ -194,6 +200,13 @@ export default {
     padding-bottom: 10px;
     margin: 0 10px;
     border-bottom: 1px solid #bcbcbc;
+    .icon-batchassociation{
+      float: right;
+      font-size: 12px;
+      /deep/ span{
+        margin-left: 5px;
+      }
+    }
   }
 }
 </style>

+ 7 - 9
src/views/ledger/property/addproperty.vue

@@ -2,10 +2,9 @@
   <div id="deviceList">
     <el-row class="right">
       <span style="float:left;">当前选择的设备族:{{category.name}}</span>
-      <div style="width:200px;display:inline-block;text-align:left;color:gray;">
-        <span>隐藏自动填充的信息</span>
-        <el-checkbox v-model="showTypeFlag" @change="getTableHeader"></el-checkbox>
-      </div>
+      <el-select v-model="showType" @change="initTable" style="width:125px;margin-right:10px;vertical-align:bottom;">
+        <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
+      </el-select>
       <span>增加</span>
       <el-input v-model="addNum" style="width:50px;" size="small"></el-input>
       <span>个{{category.name}}</span>
@@ -78,6 +77,7 @@ export default {
     return {
       addNum: 1,
       onlyRead: false,
+      showTypes: [{ value: "partInfo", label: '隐藏信息点' }, { value: "all", label: '全部' }, { value: "Visible", label: '只看采集信息' }],
       buildFloorData: [],
       tableHeader: [],
       tableData: session.get("propertyAddData")
@@ -109,7 +109,7 @@ export default {
       systemId: null,
       graphyId: null,
       id: 0,
-      showTypeFlag: true,
+      showType: 'partInfo',
       EquipmentList: []
     };
   },
@@ -226,16 +226,14 @@ export default {
     //格式化表头显示的数据
     formatHeaderData(list) {
       let arr = tools.copyArr(list)
-      let showType = this.showTypeFlag?'partInfo':'all'
-      let data = showTools.headerTextFilter(arr, 'property', this.onlyRead, showType, true)
+      let data = showTools.headerTextFilter(arr, 'property', this.onlyRead, this.showType, true)
       data.unshift("所属建筑楼层")
       return data
     },
     //格式化表头头映射的数据
     formatHeaderType(list) {
       let arr = tools.copyArr(list)
-      let showType = this.showTypeFlag?'partInfo':'all'
-      let data = showTools.headerTypeFilter(arr, 'property', this.onlyRead, showType, true)
+      let data = showTools.headerTypeFilter(arr, 'property', this.onlyRead, this.showType, true)
       data.unshift({
         data: "flowBuild",
         renderer: tools.customDropdownRenderer,

+ 54 - 5
src/views/ledger/rentlist/index.vue

@@ -69,6 +69,19 @@
       layout="total, sizes, prev, pager, next, jumper"
       :total="page.total">
     </el-pagination>
+    <!-- 不支持的输入方式 -->
+    <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>
   </div>
 </template>
 <script>
@@ -111,7 +124,16 @@ export default {
         total: 0
       },
       tableData: [],
-      copyTableData: []
+      copyTableData: [],
+      myDialog: {
+        update: false,//临时维护信息点
+      },
+      inputMap: {
+        FloorId: 'B1'
+      }, //信息点和输入方式映射表
+      updateInputShow: false, //是否显示临时维护输入框
+      updateInfoPoint: '',//临时维护信息点
+      updateInput: '', //临时维护信息点值
     };
   },
   computed: {
@@ -123,7 +145,7 @@ export default {
     showTypes () {
       return this.onlyRead?
         [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]: 
-        [{value: "partInfo", label: '隐藏信息点'}, {value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]
+        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]
     }
   },
   created() {
@@ -158,6 +180,11 @@ export default {
       }
       await getDataDictionary(param, res => {
         this.tableHeader = res.Content;
+        this.tableHeader.forEach(item => {
+          if(item.Path && item.InputMode){
+            this.inputMap[item.Path] = item.InputMode
+          }
+        })
         this.getTableData()
       })
     },
@@ -360,14 +387,16 @@ export default {
     //获取到了正确的信息
     getInfors(infos, row) {
       //其他的开始判断
-      let val = this.tableExample.colToProp(row.col);
+      let val = this.tableExample.colToProp(row.col)
+      let inputMode = this.inputMap[val]
       this.row = row.row //要操作的列号
       this.messKey = val //要操作的列类型
       this.tenantID = infos.TenantID //要操作的数据id
       //点击操作跳转详情
       if (val === "caozuo") {
-
-        window.open(`${process.env.BASE_URL}:8889/#/details?perjectId=${this.projectId}&secret=${this.secret}&FmId=${this.tenantID}&type=0&code=VOTn`,"_blank")
+        this.$message("开发中!")
+        // window.open(`${process.env.BASE_URL}:8889/#/details?perjectId=${this.projectId}&secret=${this.secret}&FmId=${this.tenantID}&type=0&code=VOTn`,"_blank")
+        return false
       }
       //点击关联的元空间
       if (val === "RoomCount") {
@@ -377,7 +406,27 @@ export default {
           this.roomId = ""
         }
         this.isTableRightShow = true;
+        return false
       }
+      if (!this.onlyRead && showTools.InputModeArr.indexOf(inputMode) == '-1') {
+        this.updateInfoPoint = val
+        this.updateInput = tools.dataForKey(this.tableData[row.row], val)
+        this.myDialog.update = true
+      }
+    },
+    //关闭临时维护弹窗回调
+    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 = ''
     },
     //表格点击事件
     handleTdClick(el, rowArr) {

+ 6 - 6
src/views/ledger/rentlist/rentadd/index.vue

@@ -2,6 +2,9 @@
   <div id="deviceList">
     <el-row class="right">
       <!-- <span style="float:left;">当前选择的部件类型:{{page.total || '--'}}</span> -->
+      <el-select v-model="showType" @change="initTable" style="width:125px;margin-right:10px;vertical-align:bottom;">
+        <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
+      </el-select>
       <span>增加</span>
       <el-input v-model="addNum" style="width:50px;" size="small"></el-input>
       <span>个租户</span>
@@ -43,18 +46,15 @@ export default {
       isTableRightShow: false,
       relationids: "",
       onlyRead: false,
-      showType: "all",
+      showTypes: [{ value: "partInfo", label: '隐藏信息点' }, { value: "all", label: '全部' }, { value: "Visible", label: '只看采集信息' }],
+      showType: "partInfo",
       tableHeader: [],
       tableData: session.get("rentAddData")? session.get("rentAddData").length? session.get("rentAddData"): [{}]: [{}],
       copyTableData: []
     };
   },
   computed: {
-    ...mapGetters("layout", [
-        "projectId",
-        "secret",
-        "userId"
-    ])
+    ...mapGetters("layout", [ "projectId", "secret", "userId" ])
   },
   created() {
     this.getTableHeader()

+ 161 - 332
src/views/ledger/spacelist/index.vue

@@ -4,80 +4,67 @@
 <template>
   <div id="businessSpace">
     <!------------------------    头部弹窗,选择楼层信息     -------------->
-    <!-- <no-model-dialog :param="param" title="选择要进行空间管理的楼层" :isShow="floor" @close="close"></no-model-dialog> -->
     <influence-dialog ref="influence" :param="param" :tabsList="tabsList" title="受元空间变化影响的业务空间" :isShow="floor"></influence-dialog>
-    <details-dialog ref="details" @del="delSuccess" :param="param" :tabsList="tabsList" title="业务空间详情" :isShow="floor" :activeTabType="activeTabType"></details-dialog>
+    <details-dialog ref="details" @del="delSuccess" :param="param" :tabsList="tabsList" title="业务空间详情" :isShow="floor" :activeTabType="activeTabType">
+    </details-dialog>
     <not-related ref="notRelated" @createSuccess="createSuccess" :isShow="floor"></not-related>
     <facility-dialog ref="facility" :activeTabType="activeTabType" :isShow="floor"></facility-dialog>
     <!--------- 页面头部   -------------->
     <div class="saga-title">
-      <!-- <div class="saga-build-mess">
-                <p>
-                    <i class="iconfont icon-jianzhu"></i> {{buildMess.buildName}} - {{buildMess.name}}
-                </p>
-                <el-button class="saga-btn" type="text" @click="changeShow">切换楼层</el-button>
-            </div> -->
       <div class="saga-build-mess">
         <span style="padding-right:12px;color:#999999;">建筑楼层</span>
-        <el-cascader :options="options" v-model="buildMess.selectd" :props="props" @change="close"></el-cascader>
+        <el-cascader :options="options" v-model="buildFloorSelectd" :props="props" @change="changeCascader"></el-cascader>
       </div>
       <div class="saga-build-tab">
-        <!-- <div class="tab-main" @click="tabList(1)" :class="isMyTab == 1 ? 'tab-active' : ''">
-                    <i class="iconfont icon-tupian"></i>
-                    <span>平面图</span>
-                </div>
-                <div class="tab-main" @click="tabList(2)" :class="isMyTab == 2 ? 'tab-active' : ''">
-                    <i class="iconfont icon-liebiao"></i>
-                    <span>列表</span>
-                </div> -->
         <el-radio-group v-model="isMyTab" @change="changeRadio" style="width: 136px;">
           <el-radio-button label="1">平面图</el-radio-button>
           <el-radio-button label="2" class="space-own-radio" style="width: 68px;">列表</el-radio-button>
         </el-radio-group>
       </div>
     </div>
-    <div v-show="isMyTab == 1" class="saga-business-sapce-main">
-      <el-tabs v-model="activeName" @tab-click="tab1Click">
-        <template v-for="(item,index) in tabsList">
-          <el-tab-pane :name="item.code" :key="index" :disabled="item.code > 3">
-            <span slot="label">{{item.name}}</span>
-            <graphy @getSp="checkSpace" @dimension="checkSpace" @businessDetails="getBuinessDetails"
-              :ref="'graphy' + item.code" :canvasId="item.code"></graphy>
-          </el-tab-pane>
-        </template>
-      </el-tabs>
-      <!-- <space-graphy @dimension="checkSpace" :tabsList="tabsList" ref="graphy" :param="param"></space-graphy> -->
-    </div>
-    <div v-show="isMyTab == 2" class="saga-business-sapce-main">
-      <el-tabs v-model="activeName" @tab-click="handleClick">
-        <template v-for="(item,index) in tabsList">
-          <el-tab-pane :name="item.code" :key="index" :disabled="item.code > 3">
-            <span slot="label">{{item.name}}</span>
-            <handsontable-main @lookEqu="lookEqu" :ref="'handsontable' + item.code" :zoneObj="item" :id="'handsontable' + item.code" :param="param"></handsontable-main>
-          </el-tab-pane>
-        </template>
-      </el-tabs>
-      <!-- <space-handsontable :tabsList="tabsList" ref="spaceTable" :param="param"></space-handsontable> -->
+    <div class="saga-business-sapce-main">
+      <el-row class="spaceTypes">
+        <div class="types">
+          <el-tabs v-model="activeName" type='card' @tab-click="tabClick">
+            <template v-for="(item,index) in tabsList">
+              <el-tab-pane :name="item.Code" :key="index" :label="item.Name"></el-tab-pane>
+            </template>
+          </el-tabs>
+        </div>
+        <div class="groupAdd">
+          <el-button size="small" @click="groupCreateBSpace">批量创建业务空间</el-button>
+        </div>
+      </el-row>
+      <div v-show="isMyTab == 1" style="width:100%;height:100%">
+        <graphy @getSp="checkSpace" @dimension="checkSpace" @businessDetails="getBuinessDetails" ref="graphy"></graphy>
+      </div>
+      <div v-show="isMyTab == 2">
+        <handsontable-main @lookEqu="lookEqu" ref="handsontable" :zoneCode="activeName" :id="`handsontable${activeName}`"></handsontable-main>
+      </div>
     </div>
   </div>
 </template>
-
 <script>
 import noModelDialog from "@/components/business_space/dialogs/noModelDialog";
 import influenceDialog from "@/components/business_space/dialogs/influenceDialog";
 import detailsDialog from "@/components/business_space/dialogs/detailsDialog";
 import notRelated from "@/components/business_space/dialogs/notRelated";
 import facilityDialog from "@/components/business_space/dialogs/facilityDialog";
-// import spaceHandsontable from "@/components/business_space/business/spaceHandsontable";
-import graphy from "@/components/business_space/graphy/business";
+// import graphy from "@/components/business_space/graphy/business";
+import graphy from "@/components/business_space/newGraphy/graphy";
 import handsontableMain from "@/components/business_space/business/handsontable";
-import { getDataDictionary, getAllbusiness, getBussTypes, getSpaceFloor, buildingQuery, floorQuery } from "@/api/scan/request";
+import {
+  getDataDictionary,
+  getAllbusiness,
+  getSpaceFloor,
+  buildingQuery, //数据中心-建筑查询
+  queryDictionaryHead, //数据中心-字典头部信息查询接口
+} from "@/api/scan/request";
 import tools from '@/utils/scan/tools'
 import { mapGetters, mapActions } from "vuex";
 export default {
   components: {
     noModelDialog,
-    // spaceHandsontable,
     influenceDialog,
     detailsDialog,
     notRelated,
@@ -91,7 +78,6 @@ export default {
   data() {
     return {
       floor: {
-        // dialogVisible: true, //选择楼层弹窗
         influence: false, //受影响的业务空间弹窗
         details: false, //详情弹窗
         notRelated: false,
@@ -112,203 +98,145 @@ export default {
         buildCode: ""
       },
       isMyTab: 1,
-      activeName: "GeneralZone",
+      activeName: "0",
       tabsList: [],
       activeTabType: {
         "code": "GeneralZone",
         "name": "默认分区",
         "rel_type": "99"
       },
-      options: [],
-      props: {
-        value: "code",
-        label: "name",
-        children: "children"
-      }
+      options: [], //建筑楼层级联下拉
+      props: { //自定义字段
+        value: "BuildID",
+        label: "BuildLocalName",
+        children: "Floor"
+      },
+      floorToMap: {}, //楼层及其对应的模型图
+      FloorMap: "", //当前选中的楼层平面图
+      buildFloorSelectd: [], //当前所选的建筑楼层
+      childBackParam: {}
     };
   },
   created() {
-    this.changeData()
+    this.init();
+    this.childBackParam = this.$route.params;
   },
   mounted() { },
   methods: {
-    changeData() {
-      this.param.ProjId = this.projectId
-      this.param.UserId = this.userId
-      this.param.secret = this.secret
-      this.getFloor()
+    // 初始化
+    init() {
       this.getTypes()
+      this.getBuilding()
     },
-    changeRadio() {
-      if (!this.buildMess.selectd.length) {
-        this.$message("请选择楼层")
-        return false
+    // 获取项目下建筑
+    getBuilding() {
+      let pa = {
+        Cascade: [{ name: 'floor', Orders: 'SequenceId desc' }],
+        Orders: "BuildLocalName asc",
       }
-      this.tabClick(this.isMyTab)
-    },
-    //获取楼层
-    getFloor() {
-      // let data, buildParams = {
-      //   PageNumber: 1,
-      //   PageSize: 500
-      // }, floorParams = {
-      //   Orders: "FloorSequenceID desc",
-      //   PageNumber: 1,
-      //   PageSize: 500
-      // }
-      // let promise1 = new Promise((resolve, reject) => {
-      //   buildingQuery(buildParams, res => {
-      //     resolve(res)
-      //   })
-      // })
-      // let promise2 = new Promise((resolve, reject) => {
-      //   floorQuery(floorParams, res => {
-      //     resolve(res)
-      //   })
-      // })
-      // Promise.all([promise1, promise2]).then(values => {
-      //   let builData = values[0].Content, floorData = values[1].Content
-      //   data = builData.map(build => {
-      //     return {
-      //       code: build.BuildID,
-      //       name: build.BuildLocalName
-      //     }
-      //   })
-      //   data.forEach(build => {
-      //     floorData.forEach(floor => {
-      //       if (build.code == floor.BuildID && floor.FloorID && floor.FloorLocalName) {
-      //         if (build.children) {
-      //           build.children.push({
-      //             code: floor.FloorID,
-      //             name: (floor.FloorLocalName || floor.FloorName || "未知") + this.myMess(floor),
-      //             map: floor.StructureInfo?floor.StructureInfo.FloorMap?floor.StructureInfo.FloorMap:null:null,
-      //             affected: floor.affected,
-      //             buildCode: build.BuildID,
-      //             buildName: build.BuildLocalName,
-      //             FloorSequenceID: floor.FloorSequenceID
-      //           })
-      //         } else {
-      //           build.children = []
-      //           build.children.push({
-      //             code: floor.FloorID,
-      //             name: (floor.FloorLocalName || floor.FloorName || "未知") + this.myMess(floor),
-      //             map: floor.StructureInfo?floor.StructureInfo.FloorMap?floor.StructureInfo.FloorMap:null:null,
-      //             affected: floor.affected,
-      //             buildCode: build.BuildID,
-      //             buildName: build.BuildLocalName,
-      //             FloorSequenceID: floor.FloorSequenceID
-      //           })
-      //         }
-      //       }
-      //     })
-      //   })
-      //   this.options = data
-      // })
-
-      let param = {
-        ProjId: this.projectId,
-        UserId: this.UserId,
-        secret: this.secret
-      };
-      getSpaceFloor(param).then(res => {
-        console.log(res, 'res')
-        if (res.data.Result == 'success') {
-          let data = this.changeArr(res.data.Content).map(item => {
-            if (item.children && item.children.length) {
-              item.children = tools.sortArr(item.children, "shunxu", false)
-            }
-            return item
-          })
-          console.log(data, 'res.data')
-          this.options = data
-        } else {
-          this.$message.error(res.data.ResultMsg)
+      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.floorToMap[item.FloorID] = item.StructureInfo ? item.StructureInfo.FloorMap : '';
+              return item;
+            })
+          } else {
+            t.Floor = []
+          }
+          return t;
+        })
+        if (this.childBackParam.zone) {
+          this.changeCascader(this.buildFloorSelectd)
         }
-      }).catch(() => {
-        this.$message.error("请求出错")
       })
     },
-
-    //修改已有数组
-    changeArr(arr) {
-      return arr.map(item => {
-        console.log(item.floors)
-        if (item.floors && item.floors.length) {
-          return {
-            code: item.id,
-            name: item.infos.BuildLocalName,
-            children: item.floors.map(i => {
-              return {
-                code: i.id,
-                name: (i.infos.FloorLocalName || i.infos.FloorName || "未知") + this.myMess(i),
-                map: i.infos.FloorMap || null,
-                affected: i.affected,
-                isChilren: 2,
-                buildCode: item.id,
-                buildName: item.infos.BuildLocalName,
-                shunxu: i.infos.FloorSequenceID || 0
-              }
-            })
+    // 切换平面图和列表
+    changeRadio(val) {
+      this.changeGraphyOrTable(val)
+    },
+    // 获取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);
+        if (this.childBackParam.zone) {
+          this.activeName = this.childBackParam.zone;
+          this.buildFloorSelectd = [this.childBackParam.BuildingId, this.childBackParam.FloorId];
+          this.isMyTab = this.childBackParam.isMyTab;
         } else {
-          return {
-            code: item.id,
-            name: item.infos.BuildLocalName,
-            children: null,
-            isChilren: 1,
-          }
+          this.activeName = 'GeneralZone';
         }
       })
     },
-    myMess(i) {
-      if (i.affected) {
-        return "(该业务空间受元空间变化影响)"
-      } else {
-        if (i.infos.FloorMap) {
-        // if (i.StructureInfo && i.StructureInfo.FloorMap) {
-          return ''
-        } else {
-          return "(请初始化平面图)"
+    // 通过选中的tab-Code 获取选中的tab的所有数据
+    getItemForType() {
+      let data = {}
+      this.tabsList.map(item => {
+        if (item.Code == this.activeName) {
+          data.code = item.Code;
+          data.name = item.Name;
         }
+      })
+      return data
+    },
+    // 点击tab
+    tabClick(val) {
+      this.changeGraphyOrTable(this.isMyTab)
+    },
+    //修改所选建筑楼层
+    changeCascader(val) {
+      // val[0]->建筑 val[1]->楼层
+      if (!this.floorToMap[val[1]]) {
+        this.isMyTab = 2;
       }
+      this.FloorMap = this.floorToMap[val[1]];
+      this.changeGraphyOrTable(this.isMyTab)
     },
-    //获取tabs的列表
-    getTypes() {
-      getBussTypes(res => {
-        let arr = [{
-          "code": "GeneralZone",
-          "name": "默认分区",
-          "rel_type": "99"
-        },
-        {
-          "name": "供电分区",
-          "rel_type": "1",
-          "code": "PowerSupplyZone"
-        },
-        {
-          "name": "照明分区",
-          "rel_type": "2",
-          "code": "LightingZone"
+    // 判断切换至图还是表
+    changeGraphyOrTable(num) {
+      if (!this.buildFloorSelectd.length) {
+        this.$message("请选择楼层")
+        return false
+      }
+      this.activeTabType = this.getItemForType()
+      if (num == 2) {
+        this.initMessage();
+      } else {
+        this.$refs.graphy.getData(this.buildFloorSelectd, this.FloorMap, this.activeTabType);
+      }
+    },
+    // 触发获取表头-获取初始化信息点
+    initMessage() {
+      let params = {
+        data: {
+          Orders: "sort asc",
+          PageNumber: 1,
+          PageSize: 500
         },
-        {
-          "name": "空调分区",
-          "rel_type": "4",
-          "code": "AirConditioningZone"
-        }, {
-          "name": '租赁分区',
-          'rel_type': '10',
-          "code": 'TenantZone'
-        }
-        ]
-        this.tabsList = arr
-        // console.log(res)
-        // this.tabsList = res.Content
+        type: this.activeName
+      }
+      getDataDictionary(params, res => {
+        this.$refs.handsontable.getHeader(res.Content, this.buildFloorSelectd);
       })
     },
+    // 批量创建业务空间
+    groupCreateBSpace() {
+      this.$refs.graphy.groupCreateBSpace()
+    },
     checkSpace(list, build, graphyId) {
       this.floor.notRelated = true;
       this.$refs.notRelated.getIdList(list, build, graphyId, this.activeTabType);
-      this.$refs["graphy" + this.activeName][0].getHasSpace();
+      this.$refs["graphy"].getHasSpace();
     },
     changeShow() {
       this.floor.dialogVisible = true;
@@ -316,50 +244,15 @@ export default {
     },
     //成功关联平面图
     createSuccess() {
-      this.$refs["graphy" + this.activeName][0].getHasSpace();
-      this.$refs["graphy" + this.activeName][0].clearDimension();
+      this.$refs["graphy"].getHasSpace();
+      this.$refs["graphy"].clearDimension();
       this.floor.notRelated = false;
     },
     //成功删除业务空间
     delSuccess() {
       this.floor.details = false;
-      this.$refs["graphy" + this.activeName][0].getData(this.buildMess.map, this.buildMess, this.activeTabType);
-      // this.$refs["graphy" + this.activeName][0].getHasSpace();
-      // this.$refs["graphy" + this.activeName][0].clearDimension();
-    },
-    close() {
-      this.buildMess = this.changeBuildMess(this.buildMess, this.options)
-      console.log(this.buildMess, 'this.buildMess')
-      if (this.buildMess.affected) {
-        this.floor.influence = true;
-        this.$nextTick(() => {
-          this.$refs.influence.getData(this.buildMess);
-        });
-      }
-      if (!this.buildMess.map) {
-        this.isMyTab = 2;
-      }
-      if (this.isMyTab == 2) {
-        this.initTabs(this.buildMess);
-      } else {
-        let data = this.getItemForType()
-        this.$refs["graphy" + this.activeName][0].getData(this.buildMess.map, this.buildMess, this.activeTabType);
-      }
-    },
-
-    //通过code查询options中的其他参数
-    changeBuildMess(mess, options) {
-      options.map(item => {
-        if (!!item.children && item.children.length) {
-          item.children.map(child => {
-            if (child.code == mess.selectd[1]) {
-              console.log(child, mess)
-              mess = Object.assign(mess, child)
-            }
-          })
-        }
-      })
-      return mess
+      this.$refs["graphy"].getHasSpace();
+      this.$refs["graphy"].clearDimension();
     },
     //查看业务空间详情
     getBuinessDetails(list) {
@@ -372,87 +265,18 @@ export default {
       this.floor.facility = true
       this.$refs.facility.getData(infos, this.buildMess)
     },
-    tabClick(num) {
-      console.log(this.$refs)
-      this.isMyTab = num;
-      if (num == 2) {
-        this.initTabs(this.buildMess);
-      } else {
-        let data = this.getItemForType()
-        this.$refs["graphy" + this.activeName][0].getData(this.buildMess.map, this.buildMess, this.activeTabType);
-      }
-    },
-    //获取初始化信息点
-    initMessage() {
-      let params = {
-        data: {
-          Orders: "sort asc",
-          PageNumber: 1,
-          PageSize: 500
-        },
-        type: this.activeTabType.code
-      }
-      getDataDictionary(params, res => {
-        let refFlag = "handsontable" + this.activeName;
-        this.$refs[refFlag][0].getHeader(res.Content, this.activeTabType);
-        this.getTableMain()
-      })
-    },
-    getItemForType() {
-      let data = {}
-      this.tabsList.map(item => {
-        if (item.code == this.activeName) {
-          data = item
-        }
-      })
-      return data
-    },
-    tab1Click() {
-      this.activeTabType = this.getItemForType()
-      this.$refs["graphy" + this.activeName][0].getData(this.buildMess.map, this.buildMess, this.activeTabType);
-    },
-    /**
-     * tab标签被点击触发后的函数
-     * @param tab   tab实例
-     * @param event tab的dom
-     *
-     */
-    handleClick(tab, event) {
-      this.activeTabType = this.getItemForType()
-      this.initMessage();
-    },
-    /**
-     * 选择楼层后初始化tabs
-     * 由父级页面调用
-     *
-     * @param  floorParam  父级传入的楼层信息
-     */
-    initTabs(floorParam) {
-      // this.floor = floorParam;
-      this.initMessage();
-    },
-    getTableMain() {
-      let refFlag = "handsontable" + this.activeName;
-      this.$nextTick(() => {
-        this.$refs[refFlag][0].getData(this.buildMess);
-      });
-      //   for (let i = 0; i < this.tabsList.length; i++) {
-      //     if (i == 0) {
-      //     }
-      //   }
-    }
   },
   watch: {
     floor: {
       deep: true,
       handler: function () {
         if (this.floor.notRelated) {
-          this.$refs["graphy" + this.activeName][0].clearDimension();
+          this.$refs["graphy"].clearDimension();
         }
       }
     },
     projectId() {
-      this.changeData()
+      this.init()
     }
   }
 };
@@ -534,23 +358,28 @@ export default {
     }
   }
   .saga-business-sapce-main {
-    flex: 1;
-    top: 40px;
-    left: 0;
-    right: 0;
-    bottom: 0;
     overflow: hidden;
-    overflow-y: auto;
+    height: 100%;
     background: #fff;
     padding: 10px;
-    .el-tabs__nav {
-      padding-left: 10px;
+    /deep/ .el-tabs__item.is-top {
+      border-top: 2px solid transparent;
+      &.is-active {
+        border-top: 2px solid #409eff;
+      }
     }
-    .el-tabs__header{
-      margin-bottom: 10px;
+  }
+  .spaceTypes {
+    .types {
+      float: left;
+      width: calc(100% - 200px);
     }
-    .el-tabs__active-bar {
-      padding-left: 24px;
+    .groupAdd {
+      float: left;
+      width: 200px;
+      text-align: right;
+      height: 40px;
+      border-bottom: 1px solid #e4e7ed;
     }
   }
 }

+ 174 - 0
src/views/ledger/spacelist/spaceDetail/index.vue

@@ -0,0 +1,174 @@
+<template>
+  <div class="box">
+    <div class="condition">
+      <div class="header">
+        <el-button style="float:left;" size="small" type="default" icon="el-icon-back" @click="goBack"></el-button>
+        <span>{{spaceDetails.RoomLocalName||spaceDetails.RoomName||''}}</span>
+      </div>
+      <el-row class="spaceTypes">
+        <div class="types">
+          <el-tabs v-model="activeTab" type='card'>
+            <template v-for="(item,index) in tabsList">
+              <el-tab-pane :name="item.Code" :key="index" :label="item.Name"></el-tab-pane>
+            </template>
+          </el-tabs>
+        </div>
+        <div class="deleBtn">
+          <el-button size="small" @click="deleteSpace">删除业务空间</el-button>
+        </div>
+      </el-row>
+      <div v-if="activeTab=='detail'" style="height:calc(100% - 110px)">
+        <iframe height="100%" width="100%" :src="iframeSrc"></iframe>
+      </div>
+      <!-- 空间内设备列表--服务于空间的设备 -->
+      <eqToSpaceTable v-else-if="activeTab=='Equipment' || activeTab=='EquipmentFor'" :params="params" :type="activeTab"></eqToSpaceTable>
+      <!-- 空间内系统 -->
+      <syInSpaceTable v-else-if="activeTab=='generalSystem'" :params="params" :type="activeTab"></syInSpaceTable>
+
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex"
+import { queryZone, deleteZone } from '@/api/scan/request'
+import eqToSpaceTable from '@/components/business_space/newTables/eqToSpaceTable'
+import syInSpaceTable from '@/components/business_space/newTables/syInSpaceTable'
+export default {
+  data() {
+    return {
+      params: {}, //参数-包含空间id 分区类型 进入方式(1-平面图 2-列表)
+      tabsList: [
+        { Code: 'detail', Name: '空间详情' },
+        { Code: 'Equipment', Name: '空间内设备' },
+        { Code: 'EquipmentFor', Name: '服务于空间的设备' },
+        { Code: 'generalSystem', Name: '空间内系统' },
+      ], //tab页
+      activeTab: 'detail', //当前选中的tab
+      spaceDetails: {}, //空间信息
+      iframeSrc: '', //空间详情iframe
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "userId", "secret"])
+  },
+  components: {
+    eqToSpaceTable,
+    syInSpaceTable
+  },
+  created() {
+    this.params = this.$route.query;
+    this.getSpaceDetails();
+    this.setFrame()
+  },
+  mounted() { },
+  watch: {
+    projectId() { }
+  },
+  methods: {
+    // 返回
+    goBack() {
+      this.$router.push({
+        name: "spacelist",
+        params: this.params
+      })
+    },
+    // 查询空间详情
+    getSpaceDetails() {
+      let pa = {
+        data: {
+          Filters: `RoomID="${this.params.RoomID}"`
+        },
+        zone: this.params.zone
+      }
+      queryZone(pa, res => {
+        this.spaceDetails = res.Content[0];
+        this.params.BuildingId = this.spaceDetails.BuildingId;
+        this.params.FloorId = this.spaceDetails.FloorId;
+      })
+    },
+    // 设置iframe
+    setFrame() {
+      this.iframeSrc =
+        `${process.env.BASE_URL}:8889/#/details?perjectId=${this.projectId}&secret=${this.secret}&FmId=${this.params.RoomID}&type=0&code=${this.params.zone}`;
+    },
+    // 删除业务空间
+    deleteSpace() {
+      this.$confirm("此操作将删除业务空间,是否继续?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let pa = {
+          data: [{
+            RoomID: this.spaceDetails.RoomID
+          }],
+          zone: this.params.zone
+        }
+        deleteZone(pa, res => {
+          this.$message.success('删除成功')
+          this.goBack()
+        })
+      }).catch(() => {
+        this.getData()
+        this.$message("取消删除")
+      })
+    }
+  }
+};
+</script>
+
+<style scoped lang='less'>
+.box {
+  .condition {
+    padding: 10px;
+    display: flex;
+    height: 100%;
+    flex-direction: column;
+    border: 1px solid #dfe6ec;
+    background: #fff;
+    margin-bottom: 10px;
+    .header {
+      padding-bottom: 10px;
+      span {
+        line-height: 33px;
+        margin-left: 15px;
+      }
+    }
+    .spaceTypes {
+      .types {
+        float: left;
+        width: calc(100% - 200px);
+        /deep/ .el-tabs__item.is-top {
+          border-top: 2px solid transparent;
+          &.is-active {
+            border-top: 2px solid #409eff;
+          }
+        }
+      }
+      .deleBtn {
+        float: left;
+        width: 200px;
+        text-align: right;
+        height: 40px;
+        border-bottom: 1px solid #e4e7ed;
+      }
+    }
+    .main {
+      margin-top: 10px;
+      height: calc(100% - 96px);
+    }
+    .footer {
+      margin-bottom: 10px;
+    }
+  }
+}
+</style>
+
+<style lang="less">
+.el-table th {
+  background-color: #d9d9d9;
+  color: #000;
+}
+</style>
+

+ 7 - 9
src/views/ledger/system/addsystem.vue

@@ -5,10 +5,9 @@
         <i class="el-icon-fa  el-icon-fa-compass"></i>
       </span>
       <span style="float:left;">当前选择的系统类型:{{category.CategoryName}}</span>
-      <div style="width:200px;display:inline-block;text-align:left;color:gray;">
-        <span>隐藏自动填充的信息</span>
-        <el-checkbox v-model="showTypeFlag" @change="getTableHeader"></el-checkbox>
-      </div>
+      <el-select v-model="showType" @change="initTable" style="width:125px;margin-right:10px;vertical-align:bottom;">
+        <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value"></el-option>
+      </el-select>
       <span>增加</span>
       <el-input v-model="addNum" style="width:50px;" size="small"></el-input>
       <span>个{{category.CategoryName}}</span>
@@ -54,6 +53,7 @@ export default {
     return {
       addNum: 1,
       onlyRead: false,
+      showTypes: [{ value: "partInfo", label: '隐藏信息点' }, { value: "all", label: '全部' }, { value: "Visible", label: '只看采集信息' }],
       tableHeader: [],
       tableData: session.get("systemAddData")
         ? session.get("systemAddData").length
@@ -86,7 +86,7 @@ export default {
       systemId: null,
       graphyId: null,
       id: 0,
-      showTypeFlag: true,
+      showType: 'partInfo',
       EquipmentList: [],
     };
   },
@@ -236,16 +236,14 @@ export default {
     //格式化表头显示的数据
     formatHeaderData(list) {
       let arr = tools.copyArr(list);
-      let showType = this.showTypeFlag ? 'partInfo' : 'all';
-      let data = showTools.headerTextFilter(arr, 'system', this.onlyRead, showType);
+      let data = showTools.headerTextFilter(arr, 'system', this.onlyRead, this.showType);
       data.unshift("所属建筑");
       return data;
     },
     formatHeaderType(list) {
       //格式化表头头映射的数据
       let arr = tools.copyArr(list);
-      let showType = this.showTypeFlag ? 'partInfo' : 'all';
-      let data = showTools.headerTypeFilter(arr, 'system', this.onlyRead, showType);
+      let data = showTools.headerTypeFilter(arr, 'system', this.onlyRead, this.showType);
       data.unshift({
         data: "flowBuild",
         renderer: tools.customDropdownRenderer,

+ 59 - 91
src/views/model/file/index.vue

@@ -23,17 +23,9 @@
             <div class="head">模型文件夹</div>
             <ul class="lists">
               <el-scrollbar style="height:100%;">
-                <li
-                  @click="openFolder(index,item)"
-                  v-for="(item,index) in navigationModel"
-                  :key="index"
-                  :class="[choiceIndex == index + 1 ? 'li-active' : '']"
-                >
-                  <i
-                    :class="[choiceIndex == index + 1 ?  'el-icon-folder-opened':'el-icon-folder','icon_font']"
-                    width="40"
-                    height="40"
-                  ></i>
+                <li @click="openFolder(index,item)" v-for="(item,index) in navigationModel" :key="index"
+                  :class="[choiceIndex == index + 1 ? 'li-active' : '']">
+                  <i :class="[choiceIndex == index + 1 ?  'el-icon-folder-opened':'el-icon-folder','icon_font']" width="40" height="40"></i>
                   <span>{{item.Name}}</span>
                 </li>
               </el-scrollbar>
@@ -44,72 +36,42 @@
     </el-col>
     <!-- 右边文件表格 -->
     <el-col class="col_left" :span="19">
-      <el-card class="box-card" :body-style="{ padding: '0px' }">
+      <el-card class="box-card" :body-style="{ padding: '0px', height:'100%' }">
         <!-- 顶部操作栏 -->
         <div class="top_hand right_top_hand">
           <el-button @click="addFloorFile">添加楼层文件</el-button>
           <el-button @click="queryFloorFile(currentFolderId)">刷新</el-button>
         </div>
         <!-- 列表 -->
-        <floorTable
-          ref="floorTable"
-          :tableData="tableData"
-          :modelFolderName="currentFolderName"
-          @openModelLog="queryModelLog"
-          @replaceModel="repliaceModel"
-          @closeUpdateFile="removePersentList"
-          @percentFinish="queryFloorFile(currentFolderId)"
-          :persentList="persentList"
-        ></floorTable>
+        <floorTable ref="floorTable" :tableData="tableData" :modelFolderName="currentFolderName" @openModelLog="queryModelLog"
+          @replaceModel="repliaceModel" @closeUpdateFile="removePersentList" @percentFinish="queryFloorFile(currentFolderId)"
+          :persentList="persentList"></floorTable>
       </el-card>
     </el-col>
     <!-- 弹窗 开始-->
 
     <!-- 模型日志弹窗 -->
-    <modelLog
-      :modelLogVisible="modelLogVisible"
-      :modelFolderName="currentFolderName"
-      @deleteFinish="updataLog"
-      @CloseModelLogDia="modelLogVisible=false"
-      :logData="logData"
-    ></modelLog>
+    <modelLog :modelLogVisible="modelLogVisible" :modelFolderName="currentFolderName" @deleteFinish="updataLog"
+      @CloseModelLogDia="modelLogVisible=false" :logData="logData"></modelLog>
     <!-- 替换模型弹窗 -->
-    <repliceModel
-      :repliceModelVisible="repliceModelVisible"
-      @closeReplaceModelDia="repliceModelVisible=false"
-      :replaceModelItem="replaceModelItem"
-      @updataModel="updateModelFile"
-    ></repliceModel>
+    <repliceModel :repliceModelVisible="repliceModelVisible" @closeReplaceModelDia="repliceModelVisible=false" :replaceModelItem="replaceModelItem"
+      @updataModel="updateModelFile"></repliceModel>
     <!-- 新增楼层 -->
-    <addFloorDialog
-      :addFloorFileVisible="addFloorFileVisible"
-      :floorList="tableData"
-      :FolderName="currentFolderName"
-      :FolderId="currentFolderId"
-      @closeAddFloorDia="addFloorFileVisible=false"
-      @finishCreateFloor="uploadModelFIle"
-    ></addFloorDialog>
+    <addFloorDialog :addFloorFileVisible="addFloorFileVisible" :floorList="tableData" :FolderName="currentFolderName" :FolderId="currentFolderId"
+      @closeAddFloorDia="addFloorFileVisible=false" @finishCreateFloor="uploadModelFIle"></addFloorDialog>
     <!-- 新增文件夹名称 -->
-    <addFolder
-      :addFolderVisible="addFolderVisible"
-      @closeAddFolderVisible="addFolderVisible=false;folderName=''"
-      :folderName="folderName"
-      @getfolderModel="queryModel"
-    ></addFolder>
+    <addFolder :addFolderVisible="addFolderVisible" @closeAddFolderVisible="addFolderVisible=false;folderName=''" :folderName="folderName"
+      @getfolderModel="queryModel"></addFolder>
     <!-- 编辑文件夹名字 -->
-    <changeFolderName
-      :currentFolderId="currentFolderId"
-      :changeFolderNameVisible="changeFolderNameVisible"
-      :folderName="folderName"
-      @finishChangeFolderName="queryModel"
-      @closeChangeFolderVisible="changeFolderNameVisible=false;folderName=''"
-    ></changeFolderName>
+    <changeFolderName :currentFolderId="currentFolderId" :changeFolderNameVisible="changeFolderNameVisible" :folderName="folderName"
+      @finishChangeFolderName="queryModel" @closeChangeFolderVisible="changeFolderNameVisible=false;folderName=''"></changeFolderName>
     <!-- 弹窗 结束-->
   </div>
 </template>
 <script>
 import { mapGetters } from "vuex";
 import request from "@/api/model/file.js";
+import Bus from '@/utils/bus.js'
 import dasBoard from "@/views/dasboard/index";
 import modelLog from "@/components/model/file/modelLog"; //模型日志弹窗
 import repliceModel from "@/components/model/file/replaceModelDialog"; //替换模型弹窗
@@ -119,7 +81,7 @@ import changeFolderName from "@/components/model/file/changeFolderName"; //编
 import floorTable from "@/components/model/file/floorTable"; //右侧list表
 export default {
   // 离开此页面前要判断是是否有下载
-  beforeRouteLeave: function(to, from, next) {
+  beforeRouteLeave: function (to, from, next) {
     console.log(this.uploadClassList);
     if (this.uploadClassList.length) {
       this.$alert(
@@ -247,7 +209,7 @@ export default {
       request.queryModel("", res => {
         this.navigationModel = res.Content;
         this.loading = false;
-        if(this.navigationModel.length){
+        if (this.navigationModel.length) {
           //默认选择第一个文件夹
           this.choiceIndex = 1;
           this.currentFolderName = this.navigationModel[0].Name;
@@ -266,40 +228,42 @@ export default {
      * @param currentFolderId 当前选择的文件夹id
      */
     queryFloorFile(currentFolderId) {
-      let data = {
-        FolderId: currentFolderId,
-        ProjectId: this.projectId
-      };
-      return new Promise((resolve, reject) => {
-        request.queryFloorList(data, res => {
-          res.Content.map(item => {
-            /**
-             * @info: 状态显示说明
-             * 0: 上传中(上传的用户可操作:中止)
-             * 1: 等待检查
-             * 10: 模型检查中
-             * 11: 未通过检查
-             * 2、20、21、3、31: 正常(所有用户可操作:下载、查看历史)
-             * 4: 正常(所有用户可操作:下载、替换、查看历史)
-             */
-            if (item.Status == 2 || item.Status == 20 || item.Status == 21 || item.Status == 3 || item.Status == 31 || item.Status == 4) {
-              Object.assign(item, { isDown: false, precent: 0 });
-            } else {
-              Object.assign(item, { isDown: true, precent: 100 });
-              if (this.persentList.length != 0) {
-                this.persentList.forEach(pItem => {
-                  if (item.Id == pItem.Id) {
-                    Object.assign(item, { isDown: true, precent: pItem.precent?pItem.precent:0 });
-                  }
-                });
+      if(currentFolderId){
+        let data = {
+          FolderId: currentFolderId,
+          ProjectId: this.projectId
+        };
+        return new Promise((resolve, reject) => {
+          request.queryFloorList(data, res => {
+            res.Content.map(item => {
+              /**
+               * @info: 状态显示说明
+               * 0: 上传中(上传的用户可操作:中止)
+               * 1: 等待检查
+               * 10: 模型检查中
+               * 11: 未通过检查
+               * 2、20、21、3、31: 正常(所有用户可操作:下载、查看历史)
+               * 4: 正常(所有用户可操作:下载、替换、查看历史)
+               */
+              if (item.Status == 2 || item.Status == 20 || item.Status == 21 || item.Status == 3 || item.Status == 31 || item.Status == 4) {
+                Object.assign(item, { isDown: false, precent: 0 });
+              } else {
+                Object.assign(item, { isDown: true, precent: 100 });
+                if (this.persentList.length != 0) {
+                  this.persentList.forEach(pItem => {
+                    if (item.Id == pItem.Id) {
+                      Object.assign(item, { isDown: true, precent: pItem.precent ? pItem.precent : 0 });
+                    }
+                  });
+                }
               }
-            }
+            });
+            this.tableData = res.Content;
+            this.loading = false;
+            resolve();
           });
-          this.tableData = res.Content;
-          this.loading = false;
-          resolve();
         });
-      });
+      }
     },
     //添加楼层文件
     addFloorFile() {
@@ -450,7 +414,8 @@ export default {
           request.upDateModelFile(
             data,
             that.projectId,
-            that.userInfo.username,
+            that.userInfo.userName,
+            that.userInfo.userId,
             res => {
               let loaded = res.loaded, //加载量
                 total = res.total; //文件大小
@@ -551,7 +516,7 @@ export default {
   watch: {
     uploadClassList: {
       deep: true,
-      handler: function(val) {
+      handler: function (val) {
         console.log(val);
       }
     },
@@ -561,6 +526,9 @@ export default {
   },
   mounted() {
     this.queryModel();
+    Bus.$on('modelStatusChange', message => {
+      this.queryFloorFile(this.currentFolderId);
+    })
     // 十秒刷新次楼层列表
     // setInterval(()=>{
     //    this.queryFloorFile(this.currentFolderId)

+ 1 - 1
src/views/point/dynamicdata/index.vue

@@ -26,7 +26,7 @@
         </el-tooltip>
       </div>
     </el-row>
-    <div v-show="typeList.length" style="height: 100%;">
+    <div v-show="typeList.length" style="height: calc(100% - 54px);">
       <!-- 设备 -->
       <equipRules v-if="curType=='设备'" ref="equip" :typeName="curType" @refresh="refreshTabs" :isPending="isPending"></equipRules>
       <!-- 部件 -->

+ 8 - 4
src/views/ready/buildfloor/addFloor/index.vue

@@ -1,10 +1,10 @@
 <template>
   <el-dialog :title="title" :visible.sync="dialogVisible" width="40%" @close="handleClose" id="messageDialog">
-    <div>
+    <el-row>
       <formItems :type="'Floor'" ref="formItems"></formItems>
-    </div>
+    </el-row>
     <span slot="footer" class="dialog-footer">
-      <el-button size="small">取消</el-button>
+      <el-button size="small" @click="dialogVisible=false">取消</el-button>
       <el-button size="small" type="primary" @click="confirm">确认</el-button>
     </span>
   </el-dialog>
@@ -89,13 +89,17 @@ export default {
 </script>
 <style lang="scss" scoped>
 #messageDialog {
+  /deep/ .el-dialog__body {
+    height: 420px;
+    overflow: auto;
+  }
   .el-form-item {
     /deep/ label.el-form-item__label {
       font-size: 12px;
     }
   }
   /deep/ .FloorTypeSelect .el-form-item__content {
-    width: 178px;
+    width: 200px;
   }
 }
 </style>

+ 13 - 15
src/views/ready/buildfloor/drawGraphy/checkGraphy.vue

@@ -1,7 +1,7 @@
 <template>
   <el-dialog id="checkGraphy" title="添加平面图" :visible.sync="checkGraphyVisible" width="900px" @close="handleClose">
     <div class="bodys">
-      <el-cascader :options="options" :show-all-levels="false" :props="props" @change="handleChange" @active-item-change='handleItemChange' clearable
+      <el-cascader :options="options" :show-all-levels="false" @change="handleChange" @active-item-change='handleItemChange' clearable
         placeholder="请选择模型文件" v-model="casVal"></el-cascader>
       <div>
@@ -9,7 +9,7 @@
       </div>
       <!-- 展示框 -->
       <div class="showBox">
-        <drawFloor ref="drawFloor"></drawFloor>
+        <drawFloor ref="drawFloorDialog" :showTools="false" :id="0"></drawFloor>
       </div>
     </div>
     <span slot="footer" class="dialog-footer">
@@ -22,7 +22,7 @@
 import drawFloor from "./drawFloor";
 import { mapGetters, mapActions } from "vuex";
 import request from "@/api/model/file.js";
-import { floorUpdate } from "@/api/scan/request";
+import { bindFloorModel } from "@/api/model/file";
 export default {
   components: {
     drawFloor
@@ -32,11 +32,12 @@ export default {
   },
   data() {
     return {
-      casVal:[],
+      casVal: [],
       jsonKey: "", //map.josn
       checkGraphyVisible: false,
       options: [],
       floor: {}, // 当前选中的楼层数据
+      modelIdToFloorId: {}
     };
   },
   methods: {
@@ -49,7 +50,7 @@ export default {
     handleClose() {
       this.checkGraphyVisible = false;
       this.casVal = []
-      this.$refs.drawFloor.clearGraphy()
+      this.$refs.drawFloorDialog.clearGraphy()
     },
     // 更新楼层 平面图文件
     bindGraphy() {
@@ -57,22 +58,18 @@ export default {
         this.$message.warning("请选择模型文件");
         return
       }
-      if (!this.floor.StructureInfo) {
-        this.floor.StructureInfo = {}
-      }
-      this.floor.StructureInfo.FloorMap = this.jsonKey
       let pa = {
-        Content: [this.floor]
+        Content: [{ FloorId: this.floor.FloorID, Id: this.modelIdToFloorId[this.jsonKey], BuildingId: this.floor.BuildID }]
       };
-      floorUpdate(pa, res => {
-        this.$message.success("添加成功");
+      bindFloorModel(pa, res => {
+        this.$message.success("更新成功");
         this.handleClose()
-        this.$emit('refresh')
+        this.$emit('refresh', this.jsonKey)
       });
     },
     // 点击多级联动
     handleChange(val) {
-      this.$refs.drawFloor.initGraphy(val[1])
+      this.$refs.drawFloorDialog.initGraphy(val[1])
       this.jsonKey = val[1]
     },
     // 通过id查询文件夹下模型文件
@@ -83,6 +80,7 @@ export default {
       };
       request.queryFloorList(data, res => {
         let tempArr = res.Content.map(t => {
+          this.modelIdToFloorId[t.CurrentModelId] = t.Id;
           return {
             value: t.CurrentModelId,
             label: t.FloorName
@@ -118,7 +116,7 @@ export default {
       });
     },
   },
-  created(){
+  created() {
     this.init()
   },
   watch: {

+ 136 - 75
src/views/ready/buildfloor/drawGraphy/drawFloor.vue

@@ -1,15 +1,24 @@
 <template>
-  <div id="drawFloor" v-loading="canvasLoading">
-    <canvas id="floorCanvas" :width="cadWidth" :height="cadHeight" ref="canvas"></canvas>
+  <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-if="showTools">
+      <canvasFun @move="moveCanvas" @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @divide="divide" @clearDivide="clearDivide" @undo="undo"
+        @redo="redo" @scale="scale" :isEdit="isEdit" ref="canvasFun"></canvasFun>
+    </div>
   </div>
 </template>
 
 <script>
 import eventBus from "./bus.js";
 import { SGraphyView } from "@sybotan-web/graphy/lib";
-import { FloorScene } from "cad-engine";
-import { SColor } from "@sybotan-web/draw/lib";
+import { DivideFloorScene } from "cad-engine"
+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,
@@ -17,102 +26,154 @@ export default {
       dataKey: '',
       cadWidth: 800,
       cadHeight: 600,
-      canvasLoading: false
+      canvasLoading: false,
+      modelId: '',
+      FloorID: '',
+      Outline: [],
     };
   },
+  props: {
+    isEdit: {
+      default: false
+    },
+    showTools: {
+      default: false
+    },
+    id: {
+      default: 0
+    }
+  },
+  created() {
+    this.FloorID = this.$route.query.FloorID;
+    this.OutlineFlag = this.$route.query.OutlineFlag;
+  },
   mounted() {
-    // this.initGraphy('3af6d175c34e11e993ac85337be80696');
-    // let that = this;
-    // eventBus.$on("suitableRatios", function () {
-    //   that.view.fitSceneToView();
-    // });
-    // eventBus.$on("changeRatios", function (val) {
-    //   that.changeRatios(val);
-    // });
-    // eventBus.$on("downImgs", function (val) {
-    //   that.view.saveImage("saveImage" + new Date(), "png");
-    // });
-    // eventBus.$on("openDrags", function (val) {
-    //   if (val) {
-
-    //   }
-    // });
-    this.cadWidth = document.getElementById("drawFloor").offsetWidth;
-    this.cadHeight = document.getElementById("drawFloor").offsetHeight;
+    this.cadWidth = document.getElementById(`drawFloor${this.id}`).offsetWidth;
+    this.cadHeight = document.getElementById(`drawFloor${this.id}`).offsetHeight;
   },
   methods: {
-    clickItem(item) {
-      this.$emit("clickGraphyItem", item);
-    },
-    // 单个个体绘制颜色
-    drawItemColor(item, color) {
-      item.fillColor = new SColor(color); //需要缓存的边框
-      item.cacheFillColor = new SColor(color); //需要
-    },
-    // 绘制所有的item
-    drawAllItemColor() {
-      this.drawMainScene.root.children.forEach((item, index) => {
-        let color = this.initColor[index % 10];
-        this.drawItemColor(item, color);
-      });
-    },
     initGraphy(ModelId) {
-      this.dataKey = ModelId
-      if (!this.dataKey) {
-        return;
-      }
-      this.canvasLoading = true
-      this.clearGraphy()
-      // 初始化view类
-      this.view = new SGraphyView("floorCanvas");
-      this.drawMainScene = new FloorScene(null);
       let that = this;
-      this.drawMainScene.getFloorData('/modelapi/base-graph/query', { ModelId: ModelId }).then(res => {
-        that.view.scene = that.drawMainScene
-        that.view.fitSceneToView();
-        this.canvasLoading = false
+      that.modelId = ModelId;
+      that.clearGraphy()
+      that.drawMainScene = new DivideFloorScene();
+      that.canvasLoading = true;
+      that.drawMainScene.getFloorData('/modelapi/base-graph/query', { ModelId: ModelId }).then(res => {
+        let Elements = res.EntityList[0].Elements;
+        let flag = false;
+        for (let key in Elements) {
+          if (Elements[key].length > 0) {
+            flag = true;
+          }
+        }
+        if (flag) {
+          that.view.scene = that.drawMainScene
+          that.view.fitSceneToView();
+          that.canvasLoading = false;
+          that.view.maxScale = that.view.scale * 10;
+          that.view.minScale = that.view.scale;
+          that.drawMainScene.isSpaceSelectable = false;
+          if (this.$refs.canvasFun) {
+            that.$refs.canvasFun.everyScale = that.view.scale;
+          }
+          if (that.OutlineFlag) {
+            this.getFloorData()
+          }
+        }
+      })
+    },
+    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)
       })
-      if (this.isScale) {
-        this.cancelScale(this.view);
+    },
+    // 清空平面图
+    clearGraphy() {
+      if (this.view) {
+        this.view.scene = null;
+        return
       }
+      let id = `floorCanvas${this.id}`;
+      this.view = new SGraphyView(id)
     },
-    // 单个item 高亮
-    heightLightitem(item, highlightColor) {
-      // this.drawItemColor(item, highlightColor);
+    // canvas 获取焦点
+    focus() {
+      document.getElementById(`floorCanvas${this.id}`).focus()
     },
-    // 取消放大缩小
-    cancelScale(view) {
-      // view.wheelZoom = 1;
+    // 工具栏操作
+    // 移动底图
+    moveCanvas(move) {
+      // todo
+      let canvas = document.getElementById(`floorCanvas${this.id}`);
+      if (move) {
+        canvas.style.cursor = 'move';
+      } else {
+        canvas.style.cursor = 'default';
+      }
     },
-    // 左键长按控制canvas的坐标
-    leftClickMove(a, b) {
-      //  console.log('move',a,b)
+    // 适配底图到窗口
+    fit() {
+      this.view.fitSceneToView()
     },
-    changeRatios(val) {
-      //计算缩放比例
-      this.view.scale = val;
+    // 保存为png
+    savePng() {
+      this.view.saveImage(`${this.floor}.png`, 'png');
     },
-    clearGraphy() {
-      if(this.drawMainScene){
-        this.drawMainScene.root.children = null
-        this.drawMainScene = null;
-        this.view = null;
+    // 保存为svg
+    saveSvg() {
+      this.view.saveSceneSvg(`${this.floor}.svg`, 6400, 4800);
+    },
+    // 切割划分
+    divide() {
+      this.drawMainScene.isMarking = true;
+    },
+    // 清除切割划分
+    clearDivide() {
+      this.drawMainScene.clearSceneMark()
+    },
+    // 撤销
+    undo() {
+
+    },
+    // 反撤销
+    redo() { },
+    // 缩放
+    scale(val) {
+      if (!this.view) {
+        return;
       }
-    }
+      let scale = this.view.scale;
+      this.view.scaleByPoint(val / scale, this.cadWidth / 2, this.cadHeight / 2)
+    },
   },
   watch: {
-    findGraphyItemId(n) {
-      if (n) {
-        this.heightLightitem();
+    "view.scale": {
+      handler(n) {
+        if (this.$refs.canvasFun) {
+          this.$refs.canvasFun.sliderVal = n * 10 / this.view.minScale;
+        }
       }
     }
   }
 };
 </script>
 <style scoped lang="less">
-#drawFloor {
+.drawFloor {
   width: 100%;
   height: 100%;
   position: relative;
+  .operate {
+    position: absolute;
+    left: 50%;
+    bottom: 20px;
+    transform: translateX(-50%);
+    z-index: 99;
+  }
 }
 </style>

+ 0 - 112
src/views/ready/buildfloor/drawGraphy/operateGraphyItem.vue

@@ -1,112 +0,0 @@
-<template>
-  <div id="operateGraphyItem">
-    <div class="div-box" @click="openDrag">
-      <i class="el-icon-rank"></i>
-    </div>
-    <div class="div-box" @click="suitableRatio">
-      <i class="el-icon-rank"></i>
-    </div>
-    <div class="div-box" @click="downImg">
-      <i class="el-icon-download"></i>
-    </div>
-    <div class="div-box" @click="removeRatio">
-      <i class="el-icon-remove-outline"></i>
-    </div>
-    <div class="line">
-      <el-slider tooltip-class="tooltip-class"  :max="0.02" :min="0.004" v-model="sliderValue" @change="adjustRatio"></el-slider>
-    </div>
-    <div class="div-box" @click="addRatio">
-      <i class="el-icon-circle-plus-outline"></i>
-    </div>
-  </div>
-</template>
-<script>
-import eventBus from "./bus.js";
-export default {
-  data() {
-    return {
-      sliderValue: 0.004,
-      isopenDrags:false ,//是否鼠标左键移动图片
-    };
-  },
-  methods: {
-    // 开启拖动
-    openDrag() {
-      this.isopenDrags = !this.isopenDrags;
-      eventBus.$emit('openDrags',this.isopenDrags)
-    },
-    //合适比例
-    suitableRatio() {
-      eventBus.$emit("suitableRatios");
-    },
-    // 滑块调整比例
-    adjustRatio(val) {
-      this.sliderValue = val;
-      eventBus.$emit("changeRatios", this.sliderValue);
-    },
-    //增加比例
-    addRatio() {
-      if (this.sliderValue >= 0.02) {
-        this.sliderValue = 0.02;
-      } else {
-        this.sliderValue = this.sliderValue + 0.001;
-      }
-      eventBus.$emit("changeRatios", this.sliderValue);
-    },
-    //减少比例
-    removeRatio() {
-      if (this.sliderValue <=0.004) {
-        this.sliderValue = 0.004;
-      } else {
-        this.sliderValue = this.sliderValue - 0.001;
-      }
-      eventBus.$emit("changeRatios", this.sliderValue);
-    },
-    // 下载图片
-    downImg(){
-      eventBus.$emit("downImgs");
-    }
-  },
-  mounted() {
-    let that = this;
-     eventBus.$on('viewScale',function(scale){
-       console.log(scale,'scalescale')
-       that.sliderValue = scale;
-
-     })
-  },
-};
-</script>
-<style lang="less">
-#operateGraphyItem {
-  display: flex;
-  position: relative;
-  border: 1px #ddd solid;
-  border-radius: 5px;
-  overflow: hidden;
-  z-index: 999;
-  .div-box {
-    font-size: 24px;
-    width: 40px;
-    height: 40px;
-    background: #67c23a;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    color: #fff;
-    cursor: pointer;
-    border-right: 1px #ddd solid;
-  }
-  .line {
-    width: 200px;
-    font-size: 12px;
-    display: block;
-    background: #67c23a;
-    border-right: 1px #ddd solid;
-    .tooltip-class {
-      width: 100%;
-      background-color: #409eff;
-    }
-  }
-}
-</style>

+ 0 - 60
src/views/ready/buildfloor/drawGraphy/repetitionGraphy.vue

@@ -1,60 +0,0 @@
-<template>
-  <el-dialog id="checkdrawimg" title="前期准备/建筑楼层管理/平面图维护" :visible.sync="repetitionGraphyVisible" width="60%" :before-close="handleClose">
-    <div class="bodys">
-      <div class="buttons">
-        <el-button icon="el-icon-back" size="mini"></el-button>
-        <el-button size="mini">替换平面图</el-button>
-        <el-button size="mini">编辑平面图</el-button>
-      </div>
-      <!-- 展示图片 -->
-      <div class="drawImg">
-        <drawFloor ref="drawFloor" :findGraphyItemId="findGraphyItemId" :point="point" :pointWidth="pointWidth" :cadWidth="1000" :cadHeight="500"
-          :isScale="true"></drawFloor>
-      </div>
-    </div>
-    <span slot="footer" class="dialog-footer">
-      <el-button @click="dialogVisible = false">取 消</el-button>
-      <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
-    </span>
-  </el-dialog>
-</template>
-<script>
-import drawFloor from "./drawFloor";
-export default {
-  components: {
-    drawFloor
-  },
-  props: {
-    repetitionGraphyVisible: Boolean
-  },
-  data() {
-    return {
-      modelId: "04153a22ce3111e9b1c7318645437bfe", // key
-      point: [40703.54760591985, 42678.14510522981], //坐标
-      pointWidth: 2000,
-      findGraphyItemId: "" //高亮的id
-    };
-  },
-  methods: {
-    handleClose() {
-      this.$emit("closeRepeatVisible");
-    }
-  },
-  mounted(){
-    // this.modelId = this.$router.query.modelId
-    console.log(22222)
-    let modelId = this.modelId
-    this.$refs.drawFloor.initGraphy(modelId)
-  }
-};
-</script>
-<style lang="less">
-#checkdrawimg {
-  .drawImg {
-    width: 100%;
-    height: 500px;
-    margin-top: 12px;
-    border: 1px solid #ccc;
-  }
-}
-</style>

+ 18 - 18
src/views/ready/buildfloor/index.vue

@@ -14,7 +14,7 @@
           <div v-for="(item,index) in buildList" :key="item.BuildID" :class="{'floor-item':true,active:item.active}" @click="changeBuild(index)">
             <span>
               {{item.BuildLocalName || item.BuildName}}
-              <el-badge class="mark" :is-dot="false" />
+              <el-badge v-if="item.Count>0" class="mark" :value="item.Count" />
             </span>
           </div>
         </div>
@@ -38,16 +38,16 @@
             </el-table-column>
             <el-table-column prop="Datasource" label="平面图">
               <template slot-scope="scope">
-                <p v-if="scope.row.StructureInfo&&scope.row.StructureInfo.FloorMap" @click="checfDrawImg(scope.row,1)">
-                  <i class="iconfont icon-floorplan"></i>
-                  查看平面图
-                </p>
-                <p v-else-if="scope.row.type==2" @click="checfDrawImg(scope.row,2)">
+                <p v-if="scope.row.Sign>0" @click="checkDrawImg(scope.row,2)">
                   <el-badge is-dot>
                     <i class="iconfont icon-floorplan"></i>
                   </el-badge>平面图重复
                 </p>
-                <p v-else @click="checfDrawImg(scope.row,3)">
+                <p v-else-if="scope.row.ModelId" @click="checkDrawImg(scope.row,1)">
+                  <i class="iconfont icon-floorplan"></i>
+                  查看平面图
+                </p>
+                <p v-else @click="checkDrawImg(scope.row,3)">
                   <i class="iconfont icon-nopicture"></i>
                   暂无平面图
                 </p>
@@ -93,7 +93,7 @@ import addBuild from "@/components/ready/buildfloor/addBuild";
 import { mapGetters, mapActions } from "vuex";
 import addConnectivity from "@/components/ready/buildfloor/addConnectivity";
 import checkGraphy from "./drawGraphy/checkGraphy"; //查看图片
-import { buildingQuery, floorQuery, manageDeleteFloor } from "@/api/scan/request";
+import { buildingQueryAndCount, floorQueryAndSign, manageDeleteFloor } from "@/api/scan/request";
 export default {
   components: {
     addFloor,
@@ -114,11 +114,7 @@ export default {
         lineHeight: "30px"
       },
       buildList: [],
-      tableData: [
-        {
-          EquipmentMark: 1
-        }
-      ],
+      tableData: [],
       page: {
         pageSize: 500,
         pageSizes: [10, 20, 50, 100],
@@ -144,7 +140,7 @@ export default {
         PageNumber: 1,
         PageSize: 500
       };
-      buildingQuery(bdParam, res => {
+      buildingQueryAndCount(bdParam, res => {
         this.buildList = res.Content;
         if (this.buildList.length) {
           this.changeBuild(0);
@@ -201,7 +197,7 @@ export default {
         PageSize: this.page.pageSize,
         Filters: `BuildID='${this.curBuildId}'`
       };
-      floorQuery(floorParam, res => {
+      floorQueryAndSign(floorParam, res => {
         this.tableData = res.Content;
         this.page.total = res.Total;
       });
@@ -235,13 +231,17 @@ export default {
       this.$refs.addConnectivity.floor = row;
     },
     // 查看平面图
-    checfDrawImg(row, index) {
+    checkDrawImg(row, index) {
       if (3 == index) {
         this.$refs.checkGraphy.showDialog(row)
         this.modelId = "";
       } else {
-        this.modelId = row.StructureInfo.FloorMap;
-        this.$router.push({ name: "repetitionGraphy", query: { modelId: this.modelId } });
+        this.modelId = row.ModelId;
+        let pa = { modelId: this.modelId, FloorID: row.FloorID, BuildID: row.BuildID }
+        if (row.Outline && row.Outline.length) {
+          pa.OutlineFlag = true;
+        }
+        this.$router.push({ name: "repetitionGraphy", query: pa });
       }
     }
   },

+ 71 - 34
src/views/ready/buildfloor/repetitionGraphy.vue

@@ -3,60 +3,103 @@
   <div id="repetitionGraphy">
     <div class="buttons">
       <el-button icon="el-icon-back" size="mini" @click="backRouter"></el-button>
-      <el-button size="mini" @click="changeGraphy">替换平面图</el-button>
-      <el-button size="mini">编辑平面图</el-button>
+      <el-button v-if="!isEdit" size="mini" @click="changeGraphy">替换平面图</el-button>
+      <el-button v-if="!isEdit" size="mini" @click="editGraphy">编辑平面图</el-button>
+      <el-button v-if="isEdit" size="mini" @click="cancel">取消</el-button>
+      <el-button v-if="isEdit" size="mini" @click="confirm" type="primary">确认</el-button>
     </div>
     <!-- 展示图片 -->
     <div class="drawImg">
-      <drawFloor ref="drawFloor"></drawFloor>
+      <drawFloor ref="drawFloor" :isEdit="isEdit" :showTools="true" :id="1"></drawFloor>
     </div>
     <!-- 查看图片弹窗 -->
-    <checkGraphy :checkGraphyVisible="checkGraphyVisible" @handleCloseCGraphy="checkGraphyVisible=false"></checkGraphy>
-    <div id="operateList">
-      <operateGraphyItem></operateGraphyItem>
-    </div>
+    <checkGraphy ref="checkGraphy" @refresh="refresh"></checkGraphy>
   </div>
 </template>
 <script>
 import drawFloor from "./drawGraphy/drawFloor";
 import checkGraphy from "./drawGraphy/checkGraphy"; //查看图片
-import operateGraphyItem from "./drawGraphy/operateGraphyItem" //各个item
+import { floorUpdate } from "@/api/scan/request";
 export default {
   components: {
     drawFloor,
-    checkGraphy,
-    operateGraphyItem
+    checkGraphy
   },
   data() {
     return {
-      checkGraphyVisible: false, //查看平面图弹窗
-      modelId: "04153a22ce3111e9b1c7318645437bfe", // key
-      point: [40703.54760591985, 42678.14510522981], //坐标
-      pointWidth: 2000,
-      findGraphyItemId: "", //高亮的id
-      slidervalue: 0
+      modelId: "", // 
+      isEdit: false, // 是否编辑模式
     };
   },
+  created() {
+    this.modelId = this.$route.query.modelId;
+    this.FloorID = this.$route.query.FloorID;
+    this.BuildID = this.$route.query.BuildID;
+    this.OutlineFlag = this.$route.query.OutlineFlag;
+  },
+  mounted() {
+    this.$refs.drawFloor.initGraphy(this.modelId)
+  },
   methods: {
-    handleClose() {
-      this.$emit("closeRepeatVisible");
-    },
     // 返回路由
     backRouter() {
-      this.$router.go(-1);
+      this.$router.push({ name: 'buildFloor' })
     },
     // 替换模型文件
     changeGraphy() {
-      this.checkGraphyVisible = true;
+      this.$refs.checkGraphy.showDialog({ FloorID: this.FloorID, BuildID: this.BuildID })
     },
+    // 确认保存
+    confirm() {
+      let sceneMark = this.$refs.drawFloor.drawMainScene.sceneMark, Outline = null;
+      if (sceneMark) {
+        if (sceneMark.outLine.length < 3) {
+          this.$message.warning('请添加轮廓线');
+          return;
+        }
+        if (!sceneMark.closeFlag) {
+          this.$message.warning('请按回车闭合轮廓线');
+          this.$refs.drawFloor.focus();
+          return;
+        }
+        Outline = this.$refs.drawFloor.drawMainScene.sceneMark.outLine
+        Outline = Outline.map(t => {
+          return {
+            x: t.x.toFixed(2),
+            y: t.y.toFixed(2),
+          }
+        })
+      }
+      let pa = {
+        Content: [{ FloorID: this.FloorID, Outline: Outline }],
+        Projection: ['Outline']
+      }
+      floorUpdate(pa, res => {
+        this.isEdit = false;
+        this.$message.success("更新成功");
+      })
+    },
+    // 取消
+    cancel() {
+      this.isEdit = false;
+      this.$refs.drawFloor.initGraphy(this.modelId)
+    },
+    // 编辑平面图
+    editGraphy() {
+      this.isEdit = true;
+    },
+    // 替换模型文件成功
+    refresh(modelId) {
+      this.modelId = modelId
+    }
   },
-  mounted() {
-    // this.dataKey = `/image-service/common/file_get/${this.$route.query.jsonKey}?systemId=revit`;
-    // this.modelId = this.$router.query.modelId
-    let modelId = this.modelId
-    console.log(this.$refs.drawFloor)
-    this.$refs.drawFloor.initGraphy(modelId)
-  },
+  watch: {
+    modelId(n, o) {
+      if (o && n != o) {
+        this.$refs.drawFloor.initGraphy(n)
+      }
+    }
+  }
 };
 </script>
 <style lang="less">
@@ -72,11 +115,5 @@ export default {
     margin-top: 10px;
     height: calc(100% - 40px);
   }
-  #operateList {
-    position: absolute;
-    left: 50%;
-    bottom: 100px;
-    // margin-left:
-  }
 }
 </style>