Browse Source

Merge branch 'dev' of git.sagacloud.cn:web/ibms into dev

zhangyu 5 years ago
parent
commit
3ddf24af81
96 changed files with 9945 additions and 4591 deletions
  1. 1 1
      config/index.js
  2. 4 4
      package.json
  3. 112 7
      src/api/scan/request.js
  4. 11 3
      src/components/business_space/business/handsontable.vue
  5. 1 1
      src/components/business_space/dialogs/addDialog/businessDialog.vue
  6. 64 20
      src/components/business_space/dialogs/list/firm.vue
  7. 2 1
      src/components/business_space/newAddDialogs/addEquipDialog.vue
  8. 1 0
      src/components/business_space/newAddDialogs/addSystemDialog.vue
  9. 180 75
      src/components/business_space/newGraphy/graphy.vue
  10. 1 1
      src/components/business_space/newGraphy/unRelateBSP.vue
  11. 9 8
      src/components/business_space/newTables/eqToSpaceTable.vue
  12. 8 7
      src/components/business_space/newTables/syInSpaceTable.vue
  13. 1 1
      src/components/common/handsontable.vue
  14. 49 172
      src/components/config_point/dictionaryCascader.vue
  15. 3 3
      src/components/config_point/step3_edit/index.vue
  16. 3 3
      src/components/config_point/step3_point/3_temps.vue
  17. 1 0
      src/components/config_point/step3_point/steps3_main.vue
  18. 135 0
      src/components/data_admin/zoneInput.vue
  19. 1 1
      src/components/dialogHanson/addDevice.vue
  20. 1 1
      src/components/dialogs/addDialog/businessDialog.vue
  21. 1 1
      src/components/dialogs/addDialog/dialogAssets.vue
  22. 2 2
      src/components/dialogs/addDialog/dialogDevice.vue
  23. 1 1
      src/components/dialogs/addDialog/dialogSystem.vue
  24. 539 0
      src/components/dialogs/list/batchDialog.vue
  25. 87 43
      src/components/dialogs/list/filesDialog.vue
  26. 132 85
      src/components/dialogs/list/firm.vue
  27. 111 107
      src/components/dialogs/list/insurerDialog.vue
  28. 111 107
      src/components/dialogs/list/maintainerDialog.vue
  29. 147 126
      src/components/dialogs/list/picDialog.vue
  30. 110 106
      src/components/dialogs/list/supplierDialog.vue
  31. 68 34
      src/components/dialogs/list/uploadImgDialog.vue
  32. 1 1
      src/components/ledger/addDialog/dialogAssets.vue
  33. 2 2
      src/components/ledger/addDialog/dialogDevice.vue
  34. 1 1
      src/components/ledger/addDialog/dialogSystem.vue
  35. 6 8
      src/components/ledger/cenote/dialog/addSpaceDialog.vue
  36. 6 2
      src/components/ledger/handsontables/assets.vue
  37. 1187 864
      src/components/ledger/handsontables/device.vue
  38. 5 3
      src/components/ledger/handsontables/system.vue
  39. 1 1
      src/components/ledger/lib/addDevice.vue
  40. 299 0
      src/components/ledger/lib/cenoteGraphy.vue
  41. 196 155
      src/components/ledger/lib/uploadFiles.vue
  42. 1 1
      src/components/ledger/lib/uploadImgsName.vue
  43. 281 0
      src/components/point/dynamicdata/buildRules.vue
  44. 19 1
      src/components/point/dynamicdata/delRelationDialog.vue
  45. 1 1
      src/components/point/dynamicdata/equipRules.vue
  46. 289 0
      src/components/point/dynamicdata/floorRules.vue
  47. 25 5
      src/components/point/dynamicdata/historyDialog.vue
  48. 8 2
      src/components/point/dynamicdata/locationCascader.vue
  49. 287 0
      src/components/point/dynamicdata/projectRules.vue
  50. 278 0
      src/components/point/dynamicdata/tenantRules.vue
  51. 6 0
      src/fetch/point_http.js
  52. 1 0
      src/framework/layout/layout-store.js
  53. 2 2
      src/main.js
  54. 55 4
      src/router/system.js
  55. 31 3
      src/store/modules/project.js
  56. 4 1
      src/utils/handsontable/mainText.js
  57. 1 1
      src/utils/handsontable/notShow.js
  58. 4 0
      src/utils/scan/tools.js
  59. 10 0
      src/utils/spaceColor.js
  60. 161 0
      src/views/business_space/dataUtil/index2.vue
  61. 26 66
      src/views/data_admin/buildData/index.vue
  62. 214 0
      src/views/data_admin/buildGraphy/createPointZone.vue
  63. 349 909
      src/views/data_admin/buildGraphy/graphyCanvas.vue
  64. 481 452
      src/views/data_admin/buildGraphy/graphyTabs.vue
  65. 222 228
      src/views/data_admin/buildGraphy/index.vue
  66. 79 0
      src/views/data_admin/buildGraphy/locationPointMsg.vue
  67. 272 0
      src/views/data_admin/buildGraphy/updatePointZone.vue
  68. 2 2
      src/views/ledger/cenotelist/cenoteadd/index.vue
  69. 5 5
      src/views/ledger/cenotelist/index.vue
  70. 203 67
      src/views/ledger/cenotelist/relatedSpace.vue
  71. 160 27
      src/views/ledger/cenotelist/relatedSpaceList.vue
  72. 11 7
      src/views/ledger/facility/addfacility.vue
  73. 2 2
      src/views/ledger/facility/parts/index.vue
  74. 12 8
      src/views/ledger/facility/partsmanage/addparts/index.vue
  75. 12 7
      src/views/ledger/facility/partsmanage/index.vue
  76. 12 8
      src/views/ledger/property/addproperty.vue
  77. 4 4
      src/views/ledger/rentlist/index.vue
  78. 2 2
      src/views/ledger/rentlist/rentadd/index.vue
  79. 13 9
      src/views/ledger/spacelist/index.vue
  80. 0 2
      src/views/ledger/spacelist/spaceDetail/index.vue
  81. 2 2
      src/views/ledger/system/addsystem.vue
  82. 39 14
      src/views/point/config_point/steps/step1.vue
  83. 174 0
      src/views/point/dynamicdata/addRelation/addRelationCommon.scss
  84. 557 0
      src/views/point/dynamicdata/addRelation/buildRela/index.vue
  85. 7 171
      src/views/point/dynamicdata/addRelation/equipRela/index.vue
  86. 564 0
      src/views/point/dynamicdata/addRelation/floorRela/index.vue
  87. 7 171
      src/views/point/dynamicdata/addRelation/partsRela/index.vue
  88. 558 0
      src/views/point/dynamicdata/addRelation/projectRela/index.vue
  89. 7 171
      src/views/point/dynamicdata/addRelation/spaceRela/index.vue
  90. 6 171
      src/views/point/dynamicdata/addRelation/systemRela/index.vue
  91. 558 0
      src/views/point/dynamicdata/addRelation/tenantRela/index.vue
  92. 22 2
      src/views/point/dynamicdata/index.vue
  93. 21 6
      src/views/ready/buildfloor/drawGraphy/drawFloor.vue
  94. 5 4
      src/views/ready/buildfloor/repetitionGraphy.vue
  95. 2 1
      src/views/screen/splitscreen/integrateresults/index.vue
  96. 270 94
      src/views/screen/splitscreen/spaceledger/index.vue

+ 1 - 1
config/index.js

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

+ 4 - 4
package.json

@@ -25,10 +25,10 @@
         "vue-router": "^3.0.1",
         "vuex": "^3.1.0",
         "cad-engine": "2.0.250",
-        "@saga-web/base": "2.1.9",
-        "@saga-web/draw": "2.1.58",
-        "@saga-web/graphy": "2.1.30",
-        "@saga-web/cad-engine": "2.0.385"
+        "@saga-web/base": "2.1.8",
+        "@saga-web/draw": "2.1.57",
+        "@saga-web/graphy": "2.1.28",
+        "@saga-web/cad-engine": "2.0.308"
     },
     "devDependencies": {
         "ajv": "^6.9.1",

+ 112 - 7
src/api/scan/request.js

@@ -158,7 +158,6 @@ export function getPT(param) {
         "BeginTime": param.BeginTime,
         "ProjId": param.ProjId,
         "UserId": param.UserId,
-        "BeginTime": param.BeginTime,
         "EndTime": param.EndTime,
         "BuildId": param.BuildId,
         "FloorId": param.FloorId
@@ -171,6 +170,37 @@ export function getPT(param) {
     return fetch({ method: 'POST', url: `${api}/service/fm/point_group`, data })
 }
 
+//查询点位标签信息/location-point/query
+export function locationPointQuery(param, success) {
+    let url = `${baseUrl}/datacenter/location-point/query`;
+    http.postJson(url, param, success)
+}
+
+//点位标签详情修改【数据中心接口】
+export function updateLocationPoint(param, success) {
+    let url = `${baseUrl}/datacenter/location-point/update`;
+    http.postJson(url, param, success)
+}
+
+//根据点位标签推荐业务空间
+export function zoneQueryByPoint(param, success) {
+    let url = `${baseUrl}/equip-component/space/in-bdfl-zonespacebase?X=${param.X}&Y=${param.Y}`;
+    http.postJson(url, param.data, success)
+}
+
+//更新业务空间图片
+export function updateZonePic(param, success) {
+    let url = `${baseUrl}/equip-component/space/update-space-picinfo`;
+    http.postJson(url, param, success)
+}
+
+//扫楼作业-位置标签-删除图片
+export function deleteLocationImg(param, success) {
+    let url = `${baseUrl}/datacenter/location-point/delete-image`;
+    http.postJson(url, param, success)
+}
+
+
 //点位标签查看详情
 export function getPoint(param) {
     let data = {
@@ -193,7 +223,7 @@ export function updatePoint(param) {
     return fetch({ method: 'POST', url: `${api}/service/point/update`, data })
 }
 
-//点击点位标签获取tab设备族列表 
+//点击点位标签获取tab设备族列表
 export function getTabFamily(param) {
     let data = {
         "Comming": Comming,
@@ -690,13 +720,27 @@ export function getSysToEq(param, success) {
     http.postJson(url, data, success)
 }
 
-//台账查询型号
+//按生产商名, 品牌名, 型号名模糊查询型号
 export function getSpecList(param, success) {
     let url = `${venders}/manufacturer/specification/query_spec`
     let data = param
     http.postJson(url, data, success)
 }
 
+//按品牌名称和生厂商名称模糊查询品牌
+export function getBrandList(param, success) {
+    let url = `${venders}/manufacturer/brand/queryByName`
+    let data = param
+    http.postJson(url, data, success)
+}
+
+//按名称模糊查询生产商
+export function getManufacturerList(param, success) {
+    let url = `${venders}/manufacturer/queryByName`
+    let data = param
+    http.postJson(url, data, success)
+}
+
 //台账根据设备id创建岗位
 export function EqToAssets(param, success) {
     let url = `${physics}/property/create_by_equip?projectId=${param.ProjId}&secret=${param.secret}`
@@ -765,6 +809,36 @@ export function saveCenoteRelateSpace(param, success) {
     http.postJson(url, param, success)
 }
 
+//竖井关联的业务空间的楼层
+export function shaftSpaceBuildingQuery(param, success) {
+    let url = `${baseUrl}/datacenter/shaft/shaft-zoneSpaceBaseTable-building`
+    http.getJson(url, param, success)
+}
+
+//竖井关联的业务空间
+export function shaftSpaceQuery(param, success) {
+    let url = `${baseUrl}/datacenter/shaft/shaft-zoneSpaceBaseTable?ShaftId=${param.ShaftId}`
+    http.postJson(url, param.data, success)
+}
+
+//获取未和当前竖井关联的业务空间
+export function shaftUnlinkSpaceQuery(param, success) {
+    let url = `${baseUrl}/datacenter/shaft/un-shaft-zoneSpaceBaseTable?ShaftId=${param.ShaftId}`
+    http.postJson(url, param.data, success)
+}
+
+//竖井下的业务空间,竖井一对多,不覆盖
+export function linkShaftSpace(param, success) {
+    let url = `${baseUrl}/datacenter/sh-contain-sp-base/link`
+    http.postJson(url, param, success)
+}
+
+//删除竖井下的业务空间,只针对一个对象
+export function spaceInShaftUnlink(param, success) {
+    let url = `${baseUrl}/datacenter/sh-contain-sp-base/unlink?type=${param.type}`
+    http.postJson(url, param.data, success)
+}
+
 //获取租户表格内容信息
 export function getRentTableData(param, success) {
     let url = `${baseUrl}/datacenter/tenant/query-with-count`
@@ -851,6 +925,12 @@ export function getDataDictionary(param, success) {
     http.postJson(url, data, success)
 }
 
+//all - 查询数据字典 --列表表头
+export function cacheDictionary(param, success) {
+    let url = `${baseUrl}/datacenter/class-def/query-dict`;
+    http.postJson(url, param, success)
+}
+
 //批量处理字典信息操作
 export function setInfoPoint(param, success) {
     let url = `${baseUrl}/datacenter/data-dictionary/project/dict-batch`;
@@ -922,10 +1002,10 @@ export function queryLinkSys(param, success) {
 //查询系统信息 - 建筑楼层 - 系统一对多
 export function querySysLinkBuild(param, success) {
     let url = `${baseUrl}/datacenter/general—system/query-new`;
-    if(param.buildingId){
+    if (param.buildingId) {
         url += `?buildingId=${param.buildingId}`
     }
-    if(param.floorId){
+    if (param.floorId) {
         url += `&floorId=${param.floorId}`
     }
     http.postJson(url, param.data, success)
@@ -938,7 +1018,7 @@ export function equipLinkSys(param, success) {
     http.postJson(url, param, success)
 }
 
-//设备清单 - 设备关联系统 系统1-n   
+//设备清单 - 设备关联系统 系统1-n
 export function sysLinkEquip(param, success) {
     let url = `${baseUrl}/datacenter/sy-in-eq/link-sy-eq`;
     http.postJson(url, param, success)
@@ -994,6 +1074,11 @@ export function queryProperty(param, success) {
     http.postJson(url, param, success)
 }
 
+// 修改设备的附件功能
+export function queryUpdate(param, success) {
+    let url = `${baseUrl}/equip-component/equip-query/update`;
+    http.postJson(url, param, success)
+}
 //查询资产 同时关联设备信息
 export function propertyLinkEq(param, success) {
     let url = `${baseUrl}/equip-component/property/property-query`;
@@ -1504,6 +1589,16 @@ export function updateRelateInSpAndBuild(param, success) {
     let url = `${baseUrl}/datacenter/update-relationship/update-sp`;
     http.postJson(url, param, success)
 }
+//关系-----查询竖井关联的空间类型和名称
+export function shaftSpaceTypeQuery(param, success) {
+    let url = `${baseUrl}/datacenter/sh-contain-sp-base/space-type-query?shaftId=${param.shaftId}`;
+    http.postJson(url, param, success)
+}
+//关系-----竖井下的业务空间,竖井一对多,此方法会覆盖以前的记录
+export function shaftZoneLink(param, success) {
+    let url = `${baseUrl}/datacenter/sh-contain-sp-base/link-shsps-replace?BuildingId=${param.BuildingId}&FloorId=${param.FloorId}&Type=${param.Type}`;
+    http.postJson(url, param.data, success)
+}
 
 /**系统集成成果管理 */
 //系统集成统计条形图
@@ -1550,4 +1645,14 @@ export function addTabFunNum(param, success) {
 export function tableFuncRelatedOverview(param, success) {
     let url = `/pointconfig/report/meter-related`
     http.postJson(url, param, success)
-}
+}
+//实例中查询设备信息
+export function getEquipByEqID(param, success) {
+    let url = `${baseUrl}/datacenter/equip/query`
+    http.postJson(url, param, success)
+}
+//获取楼层信息
+export function getFloorMsgByFloorID(param, success) {
+    let url = `${baseUrl}/datacenter/floor/query`
+    http.postJson(url, param, success)
+}

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

@@ -206,7 +206,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"
@@ -254,9 +254,15 @@ export default {
       let val = this.hot.colToProp(row.col);
       lStorage.set('screen_data', {path: this.$route.path, data: {RoomID: infos.RoomID, zone: this.zoneCode}})
       if (val == "point") {
+        let query = {
+          RoomID: infos.RoomID,
+          zone: this.zoneCode,
+          isMyTab: 2,
+          buildFloorSelectd: this.buildFloorSelectd
+        }
         this.$router.push({
           path: "/ledger/spaceDetail",
-          query: { RoomID: infos.RoomID, zone: this.zoneCode, isMyTab: 2 }
+          query: query
         })
       } else if (val == "RoomQRCode") {
         this.qrcodeUrl = this.main[row.row].RoomQRCode
@@ -616,6 +622,8 @@ export default {
   },
   watch: {
     projectId() {
+      this.buildFloorData = []
+      buildFloor.getData(this.buildFloorData)
       this.setData()
       this.main = null
     },
@@ -646,4 +654,4 @@ export default {
     color: gray;
   }
 }
-</style>
+</style>

+ 1 - 1
src/components/business_space/dialogs/addDialog/businessDialog.vue

@@ -478,7 +478,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"

+ 64 - 20
src/components/business_space/dialogs/list/firm.vue

@@ -14,6 +14,9 @@
             clearable
           ></el-input>
           <el-button @click="searchKey" size="small">查找</el-button>
+          <el-select v-model="value" style="margin-left:10px;" @change="handleChangeType" placeholder="请选择">
+            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+          </el-select>
         </div>
         <el-radio-group v-model="radio" style="width:100%;">
           <el-table class="data-table" border :data="tableData" style="width: 100%" height="300px">
@@ -26,7 +29,8 @@
             <el-table-column header-align='center' prop="name" label="型号"></el-table-column>
             <el-table-column header-align='center' label="技术参数">
               <template slot-scope="scope">
-                <el-button type="text" @click="lookParam(scope.row)">技术参数</el-button>
+                <el-button type="text"  @click="lookParam(scope.row)">技术参数</el-button>
+                <el-button :disabled="scope.row.specificationId?false:true" type="text" @click="lookParam(scope.row)">技术参数</el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -37,8 +41,8 @@
                 <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
             </p>
             <my-pagination :page="page" @change="changed" style="margin-top:10px;"></my-pagination>
-        </div>       
-        
+        </div>
+
       </div>
     </div>
     <param-details :isLoad="isLoad" :data="data"></param-details>
@@ -51,11 +55,12 @@
   </el-dialog>
 </template>
 <script>
+
 import myPagination from "@/components/common/myPagination";
 import paramDetails from "@/components/business_space/dialogs/list/paramDetails"
-import { getSpecList } from "@/api/scan/request"
+import { getSpecList, getBrandList, getManufacturerList } from "@/api/scan/request"
 
-export default {
+    export default {
   components: {
     myPagination,
     paramDetails
@@ -77,8 +82,18 @@ export default {
     return {
       search: "", //搜索文案
       radio: "",
-      tableData: [
-      ],
+      value: "specification",//当前选择的查看类型
+      options: [{
+          value: 'specification',
+          label: '选型号'
+        }, {
+          value: 'brand',
+          label: '选生产厂家-品牌'
+        }, {
+          value: 'manufacturer',
+          label: '选生产厂家'
+      }],
+      tableData: [],
       data: {},
       isLoad: {
         paramShow: false
@@ -122,19 +137,48 @@ export default {
       }
       this.getData()
     },
+    handleChangeType(item) {
+      this.page.total = 0
+      this.tableData = []
+      this.getData()
+    },
     getData() {
-      getSpecList({
-        limit: {
-          skip: this.page.size * (this.page.currentPage - 1),
-          count: this.page.size
-        },
-        eqFamily: this.mess.deviceId,
-        name: this.search
-      }, res => {
-        this.page.total = res.totalCount
-        this.tableData = res.content
-        console.log(this.tableData)
-      })
+      if(this.value == 'specification') {//型号
+        getSpecList({
+          limit: {
+            skip: this.page.size * (this.page.currentPage - 1),
+            count: this.page.size
+          },
+          eqFamily: this.mess.deviceId,
+          name: this.search
+        }, res => {
+          this.page.total = res.totalCount
+          this.tableData = res.content
+        })
+      } else if(this.value == 'brand') {//生产厂家-品牌
+        getBrandList({
+          limit: {
+            skip: this.page.size * (this.page.currentPage - 1),
+            count: this.page.size
+          },
+          name: this.search
+        }, res => {
+          this.page.total = res.totalCount
+          this.tableData = res.content
+        })
+      } else if(this.value == 'manufacturer') {//生产厂家
+        getManufacturerList({
+          limit: {
+            skip: this.page.size * (this.page.currentPage - 1),
+            count: this.page.size
+          },
+          name: this.search
+        }, res => {
+          this.page.total = res.totalCount
+          this.tableData = res.content
+        })
+      }
+      console.log(this.tableData)
     }
   },
   watch: {
@@ -142,7 +186,7 @@ export default {
       deep: true,
       handler: function () {
         if (this.dialog.firm) {
-          console.log(this.mess)
+          this.value = 'specification'
           this.changePage()
         }
       }

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

@@ -139,6 +139,7 @@ export default {
           Filters: '',
           PageNumber: this.page.pageNumber,
           PageSize: this.page.pageSize,
+          Orders: 'EquipID asc'
         },
         type: this.zone,
         spaceId: this.spaceId
@@ -157,7 +158,7 @@ export default {
         pa.data.Filters += `;EquipName contain "${this.keycode}" or EquipLocalName contain "${this.keycode}" or EquipLocalID contain "${this.keycode}"`
       }
       // 删除首尾分号
-      pa.data.Filters = pa.data.Filters.replace(/(^;)|(;$)/g,'');
+      pa.data.Filters = pa.data.Filters.replace(/(^;)|(;$)/g, '');
       if (pa.data.Filters == '') {
         delete pa.data.Filters
       }

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

@@ -87,6 +87,7 @@ export default {
       let pa = {
         data: {
           PageSize: 200,
+          Orders: 'SysID asc'
         },
         type: this.zone,
         spaceId: this.spaceId

+ 180 - 75
src/components/business_space/newGraphy/graphy.vue

@@ -31,13 +31,14 @@
                 <el-dropdown-item command="groupCreateBSpace">批量创建业务空间</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>
+            <!-- 点击已经关联的业务空间 -->
+            <el-button type="primary" plain @click="refactorBSP" :disabled="zoneDisable" style="margin-left:10px;">重新划分业务空间</el-button>
+            <el-button type="primary" @click="editeSpaceDetail" :disabled="zoneDisable">编辑空间详情</el-button>
+            <el-button plain @click="cancelGraphy" v-show="!zoneDisable">取 消</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==2">
+          </div> -->
           <!-- 点击未关联的业务空间 -->
           <div v-show="type==3">
             <el-button plain @click="createNewZone">创建单个全新的业务空间</el-button>
@@ -92,8 +93,8 @@
 import canvasFun from "./canvasFun"
 import { mapGetters, mapActions } from "vuex";
 import { SColor, SPoint } from "@saga-web/draw/lib";
-import { DivideFloorScene, SpaceItem, ZoneItem } from "@saga-web/cad-engine/lib";
-import { FloorView } from "@saga-web/cad-engine/lib/FloorView";
+import { DivideFloorScene, SpaceItem, ZoneItem, FloorView } from "@saga-web/cad-engine/lib";
+import { colorArr } from "@/utils/spaceColor"
 import unRelateBSP from "./unRelateBSP";
 import createBSP from "./createBSP";
 import {
@@ -106,18 +107,7 @@ import {
   createRelateInZoneAndISp,
   groupCreRelaZoneAndISp
 } from "@/api/scan/request"
-const colorArr = [
-  "#F9C3C3",
-  "#FFD1BF",
-  "#FFF3BF",
-  "#D8F7C6",
-  "#C6F2F6",
-  "#DCE3C0",
-  "#FAE6C9",
-  "#E3D7F7",
-  "#C4CBF8",
-  "#DEC3F6"
-];
+
 //  BSP => 业务空间
 export default {
   components: {
@@ -156,13 +146,13 @@ export default {
       zoneList: [], // 业务空间-canvas图中
       groupCreateDialogVis: false, //批量创建业务空间弹窗
       groupCreateType: 1, //批量创建方式
+      zoneDisable: true, // 重新划分是否禁用
     }
   },
   computed: {
     ...mapGetters('layout', ['projectId'])
   },
-  created() {
-  },
+  created() {},
   mounted() {
     this.canvasWidth = this.$refs.graphy.offsetWidth;
     this.canvasHeight = this.$refs.graphy.offsetHeight;
@@ -172,10 +162,13 @@ export default {
     init(initType) {
       this.type = 1;
       if (this.scene) {
-        this.scene.isZoneSelectable = true;
-        this.scene.isSpaceSelectable = true;
         this.scene.clearSpaceSelection();
         this.scene.clearZoneSelection();
+        this.scene.clearCut();
+        this.scene.clearLikeSpaces();
+        this.zoneDisable = true;
+        this.scene.isZoneSelectable = true;
+        this.scene.isSpaceSelectable = false;
       }
       if (this.buildFloor.indexOf('all') > -1 || this.buildFloor.indexOf('noKnow') > -1) {
         return;
@@ -238,7 +231,7 @@ export default {
       // 选中当前
       zone.selected = true;
       this.curZoneItem = zone;
-      this.type = 2;
+      this.zoneDisable = false;
       this.view.fitSelectedToView();
     },
     // 父组件调用
@@ -289,6 +282,7 @@ export default {
           })
           this.scene.addSceneMark(newArr)
         }
+        this.scene.isSpaceSelectable = false;
         // 绘制业务空间
         that.getBusinessSpace();
         that.view.fitSceneToView();
@@ -299,12 +293,6 @@ export default {
         }
       })
     },
-    // 清空绘制业务空间
-    clearZoneCanvas() {
-      this.zoneList.map(t => {
-        this.scene.removeItem(t);
-      })
-    },
     // 获取当前分区下的业务空间
     getBusinessSpace() {
       this.canvasLoading = true
@@ -319,7 +307,6 @@ export default {
       if (this.buildFloor.length && this.buildFloor.length > 1) {
         pa.data.Filters = `BuildingId='${this.buildFloor[0]}';FloorId='${this.buildFloor[1]}'`
       }
-      this.clearZoneCanvas();
       queryZone(pa, res => {
         // 所有业务空间
         this.businessSpaceList = res.Content;
@@ -332,14 +319,19 @@ export default {
         })
         // 绘制业务空间
         let tempArr = this.BSPRelaISPList.map((t, i) => {
-          return {
-            RoomLocalName: t.RoomLocalName,
-            OutLine: t.Outline,
-            RoomID: t.RoomID,
-            Color: new SColor(colorArr[i % colorArr.length]),
+          if (t.FloorId == this.buildFloor[1] && t.ObjectType == this.tab.code) {
+            return {
+              RoomLocalName: t.RoomLocalName,
+              OutLine: t.Outline,
+              RoomID: t.RoomID,
+              Color: colorArr[i % colorArr.length],
+            }
+          } else {
+            console.log('internet slow')
+            return undefined;
           }
-        })
-        this.scene.zoneList = [];
+        }).filter(item => item)
+        this.scene.removeAllZone();
         this.scene.addZoneList(tempArr);
         this.scene.click(this, this.canvasClick);
         this.zoneList = this.scene.zoneList;
@@ -366,7 +358,7 @@ export default {
           if (this.type == 3) {
             this.scene.clearSpaceSelection();
           }
-          this.type = 2;
+          this.zoneDisable = false;
           this.curZoneItem = item;
           this.scene.clearZoneSelection();
           item.selected = true;
@@ -379,6 +371,7 @@ export default {
       this.config.isEdit = true;
       this.config.groupSelect = false;
       this.config.divide = true;
+      this.scene.isSpaceSelectable = true;
       // 设置业务空间不可选
       this.scene.isZoneSelectable = false
     },
@@ -418,7 +411,7 @@ export default {
         this.scene.isZoneSelectable = false;
       }
     },
-    // 批量创建业务空间
+    // 根据未关联元空间批量创建业务空间
     groupCreateBSpace() {
       let text = []
       let Spaces = this.allUnRelatISP.map(t => {
@@ -460,7 +453,7 @@ export default {
           });
         });
       } else {
-        this.$message('没有未关联的空间')
+        this.$message('没有未关联的空间')
       }
     },
     // 创建新的业务空间
@@ -476,33 +469,54 @@ export default {
         this.$message.warning('请至少选择一个空间');
       }
     },
-    // 创建新的业务空间-弹窗返回确认创建
+    // 根据图创建新的业务空间-弹窗返回确认创建
     createRoom(val) {
-      let arr = this.scene.getSelectedSpaces();
       let zoneObj = { Outline: [], Height: 0 }, IspaceIdList = [];
-      arr.map(t => {
+      let selectSpaces = this.scene.getSelectedSpaces();
+      selectSpaces.map(t => {
         zoneObj.Outline.push(t.data.OutLine);
-        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
-        console.log(zoneObj.Height)
+        if (this.BIMIDToSID[t.data.SourceId]) {
+          IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        }
         if (t.data.Height && (zoneObj.Height == 0 || t.data.Height < zoneObj.Height)) {
-          zoneObj.Height = t.data.Height;
+          zoneObj.Height = t.data.Height > 100 ? (t.data.Height / 1000).toFixed(2) : t.data.Height;
         }
       })
+      // 如果有划分,求交集
+      if (this.scene.cutItem || this.scene.sceneMark) {
+        zoneObj.Outline = [];
+        let arr = this.scene.getIntersect();
+        arr.map(t => {
+          let temp = t.map(item => {
+            return {
+              X: item.x,
+              Y: -item.y,
+              Z: 0
+            }
+          })
+          zoneObj.Outline.push([temp]);
+        })
+      }
+      if (!zoneObj.Outline.length) {
+        zoneObj.Outline = null;
+      }
       zoneObj.RoomLocalName = val;
       zoneObj.BuildingId = this.buildFloor[0];
       zoneObj.FloorId = this.buildFloor[1];
       this.createSingleBSP(zoneObj, IspaceIdList)
     },
-    // 从未关联平面图的业务空间中选择--按钮返回关联信号
+    // 根据图从未关联平面图的业务空间中选择--按钮返回关联信号
     createFromUnrelated(BSP) {
       BSP.Outline = [];
       BSP.Height = 0;
       let arr = this.scene.getSelectedSpaces(), IspaceIdList = [];
       arr.map(t => {
         BSP.Outline.push(t.data.OutLine);
-        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        if (this.BIMIDToSID[t.data.SourceId]) {
+          IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        }
         if (t.Height && (BSP.Height == 0 || t.Height < BSP.Height)) {
-          BSP.Height = t.Height;
+          BSP.Height = t.Height > 100 ? (t.Height / 1000).toFixed(2) : t.Height;
         }
       })
       this.updateBSPOutline(BSP, IspaceIdList)
@@ -510,41 +524,84 @@ export default {
     // 编辑空间详情
     editeSpaceDetail() {
       let item = this.curZoneItem.data;
+      let query = {
+        RoomID: item.RoomID,
+        zone: this.tab.code,
+        isMyTab: 1,
+        buildFloorSelectd: this.buildFloor
+      }
       this.$router.push({
         path: "/ledger/spaceDetail",
-        query: { RoomID: item.RoomID, zone: this.tab.code, isMyTab: 1 }
+        query: query
       })
     },
     // 重新划分业务空间
     refactorBSP() {
+      this.config.isEdit = true;
+      this.config.groupSelect = false;
+      this.config.divide = true;
       this.type = 4;
-      // 清空选中空间
-      this.scene.clearSpaceSelection();
       // 设置空间可选
       this.scene.isSpaceSelectable = true;
       // 将已关联的设置不可选,并将当前选的隐藏
       this.scene.isZoneSelectable = false;
       this.curZoneItem.visible = false;
+      // 将当前业务空间的每个元素添加到场景中并选中
+      this.scene.addAllLikeSpace(this.curZoneItem.data.OutLine);
     },
     // 重新划分--保存
     saveRefactorBSP() {
-      let arr = this.scene.getSelectedSpaces();
+      let selectSpace = this.scene.getSelectedSpaces();
+      let selectLikeSpace = this.scene.getSelectedLikeSpace();
       //更新业务空间
       let zoneObj = { Outline: [], Height: 0 }, IspaceIdList = [];
-      arr.map(t => {
+      // 空间
+      selectSpace.map(t => {
         zoneObj.Outline.push(t.data.OutLine);
-        IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        if (this.BIMIDToSID[t.data.SourceId]) {
+          IspaceIdList.push(this.BIMIDToSID[t.data.SourceId]);
+        }
         if (t.Height && (zoneObj.Height == 0 || t.Height < zoneObj.Height)) {
-          zoneObj.Height = t.Height;
+          zoneObj.Height = t.Height > 100 ? (t.Height / 1000).toFixed(2) : t.Height;
         }
       })
-      zoneObj.RoomID = this.curZoneItem.data.RoomID;
+      // 类空间
+      selectLikeSpace.map(t => {
+        zoneObj.Outline.push(t.data);
+      })
+      // 如果有划分,求交集
+      if (this.scene.cutItem || this.scene.sceneMark) {
+        zoneObj.Outline = [];
+        let spaceIntersect = this.scene.getIntersect();
+        spaceIntersect.map(t => {
+          let temp = t.map(item => {
+            return {
+              X: item.x,
+              Y: -item.y,
+              Z: 0
+            }
+          })
+          zoneObj.Outline.push([temp]);
+        })
+        let likeSpaceIntersect = this.scene.getLikeIntersect();
+        likeSpaceIntersect.map(t => {
+          let temp = t.map(item => {
+            return {
+              X: item.x,
+              Y: -item.y,
+              Z: 0
+            }
+          })
+          zoneObj.Outline.push([temp]);
+        })
+      }
       if (!zoneObj.Outline.length) {
         zoneObj.Outline = null;
       }
+      zoneObj.RoomID = this.curZoneItem.data.RoomID;
       this.updateBSPOutline(zoneObj, IspaceIdList)
     },
-    // 批量创建所选业务空间
+    // 根据图批量创建所选业务空间
     groupCreateZone() {
       let arr = this.scene.getSelectedSpaces();
       let spaces = arr.map(t => {
@@ -554,7 +611,7 @@ export default {
           Outline: [t.data.OutLine],
           BuildingId: this.buildFloor[0],
           FloorId: this.buildFloor[1],
-          Height: t.data.Height || 0
+          Height: t.data.Height > 100 ? (t.data.Height / 1000).toFixed(2) : t.data.Height || 0
         }
       })
       if (spaces.length) {
@@ -577,20 +634,31 @@ export default {
     },
     // 批量更新业务空间和元空间的关系
     groupCreRelaZoneAndISp(Spaces) {
-      let param = {
-        data: {
-          Content: Spaces
-        },
-        type: this.tab.code
-      }
-      groupCreRelaZoneAndISp(param, res => {
+      Spaces = Spaces.filter(item => item.IspaceId);
+      if (Spaces.length) {
+        let param = {
+          data: {
+            Content: Spaces
+          },
+          type: this.tab.code
+        }
+        groupCreRelaZoneAndISp(param, res => {
+          this.$message.success('创建成功')
+          this.canvasLoading = false;
+          this.init(2)
+        })
+      } else {
         this.$message.success('创建成功')
         this.canvasLoading = false;
         this.init(2)
-      })
+      }
     },
     // 批量创建
     groupCreateBSP(spaces) {
+      spaces = spaces.map(t => {
+        t.BIMLocation = this.getAverageVal(t.Outline);
+        return t;
+      })
       let pa = {
         zone: this.tab.code,
         data: {
@@ -611,6 +679,7 @@ export default {
     },
     // 单个创建
     createSingleBSP(space, IspaceIdList) {
+      space.BIMLocation = space.Outline ? this.getAverageVal(space.Outline) : null;
       let pa = {
         zone: this.tab.code,
         data: {
@@ -623,11 +692,12 @@ export default {
     },
     // 更新业务空间区域
     updateBSPOutline(zoneObj, IspaceIdList) {
+      zoneObj.BIMLocation = zoneObj.Outline ? this.getAverageVal(zoneObj.Outline) : null;
       let pa = {
         zone: this.tab.code,
         data: {
           Content: [zoneObj],
-          Projection: ['Outline']
+          Projection: ['Outline', 'BIMLocation']
         },
       }
       updateZone(pa, res => {
@@ -646,13 +716,31 @@ export default {
         this.num = res.Count;
       })
     },
+    // 计算平均值 作为业务空间BIMLocation
+    getAverageVal(Outline) {
+      let X = 0, Y = 0, Z = 0, len = 0;
+      Outline.map(t => {
+        if (t[0]) {
+          t[0].map(item => {
+            X += item.X;
+            Y += item.Y;
+            Z += item.Z;
+          })
+          len += t[0].length
+        }
+      })
+      X = (X / len).toFixed(2);
+      Y = (Y / len).toFixed(2);
+      Z = (Z / len).toFixed(2);
+      return `${X},${Y},${Z}`
+    },
     // canvas 获取焦点
     focus() {
       document.getElementById(`floorCanvas`).focus()
     },
     // 清除canvas
     clearGraphy() {
-      if (this.view && this.view.scene) {
+      if (this.view) {
         this.view.scene = null;
         return
       }
@@ -685,11 +773,11 @@ export default {
     },
     // 切割划分
     divide() {
-      this.scene.isMarking = true;
+      this.scene.isCutting = true;
     },
     // 清除切割划分
     clearDivide() {
-      this.scene.clearSceneMark()
+      this.scene.clearCut();
     },
     // 撤销
     undo() {
@@ -727,7 +815,23 @@ export default {
           this.$refs.canvasFun.sliderVal = n * 10 / this.view.minScale;
         }
       }
-    }
+    },
+    "scene.isRectSelection": {
+      handler(n) {
+        if (!n) {
+          this.$refs.canvasFun.active = '';
+        }
+      }
+    },
+    "scene.isCutting": {
+      handler(n) {
+        if (!n) {
+          this.$refs.canvasFun.active = '';
+          this.$refs.canvasFun.isSwitch = false;
+          this.scene.isAbsorbing = false;
+        }
+      }
+    },
   }
 }
 </script>
@@ -753,7 +857,8 @@ export default {
       width: 320px;
       margin-right: 10px;
     }
-    .button-group button {
+    .button-group button,
+    .button-group .el-dropdown {
       display: block;
       float: left;
     }
@@ -783,4 +888,4 @@ export default {
     z-index: 999;
   }
 }
-</style>
+</style>

+ 1 - 1
src/components/business_space/newGraphy/unRelateBSP.vue

@@ -123,7 +123,7 @@ export default {
           t.Floor.unshift({ BuildID: 'all', BuildLocalName: '全部' }, { BuildID: 'isNull', BuildLocalName: '未明确楼层' })
           return t;
         })
-        this.options.unshift({ BuildID: 'all', BuildLocalName: '全部' }, { BuildID: 'isNull', BuildLocalName: '未明确楼层' })
+        this.options.unshift({ BuildID: 'all', BuildLocalName: '全部' }, { BuildID: 'isNull', BuildLocalName: '未明确建筑' })
       })
     },
     // 查询未关联平面图的业务空间(项目下+当前分区)

+ 9 - 8
src/components/business_space/newTables/eqToSpaceTable.vue

@@ -1,13 +1,13 @@
 <template>
   <div id="eqInSp">
-    <el-row v-show="hidden">
+    <el-row v-if="hidden">
       <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" :style="heightData">
-      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" :header-cell-style="headerStyle"  v-loading="loading">
         <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
           <template slot-scope="scope">
             <div>
@@ -73,7 +73,7 @@ export default {
         EquipmentFor: '服务于空间的设备',
       },
       hidden: true,
-      heightData: "height:calc(100% - 50px)"
+      loading: false
     };
   },
   props: {
@@ -131,6 +131,7 @@ export default {
     },
     // 获取列表数据
     getTableData() {
+      this.loading = true;
       let pa = {
         data: {
           Filters: `RoomID='${this.params.RoomID}'`,
@@ -144,6 +145,7 @@ export default {
         zone: this.params.zone
       }
       queryZone(pa, res => {
+        this.loading = false;
         this.tableData = res.Content[0][this.type] || []
         this.tableData.map(t => {
           t.SpaceId = res.Content[0].RoomID
@@ -153,13 +155,11 @@ export default {
     },
     // 添加设备
     add() {
-      this.$refs.addEqDialog.floor = [this.params.BuildingId, this.params.FloorId];
+      this.$refs.addEqDialog.floor = this.params.buildFloorSelectd;
       this.$refs.addEqDialog.showDialog()
     },
     changeContentStyle(){
-      // 在辅助屏不显示添加按钮,动态设置高度
-      this.$route.query.isMyTab?this.hidden = true:this.hidden = false;
-      this.heightData = "height:750px";
+      this.$route.name == "spaceLedger"?this.hidden = false:this.hidden = true;
     }
   },
   watch: {
@@ -174,6 +174,7 @@ export default {
   height: 100%;
   .table-box {
     margin-top: 10px;
+    height: calc(100% - 50px);
   }
 }
 </style>

+ 8 - 7
src/components/business_space/newTables/syInSpaceTable.vue

@@ -6,7 +6,7 @@
         <el-button>按空间计算</el-button>
       </el-tooltip>
     </el-row>
-    <div class="table-box" :style="heightData">
+    <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">
@@ -63,7 +63,7 @@ export default {
         generalSystem: '空间内的系统',
       },
       hidden: true,
-      heightData: "height:calc(100% - 50px)"
+      loading: false
     };
   },
   props: {
@@ -72,7 +72,7 @@ export default {
   },
   created() {
     this.getTableData();
-     this.changeContentStyle();
+    this.changeContentStyle();
   },
   methods: {
     // 删除关系
@@ -92,7 +92,7 @@ export default {
       })
     },
     // 删除关系
-    deleteSyInSpace(pa){
+    deleteSyInSpace(pa) {
       syInSpaceDelete(pa, res => {
         this.$message.success('删除成功');
         this.getTableData();
@@ -100,6 +100,7 @@ export default {
     },
     // 获取列表数据
     getTableData() {
+      this.loading = true;
       let pa = {
         data: {
           Cascade: [{ Name: "generalSystem" }],
@@ -108,6 +109,7 @@ export default {
         zone: this.params.zone
       }
       queryZone(pa, res => {
+        this.loading = false;
         this.tableData = res.Content[0].GeneralSystem || [];
         this.tableData.map(t => {
           t.SpaceId = res.Content[0].RoomID;
@@ -119,10 +121,9 @@ export default {
     add() {
       this.$refs.addSyDialog.showDialog()
     },
-    changeContentStyle(){
+    changeContentStyle() {
       // 在辅助屏不显示添加按钮,动态设置高度
-      this.$route.query.isMyTab?this.hidden = true:this.hidden = false;
-      this.heightData = "height:750px";
+      this.$route.name == "spaceLedger" ? this.hidden = false : this.hidden = true;
     }
   },
   watch: {

+ 1 - 1
src/components/common/handsontable.vue

@@ -166,7 +166,7 @@
                     sortIndicator: true, //添加排序
                     renderAllRows: true,
                     autoColumnSize: true,
-                    observeChanges: false, //启用observeChanges插件
+                    // observeChanges: false, //启用observeChanges插件
                     language: "zh-CN",
                     manualColumnResize: true,
                     manualColumnMove: true,

+ 49 - 172
src/components/config_point/dictionaryCascader.vue

@@ -1,207 +1,67 @@
 <template>
   <div>
     <el-form ref="form" :rules='rules' :model="form">
-      <el-form-item prop="dict">
-        <el-cascader style='width: 100%;' :options='options' v-model='form.dict' @active-item-change='handleChange' :props='props' filterable
-          @change="changeSelect" ref="dictCas"></el-cascader>
+      <el-form-item prop="dict" class="cascader-container">
+        <el-cascader :options='options' v-model='form.dict' :props='props' filterable @change="changeSelect" ref="dictCas">
+        </el-cascader>
+        <el-tooltip class="item" effect="dark" :content="`于${cacheTime}缓存,点击重新缓存`" placement="top">
+          <el-button icon="el-icon-refresh" class="update-button" @click="getDictionary"></el-button>
+        </el-tooltip>
       </el-form-item>
     </el-form>
   </div>
 </template>
 <script>
-import {
-  getDataDictionary,//查询信息点
-  queryPhysicsAllType,//查询所有部件类型
-  queryDictionaryHead,//查询所有空间类型
-
-} from "@/api/scan/request"
-import { mapGetters, mapActions } from "vuex";
+import { mapGetters, mapMutations, mapActions } from "vuex";
 import tools from "@/utils/scan/tools";
 export default {
   data() {
     return {
-      options: [
-        {
-          Code: 'Pj',
-          Name: '项目',
-          children: []
-        }, {
-          Code: 'Bd',
-          Name: '建筑',
-          children: []
-        }, {
-          Code: 'Fl',
-          Name: '楼层',
-          children: []
-        }, {
-          Code: 'Eq',
-          Name: '设备',
-          children: []
-        }, {
-          Code: 'Ec',
-          Name: '部件',
-          children: []
-        }, {
-          Code: 'Sy',
-          Name: '系统',
-          children: []
-        }, {
-          Code: 'Sp',
-          Name: '空间',
-          children: []
-        }, {
-          Code: 'VOTn',
-          Name: '租户',
-          children: []
-        },
-      ],
+      options: [],
       form: {
         dict: [],
       },
       props: {
-        value: 'Code',
-        label: 'Name',
-        children: 'children'
+        value: 'InfoPointCode',
+        label: 'InfoPointName',
+        children: 'Content'
       },
       rules: {
         dict: [{ required: true, message: '请选择对应数据字典', trigger: 'blur' }]
       },
-      typeRelation: {
-        Pj: 'Project',
-        Bd: 'Building',
-        Fl: 'Floor',
-        VOTn: 'Tenant',
-      },
-      timer: null
     }
   },
+  computed: {
+    ...mapGetters("project", ["dictionary", "cacheTime"]),
+  },
   created() {
-    this.getAllData()
+    if (!this.dictionary.length) {
+      this.getDictionary().then(res => {
+        this.getDictSuc(res.Content)
+      })
+    } else {
+      this.getDictSuc(this.dictionary);
+    }
   },
   methods: {
-    //选择
-    handleChange(val) {
-      let type = val[0];
-      let singleStr = "Pj-Bd-Fl-VOTn";
-      console.log(val)
-      if (type == "Eq" && val.length == 2) {
-        this.getDataPoint(val[1])
-      } else if (type == "Ec" && val.length == 2) {
-        this.getDataPoint(val[1])
-      } else if (type == "Sy" && val.length == 3) {
-        this.getDataPoint(val[2])
-      } else if (type == "Sp" && val.length == 2) {
-        this.getDataPoint(val[1])
-      } else if (singleStr.indexOf(type) > -1) {
-        this.hasChildren(type) && this.getDataPoint(type)
-      }
-    },
+    ...mapActions('project', ['getDictionary']),
     //获取物理世界所有设备类型
-    getAllData() {
-      queryPhysicsAllType('Equipment', res => {
-        this.options[3].children = this.formatOptions(res.Content)
-      })
-      queryPhysicsAllType('Component', res => {
-        this.options[4].children = this.formatOptions(res.Content)
-      })
-      queryPhysicsAllType('Major-System', res => {
-        let data = JSON.parse(JSON.stringify(res.Content).replace(/ListClassDef/g, 'children'));
-        this.options[5].children = this.formatOptions(data)
-      })
-      let param1 = {
-        Distinct: true,
-        Filters: "ParentId='Space'"
-      }
-      queryDictionaryHead(param1, res => {
-        this.options[6].children = this.formatOptions(res.Content)
-      })
-    },
-    //格式化options数据
-    formatOptions(arr) {
-      return arr.map(item => {
-        return {
-          Code: item.Code,
-          Name: item.Name,
-          children: item.children && item.children.length ? this.formatOptions(item.children) : []
-        }
-      })
-    },
-    //请求信息点
-    getDataPoint(type) {
-      let param = {
-        data: {
-          Filters: "InputMode='M' or InputMode='L'",
-          PageNumber: 1,
-          PageSize: 500,
-          Orders: 'InfoPointName asc'
-        },
-        type: this.typeRelation[type] || type
-      }
-      getDataDictionary(param, res => {
-        let tempArr = res.Content.map(item => {
-          return {
-            Code: item.InfoPointCode,
-            Name: item.InfoPointName
-          }
-        })
-        this.pointDataSource = {}
-        res.Content.map(item => {
-          let code = item.InfoPointCode
-          this.pointDataSource[code] = item
-        })
-        this.timer = setTimeout(() => {
-          if (this.interval()) {
-            this.pushPoints(this.options, tempArr, type);
-            this.changeSelect(this.form.dict);
-            clearTimeout(this.timer);
-            this.timer = null;
-            return
-          }
-          this.timer()
-        }, 100);
-      })
-    },
-    interval() {
-      for (let i = 0; i < this.options.length; i++) {
-        if (this.options[i].children.length > 0) {
-          return true;
-        }
-      }
-      return false;
-    },
-    //根据返回数据拼接options
-    pushPoints(options, arr, Code) {
-      options.map(option => {
-        if (option.Code == Code) {
-          option.children = arr;
-        } else {
-          if (option.children) {
-            this.pushPoints(option.children, arr, Code)
-          }
-        }
-      })
+    getDictSuc(list) {
+      this.options = list;
+      this.changeSelect(this.form.dict);
     },
     changeSelect(val) {
-      if (this.$refs.dictCas.getCheckedNodes()[0]) {
-        let labels = this.$refs.dictCas.getCheckedNodes()[0].pathLabels
-        this.$emit('change', { val: val, labels: labels })
-      }
-    },
-    //减少请求次数
-    hasChildren(Code) {
-      let flag = true;
-      this.options.map(option => {
-        if (option.Code == Code && option.children.length) {
-          flag = false;
+      setTimeout(() => {
+        if (this.$refs.dictCas.getCheckedNodes()[0]) {
+          let labels = this.$refs.dictCas.getCheckedNodes()[0].pathLabels;
+          let data = this.$refs.dictCas.getCheckedNodes()[0].data;
+          this.$emit('change', { val: val, labels: labels, data: data })
         }
-      })
-      return flag;
+      }, 500)
     },
     //设置值
     setCascaderVal(value) {
       this.form.dict = tools.deepCopy(value)
-      value.splice(value.length - 1, 1)
-      this.handleChange(value)
     },
     //校验是否选择
     validate(cb) {
@@ -217,4 +77,21 @@ export default {
 }
 </script>
 <style lang="less" scoped>
-</style>
+.cascader-container {
+  /deep/ .el-cascader {
+    width: 89%;
+    display: block;
+    float: left;
+    .el-input .el-input__inner {
+      border-radius: 4px 0 0 4px;
+      vertical-align: bottom;
+    }
+  }
+  .update-button {
+    display: block;
+    float: left;
+    border-left: 0;
+    border-radius: 0 4px 4px 0;
+  }
+}
+</style>

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

@@ -583,11 +583,11 @@ export default {
       return str
     },
     //对应数据字典变化
-    changeDictionaryCas({ val, labels }) {
+    changeDictionaryCas({ val, labels, data }) {
       this.dictionaryData = val;
       this.dictionaryNames = labels
-      this.infoDict = this.$refs.dictionaryCas.pointDataSource
-      this.unitObj = this.infoDict[val[val.length - 1]]
+      // this.infoDict = this.$refs.dictionaryCas.pointDataSource
+      this.unitObj = data
       this.InfomationPoint = this.unitObj.InfoPointName || ''
       this.ValueDescription = this.delDataSource(this.unitObj.DataSource)
     }

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

@@ -599,11 +599,11 @@ export default {
       return str
     },
     //对应数据字典变化
-    changeDictionaryCas({ val, labels }) {
+    changeDictionaryCas({ val, labels, data }) {
       this.dictionaryData = val;
       this.dictionaryNames = labels
-      this.infoDict = this.$refs.dictionaryCas.pointDataSource
-      this.unitObj = this.infoDict[val[val.length - 1]]
+      // this.infoDict = this.$refs.dictionaryCas.pointDataSource
+      this.unitObj = data
       this.InfomationPoint = this.unitObj.InfoPointName || ''
     },
     //分页发生更改

+ 1 - 0
src/components/config_point/step3_point/steps3_main.vue

@@ -145,6 +145,7 @@
                                     // KeyEquipmentParameter: '温度',
                                     // KeyEquipmentType: '冷机'
                                 },
+                                Orders: 'EquipmentMark asc',
                                 PageNumber: this.pages.currentPage,
                                 PageSize: this.pages.size
                             },

+ 135 - 0
src/components/data_admin/zoneInput.vue

@@ -0,0 +1,135 @@
+<template>
+  <div id="zoneinput">
+    <el-form label-position="left" :label-width="labelWidth" :model="form">
+      <div v-for="(titem, tkey) in inputTypeList" :key="tkey">
+        <h4>{{ tkey }}</h4>
+        <el-form-item v-for="(item, key) in titem" :key="key" :label="item.InfoPointName" class="input-item">
+          <el-input v-model="item.inputValue" v-if="item.InputMode == 'A1'|| item.InputMode == 'A2'" type="number">
+            <template slot="append" v-if="item.Unit">{{item.Unit}}</template>
+          </el-input>
+          <el-input v-model="item.inputValue" v-else-if="item.InputMode == 'B1' || item.InputMode == 'L' || item.InputMode == 'M'"></el-input>
+          <el-select v-model="item.inputValue" v-else-if="item.InputMode == 'D1'" placeholder="请选择">
+            <el-option v-for="(soption,skey) in item.options" :key="skey" :label="soption.Name" :value="soption.Code">
+            </el-option>
+          </el-select>
+          <el-cascader v-model="item.inputValue" v-else-if="item.InputMode == 'D1L'" placeholder="请选择"
+            :props="item.props" :options="item.options" filterable :show-all-levels="false"></el-cascader>
+          <el-input v-model="item.inputValue" v-else></el-input>
+        </el-form-item>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      form: {},
+      inputTypeList: {},//输入框表头种类
+      inputData: [],//所有输入框
+    }
+  },
+  props: {
+    labelWidth: {
+      default: "130px",
+      type: String
+    }
+  },
+  created() {
+  },
+  methods: {
+    //初始化
+    init(val) {
+      this.inputTypeList = {};
+      this.inputData = [];
+      this.inputData = val.concat()
+      this.filterInput();
+      this.inputGroup();
+    },
+    //数据过滤
+    filterInput() {
+      this.inputData = this.inputData.filter(item => {
+        return item.Editable == true && item.Visible == true && item.FirstName && item.InfoPointCode;
+      })
+      let numbersInput = ['A1', 'A2'];
+      let stringInput = ['B1', 'L', 'M'];
+      let arrayInput = ['D1'];
+      let cascaderInput = ['D1L'];
+      this.inputData.map(item => {
+        if (numbersInput.indexOf(item.InputMode) != -1) {
+          item.inputValue = null;
+        }
+        else if (stringInput.indexOf(item.InputMode) != -1) {
+          item.inputValue = '';
+        }
+        else if (arrayInput.indexOf(item.InputMode) != -1) {
+          let options = JSON.parse(item.DataSource)
+          item.inputValue = '';
+          item.options = options;
+        }
+        else if(cascaderInput.indexOf(item.InputMode) != -1){
+          let options = JSON.parse(item.DataSource);
+          if (options[0] && options[0].Content) {
+            item.props = {
+              value: 'Code',
+              label: 'Name',
+              children: 'Content'
+            }
+          }
+          item.options = options;
+          item.inputValue = [];
+        }
+        else {
+          item.inputValue = '';
+        }
+      });
+
+    },
+    //数据分组
+    inputGroup() {
+      this.inputData.map(item => {
+        if (!this.inputTypeList[item.FirstName]) {
+          this.inputTypeList[item.FirstName] = [];
+        }
+        this.inputTypeList[item.FirstName].push(item)
+      })
+      for (let key in this.inputTypeList) {
+        if (this.inputTypeList[key] instanceof Array) {
+          this.inputTypeList[key].sort((item1, item2) => { return item1.Sort < item2.Sort });
+        }
+      }
+    },
+    //父组件获取form
+    getFormData() {
+      let f = {}
+      for (let key in this.inputTypeList) {
+        this.inputTypeList[key].map(item => {
+          if (item.inputValue != '' && item.inputValue != null) {
+            if (item.inputValue instanceof Array) {
+              f[item.InfoPointCode] = item.inputValue.pop();
+            }
+            else {
+              f[item.InfoPointCode] = item.inputValue;
+            }
+          }
+        })
+      }
+      return f;
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.input-item {
+  display: inline-block;
+  position: relative;
+  margin-right: 10px;
+}
+#zoneinput {
+  /deep/ .el-form-item__content {
+    width: 220px;
+  }
+}
+</style>

+ 1 - 1
src/components/dialogHanson/addDevice.vue

@@ -344,7 +344,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"

+ 1 - 1
src/components/dialogs/addDialog/businessDialog.vue

@@ -478,7 +478,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"

+ 1 - 1
src/components/dialogs/addDialog/dialogAssets.vue

@@ -502,7 +502,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该资产"

+ 2 - 2
src/components/dialogs/addDialog/dialogDevice.vue

@@ -623,7 +623,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"
@@ -972,7 +972,7 @@ export default {
 </style>
 <style lang="">
     .confirmButtonClass {
-    width: 180px; 
+    width: 180px;
 }
 .cancelButtonClass {
     width: 180px;

+ 1 - 1
src/components/dialogs/addDialog/dialogSystem.vue

@@ -556,7 +556,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该资产"

+ 539 - 0
src/components/dialogs/list/batchDialog.vue

@@ -0,0 +1,539 @@
+<template>
+    <el-dialog
+        title="批量维护信息点"
+        :visible.sync="batchDialog"
+        class="batchContainer"
+    >
+        <el-steps
+            :active="active"
+            align-center
+        >
+            <el-step
+                @click.native="active = 0"
+                description="填写需维护的信息点"
+            />
+            <el-step
+                @click.native="active = 1"
+                description="选择批量维护的对象实例"
+            />
+        </el-steps>
+        <hr>
+        <div v-show="active === 0">
+            <section>
+                <p class="text-message">维护只有单值的信息点</p>
+                <span class="small">请选择需维护的信息点</span>
+                <el-checkbox
+                    :indeterminate="isIndeterminate"
+                    v-model="checkAll"
+                    @change="handleCheckChange"
+                >
+                    全部选择
+                </el-checkbox>
+
+                <div style="margin: 15px "></div>
+                <el-checkbox-group
+                    v-model="checkedCities"
+                    @change="handleCheckedCitiesChange"
+                >
+                    <el-checkbox
+                        v-for="(city,index) in newFirm"
+                        :label="city"
+                        :key="index"
+                    >
+                        <span @click="fourVendors(city.code)"> {{city.name}}:</span>
+                        <span>{{city.rname}}</span>
+                    </el-checkbox>
+                </el-checkbox-group>
+            </section>
+            <!--维护有多个值的信息-->
+            <section>
+                <p class="text-message">维护有多个值的信息点</p>
+                <span class="small">选择值的更新方式</span>
+                <el-radio-group
+                    v-model="radio"
+                    @change="maintenance"
+                >
+                    <el-radio :label="1">以增量方式维护</el-radio>
+                    <el-radio :label="2">以覆盖方式维护</el-radio>
+                </el-radio-group>
+                <div style="margin: 15px "></div>
+                <div class="checkbox">
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.archive"
+                            @change="multiple('archive')"
+                        > <!--设备文档-->
+                            {{information.archive.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.archive.Archive">{{item | filterImgName}}</span>
+                    </p>
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.checkReport"
+                            @change="multiple('checkReport')"
+                        ><!--安装质检报告-->
+                            {{information.checkReport.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.checkReport.CheckReport">{{item | filterImgName}}</span>
+
+                    </p>
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.drawing"
+                            @change="multiple('drawing')"
+                        ><!--设备图纸-->
+                            {{information.drawing.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.drawing.Drawing">{{item.key | filterImgName}}</span>
+
+                    </p>
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.installDrawing"
+                            @change="multiple('installDrawing')"
+                        ><!--安装图纸-->
+                            {{information.installDrawing.name}}
+                        </el-checkbox>
+                        <span
+                            v-for="item in information.installDrawing.InstallDrawing">{{item.key | filterImgName}}</span>
+                    </p>
+
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.installPic"
+                            @change="multiple('installPic')"
+                        ><!--安装照片-->
+                            {{information.installPic.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.installPic.InstallPic">{{item.key | filterImgName}}</span>
+                    </p>
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.insuranceFile"
+                            @change="multiple('insuranceFile')"
+                        ><!--保险文件-->
+                            {{information.insuranceFile.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.insuranceFile.InsuranceFile">{{item | filterImgName}}</span>
+
+                    </p>
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.pic"
+                            @change="multiple('pic')"
+                        ><!--设备照片-->
+                            {{information.pic.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.pic.Pic">{{item.key | filterImgName}}</span>
+                    </p>
+                    <p>
+                        <el-checkbox
+                            v-model="videoModel.nameplate"
+                            @change="multiple('nameplate')"><!--设备铭牌照片-->
+                            {{information.nameplate.name}}
+                        </el-checkbox>
+                        <span v-for="item in information.nameplate.Nameplate">{{item.key | filterImgName}}</span>
+                    </p>
+                </div>
+            </section>
+            <el-button
+                style="margin-top: 12px"
+                @click="next"
+            >下一步
+            </el-button>
+        </div>
+        <div
+            v-show="active === 1"
+            class="all-message"
+        >
+            <el-table
+                ref="multipleTable"
+                :data="tableData"
+                tooltip-effect="dark"
+                style="width:100%;margin-bottom: 10px"
+                @selection-change="handleSelectionChange"
+            >
+                <el-table-column
+                    type="selection"
+                    width="55"
+                />
+                <el-table-column
+                    label="设备本地名称"
+                    width=""
+                >
+                    <template slot-scope="scope">{{scope.row.EquipLocalName}}</template>
+                </el-table-column>
+                <el-table-column
+                    prop="EquipLocalID"
+                    label="设备本地编码"
+                    width="120"
+                />
+                <el-table-column
+                    prop="build"
+                    label="所属建筑楼层"
+                    show-overflow-tooltip
+                />
+            </el-table>
+            <my-pagination
+                @change="getAllData"
+                :page="page"
+            ></my-pagination>
+            <el-button
+                type="primary"
+                @click="maintenanceSelect"
+            >维护已选
+            </el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+    import myPagination from "@/components/ledger/lib/myPagination"
+
+    export default {
+        name: "batchDialog",
+        props: ['firmName', 'allObject', 'page','information'],
+        components: {myPagination},
+        data() {
+            return {
+                batchDialog: false,//dialog
+                active: 0,//进度条
+                checkAll: false,//全选
+                isIndeterminate: true,
+                checkedCities: [],//选择的项,单项
+                firm: [
+                    {
+                    name: "品牌型号",
+                    code: "DPManufacturerID",
+                    num: 2,
+                }, {
+                    name: "供应商信息",
+                    code: "DPSupplierID",
+                    num: 8
+                }, {
+                    name: "维修商信息",
+                    code: "DPMaintainerID",
+                    num: 35
+                }, {
+                    name: "保险公司信息",
+                    code: "DPInsurerID",
+                    num: 42
+                    }
+                ],
+                radio: 1, //1增加,2覆盖
+                checkedFile: [],//多项
+                multipleSelection: [],//checkbox选择的对象数组
+                filterList: [],//过滤单项选择的值
+                deviceList: [],//过滤全选数据
+                onlySelect: [],//检测是否有勾选单值信息
+                videoModel: {
+                    archive: false,
+                    checkReport: false,
+                    drawing: false,
+                    installDrawing: false,
+                    insuranceFile: false,
+                    installPic: false,
+                    nameplate: false,
+                    pic: false
+                }
+            }
+        },
+        watch:{
+          information() {
+              return this.information
+          }
+        },
+        computed: {
+            newFirm() {
+                this.firm.map(item => {
+                    if (item.num === this.firmName.num) {
+                        item.rname = this.firmName.name
+                        item.info = this.firmName
+                    }
+                    return item
+                })
+                return this.firm
+            },
+            tableData() {
+                this.allObject.map(item => {
+                    let build = ''
+                    if (item.Building && item.Floor) {
+                        build = item.Building.BuildLocalName + ' - ' + item.Floor.FloorLocalName
+                    } else if (item.Building) {
+                        build = item.Building.BuildLocalName
+                    } else if (item.Floor) {
+                        build = item.Floor.FloorLocalName
+                    } else {
+                        build = '-'
+                    }
+                    item.build = build
+                    return item
+                })
+                return this.allObject
+            },
+        },
+        filters: {
+            filterImgName(value) {
+                if (value.length > 16) {
+                    return value.substring(0, 12) + '...'
+                } else {
+                    return value
+                }
+            }
+        },
+        methods: {
+            next() { //下一步按钮
+                // if (this.active++ > 1) this.active = 0
+                this.deviceList = this.firm.filter(item => item.info)
+                if (!this.onlySelect.length) { //对单项全选进行过滤
+                    this.$message({
+                        message: '还没有选择单值信息哦',
+                        type: 'warning'
+                    });
+                    return false
+                }
+                if (!this.deviceList.length) { //对单项全选进行过滤
+                    this.$message({
+                        message: '单值信息没有填写哦',
+                        type: 'warning'
+                    });
+                    return false
+                }
+                if (this.checkAll) {    // 如果单项全选
+                    if (this.deviceList.length < 4) { //对单项全选进行过滤
+                        this.$message({
+                            message: '单值的信息点存在未填写',
+                            type: 'warning'
+                        });
+                        return false
+                    } else {
+                        this.active++
+                    }
+                } else {
+                    this.active++
+                }
+            },
+            handleCheckChange(val) { //全选
+                this.checkedCities = val ? this.firm : []
+                this.isIndeterminate = false
+
+            },
+            handleCheckedCitiesChange(value) { //维护单项触发
+                this.onlySelect = value
+                this.filterList = value.filter(item => item.info)
+                let checkCount = value.length
+                this.checkAll = checkCount === this.firm.length
+                this.isIndeterminate = checkCount > 0 && checkCount < this.firm.length
+            },
+            handleCheckedFileChange(value) { //维护多项触发
+            },
+            fourVendors(code) {
+                this.$emit('code', code)
+            },
+            //    选择维护方式
+            maintenance(val) {
+            },
+
+            maintenanceSelect() { //维护已选
+                if (!this.multipleSelection.length) {
+                    this.$message({
+                        message: '还没有选择实例哦',
+                        type: 'warning'
+                    });
+                    return false
+                }
+                let arr = []
+                // DPSupplierID 供应商 DPManufacturerID 生产商 DPBrandID 品牌
+                // DPSpecificationID 型号 DPInsurerID 保险商 DPMaintainerID 维修商
+                this.multipleSelection.forEach(item => {
+                    let EquipID = item.EquipID
+                    arr.push({EquipID})
+                })
+                let Id = {}
+                let single = {
+                    EquipManufactor: {
+                        // Manufacturer: '', //生产商
+                        // Brand: '',//品牌
+                        // Specification: '',//型号
+                    },
+                    SupplyPurchase: { //供应商
+                        // SupplierWeb: '',
+                        // Supplier: '',
+                        // PurchasePrice: ''
+                    },
+                    OperationMainte: { //维修商
+                        // Maintainer: '',
+                    },
+                    InsuranceDoc: {
+                        // Insurer: '',
+                        // InsurerWeb: '',
+                        InsuranceFile: this.information.insuranceFile.InsuranceFile ? this.information.insuranceFile.InsuranceFile : null
+                    }
+                };
+                // this.deviceList 单选数组,取到需要数据
+                // 过滤数组,取对象
+                this.deviceList.filter(item => item.num === 2).forEach(i => { //型号
+                    let {venderName, brandName, Specification, venderId, brandId, specificationId} = i.info
+                    single.EquipManufactor.Manufacturer = venderName
+                    Id.DPManufacturerID = venderId
+                    single.EquipManufactor.Brand = brandName
+                    Id.DPBrandID = brandId
+                    single.EquipManufactor.Specification = Specification
+                    Id.DPSpecificationID = specificationId
+                })
+                this.deviceList.filter(item => item.num === 8).forEach(i => {  //供应商8
+                    let {website, name, venderId} = i.info
+                    single.SupplyPurchase.SupplierWeb = website
+                    single.SupplyPurchase.Supplier = name
+                    Id.DPSupplierID = venderId
+                })
+                this.deviceList.filter(item => item.num === 35).forEach(i => {  //维修商
+                    let {name, venderId} = i.info
+                    single.OperationMainte.Maintainer = name
+                    Id.DPMaintainerID = venderId
+                })
+                this.deviceList.filter(item => item.num === 42).forEach(i => {  //保险
+                    let {website, name, venderId} = i.info
+                    single.InsuranceDoc.Insurer = name
+                    single.InsuranceDoc.InsurerWeb = website
+                    Id.DPInsurerID = venderId
+                })
+                // this.information 多选信息
+                let {archive, checkReport, drawing, installDrawing, installPic, insuranceFile, nameplate, pic} = this.information
+                let multiple = {
+                    InsuranceDoc: {
+                        InsuranceFile: insuranceFile.InsuranceFile ? insuranceFile.InsuranceFile : null
+                    },
+                    PhotoDoc: {
+                        Archive: archive.Archive ? archive.Archive : null,
+                        Drawing: drawing.Drawing ? drawing.Drawing : null,
+                        Nameplate: nameplate.Nameplate ? nameplate.Nameplate : null,
+                        Pic: pic.Pic ? pic.Pic : null
+                    },
+                    Siteinstall: {
+                        InstallPic: installPic.InstallPic ? installPic.InstallPic : null,
+                        InstallDrawing: installDrawing.InstallDrawing ? installDrawing.InstallDrawing : null,
+                        CheckReport: checkReport.CheckReport ? checkReport.CheckReport : null
+                    }
+                }
+                let LedgerParam = {}
+                if (this.radio === 1) { //组装数据,根据是覆盖该是增量,1是增量
+                    //    1:单选数据
+                    let arr1 = this.deepCopy(arr).map(item => ({
+                        ...Id,
+                        ...item,
+                        LedgerParam: {...single}
+                    }))
+                    //    2:多选数据
+                    let arr2 = this.deepCopy(arr).map(item => ({
+                        ...Id,
+                        ...item,
+                        LedgerParam: {...multiple}
+                    }))
+                    this.$emit('upDataDevice', 1, arr1, arr2)
+
+                }
+                if (this.radio === 2) {
+
+                    let {InsuranceDoc, ...multiples} = multiple
+                    LedgerParam = {
+                        ...single,
+                        ...multiples
+
+                    };
+                    let arr3 = this.deepCopy(arr).map(item => ({
+                        ...Id,
+                        ...item,
+                        LedgerParam: {...LedgerParam}
+                    }))
+                    this.$emit('upDataDevice', 2, arr3)
+                }
+                this.closeDialog()
+            },
+            closeDialog() {  //关闭弹窗,返回初始状态
+                this.batchDialog = false
+                this.active = 0
+                // this.checkedCities = []//清空单项的checkbox
+                // this.deviceList = [] //清空单选数组内容
+                // this.radio = 1 //返回到默认增量
+                // this.multipleSelection = [] //清空实例内容
+
+            },
+            handleSelectionChange(val) {
+                this.multipleSelection = val
+            },
+            getAllData() {
+                this.$emit('getAllData')
+            },
+            multiple(val) {
+                this.$emit('multiple',val)
+            },
+
+            deepCopy(obj) {
+                return JSON.parse(JSON.stringify(obj))
+            }
+        }
+    }
+</script>
+
+<style scoped lang="less">
+    .batchContainer {
+        /deep/ .el-step__description {
+            margin: 2% 0;
+        }
+        .el-checkbox-group {
+            display: flex;
+            justify-content: space-between;
+            flex-direction: row;
+            flex-wrap: wrap;
+
+            .el-checkbox {
+                width: 43%;
+            }
+
+            .el-checkbox:last-of-type {
+                margin-right: 30px;
+            }
+        }
+
+        .checkbox {
+            display: flex;
+            justify-content: space-between;
+            flex-direction: row;
+            flex-wrap: wrap;
+
+            p {
+                width: 50%;
+            }
+
+            .el-checkbox:last-of-type {
+                margin-right: 10px;
+            }
+        }
+
+        .text-message {
+            overflow: hidden;
+            margin-top: 10px;
+            color: #333;
+            border-left: 8px solid #333;
+            text-indent: 10px;
+            font-weight: 600;
+        }
+
+        .small {
+            font-size: 12px;
+            color: #555;
+        }
+
+        .all-message {
+            overflow: hidden;
+
+            button {
+                float: right;
+                padding: 10px;
+                margin-left: 5px;
+            }
+        }
+
+    }
+</style>

+ 87 - 43
src/components/dialogs/list/filesDialog.vue

@@ -3,50 +3,94 @@
 -->
 
 <template>
-  <el-dialog title="上传文件" :visible.sync="dialog.uploadFiles" width="500px">
-      <div class='max-height: 500px; overflow-y: auto;'>
-        <upload-files :readOnly="read" :keysArr="keysArr" @change="changeItem" max="2"></upload-files>
-      </div>
-  </el-dialog>
+    <el-dialog
+        title="上传文件"
+        :visible.sync="dialog.uploadFiles"
+        width="500px">
+        <div class='max-height: 500px; overflow-y: auto;'>
+            <upload-files
+                :readOnly="read"
+                :keysArr="keysArr"
+                :firmDataType="firmDataType"
+                @change="changeItem"
+                max="2"/>
+        </div>
+    </el-dialog>
 </template>
 <script>
-import uploadFiles from "@/components/ledger/lib/uploadFiles";
-export default {
-  components: {
-    uploadFiles
-  },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          uploadFiles: false
-        };
-      }
-    },
-    keysArr: {
-      type: Array,
-      default: function () {
-        return []
-      }
-    },
-    read: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {};
-  },
-  created() { },
-  mounted() { },
-  methods: {
-    changeItem(file) {
-      console.log(file)
-      this.$emit("changeFile", file)
-    }
-  },
-};
+    import uploadFiles from "@/components/ledger/lib/uploadFiles";
+
+    export default {
+        components: {
+            uploadFiles
+        },
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        uploadFiles: false
+                    };
+                }
+            },
+            keysArr: {
+                type: Array,
+                default: function () {
+                    return []
+                }
+            },
+            read: {
+                type: Boolean,
+                default: false
+            },
+            firmDataType: {
+                type: String
+            },
+            infoType: {
+                type: String
+            },
+            information: {
+                type: Object
+            }
+        },
+        data() {
+            return {};
+        },
+        created() {
+        },
+        computed: {
+
+        },
+        mounted() {
+        },
+        methods: {
+            changeItem(file) {
+                if (this.firmDataType === 'dialog') {
+                    let info = this.infoType;
+                    switch (info) {
+                        case 'archive':
+                            this.information.archive.Archive = file
+                            this.$emit("changeFile", this.information, this.firmDataType)
+                            break
+                        case 'checkReport':
+                            this.information.checkReport.CheckReport = file
+                            this.$emit("changeFile", this.information, this.firmDataType)
+                            break
+                        case 'insuranceFile':
+                            this.information.insuranceFile.InsuranceFile = file
+                            this.$emit("changeFile", this.information, this.firmDataType)
+                            break
+                    }
+                } else {
+                    this.$emit("changeFile", file, this.firmDataType)
+
+                }
+            },
+            deepCopy(obj) {
+                return JSON.parse((JSON.stringify(obj)))
+            }
+        },
+    };
 </script>
 <style>
-</style>
+</style>

+ 132 - 85
src/components/dialogs/list/firm.vue

@@ -2,7 +2,7 @@
     firm 厂商
 -->
 <template>
-  <el-dialog title="选择型号" :visible.sync="dialog.firm" width="900px">
+  <el-dialog title="选择生产厂家/品牌/型号" :visible.sync="dialog.firm" width="900px">
     <div>
       <div id="firm">
         <div class="title-search query-form" style="padding: 10px;margin-bottom: 10px;">
@@ -14,6 +14,9 @@
             clearable
           ></el-input>
           <el-button @click="searchKey" size="small">查找</el-button>
+          <el-select v-model="value" style="margin-left:10px;" @change="handleChangeType" placeholder="请选择">
+            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
+          </el-select>
         </div>
         <el-radio-group v-model="radio" style="width:100%;">
           <el-table class='data-table' :data="tableData" style="width: 100%" height="300px" border>
@@ -24,9 +27,9 @@
             </el-table-column>
             <el-table-column prop="brandName" label="品牌" header-align='center'></el-table-column>
             <el-table-column prop="name" label="型号" header-align='center'></el-table-column>
-            <el-table-column label="技术参数" header-align='center'>
+            <el-table-column  label="技术参数" header-align='center'>
               <template slot-scope="scope">
-                <el-button type="text" @click="lookParam(scope.row)">技术参数</el-button>
+                <el-button :disabled="scope.row.specificationId?false:true" type="text" @click="lookParam(scope.row)">技术参数</el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -37,8 +40,8 @@
                 <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
             </p>
             <my-pagination :page="page" @change="changed" style="margin-top:10px;"></my-pagination>
-        </div> 
-        
+        </div>
+
       </div>
     </div>
     <div slot="footer" class="dialog-footer">
@@ -53,97 +56,141 @@
 <script>
 import myPagination from "@/components/ledger/lib/myPagination";
 import paramDetails from "@/components/dialogs/list/paramDetails"
-import { getSpecList } from "@/api/scan/request"
+import { getSpecList, getBrandList, getManufacturerList } from "@/api/scan/request"
 
 export default {
   components: {
     myPagination,
     paramDetails
   },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          firm: false
-        };
-      }
-    },
-    mess: {
-      type: [Object, String]
-    }
-  },
-  data() {
-    return {
-      search: "", //搜索文案
-      radio: "",
-      tableData: [
-      ],
-      data: {},
-      isLoad: {
-        paramShow: false
-      },
-      page: {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      },
-    };
-  },
-  created() { },
-  mounted() { },
-  methods: {
-    changed() {
-      this.getData()
-    },
-    //查询技术参数
-    lookParam(data) {
-      this.data = data
-      this.isLoad.paramShow = true
-    },
-    getChange() {
-      if (!!this.radio) {
-        this.$emit("changeFirm", this.radio)
-        this.dialog.firm = false
-        this.radio = ''
-      } else {
-        this.$message("请选择型号")
-      }
-    },
-    searchKey() {
-      this.changePage()
-    },
-    changePage() {
-      this.page = {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-      this.getData()
-    },
-    getData() {
-      getSpecList({
-        limit: {
-          skip: this.page.size * (this.page.currentPage - 1),
-          count: this.page.size
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        firm: false
+                    };
+                }
+            },
+            mess: {
+                type: [Object, String]
+            },
+            firmDataType: {
+                type: String
+            }
         },
-        eqFamily: this.mess.deviceId,
-        name: this.search
-      }, res => {
-        this.page.total = res.totalCount
-        this.tableData = res.content
-        console.log(this.tableData)
-      })
-    }
-  },
-  watch: {
+        data() {
+            return {
+                search: "", //搜索文案
+                radio: "",
+                value: "specification",//当前选择的查看类型
+                options: [{
+                    value: 'specification',
+                    label: '选型号'
+                }, {
+                    value: 'brand',
+                    label: '选生产厂家-品牌'
+                }, {
+                    value: 'manufacturer',
+                    label: '选生产厂家'
+                }],
+                tableData: [],
+                data: {},
+                isLoad: {
+                    paramShow: false
+                },
+                page: {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                },
+            };
+        },
+        created() {
+        },
+        mounted() {
+        },
+        methods: {
+            changed() {
+                this.getData()
+            },
+            //查询技术参数
+            lookParam(data) {
+                this.data = data
+                this.isLoad.paramShow = true
+            },
+            getChange() {
+                if (!!this.radio) {
+                    this.$emit("changeFirm", this.radio,this.firmDataType)
+                    this.dialog.firm = false
+                    this.radio = ''
+                } else {
+                    this.$message("请选择型号")
+                }
+            },
+            searchKey() {
+                this.changePage()
+            },
+            changePage() {
+                this.page = {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+                this.getData()
+            },
+            getData() {
+                if (this.value == 'specification') {//型号
+                    getSpecList({
+                        limit: {
+                            skip: this.page.size * (this.page.currentPage - 1),
+                            count: this.page.size
+                        },
+                        eqFamily: this.mess.deviceId,
+                        name: this.search
+                    }, res => {
+                        this.page.total = res.totalCount
+                        this.tableData = res.content
+                    })
+                } else if (this.value == 'brand') {//生产厂家-品牌
+                    getBrandList({
+                        limit: {
+                            skip: this.page.size * (this.page.currentPage - 1),
+                            count: this.page.size
+                        },
+                        name: this.search
+                    }, res => {
+                        this.page.total = res.totalCount
+                        this.tableData = res.content
+                    })
+                } else if (this.value == 'manufacturer') {//生产厂家
+                    getManufacturerList({
+                        limit: {
+                            skip: this.page.size * (this.page.currentPage - 1),
+                            count: this.page.size
+                        },
+                        name: this.search
+                    }, res => {
+                        this.page.total = res.totalCount
+                        this.tableData = res.content
+                    })
+                }
+                console.log(this.tableData)
+            },
+            handleChangeType(item) {
+                this.page.total = 0
+                this.tableData = []
+                this.getData()
+            },
+        },
+        watch: {
     dialog: {
       deep: true,
       handler: function () {
         if (this.dialog.firm) {
-          console.log(this.mess)
+          this.value = 'specification'
           this.changePage()
         }
       }

+ 111 - 107
src/components/dialogs/list/insurerDialog.vue

@@ -38,7 +38,7 @@
                 <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
             </p>
             <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
-        </div>         
+        </div>
       </div>
     </div>
     <div slot="footer">
@@ -50,120 +50,124 @@
   </el-dialog>
 </template>
 <script>
-import myPagination from "@/components/ledger/lib/myPagination";
-import { getLib } from "@/api/scan/request"
-import { mapGetters, mapActions } from "vuex";
-import tools from "@/utils/scan/tools"
+    import myPagination from "@/components/ledger/lib/myPagination";
+    import {getLib} from "@/api/scan/request"
+    import {mapGetters} from "vuex";
+    import tools from "@/utils/scan/tools"
 
-export default {
-  components: {
+    export default {
+        components: {
     myPagination
   },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          insurer: true
-        };
-      }
-    }
-  },
-  computed: {
-    ...mapGetters("layout", ["projectId", "secret", "userId"]),
-  },
-  data() {
-    return {
-      search: "", //搜索文案
-      radio: "",
-      tableData: [],
-      page: {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-    };
-  },
-  created() {
-    // this.getData()
-  },
-  mounted() { },
-  methods: {
-    //过滤
-    filterSearch() {
-      this.tableData = this.allData.map(item => {
-        if (item.name.indexOf(this.search) != -1) {
-          return item
-        } else {
-          return undefined
-        }
-      }).filter(cb => cb)
-    },
-    getData() {
-      console.log("insurer")
-      this.page = {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-      getLib({ "type": ["insurance"] }).then(res => {
-        if (res.data.result == "success") {
-          let data = res.data.content.insurance.map(item => {
-            if (item.contacts && item.contacts.length) {
-              item.contacts.map(child => {
-                if (child.projectId == this.projectId) {
-                  item.phone = child.phone
-                  item.man = child.name
-                  item.fox = child.fox
-                  item.email = child.email
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        insurer: true
+                    };
                 }
-                return child
-              })
-            }
-            if (!item.man) {
-              item.man = "--"
-              item.phone = "--"
-              item.fox = "--"
-              item.email = "--"
+            },
+            firmDataType: {
+                type: String
             }
-            return item
-          })
-          this.allData = tools.deepCopy(data)
-          this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
-          this.page.total = data.length
-        } else {
-          this.$message.error("请求失败:" + res.data.resultMsg)
-        }
-      })
-    },
+        },
+        computed: {
+            ...mapGetters("layout", ["projectId", "secret", "userId"]),
+        },
+        data() {
+            return {
+                search: "", //搜索文案
+                radio: "",
+                tableData: [],
+                page: {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+            };
+        },
+        created() {
+            // this.getData()
+        },
+        mounted() {
+        },
+        methods: {
+            //过滤
+            filterSearch() {
+                this.tableData = this.allData.map(item => {
+                    if (item.name.indexOf(this.search) != -1) {
+                        return item
+                    } else {
+                        return undefined
+                    }
+                }).filter(cb => cb)
+            },
+            getData() {
+                console.log("insurer")
+                this.page = {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+                getLib({"type": ["insurance"]}).then(res => {
+                    if (res.data.result == "success") {
+                        let data = res.data.content.insurance.map(item => {
+                            if (item.contacts && item.contacts.length) {
+                                item.contacts.map(child => {
+                                    if (child.projectId == this.projectId) {
+                                        item.phone = child.phone
+                                        item.man = child.name
+                                        item.fox = child.fox
+                                        item.email = child.email
+                                    }
+                                    return child
+                                })
+                            }
+                            if (!item.man) {
+                                item.man = "--"
+                                item.phone = "--"
+                                item.fox = "--"
+                                item.email = "--"
+                            }
+                            return item
+                        })
+                        this.allData = tools.deepCopy(data)
+                        this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+                        this.page.total = data.length
+                    } else {
+                        this.$message.error("请求失败:" + res.data.resultMsg)
+                    }
+                })
+            },
 
-    //分页改变
-    changePage() {
-      this.pagination(this.page.currentPage, this.page.size, this.allData)
-    },
+            //分页改变
+            changePage() {
+                this.pagination(this.page.currentPage, this.page.size, this.allData)
+            },
 
-    //发生修改
-    getChange() {
-      if (!!this.radio) {
-        this.$emit("changeInsurer", this.radio)
-        this.dialog.insurer = false
-        this.radio = ''
-      } else {
-        this.$message("请选择一个生产厂商")
-      }
-    },
+            //发生修改
+            getChange() {
+                if (!!this.radio) {
+                    this.$emit("changeInsurer", this.radio,this.firmDataType)
+                    this.dialog.insurer = false
+                    this.radio = ''
+                } else {
+                    this.$message("请选择一个生产厂商")
+                }
+            },
 
-    //分页事件
-    pagination(pageNo, pageSize, array) {
-      let offset = (pageNo - 1) * pageSize;
-      return offset + pageSize >= array.length
-        ? array.slice(offset, array.length)
-        : array.slice(offset, offset + pageSize);
-    }
-  },
-  watch: {
+            //分页事件
+            pagination(pageNo, pageSize, array) {
+                let offset = (pageNo - 1) * pageSize;
+                return offset + pageSize >= array.length
+                    ? array.slice(offset, array.length)
+                    : array.slice(offset, offset + pageSize);
+            }
+        },
+        watch: {
     dialog: {
       deep: true,
       handler: function () {

+ 111 - 107
src/components/dialogs/list/maintainerDialog.vue

@@ -1,5 +1,5 @@
 <!--
-    maintenance 选择供应
+    maintenance 选择维修
 
 -->
 <template>
@@ -38,7 +38,7 @@
                 <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
             </p>
             <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
-        </div>         
+        </div>
       </div>
     </div>
     <div slot="footer">
@@ -50,119 +50,123 @@
   </el-dialog>
 </template>
 <script>
-import myPagination from "@/components/ledger/lib/myPagination";
-import { mapGetters, mapActions } from "vuex";
-import { getLib } from "@/api/scan/request"
-import tools from "@/utils/scan/tools"
+    import myPagination from "@/components/ledger/lib/myPagination";
+    import {mapGetters} from "vuex";
+    import {getLib} from "@/api/scan/request"
+    import tools from "@/utils/scan/tools"
 
-export default {
-  components: {
+    export default {
+        components: {
     myPagination
   },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          maintainer: true
-        };
-      }
-    }
-  },
-  computed: {
-    ...mapGetters("layout", ["projectId", "secret", "userId"]),
-  },
-  data() {
-    return {
-      search: "", //搜索文案
-      radio: "",
-      tableData: [],
-      page: {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-    };
-  },
-  created() {
-    // this.getData()
-  },
-  mounted() { },
-  methods: {
-    //过滤
-    filterSearch() {
-      this.tableData = this.allData.map(item => {
-        if (item.name.indexOf(this.search) != -1) {
-          return item
-        } else {
-          return undefined
-        }
-      }).filter(cb => cb)
-    },
-    getData() {
-      this.page = {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-      getLib({ "type": ["maintenance"] }).then(res => {
-        if (res.data.result == "success") {
-          let data = res.data.content.maintenance.map(item => {
-            if (item.contacts && item.contacts.length) {
-              item.contacts.map(child => {
-                if (child.projectId == this.projectId) {
-                  item.phone = child.phone
-                  item.man = child.name
-                  item.fox = child.fox
-                  item.email = child.email
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        maintainer: true
+                    };
                 }
-                return child
-              })
-            }
-            if (!item.man) {
-              item.man = "--"
-              item.phone = "--"
-              item.fox = "--"
-              item.email = "--"
+            },
+            firmDataType: {
+                type: String
             }
-            return item
-          })
-          this.allData = tools.deepCopy(data)
-          this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
-          this.page.total = data.length
-        } else {
-          this.$message.error("请求失败:" + res.data.resultMsg)
-        }
-      })
-    },
+        },
+        computed: {
+            ...mapGetters("layout", ["projectId", "secret", "userId"]),
+        },
+        data() {
+            return {
+                search: "", //搜索文案
+                radio: "",
+                tableData: [],
+                page: {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+            };
+        },
+        created() {
+            // this.getData()
+        },
+        mounted() {
+        },
+        methods: {
+            //过滤
+            filterSearch() {
+                this.tableData = this.allData.map(item => {
+                    if (item.name.indexOf(this.search) != -1) {
+                        return item
+                    } else {
+                        return undefined
+                    }
+                }).filter(cb => cb)
+            },
+            getData() {
+                this.page = {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+                getLib({"type": ["maintenance"]}).then(res => {
+                    if (res.data.result == "success") {
+                        let data = res.data.content.maintenance.map(item => {
+                            if (item.contacts && item.contacts.length) {
+                                item.contacts.map(child => {
+                                    if (child.projectId == this.projectId) {
+                                        item.phone = child.phone
+                                        item.man = child.name
+                                        item.fox = child.fox
+                                        item.email = child.email
+                                    }
+                                    return child
+                                })
+                            }
+                            if (!item.man) {
+                                item.man = "--"
+                                item.phone = "--"
+                                item.fox = "--"
+                                item.email = "--"
+                            }
+                            return item
+                        })
+                        this.allData = tools.deepCopy(data)
+                        this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+                        this.page.total = data.length
+                    } else {
+                        this.$message.error("请求失败:" + res.data.resultMsg)
+                    }
+                })
+            },
 
-    //分页改变
-    changePage() {
-      this.pagination(this.page.currentPage, this.page.size, this.allData)
-    },
+            //分页改变
+            changePage() {
+                this.pagination(this.page.currentPage, this.page.size, this.allData)
+            },
 
-    //发生修改
-    getChange() {
-      if (!!this.radio) {
-        this.$emit("changeMaintainer", this.radio)
-        this.dialog.maintainer = false
-        this.radio = ''
-      } else {
-        this.$message("请选择一个生产厂商")
-      }
-    },
+            //发生修改
+            getChange() {
+                if (!!this.radio) {
+                    this.$emit("changeMaintainer", this.radio,this.firmDataType)
+                    this.dialog.maintainer = false
+                    this.radio = ''
+                } else {
+                    this.$message("请选择一个生产厂商")
+                }
+            },
 
-    //分页事件
-    pagination(pageNo, pageSize, array) {
-      let offset = (pageNo - 1) * pageSize;
-      return offset + pageSize >= array.length
-        ? array.slice(offset, array.length)
-        : array.slice(offset, offset + pageSize);
-    }
-  },
-  watch: {
+            //分页事件
+            pagination(pageNo, pageSize, array) {
+                let offset = (pageNo - 1) * pageSize;
+                return offset + pageSize >= array.length
+                    ? array.slice(offset, array.length)
+                    : array.slice(offset, offset + pageSize);
+            }
+        },
+        watch: {
     dialog: {
       deep: true,
       handler: function () {

+ 147 - 126
src/components/dialogs/list/picDialog.vue

@@ -3,139 +3,160 @@
 -->
 
 <template>
-  <el-dialog title="上传图片" :visible.sync="dialog.pic" width="500px;">
-    <div style="max-height:500px;overflow-y:auto;">
-      <div>
-        <h3>设备图片</h3>
-        <upload-imgs :readOnly="read" :keysArr="picArrs" @change="imageItem" max="6"></upload-imgs>
-      </div>
-      <div>
-        <h3>视频</h3>
-        <upload-imgs
-          :accept="'video/*'"
-          type="video"
-          :keysArr="videoArr"
-          @change="videoItem"
-          :videoPicArr="videoPicArr"
-          max="2"
-          :readOnly="read"
-        ></upload-imgs>
-      </div>
-    </div>
-  </el-dialog>
+    <el-dialog title="上传图片" :visible.sync="dialog.pic" width="500px;">
+        <div style="max-height:500px;overflow-y:auto;">
+            <div>
+                <h3>设备图片</h3>
+                <upload-imgs
+                    :readOnly="read"
+                    :keysArr="picArrs"
+                    @change="imageItem"
+                    max="6"
+                />
+            </div>
+            <div>
+                <h3>视频</h3>
+                <upload-imgs
+                    :accept="'video/*'"
+                    type="video"
+                    :keysArr="videoArr"
+                    @change="videoItem"
+                    :videoPicArr="videoPicArr"
+                    max="2"
+                    :readOnly="read"
+                />
+            </div>
+        </div>
+    </el-dialog>
 </template>
 <script>
-import uploadImgs from "@/components/ledger/lib/uploadImgsName";
-import tools from "@/utils/scan/tools"
-export default {
-  components: {
-    uploadImgs
-  },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          pic: true
-        };
-      }
-    },
-    keysArr: {
-      type: Array,
-      default: function () {
-        return []
-      }
-    },
-    read: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {
-      picArrs: [],
-      panoramaArr: [],
-      videoArr: [],
-      videoPicArr: [],
-      changeKeys: []
-    };
-  },
-  created() { },
-  mounted() { },
-  methods: {
-    imageItem(images) {
-      this.picArrs = images
-      this.change()
-    },
+    import uploadImgs from "@/components/ledger/lib/uploadImgsName";
+
+    export default {
+        components: {
+            uploadImgs
+        },
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        pic: true
+                    };
+                }
+            },
+            keysArr: {
+                type: Array,
+                default: function () {
+                    return []
+                }
+            },
+            read: {
+                type: Boolean,
+                default: false
+            },
+            firmDataType: {
+                type: String
+            },
+            information: {
+                type: Object
+            },
+            infoType: {
+                type: String
+            }
+        },
+        data() {
+            return {
+                picArrs: [],
+                panoramaArr: [],
+                videoArr: [],
+                videoPicArr: [],
+                changeKeys: []
+            };
+        },
+        created() {
+        },
+        mounted() {
+        },
+        methods: {
+            imageItem(images) {
+                this.picArrs = images
+                this.change()
+            },
 
-    panoramaItem(images) {
-      this.panoramaArr = images
-      this.change()
-    },
+            panoramaItem(images) {
+                this.panoramaArr = images
+                this.change()
+            },
 
-    videoItem(videos, pe, pics) {
-      this.videoArr = videos
-      this.videoPicArr = pics
-      this.change()
-    },
+            videoItem(videos, pe, pics) {
+                this.videoArr = videos
+                this.videoPicArr = pics
+                this.change()
+            },
 
-    change() {
-      //   let picsArr = this.getArr(this.picArrs, "设备图片", "image")
-      //   let videos = this.getArr(this.videoArr, "视频", "video")
-      //   let videoPics = this.getArr(this.videoPicArr, "视频资料", "image_video")
-      //   let panoramas = this.getArr(this.panoramaArr, "全景照片", "panorama")
-      let picsArr = this.picArrs
-      let videos = this.videoArr
-      let videoPics = this.videoPicArr
-      let panoramas = this.panoramaArr
-      this.changeKeys = picsArr.concat(videos).concat(videoPics).concat(panoramas)
-      console.log(this.changeKeys)
-      this.$emit("change", this.changeKeys)
-    },
+            change() {
+                //   let picsArr = this.getArr(this.picArrs, "设备图片", "image")
+                //   let videos = this.getArr(this.videoArr, "视频", "video")
+                //   let videoPics = this.getArr(this.videoPicArr, "视频资料", "image_video")
+                //   let panoramas = this.getArr(this.panoramaArr, "全景照片", "panorama")
+                let picsArr = this.picArrs
+                let videos = this.videoArr
+                let videoPics = this.videoPicArr
+                let panoramas = this.panoramaArr
+                this.changeKeys = picsArr.concat(videos).concat(videoPics).concat(panoramas)
+                if (this.firmDataType === 'dialog') {
+                    this.information.pic.Pic = this.changeKeys
+                    this.$emit("change",this.information,this.firmDataType)
+                } else {
+                    this.$emit("change", this.changeKeys)
 
-    getArr(arr, name, type) {
-      return arr.map(item => {
-        return { "systemId": "dataPlatform", "name": name, "type": type, "key": item }
-      })
-    },
+                }
+            },
 
-    //将父组件传来的数据进行分组
-    fatherTochild() {
-      this.panoramaArr = []
-      this.videoArr = []
-      this.videoPicArr = []
-      this.picArrs = []
-      if (this.keysArr instanceof Array) {
-        this.keysArr.map(item => {
-          if (item.type == 'panorama') {
-            this.panoramaArr.push(item)
-          } else if (item.type == "video") {
-            this.videoArr.push(item)
-          } else if (item.type == 'image_video') {
-            this.videoPicArr.push(item)
-          } else {
-            this.picArrs.push(item)
-          }
-        })
-      } else {
-        this.panoramaArr = []
-        this.videoArr = []
-        this.videoPicArr = []
-        this.picArrs = []
-      }
-    }
-  },
-  watch: {
-    dialog: {
-      deep: true,
-      handler: function () {
-        if (this.dialog.pic) {
-          this.fatherTochild()
+            getArr(arr, name, type) {
+                return arr.map(item => {
+                    return {"systemId": "dataPlatform", "name": name, "type": type, "key": item}
+                })
+            },
+
+            //将父组件传来的数据进行分组
+            fatherTochild() {
+                this.panoramaArr = []
+                this.videoArr = []
+                this.videoPicArr = []
+                this.picArrs = []
+                if (this.keysArr instanceof Array) {
+                    this.keysArr.map(item => {
+                        if (item.type == 'panorama') {
+                            this.panoramaArr.push(item)
+                        } else if (item.type == "video") {
+                            this.videoArr.push(item)
+                        } else if (item.type == 'image_video') {
+                            this.videoPicArr.push(item)
+                        } else {
+                            this.picArrs.push(item)
+                        }
+                    })
+                } else {
+                    this.panoramaArr = []
+                    this.videoArr = []
+                    this.videoPicArr = []
+                    this.picArrs = []
+                }
+            }
+        },
+        watch: {
+            dialog: {
+                deep: true,
+                handler: function () {
+                    if (this.dialog.pic) {
+                        this.fatherTochild()
+                    }
+                }
+            }
         }
-      }
-    }
-  }
-};
+    };
 </script>
 <style>
-</style>
+</style>

+ 110 - 106
src/components/dialogs/list/supplierDialog.vue

@@ -38,7 +38,7 @@
                 <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
             </p>
             <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
-        </div>        
+        </div>
       </div>
     </div>
     <div slot="footer" class="footer">
@@ -50,119 +50,123 @@
   </el-dialog>
 </template>
 <script>
-import myPagination from "@/components/ledger/lib/myPagination";
-import { mapGetters } from "vuex";
-import { getLib } from "@/api/scan/request"
-import tools from "@/utils/scan/tools"
+    import myPagination from "@/components/ledger/lib/myPagination";
+    import {mapGetters} from "vuex";
+    import {getLib} from "@/api/scan/request"
+    import tools from "@/utils/scan/tools"
 
-export default {
-  components: {
+    export default {
+        components: {
     myPagination
   },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          supplier: true
-        };
-      }
-    }
-  },
-  data() {
-    return {
-      search: "", //搜索文案
-      radio: "",
-      tableData: [],
-      page: {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-    };
-  },
-  computed: {
-    ...mapGetters("layout", ["projectId", "secret", "userId"]),
-  },
-  created() {
-    // this.getData()
-  },
-  mounted() { },
-  methods: {
-    //过滤
-    filterSearch() {
-      this.tableData = this.allData.map(item => {
-        if (item.name.indexOf(this.search) != -1) {
-          return item
-        } else {
-          return undefined
-        }
-      }).filter(cb => cb)
-    },
-    getData() {
-      this.page = {
-        size: 50,
-        sizes: [10, 30, 50, 100, 150, 200],
-        total: 0,
-        currentPage: 1
-      }
-      getLib({ "type": ["supplier"] }).then(res => {
-        if (res.data.result == "success") {
-          let data = res.data.content.supplier.map(item => {
-            if (item.contacts && item.contacts.length) {
-              item.contacts.map(child => {
-                if (child.projectId == this.projectId) {
-                  item.phone = child.phone
-                  item.man = child.name
-                  item.fox = child.fox
-                  item.email = child.email
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        supplier: true
+                    };
                 }
-                return child
-              })
-            }
-            if (!item.man) {
-              item.man = "--"
-              item.phone = "--"
-              item.fox = "--"
-              item.email = "--"
+            },
+            firmDataType: {
+                type: String
             }
-            return item
-          })
-          this.allData = tools.deepCopy(data)
-          this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
-          this.page.total = data.length
-        } else {
-          this.$message.error("请求失败:" + res.data.resultMsg)
-        }
-      })
-    },
+        },
+        data() {
+            return {
+                search: "", //搜索文案
+                radio: "",
+                tableData: [],
+                page: {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+            };
+        },
+        computed: {
+            ...mapGetters("layout", ["projectId", "secret", "userId"]),
+        },
+        created() {
+            // this.getData()
+        },
+        mounted() {
+        },
+        methods: {
+            //过滤
+            filterSearch() {
+                this.tableData = this.allData.map(item => {
+                    if (item.name.indexOf(this.search) != -1) {
+                        return item
+                    } else {
+                        return undefined
+                    }
+                }).filter(cb => cb)
+            },
+            getData() {
+                this.page = {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                }
+                getLib({"type": ["supplier"]}).then(res => {
+                    if (res.data.result == "success") {
+                        let data = res.data.content.supplier.map(item => {
+                            if (item.contacts && item.contacts.length) {
+                                item.contacts.map(child => {
+                                    if (child.projectId == this.projectId) {
+                                        item.phone = child.phone
+                                        item.man = child.name
+                                        item.fox = child.fox
+                                        item.email = child.email
+                                    }
+                                    return child
+                                })
+                            }
+                            if (!item.man) {
+                                item.man = "--"
+                                item.phone = "--"
+                                item.fox = "--"
+                                item.email = "--"
+                            }
+                            return item
+                        })
+                        this.allData = tools.deepCopy(data)
+                        this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+                        this.page.total = data.length
+                    } else {
+                        this.$message.error("请求失败:" + res.data.resultMsg)
+                    }
+                })
+            },
 
-    //分页改变
-    changePage() {
-      this.pagination(this.page.currentPage, this.page.size, this.allData)
-    },
+            //分页改变
+            changePage() {
+                this.pagination(this.page.currentPage, this.page.size, this.allData)
+            },
 
-    //发生修改
-    getChange() {
-      if (!!this.radio) {
-        this.$emit("changeSupplier", this.radio)
-        this.dialog.supplier = false
-        this.radio = ''
-      } else {
-        this.$message("请选择一个生产厂商")
-      }
-    },
+            //发生修改
+            getChange() {
+                if (!!this.radio) {
+                    this.$emit("changeSupplier", this.radio, this.firmDataType)
+                    this.dialog.supplier = false
+                    this.radio = ''
+                } else {
+                    this.$message("请选择一个生产厂商")
+                }
+            },
 
-    //分页事件
-    pagination(pageNo, pageSize, array) {
-      let offset = (pageNo - 1) * pageSize;
-      return offset + pageSize >= array.length
-        ? array.slice(offset, array.length)
-        : array.slice(offset, offset + pageSize);
-    }
-  },
-  watch: {
+            //分页事件
+            pagination(pageNo, pageSize, array) {
+                let offset = (pageNo - 1) * pageSize;
+                return offset + pageSize >= array.length
+                    ? array.slice(offset, array.length)
+                    : array.slice(offset, offset + pageSize);
+            }
+        },
+        watch: {
     dialog: {
       deep: true,
       handler: function () {

+ 68 - 34
src/components/dialogs/list/uploadImgDialog.vue

@@ -10,47 +10,81 @@
   </el-dialog>
 </template>
 <script>
-import uploadImgs from "@/components/ledger/lib/uploadImgs";
-export default {
-  components: {
-    uploadImgs
-  },
-  props: {
-    dialog: {
-      type: Object,
-      default: function () {
-        return {
-          uploadImgs: true
-        };
-      }
-    },
-    keysArr: {
-      type: Array,
-      default: function () {
-        return []
-      }
-    },
-    read: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {};
-  },
-  created() { },
-  mounted() { },
-  methods: {
+    import uploadImgs from "@/components/ledger/lib/uploadImgs";
+
+    export default {
+        components: {
+            uploadImgs
+        },
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        uploadImgs: true
+                    };
+                }
+            },
+            keysArr: {
+                type: Array,
+                default: function () {
+                    return []
+                }
+            },
+            read: {
+                type: Boolean,
+                default: false
+            },
+            firmDataType: {
+                type: String
+            },
+            information: {
+                type: Object
+            },
+            infoType: {
+                type: String
+            }
+        },
+        data() {
+            return {};
+        },
+        created() {
+        },
+        mounted() {
+        },
+        methods: {
     deepcopy(obj) {
       console.log(obj, "out")
       return JSON.parse(JSON.stringify(obj));
     },
     changeItem(file) {
-      console.log(file, "changed")
-      this.$emit("changeFile", file)
+        if (this.firmDataType === 'dialog') {
+            let info = this.infoType
+            switch (info) {
+                case 'installPic':
+                    this.information.installPic.InstallPic = file
+                    this.$emit('changeFile', this.information, this.firmDataType)
+                    break
+                case 'installDrawing':
+                    this.information.installDrawing.InstallDrawing = file
+                    this.$emit('changeFile', this.information, this.firmDataType)
+                    break
+                case 'nameplate':
+                    this.information.nameplate.Nameplate = file
+                    this.$emit('changeFile', this.information, this.firmDataType)
+                    break
+                case 'drawing':
+                    this.information.drawing.Drawing = file
+                    this.$emit('changeFile', this.information, this.firmDataType)
+                    break
+            }
+        } else {
+            this.$emit("changeFile", file)
+        }
+
     }
   },
 };
 </script>
 <style>
-</style>
+</style>

+ 1 - 1
src/components/ledger/addDialog/dialogAssets.vue

@@ -508,7 +508,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该资产"

+ 2 - 2
src/components/ledger/addDialog/dialogDevice.vue

@@ -612,7 +612,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"
@@ -958,7 +958,7 @@ export default {
     overflow: hidden;
     // height: 300px;
     // overflow-x: hidden;
-    // overflow-y:auto; 
+    // overflow-y:auto;
 
 }
 </style>

+ 1 - 1
src/components/ledger/addDialog/dialogSystem.vue

@@ -570,7 +570,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该资产"

+ 6 - 8
src/components/ledger/cenote/dialog/addSpaceDialog.vue

@@ -55,9 +55,9 @@
 
 <script>
 import {
+  shaftUnlinkSpaceQuery,
   unSysZoneSpace,
-  linkSysSp,
-  queryDictionaryHead
+  linkShaftSpace
 } from "@/api/scan/request";
 import floorCascader from "@/components/ledger/lib/floorCascader";
 import dictionaryCas from "@/components/config_point/dictionaryCascader";
@@ -130,8 +130,7 @@ export default {
           PageNumber: this.page.pageNumber,
           PageSize: this.page.pageSize
         },
-        shaftId: this.params.ShaftID,
-        sysId: this.$route.query.SysID
+        ShaftId: this.$route.query.ShaftId
       };
       if (this.Buildfloor[0] == "noKnow") {
         params.data.Filters += `;buildingId isNull`;
@@ -149,8 +148,7 @@ export default {
       if (this.keycode != "") {
         params.data.Filters += `;RoomName contain '${this.keycode}' or RoomLocalName contain '${this.keycode}'`;
       }
-
-      unSysZoneSpace(params, res => {
+      shaftUnlinkSpaceQuery(params, res => {
         this.tableData = res.Content;
         this.page.total = res.Total;
       });
@@ -168,12 +166,12 @@ export default {
           Content: this.selections.map(item => {
             return {
               SpaceID: item.RoomID,
-              SysID: this.$route.query.SysID,
+              ShaftId: this.$route.query.ShaftId,
               ObjectType: item.ObjectType
             };
           })
         };
-        linkSysSp(params, res => {
+        linkShaftSpace(params, res => {
           this.$message.success("关联成功!");
           this.$emit("refresh");
         });

+ 6 - 2
src/components/ledger/handsontables/assets.vue

@@ -536,7 +536,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除选中资产"
@@ -890,7 +890,7 @@ export default {
     supplyChange(data) {
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.SupplierContractID", { id: data })
     },
-    //保险单号-保险文件 
+    //保险单号-保险文件
     guaranteeChange(data) {
       for (let key in data) {
         this.utilToKey(key, "insuranceNo", data, "InsuranceNum")
@@ -907,6 +907,7 @@ export default {
       tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)//生产商ID
       tools.setDataForKey(this.tableData[this.row], "DPBrandID", data.brandId)//品牌ID
       tools.setDataForKey(this.tableData[this.row], "DPSpecificationID", data.specificationId)//型号ID
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Manufacturer", data.venderName)
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brandName)
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Specification", data.name)
       this.handleUpdataTable(
@@ -914,6 +915,7 @@ export default {
           [this.row, "DPManufacturerID", null, data.venderId],
           [this.row, "DPBrandID", null, data.brandId],
           [this.row, "DPSpecificationID", null, data.specificationId],
+          [this.row, "LedgerParam.EquipManufactor.Manufacturer", null, data.venderName],
           [this.row, "LedgerParam.EquipManufactor.Brand", null, data.brandName],
           [this.row, "LedgerParam.EquipManufactor.Specification", null, data.name]
         ],
@@ -996,6 +998,8 @@ export default {
   },
   watch: {
     projectId() {
+      this.buildFloorData = []
+      buildFloor.getData(this.buildFloorData)
       this.main = []
       this.mess.deviceId = null
       this.page.total = 0

File diff suppressed because it is too large
+ 1187 - 864
src/components/ledger/handsontables/device.vue


+ 5 - 3
src/components/ledger/handsontables/system.vue

@@ -393,7 +393,7 @@ export default {
         columnSorting: true, //添加排序
         sortIndicator: true, //添加排序
         renderAllRows: true,
-        observeChanges: false,
+        // observeChanges: false, //启用observeChanges插件
         // colWidths: 200,
         autoColumnSize: true,
         language: "zh-CN",
@@ -404,7 +404,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该系统"
@@ -557,7 +557,9 @@ export default {
           }
           return false
         case 'BuildingFloorInfoList':
-          this.$refs.editFloor.showDialog(this.tableData[row.row]);
+          if (!this.onlyRead) {
+            this.$refs.editFloor.showDialog(this.tableData[row.row]);
+          }
           return false
         default:
           break;

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

@@ -352,7 +352,7 @@ export default {
           "filter_by_value",
           "filter_action_bar"
         ],
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除该业务空间"

+ 299 - 0
src/components/ledger/lib/cenoteGraphy.vue

@@ -0,0 +1,299 @@
+<template>
+  <div id="cenoteGraphy" style="height:100%;width:100%;" 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="canvas-actions-box">
+        <canvasFun @scale="scale" @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @saveJson="saveJson" :config="config" ref="canvasFun"></canvasFun>
+      </el-row>
+    </div>
+  </div>
+</template>
+
+<script>
+import canvasFun from "@/components/business_space/newGraphy/canvasFun";
+import { SColor, SPoint } from "@saga-web/draw/lib";
+import { DivideFloorScene, SpaceItem, ZoneItem } from "@saga-web/cad-engine/lib";
+import { FloorView } from "@saga-web/cad-engine/lib/FloorView";
+import { colorArr } from '@/utils/spaceColor';
+import { getFloorMsgByFloorID, queryZone, shaftSpaceQuery, shaftZoneLink } from '@/api/scan/request';
+import { resolve, reject } from 'q';
+export default {
+  data() {
+    return {
+      canvasLoading: false,//加载canvas
+      floorMap: '',//地图
+      canvasWidth: 800,
+      canvasHeight: 600,
+      view: null,
+      scene: null,
+      buildingData: [],//建筑,楼层
+      space: '',//当前空间类型
+      businessSpaceList: [],//所有业务空间
+      BSPRelaISPList: [],//已关联元空间的业务空间
+      zoneList: [], // 业务空间-canvas图中
+      selectAble: false,
+      relatedSpaceIdList: [],//已关联的业务空间id
+      config: {
+        isEdit: false
+      },
+    }
+  },
+  mounted() {
+    this.canvasWidth = this.$refs.graphy.offsetWidth;
+    this.canvasHeight = this.$refs.graphy.offsetHeight;
+  },
+  components: {
+    canvasFun
+  },
+  created() {
+
+  },
+  methods: {
+    //获取楼层map
+    getFloorMap(buildfloor, space) {
+      if (buildfloor.length == 2 && space && buildfloor[1] && buildfloor[0]) {
+        this.buildingData = buildfloor
+        let pa = {
+          Filters: `FloorID='${this.buildingData[1]}'`
+        }
+        getFloorMsgByFloorID(pa, res => {
+          this.floorMap = res.Content[0].StructureInfo ? res.Content[0].StructureInfo.FloorMap : '';
+          this.space = space;
+          this.getGraphy();
+        })
+      }
+      else{
+        this.floorMap = '';
+      }
+    },
+    //加载
+    load() {
+      if (this.scene) {
+        this.scene.clearSpaceSelection();
+        this.scene.clearZoneSelection();
+      }
+      //加载底板
+      this.getGraphy()
+    },
+    //获取底图
+    getGraphy() {
+      let that = this;
+      that.clearGraphy()
+      that.scene = new DivideFloorScene();
+      that.scene.isSpaceSelectable = false;
+      that.canvasLoading = true;
+      that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.floorMap}`).then(res => {
+        that.canvasLoading = false;
+        if (res == 'error') {
+          this.floorMap = '';
+          this.$message.warning('数据解析异常');
+          return;
+        }
+        that.view.scene = that.scene;
+        // 绘制业务空间
+        that.getBusinessSpace();
+        that.view.fitSceneToView();
+        that.view.maxScale = that.view.scale * 10;
+        that.view.minScale = that.view.scale;
+        if (that.$refs.canvasFun) {
+          that.$refs.canvasFun.everyScale = that.view.scale;
+        }
+      })
+    },
+    // 获取当前分区下的业务空间
+    getBusinessSpace() {
+      this.canvasLoading = true
+      this.clearZoneCanvas();
+      let promise1 = new Promise((resolve, reject) => {
+        let params = {
+          data: {
+            Filters: `not RoomID isNull;ObjectType = '${this.space}';buildingId = '${this.buildingData[0]}';floorId = '${this.buildingData[1]}'`,
+            Orders: "RoomLocalName desc"
+          },
+          ShaftId: this.$route.query.ShaftId
+        };
+        shaftSpaceQuery(params, res => {
+          resolve(res)
+        })
+      });
+      let promise2 = new Promise((resolve, reject) => {
+        let pa = {
+          zone: this.space,
+          data: {
+            Filters: ``,
+            Orders: "createTime desc, RoomID asc",
+            PageSize: 1000
+          }
+        }
+        if (this.buildingData.length && this.buildingData.length > 1) {
+          pa.data.Filters = `BuildingId='${this.buildingData[0]}';FloorId='${this.buildingData[1]}'`
+        }
+        queryZone(pa, res => {
+          resolve(res);
+        })
+      })
+      Promise.all([promise1, promise2]).then(values => {
+        let relatedZone = values[0].Content;
+        let zoneData = values[1].Content;
+        this.relatedSpaceIdList = [];
+        relatedZone.map(item => {
+          this.relatedSpaceIdList.push(item.RoomID);
+        })
+        // 所有业务空间
+        this.businessSpaceList = zoneData;
+        // 已关联元空间的业务空间
+        this.BSPRelaISPList = [];
+        zoneData.map(t => {
+          if (t.Outline && t.Outline.length) {
+            this.BSPRelaISPList.push(t)
+          }
+        })
+        // 绘制业务空间
+        let tempArr = this.BSPRelaISPList.map((t, i) => {
+          let item = {
+            RoomLocalName: t.RoomLocalName,
+            OutLine: t.Outline,
+            RoomID: t.RoomID,
+            Color: colorArr[i % colorArr.length],
+          }
+          return item;
+        })
+        this.scene.zoneList = [];
+        this.scene.addZoneList(tempArr);
+        this.scene.click(this, this.canvasClick);
+        this.zoneList = this.scene.zoneList;
+        this.scene.zoneList.map(t => {
+          t.selected = false;
+          if (this.relatedSpaceIdList.indexOf(t.data.RoomID) != -1) {
+            // t.selected = true;
+            t.highLightFlag = true;
+          }
+        })
+        this.canvasLoading = false;
+      })
+    },
+    // canvas点击事件
+    canvasClick(item, event) {
+      if (item.selectable) {
+        if (this.selectAble) {
+          if (this.relatedSpaceIdList.indexOf(item.data.RoomID) != -1) {
+            this.relatedSpaceIdList = this.relatedSpaceIdList.filter(t => { return t != item.data.RoomID });
+          }
+          else {
+            this.relatedSpaceIdList.push(item.data.RoomID);
+          }
+        }
+        else {
+          item.selected = !item.selected;
+        }
+      }
+    },
+    //取消编辑
+    cancelEdit() {
+      this.getBusinessSpace();
+    },
+    //保存编辑
+    saveEdit() {
+      let param = {
+        BuildingId: this.buildingData[0],
+        FloorId: this.buildingData[1],
+        Type: this.space,
+        data: {
+          ShaftId: this.$route.query.ShaftId,
+          SpaceIdList: this.relatedSpaceIdList
+        }
+      }
+      shaftZoneLink(param, res => {
+        if (res.Result == "success") {
+          this.$message.success("保存成功");
+          this.getBusinessSpace();
+        }
+      })
+    },
+    //是否可点
+    setSelectAble(val) {
+      if (this.scene) {
+        this.selectAble = val && !this.$route.query.onlyRead;
+        if (this.selectAble) {
+          this.scene.zoneList.map(t => {
+            t.highLightFlag = false;
+            t.selected = false;
+            if (this.relatedSpaceIdList.indexOf(t.data.RoomID) != -1) {
+              t.selected = true;
+            }
+          })
+        }
+      }
+    },
+    // 清除canvas
+    clearGraphy() {
+      // debugger
+      this.scene = null;
+      if (this.view) {
+        this.view.scene = null;
+        return
+      }
+      this.view = new FloorView('floorCanvas')
+    },
+    // 清空绘制业务空间
+    clearZoneCanvas() {
+      this.zoneList.map(t => {
+        this.scene.removeItem(t);
+      })
+    },
+    // 适配底图到窗口
+    fit() {
+      this.view.fitSceneToView()
+    },
+    // 缩放
+    scale(val) {
+      if (!this.view) {
+        return;
+      }
+      let scale = this.view.scale;
+      this.view.scaleByPoint(val / scale, this.canvasWidth / 2, this.canvasHeight / 2);
+    },
+    // 保存为png
+    savePng() {
+      this.view.saveImage(`${this.buildingData[1]}.png`, 'png');
+    },
+    // 保存为svg
+    saveSvg() {
+      this.view.saveSceneSvg(`${this.buildingData[1]}.svg`, 6400, 4800);
+    },
+    // 保存json
+    saveJson() {
+      this.view.saveFloorJson(`${this.buildingData[1]}.json`)
+    },
+  },
+  watch: {
+    "view.scale": {
+      handler(n) {
+        if (this.$refs.canvasFun) {
+          this.$refs.canvasFun.sliderVal = n * 10 / this.view.minScale;
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.canvas-actions-box {
+  position: absolute;
+  bottom: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 999;
+}
+.canvas-box {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 196 - 155
src/components/ledger/lib/uploadFiles.vue

@@ -8,166 +8,207 @@
   isShow: 图片的显示
  -->
 <template>
-  <div id="saga-upload">
-    <div id="uploadFile">
-
-      <el-upload
-        v-if="filesArr.length < max"
-        class="upload-file"
-        action
-        :http-request="uploadAndSubmit"
-        drag
-      >
-        <el-button size="small" type="primary" v-if="!readOnly">点击上传</el-button>
-        <div slot="tip" class="el-upload__tip" v-if="!readOnly">请上传文件</div>
-      </el-upload>
-            <div v-if="item && filesArr.length" v-for="(item,index) in filesArr">
-        <el-button type="text" @click="download(item)">{{delFile(item)}}</el-button>
-        <i
-          v-if="!readOnly"
-          class="el-icon-close delete-icon"
-          style="margin-left:10px; cursor:pointer"
-          @click="deleteFile(index,item)"
-        ></i>
-      </div>
-    </div>
+    <div id="saga-upload">
+        <div id="uploadFile">
+
+            <el-upload
+                v-if="filesArr.length < max"
+                class="upload-file"
+                action
+                :show-file-list="showFileList"
+                :http-request="uploadAndSubmit"
+                drag
+            >
+
+                <el-button
+                    size="small"
+                    type="primary"
+                    v-if="!readOnly"
+                >点击上传
+                </el-button>
+                <div
+                    slot="tip"
+                    class="el-upload__tip"
+                    v-if="!readOnly"
+                >请上传文件
+                </div>
+            </el-upload>
+
+            <div
+                v-show="item && filesArr.length"
+                v-for="(item,index) in filesArr"
+            >
+                <el-button
+                    type="text"
+                    @click="download(item)"
+                >{{delFile(item)}}
+                </el-button>
+                <i
+                    v-if="!readOnly"
+                    class="el-icon-close delete-icon"
+                    style="margin-left:10px; cursor:pointer"
+                    @click="deleteFile(index,item)"
+                ></i>
+            </div>
+        </div>
   </div>
 </template>
 
 <script>
-import tools from "@/utils/scan/tools";
-export default {
-  props: {
-    keysArr: {
-      type: [Array, String],
-      default: function () {
-        return []
-      }
-    },
-    readOnly: {
-      type: Boolean,
-      default: false
-    },
-    max: {
-      type: [Number, String],
-      default: 6
-    },
-    defined: null
-  },
-  data() {
-    return {
-      filesArr: []
-    };
-  },
-  created() {
-    let type = typeof (this.keysArr)
-    this.fileFalg()
-  },
-  methods: {
-    //判断是否为空
-    fileFalg() {
-      let type = typeof (this.keysArr)
-      console.log(this.keysArr, "keysAee")
-      if (type == 'string') {
-        this.filesArr = [this.keysArr]
-      } else {
-        this.filesArr = tools.deepCopy(this.keysArr)
-      }
+    import tools from "@/utils/scan/tools";
 
-      if (!this.keysArr) {
-        this.filesArr = []
-      }
-    },
-    //处理地址
-    delFile(name) {
-      console.log(name, "name")
-      return name.length > 20 ? name.substring(0, 20) + "..." : ""
-    },
-
-    resetFile() {
-      this.filesArr = []
-    },
-
-
-    //点击下载
-    download(key) {
-      console.log(key)
-      window.open("/image-service/common/file_get/" + key + "?systemId=dataPlatform")
-    },
-
-    //删除图片
-    deleteFile(i, key) {
-      this.filesArr.splice(i, 1);
-      this.$emit("change", this.filesArr, this.defined);
-    },
-
-    //上传
-    uploadAndSubmit(item) {
-      // var form = document.forms["demoForm"];
-
-      // if (form["file"].files.length > 0) {
-      // 寻找表单域中的 <input type="file" ... /> 标签
-      // var file = form["file"].files[0];
-
-      let file = item.file;
-      // try sending
-      let reader = new FileReader();
-
-      let vm = this;
-
-      let fileType = file.name.split(".");
-      let type = fileType[fileType.length - 1];
-      let key = "&key=" + fileType[0] + file.uid + "." + type
-
-      reader.onloadstart = function () {
-        // 这个事件在读取开始时触发
-      };
-      reader.onprogress = function (p) {
-        // 这个事件在读取进行中定时触发
-      };
-
-      reader.onload = function () {
-        // 这个事件在读取成功结束后触发
-      };
-      reader.onloadend = function () {
-        // 这个事件在读取结束后,无论成功或者失败都会触发
-        if (reader.error) {
-        } else {
-          // document.getElementById("bytesRead").textContent = file.size;
-          // 构造 XMLHttpRequest 对象,发送文件 Binary 数据
-          var xhr = new XMLHttpRequest();
-          xhr.open(
-            /* method */
-            "POST",
-            /* target url */
-            "/image-service/common/file_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true" + key
-            /*, async, default to true */
-          );
-          //xhr.overrideMimeType("application/octet-stream");
-          xhr.send(reader.result);
-          xhr.onreadystatechange = function () {
-            if (xhr.readyState == 4) {
-              console.log(xhr)
-              if (xhr.status == 200) {
-                vm.filesArr.push(
-                  key.split("=")[1]
-                );
-                console.log(vm.filesArr)
-                vm.$emit("change", vm.filesArr, vm.defined);
-              } else {
-                this.$message.error(res.data.ResultMsg)
-              }
+    export default {
+        props: {
+            keysArr: {
+                type: [Array, String],
+                default: function () {
+                    return []
+                }
+            },
+            readOnly: {
+                type: Boolean,
+                default: false
+            },
+            max: {
+                type: [Number, String],
+                default: 6
+            },
+            defined: null,
+            firmDataType: {
+                type: String
+            },
+            information: {
+                type: Object
+            },
+            infoType: {
+                type: String
+            }
+        },
+        data() {
+            return {
+                filesArr: [],
+                isShow: Boolean
+            };
+        },
+        created() {
+            let type = typeof (this.keysArr)
+            this.fileFalg()
+            // this.resetFile()
+        },
+        computed: {
+            showFileList() {
+                if (this.firmDataType === 'dialog') {
+                    this.isShow = false
+                } else {
+                    this.isShow = true
+                }
+                return this.isShow
+            }
+        },
+        methods: {
+            //判断是否为空
+            fileFalg() {
+                let type = typeof (this.keysArr)
+                if (type == 'string') {
+                    this.filesArr = [this.keysArr]
+
+                } else {
+                    this.filesArr = tools.deepCopy(this.keysArr)
+
+                }
+
+                if (!this.keysArr) {
+                    this.filesArr = []
+                }
+            },
+            //处理地址
+            delFile(name) {
+                return name.length > 20 ? name.substring(0, 20) + "..." : name
+            },
+
+            resetFile() {
+                this.filesArr = []
+            },
+
+
+            //点击下载
+            download(key) {
+                console.log(key)
+                window.open("/image-service/common/file_get/" + key + "?systemId=dataPlatform")
+            },
+
+            //删除图片
+            deleteFile(i, key) {
+                this.filesArr.splice(i, 1);
+                this.$emit("change", this.filesArr, this.defined);
+            },
+
+            //上传
+            uploadAndSubmit(item) {
+                // var form = document.forms["demoForm"];
+
+                // if (form["file"].files.length > 0) {
+                // 寻找表单域中的 <input type="file" ... /> 标签
+                // var file = form["file"].files[0];
+
+                let file = item.file;
+                // try sending
+                let reader = new FileReader();
+
+                let vm = this;
+
+                let fileType = file.name.split(".");
+                let type = fileType[fileType.length - 1];
+                let key = "&key=" + fileType[0] + file.uid + "." + type
+
+                reader.onloadstart = function () {
+                    // 这个事件在读取开始时触发
+                };
+                reader.onprogress = function (p) {
+                    // 这个事件在读取进行中定时触发
+                };
+
+                reader.onload = function () {
+                    // 这个事件在读取成功结束后触发
+                };
+                reader.onloadend = function () {
+                    // 这个事件在读取结束后,无论成功或者失败都会触发
+                    if (reader.error) {
+                    } else {
+                        // document.getElementById("bytesRead").textContent = file.size;
+                        // 构造 XMLHttpRequest 对象,发送文件 Binary 数据
+                        var xhr = new XMLHttpRequest();
+                        xhr.open(
+                            /* method */
+                            "POST",
+                            /* target url */
+                            "/image-service/common/file_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true" + key
+                            /*, async, default to true */
+                        );
+                        //xhr.overrideMimeType("application/octet-stream");
+                        xhr.send(reader.result);
+                        xhr.onreadystatechange = function () {
+                            if (xhr.readyState == 4) {
+                                console.log(xhr)
+                                if (xhr.status == 200) {
+                                    vm.filesArr.push(
+                                        key.split("=")[1]
+                                    );
+                                    vm.$emit("change", vm.filesArr, vm.defined);
+                                } else {
+                                    this.$message.error(res.data.ResultMsg)
+                                }
+                            }
+                        };
+                    }
+                };
+                reader.readAsArrayBuffer(file);
+            }
+        },
+        watch: {
+            keysArr: function (val) {
+                this.fileFalg()
             }
-          };
-        }
-      };
-      reader.readAsArrayBuffer(file);
-    }
-  },
-  watch: {
-    keysArr: function (val) {
-      this.fileFalg()
-    }
   }
 };
 </script>
@@ -204,4 +245,4 @@ export default {
     }
   }
 }
-</style>
+</style>

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

@@ -34,7 +34,7 @@
           :accept="accept"
           action
           drag
-          style="position: relation"
+          style="position: relative"
         >
           <i class="el-icon-plus avatar-uploader-icon"></i>
         </el-upload>

+ 281 - 0
src/components/point/dynamicdata/buildRules.vue

@@ -0,0 +1,281 @@
+
+<template>
+  <div id="equipRules">
+    <!-- 查询条件 -->
+    <div class="query-area">
+      <el-row>
+        <el-col :span="22">
+          <el-form ref="form" :model="form" :inline="true">
+            <el-row>
+              <div class="query-item special" style="margin-bottom:20px;">
+                <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryTableData">
+                  <i slot="suffix" class="el-input__icon el-icon-search" @click="queryTableData"></i>
+                </el-input>
+              </div>
+              <div class="query-item">
+                <label style="padding-right:9px">数据源</label>
+                <dataSource :Related="null" @change="changeDataSource" :typeName="typeName"></dataSource>
+              </div>
+              <!-- <div class="query-item">
+                <dictionary-device @change="changeDictionary" :Related="null" :typeName="typeName"></dictionary-device>
+              </div> -->
+              <div class="query-item">
+                <label style="padding-right:9px">位置标签</label>
+                <locationFlag :Related="null" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+              </div>
+            </el-row>
+          </el-form>
+        </el-col>
+        <el-col :span="2">
+          <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
+            <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending">
+            </el-button>
+          </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip>
+        </el-col>
+      </el-row>
+    </div>
+    <el-row>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">点位表中出现的所有{{typeName}}</el-col>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">对应物理世界中的{{typeName}}实例</el-col>
+    </el-row>
+    <!-- 列表区域 -->
+    <div class="table-area">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip min-width="200"></el-table-column>
+        <el-table-column prop="LocationFlag" label="位置标签" min-width="200">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+              <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column prop="Datasource" label="数据源" show-overflow-tooltip min-width="100"></el-table-column>
+        <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip min-width="100"></el-table-column> -->
+        <el-table-column prop="ObjectLocalName" :label="`${typeName}实例`" show-overflow-tooltip min-width="400" class-name="td-bl"></el-table-column>
+        <!-- <el-table-column label="所在建筑楼层" min-width="300">
+          <template slot-scope="scope">
+            <el-tooltip
+              :content="scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''"
+              placement="top">
+              <div class="tool-tip">
+                {{scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''}}
+              </div>
+            </el-tooltip>
+          </template>
+        </el-table-column> -->
+        <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" 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
+                :disabled="isPending||scope.row.Related=='False'" icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <!-- 分页 -->
+    <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>
+    <!-- 清除对应关系弹窗 -->
+    <del-relation-dialog ref="del" @refresh="refresh" :typeName="'build'"></del-relation-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import { mapGetters, mapActions } from "vuex";
+import applyRulesDialog from "@/components/point/dynamicdata/applyRulesDialog";
+import delRelationDialog from "@/components/point/dynamicdata/delRelationDialog";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import equipRules from "@/components/point/dynamicdata/equipRules";
+import {
+  dynamicClashConfirm,
+  dynamicExecute,
+  dynamicQuery,
+  dynamicQueryPoint,
+  dynamicPointTypeList
+} from "@/api/scan/request";
+export default {
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      sourceList: [], //数据源
+      DynEquipList: [], //数据字典部件类型
+      LocFlagList: [], //位置标签
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [] //数据源
+      }, //查询条件
+      loading: false, //列表loading
+      autoLoading: false, //自动对应实例
+    };
+  },
+  components: {
+    applyRulesDialog,
+    delRelationDialog,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  props: {
+    typeName: {},
+    isPending: {
+      default: false
+    }
+  },
+  created() {
+    this.init();
+  },
+  mounted() { },
+  methods: {
+    //获取查询条件-提示信息
+    init() {
+      this.getTableData()
+    },
+    //清除对应关系
+    handleDelete(index, row) {
+      this.$refs.del.showDialog(row);
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    //跳转至填充对应规则
+    toAddRelation() {
+      this.$router.push({ path: "buildRela", query: { typeName: this.typeName } });
+    },
+    //获取表格数据
+    getTableData() {
+      let param = {
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.loading = true;
+      // 查询对应关系(P1)
+      dynamicQuery(param, res => {
+        this.loading = false;
+        this.tableData = res.Content;
+        this.page.total = res.PageSize < 50 ? res.PageSize : res.Total;
+      });
+    },
+    //刷新列表
+    refresh() {
+      this.page.pageNumber = 1;
+      this.$emit('refresh', this.typeName);
+      this.getTableData();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.page.pageNumber = 1;
+      this.form.SubTypeName = val;
+      this.getTableData();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.page.pageNumber = 1;
+      this.form.Datasource = val;
+      this.getTableData();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.page.pageNumber = 1;
+      this.form.LocationFlag = val;
+      this.getTableData();
+    },
+    //查询列表
+    queryTableData() {
+      this.page.pageNumber = 1;
+      this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela', 'build');
+    }
+  },
+  watch: {
+    projectId() {
+      this.init();
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+#equipRules {
+  height: calc(100% - 54px);
+  /deep/ .text-right {
+    text-align: right;
+  }
+  .query-item {
+    float: left;
+    & + .query-item {
+      margin-left: 10px;
+    }
+  }
+  /deep/ .special .el-input__inner {
+    width: 220px;
+  }
+  /deep/ .table-area {
+    width: 100%;
+    height: calc(100% - 71px);
+    margin-bottom: 10px;
+    td div {
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+    .td-bl {
+      border-left: 1px solid #ebeef5;
+    }
+    .tool-tip {
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+}
+</style>
+

+ 19 - 1
src/components/point/dynamicdata/delRelationDialog.vue

@@ -110,7 +110,25 @@ export default {
           { label: '对象实例名称', prop: "ObjectLocalName" },
           { label: '对象本地编码', prop: "ObjectLocalCode" },
           { label: '所在建筑楼层', prop: "BuildLocalName" },
-        ]
+        ],
+        build: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" }
+        ],
+        floor: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象顺序号', prop: "ObjectLocalCode" },
+          { label: '所在建筑', prop: "BuildLocalName" },
+        ],
+        tenant: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
+          { label: '所在业务空间', prop: "BuildLocalName" },
+        ],
+        project: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
+        ],
       },
       rightTableHeader: []
     };

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

@@ -233,7 +233,7 @@ export default {
     },
     //自动对应实例
     autoGroupRela() {
-      this.$emit('autoGroupRela','equip');
+      this.$emit('autoGroupRela', 'equip');
     }
   },
   watch: {

+ 289 - 0
src/components/point/dynamicdata/floorRules.vue

@@ -0,0 +1,289 @@
+
+<template>
+  <div id="equipRules">
+    <!-- 查询条件 -->
+    <div class="query-area">
+      <el-row>
+        <el-col :span="22">
+          <el-form ref="form" :model="form" :inline="true">
+            <el-row>
+              <div class="query-item special" style="margin-bottom:20px;">
+                <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryTableData">
+                  <i slot="suffix" class="el-input__icon el-icon-search" @click="queryTableData"></i>
+                </el-input>
+              </div>
+              <div class="query-item">
+                <label style="padding-right:9px">数据源</label>
+                <dataSource :Related="null" @change="changeDataSource" :typeName="typeName"></dataSource>
+              </div>
+              <!-- <div class="query-item">
+                <dictionary-device @change="changeDictionary" :Related="null" :typeName="typeName"></dictionary-device>
+              </div> -->
+              <div class="query-item">
+                <label style="padding-right:9px">位置标签</label>
+                <locationFlag :Related="null" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+              </div>
+            </el-row>
+          </el-form>
+        </el-col>
+        <el-col :span="2">
+          <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
+            <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending">
+            </el-button>
+          </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip>
+        </el-col>
+      </el-row>
+    </div>
+    <el-row>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">点位表中出现的所有{{typeName}}</el-col>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">对应物理世界中的{{typeName}}实例</el-col>
+    </el-row>
+    <!-- 列表区域 -->
+    <div class="table-area">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip min-width="200"></el-table-column>
+        <el-table-column prop="LocationFlag" label="位置标签" min-width="200">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+              <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column prop="Datasource" label="数据源" show-overflow-tooltip min-width="100"></el-table-column>
+        <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip min-width="100"></el-table-column> -->
+        <el-table-column prop="ObjectLocalName" :label="`${typeName}实例`" show-overflow-tooltip min-width="100" class-name="td-bl"></el-table-column>
+        <el-table-column :label="`${typeName}顺序号`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <el-tooltip :content="(scope.row.ObjectSequenceID&&scope.row.ObjectSequenceID!='null')?scope.row.ObjectSequenceID:''" placement="top">
+              <div class="tool-tip">
+                {{(scope.row.ObjectSequenceID&&scope.row.ObjectSequenceID!='null')?scope.row.ObjectSequenceID:''}}</div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column label="所属建筑" min-width="200">
+          <template slot-scope="scope">
+            <el-tooltip
+              :content="scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''"
+              placement="top">
+              <div class="tool-tip">
+                {{scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''}}
+              </div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" 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
+                :disabled="isPending||scope.row.Related=='False'" icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <!-- 分页 -->
+    <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>
+    <!-- 清除对应关系弹窗 -->
+    <del-relation-dialog ref="del" @refresh="refresh" :typeName="'floor'"></del-relation-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import { mapGetters, mapActions } from "vuex";
+import applyRulesDialog from "@/components/point/dynamicdata/applyRulesDialog";
+import delRelationDialog from "@/components/point/dynamicdata/delRelationDialog";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import equipRules from "@/components/point/dynamicdata/equipRules";
+import {
+  dynamicClashConfirm,
+  dynamicExecute,
+  dynamicQuery,
+  dynamicQueryPoint,
+  dynamicPointTypeList
+} from "@/api/scan/request";
+export default {
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      sourceList: [], //数据源
+      DynEquipList: [], //数据字典部件类型
+      LocFlagList: [], //位置标签
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [] //数据源
+      }, //查询条件
+      loading: false, //列表loading
+      autoLoading: false, //自动对应实例
+    };
+  },
+  components: {
+    applyRulesDialog,
+    delRelationDialog,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  props: {
+    typeName: {},
+    isPending: {
+      default: false
+    }
+  },
+  created() {
+    this.init();
+  },
+  mounted() { },
+  methods: {
+    //获取查询条件-提示信息
+    init() {
+      this.getTableData()
+    },
+    //清除对应关系
+    handleDelete(index, row) {
+      this.$refs.del.showDialog(row);
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    //跳转至填充对应规则
+    toAddRelation() {
+      this.$router.push({ path: "floorRela", query: { typeName: this.typeName } });
+    },
+    //获取表格数据
+    getTableData() {
+      let param = {
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.loading = true;
+      // 查询对应关系(P1)
+      dynamicQuery(param, res => {
+        this.loading = false;
+        this.tableData = res.Content;
+        this.page.total = res.PageSize < 50 ? res.PageSize : res.Total;
+      });
+    },
+    //刷新列表
+    refresh() {
+      this.page.pageNumber = 1;
+      this.$emit('refresh', this.typeName);
+      this.getTableData();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.page.pageNumber = 1;
+      this.form.SubTypeName = val;
+      this.getTableData();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.page.pageNumber = 1;
+      this.form.Datasource = val;
+      this.getTableData();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.page.pageNumber = 1;
+      this.form.LocationFlag = val;
+      this.getTableData();
+    },
+    //查询列表
+    queryTableData() {
+      this.page.pageNumber = 1;
+      this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela', 'floor');
+    }
+  },
+  watch: {
+    projectId() {
+      this.init();
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+#equipRules {
+  height: calc(100% - 54px);
+  /deep/ .text-right {
+    text-align: right;
+  }
+  .query-item {
+    float: left;
+    & + .query-item {
+      margin-left: 10px;
+    }
+  }
+  /deep/ .special .el-input__inner {
+    width: 220px;
+  }
+  /deep/ .table-area {
+    width: 100%;
+    height: calc(100% - 71px);
+    margin-bottom: 10px;
+    td div {
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+    .td-bl {
+      border-left: 1px solid #ebeef5;
+    }
+    .tool-tip {
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+}
+</style>
+

+ 25 - 5
src/components/point/dynamicdata/historyDialog.vue

@@ -7,7 +7,8 @@
           <el-table-column v-for="item in showLeftHeader" :label="item.label" align="right" :key="item.prop">
             <template slot-scope="scope">
               <div v-for="t in scope.row.leftList" :key="t.id">
-                <el-tooltip :content="t[item.prop]&&t[item.prop].length?t[item.prop].toString():''" placement="top" :disabled="!(t[item.prop]&&t[item.prop].length)">
+                <el-tooltip :content="t[item.prop]&&t[item.prop].length?t[item.prop].toString():''" placement="top"
+                  :disabled="!(t[item.prop]&&t[item.prop].length)">
                   <div>{{t[item.prop]&&t[item.prop].length?t[item.prop].toString():'--'}}</div>
                 </el-tooltip>
               </div>
@@ -21,7 +22,8 @@
                 <div v-if="item.prop=='BuildLocalName'">
                   <el-tooltip
                     :content="t.BuildLocalName&&t.BuildLocalName!='null'?t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:t.BuildLocalName:''"
-                    placement="top" :disabled="!(t.BuildLocalName&&t.BuildLocalName!='null'?t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:t.BuildLocalName:'')">
+                    placement="top"
+                    :disabled="!(t.BuildLocalName&&t.BuildLocalName!='null'?t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:t.BuildLocalName:'')">
                     <div>
                       {{t.BuildLocalName&&t.BuildLocalName!='null'?t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:t.BuildLocalName:'--'}}
                     </div>
@@ -62,7 +64,7 @@ export default {
       showLeftHeader: [
         { label: '数据源', prop: 'Datasource' },
         { label: '位置标签', prop: 'LocationFlag' },
-        { label: '设备标识', prop: 'EquipmentMark' }
+        { label: '对象标识', prop: 'EquipmentMark' }
       ],
       tableHeader: {
         equip: [
@@ -82,11 +84,29 @@ export default {
           { label: '对象实例名称', prop: 'ObjectLocalName' },
           { label: '对象本地编码', prop: 'ObjectLocalCode' }
         ],
-        space:[
+        space: [
           { label: '对象实例名称', prop: "ObjectLocalName" },
           { label: '对象本地编码', prop: "ObjectLocalCode" },
           { label: '所在建筑楼层', prop: "BuildLocalName" },
-        ]
+        ],
+        build: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" }
+        ],
+        floor: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象顺序号', prop: "ObjectLocalCode" },
+          { label: '所在建筑', prop: "BuildLocalName" },
+        ],
+        tenant: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
+          { label: '所在业务空间', prop: "BuildLocalName" },
+        ],
+        project: [
+          { label: '对象实例名称', prop: "ObjectLocalName" },
+          { label: '对象本地编码', prop: "ObjectLocalCode" },
+        ],
       }, //所有类型列表头部
       showRightHeader: [], //实际显示的列表头部
     };

+ 8 - 2
src/components/point/dynamicdata/locationCascader.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-cascader placeholder="全部" :options="LocationList" v-model="value" filterable size="small" @change="changeCascader" change-on-select
+  <el-cascader placeholder="全部" :options="LocationList" v-model="value" filterable size="small" @change="changeCascader" :change-on-select="!isFloor"
     :props="props" clearable class="location"></el-cascader>
 </template>
 <script>
@@ -23,7 +23,10 @@ export default {
   },
   props: {
     Related: {},
-    typeName: {}
+    typeName: {},
+    isFloor: {
+      default: false
+    }
   },
   computed: {
     ...mapGetters("layout", ["projectId"])
@@ -36,6 +39,9 @@ export default {
         //添加未明确对象
         this.LocationList = this.delNullItems(this.LocationList)
         this.LocationList.map(item => {
+          if (this.isFloor) {
+            delete item.List;
+          }
           if (item.List) {
             item.List.map(child => {
               if (child.List) {

+ 287 - 0
src/components/point/dynamicdata/projectRules.vue

@@ -0,0 +1,287 @@
+
+<template>
+  <div id="equipRules">
+    <!-- 查询条件 -->
+    <div class="query-area">
+      <el-row>
+        <el-col :span="22">
+          <el-form ref="form" :model="form" :inline="true">
+            <el-row>
+              <div class="query-item special" style="margin-bottom:20px;">
+                <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryTableData">
+                  <i slot="suffix" class="el-input__icon el-icon-search" @click="queryTableData"></i>
+                </el-input>
+              </div>
+              <div class="query-item">
+                <label style="padding-right:9px">数据源</label>
+                <dataSource :Related="null" @change="changeDataSource" :typeName="typeName"></dataSource>
+              </div>
+              <!-- <div class="query-item">
+                <dictionary-device @change="changeDictionary" :Related="null" :typeName="typeName"></dictionary-device>
+              </div> -->
+              <div class="query-item">
+                <label style="padding-right:9px">位置标签</label>
+                <locationFlag :Related="null" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+              </div>
+            </el-row>
+          </el-form>
+        </el-col>
+        <el-col :span="2">
+          <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
+            <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending">
+            </el-button>
+          </el-tooltip>
+          <!-- <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip> -->
+        </el-col>
+      </el-row>
+    </div>
+    <el-row>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">点位表中出现的所有{{typeName}}</el-col>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">对应物理世界中的{{typeName}}实例</el-col>
+    </el-row>
+    <!-- 列表区域 -->
+    <div class="table-area">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip min-width="200"></el-table-column>
+        <el-table-column prop="LocationFlag" label="位置标签" min-width="200">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+              <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column prop="Datasource" label="数据源" show-overflow-tooltip min-width="100"></el-table-column>
+        <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip min-width="100"></el-table-column> -->
+        <el-table-column prop="ObjectLocalName" :label="`${typeName}实例`" show-overflow-tooltip min-width="400" class-name="td-bl"></el-table-column>
+        <!-- <el-table-column label="所在建筑楼层" min-width="300">
+          <template slot-scope="scope">
+            <el-tooltip
+              :content="scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''"
+              placement="top">
+              <div class="tool-tip">
+                {{scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''}}
+              </div>
+            </el-tooltip>
+          </template>
+        </el-table-column> -->
+        <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" 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
+                :disabled="isPending||scope.row.Related=='False'" icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <!-- 分页 -->
+    <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>
+    <!-- 清除对应关系弹窗 -->
+    <del-relation-dialog ref="del" @refresh="refresh" :typeName="'space'"></del-relation-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import { mapGetters, mapActions } from "vuex";
+import applyRulesDialog from "@/components/point/dynamicdata/applyRulesDialog";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import delRelationDialog from "@/components/point/dynamicdata/delRelationDialog";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import equipRules from "@/components/point/dynamicdata/equipRules";
+import {
+  dynamicClashConfirm,
+  dynamicExecute,
+  dynamicQuery,
+  dynamicQueryPoint,
+  dynamicPointTypeList,
+  dynamicPendingobjs,
+  dynamicCreateRelation,
+  dynamicDeleteRelation
+} from "@/api/scan/request";
+export default {
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      sourceList: [], //数据源
+      DynEquipList: [], //数据字典部件类型
+      LocFlagList: [], //位置标签
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [] //数据源
+      }, //查询条件
+      loading: false, //列表loading
+      autoLoading: false, //自动对应实例
+      RtableData: {}, //当前项目实例
+      deleteRelationVis: false, // 删除弹窗
+      row: {}, // 删除时,选中的行
+    };
+  },
+  components: {
+    applyRulesDialog,
+    dictionaryDevice,
+    dataSource,
+    locationFlag,
+    delRelationDialog
+  },
+  props: {
+    typeName: {},
+    isPending: {
+      default: false
+    }
+  },
+  created() {
+    this.init();
+  },
+  mounted() { },
+  methods: {
+    //获取查询条件-提示信息
+    init() {
+      this.getTableData();
+    },
+    //清除对应关系
+    handleDelete(index, row) {
+      this.$refs.del.showDialog(row);
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    //跳转至填充对应规则
+    toAddRelation() {
+      this.$router.push({ path: "projectRela", query: { typeName: this.typeName } });
+    },
+    //获取表格数据
+    getTableData() {
+      let param = {
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.loading = true;
+      // 查询对应关系(P1)
+      dynamicQuery(param, res => {
+        this.loading = false;
+        this.tableData = res.Content;
+        this.page.total = res.PageSize < 50 ? res.PageSize : res.Total;
+      });
+    },
+    //刷新列表
+    refresh() {
+      this.page.pageNumber = 1;
+      this.$emit('refresh', this.typeName);
+      this.getTableData();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.page.pageNumber = 1;
+      this.form.SubTypeName = val;
+      this.getTableData();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.page.pageNumber = 1;
+      this.form.Datasource = val;
+      this.getTableData();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.page.pageNumber = 1;
+      this.form.LocationFlag = val;
+      this.getTableData();
+    },
+    //查询列表
+    queryTableData() {
+      this.page.pageNumber = 1;
+      this.getTableData();
+    },
+    //自动对应实例
+    // autoGroupRela() {
+    //   this.$emit('autoGroupRela','project');
+    // }
+  },
+  watch: {
+    projectId() {
+      this.init();
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+#equipRules {
+  height: calc(100% - 54px);
+  /deep/ .text-right {
+    text-align: right;
+  }
+  .query-item {
+    float: left;
+    & + .query-item {
+      margin-left: 10px;
+    }
+  }
+  /deep/ .special .el-input__inner {
+    width: 220px;
+  }
+  /deep/ .table-area {
+    width: 100%;
+    height: calc(100% - 71px);
+    margin-bottom: 10px;
+    td div {
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+    .td-bl {
+      border-left: 1px solid #ebeef5;
+    }
+    .tool-tip {
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+}
+</style>
+

+ 278 - 0
src/components/point/dynamicdata/tenantRules.vue

@@ -0,0 +1,278 @@
+
+<template>
+  <div id="equipRules">
+    <!-- 查询条件 -->
+    <div class="query-area">
+      <el-row>
+        <el-col :span="22">
+          <el-form ref="form" :model="form" :inline="true">
+            <el-row>
+              <div class="query-item special" style="margin-bottom:20px;">
+                <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryTableData">
+                  <i slot="suffix" class="el-input__icon el-icon-search" @click="queryTableData"></i>
+                </el-input>
+              </div>
+              <div class="query-item">
+                <label style="padding-right:9px">数据源</label>
+                <dataSource :Related="null" @change="changeDataSource" :typeName="typeName"></dataSource>
+              </div>
+              <!-- <div class="query-item">
+                <dictionary-device @change="changeDictionary" :Related="null" :typeName="typeName"></dictionary-device>
+              </div> -->
+              <div class="query-item">
+                <label style="padding-right:9px">位置标签</label>
+                <locationFlag :Related="null" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+              </div>
+            </el-row>
+          </el-form>
+        </el-col>
+        <el-col :span="2">
+          <el-tooltip class="item" effect="dark" :content="`填充${typeName}标识与实例对应规则`" placement="left">
+            <el-button size="small" type="primary" @click="toAddRelation" icon="el-icon-edit-outline" style="float:right;" :disabled="isPending"></el-button>
+          </el-tooltip>
+          <el-tooltip class="item" effect="dark" :content="`根据${typeName}标识自动填充实例`" placement="left">
+            <el-button size="small" type="primary" @click="autoGroupRela" :icon="autoLoading?'iconfont icon-jiazai':'iconfont icon-zidong'"
+              style="float:right;padding:7px 14px;margin-right:10px;" :disabled="autoLoading"></el-button>
+          </el-tooltip>
+        </el-col>
+      </el-row>
+    </div>
+    <el-row>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">点位表中出现的所有{{typeName}}</el-col>
+      <el-col :span="12" style="padding-left:10px;font-size:13px;border-left:2px solid #000;">对应物理世界中的{{typeName}}实例</el-col>
+    </el-row>
+    <!-- 列表区域 -->
+    <div class="table-area">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip min-width="200"></el-table-column>
+        <el-table-column prop="LocationFlag" label="位置标签" min-width="200">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+              <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column prop="Datasource" label="数据源" show-overflow-tooltip min-width="100"></el-table-column>
+        <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip min-width="100"></el-table-column> -->
+        <el-table-column prop="ObjectLocalName" :label="`${typeName}实例`" show-overflow-tooltip min-width="100" class-name="td-bl"></el-table-column>
+        <el-table-column label="所在业务空间" min-width="300">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''"
+              placement="top">
+              <div class="tool-tip">{{scope.row.BuildLocalName?scope.row.FloorLocalName?scope.row.BuildLocalName+'-'+scope.row.FloorLocalName:scope.row.BuildLocalName:''}}
+              </div>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" 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 :disabled="isPending||scope.row.Related=='False'"
+                icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <!-- 分页 -->
+    <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>
+    <!-- 清除对应关系弹窗 -->
+    <del-relation-dialog ref="del" @refresh="refresh" :typeName="'tenant'"></del-relation-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import { mapGetters, mapActions } from "vuex";
+import applyRulesDialog from "@/components/point/dynamicdata/applyRulesDialog";
+import delRelationDialog from "@/components/point/dynamicdata/delRelationDialog";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import equipRules from "@/components/point/dynamicdata/equipRules";
+import {
+  dynamicClashConfirm,
+  dynamicExecute,
+  dynamicQuery,
+  dynamicQueryPoint,
+  dynamicPointTypeList
+} from "@/api/scan/request";
+export default {
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      sourceList: [], //数据源
+      DynEquipList: [], //数据字典部件类型
+      LocFlagList: [], //位置标签
+      tableData: [], //列表数据
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [] //数据源
+      }, //查询条件
+      loading: false, //列表loading
+      autoLoading: false, //自动对应实例
+    };
+  },
+  components: {
+    applyRulesDialog,
+    delRelationDialog,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  props: {
+    typeName: {},
+    isPending: {
+      default: false
+    }
+  },
+  created() {
+    this.init();
+  },
+  mounted() { },
+  methods: {
+    //获取查询条件-提示信息
+    init() {
+      this.getTableData()
+    },
+    //清除对应关系
+    handleDelete(index, row) {
+      this.$refs.del.showDialog(row);
+    },
+    //改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    //改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    //跳转至填充对应规则
+    toAddRelation() {
+      this.$router.push({ path: "tenantRela", query: { typeName: this.typeName } });
+    },
+    //获取表格数据
+    getTableData() {
+      let param = {
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.loading = true;
+      // 查询对应关系(P1)
+      dynamicQuery(param, res => {
+        this.loading = false;
+        this.tableData = res.Content;
+        this.page.total = res.PageSize < 50 ? res.PageSize : res.Total;
+      });
+    },
+    //刷新列表
+    refresh() {
+      this.page.pageNumber = 1;
+      this.$emit('refresh', this.typeName);
+      this.getTableData();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.page.pageNumber = 1;
+      this.form.SubTypeName = val;
+      this.getTableData();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.page.pageNumber = 1;
+      this.form.Datasource = val;
+      this.getTableData();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.page.pageNumber = 1;
+      this.form.LocationFlag = val;
+      this.getTableData();
+    },
+    //查询列表
+    queryTableData() {
+      this.page.pageNumber = 1;
+      this.getTableData();
+    },
+    //自动对应实例
+    autoGroupRela() {
+      this.$emit('autoGroupRela','tenant');
+    }
+  },
+  watch: {
+    projectId() {
+      this.init();
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+#equipRules {
+  height: calc(100% - 54px);
+  /deep/ .text-right {
+    text-align: right;
+  }
+  .query-item {
+    float: left;
+    & + .query-item {
+      margin-left: 10px;
+    }
+  }
+  /deep/ .special .el-input__inner {
+    width: 220px;
+  }
+  /deep/ .table-area {
+    width: 100%;
+    height: calc(100% - 71px);
+    margin-bottom: 10px;
+    td div {
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+    .td-bl {
+      border-left: 1px solid #ebeef5;
+    }
+    .tool-tip {
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+}
+</style>
+

+ 6 - 0
src/fetch/point_http.js

@@ -318,6 +318,12 @@ export function uploadPointFile(param, success) {
     return post(`${point}/point/${param.type}/point-import`, data, success)
 }
 
+//上传2
+export function uploadPointFile2(param, success) {
+    let data = param.data
+    return post(`${point}/point/${param.type}/point-import2`, data, success)
+}
+
 //根据id批量删除对应关系
 export function deleteRelationList(param, success) {
     let data = param

+ 1 - 0
src/framework/layout/layout-store.js

@@ -79,6 +79,7 @@ export default {
             state.projects.map((item) => {
                 if (item.id == val) {
                     state.secret = item.pwd
+                    localStorage.setItem('secret', item.pwd)
                 }
             })
         }

+ 2 - 2
src/main.js

@@ -24,7 +24,7 @@ import componentsPlugin from '@/framework/plugins/components'
 Vue.use(componentsPlugin)
 
 Vue.config.productionTip = false
-
+Vue.config.devtools = true;
 /* eslint-disable no-new */
 new Vue({
     el: '#app',
@@ -32,4 +32,4 @@ new Vue({
     store,
     components: { App },
     template: '<App/>'
-})
+})

+ 55 - 4
src/router/system.js

@@ -34,6 +34,10 @@ import equipRela from '@/views/point/dynamicdata/addRelation/equipRela'
 import partsRela from '@/views/point/dynamicdata/addRelation/partsRela'
 import systemRela from '@/views/point/dynamicdata/addRelation/systemRela'
 import spaceRela from '@/views/point/dynamicdata/addRelation/spaceRela'
+import buildRela from '@/views/point/dynamicdata/addRelation/buildRela'
+import floorRela from '@/views/point/dynamicdata/addRelation/floorRela'
+import tenantRela from '@/views/point/dynamicdata/addRelation/tenantRela'
+import projectRela from '@/views/point/dynamicdata/addRelation/projectRela'
 
 /** 扫楼作业 */
 import buildTask from '@/views/data_admin/buildTask'
@@ -44,6 +48,8 @@ import buildAssets from '@/views/data_admin/buildAssets'
 import buildLog from '@/views/data_admin/buildLog'
 import buildData from '@/views/data_admin/buildData'
 import buildGraphy from '@/views/data_admin/buildGraphy'
+import updatePointZone from '@/views/data_admin/buildGraphy/updatePointZone'
+import createPointZone from '@/views/data_admin/buildGraphy/createPointZone'
 
 /**  台账管理 */
 import systemLedger from '@/views/ledger/system'
@@ -83,7 +89,8 @@ import spaceLedger from '@/views/screen/splitScreen/spaceledger'
 import integrateResults from '@/views/screen/splitScreen/integrateresults'
 
 /**  业务空间数据导入工具 */
-import dataUtil from '@/views/business_space/dataUtil'
+import dataUtil from '@/views/business_space/dataUtil/index'
+import dataUtil2 from '@/views/business_space/dataUtil/index2'
 
 /**市场及商务 */
 const OwnerManage = () =>
@@ -102,7 +109,15 @@ export default [{
     { path: '/auth', name: 'auth', component: auth },
     { path: '/noUser', name: 'noUser', component: noUser },
     // 业务空间数据导入工具
-    { path: '/dataUtil', name: 'dataUtil', component: LayoutMain, children: [{ path: 'index', component: dataUtil }] },
+    {
+        path: '/dataUtil',
+        name: 'dataUtil',
+        component: LayoutMain,
+        children: [
+            { path: 'index', component: dataUtil },
+            { path: 'index2', component: dataUtil2 }
+        ]
+    },
     // 辅助屏
     {
         path: '/splitScreen',
@@ -205,6 +220,30 @@ export default [{
                 meta: { keepAlive: false, breadcrumbs: [{ label: '系统集成', path: '/point/pointsetting' }, { label: '配置动参从点位取值', path: '/point/dynamicdata' }, { label: '处理未对应实例对象标识' }] }
             },
             {
+                path: 'buildRela',
+                name: 'buildRela',
+                component: buildRela,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '系统集成', path: '/point/pointsetting' }, { label: '配置动参从点位取值', path: '/point/dynamicdata' }, { label: '处理未对应实例对象标识' }] }
+            },
+            {
+                path: 'floorRela',
+                name: 'floorRela',
+                component: floorRela,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '系统集成', path: '/point/pointsetting' }, { label: '配置动参从点位取值', path: '/point/dynamicdata' }, { label: '处理未对应实例对象标识' }] }
+            },
+            {
+                path: 'tenantRela',
+                name: 'tenantRela',
+                component: tenantRela,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '系统集成', path: '/point/pointsetting' }, { label: '配置动参从点位取值', path: '/point/dynamicdata' }, { label: '处理未对应实例对象标识' }] }
+            },
+            {
+                path: 'projectRela',
+                name: 'projectRela',
+                component: projectRela,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '系统集成', path: '/point/pointsetting' }, { label: '配置动参从点位取值', path: '/point/dynamicdata' }, { label: '处理未对应实例对象标识' }] }
+            },
+            {
                 path: 'objectdata',
                 name: 'objectData',
                 component: objectData,
@@ -272,6 +311,18 @@ export default [{
                 name: 'buildLog',
                 component: buildLog,
                 meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '扫楼日志查看' }] }
+            },
+            {
+                path: 'updatePointZone',
+                name: 'updatePointZone',
+                component: updatePointZone,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场数据整理', path: '/floor/data' }, { label: '位置标签整理', path: '/floor/plan' }, { label: '维护业务空间信息' }] }
+            },
+            {
+                path: 'createPointZone',
+                name: 'createPointZone',
+                component: createPointZone,
+                meta: { keepAlive: false, breadcrumbs: [{ label: '扫楼作业', path: '/floor' }, { label: '现场数据整理', path: '/floor/data' }, { label: '位置标签整理', path: '/floor/plan' }, { label: '创建业务空间' }] }
             }
         ]
     },
@@ -387,7 +438,7 @@ export default [{
                 path: 'relatedSpace',
                 name: 'relatedSpace',
                 component: relatedSpace,
-                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '竖井台账', path: '/ledger/cenotelist' }, { label: '竖井关联的空间' }] }
+                meta: { keepAlive: false, breadcrumbs: [{ label: '台账管理', path: '/ledger/facility' }, { label: '竖井台账', path: '/ledger/cenotelist' }, { label: '竖井关联的业务空间' }] }
             },
             {
                 path: 'rentlist',
@@ -428,7 +479,7 @@ export default [{
     //     component: LayoutMain,
     //     children: [
     //         { path: 'supplier', name: 'supplier', component: supplier, meta: { keepAlive: false, breadcrumbs: [{ label: '厂家库' }] }}
-    //     ] 
+    //     ]
     // },
 
     //业务空间管理

+ 31 - 3
src/store/modules/project.js

@@ -1,9 +1,12 @@
+import { cacheDictionary } from "@/api/scan/request"
 const project_mess = {
     namespaced: true,
     state: {
         datasourceId: "", //数据源id
         protocolType: "", //数据源类型
-        dataName: ""
+        dataName: "",
+        dictionary: [], // 数据字典
+        cacheTime:''
     },
     mutations: {
         set_datasource(state, val) {
@@ -17,12 +20,37 @@ const project_mess = {
         }
     },
     actions: {
-
+        getDictionary({ state }){
+            let pa = ["Project", "Building", "Floor", "Equipment", "GeneralSystem", "Tenant", "Component", "Space"];
+            let firstLevelMap = {
+                Project: 'Pj',
+                Building: 'Bd',
+                Floor: 'Fl',
+                Tenant: 'VOTn',
+                Equipment: 'Eq',
+                GeneralSystem: 'Sy',
+                Space: 'Sp',
+                Component: 'Ec'
+            }
+            return new Promise((resolve,reject) => {
+                cacheDictionary(pa, res => {
+                    state.dictionary = res.Content.map(t => {
+                        t.InfoPointCode = firstLevelMap[t.InfoPointCode];
+                        return t;
+                    });
+                    let date = new Date();
+                    state.cacheTime = `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
+                    resolve(res);
+                })
+            })
+        }
     },
     getters: {
         datasourceId: state => state.datasourceId,
         protocolType: state => state.protocolType,
-        dataName: state => state.dataName
+        dataName: state => state.dataName,
+        dictionary: state => state.dictionary,
+        cacheTime: state => state.cacheTime
     }
 }
 

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

@@ -62,9 +62,12 @@ const text = {
     //四大厂商
     idType: (instance, td, row, col, prop, value, cellProperties) => {
         let html = ''
+        let Manufacturer = instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Manufacturer')?instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Manufacturer'):'空',
+            Brand = instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Brand')?instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Brand'):'空',
+            Specification = instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Specification')?instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Specification'):'空';
         switch (prop){
             case 'DPManufacturerID':
-                html = instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Specification') + '/' + instance.getDataAtRowProp(row,'LedgerParam.EquipManufactor.Brand')
+                html = Manufacturer + '/' + Brand + '/' + Specification
                 break;
             case 'DPSupplierID':
                 html = instance.getDataAtRowProp(row,'LedgerParam.SupplyPurchase.Supplier')

+ 1 - 1
src/utils/handsontable/notShow.js

@@ -305,7 +305,7 @@ const showTools = {
                         DataType: "Str",
                         FirstName: "基本信息",
                         InfoPointCode: "DPManufacturerID",
-                        InfoPointName: "品牌型号",
+                        InfoPointName: "生产厂家/品牌/型号",
                         InputMode: "X",
                         Path: "DPManufacturerID",
                         Priority: "S",

+ 4 - 0
src/utils/scan/tools.js

@@ -533,6 +533,10 @@ tools.setDataForKey = function (data, key, value) {
             if (i == arr.length - 1) {
                 data[arr[i]] = value
             }
+        } else {
+            if (i == arr.length - 1) {
+                data[arr[i]] = ''
+            }
         }
         data = data[arr[i]]
       }

+ 10 - 0
src/utils/spaceColor.js

@@ -0,0 +1,10 @@
+export const colorArr = [
+  "#fed44c",
+  "#3485d6",
+  "#a384fc",
+  "#4caf50",
+  "#ff6316",
+  "#fd8bbe",
+  "#03a9f3",
+  "#ea615b"
+];

+ 161 - 0
src/views/business_space/dataUtil/index2.vue

@@ -0,0 +1,161 @@
+<template>
+  <div class="main-box">
+    <div class="saga-build-mess">
+      <el-button @click="queryZone">导入业务空间BIMLocation</el-button>
+    </div>
+  </div>
+</template>
+<script>
+import {
+  queryZone,
+  updateZone,
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import pako from '@/assets/pako/pako'
+import axios from "axios";
+export default {
+  data() {
+    return {
+      options: [],
+      tabsList: [
+        {
+          "Code": "GeneralZone",
+          "Name": "默认分区",
+          "Rel_type": "99"
+        },
+        {
+          "Name": "供电分区",
+          "Rel_type": "1",
+          "Code": "PowerSupplyZone"
+        },
+        {
+          "Name": "照明分区",
+          "Rel_type": "2",
+          "Code": "LightingZone"
+        },
+        {
+          "Name": "网络分区",
+          "Rel_type": "3",
+          "Code": "NetworkZone"
+        },
+        {
+          "Code": "AirConditioningZone",
+          "Name": "空调分区",
+          "Rel_type": "4"
+        },
+        {
+          "Name": "采暖分区",
+          "Rel_type": "5",
+          "Code": "HeatingZone"
+        },
+        {
+          "Name": "洁净分区",
+          "Rel_type": "6",
+          "Code": "CleanZone"
+        },
+        {
+          "Name": "生活给水分区",
+          "Rel_type": "7",
+          "Code": "DomesticWaterSupplyZone"
+        },
+        {
+          "Code": "FireZone",
+          "Name": "防火分区",
+          "Rel_type": "8"
+        },
+        {
+          "Name": "安防分区",
+          "Rel_type": "9",
+          "Code": "SecurityZone"
+        },
+        {
+          "Name": "租户分区",
+          "Rel_type": "10",
+          "Code": "TenantZone"
+        },
+        {
+          "Name": '功能分区',
+          'Rel_type': '11',
+          "Code": 'FunctionZone'
+        }
+      ],
+    }
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId', 'userId', 'secret'])
+  },
+  methods: {
+    init() { },
+    // 查询该项目下所有的业务空间
+    queryZone() {
+      this.tabsList.map(t => {
+        this.getZone(t.Code, 1, t.Name);
+      })
+    },
+    getZone(Code, PageNumber, Name) {
+      let pa = {
+        data: {
+          PageNumber: PageNumber,
+          PageSize: 1000,
+          Orders: 'RoomID asc'
+        },
+        zone: Code
+      }
+      queryZone(pa, res => {
+        if (res.Total > PageNumber * 1000) {
+          let num = PageNumber + 1
+          console.log(num)
+          this.getZone(Code, num, Name)
+        }
+        let params = {
+          data: {
+            Content: [],
+            Projection: ["BIMLocation"]
+          },
+          zone: Code
+        }
+        res.Content.map(t => {
+          if (t.Outline && t.Outline[0]) {
+            t.BIMLocation = this.getAverageVal(t.Outline);
+            let obj = {
+              RoomID: t.RoomID,
+              BIMLocation: t.BIMLocation
+            }
+            params.data.Content.push(obj);
+          }
+        });
+        if (params.data.Content.length) {
+          updateZone(params, res => {
+            console.log(`${this.projectId},${Name},${params.data.Content.length}条更新完成`);
+          })
+        }
+      })
+    },
+    getAverageVal(Outline) {
+      let X = 0, Y = 0, Z = 0, len = 0;
+      Outline.map(t => {
+        if (t[0]) {
+          t[0].map(item => {
+            X += item.X;
+            Y += item.Y;
+            Z += item.Z;
+          })
+          len += t[0].length
+        }
+      })
+      X = (X / len).toFixed(2);
+      Y = (Y / len).toFixed(2);
+      Z = (Z / len).toFixed(2);
+      return `${X},${Y},${Z}`
+    },
+  },
+  created() {
+    this.init()
+  },
+  watch: {
+    projectId() {
+      this.init()
+    }
+  }
+}
+</script>

+ 26 - 66
src/views/data_admin/buildData/index.vue

@@ -7,12 +7,12 @@
             <!-- 建筑选择 -->
             <span style="padding-right:12px;color:#999;vertical-align: middle;">建筑名称</span>
             <el-select v-model="buildId" style="margin-right:10px;" placeholder="请选择" @change="changeBuild">
-                <el-option v-for="item in buildList" :key="item.BuildId" :label="item.BuildLocalName" :value="item.BuildId"></el-option>
+                <el-option v-for="item in buildList" :key="item.BuildID" :label="item.BuildLocalName" :value="item.BuildID"></el-option>
             </el-select>
             <!-- 楼层选择 -->
             <span style="padding-right:12px;color:#999;">楼层</span>
             <el-select v-model="floorId" placeholder="请选择" @change="changeFloor">
-                <el-option v-for="item in floorList" :key="item.FloorId" :label="item.FloorLocalName" :value="item.FloorId"></el-option>
+                <el-option v-for="item in floorList" :key="item.FloorID" :label="item.FloorLocalName" :value="item.FloorID"></el-option>
             </el-select>
             <!-- 选择时间插件 -->
             <build-time :timeArr="timeArr" @checkTime="checkTime"></build-time>
@@ -332,6 +332,8 @@
         defaultFloor, //获取默认楼层
         getdelMain, //获取过滤掉后的表格主体
         getBasicMatch, //获取完全匹配的厂商库id
+        buildingQuery, //数据中心-建筑查询
+        floorQuery, //数据中心-楼层查询
     } from "@/api/scan/request";
     import { mapGetters, mapActions } from "vuex"
     export default {
@@ -596,20 +598,8 @@
             },
             //获取建筑列表
             getBuilding() {
-                let param = {
-                    ProjId: this.projectId,
-                    UserId: this.userId
-                };
-                getBuildSelect(param).then(result => {
-                    if (result.data.Result == "success" && result.data.BuildList) {
-                        this.buildList = result.data.BuildList;
-                        //获取建筑下列数据后请求默认楼层建筑数据
-                        this.getDefaultFloor();
-                    } else {
-                        // this.dialogVisible = true;
-                        // this.ajaxMsg = "请求出错";
-                        this.$message.error("请求出错")
-                    }
+                buildingQuery({}, res => {
+                    this.buildList = res.Content;
                 });
             },
             //获取点位标签详情
@@ -684,21 +674,23 @@
                 }
                 return list;
             },
-            //获取默认楼层
-            getDefaultFloor() {
+            //获取楼层列表
+            getFloorData() {
                 let param = {
-                    ProjId: this.projectId,
-                    UserId: this.userId
+                    Filters: `BuildID='${this.buildId}'`,
+                    Orders: 'FloorSequenceID desc'
                 };
-                defaultFloor(param).then(result => {
-                    //将默认建筑id赋予标签绑定
-                    // this.buildId = result.data.BuildId;
-                    //存储默认楼层,等待楼层下拉列表出现后赋予
-                    // this.defaultFloorData = result.data.FloorId;
-                    //请求楼层下拉数据
-                    if (this.buildId) {
-                        this.getFloorData();
-                    }
+                floorQuery(param, res => {
+                    this.floorList = res.Content
+                    this.floorList.unshift({
+                    FloorName: "全部",
+                    FloorLocalName: "全部",
+                    FloorID: "all"
+                    }, {
+                        FloorName: "未明确楼层",
+                        FloorLocalName: "未明确楼层",
+                        FloorID: "noKnow"
+                    })
                 });
             },
             //保存点位标签详情的修改
@@ -744,41 +736,6 @@
                     }
                 });
             },
-            //获取楼层列表
-            getFloorData() {
-                let param = {
-                    BuildId: this.buildId,
-                    ProjId: this.projectId,
-                    UserId: this.userId
-                };
-                getFloor(param).then(res => {
-                    if (res.data.Result == "success") {
-                        this.floorList = tools.sortArr(res.data.FloorList, "FloorSequenceId", false);
-                        // this.floorId = this.defaultFloorData;
-                        for (let i = 0; i < this.floorList.length; i++) {
-                            if (this.floorId == this.floorList[i].FloorId) {
-                                this.floorName = this.floorList[i].FloorLocalName;
-                            }
-                        }
-                        this.floorList.unshift({
-                            FloorName: "全部",
-                            FloorLocalName: "全部",
-                            FloorId: "all"
-                        },{
-                            FloorName: "未明确楼层",
-                            FloorLocalName: "未明确楼层",
-                            FloorId: "noKnow"
-                        })
-                        if (this.defaultFloorData) {
-                            this.getPT();
-                        }
-                    } else {
-                        // this.dialogVisible = true;
-                        // this.ajaxMsg = "请求出错";
-                        this.$message.error("请求出错")
-                    }
-                });
-            },
             //保存设备资产的更新
             upDateTableMain(paramList) {
                 let param = {
@@ -1496,6 +1453,9 @@
             },
             //创建表格实例
             createHot(variableNum, data, headerArr) {
+                if(!headerArr){
+                    return
+                }
                 let maxRow = "";
                 //当当前页数*当前页个数小于总个数时,当前表格行数为当前页数
                 if (
@@ -1566,7 +1526,7 @@
                     autoColumnSize: true,
                     fixedColumnsLeft: 5,
                     language: "zh-CN",
-                    contextMenu: {
+                    contextMenu: this.onlyRead ? false :{
                         items: {
                             remove_row: {
                                 name: "删除资产"
@@ -1601,7 +1561,7 @@
             },
             afterDocumentKeyDown(e) {
                 //   this.$nextTick(() => {
-                let activeEditer = this.myHotArr[this.tabChecked].getActiveEditor(), td, row, prop, 
+                let activeEditer = this.myHotArr[this.tabChecked].getActiveEditor(), td, row, prop,
                     val = e.realTarget.value,
                     infoArr = ["Brand", "Specification", "Manufacturer", "Supplier", "Maintainer", "Insurer", "SupplierContactor", "SupplierPhone", "SupplierEmail", "SupplierWeb", "SupplierFax", "MaintainerContactor", "MaintainerPhone", "MaintainerEmail", "MaintainerWeb", "MaintainerFax", "InsurerContactor", "InsurerPhone", "InsurerEmail", "InsurerWeb", "InsurerFax"];
                 if(activeEditer){

+ 214 - 0
src/views/data_admin/buildGraphy/createPointZone.vue

@@ -0,0 +1,214 @@
+<template>
+  <div id="createPoint">
+    <div class="condition">
+      <div class="header">
+        <el-button style="float:left;" size="small" type="default" icon="el-icon-back" @click="goBack"></el-button>
+        <el-button size="small" style="float:right" @click="createZ">创建</el-button>
+      </div>
+      <el-scrollbar style="height:calc(100% - 43px)">
+        <div class="item">
+          <span>基本信息:</span>
+          <div>
+            <label><span style="color:red;">*</span>业务空间名称</label>
+            <el-input placeholder="请输入业务空间名称" v-model="RoomLocalName" clearable style="width:215px;margin-right:10px;"></el-input>
+            <label>业务空间编码</label>
+            <el-input placeholder="请输入业务空间编码" v-model="RoomLocalID" clearable style="width:215px;margin-right:10px;"></el-input>
+          </div>
+          <div>
+            <label><span style="color:red;">*</span>所属建筑楼层</label>
+            <el-cascader placeholder='请选择' v-model="buildFloor" :options="options" :props="floorProps" filterable ref="buildfloor"
+              style="width:215px;margin-right:10px;"></el-cascader>
+            <label><span style="color:red;">*</span>业务空间类型</label>
+            <el-select v-model="space" placeholder="请选择空间" style="width:215px;margin-right:10px;" @change="changeSpace">
+              <el-option v-for="item in spaceList" :key="item.Code" :label="item.Name" :value="item.Code">
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="item">
+          <span>其它可补充信息:</span>
+          <i style="cursor: pointer;" :class="showEx"
+            @click="showEx = (showEx == 'el-icon-arrow-up' ? 'el-icon-arrow-down' : 'el-icon-arrow-up')"></i>
+          <div v-show="showEx == 'el-icon-arrow-up'" v-loading="loadingOtherMsg">
+            <zoneInput v-show="otherList.length" :inputList="otherList" labelWidth="140px" ref="zoneInput"></zoneInput>
+            <p v-show="!otherList.length">请选择业务空间类型</p>
+          </div>
+        </div>
+        <div class="item">
+          <p>位置标签图片信息:</p>
+          <locationPointMsg ref="pointMsg" :pointObj="$route.params.item"></locationPointMsg>
+        </div>
+      </el-scrollbar>
+    </div>
+  </div>
+</template>
+
+<script>
+import locationPointMsg from '@/views/data_admin/buildGraphy/locationPointMsg'
+import { queryDictionaryHead, getDataDictionary, createZone } from '@/api/scan/request';
+import { mapGetters } from 'vuex'
+import zoneInput from '@/components/data_admin/zoneInput'
+export default {
+  data() {
+    return {
+      floorProps: {
+        value: 'BuildID',
+        label: 'BuildLocalName',
+        children: 'Floor'
+      },
+      options: [],//建筑楼层
+      spaceList: [],//空间列表
+      space: '',//当前空间
+      buildFloor: [],//建筑楼层信息
+      zoneName: '',//业务空间名称
+      zoneLocalId: '',//业务空间编码
+      showEx: 'el-icon-arrow-down',//下拉菜单
+      RoomLocalID: '',//业务空间本地编码
+      RoomLocalName: '',//业务空间名称
+      otherList: [],//可补充信息list
+      loadingOtherMsg: false,
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  props: {
+
+  },
+  components: {
+    locationPointMsg,
+    zoneInput
+  },
+  created() {
+    this.options = this.$route.params.floorData
+    this.getSpaceList();
+  },
+  methods: {
+    //创建
+    createZ() {
+      let param = {
+        zone: '',
+        data: {
+          content: []
+        }
+      }
+      let zObj = this.$refs.zoneInput.getFormData();
+      zObj.Pic = this.$refs.pointMsg.choImg.concat();
+      zObj.Pic = zObj.Pic.map(item => ({
+        Id: item.ObjectId,
+        Key: item.Key,
+        Name: item.Name,
+        Type: item.Type
+      }))
+      if (this.RoomLocalName && this.buildFloor.length && this.space) {
+        zObj.RoomLocalName = this.RoomLocalName;
+        zObj.RoomLocalID = this.RoomLocalID;
+        zObj.BuildingId = this.buildFloor[0];
+        zObj.FloorId = this.buildFloor[1];
+        param.zone = this.space;
+        param.data.content = [zObj];
+        createZone(param, res => {
+          this.$message.success("创建成功");
+          this.$refs.pointMsg.clearImg();
+          this.RoomLocalName = ''
+          this.RoomLocalID = ''
+          this.buildFloor = []
+          this.space = ''
+          this.otherList = []
+        })
+      }
+      else if (!this.RoomLocalName) {
+        this.$message("请输入业务空间名称");
+      }
+      else if (!this.buildFloor.length) {
+        this.$message("请选择所属建筑楼层");
+      }
+      else {
+        this.$message("请选择业务空间类型");
+      }
+    },
+    //获取空间列表
+    getSpaceList() {
+      let pa = {
+        Filters: `parentId='Space'`
+      }
+      queryDictionaryHead(pa, res => {
+        this.spaceList = res.Content.filter((item => { return item.Name != '元空间' }));
+      });
+    },
+    //选择业务空间
+    changeSpace(val) {
+      this.space = val;
+      let pa = {
+        type: this.space,
+        data: {
+          "Orders": "sort asc", "PageNumber": 1, "PageSize": 500
+        }
+      };
+      this.loadingOtherMsg = true;
+      getDataDictionary(pa, res => {
+        this.loadingOtherMsg = false;
+        let filterCode = ["RoomLocalID", "RoomLocalName"]
+        res.Content = res.Content.filter(item => {
+          item.inputValue = null;
+          return filterCode.indexOf(item.InfoPointCode) == -1
+        });
+        this.otherList = res.Content;
+        this.$refs.zoneInput.init(this.otherList);
+      })
+    },
+    //返回
+    goBack() {
+      this.$router.push({
+        name: "buildGraphy",
+        params: { nowBuildFloor: this.$route.params.nowBuildFloor }
+      })
+    }
+  },
+  watch: {
+    projectId: {
+      handler(val) {
+        this.goBack();
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.condition {
+  position: relative;
+  padding: 10px 10px;
+  display: flex;
+  height: calc(100% - 22px);
+  flex-direction: column;
+  border: 1px solid #dfe6ec;
+  background: #fff;
+  .header {
+    padding-bottom: 10px;
+    border-bottom: 1px solid rgba(0, 0, 0, 0.5);
+    span {
+      line-height: 33px;
+      margin-left: 15px;
+    }
+    /deep/ .buildFloor {
+      line-height: 32px;
+    }
+  }
+}
+/deep/ .el-scrollbar__wrap {
+  overflow-x: hidden;
+}
+.item {
+  padding: 10px 10px;
+  label {
+    display: inline-block;
+    padding: 5px 10px;
+    width: 130px;
+  }
+}
+.suppMsg {
+  display: inline-block;
+  position: relative;
+}
+</style>

File diff suppressed because it is too large
+ 349 - 909
src/views/data_admin/buildGraphy/graphyCanvas.vue


+ 481 - 452
src/views/data_admin/buildGraphy/graphyTabs.vue

@@ -3,49 +3,51 @@ setFalg 插旗事件
 getLocation 定位
 -->
 <template>
-    <div id="graphy-tabs">
-        <el-tabs style="height:100%;" v-model="activeName2" type="card" @tab-click="handleClick">
-            <el-tab-pane label="本层的点位标签" name="point">
-                <div v-if="pointData.length" v-loading="isLoading" style="max-height: 600px;overflow-y:auto;">
-                    <div v-for="(item,index) in pointData" :key="index">
-                        <div class="point">
-                            <span>{{item.Name}}</span>
-                            <el-button size="mini" @click="getDetails(item)">编辑点位标签</el-button>
-                            <el-button :disabled="!map" size="mini" @click="btnClick(item)">{{ item.X == 0 && item.Y == 0 ? '插旗' : '定位'}}</el-button>
-                        </div>
-                    </div>
-                </div>
-                <div v-if="!pointData.length" class="center" style="height: 400px;padding-top: 260px; box-sizing:border-box;">
-                    <i class="icon-wushuju iconfont"></i>
-                    {{pointParam.FloorId ? "数据为空" : "请选择楼层"}}
-                </div>
+  <div id="graphy-tabs">
+    <el-tabs style="height:100%;" v-model="activeName2" type="card" @tab-click="handleClick">
+      <el-tab-pane label="本层的点位标签" name="point" style="height:100%">
+        <el-scrollbar style="height:100%;width:calc(100% - 10px);" v-if="pointData.length" v-loading="isLoading">
+          <div v-for="(item,index) in pointData" :key="index">
+            <div class="point">
+              <span style="line-height:30px;">{{item.Name}}</span>
+              <div style="height:30px;float:right;font-size:14px;">
+                <el-button size="mini" @click="getDetails(item)" icon="el-icon-edit-outline"></el-button>
+                <el-button size="mini" @click="updateOrCreate(item)" icon="el-icon-link"></el-button>
+                <el-button :disabled="!map" size="mini" @click="btnClick(item)"
+                  :icon="item.X == 0 && item.Y == 0 ? 'el-icon-s-flag' : 'el-icon-place'"></el-button>
+              </div>
+            </div>
+          </div>
+        </el-scrollbar>
+
+        <div v-if="!pointData.length" class="center" style="height: 400px;padding-top: 260px; box-sizing:border-box;">
+          <i class="icon-wushuju iconfont"></i>
+          {{pointParam.FloorId ? "数据为空" : "请选择楼层"}}
+        </div>
       </el-tab-pane>
       <el-tab-pane label="无法定位到楼层的点位标签" name="noPoint">
-            <div v-if="pointNoData.length" v-loading="isLoading" style="max-height: 600px;">
-                <div v-for="(item,index) in pointNoData" :key="index">
-                    <div class="point">
-                    <span>{{item.Name}}</span>
-                    <el-button @click="getDetails(item)">编辑点位标签</el-button>
-                    <el-button
-                        :disabled="!(item.X == 0 && item.Y == 0)"
-                        @click="btnClick(item)"
-                    >{{ item.X == 0 && item.Y == 0 ? '插旗' : '定位'}}</el-button>
-                </div>
-            </div>
+        <div v-if="pointNoData.length" v-loading="isLoading" style="max-height: 600px;">
+          <div v-for="(item,index) in pointNoData" :key="index">
+            <div class="point">
+              <span>{{item.Name}}</span>
+              <el-button size="mini" @click="getDetails(item)" icon="el-icon-edit-outline"></el-button>
+              <el-button :disabled="true" size="mini" @click="btnClick(item)"
+                  :icon="item.X == 0 && item.Y == 0 ? 'el-icon-s-flag' : 'el-icon-place'"></el-button>
             </div>
-            <div v-if="!pointNoData.length" class="center" style="height: 400px;padding-top: 260px; box-sizing:border-box;">
-                <i class="icon-wushuju iconfont"></i>
-                {{pointParam.FloorId ? "数据为空" : "请选择楼层"}}
-            </div>
-        </el-tab-pane>
+          </div>
+        </div>
+        <div v-if="!pointNoData.length" class="center" style="height: 400px;padding-top: 260px; box-sizing:border-box;">
+          <i class="icon-wushuju iconfont"></i>
+          {{pointParam.FloorId ? "数据为空" : "请选择楼层"}}
+        </div>
+      </el-tab-pane>
     </el-tabs>
     <el-dialog title="详情" :visible.sync="pointShow" width="500px">
       <div class="qrcode">
         <div class="qrcode-view">
           <img
             :src="'/ScanBuilding/service/qrcode/point?projectId=' + projectId + '&pointId=' + pointDetails.PointId + '&FloorId=' + pointDetails.FloorId + '&width=200&height=200'"
-            alt="点位标签二维码"
-          >
+            alt="点位标签二维码">
         </div>
         <div class="point-edit">
           <p>
@@ -54,22 +56,10 @@ getLocation 定位
             -({{pointDetails.X}},{{pointDetails.Y}})
           </p>
           <div>
-            <form-input
-              :width="100"
-              @change="changeInput"
-              :value="pointDetails.PointName"
-              :keys="'PointName'"
-              :label="'点位标签'"
-              :isRule="false"
-            ></form-input>
-            <form-input
-              :width="100"
-              @change="changeInput"
-              :value="pointDetails.PointLocalId"
-              :keys="'PointLocalId'"
-              :label="'点位本地编码'"
-              :isRule="false"
-            ></form-input>
+            <form-input :width="100" @change="changeInput" :value="pointDetails.Name" :keys="'Name'" :label="'点位标签'" :isRule="false">
+            </form-input>
+            <form-input :width="100" @change="changeInput" :value="pointDetails.LocalId" :keys="'LocalId'" :label="'点位本地编码'"
+              :isRule="false"></form-input>
             <!-- <form-input></form-input> -->
           </div>
         </div>
@@ -97,66 +87,59 @@ getLocation 定位
           <li>
             <span>备注</span>
             <span>
-              <form-input
-                :width="0"
-                @change="changeInput"
-                :value="pointDetails.Note"
-                :keys="'Note'"
-                :label="''"
-                :isRule="false"
-              ></form-input>
+              <form-input :width="0" @change="changeInput" :value="pointDetails.Note" :keys="'Note'" :label="''" :isRule="false"></form-input>
             </span>
           </li>
         </ul>
       </div>
       <div class="point-pic">
-            <p>点位安装位置效果照片</p>
-            <template v-for="(item,index) in installPic">
-                <div class="point-image" :key="index">
-                    <i class="el-icon-delete" @click="delImage(index,installPic)"></i>
-                    <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.key +'&width=200&height=200'" alt>
-                </div>
-            </template>
-            <load-img keyName="安装位置" @getKey="getKey"></load-img>
-        </div>
-        <div class="point-pic">
-            <p>全景照片</p>
-            <template v-for="(item,index) in panorama">
-                <div class="point-image" :key="index">
-                    <i class="el-icon-delete" @click="delImage(index,panorama)"></i>
-                    <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.key +'&width=200&height=200'" alt>
-                </div>
-            </template>
-            <load-img keyName="全景照片" @getKey="getKey"></load-img>
-        </div>
-        <div class="point-pic">
-            <p>周边照片</p>
-            <template v-for="(item,index) in rimPic">
-                <div class="point-image" :key="index">
-                    <i class="el-icon-delete" @click="delImage(index,rimPic)"></i>
-                    <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.key +'&width=200&height=200'" alt>
-                </div>
-            </template>
-            <load-img keyName="周边照片" @getKey="getKey"></load-img>
-        </div>
-        <div class="point-pic">
-            <p>视频资料</p>
-            <template v-for="(item,index) in videoPic">
-                <div class="point-image" :key="index">
-                    <i class="el-icon-delete" @click="delImage(index,videoPic)"></i>
-                    <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.key +'&width=200&height=200'" alt>
-                </div>
-            </template>
-            <load-img keyName="视频" @getKey="getKey"></load-img>
-        </div>
-        <div class="point-pic">
-            <p>其他照片</p>
-            <template v-for="(item,index) in elsePic">
-                <div class="point-image" :key="index">
-                    <i class="el-icon-delete" @click="delImage(index,elsePic)"></i>
-                    <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.key +'&width=200&height=200'" alt>
-                </div>
-            </template>
+        <p>点位安装位置效果照片</p>
+        <template v-for="(item,index) in installPic">
+          <div class="point-image" :key="index">
+            <i class="el-icon-delete" @click="delImage(index,installPic)"></i>
+            <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.Key +'&width=200&height=200'" alt>
+          </div>
+        </template>
+        <load-img keyName="安装位置" @getKey="getKey"></load-img>
+      </div>
+      <div class="point-pic">
+        <p>全景照片</p>
+        <template v-for="(item,index) in panorama">
+          <div class="point-image" :key="index">
+            <i class="el-icon-delete" @click="delImage(index,panorama)"></i>
+            <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.Key +'&width=200&height=200'" alt>
+          </div>
+        </template>
+        <load-img keyName="全景照片" @getKey="getKey"></load-img>
+      </div>
+      <div class="point-pic">
+        <p>周边照片</p>
+        <template v-for="(item,index) in rimPic">
+          <div class="point-image" :key="index">
+            <i class="el-icon-delete" @click="delImage(index,rimPic)"></i>
+            <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.Key +'&width=200&height=200'" alt>
+          </div>
+        </template>
+        <load-img keyName="周边照片" @getKey="getKey"></load-img>
+      </div>
+      <div class="point-pic">
+        <p>视频资料</p>
+        <template v-for="(item,index) in videoPic">
+          <div class="point-image" :key="index">
+            <i class="el-icon-delete" @click="delImage(index,videoPic)"></i>
+            <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.Key +'&width=200&height=200'" alt>
+          </div>
+        </template>
+        <load-img keyName="视频" @getKey="getKey"></load-img>
+      </div>
+      <div class="point-pic">
+        <p>其他照片</p>
+        <template v-for="(item,index) in elsePic">
+          <div class="point-image" :key="index">
+            <i class="el-icon-delete" @click="delImage(index,elsePic)"></i>
+            <img :src="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.Key +'&width=200&height=200'" alt>
+          </div>
+        </template>
         <load-img keyName="其他照片" @getKey="getKey"></load-img>
       </div>
     </el-dialog>
@@ -164,360 +147,406 @@ getLocation 定位
 </template>
 
 <script>
-    import {
-        getPT, //获取点位列表
-        getPoint, //获取点位详情
-        updatePoint //修改点位
-    } from "@/api/scan/request";
-    import formInput from "./lib/formInput";
-    import loadImg from "./lib/uploadImg";
-    import {
-        mapGetters,
-        mapActions
-    } from 'vuex';
-    export default {
-        props: {
-            pointParam: {
-                type: Object
-            }
-        },
-        components: {
-            formInput,
-            loadImg
-        },
-        data() {
-            return {
-                activeName2: "point",
-                pointData: [], //tab为本层的点位标签
-                pointNoData: [], //tab为无法定位的点位标签
-                pointShow: false, //标签详情的弹窗
-                pointDetails: {}, //标签详情信息对象
-                // projId: this.$route.query.projId,
-                index: "",
-                installPic: [], //安装位置
-                panorama: [], //全景照片
-                rimPic: [], //周边照片
-                videoPic: [], //视频资料
-                elsePic: [], //其他照片
-                map: true
-            };
-        },
-        computed: {
-            ...mapGetters('layout', ['projectId', 'secret', 'userId'])
-        },
-        methods: {
-            //tabs被点击
-            handleClick(tab, event) {
-                this.index = tab.index;
-                this.getPointList();
-            },
-            //修改input
-            changeInput(val, key) {
-                this.pointDetails[key] = val;
-                this.updatePoint();
-            },
-            //删除图片
-            delImage(index, arr) {
-                arr.splice(index, 1);
-                this.updatePoint();
-            },
-            //获取key的值
-            getKey(val, name) {
-                switch (name) {
-                    case "安装位置":
-                        this.installPic.push({
-                            key: val,
-                            name: name,
-                            type: "image_wz"
-                        });
-                        break;
-                    case "全景照片":
-                        this.panorama.push({
-                            key: val,
-                            name: name,
-                            type: "panorama"
-                        });
-                        break;
-                    case "周边照片":
-                        this.rimPic.push({
-                            key: val,
-                            name: name,
-                            type: "image_zb"
-                        });
-                        break;
-                    case "视频":
-                        this.videoPic.push({
-                            key: val,
-                            name: name,
-                            type: "video"
-                        });
-                        break;
-                    default:
-                        this.elsePic.push({
-                            key: val,
-                            name: name,
-                            type: "image_else"
-                        });
-                }
-                this.updatePoint();
-            },
-            btnClick(item) {
-                if (item.X == 0 && item.Y == 0) {
-                    this.$emit("setFalg", item);
-                } else {
-                    this.$emit("getLocation", item);
-                }
-            },
-            mapPush(detailsArr, pic) {
-                pic.map(item => {
-                    detailsArr.push(item);
-                });
-            },
-            //修改详情
-            updatePoint() {
-                this.pointDetails.ImageList = [];
-                this.mapPush(this.pointDetails.ImageList, this.installPic);
-                this.mapPush(this.pointDetails.ImageList, this.panorama);
-                this.mapPush(this.pointDetails.ImageList, this.rimPic);
-                this.mapPush(this.pointDetails.ImageList, this.videoPic);
-                this.mapPush(this.pointDetails.ImageList, this.elsePic);
-                let param = {
-                    ProjId: this.pointParam.ProjId,
-                    UserId: this.pointParam.UserId,
-                    PointList: this.pointDetails
-                };
-                updatePoint(param).then(res => {
-                    this.$message.success("修改成功");
-                });
-            },
-            getDetails(item) {
-                let params = {
-                    ProjId: this.projectId,
-                    UserId: this.userId,
-                    PointId: item.Id
-                };
-                getPoint(params).then(res => {
-                    let data = res.data;
-                    if (data.Result == "success") {
-                        this.pointShow = true;
-                        this.pointDetails = data.PointList[0];
-                        this.getPic(data.PointList[0].ImageList);
-                    } else {
-                        this.$message.error("请求出错");
-                    }
-                });
-            },
-            getPic(imgArr) {
-                this.installPic = [];
-                this.panorama = [];
-                this.rimPic = [];
-                this.videoPic = [];
-                this.elsePic = [];
-                imgArr.map((item, index) => {
-                    switch (item.name) {
-                        case "安装位置":
-                            this.installPic.push(item);
-                            break;
-                        case "全景照片":
-                            this.panorama.push(item);
-                            break;
-                        case "周边照片":
-                            this.rimPic.push(item);
-                            break;
-                        case "视频":
-                            this.videoPic.push(item);
-                            break;
-                        default:
-                            this.elsePic.push(item);
-                    }
-                });
-            },
-            //获取point
-            getPointList() {
-                this.isLoading = true;
-                if (this.pointParam.FloorId) {
-                    let param = {
-                        FloorId: this.pointParam.FloorId,
-                        ProjId: this.pointParam.ProjId,
-                        UserId: this.pointParam.UserId
-                    };
-                    console.log(param)
-                    //当index为1时FloorId为空
-                    if (this.index == "1") {
-                        param.FloorId = "";
-                    }
-                    getPT(param).then(res => {
-                        res.data.PointList.splice(0, 1);
-                        if (this.index == "1") {
-                            this.pointNoData = res.data.PointList;
-                        } else {
-                            this.$emit("getPointList", res.data.PointList);
-                            this.pointData = res.data.PointList;
-                        }
-                        this.isLoading = false;
-                    });
-                }
-            },
-            //初始化
-            reset(data, map) {
-                this.map = map
-                this.pointParam.FloorId = data.FloorId;
-                this.pointParam.fllorName = data.fllorName;
-                this.activeName2 = "point";
-                this.getPointList();
-            }
-        },
-        watch: {
-            pointShow: {
-                deep: true,
-                handler: function(old, val) {
-                    if (old == false && val == true) {
-                        this.getPointList();
-                    }
-                }
-            },
-            projectId(){
-                this.pointData= []
-                this.pointNoData= []
-                this.activeName2 = "point"
-            }
-        }
+import {
+  locationPointQuery, //获取点位列表
+  getPoint, //获取点位详情
+  updateLocationPoint, //修改点位
+  deleteLocationImg,//数据中心删除图片
+} from "@/api/scan/request";
+import formInput from "./lib/formInput";
+import loadImg from "./lib/uploadImg";
+import {
+  mapGetters,
+  mapActions
+} from 'vuex';
+export default {
+  props: {
+    pointParam: {
+      type: Object
+    },
+    floorOption: {//建筑楼层
+      Type: Array,
+      default: () => []
+    },
+  },
+  components: {
+    formInput,
+    loadImg
+  },
+  data() {
+    return {
+      activeName2: "point",
+      pointData: [], //tab为本层的点位标签
+      pointNoData: [], //tab为无法定位的点位标签
+      pointShow: false, //标签详情的弹窗
+      pointDetails: {}, //标签详情信息对象
+      // projId: this.$route.query.projId,
+      index: "",
+      installPic: [], //安装位置
+      panorama: [], //全景照片
+      rimPic: [], //周边照片
+      videoPic: [], //视频资料
+      elsePic: [], //其他照片
+      map: true,
+      buildingData: [],//建筑楼层信息
     };
-</script>
-
-<style lang="scss" scoped>
-    #graphy-tabs {
-        height: 100%;
-        border-left: 1px solid #E4E7ED;
-        .el-tabs__content {
-            height: calc(100% - 60px) !important;
-            background: red;
-        }
-        .el-dialog__body{
-            max-height: 400px;
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId', 'secret', 'userId'])
+  },
+  methods: {
+    //tabs被点击
+    handleClick(tab, event) {
+      this.index = tab.index;
+      this.getPointList();
+    },
+    //修改input
+    changeInput(val, key) {
+      this.pointDetails[key] = val;
+      this.updatePoint();
+    },
+    //删除图片
+    delImage(index, arr) {
+      let delArr = arr.splice(index, 1);
+      deleteLocationImg(delArr, res => {
+        this.$message.success("修改成功");
+      })
+    },
+    //获取key的值
+    getKey(val, name) {
+      switch (name) {
+        case "安装位置":
+          this.installPic.push({
+            Key: val,
+            name: name,
+            type: "image_wz"
+          });
+          break;
+        case "全景照片":
+          this.panorama.push({
+            Key: val,
+            name: name,
+            type: "panorama"
+          });
+          break;
+        case "周边照片":
+          this.rimPic.push({
+            Key: val,
+            name: name,
+            type: "image_zb"
+          });
+          break;
+        case "视频":
+          this.videoPic.push({
+            Key: val,
+            name: name,
+            type: "video"
+          });
+          break;
+        default:
+          this.elsePic.push({
+            Key: val,
+            name: name,
+            type: "image_else"
+          });
+      }
+      this.updatePoint();
+    },
+    //创建或更新
+    updateOrCreate(item) {
+      this.$confirm('更新:将位置标签图片填充到已有的业务空间中<br>创建:新建业务空间,并将位置标签图片和信息填充到新业务空间中', '创建/更新业务空间信息', {
+        dangerouslyUseHTMLString: true,
+        distinguishCancelAndClose: true,
+        confirmButtonText: '更新',
+        cancelButtonText: '创建'
+      }).then(() => {
+        this.$emit("closeCanvas")
+        this.$router.push({
+          name: 'updatePointZone',
+          params: { item: item, floorData: this.floorOption, nowBuildFloor: this.buildingData }
+        })
+      }).catch(action => {
+        if (action === 'cancel') {
+          this.$router.push({
+            name: 'createPointZone',
+            params: { item: item, floorData: this.floorOption, nowBuildFloor: this.buildingData }
+          })
         }
-        .saga-message {
-            height: calc(100vh - 220px);
-            line-height: 400px;
-            color: #ccc;
-            font-size: 24px;
-            text-align: center;
+      })
+    },
+    btnClick(item) {
+      if (item.X == 0 && item.Y == 0) {
+        this.$emit("setFalg", item);
+      } else {
+        this.$emit("getLocation", item);
+      }
+    },
+    mapPush(detailsArr, pic) {
+      pic.map(item => {
+        detailsArr.push(item);
+      });
+    },
+    //修改详情
+    updatePoint() {
+      this.pointDetails.ImageList = [];
+      this.mapPush(this.pointDetails.ImageList, this.installPic);
+      this.mapPush(this.pointDetails.ImageList, this.panorama);
+      this.mapPush(this.pointDetails.ImageList, this.rimPic);
+      this.mapPush(this.pointDetails.ImageList, this.videoPic);
+      this.mapPush(this.pointDetails.ImageList, this.elsePic);
+      let pa = {
+        Content: [this.pointDetails]
+      }
+      updateLocationPoint(pa, res => {
+        this.$message.success("修改成功");
+      })
+    },
+    getDetails(item) {
+      this.pointShow = true;
+      this.pointDetails = item;
+      if (item.ImageList && item.ImageList.length) {
+        this.getPic(item.ImageList);
+      }
+    },
+    getPic(imgArr) {
+      this.installPic = [];
+      this.panorama = [];
+      this.rimPic = [];
+      this.videoPic = [];
+      this.elsePic = [];
+      imgArr.map((item, index) => {
+        switch (item.name) {
+          case "安装位置":
+            this.installPic.push(item);
+            break;
+          case "全景照片":
+            this.panorama.push(item);
+            break;
+          case "周边照片":
+            this.rimPic.push(item);
+            break;
+          case "视频":
+            this.videoPic.push(item);
+            break;
+          default:
+            this.elsePic.push(item);
         }
-        .point {
-            padding-left: 20px;
-            height: 30px;
-            span {
-                font-size: 12px;
-                width: 180px;
-                display: inline-block;
-                white-space: nowrap;
-                text-overflow: ellipsis;
-                overflow: hidden;
-            }
-            button {
-                margin-bottom: 5px;
-            }
+      });
+    },
+    //获取point
+    getPointList() {
+      if (this.buildingData[0] && this.buildingData[1]) {
+        let param = {
+            Filters: `BuildId='${this.buildingData[0]}';floorId='${this.buildingData[1]}'`,
+            "Cascade": [{ "Name": "imageList" }]
+          };
+        if (this.activeName2 != "point") {
+          param.Filters =  `BuildId='${this.buildingData[0]}';floorId isNull`
         }
-        .point:hover {
-            background-color: #f2f6fc;
-        }
-        .qrcode {
-            width: 100%;
-            height: 180px;
-            overflow: hidden;
-            .qrcode-view {
-                width: 180px;
-                height: 180px;
-                overflow: hidden;
-                float: left;
-                img {
-                    width: 100%;
-                    height: 100%;
-                }
-            }
-            .point-edit {
-                height: 180px;
-                display: inline-block;
-                padding-top: 10px;
-                overflow-x: hidden;
-                width: calc(100% - 180px);
-            }
+        this.isLoading = true;
+        locationPointQuery(param, res => {
+          this.isLoading = false;
+          if (this.activeName2 != "point") {
+            this.pointNoData = res.Content;
+            this.$emit("getPointList", []);
+          }
+          else {
+            this.pointData = res.Content;
+            this.$emit("getPointList", res.Content);
+          }
+        })
+      }
+    },
+    //初始化
+    reset(data, map) {
+      this.map = map
+      this.pointParam.FloorId = data.FloorId;
+      this.pointParam.fllorName = data.fllorName;
+      this.buildingData = data.buildingData;
+      this.activeName2 = "point";
+      this.getPointList();
+    }
+  },
+  watch: {
+    pointShow: {
+      deep: true,
+      handler: function (old, val) {
+        if (old == false && val == true) {
+          this.getPointList();
         }
-        .point-coding {
-            width: 100%;
-            height: 120px;
-            margin-top: 5px;
-            overflow: hidden;
-            p {
-                height: 30px;
-                line-height: 30px;
-                padding-left: 10px;
-                font-weight: 500;
-                font-size: 16px;
-                text-align: left;
-            }
-            ul {
-                width: 100%;
-                border: 1px solid #ccc;
-                border-bottom: none;
-                box-sizing: border-box;
-                li {
-                    line-height: 40px;
-                    height: 40px;
-                    span {
-                        display: block;
-                        float: left;
-                        padding-left: 10px;
-                        box-sizing: border-box;
-                        border-right: 1px solid #ccc;
-                        border-bottom: 1px solid #ccc;
-                        border-left: 1px solid #ccc;
-                        height: 40px;
-                        overflow: hidden;
-                    }
-                    span:first-child {
-                        width: 30%;
-                    }
-                    span:last-child {
-                        width: 70%;
-                    }
-                }
-            }
+      }
+    },
+    projectId() {
+      this.pointData = []
+      this.pointNoData = []
+      this.activeName2 = "point"
+    }
+  }
+};
+
+</script>
+
+<style lang="scss" scoped>
+#graphy-tabs {
+  /deep/ .el-scrollbar__wrap {
+    overflow-x: hidden;
+  }
+  /deep/ .el-tabs__content {
+    height: calc(100% - 56px);
+  }
+  height: 100%;
+  border-left: 1px solid #e4e7ed;
+
+  .el-tabs__content {
+    height: calc(100% - 60px) !important;
+    background: red;
+  }
+
+  .el-dialog__body {
+    max-height: 400px;
+  }
+
+  .saga-message {
+    height: calc(100vh - 220px);
+    line-height: 400px;
+    color: #ccc;
+    font-size: 24px;
+    text-align: center;
+  }
+
+  .point {
+    padding-left: 20px;
+    height: 30px;
+
+    span {
+      font-size: 12px;
+      width: 180px;
+      display: inline-block;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+
+    button {
+      margin-bottom: 5px;
+    }
+  }
+
+  .point:hover {
+    background-color: #f2f6fc;
+  }
+
+  .qrcode {
+    width: 100%;
+    height: 180px;
+    overflow: hidden;
+
+    .qrcode-view {
+      width: 180px;
+      height: 180px;
+      overflow: hidden;
+      float: left;
+
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    .point-edit {
+      height: 180px;
+      display: inline-block;
+      padding-top: 10px;
+      overflow-x: hidden;
+      width: calc(100% - 180px);
+    }
+  }
+
+  .point-coding {
+    width: 100%;
+    height: 120px;
+    margin-top: 5px;
+    overflow: hidden;
+
+    p {
+      height: 30px;
+      line-height: 30px;
+      padding-left: 10px;
+      font-weight: 500;
+      font-size: 16px;
+      text-align: left;
+    }
+
+    ul {
+      width: 100%;
+      border: 1px solid #ccc;
+      border-bottom: none;
+      box-sizing: border-box;
+
+      li {
+        line-height: 40px;
+        height: 40px;
+
+        span {
+          display: block;
+          float: left;
+          padding-left: 10px;
+          box-sizing: border-box;
+          border-right: 1px solid #ccc;
+          border-bottom: 1px solid #ccc;
+          border-left: 1px solid #ccc;
+          height: 40px;
+          overflow: hidden;
         }
-        .point-pic {
-            width: 100%;
-            overflow: hidden;
-            p {
-                height: 25px;
-                line-height: 25px;
-                padding-left: 10px;
-                font-weight: 500;
-                font-size: 16px;
-                margin-top: 5px;
-                margin-bottom: 5px;
-            }
+
+        span:first-child {
+          width: 30%;
         }
-        .point-image {
-            width: 180px;
-            height: 180px;
-            float: left;
-            position: relative;
-            margin-right: 10px;
-            margin-bottom: 10px;
-            border: 1px solid #ccc;
-            img {
-                width: 100%;
-                height: 100%;
-            }
-            i {
-                position: absolute;
-                bottom: 10px;
-                right: 10px;
-                background-color: #fff;
-                padding: 5px;
-                cursor: pointer;
-            }
+
+        span:last-child {
+          width: 70%;
         }
+      }
     }
-</style>
+  }
+
+  .point-pic {
+    width: 100%;
+    overflow: hidden;
+
+    p {
+      height: 25px;
+      line-height: 25px;
+      padding-left: 10px;
+      font-weight: 500;
+      font-size: 16px;
+      margin-top: 5px;
+      margin-bottom: 5px;
+    }
+  }
+
+  .point-image {
+    width: 180px;
+    height: 180px;
+    float: left;
+    position: relative;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    border: 1px solid #ccc;
 
+    img {
+      width: 100%;
+      height: 100%;
+    }
+
+    i {
+      position: absolute;
+      bottom: 10px;
+      right: 10px;
+      background-color: #fff;
+      padding: 5px;
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 222 - 228
src/views/data_admin/buildGraphy/index.vue

@@ -2,242 +2,236 @@
   revit空间管理
  -->
 <template>
-    <div id="graphy">
-        <!-- <div class="graphy-left">
+  <div id="graphy">
+    <!-- <div class="graphy-left">
           <graphy-tree v-if="show" :param="param" @change="getPoint"></graphy-tree>
         </div> -->
-        <div class='search-title'>
-            <span class="p12">建筑楼层</span>
-            <el-cascader placeholder='请选择' :options="options" @active-item-change="handleItemChange" @change="changeFloor" filterable></el-cascader>
-        </div>
-        <div class="graphy-view">
-            <div class="graphy-main">
-                <graphy-canvas v-if="show" :param="param" @getDetails="getDetails" @resetPoint="resetPoint" ref="canvas"></graphy-canvas>
-            </div>
-            <div class="graphy-right">
-                <graphy-tabs v-show="show" ref="tabs" :pointParam="pointParam" @setFalg="setFalg" @getLocation="getLocation" @getPointList="sendPointList"></graphy-tabs>
-            </div>
-        </div>
+    <div class='search-title'>
+      <span class="p12">建筑楼层</span>
+      <el-cascader placeholder='请选择' v-model="buildVlaue" :options="options" @change="changeFloor" filterable :props="props" ref="buildfloor"></el-cascader>
     </div>
+    <div class="graphy-view">
+      <div class="graphy-main">
+        <graphy-canvas v-if="show" @getDetails="getDetails" @resetPoint="resetPoint" ref="canvas"></graphy-canvas>
+      </div>
+      <div class="graphy-right">
+        <graphy-tabs v-show="show" ref="tabs" :floorOption="options" :pointParam="pointParam" @setFalg="setFalg" @getLocation="getLocation" @getPointList="sendPointList" @closeCanvas="closeCanvas">
+        </graphy-tabs>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
-    //接口
-    import graphyTree from "./graphyTree";
-    import graphyTabs from "./graphyTabs";
-    import graphyCanvas from "./graphyCanvas";
-    import {
-        mapGetters,
-        mapActions
-    } from 'vuex';
-    import {
-        getPT,
-        getBuildSelect,
-        getFloor
-    } from "@/api/scan/request"; //获取点位坐标
-    import tools from "@/utils/scan/tools"
-    import Handsontable from "handsontable-pro"
-    import 'handsontable-pro/dist/handsontable.full.css'
-    import zhCN from 'handsontable-pro/languages/zh-CN';
-    export default {
-        components: {
-            graphyTree,
-            graphyTabs,
-            graphyCanvas
-        },
-        data() {
-            return {
-                param: {
-                    ProjId: this.projectId, //项目id
-                    UserId: this.userId //用户id
-                },
-                pointParam: {
-                    //point请求参数
-                    ProjId: this.projectId, //项目id
-                    UserId: this.userId, //用户id
-                    fllorName: ""
-                },
-                options: [],
-                map: null,
-                pointId: null,
-                show: false,
-                buildVlaue: []
-            };
-        },
-        mounted() {
-            this.changeValue()
-            this.getList()
-        },
-        computed: {
-            ...mapGetters('layout', ['projectId', 'secret', 'userId'])
-        },
-        methods: {
-            //修改楼层
-            changeFloor(val) {
-                console.log(val)
-                let floorMap = "",
-                    name = ""
-                this.options.map(item => {
-                    if (!!item.children && item.children.length) {
-                        if (item.value == val[0]) {
-                            item.children.map(child => {
-                                if (child.value == val[1]) {
-                                    console.log(child, 'child')
-                                    floorMap = child.map
-                                    name = child.label
-                                }
-                            })
-                        }
-                    }
-                })
-                let obj = {
-                    code: val[1],
-                    map: floorMap,
-                    name: name
-                }
-                this.getPoint(obj)
-                console.log(floorMap)
-            },
-            //获取建筑列表
-            getList() {
-                getBuildSelect(this.param).then(res => {
-                    console.log(res)
-                    this.options = res.data.BuildList.map(item => {
-                        return {
-                            value: item.BuildId,
-                            label: item.BuildLocalName,
-                            children: []
-                        }
-                    })
-                })
-            },
-            //点击事件
-            handleItemChange(val) {
-                if (val.length == 1) {
-                    let obj = Object.assign({
-                        BuildId: val[0]
-                    }, this.param)
-                    getFloor(obj).then(res => {
-                        console.log(res)
-                        this.options = this.options.map(item => {
-                            if (item.value == val[0]) {
-                                let FloorList = tools.sortArr(res.data.FloorList, "FloorSequenceId" , false)
-                                item.children = FloorList.map(child => {
-                                    return {
-                                        value: child.FloorId,
-                                        label: child.FloorLocalName + (child.FloorMap ? '' : '(需初始化数据)'),
-                                        map: child.FloorMap
-                                    }
-                                })
-                            }
-                            return item
-                        })
-                        console.log(this.options)
-                    })
-                } else if (val.length == 2) {
-                }
-            },
-            changeValue() {
-                this.$set(this.param, 'ProjId', this.projectId)
-                this.$set(this.param, 'UserId', this.userId)
-                this.$set(this.pointParam, 'ProjId', this.projectId)
-                this.$set(this.pointParam, 'UserId', this.userId)
-                this.show = true
-            },
-            //渲染
-            getPoint(data) {
-                this.pointParam.FloorId = data.code;
-                this.pointParam.fllorName = data.name;
-                this.$refs.tabs.reset(this.pointParam, data.map);
-                if (this.map != data.map) {
-                    this.map = data.map;
-                    this.$refs.canvas.getData(data);
-                } else {
-                    return;
-                }
-            },
-            //获取到点位标签坐标
-            sendPointList(list) {
-                if (list && list.length && list[0].Id == this.pointId) {
-                    this.$refs.canvas.doPoint(list);
-                } else {
-                    if (list.length) {
-                        this.pointId = list[0].Id;
-                        this.$refs.canvas.doPoint(list);
-                    } else {
-                        this.$refs.canvas.doPoint([]);
-                    }
-                }
-            },
-            //插旗setFalg
-            setFalg(item) {
-                this.$refs.canvas.addPoint(item);
-            },
-            //定位getLocation
-            getLocation(item) {
-                this.$refs.canvas.locationGraphy({
-                    X: item.X,
-                    Y: item.Y * -1
-                });
-            },
-            //重新获取点位信息resetPoint
-            resetPoint() {
-                this.$refs.tabs.reset(this.pointParam, true);
-            },
-            //查看详情
-            getDetails(item) {
-                this.$refs.tabs.getDetails(item);
-            }
-        },
-        watch: {
-            projectId(){
-                this. map = null
-                this.show = false
-                this.options = []
-                this.buildVlaue = []
-                this.changeValue()
-                this.getList()
-            }
-        }
+//接口
+import graphyTree from "./graphyTree";
+import graphyTabs from "./graphyTabs";
+import graphyCanvas from "./graphyCanvas";
+import {
+  mapGetters,
+  mapActions
+} from 'vuex';
+import {
+  getPT,
+  buildingQuery,
+  getFloor
+} from "@/api/scan/request"; //获取点位坐标
+import tools from "@/utils/scan/tools"
+import Handsontable from "handsontable-pro"
+import 'handsontable-pro/dist/handsontable.full.css'
+import zhCN from 'handsontable-pro/languages/zh-CN';
+export default {
+  components: {
+    graphyTree,
+    graphyTabs,
+    graphyCanvas
+  },
+  data() {
+    return {
+      props: {
+        value: 'BuildID',
+        label: 'BuildLocalName',
+        children: 'Floor'
+      },
+      param: {
+        ProjId: this.projectId, //项目id
+        UserId: this.userId //用户id
+      },
+      pointParam: {
+        ProjId: this.projectId, //项目id
+        UserId: this.userId, //用户id
+        fllorName: "",
+        buildingData:[],//建筑楼层信息
+      },
+      options: [],
+      map: null,
+      pointId: null,
+      show: false,
+      buildVlaue: []
     };
+  },
+  mounted() {
+    this.changeValue()
+    this.getList()
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId', 'secret', 'userId'])
+  },
+  methods: {
+    //修改楼层
+    changeFloor(val) {
+      let floorMap = "",
+        name = ""
+      this.options.map(item => {
+        if (!!item.Floor && item.Floor.length) {
+          if (item.BuildID == val[0]) {
+            item.Floor.map(child => {
+              if (child.BuildID == val[1]) {
+                floorMap = child.StructureInfo ? child.StructureInfo.FloorMap : ''
+                name = child.FloorLocalName
+              }
+            })
+          }
+        }
+      })
+      let obj = {
+        code: val[1],
+        map: floorMap,
+        name: name,
+        buildingData:val
+      }
+      this.getPoint(obj)
+    },
+    //获取建筑列表
+    getList() {
+      let param = {
+        Cascade: [
+          { Name: "floor", Orders: "FloorSequenceID desc", }
+        ],
+        PageNumber: 1,
+        PageSize: 50
+      }
+      buildingQuery(param, res => {
+        res.Content.map(t => {
+          if (t.Floor && t.Floor.length) {
+            t.Floor = t.Floor.map(item => {
+              if (item.FloorID == this.FloorID) return
+              item.BuildID = item.FloorID
+              item.BuildLocalName = item.FloorLocalName || item.FloorName
+              return item
+            }).filter(it => it)
+          }
+        })
+        this.options = res.Content
+        if(this.$route.params.nowBuildFloor){
+          this.changeFloor(this.$route.params.nowBuildFloor)
+          this.buildVlaue = this.$route.params.nowBuildFloor
+        }
+      })
+    },
+    changeValue() {
+      this.$set(this.param, 'ProjId', this.projectId)
+      this.$set(this.param, 'UserId', this.userId)
+      this.$set(this.pointParam, 'ProjId', this.projectId)
+      this.$set(this.pointParam, 'UserId', this.userId)
+      this.show = true
+    },
+    //渲染
+    getPoint(data) {
+      this.pointParam.FloorId = data.code;
+      this.pointParam.fllorName = data.name;
+      this.pointParam.buildingData = data.buildingData
+      
+      if (this.map != data.map) {
+        this.map = data.map;
+        this.$refs.canvas.getData(data);
+      } else {
+        // return;
+      }
+      this.$refs.tabs.reset(this.pointParam, data.map);
+    },
+    //获取到点位标签坐标
+    sendPointList(list) {
+      if (list && list.length) {
+        this.pointId = list[0].Id;
+        this.$refs.canvas.doPoint(list);
+      } else {
+        this.$refs.canvas.doPoint([]);
+      }
+    },
+    //插旗setFalg
+    setFalg(item) {
+      this.$refs.canvas.addPoint(item);
+    },
+    //定位getLocation
+    getLocation(item) {
+      this.$refs.canvas.locationGraphy({
+        X: item.X,
+        Y: item.Y * -1
+      });
+    },
+    //重新获取点位信息resetPoint
+    resetPoint() {
+      this.$refs.tabs.reset(this.pointParam, true);
+    },
+    //查看详情
+    getDetails(item) {
+      this.$refs.tabs.getDetails(item);
+    },
+    //关闭canvas
+    closeCanvas(){
+      this.show = false;
+    }
+  },
+  watch: {
+    projectId() {
+      this.map = null
+      this.show = false
+      this.options = []
+      this.buildVlaue = []
+      this.changeValue()
+      this.getList()
+    }
+  }
+};
 </script>
 
 <style lang="less" scoped>
-    #graphy {
-        // position: relative;
-        display: flex;
-        flex-direction: column;
-        .graphy-view {
-            display: flex;
-            background-color: #fff;
-            flex: 1; 
-            .graphy-main {
-                flex: 1;
-                // position: absolute;
-                // left: 200px;
-                // top: 0;
-                // right: 400px;
-                // bottom: 0;
-                // overflow: auto;
-            }
-            .graphy-right {
-                // position: absolute;
-                // right: 0;
-                width: 400px; // top: 0;
-                // bottom: 0;
-                // border-left: 1px solid #ccc;
-                // overflow: hidden;
-            }
-        }
-        .graphy-left {
-            // width: 200px;
-            // height: 100%;
-            // position: absolute;
-            // overflow-y: auto;
-            // left: 0;
-            // top: 0;
-            // bottom: 0;
-            // border-right: 1px solid #ccc;
-        }
+#graphy {
+  // position: relative;
+  display: flex;
+  flex-direction: column;
+  .graphy-view {
+    display: flex;
+    background-color: #fff;
+    flex: 1;
+    .graphy-main {
+      flex: 1;
+      // position: absolute;
+      // left: 200px;
+      // top: 0;
+      // right: 400px;
+      // bottom: 0;
+      // overflow: auto;
+    }
+    .graphy-right {
+      // position: absolute;
+      // right: 0;
+      width: 400px; // top: 0;
+      // bottom: 0;
+      // border-left: 1px solid #ccc;
+      // overflow: hidden;
     }
-</style>
+  }
+  .graphy-left {
+    // width: 200px;
+    // height: 100%;
+    // position: absolute;
+    // overflow-y: auto;
+    // left: 0;
+    // top: 0;
+    // bottom: 0;
+    // border-right: 1px solid #ccc;
+  }
+}
+</style>

+ 79 - 0
src/views/data_admin/buildGraphy/locationPointMsg.vue

@@ -0,0 +1,79 @@
+<template>
+  <div id="locationPointMsg" style="width:100%;border:1px solid rgb(204,204,204)">
+    <div style="padding:5px 10px;border-bottom:1px solid rgb(204,204,204);">
+      <label class="item">位置标签名称:{{pointObj.Name || '--'}}</label>
+      <label class="item">本地编码:{{pointObj.LocalId || '--'}}</label>
+      <label class="item">备注:{{pointObj.Note || '--'}}</label>
+    </div>
+    <div style="padding:5px 10px;">
+      <p>勾选需要补充到业务空间的图片信息</p>
+      <div v-if="pointObj.ImageList && pointObj.ImageList.length">
+        <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange"><span style="padding-left:20px">全选</span></el-checkbox>
+        <div style="margin: 15px 0;"></div>
+        <el-checkbox-group v-model="choImg" @change="handleCheckedCitiesChange">
+          <el-checkbox v-for="item in pointObj.ImageList" :label="item" :key="item.key">
+            <div style="max-width:250px;height:250px;float:left;">
+              <el-image :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`" style="height:250px;"></el-image>
+            </div>
+          </el-checkbox>
+        </el-checkbox-group>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      isIndeterminate: false,
+      checkAll: false,
+      choImg: [],//选中的图片
+    }
+  },
+  props: {
+    pointObj: {},//标签对象
+  },
+  created() {
+  },
+  methods: {
+    //是否全选
+    handleCheckAllChange(val) {
+      this.choImg = val ? this.pointObj.ImageList : [];
+      this.isIndeterminate = false;
+    },
+    //选中
+    handleCheckedCitiesChange(value) {
+      let checkedCount = value.length;
+      this.checkAll = checkedCount === this.pointObj.ImageList.length;
+      this.isIndeterminate = checkedCount > 0 && checkedCount < this.pointObj.ImageList.length;
+    },
+    //清空选项
+    clearImg(){
+      this.choImg = [];
+      this.isIndeterminate = false;
+      this.checkAll = false;
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#locationPointMsg {
+  /deep/ .el-checkbox__input {
+    position: absolute;
+    left: 10px;
+  }
+  /deep/ .el-checkbox__inner {
+    width: 20px;
+    height: 20px;
+  }
+  /deep/ .el-checkbox__inner::after {
+    left: 7px;
+    top: 4px;
+  }
+  .item{
+    padding-right:20px;
+  }
+}
+</style>

+ 272 - 0
src/views/data_admin/buildGraphy/updatePointZone.vue

@@ -0,0 +1,272 @@
+<template>
+  <div id="updatePoint">
+    <div class="condition">
+      <div class="header">
+        <el-button style="float:left;" size="small" type="default" icon="el-icon-back" @click="goBack"></el-button>
+        <el-button size="small" style="float:right" @click="updateZ">更新</el-button>
+      </div>
+      <el-scrollbar style="height:calc(100% - 43px)">
+        <div class="item">
+          <p>将位置标签图片批量补充到业务空间:</p>
+          <div v-for="item in zoneList" :key="item.objid" class="zone-item">
+            <el-tooltip class="item" effect="dark"
+              :content="`${item.Building.BuildLocalName} / ${item.Floor.FloorLocalName} / ${item.DClassDef.Name} / ${item.RoomLocalName}`"
+              placement="top">
+              <p>{{item.RoomLocalName || item.RoomName}}</p>
+            </el-tooltip>
+            <i class="el-icon-delete" circle style="float:right;line-height:32px;padding: 0 9px 0 0;cursor: pointer;" size="mini"
+              @click="deleteZone(item.RoomID)"></i>
+          </div>
+          <div class="zone-item" style="border:none;border-left:-4px;width:auto;">
+            <el-cascader :props="zoneCascader" :show-all-levels="false" v-model="zoneCa" @change="changeCascader" filterable style="float:left;">
+            </el-cascader>
+            <el-button type="primary" icon="el-icon-plus" circle style="float:right;margin:2px 10px;" size="mini" @click="addZone"></el-button>
+          </div>
+        </div>
+        <div class="item">
+          <p>位置标签图片信息:</p>
+          <locationPointMsg :pointObj="$route.params.item" ref="pointMsg"></locationPointMsg>
+        </div>
+      </el-scrollbar>
+    </div>
+  </div>
+</template>
+
+<script>
+import locationPointMsg from '@/views/data_admin/buildGraphy/locationPointMsg'
+import { queryDictionaryHead, zoneQueryByPoint, queryZone, updateZonePic } from '@/api/scan/request';
+import { mapGetters } from 'vuex'
+export default {
+  data() {
+    let that = this;
+    return {
+      zoneList: [],//业务空间列表
+      pointItem: {},//点位标签对象
+      zoneTypeList: [],//业务空间类型
+      zoneCascader: {//业务空间忌廉器
+        lazy: true,
+        lazyLoad(node, resolve) {
+          const { level } = node;
+          that.getCascaderNode(level, node, resolve);
+        }
+      },
+      newZoneObj: {},//当前新建业务空间
+      zoneCa: []
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  components: {
+    locationPointMsg
+  },
+  created() {
+    this.pointItem = this.$route.params.item
+    this.getSpaceList();
+  },
+  methods: {
+    //创建
+    updateZ() {
+      let imgs = this.$refs.pointMsg.choImg.concat();
+      imgs = imgs.map(item => ({
+        Id: item.ObjectId,
+        Key: item.Key,
+        Name: item.Name,
+        Type: item.Type
+      }))
+      if (imgs.length && this.zoneList.length) {
+        let zones = this.zoneList.map(item => {
+          if (item.Pic) {
+            item.Pic = item.Pic.concat(imgs);
+          }
+          else {
+            item.Pic = imgs;
+          }
+          return { RoomID: item.RoomID, Pic: item.Pic, ObjectType: item.ObjectType };
+        })
+        let param = {
+          Content: zones
+        }
+        updateZonePic(param, res => {
+          this.$message.success("更新成功");
+          this.$refs.pointMsg.clearImg();
+        })
+      }
+      else if (!this.$refs.pointMsg.choImg.length) {
+        this.$message("请至少选择一张图片");
+      }
+      else {
+        this.$message("请至少添加一个业务空间");
+      }
+
+    },
+    //获取空间列表
+    getSpaceList() {
+      let pa = {
+        X: this.pointItem.X,
+        Y: this.pointItem.Y,
+        data: {
+          Filters: `buildingId = '${this.pointItem.BuildId}' and floorId = '${this.pointItem.FloorId}'`,
+          "Cascade": [{ "Name": "floor" }, { "Name": "building" }, { "Name": "objectTypeO" }]
+        }
+      }
+      zoneQueryByPoint(pa, res => {
+        this.zoneList = res.Content;
+      });
+    },
+    //级联node
+    getCascaderNode(level, node, resolve) {
+      let id = (level + 1) * 10;
+      //建筑
+      if (level == 0) {
+        let nodes = this.$route.params.floorData.map(item => ({
+          value: item.BuildID,
+          label: item.BuildLocalName || item.BuildName,
+          leaf: level >= 3
+        }))
+        resolve(nodes)
+      }
+      //楼层
+      else if (level == 1) {
+        let floors = this.$route.params.floorData.filter(item => { return item.BuildID == node.value })
+        let nodes = floors[0].Floor.map(item => ({
+          value: item.FloorID,
+          label: item.FloorLocalName || item.FloorName,
+          leaf: level >= 3
+        }))
+        resolve(nodes)
+      }
+      //空间类型
+      else if (level == 2) {
+        if (this.zoneTypeList && this.zoneTypeList.length) {
+          resolve(this.zoneTypeList)
+        }
+        else {
+          let pa = {
+            Filters: `parentId='Space'`
+          }
+          queryDictionaryHead(pa, res => {
+            this.zoneTypeList = res.Content.filter((item => { return item.Name != '元空间' })).map(item => ({
+              value: item.Code,
+              label: item.Name,
+              leaf: level >= 3
+            }))
+            resolve(this.zoneTypeList)
+          });
+        }
+      }
+      //业务空间
+      else {
+        let pa = {
+          zone: node.value,
+          data: {
+            "Filters": `buildingId='${node.parent.parent.value}';floorId='${node.parent.value}'`,
+            "Orders": "createTime desc, RoomID asc",
+            "PageNumber": 1,
+            "PageSize": 999
+          }
+        }
+        queryZone(pa, res => {
+          let nodes = res.Content.map(item => {
+            item.Building = { BuildLocalName: node.parent.parent.label };
+            item.Floor = { FloorLocalName: node.parent.label };
+            item.DClassDef = { Name: node.label };
+            return {
+              value: item,
+              label: item.RoomLocalName || item.RoomName,
+              leaf: level >= 3
+            }
+          })
+          resolve(nodes)
+        })
+      }
+    },
+    //删除业务空间
+    deleteZone(zoneid) {
+      this.zoneList = this.zoneList.filter(item => { return item.RoomID != zoneid });
+    },
+    //添加业务空间
+    addZone() {
+      if (this.newZoneObj.RoomID && this.zoneList.findIndex((item) => (item.RoomID == this.newZoneObj.RoomID)) == -1) {
+        this.zoneList.push(this.newZoneObj)
+      }
+      else if (!this.newZoneObj.RoomID) {
+        this.$message("请选择业务空间后添加")
+      }
+      else {
+        this.$message("已有业务空间,请重新选择");
+      }
+      this.zoneCa = [];
+      this.newZoneObj = {}
+    },
+    //选择业务空间
+    changeCascader(val) {
+      this.newZoneObj = val[3]
+    },
+    //返回
+    goBack() {
+      this.$router.push({
+        name: "buildGraphy",
+        params: { nowBuildFloor: this.$route.params.nowBuildFloor }
+      })
+    }
+  },
+  watch: {
+    projectId: {
+      handler(val) {
+        this.goBack();
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.condition {
+  position: relative;
+  padding: 10px 10px;
+  display: flex;
+  height: calc(100% - 22px);
+  flex-direction: column;
+  border: 1px solid #dfe6ec;
+  background: #fff;
+  .header {
+    padding-bottom: 10px;
+    border-bottom: 1px solid rgba(0, 0, 0, 0.5);
+    span {
+      line-height: 33px;
+      margin-left: 15px;
+    }
+    /deep/ .buildFloor {
+      line-height: 32px;
+    }
+  }
+}
+/deep/ .el-scrollbar__wrap {
+  overflow-x: hidden;
+}
+.item {
+  padding: 10px 10px;
+  label {
+    display: inline-block;
+    padding: 5px 10px;
+    width: 130px;
+  }
+}
+.zone-item {
+  display: inline-block;
+  position: relative;
+  width: 245px;
+  margin: 5px 15px 10px 0;
+  border: 1px solid rgb(220, 223, 230);
+  border-radius: 5px;
+}
+.zone-item p {
+  width: 200px;
+  float: left;
+  height: 32px;
+  overflow: hidden;
+  padding-left: 15px;
+  padding: 0 0 0 15px;
+}
+</style>

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

@@ -175,7 +175,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除竖井"
@@ -313,4 +313,4 @@ export default {
     margin-top: 10px;
   }
 }
-</style>
+</style>

+ 5 - 5
src/views/ledger/cenotelist/index.vue

@@ -108,7 +108,7 @@ export default {
     ]),
     showTypes () {
       return this.onlyRead?
-        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]: 
+        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]:
         [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]
     }
   },
@@ -200,7 +200,7 @@ export default {
         param.Content.push(item);
       })
       await updataCenoteTableData(param, (res) => {
-        
+
       })
     },
     // 删除表格数据
@@ -290,7 +290,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) {//格式化表头头映射的数据
@@ -320,7 +320,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除竖井"
@@ -550,4 +550,4 @@ export default {
 .el-pagination button, .el-pagination span:not([class*=suffix]) {
     vertical-align: middle;
 }
-</style>
+</style>

+ 203 - 67
src/views/ledger/cenotelist/relatedSpace.vue

@@ -3,17 +3,23 @@
     <div class="condition">
       <div class="header">
         <el-button style="float:left;" size="small" type="default" icon="el-icon-back" @click="goBack"></el-button>
-        <span style="float:left;">{{ cenoteObj.name || '' }}</span>
         <div class="edit-tool" v-if="!cenoteObj.onlyRead">
           <el-button v-if="isMyTab == 2" size="small" style="float:right" @click="dialogVisible = true">添加</el-button>
           <div v-else>
             <el-button v-show="!isEdit" @click="isEdit = true" size="small" style="float:right">编辑</el-button>
-            <el-button v-show="isEdit" size="small" style="float:right">保存</el-button>
-            <el-button v-show="isEdit" size="small" @click="isEdit = false" style="float:right">取消</el-button>
+            <el-button v-show="isEdit" size="small" @click="saveEdit" style="float:right">保存</el-button>
+            <el-button v-show="isEdit" size="small" @click="cancelEdit" style="float:right">取消</el-button>
           </div>
-          <addSpaceDialog :dialogVisible.sync="dialogVisible" ref="addSpaceDialog" @refresh="refresh" :params="cenoteObj" :spaceType="spaceType" :floorType="floorType"></addSpaceDialog>
+          <addSpaceDialog :dialogVisible.sync="dialogVisible" ref="addSpaceDialog" @refresh="refresh" :params="cenoteObj" :spaceType="spaceType"
+            :floorType="floorType"></addSpaceDialog>
         </div>
-        <space-select @change="changeSpace"></space-select>
+        <el-badge :is-dot="showSpaceDot" style="margin-left:15px;">
+          <label style="line-height:32px;">业务空间类型:</label>
+          <el-select v-model="space" placeholder="请选择业务空间" @change="changeSpace" style="margin-left:15px;">
+            <el-option v-for="item in spaceList" :key="item.Code" :label="item.Name" :value="item.Code">
+            </el-option>
+          </el-select>
+        </el-badge>
       </div>
       <div class="saga-build-tab">
         <el-radio-group v-model="isMyTab" @change="changeRadio" style="width: 136px;">
@@ -22,22 +28,31 @@
         </el-radio-group>
       </div>
       <div v-show="isMyTab == 1" class="data-item">
-        <el-select v-model="building" placeholder="请选择建筑" @change="changeBuilding">
-          <el-option v-for="item in buildingList" :key="item.value" :label="item.BuildLocalName" :value="item.BuildID"></el-option>
-        </el-select>
+        <el-badge :is-dot="showBuildDot">
+          <label style="line-height:32px;padding: 0 10px;">所属建筑:</label>
+          <el-select v-model="building" placeholder="请选择建筑" @change="changeBuilding" v-loading="buildingLoading">
+            <el-option v-for="item in buildingList" :key="item.value" :label="item.BuildLocalName" :value="item.BuildID"></el-option>
+          </el-select>
+        </el-badge>
         <div style="height:calc(100% - 42px);margin:10px 0 0 0;width:100%;position:relative;">
-          <el-scrollbar style="height:100%;width:149px;border-right:1px solid;margin:0px;">
-          <div class="floor" style="width:149px;height:100%;">
-            <span class="floor-item">楼 层</span>
-            <div v-if="building">
-            <span class="floor-item" @click="changeFloor(item.FloorID)" :class="{floorItemChoose:(item.FloorID == floor)}" v-for="item in buildingObj.Floor" :key="item.FloorID">{{ item.FloorLocalName }}</span>
+          <el-scrollbar style="height:100%;width:148px;border:1px solid rgb(201,201,201);margin:0px;float:left;">
+            <div class="floor" style="width:149px;height:100%;">
+              <span class="floor-item" style="border-bottom:1px solid rgb(201,201,201)">楼 层</span>
+              <div v-if="building" v-loading="buildingLoading">
+                <span class="floor-item" @click="changeFloor(item.FloorID)" :class="{floorItemChoose:(item.FloorID == floor)}"
+                  v-for="item in buildingObj.Floor" :key="item.FloorID">{{ item.FloorLocalName }}</span>
+              </div>
             </div>
-          </div>
           </el-scrollbar>
+          <div style="float:right;height:100%;width:calc(100% - 152px);border:1px solid rgb(201,201,201);border-left:none;">
+            <cenote-graphy ref="cenotegraphy"></cenote-graphy>
+          </div>
         </div>
+
       </div>
       <div v-show="isMyTab == 2" class="data-item">
-        <related-spaceList :space="space" ref="spacelist"></related-spaceList>
+        <related-spaceList :space="space" :buildingList="buildingList" :spaceType="spaceType" :floorType="floorType" ref="relatedSpacelist">
+        </related-spaceList>
       </div>
     </div>
   </div>
@@ -47,26 +62,33 @@
 import spaceSelect from "@/components/ledger/lib/spaceSelect";
 import relatedSpaceList from "@/views/ledger/cenotelist/relatedSpaceList";
 import addSpaceDialog from '@/components/ledger/cenote/dialog/addSpaceDialog';
-import { queryDictionaryHead, buildingQuery } from '@/api/scan/request'
+import { queryDictionaryHead, buildingQuery, shaftSpaceTypeQuery, shaftSpaceBuildingQuery } from '@/api/scan/request';
+import cenoteGraphy from '@/components/ledger/lib/cenoteGraphy'
+import { mapGetters } from 'vuex'
 export default {
   data() {
     return {
       isMyTab: 1,//默认平面图
       isEdit: false,//是否正在编辑
       building: '',//当前建筑id
-      buildingObj:{},//当前建筑obj
+      buildingObj: {},//当前建筑obj
       buildingList: [],
       space: '',//当前业务空间
+      spaceList: [],//空间list
       floor: '',//当前楼层
       dialogVisible: false,//添加空间弹窗
       spaceType: {},//空间种类
       floorType: {},//子组件楼层信息
+      buildingLoading: false,//左侧列表加载
+      showSpaceDot: false,//空间提示红点
+      showBuildDot: false,//楼层提示红点
     }
   },
   computed: {
     cenoteObj() {
       return this.$route.query;
-    }
+    },
+    ...mapGetters("layout", ["projectId"])
   },
   props: {
 
@@ -74,36 +96,115 @@ export default {
   components: {
     spaceSelect,
     relatedSpaceList,
-    addSpaceDialog
+    addSpaceDialog,
+    cenoteGraphy
   },
   created() {
-    this.load();
-    let pa = {
-      Filters: `parentId='Space'`
-    }
-    queryDictionaryHead(pa, res => {
-      res.Content.map(t => {
-        if (t.Name != "元空间") {
-          this.spaceType[t.Code] = t.Name;
+    this.getSpaceData();
+  },
+  methods: {
+    //获取空间信息
+    getSpaceData() {
+      if (this.cenoteObj.onlyRead) {
+        let pa = {
+          shaftId: this.$route.query.ShaftId
         }
-      })
-    });
-
-    let param = {
-      Cascade: [
-        { Name: "floor" }
-      ]
-    };
-    buildingQuery(param, res => {
-      this.buildingList = res.Content;
-      if(this.buildingList.length > 0){
-        this.building = this.buildingList[0].BuildID;
-        this.buildingObj = this.buildingList[0];
-        if(this.buildingObj.Floor.length > 0){
-          this.floor = this.buildingObj.Floor[0].FloorID;
+        shaftSpaceTypeQuery(pa, res => {
+          this.spaceList = res.Content.map(item => {
+            return { Code: item.ObjectType, Name: item.ObjectTypeName };
+          });
+          this.showDefaultSpace();
+        });
+      }
+      else {
+        let pa = {
+          Filters: `parentId='Space'`
+        }
+        queryDictionaryHead(pa, res => {
+          this.spaceList = res.Content.map(t => {
+            if (t.Name != "元空间") {
+              this.spaceType[t.Code] = t.Name;
+            }
+            return t;
+          });
+          this.showDefaultSpace();
+        });
+      }
+    },
+    //默认显示第一个空间
+    showDefaultSpace() {
+      if (this.spaceList.length) {
+        this.space = this.spaceList[0].Code;
+        if (this.spaceList.length > 1 && this.cenoteObj.onlyRead) {
+          this.showSpaceDot = true;
         }
       }
-      res.Content.map(item => {
+      //处理空间类型
+      this.spaceList.map(item => {
+        if (item.Name != "元空间") {
+          this.spaceType[item.Code] = item.Name;
+        }
+      });
+      //加载楼层信息
+      this.loadBuildingData();
+    },
+    //获取楼层信息
+    loadBuildingData() {
+      if (this.cenoteObj.onlyRead) {
+        let param = {
+          ShaftId: this.$route.query.ShaftId,
+          ObjectType: this.space
+        };
+        this.buildingLoading = true;
+        shaftSpaceBuildingQuery(param, res => {
+          this.buildingLoading = false;
+          this.buildingList = res.Content;
+          this.buildingList = this.buildingList.map(item => {
+            item.Floor = item.FloorList;
+            item.BuildID = item.BuildingId;
+            item.BuildLocalName = item.BuildingLocalName;
+            if (item.Floor) {
+              item.Floor = item.Floor.map(item => {
+                item.FloorID = item.FloorId;
+                item.FloorLocalName = item.FloorLocalName;
+                return item;
+              })
+            }
+            return item;
+          })
+          this.handleBuildingData();
+        });
+      }
+      else {
+        let param = {
+          Cascade: [
+            { Name: "floor" }
+          ]
+        };
+        buildingQuery(param, res => {
+          this.buildingList = res.Content;
+          this.handleBuildingData();
+        });
+      }
+    },
+    //处理建筑楼层数据
+    handleBuildingData() {
+      if (this.isMyTab == 2) {
+        this.$refs.relatedSpacelist.setFloorData(this.buildingList);
+      }
+      if (this.buildingList.length) {
+        if (this.buildingList.length > 1 && this.cenoteObj.onlyRead) {
+          this.showBuildDot = true;
+        }
+        this.changeBuilding(this.buildingList[0].BuildID);
+      }
+      else {
+        this.buildingList = [];
+        this.building = '';
+        this.floor = '';
+        this.showBuildDot = false;
+      }
+      this.buildingList.map(item => {
         if (item.BuildID && item.BuildLocalName) {
           this.floorType[item.BuildID] = item.BuildLocalName;
           if (item.Floor instanceof Array) {
@@ -115,41 +216,63 @@ export default {
           }
         }
       });
-    });
-  },
-  methods: {
+    },
     //更改业务空间类型
     changeSpace(val) {
+      this.showSpaceDot = false;
       this.space = val;
-      this.load();
-    },
-    //加载数据
-    load() {
-      if (this.isMyTab == 1) {
-
-      }
-      else {
-        this.$refs.spacelist.getSpaceList();
-      }
+      this.floor = '';
+      this.buildingList = [];
+      this.building = '';
+      this.changeFloor('');
+      this.loadBuildingData();
     },
     //更换建筑
-    changeBuilding(bid){
+    changeBuilding(bid) {
+      this.buildingObj = {};
+      this.building = bid;
       this.buildingList.map(item => {
-        if(item.BuildID == bid){
+        if (item.BuildID == bid) {
           this.buildingObj = item;
+          if (item.Floor && item.Floor.length) {
+            // this.floor = item.Floor[0].FloorID
+            this.changeFloor(item.Floor[0].FloorID);
+          }
         }
       })
-      this.load();
+      this.showBuildDot = false;
     },
     //更换楼层
-    changeFloor(fid){
+    changeFloor(fid) {
       this.floor = fid;
-      this.load();
+      this.isEdit = false;
+      let buildfloor = [this.building, fid]
+      this.$refs.cenotegraphy.getFloorMap(buildfloor, this.space)
+    },
+    //取消编辑
+    cancelEdit() {
+      this.isEdit = false;
+      this.$refs.cenotegraphy.cancelEdit();
+    },
+    //保存编辑
+    saveEdit() {
+      this.isEdit = false;
+      this.$refs.cenotegraphy.saveEdit();
     },
     //更换列表或平面图
     changeRadio(val) {
+      if (val == 2) {
+        this.spaceList.unshift({ Code: '', Name: '全部' });
+      }
+      if (val == 1) {
+        if (this.spaceList.length > 0) {
+          this.spaceList.shift();
+        }
+      }
+      if (this.spaceList.length) {
+        this.changeSpace(this.spaceList[0].Code);
+      }
       this.isMyTab = val;
-      this.load();
     },
     //返回
     goBack() {
@@ -159,11 +282,21 @@ export default {
     },
     //更新
     refresh() {
-      this.load();
+      this.$refs.relatedSpacelist.getSpaceList();
+      this.dialogVisible = false;
     }
   },
   watch: {
-
+    isEdit: {
+      handler(val) {
+        this.$refs.cenotegraphy.setSelectAble(val);
+      }
+    },
+    projectId: {
+      handler(val) {
+        this.goBack();
+      }
+    }
   }
 }
 </script>
@@ -244,6 +377,9 @@ export default {
 .data-item {
   height: calc(100% - 44px);
   padding: 10px 0px;
+  /deep/ .is-horizontal {
+    display: none;
+  }
 }
 .floor-item {
   padding: 10px 10px;
@@ -252,9 +388,9 @@ export default {
   cursor: pointer;
 }
 .floorItemChoose {
-  background: rgba(0,0,0,0.2);
+  background: rgba(0, 0, 0, 0.2);
 }
 /deep/ .el-scrollbar__wrap {
-    overflow-x: hidden;
-  }
+  overflow-x: hidden;
+}
 </style>

+ 160 - 27
src/views/ledger/cenotelist/relatedSpaceList.vue

@@ -1,39 +1,44 @@
 <template>
   <div id="relatedSpaceList" style="height:100%;">
     <div class="query">
-      <el-input v-model="keyword" placeholder="请输入关键词" @keyup.enter.native="getSpaceList" style="width:240px;margin:0 0 0 10px;">
+      <el-input v-model="keyword" placeholder="请输入关键词" @keyup.enter.native="getSpaceList" style="width:240px;margin:0 0;">
         <i slot="suffix" class="el-input__icon el-icon-search" @click="getSpaceList"></i>
       </el-input>
-      <floorCascader @change="changeCascader"></floorCascader>
+      <label style="line-height:32px;padding: 0 10px;">所属建筑楼层:</label>
+      <el-cascader v-model="Buildfloor" :options="buildingData" @change="handleChange"></el-cascader>
     </div>
     <div class="table-area" style="height:calc(100% - 52px)">
-      <el-scrollbar style="height:calc(100% - 40px);">
-        <el-table :data="tableData" style="width: 100%;height:100%;" v-loading="loading" :header-cell-style="headerStyle">
-          <el-table-column prop='MeterFunc' label='业务空间建筑楼层' show-overflow-tooltip min-width="200" header-align='center' align="center">
-          </el-table-column>
-          <el-table-column prop='MeterFunc' label='业务空间类型' show-overflow-tooltip min-width="200" header-align='center' align="center">
-          </el-table-column>
-          <el-table-column prop='MeterFunc' label='业务空间本地名称' show-overflow-tooltip min-width="200" header-align='center' align="center">
-          </el-table-column>
-          <el-table-column prop='MeterFunc' label='业务空间本地编码' show-overflow-tooltip min-width="200" header-align='center' align="center">
-          </el-table-column>
-          <el-table-column prop='' label='操作' show-overflow-tooltip min-width="90" header-align='center' align='center'>
-            <template slot-scope="scope">
-              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-      </el-scrollbar>
+      <el-table :data="tableData" style="width: 100%;height:calc(100% - 48px);" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column label='业务空间建筑楼层' show-overflow-tooltip min-width="200" header-align='center' align="center">
+          <template slot-scope="scope">
+            {{ scope.row.BuildingId && floorType[scope.row.BuildingId]? ((floorType[scope.row.BuildingId] || '') + (scope.row.FloorId && floorType[scope.row.FloorId] ? (' - ' + floorType[scope.row.FloorId] || '') : '')) : ''}}
+          </template>
+        </el-table-column>
+        <el-table-column label='业务空间类型' show-overflow-tooltip min-width="200" header-align='center' align="center">
+          <template slot-scope="scope">
+            {{spaceType[scope.row.ObjectType] || ''}}
+          </template>
+        </el-table-column>
+        <el-table-column prop='RoomLocalName' label='业务空间本地名称' show-overflow-tooltip min-width="200" header-align='center' align="center">
+        </el-table-column>
+        <el-table-column prop='RoomLocalID' label='业务空间本地编码' show-overflow-tooltip min-width="200" header-align='center' align="center">
+        </el-table-column>
+        <el-table-column v-if="!$route.query.onlyRead" prop='' label='操作' show-overflow-tooltip min-width="90" header-align='center' align='center'>
+          <template slot-scope="scope">
+            <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
+          </template>
+        </el-table-column>
+      </el-table>
       <!-- 分页 -->
       <el-pagination @size-change="getSpaceList" @current-change="getSpaceList" :current-page="currentPage" :page-sizes="pageSizes"
-        :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.length" style="float:right;">
+        :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.length" style="float:right;padding:20px 20px 0 0;">
       </el-pagination>
     </div>
   </div>
 </template>
 
 <script>
-import floorCascader from "@/components/ledger/lib/floorCascader";
+import { shaftSpaceQuery, spaceInShaftUnlink } from "@/api/scan/request";
 export default {
   data() {
     return {
@@ -48,24 +53,146 @@ export default {
       currentPage: 1,
       keyword: '',//关键词
       floor: '',//当前楼层
-      options: [],//楼层
       tableData: [],//表格数据
       loading: false,//加载
+      Buildfloor: ["all"],//当前选中的楼层
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      buildingData: [],//楼层数据
     }
   },
-  components:{
-    floorCascader
+  components: {
   },
   methods: {
+    //空间列表
     getSpaceList() {
-      console.log(111)
+      this.loading = true;
+      let params = {
+        data: {
+          Filters: "not RoomID isNull",
+          Orders: "RoomLocalName desc",
+          PageNumber: this.page.pageNumber,
+          PageSize: this.page.pageSize
+        },
+        ShaftId: this.$route.query.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.space) {
+        params.data.Filters += `;ObjectType='${this.space}'`;
+      }
+      if (this.keyword) {
+        params.data.Filters += `;RoomName contain '${this.keyword}' or RoomLocalName contain '${this.keyword}'`;
+      }
+      shaftSpaceQuery(params, res => {
+        this.loading = false;
+        this.tableData = res.Content
+      })
+    },
+    //切换楼层
+    handleChange() {
+      this.getSpaceList();
+    },
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          let params = {
+            data: [
+              {
+                ShaftId: this.$route.query.ShaftId,
+                SpaceId: row.RoomID
+              }
+            ],
+            type: row.ObjectType
+          };
+          this.deleteSpInSh(params);
+        })
+        .catch(() => {
+          this.$message("取消删除");
+        });
     },
-    changeCascader(val){
-      console.log(val);
+    // 删除系统所在竖井关系
+    deleteSpInSh(params) {
+      spaceInShaftUnlink(params, res => {
+        this.$message.success("删除成功");
+        this.getSpaceList();
+      });
+    },
+    //楼层
+    setFloorData(val) {
+      if (val && val.length) {
+        let bL = val.concat();
+        bL.map(item => {
+          item.value = item.BuildID;
+          item.label = item.BuildLocalName;
+          item.children = [];
+          if (item.Floor instanceof Array) {
+            item.children = item.Floor.map(fitem => {
+              fitem.value = fitem.FloorID
+              fitem.label = fitem.FloorLocalName
+              return fitem
+            })
+          }
+          if (!this.$route.query.onlyRead) {
+            item.children.unshift({
+              value: "noKnow",
+              label: "未明确建筑"
+            })
+          }
+          item.children.unshift({
+            value: "all",
+            label: "全部"
+          })
+        });
+        if (!this.$route.query.onlyRead) {
+          bL.unshift({
+            value: "all",
+            label: "全部"
+          }, {
+            value: "noKnow",
+            label: "未明确建筑"
+          });
+        }
+        this.buildingData = bL;
+      }
+      else {
+        this.buildingData = [];
+      }
     }
   },
   props: {
     space: '',//空间id
+    buildingList: {//建筑楼层
+      Type: Array,
+      default: []
+    },
+    spaceType: Object,
+    floorType: Object
+  },
+  watch: {
+    space: {
+      handler() {
+        this.getSpaceList();
+      },
+      immediate: true
+    }
   }
 }
 </script>
@@ -78,5 +205,11 @@ export default {
   /deep/ .el-scrollbar__wrap {
     overflow-x: hidden;
   }
+  /deep/ .el-table__body-wrapper{
+    overflow-x:hidden;
+    overflow-y:auto;
+    height:calc(100% - 47px);
+    width:100%;
+  }
 }
 </style>

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

@@ -321,7 +321,9 @@ export default {
     },
     //修改
     handleUpdataTable(changeData, source) {
-      this.formaTableData();
+      if (!this.onlyRead && source != 'ObserveChanges.change') {
+        this.formaTableData();
+      }
     },
     //保存去掉空字段的新增数据
     formaTableData() {
@@ -387,7 +389,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除设备"
@@ -418,13 +420,15 @@ export default {
     },
     //选择型号修改
     firmChange(data) {
-      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brand)
+      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)//生产商ID
+      tools.setDataForKey(this.tableData[this.row], "DPBrandID", data.brandId)//品牌ID
+      tools.setDataForKey(this.tableData[this.row], "DPSpecificationID", data.specificationId)//型号ID
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Manufacturer", data.venderName)
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brandName)
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Specification", data.name)
-      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)
     },
     supplyChange(data) {
-      let changeData = { id: data };
-      this.utilToKey("id", "id", changeData, "SupplierContractID");
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.SupplierContractID", { id: data });
     },
     //如果选择供应商之后
     supplierChange(data) {
@@ -686,4 +690,4 @@ export default {
     margin-top: 10px;
   }
 }
-</style>
+</style>

+ 2 - 2
src/views/ledger/facility/parts/index.vue

@@ -229,7 +229,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除部件"
@@ -530,4 +530,4 @@ export default {
 .el-pagination span:not([class*="suffix"]) {
   vertical-align: middle;
 }
-</style>
+</style>

+ 12 - 8
src/views/ledger/facility/partsmanage/addparts/index.vue

@@ -235,7 +235,7 @@ export default {
         //     params.PropertyId = res.Id
 
         //   })
-        // } 
+        // }
         // else {
         //   await createPart(params, res => {
         //     if (i == newData.length - 1) {
@@ -268,7 +268,9 @@ export default {
     },
     //修改
     handleUpdataTable(changeData, source) {
-      this.formaTableData();
+      if (!this.onlyRead && source != 'ObserveChanges.change') {
+        this.formaTableData();
+      }
     },
     //保存去掉空字段的新增数据
     formaTableData() {
@@ -316,7 +318,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除部件"
@@ -347,9 +349,12 @@ export default {
     },
     //选择型号修改
     firmChange(data) {
-      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brand)
+      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)//生产商ID
+      tools.setDataForKey(this.tableData[this.row], "DPBrandID", data.brandId)//品牌ID
+      tools.setDataForKey(this.tableData[this.row], "DPSpecificationID", data.specificationId)//型号ID
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Manufacturer", data.venderName)
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brandName)
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Specification", data.name)
-      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)
     },
     //供应商变更
     supplierChange(data) {
@@ -367,8 +372,7 @@ export default {
       tools.setDataForKey(this.tableData[this.row], "DPMaintainerID", data.venderId)
     },
     supplyChange(data) {
-      let changeData = { id: data };
-      this.utilToKey("id", "id", changeData, "SupplierContractID");
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.SupplierContractID", { id: data });
     },
     //保险合同
     guaranteeChange(data) {
@@ -599,4 +603,4 @@ export default {
     margin-top: 10px;
   }
 }
-</style>
+</style>

+ 12 - 7
src/views/ledger/facility/partsmanage/index.vue

@@ -406,7 +406,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除部件"
@@ -436,13 +436,19 @@ export default {
     },
     //选择型号修改
     firmChange(data) {
-      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)
-      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brand)
+      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)//生产商ID
+      tools.setDataForKey(this.tableData[this.row], "DPBrandID", data.brandId)//品牌ID
+      tools.setDataForKey(this.tableData[this.row], "DPSpecificationID", data.specificationId)//型号ID
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Manufacturer", data.venderName)
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brandName)
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Specification", data.name)
       this.handleUpdataTable(
         [
           [this.row, "DPManufacturerID", null, data.venderId],
-          [this.row, "LedgerParam.EquipManufactor.Brand", null, data.brand],
+          [this.row, "DPBrandID", null, data.brandId],
+          [this.row, "DPSpecificationID", null, data.specificationId],
+          [this.row, "LedgerParam.EquipManufactor.Manufacturer", null, data.venderName],
+          [this.row, "LedgerParam.EquipManufactor.Brand", null, data.brandName],
           [this.row, "LedgerParam.EquipManufactor.Specification", null, data.name]
         ],
         "edit"
@@ -490,8 +496,7 @@ export default {
       // this.handleUpdataTable([[this.row, "LedgerParam.OperationMainte.Maintainer", null, data.name]], "edit")
     },
     supplyChange(data) {
-      let changeData = { id: data };
-      this.utilToKey("id", "id", changeData, "SupplierContractID");
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.SupplierContractID", { id: data });
     },
     //保险合同
     guaranteeChange(data) {
@@ -759,4 +764,4 @@ export default {
 .el-pagination span:not([class*="suffix"]) {
   vertical-align: middle;
 }
-</style>
+</style>

+ 12 - 8
src/views/ledger/property/addproperty.vue

@@ -205,7 +205,9 @@ export default {
     },
     //修改
     handleUpdataTable(changeData, source) {
-      this.formaTableData()
+      if (!this.onlyRead && source != 'ObserveChanges.change') {
+        this.formaTableData()
+      }
     },
     //保存去掉空字段的新增数据
     formaTableData() {
@@ -252,7 +254,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除资产"
@@ -283,18 +285,20 @@ export default {
     },
     //选择型号修改
     firmChange(data) {
-      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brand)
+      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)//生产商ID
+      tools.setDataForKey(this.tableData[this.row], "DPBrandID", data.brandId)//品牌ID
+      tools.setDataForKey(this.tableData[this.row], "DPSpecificationID", data.specificationId)//型号ID
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Manufacturer", data.venderName)
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Brand", data.brandName)
       tools.setDataForKey(this.tableData[this.row], "LedgerParam.EquipManufactor.Specification", data.name)
-      tools.setDataForKey(this.tableData[this.row], "DPManufacturerID", data.venderId)
     },
     supplyChange(data) {
-      let changeData = { id: data };
-      this.utilToKey("id", "id", changeData, "SupplierContractID");
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.SupplierContractID", { id: data })
     },
     //如果选择供应商之后
     supplierChange(data) {
-      tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.Supplier", data.name)
       tools.setDataForKey(this.tableData[this.row], "DPSupplierID", data.venderId)
+      tools.setDataForKey(this.tableData[this.row], "LedgerParam.SupplyPurchase.Supplier", data.name)
     },
     //保险合同
     guaranteeChange(data) {
@@ -512,4 +516,4 @@ export default {
     margin-top: 10px;
   }
 }
-</style>
+</style>

+ 4 - 4
src/views/ledger/rentlist/index.vue

@@ -144,7 +144,7 @@ export default {
     ]),
     showTypes () {
       return this.onlyRead?
-        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]: 
+        [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]:
         [{value: "Visible", label: '只看采集信息'}, {value: "all", label: '全部'}]
     }
   },
@@ -238,7 +238,7 @@ export default {
         param.Content.push(item);
       });
       await updataRentTableData(param, (res) => {
-        
+
       })
     },
     //保存元空间关联
@@ -366,7 +366,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除租户"
@@ -596,4 +596,4 @@ export default {
 .el-pagination button, .el-pagination span:not([class*=suffix]) {
     vertical-align: middle;
 }
-</style>
+</style>

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

@@ -169,7 +169,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除租户"
@@ -307,4 +307,4 @@ export default {
     margin-top: 10px;
   }
 }
-</style>
+</style>

+ 13 - 9
src/views/ledger/spacelist/index.vue

@@ -13,7 +13,7 @@
     <div class="saga-title">
       <div class="saga-build-mess">
         <!-- <span style="padding-right:12px;color:#999999;">建筑楼层</span> -->
-        <floorCascader @change="changeCascader"></floorCascader>
+        <floorCascader @change="changeCascader" ref="floorCascader"></floorCascader>
         <!-- <el-cascader :options="options" v-model="buildFloorSelectd" :props="props" @change="changeCascader"></el-cascader> -->
       </div>
       <div class="saga-build-tab">
@@ -112,8 +112,8 @@ export default {
         children: "Floor"
       },
       floorToMap: {}, //楼层及其对应的模型图
-      FloorMap: "", //当前选中的楼层对象
-      buildFloorSelectd: ['all'], //当前所选的建筑楼层
+      FloorMap: {}, //当前选中的楼层对象
+      buildFloorSelectd: [''], //当前所选的建筑楼层
       childBackParam: {}
     };
   },
@@ -149,7 +149,10 @@ export default {
           return t;
         })
         if (this.childBackParam.zone) {
-          this.changeCascader(this.buildFloorSelectd)
+          this.changeCascader(this.buildFloorSelectd);
+          this.$refs.floorCascader.setValue(this.buildFloorSelectd)
+        } else {
+          this.$refs.floorCascader.setValue([''])
         }
       })
     },
@@ -171,7 +174,7 @@ export default {
         }).filter(item => item);
         if (this.childBackParam.zone) {
           this.activeName = this.childBackParam.zone;
-          // this.buildFloorSelectd = [this.childBackParam.BuildingId, this.childBackParam.FloorId];
+          this.buildFloorSelectd = this.childBackParam.buildFloorSelectd;
           this.isMyTab = this.childBackParam.isMyTab;
         } else {
           this.activeName = 'GeneralZone';
@@ -199,6 +202,7 @@ export default {
       // 如果选择的是全部或者未明确
       if (val.indexOf('noKnow') > -1 || val.indexOf('all') > -1) {
         this.isMyTab = 2;
+        this.FloorMap = {}
       } else {
         // 选择的是具体某个楼层
         if (!this.floorToMap[val[1]].StructureInfo || !this.floorToMap[val[1]].StructureInfo.FloorMap) {
@@ -211,6 +215,10 @@ export default {
     // 判断切换至图还是表
     changeGraphyOrTable(num) {
       this.activeTabType = this.getItemForType()
+      if(!this.buildFloorSelectd[0]) {
+        this.$message.warning('请选择建筑楼层')
+        return
+      };
       if (num == 2) {
         this.initMessage();
       } else {
@@ -231,10 +239,6 @@ export default {
         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);

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

@@ -83,8 +83,6 @@ export default {
       }
       queryZone(pa, res => {
         this.spaceDetails = res.Content[0];
-        // this.params.BuildingId = this.spaceDetails.BuildingId;
-        // this.params.FloorId = this.spaceDetails.FloorId;
       })
     },
     // 设置iframe

+ 2 - 2
src/views/ledger/system/addsystem.vue

@@ -263,7 +263,7 @@ export default {
         columns: this.formatHeaderType(this.tableHeader),
         rowHeights: 30,
         maxRows: this.tableData.length,
-        contextMenu: {
+        contextMenu: this.onlyRead ? false :{
           items: {
             remove_row: {
               name: "删除设备"
@@ -490,4 +490,4 @@ export default {
     margin-top: 10px;
   }
 }
-</style>
+</style>

+ 39 - 14
src/views/point/config_point/steps/step1.vue

@@ -19,14 +19,24 @@
         <own-dialog :width="'500px'" :index="true" title="位置标签" :dialogVisible="localtionDialog" @cancel="closeFalg">
             <localtion-falg :renderData="renderData" @changeTag="changeLoc"></localtion-falg>
         </own-dialog>
-        <own-dialog :width="'300px'" :index="true" title="导出excel模板" :dialogVisible="downloadExcel" @cancel="close">
-            <div class="center">
-                <el-button type="text" @click="download">下载模板</el-button>
-            </div>
+        <own-dialog :width="'500px'" :index="true" title="导出excel模板" :dialogVisible="downloadExcel" :footer="footer" @cancel="close" @confirm="download">
+            <span>请选择要导出的模板</span>
+            <el-select v-model="exportTemplate" placeholder="请选择模板">
+                <el-option label="模板一" value="0"></el-option>
+                <el-option label="模板二" value="1" :disabled="protocolType!='common'"></el-option>
+            </el-select>
         </own-dialog>
         <own-dialog :width="'500px'" :index="true" :footer="footer" title="导入excel" :dialogVisible="updateExcel" @confirm="sureOfUpload" @cancel="close">
             <div class="center" style="height:100px;">
                 <upload-file accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" @change="changeFile"></upload-file>
+                <p style="font-size:12px;">上传文件大小在1M以内</p>
+            </div>
+            <div>
+                <span>请选择要导入的模板</span>
+                <el-select v-model="importTemplate" placeholder="请选择模板">
+                    <el-option label="模板一" value="0"></el-option>
+                    <el-option label="模板二" value="1" :disabled="protocolType!='common'"></el-option>
+                </el-select>
             </div>
             <div>
                 <el-radio class="radio-left" v-model="radio" label="1">默认使用导入的全部原始点位</el-radio>
@@ -62,6 +72,7 @@
         createPoint,
         downloadTemplete,
         uploadPointFile,
+        uploadPointFile2,
         deletePoint,
         getPointValue
     } from "@/fetch/point_http"
@@ -96,7 +107,9 @@
                 footer: {
                     cancel: '取消',
                     confirm: '确定'
-                }
+                },
+                exportTemplate:'0',
+                importTemplate:'0'
             }
         },
         computed: {
@@ -224,9 +237,13 @@
             },
             //下载excel模板
             download() {
+                let url = `/pointconfig/point/${this.protocolType}/template-export`
+                if(this.exportTemplate=='1'){
+                    url += '2'
+                }
                 axios({
                     method: 'post',
-                    url: `/pointconfig/point/${this.protocolType}/template-export`,
+                    url: url,
                     data: {
                         DataSourceId: this.datasourceId
                     },
@@ -345,7 +362,7 @@
                     columns: showTypes(header),
                     rowHeights: 30,
                     maxRows: this.allData.length,
-                    contextMenu: {
+                     contextMenu: {
                         items: {
                             remove_row: {
                                 name: "删除点位"
@@ -451,7 +468,7 @@
                                flag = false
                                return false
                             }
-                          } 
+                          }
                         }
                         if (flag) {
                             this.createList(createList)
@@ -491,7 +508,7 @@
             },
             /**
              * @param {更新list} updateList
-             * 
+             *
              * 更新点位
              */
             update(updateList) {
@@ -523,11 +540,19 @@
                     param.data.set('DataSourceId', this.datasourceId)
                     param.data.set('Used', this.radio == 1 ? true : false)
                     param.data.set('multipartFile', this.file.raw)
-                    uploadPointFile(param, res => {
-                        this.$message.success("上传成功")
-                        this.getData()
-                        this.updateExcel = false
-                    })
+                    if(this.importTemplate=='1'){
+                        uploadPointFile2(param, res => {
+                            this.$message.success("上传成功")
+                            this.getData()
+                            this.updateExcel = false
+                        })
+                    } else {
+                        uploadPointFile(param, res => {
+                            this.$message.success("上传成功")
+                            this.getData()
+                            this.updateExcel = false
+                        })
+                    }
                 } else {
                     this.$message.info("请选择文件")
                 }

+ 174 - 0
src/views/point/dynamicdata/addRelation/addRelationCommon.scss

@@ -0,0 +1,174 @@
+
+#addRelation {
+  height: 100%;
+  background-color: #fff;
+  padding: 10px 20px 10px 10px;
+  .text-right {
+    text-align: right;
+  }
+  /deep/ .table-container {
+    height: calc(100% - 160px);
+    & > div {
+      width: 49.5%;
+      float: left;
+    }
+    .left-table,
+    .right-table {
+      height: 100%;
+      h5 {
+        line-height: 44px;
+        padding-left: 5px;
+        background-color: #e1e4e5;
+        color: #2b2b2b
+      }
+      .query-box {
+        margin-bottom: 20px;
+        .query-item {
+          float: left;
+          width: 30%;
+          margin: 5px;
+          label {
+            display: block;
+            margin-bottom: 5px;
+          }
+          .el-select {
+            width: 100%;
+          }
+        }
+      }
+      .table-box {
+        height: calc(100% - 50px);
+        position: relative;
+        .AIRecom {
+          position: absolute;
+          width: 96%;
+          height: 160px;
+          bottom: 5px;
+          left: 1%;
+          background-color: rgba(255, 255, 255, 0.9);
+          z-index: 3;
+          font-size: 12px;
+          .r-title {
+            padding-left: 10px;
+            i {
+              float: right;
+            }
+          }
+          .l-title {
+            text-align: right;
+            padding-right: 10px;
+            i {
+              float: left;
+            }
+          }
+          .ai-recom-item {
+            width: 30%;
+            height: 126px;
+            float: left;
+            border: 1px solid #ebeef5;
+            overflow: hidden;
+            padding-top: 5px;
+            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+            p {
+              position: relative;
+              white-space: nowrap;
+              text-overflow: ellipsis;
+              overflow: hidden;
+              padding: 0 8px;
+              z-index: -1;
+              span {
+                float: right;
+              }
+              .el-checkbox {
+                margin-right: 0;
+              }
+            }
+          }
+          .ai-recom-item.r-ai-recom-item + .ai-recom-item {
+            margin-left: 3%;
+          }
+          .l-ai-recom-item {
+            float: right;
+            p {
+              text-align: right;
+              padding-right: 10px;
+              span {
+                float: left;
+              }
+            }
+          }
+          .ai-recom-item.l-ai-recom-item + .ai-recom-item {
+            margin-right: 3%;
+          }
+        }
+      }
+      ::-webkit-scrollbar {
+        display: none;
+      }
+      //列表
+      .custom-table {
+        height: 100%;
+        .bgf5 {
+          background-color: #f5f7fa;
+        }
+        thead {
+          color: #2b2b2b;
+          tr th{
+            border-top:1px solid #EBEEF5;
+          }
+        }
+        thead label.el-checkbox {
+          display: none;
+        }
+      }
+      .l-custom-table {
+        td {
+          text-align: right;
+        }
+      }
+      .tool-tip {
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+  .fr {
+    padding-top: 10px;
+    float: right;
+  }
+  .clearfix:before,
+  .clearfix:after {
+    content: "";
+    display: block;
+    clear: both;
+  }
+  .clearfix {
+    zoom: 1;
+  }
+  .ani-his-plus {
+    position: relative;
+    .plusOne {
+      position: absolute;
+      color: red;
+      left: 50%;
+      bottom: 50%;
+      font-size: 20px;
+      font-weight: 800;
+    }
+    .startAni {
+      animation: fadeToTop 1s;
+    }
+  }
+  @keyframes fadeToTop {
+    0% {
+      left: 50%;
+      bottom: 50%;
+      opacity: 1;
+    }
+    100% {
+      bottom: 100%;
+      opacity: 0;
+    }
+  }
+}

+ 557 - 0
src/views/point/dynamicdata/addRelation/buildRela/index.vue

@@ -0,0 +1,557 @@
+<template>
+  <div id="addRelation">
+    <!-- 数据字典对象类型 -->
+    <el-row style="margin-bottom:16px;">
+      <el-col :span="12">
+        <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
+        <!-- <div style="display:inline-block;width:345px;margin-left:10px;">
+          <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
+        </div> -->
+      </el-col>
+      <el-col :span="12" class="text-right">
+        <el-switch @change="changeType" v-model="isSwitch"></el-switch>
+        <span style="padding:0 5px;">AI辅助</span>
+        <el-button size="medium" @click="showHistory" class="ani-his-plus">
+          本次对应记录 {{num}}
+          <span v-if="showPlus" :class="{'plusOne':true,'startAni':showPlus}">+1</span>
+        </el-button>
+      </el-col>
+    </el-row>
+    <!-- 列表及查询条件区域 -->
+    <div class="table-container clearfix">
+      <div class="left-table">
+        <h5>未对应的{{typeName}}标识</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}标识关键字</label>
+            <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryLeftTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryLeftTable"></i>
+            </el-input>
+          </div>
+          <div class="query-item">
+            <label>数据源</label>
+            <dataSource :Related="false" @change="changeDataSource" :typeName="typeName"></dataSource>
+          </div>
+          <div class="query-item">
+            <label>位置标签</label>
+            <locationFlag :Related="false" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+          </div>
+        </div>
+        <!-- 左侧列表 -->
+        <div class="table-box">
+          <div class="l-custom-table custom-table" v-loading="lTableLoading">
+            <el-table ref="lTableBody" :data="LtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickLeftRow"
+              @selection-change="leftSelectionChange">
+              <el-table-column label="数据源" align="right" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.Datasource }}</template>
+              </el-table-column>
+              <el-table-column label="位置标签" align="right">
+                <template slot-scope="scope">
+                  <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+                    <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column> -->
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="leftRecoList.length&&leftAI&&rArray.length">
+              <div class="l-title">
+                可能对应的{{typeName}}标识
+                <i class="el-icon-close" @click="leftRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in leftRecoList" :key="t.id" class="l-ai-recom-item ai-recom-item" @click="selectAI(i,'l')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.EquipmentMark&&t.EquipmentMark!='null'?t.EquipmentMark:''}}</p>
+                <p>{{t.LocationFlag.toString()}}</p>
+                <!-- <p>{{t.address}}</p> -->
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+      <div class="right-table" style="float: right;">
+        <h5>未对应的{{typeName}}实例</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}实例关键字</label>
+            <el-input :placeholder="`请输入${typeName}实例关键字`" v-model="form.ObjectLocalName" @keyup.enter.native="queryRightTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryRightTable"></i>
+            </el-input>
+          </div>
+          <!-- <div class="query-item">
+            <label>所在位置</label>
+            <location-cas @change="changeLocation" :Related="false" :typeName="typeName"></location-cas>
+          </div> -->
+        </div>
+        <!-- 右侧列表 -->
+        <div class="table-box">
+          <div class="r-custom-table custom-table" v-loading="rTableLoading">
+            <el-table ref="rTableBody" :data="RtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickRightRow"
+              @selection-change="rightSelectionChange">
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+              <el-table-column :label="`${typeName}实例名称`" width="200" class-name="bgf5" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.ObjectLocalName }}</template>
+              </el-table-column>
+              <el-table-column prop="ObjectLocalCode" :label="`${typeName}本地编码`" show-overflow-tooltip></el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip></el-table-column> -->
+              <!-- <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column> -->
+              <!-- <el-table-column label="所在建筑楼层">
+                <template slot-scope="scope">
+                  <el-tooltip :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
+                    placement="top">
+                    <div class="tool-tip">
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column> -->
+              <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip></el-table-column> -->
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="rightRecoList.length&&!leftAI&&lArray.length">
+              <div class="r-title">
+                可能对应的{{typeName}}实例
+                <i class="el-icon-close" @click="rightRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in rightRecoList" :key="t.id" class="r-ai-recom-item ai-recom-item" @click="selectAI(i,'r')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.ObjectLocalName}}</p>
+                <p>
+                  {{t.BuildLocalName&&t.BuildLocalName!='null'&&t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:''}}
+                </p>
+                <p>{{t.RoomLocalName&&t.RoomLocalName!='null'?t.RoomLocalName:''}}</p>
+                <p>{{t.InstallLocation&&t.InstallLocation!='null'?t.InstallLocation:''}}</p>
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+    </div>
+    <!-- 历史记录弹窗 -->
+    <history-dialog ref="history" @delSuc="deleteSuc" :typeName="'space'"></history-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import historyDialog from "@/components/point/dynamicdata/historyDialog";
+import locationCas from "@/components/point/dynamicdata/locationCascader";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import { mapGetters, mapActions } from "vuex";
+import {
+  dynamicPendingobjs,
+  dynamicPendingPoint,
+  dynamicCreateRelation,
+  dynamicDeleteRelation,
+  dynamicPointTypeList,
+  dynamicQueryAI
+} from "@/api/scan/request";
+export default {
+  components: {
+    historyDialog,
+    locationCas,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  data() {
+    return {
+      isSwitch: true, //AI辅助
+      typeName: "", //当前类型
+      LtableData: [], //列表数据
+      RtableData: [], //列表数据
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [], //数据源
+        ObjectLocalName: "", //部件实例关键字
+        locationVal: [] //所在位置下拉
+      }, //查询条件
+      leftRecoList: [], //左推荐
+      rightRecoList: [], //右推荐
+      leftAI: true, //左右推荐公用-互斥
+      lArray: [], //左侧选中数据
+      rArray: [], //右侧选中数据
+      hasRequestedFlag: false, //用于标识是否关联过数据,若是则重新请求第一页数据,
+      showPlus: false, //+1记录动画
+      num: 0, //记录条数
+      timer: null, //函数节流 延时器
+      historyList: [], //操作历史
+      lTableLoading: false, //loading
+      rTableLoading: false,
+      lPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      },
+      rPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      }
+    };
+  },
+  created() {
+    this.typeName = this.$route.query.typeName;
+    this.init();
+  },
+  mounted() {
+    this.lTableBody = this.$refs.lTableBody.bodyWrapper;
+    this.rTableBody = this.$refs.rTableBody.bodyWrapper;
+
+    this.lTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.lTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.lTableBody.clientHeight || this.lTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.lTableBody.scrollHeight || this.lTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        if (this.lPage.pageNumber * this.lPage.pageSize < this.lPage.total) {
+          this.lPage.pageNumber++;
+          if (this.LtableData.length < 50) {
+            this.lPage.pageNumber = 1
+          }
+          this.getLeftData();
+        }
+      }
+    });
+    this.rTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.rTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.rTableBody.clientHeight || this.rTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.rTableBody.scrollHeight || this.rTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        // 获取到的不是全部数据 当滚动到底部 继续获取新的数据
+        if (this.rPage.pageNumber * this.rPage.pageSize < this.rPage.total) {
+          this.rPage.pageNumber++;
+          if (this.RtableData.length < 50) {
+            this.rPage.pageNumber = 1
+          }
+          this.getRightData();
+        }
+      }
+    });
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    requestFlag() {
+      return this.lArray.length > 0 && this.rArray.length > 0;
+    }
+  },
+  methods: {
+    init() {
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //切换AI辅助
+    changeType() { },
+    //推荐中的选择事件
+    selectAI(i, l) {
+      //i 索引 l 左侧AI or 右侧AI
+      if (l == "l") {
+        this.leftRecoList[i].checked = true;
+        this.lArray = [];
+        this.lArray.push(this.leftRecoList[i]);
+      } else {
+        this.rightRecoList[i].checked = true;
+        this.rArray = [];
+        this.rArray.push(this.rightRecoList[i]);
+      }
+    },
+    //查看本次历史记录
+    showHistory() {
+      this.$refs.history.showDialog(this.historyList);
+    },
+    //重新获取数据
+    reGetData() {
+      //删除选中项
+      this.delSelectedRows(this.lArray, this.rArray);
+      let history = { leftList: this.lArray, rightList: this.rArray };
+      this.historyList.push(history); //保存本次操作记录
+      this.lArray = []; //清空选中list
+      this.rArray = [];
+      this.num++; //右上角操作记录
+      this.showPlus = true;
+      setTimeout(() => {
+        this.showPlus = false;
+      }, 800);
+    },
+    //少于20条请求数据-否则删除选中项
+    delSelectedRows(lArray, rArray) {
+      for (let li = this.LtableData.length - 1; li >= 0; li--) {
+        for (let lj = 0; lj < lArray.length; lj++) {
+          if (this.LtableData[li] && (this.LtableData[li].EquipmentMark == lArray[lj].EquipmentMark && this.LtableData[li].SubTypeCode == lArray[lj].SubTypeCode)) {
+            // this.LtableData.splice(i, 1)
+            delete this.LtableData[li]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.LtableData = this.LtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      for (let ri = this.RtableData.length - 1; ri >= 0; ri--) {
+        for (let rj = 0; rj < rArray.length; rj++) {
+          if (this.RtableData[ri] && (this.RtableData[ri].ObjectID == rArray[rj].ObjectID && this.RtableData[ri].SubTypeCode == rArray[rj].SubTypeCode)) {
+            // this.RtableData.splice(i, 1)
+            delete this.RtableData[ri]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.RtableData = this.RtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      if (this.LtableData.length < 20 && this.lPage.Total > 49) {
+        this.queryLeftTable()
+      }
+      if (this.RtableData.length < 20 && this.rPage.Total > 49) {
+        this.queryRightTable()
+      }
+    },
+    //表格中的选中事件
+    leftSelectionChange(selection) {
+      this.lArray = selection;
+    },
+    rightSelectionChange(selection) {
+      this.rArray = selection;
+    },
+    //查询左侧列表
+    queryLeftTable() {
+      this.lPage.pageNumber = 1;
+      if (this.$refs.lTableBody && this.$refs.lTableBody.bodyWrapper) {
+        this.$refs.lTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getLeftData();
+    },
+    //查询右侧列表
+    queryRightTable() {
+      this.rPage.pageNumber = 1;
+      if (this.$refs.rTableBody && this.$refs.rTableBody.bodyWrapper) {
+        this.$refs.rTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getRightData();
+    },
+    //获取待关联点位-左侧
+    getLeftData() {
+      let param = {
+        PageNumber: this.lPage.pageNumber,
+        PageSize: this.lPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件(目前只是单个查,需后台支持)
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.lTableLoading = true;
+      dynamicPendingPoint(param, res => {
+        this.lPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.lPage.pageNumber == 1) {
+          this.LtableData = res.Content;
+        } else {
+          this.LtableData = this.LtableData.concat(res.Content);
+        }
+        this.lTableLoading = false;
+      });
+    },
+    //获取待关联实例-右侧
+    getRightData() {
+      let param = {
+        PageNumber: this.rPage.pageNumber,
+        PageSize: this.rPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.ObjectLocalName && this.form.ObjectLocalName.length) {
+        param.ObjectLocalName = this.form.ObjectLocalName;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.locationVal.length > 0) {
+        param.BuildLocalName = this.form.locationVal[0];
+      }
+      if (this.form.locationVal.length > 1) {
+        param.FloorLocalName = this.form.locationVal[1];
+      }
+      if (this.form.locationVal.length > 2) {
+        param.SpaceType = this.form.locationVal[2];
+      }
+      if (this.form.locationVal.length > 3) {
+        param.RoomLocalName = this.form.locationVal[3];
+      }
+      if (!this.form.locationVal.length) {
+        delete param.BuildLocalName
+        delete param.FloorLocalName
+        delete param.SpaceType
+        delete param.RoomLocalName
+      }
+      this.rTableLoading = true;
+      dynamicPendingobjs(param, res => {
+        this.rPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.rPage.pageNumber == 1) {
+          this.RtableData = res.Content;
+        } else {
+          this.RtableData = this.RtableData.concat(res.Content);
+        }
+        this.rTableLoading = false;
+      });
+    },
+    //清除对应关系成功
+    deleteSuc() {
+      this.num--;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //所在位置修改
+    changeLocation(val) {
+      this.form.locationVal = val;
+      this.queryRightTable();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.form.SubTypeName = val;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.form.Datasource = val;
+      this.queryLeftTable();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.form.LocationFlag = val;
+      this.queryLeftTable();
+    },
+    //返回
+    goback() {
+      this.$router.push({ path: '/point/dynamicdata', query: { typeName: this.typeName } })
+    },
+    //点击行
+    clickLeftRow(row, column, event) {
+      this.$refs.lTableBody.toggleRowSelection(row);
+    },
+    //点击行
+    clickRightRow(row, column, event) {
+      this.$refs.rTableBody.toggleRowSelection(row);
+    },
+  },
+  watch: {
+    projectId(n, o) {
+      this.init();
+    },
+    //判断两边是否均有选中值-创建关联
+    requestFlag(n, o) {
+      if (n) {
+        this.rightRecoList = [];
+        this.leftRecoList = [];
+        let object = {
+          Objs: this.rArray,
+          Points: this.lArray
+        };
+        let param = [];
+        param.push(object);
+        setTimeout(() => {
+          this.reGetData();
+        }, 200)
+        dynamicCreateRelation(param, res => {
+          if (res.Result == "success") {
+            this.$message.success("关联成功");
+          }
+        });
+      }
+    },
+    //AI辅助-左侧
+    lArray(n, o) {
+      //先清空,返回结果后赋值
+      this.rightRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Points: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.rightRecoList = res.Content[0].Objs;
+            this.leftAI = !this.rightRecoList.length
+          })
+        }, 800)
+      } else {
+        this.rightRecoList = []
+        this.leftAI = true;
+      }
+    },
+    //AI辅助-右侧
+    rArray(n, o) {
+      this.leftRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Objs: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.leftRecoList = res.Content[0].Points;
+            this.leftAI = !!this.leftRecoList.length
+          })
+        }, 800)
+      } else {
+        this.leftRecoList = []
+        this.leftAI = false
+      }
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+@import "../addRelationCommon.scss";
+</style>
+<style>
+body {
+  overflow-y: hidden;
+}
+</style>

+ 7 - 171
src/views/point/dynamicdata/addRelation/equipRela/index.vue

@@ -4,7 +4,7 @@
     <el-row>
       <el-col :span="12">
         <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
-        <div style="display:inline-block;width:317px;margin-left:10px;">
+        <div style="display:inline-block;width:345px;margin-left:10px;">
           <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
         </div>
       </el-col>
@@ -54,7 +54,8 @@
                 </template>
               </el-table-column>
               <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column>
-              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5"></el-table-column>
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
               <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
             </el-table>
           </div>
@@ -106,10 +107,11 @@
               <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip></el-table-column>
               <el-table-column label="所在建筑楼层">
                 <template slot-scope="scope">
-                  <el-tooltip :content="scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''"
+                  <el-tooltip
+                    :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
                     placement="top">
                     <div class="tool-tip">
-                      {{scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''}}</div>
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
                   </el-tooltip>
                 </template>
               </el-table-column>
@@ -546,173 +548,7 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-#addRelation {
-  height: 100%;
-  background-color: #fff;
-  padding: 10px 20px 10px 10px;
-  .text-right {
-    text-align: right;
-  }
-  /deep/ .table-container {
-    height: calc(100% - 160px);
-    & > div {
-      width: 49.5%;
-      float: left;
-    }
-    .left-table,
-    .right-table {
-      height: 100%;
-      h5 {
-        line-height: 44px;
-        padding-left: 5px;
-        background-color: #e1e4e5;
-        color: #2b2b2b
-      }
-      .query-box {
-        margin-bottom: 20px;
-        .query-item {
-          float: left;
-          width: 30%;
-          margin: 5px;
-          label {
-            display: block;
-            margin-bottom: 5px;
-          }
-          .el-select {
-            width: 100%;
-          }
-        }
-      }
-      .table-box {
-        height: calc(100% - 50px);
-        position: relative;
-        .AIRecom {
-          position: absolute;
-          width: 96%;
-          height: 160px;
-          bottom: 5px;
-          left: 1%;
-          background-color: rgba(255, 255, 255, 0.9);
-          z-index: 3;
-          font-size: 12px;
-          .r-title {
-            padding-left: 10px;
-            i {
-              float: right;
-            }
-          }
-          .l-title {
-            text-align: right;
-            padding-right: 10px;
-            i {
-              float: left;
-            }
-          }
-          .ai-recom-item {
-            width: 30%;
-            height: 126px;
-            float: left;
-            border: 1px solid #ebeef5;
-            overflow: hidden;
-            padding-top: 5px;
-            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-            p {
-              position: relative;
-              white-space: nowrap;
-              text-overflow: ellipsis;
-              overflow: hidden;
-              padding: 0 8px;
-              z-index: -1;
-              span {
-                float: right;
-              }
-              .el-checkbox {
-                margin-right: 0;
-              }
-            }
-          }
-          .ai-recom-item.r-ai-recom-item + .ai-recom-item {
-            margin-left: 3%;
-          }
-          .l-ai-recom-item {
-            float: right;
-            p {
-              text-align: right;
-              padding-right: 10px;
-              span {
-                float: left;
-              }
-            }
-          }
-          .ai-recom-item.l-ai-recom-item + .ai-recom-item {
-            margin-right: 3%;
-          }
-        }
-      }
-      ::-webkit-scrollbar {
-        display: none;
-      }
-      //列表
-      .custom-table {
-        height: 100%;
-        .bgf5 {
-          background-color: #f5f7fa;
-        }
-        thead label.el-checkbox {
-          display: none;
-        }
-      }
-      .l-custom-table {
-        td {
-          text-align: right;
-        }
-      }
-      .tool-tip {
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-      }
-    }
-  }
-  .fr {
-    padding-top: 10px;
-    float: right;
-  }
-  .clearfix:before,
-  .clearfix:after {
-    content: "";
-    display: block;
-    clear: both;
-  }
-  .clearfix {
-    zoom: 1;
-  }
-  .ani-his-plus {
-    position: relative;
-    .plusOne {
-      position: absolute;
-      color: red;
-      left: 50%;
-      bottom: 50%;
-      font-size: 20px;
-      font-weight: 800;
-    }
-    .startAni {
-      animation: fadeToTop 1s;
-    }
-  }
-  @keyframes fadeToTop {
-    0% {
-      left: 50%;
-      bottom: 50%;
-      opacity: 1;
-    }
-    100% {
-      bottom: 100%;
-      opacity: 0;
-    }
-  }
-}
+@import "../addRelationCommon.scss";
 </style>
 <style>
 body {

+ 564 - 0
src/views/point/dynamicdata/addRelation/floorRela/index.vue

@@ -0,0 +1,564 @@
+<template>
+  <div id="addRelation">
+    <!-- 数据字典对象类型 -->
+    <el-row style="margin-bottom:16px;">
+      <el-col :span="12">
+        <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
+        <!-- <div style="display:inline-block;width:345px;margin-left:10px;">
+          <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
+        </div> -->
+      </el-col>
+      <el-col :span="12" class="text-right">
+        <el-switch @change="changeType" v-model="isSwitch"></el-switch>
+        <span style="padding:0 5px;">AI辅助</span>
+        <el-button size="medium" @click="showHistory" class="ani-his-plus">
+          本次对应记录 {{num}}
+          <span v-if="showPlus" :class="{'plusOne':true,'startAni':showPlus}">+1</span>
+        </el-button>
+      </el-col>
+    </el-row>
+    <!-- 列表及查询条件区域 -->
+    <div class="table-container clearfix">
+      <div class="left-table">
+        <h5>未对应的{{typeName}}标识</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}标识关键字</label>
+            <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryLeftTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryLeftTable"></i>
+            </el-input>
+          </div>
+          <div class="query-item">
+            <label>数据源</label>
+            <dataSource :Related="false" @change="changeDataSource" :typeName="typeName"></dataSource>
+          </div>
+          <div class="query-item">
+            <label>位置标签</label>
+            <locationFlag :Related="false" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+          </div>
+        </div>
+        <!-- 左侧列表 -->
+        <div class="table-box">
+          <div class="l-custom-table custom-table" v-loading="lTableLoading">
+            <el-table ref="lTableBody" :data="LtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickLeftRow"
+              @selection-change="leftSelectionChange">
+              <el-table-column label="数据源" align="right" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.Datasource }}</template>
+              </el-table-column>
+              <el-table-column label="位置标签" align="right">
+                <template slot-scope="scope">
+                  <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+                    <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column> -->
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="leftRecoList.length&&leftAI&&rArray.length">
+              <div class="l-title">
+                可能对应的{{typeName}}标识
+                <i class="el-icon-close" @click="leftRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in leftRecoList" :key="t.id" class="l-ai-recom-item ai-recom-item" @click="selectAI(i,'l')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.EquipmentMark&&t.EquipmentMark!='null'?t.EquipmentMark:''}}</p>
+                <p>{{t.LocationFlag.toString()}}</p>
+                <!-- <p>{{t.address}}</p> -->
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+      <div class="right-table" style="float: right;">
+        <h5>未对应的{{typeName}}实例</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}实例关键字</label>
+            <el-input :placeholder="`请输入${typeName}实例关键字`" v-model="form.ObjectLocalName" @keyup.enter.native="queryRightTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryRightTable"></i>
+            </el-input>
+          </div>
+          <div class="query-item">
+            <label>所属建筑</label>
+            <location-cas @change="changeLocation" :Related="false" :typeName="typeName" :isFloor="true"></location-cas>
+          </div>
+        </div>
+        <!-- 右侧列表 -->
+        <div class="table-box">
+          <div class="r-custom-table custom-table" v-loading="rTableLoading">
+            <el-table ref="rTableBody" :data="RtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickRightRow"
+              @selection-change="rightSelectionChange">
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+              <el-table-column :label="`${typeName}实例名称`" width="200" class-name="bgf5" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.ObjectLocalName }}</template>
+              </el-table-column>
+              <el-table-column prop="ObjectLocalCode" :label="`${typeName}本地编码`" show-overflow-tooltip></el-table-column>
+              <el-table-column :label="`${typeName}顺序号`" show-overflow-tooltip>
+                <template slot-scope="scope">
+                  <el-tooltip :content="(scope.row.ObjectSequenceID&&scope.row.ObjectSequenceID!='null')?scope.row.ObjectSequenceID:''"
+                    placement="top">
+                    <div class="tool-tip">
+                      {{(scope.row.ObjectSequenceID&&scope.row.ObjectSequenceID!='null')?scope.row.ObjectSequenceID:''}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column> -->
+              <el-table-column label="所在建筑">
+                <template slot-scope="scope">
+                  <el-tooltip :content="scope.row.BuildLocalName?scope.row.BuildLocalName:''" placement="top">
+                    <div class="tool-tip">
+                      {{scope.row.BuildLocalName?scope.row.BuildLocalName:''}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip></el-table-column> -->
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="rightRecoList.length&&!leftAI&&lArray.length">
+              <div class="r-title">
+                可能对应的{{typeName}}实例
+                <i class="el-icon-close" @click="rightRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in rightRecoList" :key="t.id" class="r-ai-recom-item ai-recom-item" @click="selectAI(i,'r')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.ObjectLocalName}}</p>
+                <p>
+                  {{t.BuildLocalName&&t.BuildLocalName!='null'&&t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:''}}
+                </p>
+                <p>{{t.RoomLocalName&&t.RoomLocalName!='null'?t.RoomLocalName:''}}</p>
+                <p>{{t.InstallLocation&&t.InstallLocation!='null'?t.InstallLocation:''}}</p>
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+    </div>
+    <!-- 历史记录弹窗 -->
+    <history-dialog ref="history" @delSuc="deleteSuc" :typeName="'space'"></history-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import historyDialog from "@/components/point/dynamicdata/historyDialog";
+import locationCas from "@/components/point/dynamicdata/locationCascader";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import { mapGetters, mapActions } from "vuex";
+import {
+  dynamicPendingobjs,
+  dynamicPendingPoint,
+  dynamicCreateRelation,
+  dynamicDeleteRelation,
+  dynamicPointTypeList,
+  dynamicQueryAI
+} from "@/api/scan/request";
+export default {
+  components: {
+    historyDialog,
+    locationCas,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  data() {
+    return {
+      isSwitch: true, //AI辅助
+      typeName: "", //当前类型
+      LtableData: [], //列表数据
+      RtableData: [], //列表数据
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [], //数据源
+        ObjectLocalName: "", //部件实例关键字
+        locationVal: [] //所在位置下拉
+      }, //查询条件
+      leftRecoList: [], //左推荐
+      rightRecoList: [], //右推荐
+      leftAI: true, //左右推荐公用-互斥
+      lArray: [], //左侧选中数据
+      rArray: [], //右侧选中数据
+      hasRequestedFlag: false, //用于标识是否关联过数据,若是则重新请求第一页数据,
+      showPlus: false, //+1记录动画
+      num: 0, //记录条数
+      timer: null, //函数节流 延时器
+      historyList: [], //操作历史
+      lTableLoading: false, //loading
+      rTableLoading: false,
+      lPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      },
+      rPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      }
+    };
+  },
+  created() {
+    this.typeName = this.$route.query.typeName;
+    this.init();
+  },
+  mounted() {
+    this.lTableBody = this.$refs.lTableBody.bodyWrapper;
+    this.rTableBody = this.$refs.rTableBody.bodyWrapper;
+
+    this.lTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.lTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.lTableBody.clientHeight || this.lTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.lTableBody.scrollHeight || this.lTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        if (this.lPage.pageNumber * this.lPage.pageSize < this.lPage.total) {
+          this.lPage.pageNumber++;
+          if (this.LtableData.length < 50) {
+            this.lPage.pageNumber = 1
+          }
+          this.getLeftData();
+        }
+      }
+    });
+    this.rTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.rTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.rTableBody.clientHeight || this.rTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.rTableBody.scrollHeight || this.rTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        // 获取到的不是全部数据 当滚动到底部 继续获取新的数据
+        if (this.rPage.pageNumber * this.rPage.pageSize < this.rPage.total) {
+          this.rPage.pageNumber++;
+          if (this.RtableData.length < 50) {
+            this.rPage.pageNumber = 1
+          }
+          this.getRightData();
+        }
+      }
+    });
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    requestFlag() {
+      return this.lArray.length > 0 && this.rArray.length > 0;
+    }
+  },
+  methods: {
+    init() {
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //切换AI辅助
+    changeType() { },
+    //推荐中的选择事件
+    selectAI(i, l) {
+      //i 索引 l 左侧AI or 右侧AI
+      if (l == "l") {
+        this.leftRecoList[i].checked = true;
+        this.lArray = [];
+        this.lArray.push(this.leftRecoList[i]);
+      } else {
+        this.rightRecoList[i].checked = true;
+        this.rArray = [];
+        this.rArray.push(this.rightRecoList[i]);
+      }
+    },
+    //查看本次历史记录
+    showHistory() {
+      this.$refs.history.showDialog(this.historyList);
+    },
+    //重新获取数据
+    reGetData() {
+      //删除选中项
+      this.delSelectedRows(this.lArray, this.rArray);
+      let history = { leftList: this.lArray, rightList: this.rArray };
+      this.historyList.push(history); //保存本次操作记录
+      this.lArray = []; //清空选中list
+      this.rArray = [];
+      this.num++; //右上角操作记录
+      this.showPlus = true;
+      setTimeout(() => {
+        this.showPlus = false;
+      }, 800);
+    },
+    //少于20条请求数据-否则删除选中项
+    delSelectedRows(lArray, rArray) {
+      for (let li = this.LtableData.length - 1; li >= 0; li--) {
+        for (let lj = 0; lj < lArray.length; lj++) {
+          if (this.LtableData[li] && (this.LtableData[li].EquipmentMark == lArray[lj].EquipmentMark && this.LtableData[li].SubTypeCode == lArray[lj].SubTypeCode)) {
+            // this.LtableData.splice(i, 1)
+            delete this.LtableData[li]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.LtableData = this.LtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      for (let ri = this.RtableData.length - 1; ri >= 0; ri--) {
+        for (let rj = 0; rj < rArray.length; rj++) {
+          if (this.RtableData[ri] && (this.RtableData[ri].ObjectID == rArray[rj].ObjectID && this.RtableData[ri].SubTypeCode == rArray[rj].SubTypeCode)) {
+            // this.RtableData.splice(i, 1)
+            delete this.RtableData[ri]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.RtableData = this.RtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      if (this.LtableData.length < 20 && this.lPage.Total > 49) {
+        this.queryLeftTable()
+      }
+      if (this.RtableData.length < 20 && this.rPage.Total > 49) {
+        this.queryRightTable()
+      }
+    },
+    //表格中的选中事件
+    leftSelectionChange(selection) {
+      this.lArray = selection;
+    },
+    rightSelectionChange(selection) {
+      this.rArray = selection;
+    },
+    //查询左侧列表
+    queryLeftTable() {
+      this.lPage.pageNumber = 1;
+      if (this.$refs.lTableBody && this.$refs.lTableBody.bodyWrapper) {
+        this.$refs.lTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getLeftData();
+    },
+    //查询右侧列表
+    queryRightTable() {
+      this.rPage.pageNumber = 1;
+      if (this.$refs.rTableBody && this.$refs.rTableBody.bodyWrapper) {
+        this.$refs.rTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getRightData();
+    },
+    //获取待关联点位-左侧
+    getLeftData() {
+      let param = {
+        PageNumber: this.lPage.pageNumber,
+        PageSize: this.lPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件(目前只是单个查,需后台支持)
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.lTableLoading = true;
+      dynamicPendingPoint(param, res => {
+        this.lPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.lPage.pageNumber == 1) {
+          this.LtableData = res.Content;
+        } else {
+          this.LtableData = this.LtableData.concat(res.Content);
+        }
+        this.lTableLoading = false;
+      });
+    },
+    //获取待关联实例-右侧
+    getRightData() {
+      let param = {
+        PageNumber: this.rPage.pageNumber,
+        PageSize: this.rPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.ObjectLocalName && this.form.ObjectLocalName.length) {
+        param.ObjectLocalName = this.form.ObjectLocalName;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.locationVal.length > 0) {
+        param.BuildLocalName = this.form.locationVal[0];
+      }
+      if (this.form.locationVal.length > 1) {
+        param.FloorLocalName = this.form.locationVal[1];
+      }
+      if (this.form.locationVal.length > 2) {
+        param.SpaceType = this.form.locationVal[2];
+      }
+      if (this.form.locationVal.length > 3) {
+        param.RoomLocalName = this.form.locationVal[3];
+      }
+      if (!this.form.locationVal.length) {
+        delete param.BuildLocalName
+        delete param.FloorLocalName
+        delete param.SpaceType
+        delete param.RoomLocalName
+      }
+      this.rTableLoading = true;
+      dynamicPendingobjs(param, res => {
+        this.rPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.rPage.pageNumber == 1) {
+          this.RtableData = res.Content;
+        } else {
+          this.RtableData = this.RtableData.concat(res.Content);
+        }
+        this.rTableLoading = false;
+      });
+    },
+    //清除对应关系成功
+    deleteSuc() {
+      this.num--;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //所在位置修改
+    changeLocation(val) {
+      this.form.locationVal = val;
+      this.queryRightTable();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.form.SubTypeName = val;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.form.Datasource = val;
+      this.queryLeftTable();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.form.LocationFlag = val;
+      this.queryLeftTable();
+    },
+    //返回
+    goback() {
+      this.$router.push({ path: '/point/dynamicdata', query: { typeName: this.typeName } })
+    },
+    //点击行
+    clickLeftRow(row, column, event) {
+      this.$refs.lTableBody.toggleRowSelection(row);
+    },
+    //点击行
+    clickRightRow(row, column, event) {
+      this.$refs.rTableBody.toggleRowSelection(row);
+    },
+  },
+  watch: {
+    projectId(n, o) {
+      this.init();
+    },
+    //判断两边是否均有选中值-创建关联
+    requestFlag(n, o) {
+      if (n) {
+        this.rightRecoList = [];
+        this.leftRecoList = [];
+        let object = {
+          Objs: this.rArray,
+          Points: this.lArray
+        };
+        let param = [];
+        param.push(object);
+        setTimeout(() => {
+          this.reGetData();
+        }, 200)
+        dynamicCreateRelation(param, res => {
+          if (res.Result == "success") {
+            this.$message.success("关联成功");
+          }
+        });
+      }
+    },
+    //AI辅助-左侧
+    lArray(n, o) {
+      //先清空,返回结果后赋值
+      this.rightRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Points: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.rightRecoList = res.Content[0].Objs;
+            this.leftAI = !this.rightRecoList.length
+          })
+        }, 800)
+      } else {
+        this.rightRecoList = []
+        this.leftAI = true;
+      }
+    },
+    //AI辅助-右侧
+    rArray(n, o) {
+      this.leftRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Objs: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.leftRecoList = res.Content[0].Points;
+            this.leftAI = !!this.leftRecoList.length
+          })
+        }, 800)
+      } else {
+        this.leftRecoList = []
+        this.leftAI = false
+      }
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+@import "../addRelationCommon.scss";
+</style>
+<style>
+body {
+  overflow-y: hidden;
+}
+</style>

+ 7 - 171
src/views/point/dynamicdata/addRelation/partsRela/index.vue

@@ -4,7 +4,7 @@
     <el-row>
       <el-col :span="12">
         <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
-        <div style="display:inline-block;width:317px;margin-left:10px;">
+        <div style="display:inline-block;width:345px;margin-left:10px;">
           <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
         </div>
       </el-col>
@@ -54,7 +54,8 @@
                 </template>
               </el-table-column>
               <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column>
-              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5"></el-table-column>
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
               <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
             </el-table>
           </div>
@@ -107,10 +108,11 @@
               <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column>
               <el-table-column label="所在建筑楼层">
                 <template slot-scope="scope">
-                  <el-tooltip :content="scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''"
+                  <el-tooltip
+                    :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
                     placement="top">
                     <div class="tool-tip">
-                      {{scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''}}</div>
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
                   </el-tooltip>
                 </template>
               </el-table-column>
@@ -547,173 +549,7 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-#addRelation {
-  height: 100%;
-  background-color: #fff;
-  padding: 10px 20px 10px 10px;
-  .text-right {
-    text-align: right;
-  }
-  /deep/ .table-container {
-    height: calc(100% - 160px);
-    & > div {
-      width: 49.5%;
-      float: left;
-    }
-    .left-table,
-    .right-table {
-      height: 100%;
-      h5 {
-        line-height: 44px;
-        padding-left: 5px;
-        background-color: #e1e4e5;
-        color: #2b2b2b
-      }
-      .query-box {
-        margin-bottom: 20px;
-        .query-item {
-          float: left;
-          width: 30%;
-          margin: 5px;
-          label {
-            display: block;
-            margin-bottom: 5px;
-          }
-          .el-select {
-            width: 100%;
-          }
-        }
-      }
-      .table-box {
-        height: calc(100% - 50px);
-        position: relative;
-        .AIRecom {
-          position: absolute;
-          width: 96%;
-          height: 160px;
-          bottom: 5px;
-          left: 1%;
-          background-color: rgba(255, 255, 255, 0.9);
-          z-index: 3;
-          font-size: 12px;
-          .r-title {
-            padding-left: 10px;
-            i {
-              float: right;
-            }
-          }
-          .l-title {
-            text-align: right;
-            padding-right: 10px;
-            i {
-              float: left;
-            }
-          }
-          .ai-recom-item {
-            width: 30%;
-            height: 126px;
-            float: left;
-            border: 1px solid #ebeef5;
-            overflow: hidden;
-            padding-top: 5px;
-            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-            p {
-              position: relative;
-              white-space: nowrap;
-              text-overflow: ellipsis;
-              overflow: hidden;
-              padding: 0 8px;
-              z-index: -1;
-              span {
-                float: right;
-              }
-              .el-checkbox {
-                margin-right: 0;
-              }
-            }
-          }
-          .ai-recom-item.r-ai-recom-item + .ai-recom-item {
-            margin-left: 3%;
-          }
-          .l-ai-recom-item {
-            float: right;
-            p {
-              text-align: right;
-              padding-right: 10px;
-              span {
-                float: left;
-              }
-            }
-          }
-          .ai-recom-item.l-ai-recom-item + .ai-recom-item {
-            margin-right: 3%;
-          }
-        }
-      }
-      ::-webkit-scrollbar {
-        display: none;
-      }
-      //列表
-      .custom-table {
-        height: 100%;
-        .bgf5 {
-          background-color: #f5f7fa;
-        }
-        thead label.el-checkbox {
-          display: none;
-        }
-      }
-      .l-custom-table {
-        td {
-          text-align: right;
-        }
-      }
-      .tool-tip {
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-      }
-    }
-  }
-  .fr {
-    padding-top: 10px;
-    float: right;
-  }
-  .clearfix:before,
-  .clearfix:after {
-    content: "";
-    display: block;
-    clear: both;
-  }
-  .clearfix {
-    zoom: 1;
-  }
-  .ani-his-plus {
-    position: relative;
-    .plusOne {
-      position: absolute;
-      color: red;
-      left: 50%;
-      bottom: 50%;
-      font-size: 20px;
-      font-weight: 800;
-    }
-    .startAni {
-      animation: fadeToTop 1s;
-    }
-  }
-  @keyframes fadeToTop {
-    0% {
-      left: 50%;
-      bottom: 50%;
-      opacity: 1;
-    }
-    100% {
-      bottom: 100%;
-      opacity: 0;
-    }
-  }
-}
+@import "../addRelationCommon.scss";
 </style>
 <style>
 body {

+ 558 - 0
src/views/point/dynamicdata/addRelation/projectRela/index.vue

@@ -0,0 +1,558 @@
+<template>
+  <div id="addRelation">
+    <!-- 数据字典对象类型 -->
+    <el-row style="margin-bottom:16px;">
+      <el-col :span="12">
+        <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
+        <!-- <div style="display:inline-block;width:345px;margin-left:10px;">
+          <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
+        </div> -->
+      </el-col>
+      <el-col :span="12" class="text-right">
+        <el-switch @change="changeType" v-model="isSwitch"></el-switch>
+        <span style="padding:0 5px;">AI辅助</span>
+        <el-button size="medium" @click="showHistory" class="ani-his-plus">
+          本次对应记录 {{num}}
+          <span v-if="showPlus" :class="{'plusOne':true,'startAni':showPlus}">+1</span>
+        </el-button>
+      </el-col>
+    </el-row>
+    <!-- 列表及查询条件区域 -->
+    <div class="table-container clearfix">
+      <div class="left-table">
+        <h5>未对应的{{typeName}}标识</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}标识关键字</label>
+            <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryLeftTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryLeftTable"></i>
+            </el-input>
+          </div>
+          <div class="query-item">
+            <label>数据源</label>
+            <dataSource :Related="false" @change="changeDataSource" :typeName="typeName"></dataSource>
+          </div>
+          <div class="query-item">
+            <label>位置标签</label>
+            <locationFlag :Related="false" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+          </div>
+        </div>
+        <!-- 左侧列表 -->
+        <div class="table-box">
+          <div class="l-custom-table custom-table" v-loading="lTableLoading">
+            <el-table ref="lTableBody" :data="LtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickLeftRow"
+              @selection-change="leftSelectionChange">
+              <el-table-column label="数据源" align="right" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.Datasource }}</template>
+              </el-table-column>
+              <el-table-column label="位置标签" align="right">
+                <template slot-scope="scope">
+                  <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+                    <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column> -->
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="leftRecoList.length&&leftAI&&rArray.length">
+              <div class="l-title">
+                可能对应的{{typeName}}标识
+                <i class="el-icon-close" @click="leftRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in leftRecoList" :key="t.id" class="l-ai-recom-item ai-recom-item" @click="selectAI(i,'l')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.EquipmentMark&&t.EquipmentMark!='null'?t.EquipmentMark:''}}</p>
+                <p>{{t.LocationFlag.toString()}}</p>
+                <!-- <p>{{t.address}}</p> -->
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+      <div class="right-table" style="float: right;">
+        <h5>未对应的{{typeName}}实例</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}实例关键字</label>
+            <el-input :placeholder="`请输入${typeName}实例关键字`" v-model="form.ObjectLocalName" @keyup.enter.native="queryRightTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryRightTable"></i>
+            </el-input>
+          </div>
+          <!-- <div class="query-item">
+            <label>所在位置</label>
+            <location-cas @change="changeLocation" :Related="false" :typeName="typeName"></location-cas>
+          </div> -->
+        </div>
+        <!-- 右侧列表 -->
+        <div class="table-box">
+          <div class="r-custom-table custom-table" v-loading="rTableLoading">
+            <el-table ref="rTableBody" :data="RtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickRightRow"
+              @selection-change="rightSelectionChange">
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+              <el-table-column :label="`${typeName}实例名称`" width="200" class-name="bgf5" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.ObjectLocalName }}</template>
+              </el-table-column>
+              <el-table-column prop="ObjectLocalCode" :label="`${typeName}本地编码`" show-overflow-tooltip></el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip></el-table-column> -->
+              <!-- <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column> -->
+              <!-- <el-table-column label="所在建筑楼层">
+                <template slot-scope="scope">
+                  <el-tooltip
+                    :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
+                    placement="top">
+                    <div class="tool-tip">
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column> -->
+              <!-- <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip></el-table-column> -->
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="rightRecoList.length&&!leftAI&&lArray.length">
+              <div class="r-title">
+                可能对应的{{typeName}}实例
+                <i class="el-icon-close" @click="rightRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in rightRecoList" :key="t.id" class="r-ai-recom-item ai-recom-item" @click="selectAI(i,'r')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.ObjectLocalName}}</p>
+                <p>
+                  {{t.BuildLocalName&&t.BuildLocalName!='null'&&t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:''}}
+                </p>
+                <p>{{t.RoomLocalName&&t.RoomLocalName!='null'?t.RoomLocalName:''}}</p>
+                <p>{{t.InstallLocation&&t.InstallLocation!='null'?t.InstallLocation:''}}</p>
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+    </div>
+    <!-- 历史记录弹窗 -->
+    <history-dialog ref="history" @delSuc="deleteSuc" :typeName="'space'"></history-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import historyDialog from "@/components/point/dynamicdata/historyDialog";
+import locationCas from "@/components/point/dynamicdata/locationCascader";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import { mapGetters, mapActions } from "vuex";
+import {
+  dynamicPendingobjs,
+  dynamicPendingPoint,
+  dynamicCreateRelation,
+  dynamicDeleteRelation,
+  dynamicPointTypeList,
+  dynamicQueryAI
+} from "@/api/scan/request";
+export default {
+  components: {
+    historyDialog,
+    locationCas,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  data() {
+    return {
+      isSwitch: true, //AI辅助
+      typeName: "", //当前类型
+      LtableData: [], //列表数据
+      RtableData: [], //列表数据
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [], //数据源
+        ObjectLocalName: "", //部件实例关键字
+        locationVal: [] //所在位置下拉
+      }, //查询条件
+      leftRecoList: [], //左推荐
+      rightRecoList: [], //右推荐
+      leftAI: true, //左右推荐公用-互斥
+      lArray: [], //左侧选中数据
+      rArray: [], //右侧选中数据
+      hasRequestedFlag: false, //用于标识是否关联过数据,若是则重新请求第一页数据,
+      showPlus: false, //+1记录动画
+      num: 0, //记录条数
+      timer: null, //函数节流 延时器
+      historyList: [], //操作历史
+      lTableLoading: false, //loading
+      rTableLoading: false,
+      lPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      },
+      rPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      }
+    };
+  },
+  created() {
+    this.typeName = this.$route.query.typeName;
+    this.init();
+  },
+  mounted() {
+    this.lTableBody = this.$refs.lTableBody.bodyWrapper;
+    this.rTableBody = this.$refs.rTableBody.bodyWrapper;
+
+    this.lTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.lTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.lTableBody.clientHeight || this.lTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.lTableBody.scrollHeight || this.lTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        if (this.lPage.pageNumber * this.lPage.pageSize < this.lPage.total) {
+          this.lPage.pageNumber++;
+          if (this.LtableData.length < 50) {
+            this.lPage.pageNumber = 1
+          }
+          this.getLeftData();
+        }
+      }
+    });
+    this.rTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.rTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.rTableBody.clientHeight || this.rTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.rTableBody.scrollHeight || this.rTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        // 获取到的不是全部数据 当滚动到底部 继续获取新的数据
+        if (this.rPage.pageNumber * this.rPage.pageSize < this.rPage.total) {
+          this.rPage.pageNumber++;
+          if (this.RtableData.length < 50) {
+            this.rPage.pageNumber = 1
+          }
+          this.getRightData();
+        }
+      }
+    });
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    requestFlag() {
+      return this.lArray.length > 0 && this.rArray.length > 0;
+    }
+  },
+  methods: {
+    init() {
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //切换AI辅助
+    changeType() { },
+    //推荐中的选择事件
+    selectAI(i, l) {
+      //i 索引 l 左侧AI or 右侧AI
+      if (l == "l") {
+        this.leftRecoList[i].checked = true;
+        this.lArray = [];
+        this.lArray.push(this.leftRecoList[i]);
+      } else {
+        this.rightRecoList[i].checked = true;
+        this.rArray = [];
+        this.rArray.push(this.rightRecoList[i]);
+      }
+    },
+    //查看本次历史记录
+    showHistory() {
+      this.$refs.history.showDialog(this.historyList);
+    },
+    //重新获取数据
+    reGetData() {
+      //删除选中项
+      this.delSelectedRows(this.lArray, this.rArray);
+      let history = { leftList: this.lArray, rightList: this.rArray };
+      this.historyList.push(history); //保存本次操作记录
+      this.lArray = []; //清空选中list
+      this.rArray = [];
+      this.num++; //右上角操作记录
+      this.showPlus = true;
+      setTimeout(() => {
+        this.showPlus = false;
+      }, 800);
+    },
+    //少于20条请求数据-否则删除选中项
+    delSelectedRows(lArray, rArray) {
+      for (let li = this.LtableData.length - 1; li >= 0; li--) {
+        for (let lj = 0; lj < lArray.length; lj++) {
+          if (this.LtableData[li] && (this.LtableData[li].EquipmentMark == lArray[lj].EquipmentMark && this.LtableData[li].SubTypeCode == lArray[lj].SubTypeCode)) {
+            // this.LtableData.splice(i, 1)
+            delete this.LtableData[li]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.LtableData = this.LtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      for (let ri = this.RtableData.length - 1; ri >= 0; ri--) {
+        for (let rj = 0; rj < rArray.length; rj++) {
+          if (this.RtableData[ri] && (this.RtableData[ri].ObjectID == rArray[rj].ObjectID && this.RtableData[ri].SubTypeCode == rArray[rj].SubTypeCode)) {
+            // this.RtableData.splice(i, 1)
+            delete this.RtableData[ri]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.RtableData = this.RtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      if (this.LtableData.length < 20 && this.lPage.Total > 49) {
+        this.queryLeftTable()
+      }
+      if (this.RtableData.length < 20 && this.rPage.Total > 49) {
+        this.queryRightTable()
+      }
+    },
+    //表格中的选中事件
+    leftSelectionChange(selection) {
+      this.lArray = selection;
+    },
+    rightSelectionChange(selection) {
+      this.rArray = selection;
+    },
+    //查询左侧列表
+    queryLeftTable() {
+      this.lPage.pageNumber = 1;
+      if (this.$refs.lTableBody && this.$refs.lTableBody.bodyWrapper) {
+        this.$refs.lTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getLeftData();
+    },
+    //查询右侧列表
+    queryRightTable() {
+      this.rPage.pageNumber = 1;
+      if (this.$refs.rTableBody && this.$refs.rTableBody.bodyWrapper) {
+        this.$refs.rTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getRightData();
+    },
+    //获取待关联点位-左侧
+    getLeftData() {
+      let param = {
+        PageNumber: this.lPage.pageNumber,
+        PageSize: this.lPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件(目前只是单个查,需后台支持)
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.lTableLoading = true;
+      dynamicPendingPoint(param, res => {
+        this.lPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.lPage.pageNumber == 1) {
+          this.LtableData = res.Content;
+        } else {
+          this.LtableData = this.LtableData.concat(res.Content);
+        }
+        this.lTableLoading = false;
+      });
+    },
+    //获取待关联实例-右侧
+    getRightData() {
+      let param = {
+        PageNumber: this.rPage.pageNumber,
+        PageSize: this.rPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.ObjectLocalName && this.form.ObjectLocalName.length) {
+        param.ObjectLocalName = this.form.ObjectLocalName;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.locationVal.length > 0) {
+        param.BuildLocalName = this.form.locationVal[0];
+      }
+      if (this.form.locationVal.length > 1) {
+        param.FloorLocalName = this.form.locationVal[1];
+      }
+      if (this.form.locationVal.length > 2) {
+        param.SpaceType = this.form.locationVal[2];
+      }
+      if (this.form.locationVal.length > 3) {
+        param.RoomLocalName = this.form.locationVal[3];
+      }
+      if (!this.form.locationVal.length) {
+        delete param.BuildLocalName
+        delete param.FloorLocalName
+        delete param.SpaceType
+        delete param.RoomLocalName
+      }
+      this.rTableLoading = true;
+      dynamicPendingobjs(param, res => {
+        this.rPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.rPage.pageNumber == 1) {
+          this.RtableData = res.Content;
+        } else {
+          this.RtableData = this.RtableData.concat(res.Content);
+        }
+        this.rTableLoading = false;
+      });
+    },
+    //清除对应关系成功
+    deleteSuc() {
+      this.num--;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //所在位置修改
+    changeLocation(val) {
+      this.form.locationVal = val;
+      this.queryRightTable();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.form.SubTypeName = val;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.form.Datasource = val;
+      this.queryLeftTable();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.form.LocationFlag = val;
+      this.queryLeftTable();
+    },
+    //返回
+    goback() {
+      this.$router.push({ path: '/point/dynamicdata', query: { typeName: this.typeName } })
+    },
+    //点击行
+    clickLeftRow(row, column, event) {
+      this.$refs.lTableBody.toggleRowSelection(row);
+    },
+    //点击行
+    clickRightRow(row, column, event) {
+      this.$refs.rTableBody.toggleRowSelection(row);
+    },
+  },
+  watch: {
+    projectId(n, o) {
+      this.init();
+    },
+    //判断两边是否均有选中值-创建关联
+    requestFlag(n, o) {
+      if (n) {
+        this.rightRecoList = [];
+        this.leftRecoList = [];
+        let object = {
+          Objs: this.rArray,
+          Points: this.lArray
+        };
+        let param = [];
+        param.push(object);
+        setTimeout(() => {
+          this.reGetData();
+        }, 200)
+        dynamicCreateRelation(param, res => {
+          if (res.Result == "success") {
+            this.$message.success("关联成功");
+          }
+        });
+      }
+    },
+    //AI辅助-左侧
+    lArray(n, o) {
+      //先清空,返回结果后赋值
+      this.rightRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Points: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.rightRecoList = res.Content[0].Objs;
+            this.leftAI = !this.rightRecoList.length
+          })
+        }, 800)
+      } else {
+        this.rightRecoList = []
+        this.leftAI = true;
+      }
+    },
+    //AI辅助-右侧
+    rArray(n, o) {
+      this.leftRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Objs: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.leftRecoList = res.Content[0].Points;
+            this.leftAI = !!this.leftRecoList.length
+          })
+        }, 800)
+      } else {
+        this.leftRecoList = []
+        this.leftAI = false
+      }
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+@import "../addRelationCommon.scss";
+</style>
+<style>
+body {
+  overflow-y: hidden;
+}
+</style>

+ 7 - 171
src/views/point/dynamicdata/addRelation/spaceRela/index.vue

@@ -4,7 +4,7 @@
     <el-row>
       <el-col :span="12">
         <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
-        <div style="display:inline-block;width:317px;margin-left:10px;">
+        <div style="display:inline-block;width:345px;margin-left:10px;">
           <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
         </div>
       </el-col>
@@ -54,7 +54,8 @@
                 </template>
               </el-table-column>
               <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column>
-              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5"></el-table-column>
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
               <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
             </el-table>
           </div>
@@ -107,10 +108,11 @@
               <!-- <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column> -->
               <el-table-column label="所在建筑楼层">
                 <template slot-scope="scope">
-                  <el-tooltip :content="scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''"
+                  <el-tooltip
+                    :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
                     placement="top">
                     <div class="tool-tip">
-                      {{scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''}}</div>
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
                   </el-tooltip>
                 </template>
               </el-table-column>
@@ -547,173 +549,7 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-#addRelation {
-  height: 100%;
-  background-color: #fff;
-  padding: 10px 20px 10px 10px;
-  .text-right {
-    text-align: right;
-  }
-  /deep/ .table-container {
-    height: calc(100% - 160px);
-    & > div {
-      width: 49.5%;
-      float: left;
-    }
-    .left-table,
-    .right-table {
-      height: 100%;
-      h5 {
-        line-height: 44px;
-        padding-left: 5px;
-        background-color: #e1e4e5;
-        color: #2b2b2b
-      }
-      .query-box {
-        margin-bottom: 20px;
-        .query-item {
-          float: left;
-          width: 30%;
-          margin: 5px;
-          label {
-            display: block;
-            margin-bottom: 5px;
-          }
-          .el-select {
-            width: 100%;
-          }
-        }
-      }
-      .table-box {
-        height: calc(100% - 50px);
-        position: relative;
-        .AIRecom {
-          position: absolute;
-          width: 96%;
-          height: 160px;
-          bottom: 5px;
-          left: 1%;
-          background-color: rgba(255, 255, 255, 0.9);
-          z-index: 3;
-          font-size: 12px;
-          .r-title {
-            padding-left: 10px;
-            i {
-              float: right;
-            }
-          }
-          .l-title {
-            text-align: right;
-            padding-right: 10px;
-            i {
-              float: left;
-            }
-          }
-          .ai-recom-item {
-            width: 30%;
-            height: 126px;
-            float: left;
-            border: 1px solid #ebeef5;
-            overflow: hidden;
-            padding-top: 5px;
-            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-            p {
-              position: relative;
-              white-space: nowrap;
-              text-overflow: ellipsis;
-              overflow: hidden;
-              padding: 0 8px;
-              z-index: -1;
-              span {
-                float: right;
-              }
-              .el-checkbox {
-                margin-right: 0;
-              }
-            }
-          }
-          .ai-recom-item.r-ai-recom-item + .ai-recom-item {
-            margin-left: 3%;
-          }
-          .l-ai-recom-item {
-            float: right;
-            p {
-              text-align: right;
-              padding-right: 10px;
-              span {
-                float: left;
-              }
-            }
-          }
-          .ai-recom-item.l-ai-recom-item + .ai-recom-item {
-            margin-right: 3%;
-          }
-        }
-      }
-      ::-webkit-scrollbar {
-        display: none;
-      }
-      //列表
-      .custom-table {
-        height: 100%;
-        .bgf5 {
-          background-color: #f5f7fa;
-        }
-        thead label.el-checkbox {
-          display: none;
-        }
-      }
-      .l-custom-table {
-        td {
-          text-align: right;
-        }
-      }
-      .tool-tip {
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-      }
-    }
-  }
-  .fr {
-    padding-top: 10px;
-    float: right;
-  }
-  .clearfix:before,
-  .clearfix:after {
-    content: "";
-    display: block;
-    clear: both;
-  }
-  .clearfix {
-    zoom: 1;
-  }
-  .ani-his-plus {
-    position: relative;
-    .plusOne {
-      position: absolute;
-      color: red;
-      left: 50%;
-      bottom: 50%;
-      font-size: 20px;
-      font-weight: 800;
-    }
-    .startAni {
-      animation: fadeToTop 1s;
-    }
-  }
-  @keyframes fadeToTop {
-    0% {
-      left: 50%;
-      bottom: 50%;
-      opacity: 1;
-    }
-    100% {
-      bottom: 100%;
-      opacity: 0;
-    }
-  }
-}
+@import "../addRelationCommon.scss";
 </style>
 <style>
 body {

+ 6 - 171
src/views/point/dynamicdata/addRelation/systemRela/index.vue

@@ -4,7 +4,7 @@
     <el-row>
       <el-col :span="12">
         <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
-        <div style="display:inline-block;width:317px;margin-left:10px;">
+        <div style="display:inline-block;width:345px;margin-left:10px;">
           <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
         </div>
       </el-col>
@@ -54,7 +54,8 @@
                 </template>
               </el-table-column>
               <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column>
-              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5"></el-table-column>
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
               <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
             </el-table>
           </div>
@@ -107,10 +108,10 @@
               <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column>
               <el-table-column label="所在建筑楼层">
                 <template slot-scope="scope">
-                  <el-tooltip :content="scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''"
+                  <el-tooltip :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
                     placement="top">
                     <div class="tool-tip">
-                      {{scope.row.BuildLocalName?scope.row.BuildLocalName+'-':''+scope.row.FloorLocalName?scope.row.FloorLocalName:''}}</div>
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
                   </el-tooltip>
                 </template>
               </el-table-column>
@@ -547,173 +548,7 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-#addRelation {
-  height: 100%;
-  background-color: #fff;
-  padding: 10px 20px 10px 10px;
-  .text-right {
-    text-align: right;
-  }
-  /deep/ .table-container {
-    height: calc(100% - 160px);
-    & > div {
-      width: 49.5%;
-      float: left;
-    }
-    .left-table,
-    .right-table {
-      height: 100%;
-      h5 {
-        line-height: 44px;
-        padding-left: 5px;
-        background-color: #e1e4e5;
-        color: #2b2b2b
-      }
-      .query-box {
-        margin-bottom: 20px;
-        .query-item {
-          float: left;
-          width: 30%;
-          margin: 5px;
-          label {
-            display: block;
-            margin-bottom: 5px;
-          }
-          .el-select {
-            width: 100%;
-          }
-        }
-      }
-      .table-box {
-        height: calc(100% - 50px);
-        position: relative;
-        .AIRecom {
-          position: absolute;
-          width: 96%;
-          height: 160px;
-          bottom: 5px;
-          left: 1%;
-          background-color: rgba(255, 255, 255, 0.9);
-          z-index: 3;
-          font-size: 12px;
-          .r-title {
-            padding-left: 10px;
-            i {
-              float: right;
-            }
-          }
-          .l-title {
-            text-align: right;
-            padding-right: 10px;
-            i {
-              float: left;
-            }
-          }
-          .ai-recom-item {
-            width: 30%;
-            height: 126px;
-            float: left;
-            border: 1px solid #ebeef5;
-            overflow: hidden;
-            padding-top: 5px;
-            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-            p {
-              position: relative;
-              white-space: nowrap;
-              text-overflow: ellipsis;
-              overflow: hidden;
-              padding: 0 8px;
-              z-index: -1;
-              span {
-                float: right;
-              }
-              .el-checkbox {
-                margin-right: 0;
-              }
-            }
-          }
-          .ai-recom-item.r-ai-recom-item + .ai-recom-item {
-            margin-left: 3%;
-          }
-          .l-ai-recom-item {
-            float: right;
-            p {
-              text-align: right;
-              padding-right: 10px;
-              span {
-                float: left;
-              }
-            }
-          }
-          .ai-recom-item.l-ai-recom-item + .ai-recom-item {
-            margin-right: 3%;
-          }
-        }
-      }
-      ::-webkit-scrollbar {
-        display: none;
-      }
-      //列表
-      .custom-table {
-        height: 100%;
-        .bgf5 {
-          background-color: #f5f7fa;
-        }
-        thead label.el-checkbox {
-          display: none;
-        }
-      }
-      .l-custom-table {
-        td {
-          text-align: right;
-        }
-      }
-      .tool-tip {
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-      }
-    }
-  }
-  .fr {
-    padding-top: 10px;
-    float: right;
-  }
-  .clearfix:before,
-  .clearfix:after {
-    content: "";
-    display: block;
-    clear: both;
-  }
-  .clearfix {
-    zoom: 1;
-  }
-  .ani-his-plus {
-    position: relative;
-    .plusOne {
-      position: absolute;
-      color: red;
-      left: 50%;
-      bottom: 50%;
-      font-size: 20px;
-      font-weight: 800;
-    }
-    .startAni {
-      animation: fadeToTop 1s;
-    }
-  }
-  @keyframes fadeToTop {
-    0% {
-      left: 50%;
-      bottom: 50%;
-      opacity: 1;
-    }
-    100% {
-      bottom: 100%;
-      opacity: 0;
-    }
-  }
-}
+@import "../addRelationCommon.scss";
 </style>
 <style>
 body {

+ 558 - 0
src/views/point/dynamicdata/addRelation/tenantRela/index.vue

@@ -0,0 +1,558 @@
+<template>
+  <div id="addRelation">
+    <!-- 数据字典对象类型 -->
+    <el-row style="margin-bottom:16px;">
+      <el-col :span="12">
+        <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
+        <!-- <div style="display:inline-block;width:345px;margin-left:10px;">
+          <dictionary-device @change="changeDictionary" :Related="false" :typeName="typeName"></dictionary-device>
+        </div> -->
+      </el-col>
+      <el-col :span="12" class="text-right">
+        <el-switch @change="changeType" v-model="isSwitch"></el-switch>
+        <span style="padding:0 5px;">AI辅助</span>
+        <el-button size="medium" @click="showHistory" class="ani-his-plus">
+          本次对应记录 {{num}}
+          <span v-if="showPlus" :class="{'plusOne':true,'startAni':showPlus}">+1</span>
+        </el-button>
+      </el-col>
+    </el-row>
+    <!-- 列表及查询条件区域 -->
+    <div class="table-container clearfix">
+      <div class="left-table">
+        <h5>未对应的{{typeName}}标识</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}标识关键字</label>
+            <el-input :placeholder="`请输入${typeName}标识关键字`" v-model="form.EquipmentMark" @keyup.enter.native="queryLeftTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryLeftTable"></i>
+            </el-input>
+          </div>
+          <div class="query-item">
+            <label>数据源</label>
+            <dataSource :Related="false" @change="changeDataSource" :typeName="typeName"></dataSource>
+          </div>
+          <div class="query-item">
+            <label>位置标签</label>
+            <locationFlag :Related="false" @change="changeLocationFlag" :typeName="typeName"></locationFlag>
+          </div>
+        </div>
+        <!-- 左侧列表 -->
+        <div class="table-box">
+          <div class="l-custom-table custom-table" v-loading="lTableLoading">
+            <el-table ref="lTableBody" :data="LtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickLeftRow"
+              @selection-change="leftSelectionChange">
+              <el-table-column label="数据源" align="right" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.Datasource }}</template>
+              </el-table-column>
+              <el-table-column label="位置标签" align="right">
+                <template slot-scope="scope">
+                  <el-tooltip :content="scope.row.LocationFlag.toString()" placement="top">
+                    <div class="tool-tip">{{scope.row.LocationFlag.toString()}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型关键字`" align="right" show-overflow-tooltip></el-table-column> -->
+              <el-table-column prop="EquipmentMark" :label="`${typeName}标识`" show-overflow-tooltip align="right" width="200" class-name="bgf5">
+              </el-table-column>
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="leftRecoList.length&&leftAI&&rArray.length">
+              <div class="l-title">
+                可能对应的{{typeName}}标识
+                <i class="el-icon-close" @click="leftRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in leftRecoList" :key="t.id" class="l-ai-recom-item ai-recom-item" @click="selectAI(i,'l')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.EquipmentMark&&t.EquipmentMark!='null'?t.EquipmentMark:''}}</p>
+                <p>{{t.LocationFlag.toString()}}</p>
+                <!-- <p>{{t.address}}</p> -->
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+      <div class="right-table" style="float: right;">
+        <h5>未对应的{{typeName}}实例</h5>
+        <!-- 查询条件 -->
+        <div class="query-box clearfix">
+          <div class="query-item">
+            <label>{{typeName}}实例关键字</label>
+            <el-input :placeholder="`请输入${typeName}实例关键字`" v-model="form.ObjectLocalName" @keyup.enter.native="queryRightTable">
+              <i slot="suffix" class="el-input__icon el-icon-search" @click="queryRightTable"></i>
+            </el-input>
+          </div>
+          <div class="query-item">
+            <label>所在位置</label>
+            <location-cas @change="changeLocation" :Related="false" :typeName="typeName"></location-cas>
+          </div>
+        </div>
+        <!-- 右侧列表 -->
+        <div class="table-box">
+          <div class="r-custom-table custom-table" v-loading="rTableLoading">
+            <el-table ref="rTableBody" :data="RtableData" tooltip-effect="dark" style="width: 100%" height="100%" @row-click="clickRightRow"
+              @selection-change="rightSelectionChange">
+              <el-table-column type="selection" width="35" class-name="bgf5"></el-table-column>
+              <el-table-column :label="`${typeName}实例名称`" width="200" class-name="bgf5" show-overflow-tooltip>
+                <template slot-scope="scope">{{ scope.row.ObjectLocalName }}</template>
+              </el-table-column>
+              <el-table-column prop="ObjectLocalCode" :label="`${typeName}本地编码`" show-overflow-tooltip></el-table-column>
+              <!-- <el-table-column prop="SubTypeName" :label="`${typeName}类型`" show-overflow-tooltip></el-table-column> -->
+              <!-- <el-table-column prop="CascadeEquipLocalName" label="所属设备实例" show-overflow-tooltip></el-table-column> -->
+              <!-- <el-table-column label="所在建筑楼层">
+                <template slot-scope="scope">
+                  <el-tooltip
+                    :content="(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')"
+                    placement="top">
+                    <div class="tool-tip">
+                      {{(scope.row.BuildLocalName?scope.row.BuildLocalName+'-':'')+(scope.row.FloorLocalName?scope.row.FloorLocalName:'')}}</div>
+                  </el-tooltip>
+                </template>
+              </el-table-column> -->
+              <el-table-column prop="RoomLocalName" label="所在业务空间" show-overflow-tooltip></el-table-column>
+            </el-table>
+          </div>
+          <!-- 智能推荐 -->
+          <transition name="el-zoom-in-top">
+            <div class="AIRecom" v-show="rightRecoList.length&&!leftAI&&lArray.length">
+              <div class="r-title">
+                可能对应的{{typeName}}实例
+                <i class="el-icon-close" @click="rightRecoList=[]"></i>
+              </div>
+              <div v-for="(t,i) in rightRecoList" :key="t.id" class="r-ai-recom-item ai-recom-item" @click="selectAI(i,'r')">
+                <p>
+                  <el-checkbox v-model="t.checked"></el-checkbox>
+                  <span>{{(t.Proximity*100).toFixed(2)}}%</span>
+                </p>
+                <p>{{t.ObjectLocalName}}</p>
+                <p>
+                  {{t.BuildLocalName&&t.BuildLocalName!='null'&&t.FloorLocalName&&t.FloorLocalName!='null'?t.BuildLocalName+'-'+t.FloorLocalName:''}}
+                </p>
+                <p>{{t.RoomLocalName&&t.RoomLocalName!='null'?t.RoomLocalName:''}}</p>
+                <p>{{t.InstallLocation&&t.InstallLocation!='null'?t.InstallLocation:''}}</p>
+              </div>
+            </div>
+          </transition>
+        </div>
+      </div>
+    </div>
+    <!-- 历史记录弹窗 -->
+    <history-dialog ref="history" @delSuc="deleteSuc" :typeName="'space'"></history-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/tools";
+import historyDialog from "@/components/point/dynamicdata/historyDialog";
+import locationCas from "@/components/point/dynamicdata/locationCascader";
+import dictionaryDevice from "@/components/point/dynamicdata/dictionaryDevice";
+import dataSource from "@/components/point/dynamicdata/dataSource";
+import locationFlag from "@/components/point/dynamicdata/locationFlag";
+import { mapGetters, mapActions } from "vuex";
+import {
+  dynamicPendingobjs,
+  dynamicPendingPoint,
+  dynamicCreateRelation,
+  dynamicDeleteRelation,
+  dynamicPointTypeList,
+  dynamicQueryAI
+} from "@/api/scan/request";
+export default {
+  components: {
+    historyDialog,
+    locationCas,
+    dictionaryDevice,
+    dataSource,
+    locationFlag
+  },
+  data() {
+    return {
+      isSwitch: true, //AI辅助
+      typeName: "", //当前类型
+      LtableData: [], //列表数据
+      RtableData: [], //列表数据
+      form: {
+        EquipmentMark: "", //部件标识关键字
+        SubTypeName: [], //数据字典部件类型
+        LocationFlag: [], //位置标签
+        Datasource: [], //数据源
+        ObjectLocalName: "", //部件实例关键字
+        locationVal: [] //所在位置下拉
+      }, //查询条件
+      leftRecoList: [], //左推荐
+      rightRecoList: [], //右推荐
+      leftAI: true, //左右推荐公用-互斥
+      lArray: [], //左侧选中数据
+      rArray: [], //右侧选中数据
+      hasRequestedFlag: false, //用于标识是否关联过数据,若是则重新请求第一页数据,
+      showPlus: false, //+1记录动画
+      num: 0, //记录条数
+      timer: null, //函数节流 延时器
+      historyList: [], //操作历史
+      lTableLoading: false, //loading
+      rTableLoading: false,
+      lPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      },
+      rPage: {
+        pageNumber: 1,
+        pageSize: 50,
+        total: 0
+      }
+    };
+  },
+  created() {
+    this.typeName = this.$route.query.typeName;
+    this.init();
+  },
+  mounted() {
+    this.lTableBody = this.$refs.lTableBody.bodyWrapper;
+    this.rTableBody = this.$refs.rTableBody.bodyWrapper;
+
+    this.lTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.lTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.lTableBody.clientHeight || this.lTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.lTableBody.scrollHeight || this.lTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        if (this.lPage.pageNumber * this.lPage.pageSize < this.lPage.total) {
+          this.lPage.pageNumber++;
+          if (this.LtableData.length < 50) {
+            this.lPage.pageNumber = 1
+          }
+          this.getLeftData();
+        }
+      }
+    });
+    this.rTableBody.addEventListener("scroll", () => {
+      // 滚动距离
+      let scrollTop = this.rTableBody.scrollTop;
+      // 变量windowHeight是可视区的高度
+      let windowHeight =
+        this.rTableBody.clientHeight || this.rTableBody.clientHeight;
+      // 变量scrollHeight是滚动条的总高度
+      let scrollHeight =
+        this.rTableBody.scrollHeight || this.rTableBody.scrollHeight;
+      if (scrollTop + windowHeight === scrollHeight) {
+        // 获取到的不是全部数据 当滚动到底部 继续获取新的数据
+        if (this.rPage.pageNumber * this.rPage.pageSize < this.rPage.total) {
+          this.rPage.pageNumber++;
+          if (this.RtableData.length < 50) {
+            this.rPage.pageNumber = 1
+          }
+          this.getRightData();
+        }
+      }
+    });
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"]),
+    requestFlag() {
+      return this.lArray.length > 0 && this.rArray.length > 0;
+    }
+  },
+  methods: {
+    init() {
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //切换AI辅助
+    changeType() { },
+    //推荐中的选择事件
+    selectAI(i, l) {
+      //i 索引 l 左侧AI or 右侧AI
+      if (l == "l") {
+        this.leftRecoList[i].checked = true;
+        this.lArray = [];
+        this.lArray.push(this.leftRecoList[i]);
+      } else {
+        this.rightRecoList[i].checked = true;
+        this.rArray = [];
+        this.rArray.push(this.rightRecoList[i]);
+      }
+    },
+    //查看本次历史记录
+    showHistory() {
+      this.$refs.history.showDialog(this.historyList);
+    },
+    //重新获取数据
+    reGetData() {
+      //删除选中项
+      this.delSelectedRows(this.lArray, this.rArray);
+      let history = { leftList: this.lArray, rightList: this.rArray };
+      this.historyList.push(history); //保存本次操作记录
+      this.lArray = []; //清空选中list
+      this.rArray = [];
+      this.num++; //右上角操作记录
+      this.showPlus = true;
+      setTimeout(() => {
+        this.showPlus = false;
+      }, 800);
+    },
+    //少于20条请求数据-否则删除选中项
+    delSelectedRows(lArray, rArray) {
+      for (let li = this.LtableData.length - 1; li >= 0; li--) {
+        for (let lj = 0; lj < lArray.length; lj++) {
+          if (this.LtableData[li] && (this.LtableData[li].EquipmentMark == lArray[lj].EquipmentMark && this.LtableData[li].SubTypeCode == lArray[lj].SubTypeCode)) {
+            // this.LtableData.splice(i, 1)
+            delete this.LtableData[li]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.LtableData = this.LtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      for (let ri = this.RtableData.length - 1; ri >= 0; ri--) {
+        for (let rj = 0; rj < rArray.length; rj++) {
+          if (this.RtableData[ri] && (this.RtableData[ri].ObjectID == rArray[rj].ObjectID && this.RtableData[ri].SubTypeCode == rArray[rj].SubTypeCode)) {
+            // this.RtableData.splice(i, 1)
+            delete this.RtableData[ri]
+            continue; //结束当前本轮循环,开始新的一轮循环
+          }
+        }
+      }
+      this.RtableData = this.RtableData.filter(item => {
+        return !(item == 'undefined')
+      })
+      if (this.LtableData.length < 20 && this.lPage.Total > 49) {
+        this.queryLeftTable()
+      }
+      if (this.RtableData.length < 20 && this.rPage.Total > 49) {
+        this.queryRightTable()
+      }
+    },
+    //表格中的选中事件
+    leftSelectionChange(selection) {
+      this.lArray = selection;
+    },
+    rightSelectionChange(selection) {
+      this.rArray = selection;
+    },
+    //查询左侧列表
+    queryLeftTable() {
+      this.lPage.pageNumber = 1;
+      if (this.$refs.lTableBody && this.$refs.lTableBody.bodyWrapper) {
+        this.$refs.lTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getLeftData();
+    },
+    //查询右侧列表
+    queryRightTable() {
+      this.rPage.pageNumber = 1;
+      if (this.$refs.rTableBody && this.$refs.rTableBody.bodyWrapper) {
+        this.$refs.rTableBody.bodyWrapper.scrollTop = 0
+      }
+      this.getRightData();
+    },
+    //获取待关联点位-左侧
+    getLeftData() {
+      let param = {
+        PageNumber: this.lPage.pageNumber,
+        PageSize: this.lPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件(目前只是单个查,需后台支持)
+      if (this.form.EquipmentMark && this.form.EquipmentMark.length) {
+        param.EquipmentMark = this.form.EquipmentMark;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.LocationFlag.length) {
+        param.LocationFlagList = this.form.LocationFlag;
+      }
+      if (this.form.Datasource.length) {
+        param.DatasourceList = this.form.Datasource;
+      }
+      this.lTableLoading = true;
+      dynamicPendingPoint(param, res => {
+        this.lPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.lPage.pageNumber == 1) {
+          this.LtableData = res.Content;
+        } else {
+          this.LtableData = this.LtableData.concat(res.Content);
+        }
+        this.lTableLoading = false;
+      });
+    },
+    //获取待关联实例-右侧
+    getRightData() {
+      let param = {
+        PageNumber: this.rPage.pageNumber,
+        PageSize: this.rPage.pageSize,
+        TypeNameList: [this.typeName]
+      };
+      //处理查询条件
+      if (this.form.ObjectLocalName && this.form.ObjectLocalName.length) {
+        param.ObjectLocalName = this.form.ObjectLocalName;
+      }
+      if (this.form.SubTypeName.length) {
+        param.SubTypeNameList = this.form.SubTypeName;
+      }
+      if (this.form.locationVal.length > 0) {
+        param.BuildLocalName = this.form.locationVal[0];
+      }
+      if (this.form.locationVal.length > 1) {
+        param.FloorLocalName = this.form.locationVal[1];
+      }
+      if (this.form.locationVal.length > 2) {
+        param.SpaceType = this.form.locationVal[2];
+      }
+      if (this.form.locationVal.length > 3) {
+        param.RoomLocalName = this.form.locationVal[3];
+      }
+      if (!this.form.locationVal.length) {
+        delete param.BuildLocalName
+        delete param.FloorLocalName
+        delete param.SpaceType
+        delete param.RoomLocalName
+      }
+      this.rTableLoading = true;
+      dynamicPendingobjs(param, res => {
+        this.rPage.total = res.PageSize < 50 ? res.PageSize : res.Total;
+        if (this.rPage.pageNumber == 1) {
+          this.RtableData = res.Content;
+        } else {
+          this.RtableData = this.RtableData.concat(res.Content);
+        }
+        this.rTableLoading = false;
+      });
+    },
+    //清除对应关系成功
+    deleteSuc() {
+      this.num--;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //所在位置修改
+    changeLocation(val) {
+      this.form.locationVal = val;
+      this.queryRightTable();
+    },
+    //数据字典部件类型修改
+    changeDictionary(val) {
+      this.form.SubTypeName = val;
+      this.queryLeftTable();
+      this.queryRightTable();
+    },
+    //数据源修改
+    changeDataSource(val) {
+      this.form.Datasource = val;
+      this.queryLeftTable();
+    },
+    //修改位置标签
+    changeLocationFlag(val) {
+      this.form.LocationFlag = val;
+      this.queryLeftTable();
+    },
+    //返回
+    goback() {
+      this.$router.push({ path: '/point/dynamicdata', query: { typeName: this.typeName } })
+    },
+    //点击行
+    clickLeftRow(row, column, event) {
+      this.$refs.lTableBody.toggleRowSelection(row);
+    },
+    //点击行
+    clickRightRow(row, column, event) {
+      this.$refs.rTableBody.toggleRowSelection(row);
+    },
+  },
+  watch: {
+    projectId(n, o) {
+      this.init();
+    },
+    //判断两边是否均有选中值-创建关联
+    requestFlag(n, o) {
+      if (n) {
+        this.rightRecoList = [];
+        this.leftRecoList = [];
+        let object = {
+          Objs: this.rArray,
+          Points: this.lArray
+        };
+        let param = [];
+        param.push(object);
+        setTimeout(() => {
+          this.reGetData();
+        }, 200)
+        dynamicCreateRelation(param, res => {
+          if (res.Result == "success") {
+            this.$message.success("关联成功");
+          }
+        });
+      }
+    },
+    //AI辅助-左侧
+    lArray(n, o) {
+      //先清空,返回结果后赋值
+      this.rightRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Points: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.rightRecoList = res.Content[0].Objs;
+            this.leftAI = !this.rightRecoList.length
+          })
+        }, 800)
+      } else {
+        this.rightRecoList = []
+        this.leftAI = true;
+      }
+    },
+    //AI辅助-右侧
+    rArray(n, o) {
+      this.leftRecoList = [];
+      clearTimeout(this.timer);
+      if (this.isSwitch && n.length) {
+        this.timer = setTimeout(() => {
+          let param = []
+          n.map(item => {
+            param.push({
+              Objs: [item],
+              Top: 3,
+              Proximity: 0.5
+            })
+          })
+          dynamicQueryAI(param, res => {
+            this.leftRecoList = res.Content[0].Points;
+            this.leftAI = !!this.leftRecoList.length
+          })
+        }, 800)
+      } else {
+        this.leftRecoList = []
+        this.leftAI = false
+      }
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+@import "../addRelationCommon.scss";
+</style>
+<style>
+body {
+  overflow-y: hidden;
+}
+</style>

+ 22 - 2
src/views/point/dynamicdata/index.vue

@@ -39,6 +39,18 @@
       <!-- 空间 -->
       <spaceRules v-else-if="curType=='空间'" ref="space" :typeName="curType" @refresh="refreshTabs" :isPending="isPending"
         @autoGroupRela="autoGroupRela"></spaceRules>
+      <!-- 建筑 -->
+      <buildRules v-else-if="curType=='建筑'" ref="build" :typeName="curType" @refresh="refreshTabs" :isPending="isPending"
+        @autoGroupRela="autoGroupRela"></buildRules>
+      <!-- 楼层 -->
+      <floorRules v-else-if="curType=='楼层'" ref="floor" :typeName="curType" @refresh="refreshTabs" :isPending="isPending"
+        @autoGroupRela="autoGroupRela"></floorRules>
+      <!-- 租户 -->
+      <tenantRules v-else-if="curType=='租户'" ref="tenant" :typeName="curType" @refresh="refreshTabs" :isPending="isPending"
+        @autoGroupRela="autoGroupRela"></tenantRules>
+      <!-- 项目 -->
+      <projectRules v-else-if="curType=='项目'" ref="project" :typeName="curType" @refresh="refreshTabs" :isPending="isPending"
+        @autoGroupRela="autoGroupRela"></projectRules>
       <!-- 开发中 -->
       <div v-else>开发中</div>
     </div>
@@ -92,6 +104,10 @@ import equipRules from "@/components/point/dynamicdata/equipRules";
 import partsRules from "@/components/point/dynamicdata/partsRules";
 import systemRules from "@/components/point/dynamicdata/systemRules";
 import spaceRules from "@/components/point/dynamicdata/spaceRules";
+import buildRules from "@/components/point/dynamicdata/buildRules";
+import floorRules from "@/components/point/dynamicdata/floorRules";
+import tenantRules from "@/components/point/dynamicdata/tenantRules";
+import projectRules from "@/components/point/dynamicdata/projectRules";
 import autoGroupRelaDialog from "@/components/point/dynamicdata/autoGroupRelaDialog";
 import {
   dynamicClashConfirm,
@@ -126,6 +142,10 @@ export default {
     partsRules,
     systemRules,
     spaceRules,
+    buildRules,
+    floorRules,
+    tenantRules,
+    projectRules,
     autoGroupRelaDialog
   },
   created() {
@@ -150,7 +170,7 @@ export default {
       dynamicExecuteFeedback({ Id: null }, res => {
         let missionList = res.Content
         missionList.map(mission => {
-          if ('Success/Fail'.indexOf(mission.Completed) > -1) {
+          if ('Success/Fail/Completed'.indexOf(mission.Completed) > -1) {
 
           } else {
             this.missionID = mission.Id
@@ -252,7 +272,7 @@ export default {
         dynamicExecuteFeedback(param, res => {
           this.allApplyClose()
           let response = res.Content[0]
-          if ('Success/Fail'.indexOf(response.Completed) > -1) {
+          if ('Success/Fail/Completed'.indexOf(response.Completed) > -1) {
             setTimeout(() => {
               this.isPending = false;
               this.getPrompt()

+ 21 - 6
src/views/ready/buildfloor/drawGraphy/drawFloor.vue

@@ -33,7 +33,8 @@ export default {
       config: {
         isEdit: false,
         divide: true
-      }
+      },
+      shadeList: []
     };
   },
   props: {
@@ -53,7 +54,7 @@ export default {
   created() {
     this.FloorID = this.$route.query.FloorID;
     if (!this.dialog) {
-      this.getFloorData();
+      this.init();
     }
   },
   mounted() {
@@ -61,6 +62,10 @@ export default {
     this.cadHeight = document.getElementById(`drawFloor${this.id}`).offsetHeight;
   },
   methods: {
+    //
+    init(){
+      this.getFloorData();
+    },
     // 初始化canvas
     initGraphy(Id, type) {
       // type=1 => id:模型id
@@ -117,18 +122,28 @@ export default {
       }
       floorQuery(pa, res => {
         this.floorData = res.Content[0];
+        this.getOtherFloorOutLine();
         this.initGraphy(this.floorData.StructureInfo.FloorMap, 2)
       })
     },
     // 获取绑定该模型id的其他楼层轮廓线
-    getOtherFloorOutLine(){
-      let modelid =  this.$route.query.modelId;
+    getOtherFloorOutLine() {
+      let modelid = this.floorData.ModelId;
       let pa = {
         Filters: `ModelId='${modelid}'`
       }
+      this.shadeList = [];
       floorQuery(pa, res => {
-        console.log(res)
-      })
+        res.Content.map(t => {
+          if (t.FloorID != this.FloorID && t.Outline && t.Outline.length) {
+            let line = t.Outline.map(item => {
+              return new SPoint(item.X, item.Y);
+            })
+            this.shadeList.push(line);
+          }
+        });
+        this.drawMainScene.addAllShade(this.shadeList);
+      });
     },
     // 清空平面图
     clearGraphy() {

+ 5 - 4
src/views/ready/buildfloor/repetitionGraphy.vue

@@ -27,12 +27,12 @@ export default {
   },
   data() {
     return {
-      modelId: "", // 
+      // modelId: "", // 
       isEdit: false, // 是否编辑模式
     };
   },
   created() {
-    this.modelId = this.$route.query.modelId;
+    // this.modelId = this.$route.query.modelId;
     this.FloorID = this.$route.query.FloorID;
     this.BuildID = this.$route.query.BuildID;
   },
@@ -79,7 +79,7 @@ export default {
     // 取消
     cancel() {
       this.isEdit = false;
-      this.$refs.drawFloor.getFloorData();
+      this.$refs.drawFloor.init();
     },
     // 编辑平面图
     editGraphy() {
@@ -87,7 +87,8 @@ export default {
     },
     // 替换模型文件成功
     refresh(modelId) {
-      this.modelId = modelId
+      // this.modelId = modelId
+      this.$refs.drawFloor.init();
     }
   },
   watch: {

+ 2 - 1
src/views/screen/splitscreen/integrateresults/index.vue

@@ -2,7 +2,7 @@
  * @Author: zhangyu
  * @Date: 2019-11-13 17:00:59
  * @Info: 系统集成成果辅助屏
- * @LastEditTime: 2019-11-18 18:50:07
+ * @LastEditTime: 2019-11-27 17:33:10
  -->
 <template>
   <div>
@@ -248,6 +248,7 @@ $borderColor: rgba(201, 201, 201, 1);
     .example-box{
       flex-grow: 1;
       flex-shrink: 1;
+      height: calc(100% - 160px);
       border: 1px solid $borderColor;
     }
   }

+ 270 - 94
src/views/screen/splitscreen/spaceledger/index.vue

@@ -1,46 +1,93 @@
 
 <template>
   <div class="box">
-    <el-container>
+    <el-container style="height:100%">
       <el-header>
-        <div class="boxName">
-          第二屏详情
-        </div>
         <div class="spaceName">
           <b>空间名称:</b>{{spaceDetails.RoomLocalName?spaceDetails.RoomLocalName:"-"}}
         </div>
       </el-header>
       <el-container>
         <el-aside width="450px">
-          <div class="aside-top">
-            <div class="aside-top-left">
-              <p><b>空间功能区类型:</b>{{spaceDetails.RoomFuncType?spaceDetails.RoomFuncType:"-"}}</p>
-              <p><b>备注文字:</b>{{spaceDetails.Intro?spaceDetails.Intro:"-"}}</p>
+          <el-scrollbar>
+            <div class="aside-top">
+              <div class="aside-top-left">
+                <p><b>空间功能区类型:</b>{{spaceDetails.RoomFuncType?spaceDetails.RoomFuncType:"-"}}</p>
+                <p><b>备注文字:</b>{{spaceDetails.Intro?spaceDetails.Intro:"-"}}</p>
+              </div>
+              <div class="aside-top-right">
+                <p><b>空间二维码:</b><span v-if="!spaceDetails.RoomQRCode">-</span></p>
+                <img :src="'/image-service/common/file_get/'+ spaceDetails.RoomQRCode +'?systemId=dataPlatform'" alt="二维码图片"
+                  v-if="spaceDetails.RoomQRCode">
+              </div>
+            </div>
+            <div>
+              <p><b>位置图片:</b></p>
+              <div v-show="spaceDetails.Outline && spaceDetails.Outline[0] && spaceDetails.Outline[0].length" id="graphy" ref="graphy"
+              style="width:400px;height:400px;" v-loading="canvasLoading">
+                <canvas id="floorCanvas" :width="canvasWidth" :height="canvasHeight" ref="canvas" tabindex="0"></canvas>
+              </div>
+            </div>
+            <div v-show="spaceDetails.Outline && !spaceDetails.Outline[0] || !spaceDetails.Outline"
+              style="height: 400px;transform: translateY(50%);textAlign:center;">
+              <i class="icon-wushuju iconfont"></i>
+              数据暂无
             </div>
-            <div class="aside-top-right">
-              <p><b>空间二维码:</b><span v-if="!spaceDetails.RoomQRCode">-</span></p>
-              <img :src="'/image-service/common/file_get/'+ spaceDetails.RoomQRCode +'?systemId=dataPlatform'" alt="二维码图片"
-                v-if="spaceDetails.RoomQRCode">
+            <div class="space-img" v-if="spaceDetails.Pic">
+              <div class="img-box" v-for="(item) in spaceDetails.Pic" :key='`${item.Id}+${item.key}`'>
+                <p><b>空间照片:</b></p>
+                <img :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.key}`" alt="空间图片">
+              </div>
             </div>
-          </div>
-          <div v-if="spaceDetails.Outline && spaceDetails.Outline.length">
-            <p><b>位置图片:</b></p>
-            <graphy ref="graphy"></graphy>
-          </div>
+            <div class="space-img" v-if="!spaceDetails.Pic">
+              <p><b>空间照片:</b></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/2787ad434fc2bc819a5d7deda3855d897a99d528ab4a-e3HRgR_fw658" alt="空间图片">
+              </div>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/5e4e3239dc7eca56eb92ca612d49d824f022b13621d5a-Ga7voM_fw658" alt="空间图片">
+              </div>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/60e2a25564f6ac13e7e16a19dcc3e194d565776231347-1Cw8dg_fw658" alt="空间图片">
+              </div>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/2ea712954c75ff1b1e13329e7e4209f0691b88945c73-JCmkXX_fw658" alt="空间图片">
+              </div>
+            </div>
+          </el-scrollbar>
         </el-aside>
-        <el-main>
+        <el-main style="height:100%">
           <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">
-                <div v-if="activeTab === 'staticData'" style="width:100%;textAlign:left;">
-                  <iframe height="100%" width="100%" :src="iframeSrc" id="staticData"></iframe>
+                <div v-show="activeTab === 'staticData'" style="width:100%;height:100%;textAlign:left;" id="iframe-box">
+                  <!-- <iframe height="100%" width="100%" :src="iframeSrc" id="screenIframe"></iframe> -->
                 </div>
-                <!-- 动态数据 -->
-                <div v-if="activeTab === 'dynamicData'" style="width:100%;textAlign:left;">
-                  <handsontable-main @lookEqu="lookEqu" ref="handsontable" :zoneCode="spaceDetails.ObjectType" :id="`handsontable${spaceDetails.ObjectType}`">
-                  </handsontable-main>
+                <div v-show="activeTab === 'dynamicData'" style="width:100%;height:100%;">
+                  <div class="content-box" style="height:100%;">
+                    <el-table ref="multipleTable" :data="tableData" stripe height="100%" :header-cell-style="headerStyle">
+                      <el-table-column prop="InfoPointName" label="信息点名称">
+                        <template slot-scope="scope">
+                          <div>
+                            <span>{{ scope.row.InfoPointName}}</span>
+                            <span class="unit">{{scope.row.Unit?`${"("+scope.row.Unit+")"}`:""}}</span>
+                          </div>
+                        </template>
+                      </el-table-column>
+                      <el-table-column prop="functionNo" label="表号功能号"></el-table-column>
+                      <el-table-column prop="functionNoDynamicData" label="动态数据"></el-table-column>
+                      <!-- 后台未提供,暂不显示 -->
+                      <!-- <el-table-column prop="LastUpdate" label="数据采集时间"></el-table-column> -->
+                      <template slot="empty">
+                        <div style="height: 60%;transform: translateY(50%);">
+                          <i class="icon-wushuju iconfont"></i>
+                          数据暂无
+                        </div>
+                      </template>
+                    </el-table>
+                  </div>
                 </div>
-                <div v-if="activeTab === 'objectRelationship'" class="objectRelationship">
+                <div v-if="activeTab === 'objectRelationship'" class="objectRelationship" style="height:100%">
                   <div class="objectRelationship-left">
                     <h5>空间内设备:</h5>
                     <eqToSpaceTable :params="params" type="Equipment"></eqToSpaceTable>
@@ -64,12 +111,12 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
-import { queryZone, getAllbusiness, getDataDictionary } from '@/api/scan/request'
-import graphy from "@/components/business_space/newGraphy/graphy";
+import { mapGetters } from "vuex";
+import { queryZone, getAllbusiness, getDataDictionary, floorQuery, buildingQuery, BeatchQueryParam } from '@/api/scan/request'
 import eqToSpaceTable from '@/components/business_space/newTables/eqToSpaceTable'
 import syInSpaceTable from '@/components/business_space/newTables/syInSpaceTable'
-import handsontableMain from "@/components/business_space/business/handsontable";
+import { DivideFloorScene, SpaceItem, ZoneItem, FloorView } from "@saga-web/cad-engine/lib";
+import tools from "@/utils/scan/tools";
 
 export default {
   data() {
@@ -83,38 +130,49 @@ export default {
       checked: true,
       spaceDetails: {},
       iframeSrc: '',
-      projectId: '',
+      proId: '',
       params: {},
+      view: null,
+      scene: null,
+      canvasWidth: 410,
+      canvasHeight: 400,
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      tableData: [],
+      headerStyle: {// 列表样式
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      secret: '',
+      canvasLoading: false
     }
   },
   components: {
-    graphy,
     eqToSpaceTable,
-    syInSpaceTable,
-    handsontableMain
+    syInSpaceTable
   },
-  created() {
-    if (this.$route.query.RoomID && this.$route.query.zone && !this.$route.query.isMyTab) {
-      this.getData();
-      this.setFrame();
-      this.params = this.$route.query;
+  beforeRouteEnter(to, from, next) {
+    if (to.query.RoomID && to.query.zone) {
+      next();
     }
-    this.$nextTick(() => {
-      this.getSpaceImg();
-    })
   },
-  updated() {
-    if (this.activeTab === "dynamicData") {
-      this.$nextTick(() => {
-        this.initMessage();
-      })
+  created() {
+    if (this.$route.name === "spaceLedger" && this.$route.query.RoomID && this.$route.query.zone) {
+      this.getData();
     }
   },
+  updated() { },
   computed: {
-    ...mapGetters('layout', ['userInfo', 'projects', 'userId', 'secret'])
+    ...mapGetters('layout', ['userId', 'projectId'])
   },
   methods: {
     getData() {
+      this.params = this.$route.query;
       // 获取空间数据
       let params = {
         data: {
@@ -124,58 +182,115 @@ export default {
       }
       queryZone(params, res => {
         this.spaceDetails = res.Content[0];
+        if (this.spaceDetails.Outline && this.spaceDetails.Outline[0] && this.spaceDetails.Outline[0].length) {
+          this.getSpaceFloor();
+        }
+        this.setFrame();
+        this.getInFormationPoitnName();
       })
-      this.setFrame();
     },
     setFrame() {
       // 设置静态数据tab的iframe地址
-      this.projectId = localStorage.getItem('projectId');
-      this.iframeSrc = `${process.env.BASE_URL}:8889/#/details?perjectId=${this.projectId}&secret=${this.secret}&FmId=${this.$route.query.RoomID}&type=0&code=${this.$route.query.zone}`
+      this.proId = localStorage.getItem('projectId');
+      this.secret = localStorage.getItem('secret');
+      this.iframeSrc = `${process.env.BASE_URL}:8889/#/details?perjectId=${this.proId}&secret=${this.secret}&FmId=${this.$route.query.RoomID}&type=0&code=${this.$route.query.zone}`
+      let box = document.getElementById('iframe-box');
+      box.innerHTML = '';
+      let iframe = document.createElement('iframe');
+      iframe.src = this.iframeSrc;
+      iframe.style.width = '100%';
+      iframe.style.height = '100%';
+      box.appendChild(iframe);
     },
-    getSpaceImg() {
-      // 获取业务空间位置图片
-      // console.log(this.spaceDetails, 8888)
-      this.buildFloorSelectd = [this.spaceDetails.BuildingId,this.spaceDetails.FloorId];
-      this.$refs.graphy.getData(this.buildFloorSelectd, this.FloorMap, this.activeTabType);
+    getSpaceFloor() {
+      // 获取业务空间楼层
+      let params = {
+        Filters: `FloorID='${this.spaceDetails.FloorId}'`
+      }
+      floorQuery(params, res => {
+        if (res.Content[0] && res.Content[0].StructureInfo && res.Content[0].StructureInfo.FloorMap) {
+          this.FloorMap = res.Content[0].StructureInfo.FloorMap;
+          this.getGraphy();
+        }
+      })
+    },
+    getGraphy() {// 绘制空间位置图片
+      let that = this;
+      that.clearGraphy()
+      that.scene = new DivideFloorScene();
+      this.canvasLoading = true;
+      that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.FloorMap}`).then(res => {
+        that.canvasLoading = false;
+        if (res == 'error') {
+          this.FloorMap = '';
+          this.$message.warning('数据解析异常');
+          return;
+        }
+        that.view.scene = that.scene;
+        that.view.fitSceneToView();
+        let tempArr = {
+          RoomLocalName: this.spaceDetails.RoomLocalName,
+          OutLine: this.spaceDetails.Outline,
+          RoomID: this.spaceDetails.RoomID,
+          Color: "#a384fc",
+        }
+        that.scene.addZoneList([tempArr]);
+        this.scene.isSpaceSelectable = false;
+      })
+    },
+    clearGraphy() {
+      if (this.view && this.view.scene) {
+        this.view.scene = null;
+        return
+      }
+      this.view = new FloorView('floorCanvas')
     },
-    initMessage() {
+    getInFormationPoitnName() {// 获取动态数据
+      let secret = localStorage.getItem('secret');
       let params = {
         data: {
+          Filters: 'InputMode in ["L1","L2","L","M"]',
           Orders: "sort asc",
           PageNumber: 1,
           PageSize: 500
         },
-        type: this.spaceDetails.ObjectType
+        type: this.$route.query.zone
       }
-      getDataDictionary(params, res => {
-        console.log(res, 99999)
-        console.log(this.$refs.handsontable,12345678)
-        this.buildFloorSelectd = [this.spaceDetails.BuildingId,this.spaceDetails.FloorId];
-        this.$refs.handsontable[0].getHeader(res.Content, this.buildFloorSelectd);
-      })
-    },
-    //获取表格主体内容
-    getMain() {
-      if (!!this.hot) {
-        this.hot.destroy();
-        this.hot = null;
+      let param = {
+        secret: secret,
+        ProjId: this.projectId,
+        data: {
+          criterias: []
+        }
       }
-      this.$nextTick(() => {
-        this.initHot();
-      });
-    },
-    lookEqu(infos) {
-      infos.id = infos.RoomID
-      infos.name = infos.RoomLocalName
-      this.floor.facility = true
-      this.$refs.facility.getData(infos, this.buildMess)
-    },
+      getDataDictionary(params, res => {// 获取表号功能号
+        this.tableData = res.Content;
+        this.tableData.map(item => {
+          let cur = tools.dataForKey(this.spaceDetails, item.Path);
+          item.functionNo = cur;
+          param.data.criterias.push({
+            id: this.spaceDetails.RoomID,
+            code: item.InfoPointCode
+          });
+        })
+        BeatchQueryParam(param, res => {// 获取动态数据
+          res.Content.map((item, index) => {
+            tools.setDataForKey(
+              this.spaceDetails,
+              this.tableData[index].Path,
+              this.tableData[index].functionNoDynamicData = item.error ? item.value ? "表号功能号格式错误" : "表号功能号不存在" : "暂未采集到实时数据"
+            );
+          })
+        });
+      })
+    }
   },
   watch: {
     // 监听路由地址,并判断有RoomID和zone,重新请求空间数据
-    "$route"() {
-      if (this.$route.query.RoomID && this.$route.query.zone) {
+    "$route"(to, from) {
+      if (this.$route.name === "spaceLedger" && this.$route.query.RoomID && this.$route.query.zone) {
         this.getData();
+        this.activeTab = 'staticData';
       }
     }
   }
@@ -183,39 +298,50 @@ export default {
 </script>
 
 <style lang="less" scoped>
-#screenBox .screen-router[data-v-6c06ede0] {
+.box.screen-router {
   padding: 0;
+  section {
+    .el-container {
+      padding: 0;
+    }
+  }
 }
 .el-header {
   padding: 0;
-  height: 80px !important;
+  height: 30px !important;
+  margin-top: -10px;
   .boxName {
     color: #fff;
     font-size: 16px;
     line-height: 50px;
     height: 50px !important;
-    padding: 0 20px;
+    padding: 0 10px;
     background-color: #3f4f62;
   }
   .spaceName {
     font-size: 14px;
     line-height: 30px;
-    padding: 0 20px;
-    border-bottom: 1px solid black;
+    border-bottom: 1px solid #e4e7ed;
     box-sizing: border-box;
   }
 }
 .el-aside {
   color: #333;
   border: 1px solid #e4e7ed;
-  margin: 20px 0 0 20px;
-  padding: 20px;
+  margin-top: 10px;
+  padding: 10px;
   box-sizing: border-box;
+  height: calc(100% - 10px);
+  overflow: hidden;
+  .el-scrollbar {
+    height: 100%;
+    overflow: hidden !important;
+  }
   .aside-top {
     overflow: hidden;
+    display: flex;
     .aside-top-left {
-      float: left;
-      width: 300px;
+      flex: 3;
     }
     .aside-top-right {
       float: right;
@@ -226,12 +352,44 @@ export default {
       }
     }
   }
+  .space-img {
+    width: 100%;
+    overflow: hidden;
+    margin-top: 20px;
+    .img-box {
+      float: left;
+      position: relative;
+      width: 45%;
+      height: 180px;
+      margin: 20px 20px 0 0;
+      img {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+}
+.el-scrollbar {
+  width: 430px;
 }
 .el-main {
   color: #333;
   text-align: center;
+  overflow: hidden;
+  width: 100%;
+  padding: 10px 0 0 10px;
+}
+.el-tabs.el-tabs--card.el-tabs--top {
+  height: 100% !important;
+  width: 100%;
 }
 .objectRelationship {
+  height: 100%;
+  width: 100%;
   display: flex;
   .objectRelationship-left,
   .objectRelationship-center,
@@ -239,16 +397,34 @@ export default {
     flex: 1;
     margin-right: 10px;
     text-align: left;
-    height: 100%;
+    height: 100% !important;
   }
 }
-.el-tabs__content {
-  height: 750px;
+#pane-dynamicData {
+  height: calc(100% - 10px);
+}
+.el-tab-pane {
+  height: 100%;
 }
 #pane-staticData {
-  height: 750px;
   div {
     height: 100%;
   }
 }
+.unit {
+  color: rgb(167, 167, 167);
+}
+#floorCanvas {
+  position: static;
+}
+</style>
+<style>
+.el-scrollbar__wrap {
+  height: 100%;
+  overflow-x: hidden !important;
+  overflow-y: auto !important;
+}
+.el-tabs__content {
+  height: calc(100% - 46px) !important;
+}
 </style>