Browse Source

设备台账老代码迁移

duxiangyu 3 years ago
parent
commit
889273c467
100 changed files with 16240 additions and 164 deletions
  1. 4 0
      .npmrc
  2. 5 0
      package.json
  3. 1110 0
      src/components/business_space/business/handsontable.vue
  4. 301 0
      src/components/business_space/dialogs/changeRea.vue
  5. 219 0
      src/components/business_space/dialogs/detailsDialog.vue
  6. 160 0
      src/components/business_space/dialogs/facilityDialog.vue
  7. 151 0
      src/components/business_space/dialogs/influenceDialog.vue
  8. 64 0
      src/components/business_space/dialogs/list/filesDialog.vue
  9. 193 0
      src/components/business_space/dialogs/list/guaranteeDialog.vue
  10. 169 0
      src/components/business_space/dialogs/list/insurerDialog.vue
  11. 168 0
      src/components/business_space/dialogs/list/maintainerDialog.vue
  12. 92 0
      src/components/business_space/dialogs/list/paramDetails.vue
  13. 140 0
      src/components/business_space/dialogs/list/picDialog.vue
  14. 167 0
      src/components/business_space/dialogs/list/supplierDialog.vue
  15. 163 0
      src/components/business_space/dialogs/list/supplyDialog.vue
  16. 318 0
      src/components/business_space/dialogs/list/systemType.vue
  17. 55 0
      src/components/business_space/dialogs/list/uploadImgDialog.vue
  18. 163 0
      src/components/business_space/dialogs/noModelDialog.vue
  19. 57 0
      src/components/business_space/dialogs/notRelated.vue
  20. 114 0
      src/components/business_space/lib/cascaders/assets.vue
  21. 120 0
      src/components/business_space/lib/cascaders/system.vue
  22. 72 0
      src/components/business_space/lib/detailsDia.vue
  23. 123 0
      src/components/business_space/lib/floorCascader.vue
  24. 315 0
      src/components/business_space/lib/formInput.vue
  25. 183 0
      src/components/business_space/lib/lookImages.vue
  26. 58 0
      src/components/business_space/lib/myPagination.vue
  27. 63 0
      src/components/business_space/lib/qrcode.vue
  28. 252 0
      src/components/business_space/lib/uploadFiles.vue
  29. 109 0
      src/components/business_space/lib/uploadImg.vue
  30. 321 0
      src/components/business_space/lib/uploadImgs.vue
  31. 396 0
      src/components/business_space/lib/uploadImgsName.vue
  32. 278 0
      src/components/business_space/newAddDialogs/addEquipDialog.vue
  33. 112 0
      src/components/business_space/newAddDialogs/addSystemDialog.vue
  34. 136 0
      src/components/business_space/newAddDialogs/roomInFloorDialog.vue
  35. 185 0
      src/components/business_space/newGraphy/canvasFun.vue
  36. 41 0
      src/components/business_space/newGraphy/createBSP.vue
  37. 1547 0
      src/components/business_space/newGraphy/graphy.vue
  38. 184 0
      src/components/business_space/newGraphy/unRelateBSP.vue
  39. 183 0
      src/components/business_space/newTables/eqToSpaceTable.vue
  40. 148 0
      src/components/business_space/newTables/syInSpaceTable.vue
  41. 569 0
      src/components/business_space/table/addEquip.vue
  42. 248 0
      src/components/business_space/table/businessTable.vue
  43. 368 0
      src/components/business_space/table/equipTable.vue
  44. 61 0
      src/components/common/myPagination.vue
  45. 203 0
      src/components/dialogs/changeRea.vue
  46. 151 0
      src/components/dialogs/config/infoPoint.vue
  47. 206 0
      src/components/dialogs/detailsDialog.vue
  48. 147 0
      src/components/dialogs/facilityDialog.vue
  49. 144 0
      src/components/dialogs/influenceDialog.vue
  50. 567 0
      src/components/dialogs/list/batchDialog.vue
  51. 142 0
      src/components/dialogs/list/filesDialog.vue
  52. 193 0
      src/components/dialogs/list/guaranteeDialog.vue
  53. 173 0
      src/components/dialogs/list/insurerDialog.vue
  54. 172 0
      src/components/dialogs/list/maintainerDialog.vue
  55. 80 0
      src/components/dialogs/list/menum.vue
  56. 92 0
      src/components/dialogs/list/paramDetails.vue
  57. 170 0
      src/components/dialogs/list/picDialog.vue
  58. 174 0
      src/components/dialogs/list/supplierDialog.vue
  59. 163 0
      src/components/dialogs/list/supplyDialog.vue
  60. 284 0
      src/components/dialogs/list/systemType.vue
  61. 95 0
      src/components/dialogs/list/uploadImgDialog.vue
  62. 161 0
      src/components/dialogs/noModelDialog.vue
  63. 57 0
      src/components/dialogs/notRelated.vue
  64. 3 2
      src/components/ledger/components/handsontables/assets.vue
  65. 22 20
      src/components/ledger/components/handsontables/device.vue
  66. 3 2
      src/components/ledger/components/lib/bimDialog.vue
  67. 7 4
      src/components/ledger/components/lib/cascader.vue
  68. 9 6
      src/components/ledger/components/lib/dynamicDialog.vue
  69. 3 2
      src/components/ledger/components/lib/equipCascader.vue
  70. 6 4
      src/components/ledger/components/lib/floorCascader.vue
  71. 13 9
      src/components/ledger/components/lib/linkassets.vue
  72. 1 1
      src/components/ledger/components/lib/lookImages.vue
  73. 6 4
      src/components/ledger/components/lib/noAllDataFloor.vue
  74. 11 8
      src/components/ledger/components/lib/staticDialog.vue
  75. 15 14
      src/components/ledger/components/tableTransfers.vue
  76. 14 12
      src/components/ledger/facility/index.vue
  77. 18 0
      src/controller/ScanController.ts
  78. 146 0
      src/controller/buildController.ts
  79. 8 0
      src/controller/dicController.ts
  80. 7 0
      src/controller/equipController.ts
  81. 7 0
      src/controller/facilityController.ts
  82. 4 0
      src/controller/floorController.ts
  83. 42 0
      src/data/deviceList.js
  84. 209 0
      src/data/mapTable.js
  85. 358 0
      src/data/menus.js
  86. 394 0
      src/data/old.js
  87. 40 26
      src/router/system.js
  88. 7 2
      src/store/index.js
  89. 251 0
      src/store/modules/layout.ts
  90. 146 0
      src/utils/handsontable/buildFloorData.js
  91. 16 0
      src/utils/handsontable/dataTypeMap.js
  92. 221 0
      src/utils/handsontable/delType.js
  93. 36 0
      src/utils/handsontable/fillterField.js
  94. 160 0
      src/utils/handsontable/mainText.js
  95. 592 0
      src/utils/handsontable/notShow.js
  96. 78 0
      src/utils/hasontableUtils.js
  97. 52 48
      src/utils/http/httpUtils.ts
  98. 33 0
      src/utils/localStorage.js
  99. 43 0
      src/utils/scan/cutHeader.js
  100. 0 0
      src/utils/scan/directive.js

+ 4 - 0
.npmrc

@@ -0,0 +1,4 @@
+@saga-web:registry=http://dev.dp.sagacloud.cn:8082/repository/npm-saga
+email=npm@sagacloud.cn
+_auth="c2FnYTpzYWdh"
+always-auth=true

+ 5 - 0
package.json

@@ -8,7 +8,12 @@
     "build": "vue-cli-service build"
   },
   "dependencies": {
+    "@saga-web/base": "^2.1.28",
+    "@saga-web/cad-engine": "^2.0.595",
+    "@saga-web/draw": "^2.1.114",
+    "@saga-web/graph": "^2.1.139",
     "font-awesome": "^4.7.0",
+    "handsontable-pro": "^3.0.0",
     "vue-router": "^3.5.3",
     "vuex": "^3.6.2"
   },

File diff suppressed because it is too large
+ 1110 - 0
src/components/business_space/business/handsontable.vue


+ 301 - 0
src/components/business_space/dialogs/changeRea.vue

@@ -0,0 +1,301 @@
+<!--
+    changeRea 厂商
+-->
+<template>
+  <el-dialog title="关联资产" :visible.sync="dialog.changeRea" width="800px">
+    <div>
+      <div id="changeRea">
+        <div class="title-search" style="margin-bottom: 10px;">
+          <el-input
+            placeholder="输入名称查询"
+            v-model="search"
+            size="small"
+            style="width:300px;"
+            clearable
+          ></el-input>
+          <el-button @click="getData" size="small">查找</el-button>
+        </div>
+        <div>
+          <floor-cascader @change="changeFloor"></floor-cascader>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table :data="tableData" class="data-table border" style="width: 100%" height="300px">
+            <el-table-column label="资产名称">
+              <template slot-scope="scope">
+                <el-radio
+                  v-model="radio"
+                  :label="scope.row.id"
+                >{{scope.row.infos.EquipLocalName || scope.row.infos.EquipName}}</el-radio>
+              </template>
+            </el-table-column>
+            <el-table-column label="本地编码">
+              <template
+                slot-scope="scope"
+              >{{scope.row.infos.EquipLocalID || scope.row.infos.EquipID}}</template>
+            </el-table-column>
+            <el-table-column prop="name" label="所在楼层">
+              <template slot-scope="scope">{{getFloor(scope.row.relation)}}</template>
+            </el-table-column>
+            <el-table-column label="设备族">
+              <template slot-scope="scope">{{getFramily(scope.row.family)}}</template>
+            </el-table-column>
+            <el-table-column label="安装位置">
+              <template slot-scope="scope">{{scope.row.infos.installLocation || "--"}}</template>
+            </el-table-column>
+          </el-table>
+        </el-radio-group>
+        <my-pagination :page="page" @change="changed" style="margin-top:10px;"></my-pagination>
+        <div class="footer">
+          <el-button
+            type="primary"
+            @click="clickTrue"
+            style="display:block;margin: 10px auto 0;"
+          >确 定</el-button>
+        </div>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/ledger/lib/myPagination";
+import { getBillPropList, getEquipmentFamily, getSpaceFloor, getBussines2, upDateTableMain } from "@/api/scan/request"
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import {mapGetters, mapActions} from "vuex"
+
+export default {
+  components: {
+    myPagination,
+    floorCascader
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          changeRea: true
+        };
+      }
+    },
+    category: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      radio: "",
+      tableData: [
+      ],
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      },
+      mess: {},
+      codeListCode: [],
+      floorList: []
+    };
+  },
+  created() {
+    this.getCode()
+  },
+  computed: {
+    ...mapGetters("layout", [
+        "projectId",
+        "secret",
+        "userId"
+    ])
+  },
+  mounted() { },
+  methods: {
+    getFloor(relation) {
+      let floor = !!relation ? relation.floor || "" : ""
+      if (!!floor) {
+        console.log(floor)
+        let floorName = ""
+        this.floorList.map(item => {
+          if (!!item.floors && item.floors.length) {
+            item.floors.map(child => {
+              if (child.id == floor) {
+                floorName = child.infos.FloorLocalName || child.infos.FloorName
+              }
+            })
+          }
+        })
+        return floorName
+      } else {
+        return "--"
+      }
+    },
+
+    clickTrue() {
+      if (!!this.radio) {
+        let param = {
+          UserId: this.userId,
+          ProjId: this.projectId
+        }
+        let paramList = [{
+          EquipmentId: this.category.id,
+          FmId: this.radio
+        }]
+        console.log(param, paramList)
+        upDateTableMain(param, paramList).then(res => {
+          this.$emit("close")
+          this.dialog.changeRea = false
+        })
+        // upDateTableMain(param, res => {
+        // })
+      } else {
+        this.$message("请先选择资产")
+      }
+    },
+
+    getFramily(code) {
+      console.log(code)
+      let name = ""
+      this.codeListCode.map(item => {
+        if (item.code == code) {
+          name = item.name
+        }
+      })
+      return name || "--"
+    },
+    getCode() {
+      getEquipmentFamily(res => {
+        this.codeListCode = res.Content
+        // this.getFloorList()
+      })
+    },
+    // getFloorList() { // 物理世界 已无接口
+    //   let param = {
+    //     secret: this.secret,
+    //     ProjId: this.projectId
+    //   }
+    //   getSpaceFloor(param).then(res => {
+    //     if (res.data.Result == "success") {
+    //       this.floorList = res.data.Content
+    //     } else {
+    //       this.$message.error("请求错误:" + res.data.ResultMsg)
+    //     }
+    //   }).catch(_ => {
+    //     this.$message.error("请求错误")
+    //   })
+    // },
+    changeFloor(val) {
+      this.mess = {
+        buildId: val[0] || "",
+        floorId: val[1] || ""
+      }
+      this.getData()
+      console.log(val)
+    },
+    changed() {
+      this.getData()
+    },
+    getChange() {
+      if (!!this.radio) {
+        this.$emit("changechangeRea", this.radio)
+        this.dialog.changeRea = false
+      } 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() {
+      let param = {
+        data: {
+          directOnly: false,
+          criteria: {
+            EquipLocalName: [this.search == ""? null: this.search],
+            id: "",
+            type: [],
+            exclude: [{
+              graphType: "Pe2Eq",
+              side: "fromId",
+            }]
+          }
+        },
+        secret: this.secret,
+        ProjId: this.projectId
+      }
+      if (this.mess.buildId == "all") {
+        param.data.criteria.id = this.mess.ProjId
+      } else if (this.mess.buildId == "noKnow") {
+        param.data.criteria.id = this.mess.ProjId
+        param.data.directOnly = true
+      } else if (this.mess.floorId == "noKnow") {
+        param.data.criteria.id = this.mess.buildId
+        param.data.directOnly = true
+      } else if (this.mess.floorId && this.mess.floorId != "all") {
+        param.data.criteria.id = this.mess.floorId
+      } else if (this.mess.floorId == 'all') {
+        param.data.criteria.id = this.mess.buildId
+      } else {
+        param.data.criteria.id = this.projectId
+      }
+      param.data.criteria.type = [this.getType(this.category.category)]
+      console.log(param)
+      getBussines2(param).then(res => {
+        this.tableData = res.data.Content
+        console.log(this.tableData, "this.tableData")
+        this.page.total = res.data.Count
+      })
+    },
+
+    getType(code) {
+      console.log(code, "code")
+      console.log(code.substring(2, 6))
+      let system = code.substring(2, 6), myCode = ""
+      this.codeListCode.map(item => {
+        if (!!item.content && item.content.length) {
+          item.content.map(child => {
+            if (child.code == system) {
+              myCode = item.code
+            }
+          })
+        }
+      })
+      console.log(myCode)
+      return myCode
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.changeRea) {
+          this.changePage()
+          this.radio = ""
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#changeRea {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 219 - 0
src/components/business_space/dialogs/detailsDialog.vue

@@ -0,0 +1,219 @@
+<template>
+  <el-dialog :visible.sync="isShow.details" :width="width">
+    <span slot="title">
+      <span v-show="step == 1">{{ title }}</span>
+      <span v-show="step == 2 || step == 3">
+        <el-button
+          type="text"
+          @click="goBack"
+          icon="el-icon-arrow-left"
+        ></el-button>
+      </span>
+    </span>
+    <div id="detailsDialog" v-show="step == 1">
+      <p class="influence-p">{{ list.name }}</p>
+      <el-tabs type="border-card">
+        <el-tab-pane label="空间详情">
+          <div class="saga-details">
+            <iframe
+              height="400px"
+              v-if="isShow.details"
+              width="100%"
+              :src="iframeSrc"
+            ></iframe>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane label="与空间相关联的设备">
+          <div>
+            <equip-table ref="myEquip"></equip-table>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+    <div v-show="step == 2">
+      <add-equip :activeTabType="activeTabType" ref="addEquip"></add-equip>
+    </div>
+    <div id="detailsDialog" v-if="step == 3">
+      <iframe
+        v-if="step == 3"
+        height="400px"
+        width="100%"
+        :src="iframeSrc2"
+      ></iframe>
+    </div>
+    <div v-show="step == 1" style="line-height: 50px">
+      <el-button @click="step = 3">编辑信息</el-button>
+      <el-button type="danger" @click="delSpace" plain
+        >删除该业务空间</el-button
+      >
+      <el-dropdown
+        style="margin-left: 10px"
+        :hide-on-click="false"
+        @command="addMyEquip"
+      >
+        <span class="el-dropdown-link">
+          添加设备<i class="el-icon-arrow-down el-icon--right"></i>
+        </span>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="EquipinSpace"
+            >空间内的设备</el-dropdown-item
+          >
+          <el-dropdown-item command="EquipforSpace"
+            >服务于空间的设备</el-dropdown-item
+          >
+          <el-dropdown-item command="EquipXSpace"
+            >其他关系的设备</el-dropdown-item
+          >
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { zoneCreate } from "@/api/scan/request";
+import equipTable from "@/components/business_space/table/equipTable";
+import addEquip from "@/components/business_space/table/addEquip";
+import { mapGetters, mapActions } from "vuex";
+export default {
+  components: {
+    equipTable,
+    addEquip,
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  props: {
+    width: {
+      type: String,
+      default: "1200px",
+    },
+    title: {
+      type: String,
+      default: "头部信息",
+    },
+    isShow: {
+      type: Object,
+    },
+    param: {
+      type: Object,
+    },
+    activeTabType: {
+      type: Object,
+      default: function () {
+        return {
+          code: "GeneralZone",
+          name: "默认分区",
+          rel_type: "99",
+        };
+      },
+    },
+  },
+  data() {
+    return {
+      step: 1,
+      data: null,
+      proj: null,
+      activeName: "1",
+      list: {},
+      iframeSrc: "",
+      iframeSrc2: "",
+      buildMess: "",
+    };
+  },
+  created() {},
+  methods: {
+    handleClick() {},
+    getData(list, buildMess) {
+      this.step = 1;
+      this.list = list;
+      this.buildMess = buildMess;
+      this.$nextTick(() => {
+        this.$refs.myEquip.getData(list, this.activeTabType);
+      });
+      let perjectId = this.projectId,
+        secret = this.secret;
+      this.iframeSrc =
+        // process.env.BASE_URL +
+        window.__systemConf.BASE_URL +
+        ":8889/#/details?perjectId=" +
+        perjectId +
+        "&secret=" +
+        secret +
+        "&FmId=" +
+        list.id +
+        "&type=0&code=" +
+        this.activeTabType.code;
+      this.iframeSrc2 =
+        // process.env.BASE_URL +
+        window.__systemConf.BASE_URL +
+        ":8889/#/changeMess?perjectId=" +
+        perjectId +
+        "&secret=" +
+        secret +
+        "&id=" +
+        list.id +
+        "&type=" +
+        this.activeTabType.code;
+    },
+    addMyEquip(str) {
+      this.step = 2;
+      this.$nextTick(() => {
+        console.log(this.activeTabType);
+        this.$refs.addEquip.getData(
+          this.list,
+          this.buildMess,
+          str,
+          this.activeTabType
+        );
+      });
+    },
+    goBack() {
+      this.step = 1;
+      this.$refs.myEquip.getData(this.list, this.activeTabType);
+    },
+    delSpace() {
+      this.$confirm("此操作将永久删除该业务空间, 是否继续?", "删除", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          let param = [{ RoomID: this.list.id }];
+          zoneCreate(param, (res) => {
+            if (res.Result == "success") {
+              this.$message({ type: "success", message: "删除成功!" });
+              this.$emit("del");
+            }
+          });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+  },
+};
+</script>
+
+<style lang="less">
+.el-dialog__header {
+  .el-dropdown {
+    font-size: 12px;
+    line-height: 33px;
+  }
+}
+#detailsDialog {
+  .el-tabs__content {
+    max-height: 400px;
+  }
+  .influence-p {
+    height: 40px;
+    line-height: 40px;
+    font-size: 17px;
+    margin-bottom: 10px;
+  }
+}
+</style>

+ 160 - 0
src/components/business_space/dialogs/facilityDialog.vue

@@ -0,0 +1,160 @@
+<template>
+  <el-dialog :visible.sync="isShow.facility" :width="width">
+    <span slot="title">
+      <span v-show="step == 1">业务空间详情</span>
+      <!-- <span v-show="step == 1" @click="addMyEquip" style="float: right; margin-right: 40px;">
+        <el-button class="saga-padding0" type="text">添加设备</el-button>
+      </span>-->
+      <!-- <span  style="float: right; margin-right: 40px;">
+        <el-dropdown @command="addMyEquip" trigger="click">
+          <span class="el-dropdown-link" style="color: #409EFF">添加设备</span>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item command="EquipinSpace">空间内的设备</el-dropdown-item>
+            <el-dropdown-item command="EquipforSpace">服务于空间的设备</el-dropdown-item>
+            <el-dropdown-item command="EquipXSpace">其他关系的设备</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </span> -->
+      <span v-show="step == 2">
+        <el-button class="saga-padding0" @click="goBack" type="text" icon="el-icon-arrow-left"></el-button>
+      </span>
+    </span>
+    <div id="detailsDialog" v-show="step == 1">
+      <p class="influence-p">{{data.RoomLocalName || data.RoomName || '--'}}</p>
+      <equip-table :activeTabType="activeTabType" ref="myEquip" :param="myDia"></equip-table>
+    </div>
+    <div v-show="step == 1">
+        <el-dropdown style="margin-left: 10px;" :hide-on-click="false" @command="addMyEquip">
+            <span class="el-dropdown-link">
+                添加设备<i class="el-icon-arrow-down el-icon--right"></i>
+            </span>
+            <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item command="EquipinSpace">空间内的设备</el-dropdown-item>
+                <el-dropdown-item command="EquipforSpace">服务于空间的设备</el-dropdown-item>
+                <el-dropdown-item command="EquipXSpace">其他关系的设备</el-dropdown-item>
+            </el-dropdown-menu>
+        </el-dropdown>
+    </div>
+    <div v-show="step == 2">
+      <add-equip ref="addEquip"></add-equip>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import equipTable from "@/components/business_space/table/equipTable";
+import addEquip from "@/components/business_space/table/addEquip";
+import {
+        mapGetters,
+        mapActions
+    } from "vuex";
+export default {
+  components: {
+    equipTable,
+    addEquip
+  },
+  computed: {
+            ...mapGetters("layout", [
+                "projectId",
+                "secret",
+                "userId"
+            ])
+        },
+  props: {
+    width: {
+      type: String,
+      default: "1200px"
+    },
+    title: {
+      type: String,
+      default: "头部信息"
+    },
+    isShow: {
+      type: Object
+    },
+    param: {
+      type: Object
+    },
+    activeTabType: {
+      type: Object,
+      default: function () {
+        return {
+          "code": "GeneralZone",
+          "name": "默认分区",
+          "rel_type": "99"
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      step: 1,
+      data: { infos: {} },
+      proj: null,
+      activeName: "1",
+      myDia: {
+        id: 'Sp11010800034c251365d66111e8bf0a15b159c8e729',
+        ProjId: this.projectId,
+        secret: this.secret
+      },
+      buildMess: {},
+    };
+  },
+  created() { 
+      this.myDia.ProjId = this.projectId
+      this.myDia.secret = this.secret
+  },
+  methods: {
+    handleClick() { },
+    getData(data, buildMess) {
+      this.data = data
+      this.buildMess = buildMess
+      console.log(this.data)
+      this.step = 1
+      this.$nextTick(() => {
+        this.$refs.myEquip.getData(this.data, this.activeTabType)
+      })
+    },
+    goBack() {
+      this.step = 1
+      this.$refs.myEquip.getData(this.data, this.activeTabType)
+    },
+    delSpace() {
+      this.$confirm('此操作将永久删除该业务空间, 是否继续?', '删除', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$message({
+          type: 'success',
+          message: '删除成功!'
+        });
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消删除'
+        });
+      });
+    },
+    addMyEquip(str) {
+      console.log(this.data, this.buildMess)
+      this.step = 2
+      this.$refs.addEquip.getData(this.data, this.buildMess, str, this.activeTabType)
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#detailsDialog {
+  .el-tabs__content {
+    max-height: 400px;
+  }
+  .influence-p {
+    height: 40px;
+    line-height: 40px;
+    font-size: 17px;
+    margin-bottom: 10px;
+  }
+}
+</style>

+ 151 - 0
src/components/business_space/dialogs/influenceDialog.vue

@@ -0,0 +1,151 @@
+<template>
+    <el-dialog :visible.sync="isShow.influence" :width="width">
+        <span slot="title">{{title}}</span>
+        <div id="influenceDialog">
+            <p class="influence-p">受元空间变化影响,部分业务空间需重新划分</p>
+            <el-tabs type="border-card">
+                <el-tab-pane v-for="(item,index) in tabsList" v-if="index == 0" :key="index">
+                    <span slot="label">{{item.name}}</span>
+                    <p style="line-height:30px;font-size:20px;margin-bottom: 20px;">受影响的业务空间</p>
+                    <div v-for="(i,iIndex) in mess" :key="iIndex">
+                        <p style="line-height:20px;margin-left:10px;">{{i.localName || '--'}} - {{i.id || '--'}}</p>
+                    </div>
+                </el-tab-pane>
+            </el-tabs>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <el-button type="primary" @click="confirm">我知道了</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script>
+    import {
+        getAllMess,
+        deleteNotice
+    } from "@/api/scan/request";
+    import {
+        mapGetters,
+        mapActions
+    } from "vuex";
+    export default {
+        props: {
+            width: {
+                type: String,
+                default: "300px"
+            },
+            title: {
+                type: String,
+                default: "提示"
+            },
+            isShow: {
+                type: Object
+            },
+            param: {
+                type: Object
+            },
+            tabsList: {
+                type: Array,
+                default: []
+            }
+        },
+        computed: {
+            ...mapGetters("layout", [
+                "projectId",
+                "secret",
+                "userId"
+            ])
+        },
+        data() {
+            return {
+                data: null,
+                proj: null,
+                activeName: "1",
+                allMess: [], //所有提示
+                mess: [], //实际提示
+                build: {}
+            };
+        },
+        created() {
+            console.log(this.tabsList,'tabsList')
+            this.getAllMess();
+        },
+        methods: {
+            //我知道了
+            confirm() {
+                let ids = [];
+                if (!!this.allMess[this.build.code]) {
+                    this.allMess[this.build.code].map(item => {
+                        ids.push(item.RoomID);
+                    });
+                }
+                let param = {
+                    data: {
+                        ids: ids
+                    },
+                    ProjId: this.projectId,
+                    secret: this.secret
+                };
+                deleteNotice(param)
+                    .then(res => {
+                        if (res.data.Result == "success") {
+                            this.isShow.influence = false;
+                        } else {
+                            this.$message.error(res.data.ResultMsg);
+                        }
+                    })
+                    .catch(() => {
+                        this.$message.error("请求失败");
+                    });
+            },
+            getData(build) {
+                this.build = build;
+                this.mess = this.allMess[build.code];
+            },
+            getAllMess() {
+                getAllMess({
+                        ProjId: this.projectId,
+                        secret: this.secret
+                    })
+                    .then(res => {
+                        if (res.data.Result == "success") {
+                            // this.allMess = res.data.Content
+                            this.changeMsg(res.data.Content);
+                            console.log(this.allMess);
+                        } else {
+                            this.$message.error(res.data.ResultMsg);
+                        }
+                    })
+                    .catch(() => {
+                        this.$message.error("请求错误");
+                    });
+            },
+            //获取楼层信息
+            changeMsg(arr) {
+                arr.map(item => {
+                    if (!!this.allMess[item.location.floor]) {
+                        this.allMess[item.location.floor].push(item.infos);
+                    } else {
+                        this.allMess[item.location.floor] = [];
+                        this.allMess[item.location.floor].push(item.infos);
+                    }
+                });
+            },
+            handleClick() {}
+        }
+    };
+</script>
+
+<style lang="less">
+    #influenceDialog {
+        .el-tabs__content {
+            max-height: 200px;
+            overflow-y: auto;
+        }
+        .influence-p {
+            height: 40px;
+            line-height: 40px;
+            font-size: 17px;
+            margin-bottom: 10px;
+        }
+    }
+</style>

+ 64 - 0
src/components/business_space/dialogs/list/filesDialog.vue

@@ -0,0 +1,64 @@
+<!--
+    上传文件的弹窗
+-->
+
+<template>
+  <el-dialog
+      title="上传文件"
+      :visible.sync="dialog.uploadFiles"
+      width="500px"
+  >
+    <div class='max-height: 500px; overflow-y: auto;'>
+      <upload-files
+        :readOnly="read"
+        :keysArr="keysArr"
+        :show-file-list="false"
+        @change="changeItem"
+        max="2"
+      />
+    </div>
+  </el-dialog>
+</template>
+<script>
+  import uploadFiles from "@/components/business_space/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) {
+        this.$emit("changeFile", file)
+      },
+    },
+  };
+</script>
+<style>
+</style>

+ 193 - 0
src/components/business_space/dialogs/list/guaranteeDialog.vue

@@ -0,0 +1,193 @@
+<!--
+    guarantee 保单选择
+-->
+
+<!--
+    guarantee 供应合同选择
+-->
+<template>
+  <el-dialog title="选择保单" :visible.sync="dialog.guarantee" width="600px">
+    <el-tabs type="border-card">
+      <el-tab-pane>
+        <span slot="label">选择保单</span>
+        <div id="firm">
+          <el-radio-group v-model="radio" style="width:100%;">
+            <el-table :data="tableData" style="width: 100%" height="300px">
+              <el-table-column label="保单号">
+                <template slot-scope="scope">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.insuranceNo}}</el-radio>
+                </template>
+              </el-table-column>
+              <el-table-column label="下载">
+                <template slot-scope="scope">
+                  <el-button type="text">下载</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-radio-group>
+          <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" style="margin-top:10px;"></my-pagination>
+        </div> 
+          <div class="footer">
+            <el-button
+              type="primary"
+              @click="getSelect"
+              style="display:block;margin: 10px auto 0;"
+            >确 定</el-button>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane>
+        <span slot="label">新建保单</span>
+        <el-form label-width="80px" :rules="rules" :model="formData" ref="ruleForm">
+          <el-form-item label="保单号:" prop="name">
+            <el-input v-model="formData.name"></el-input>
+          </el-form-item>
+          <el-form-item label="保险文件">
+            <upload-files @change="changeFiles" ref="files" :keysArr="keysArr" :max="max"></upload-files>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
+            <el-button @click="resetForm('ruleForm')">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </el-tab-pane>
+    </el-tabs>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/business_space/lib/myPagination";
+import uploadFiles from '@/components/business_space/lib/uploadFiles'
+import { getListForGuarantee, createGuarantee } from "@/api/scan/request"
+import { mapGetters, mapActions } from "vuex"
+import tools from "@/utils/scan/tools"
+export default {
+  components: {
+    myPagination,
+    uploadFiles
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          guarantee: true
+        };
+      }
+    },
+    id: {
+      type: [Number, String],
+      default: 0
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      radio: "",
+      formData: {
+        name: ""
+      },
+      rules: {
+        name: { required: true, message: '请输入保单号', trigger: 'blur' },
+      },
+      tableData: [],
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 400,
+        currentPage: 1
+      },
+      keysArr: [],
+      max: 1,
+      allData: []
+    };
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.createGree()
+        } else {
+          return false;
+        }
+      });
+    },
+    changeFiles(val) {
+      this.keysArr = val
+    },
+    resetForm() {
+      this.$refs.ruleForm.resetFields();
+    },
+    //新建保单
+    createGree() {
+      let param = {
+        data: {
+          venderId: this.id,
+          insuranceNo: this.formData.name,
+          projectId: this.projectId,
+          contractFile: this.keysArr[0]
+        }
+      }
+      let _this = this
+      createGuarantee(param, res => {
+        _this.$emit("change", param.data)
+        _this.dialog.guarantee = false
+      })
+    },
+    getList() {
+      this.radio = ""
+      let _this = this
+      this.page = {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      }
+      if (!!this.id) {
+        let param = {
+          data: {
+            projectId: this.projectId,
+            venderId: this.id
+          }
+        }
+        getListForGuarantee(param, res => {
+          _this.$refs.ruleForm.resetFields()
+          _this.$refs.files.resetFile()
+          _this.allData = res.content || []
+          _this.page.total = _this.allData.length
+          //   //分页
+          _this.pageChange()
+        })
+      }
+    },
+
+    getSelect() {
+      this.$emit("change", this.radio)
+      this.dialog.guarantee = false
+    },
+    pageChange() {
+      this.tableData = tools.pagination(this.page.currentPage, this.page.size, this.allData)
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function (val) {
+        if (this.dialog.guarantee) {
+          this.getList()
+        }
+      }
+    }
+  }
+
+};
+</script>

+ 169 - 0
src/components/business_space/dialogs/list/insurerDialog.vue

@@ -0,0 +1,169 @@
+<!--
+    maintenance 选择供应商
+
+-->
+<template>
+  <el-dialog title="选择型号" :visible.sync="dialog.insurer" width="1000px">
+    <div>
+      <div id="firm">
+        <div class="title-search query-form" style="padding:10px;margin-bottom: 10px;">
+          <el-input
+            placeholder="输入厂家名称进行查找"
+            v-model="search"
+            size="small"
+            style="width:300px; margin-right: 10px;"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="filterSearch">查找</el-button>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table border class="data-table" ref="maintenance" :data="tableData" style="width: 100%" height="300px">
+            <el-table-column header-align='center' label="供应商名称">
+              <template slot-scope="scope">
+                <el-tooltip :content="scope.row.name" placement="top">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.name}}</el-radio>
+                </el-tooltip>
+              </template>
+            </el-table-column>
+            <el-table-column header-align='center' prop="website" label="网址"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].name" label="联系人"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].phone" label="联系电话"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].fax" label="传真"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].email" label="电子邮件"></el-table-column>
+          </el-table>
+        </el-radio-group>
+        <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
+        </div> 
+        
+      </div>
+    </div>
+    <div slot="footer">
+          <el-button
+            type="primary"
+            @click="getChange"
+          >确 定</el-button>
+        </div>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/common/myPagination";
+import { mapGetters } from "vuex";
+import { getLib } from "@/api/scan/request"
+import tools from "@/utils/scan/tools"
+
+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") {
+          this.allData = tools.deepCopy(res.data.content.insurance)
+          this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+          this.page.total = this.allData.length
+        } else {
+          this.$message.error("请求失败:" + res.data.resultMsg)
+        }
+      })
+    },
+
+    //分页改变
+    changePage() {
+      this.pagination(this.page.currentPage, this.page.size, this.allData)
+    },
+
+    //发生修改
+    getChange() {
+      if (!!this.radio) {
+        this.$emit("changeInsurer", this.radio)
+        this.dialog.insurer = false
+      } 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: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.insurer) {
+          this.getData()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#firm {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 168 - 0
src/components/business_space/dialogs/list/maintainerDialog.vue

@@ -0,0 +1,168 @@
+<!--
+    maintenance 选择供应商
+
+-->
+<template>
+  <el-dialog title="选择维修商" :visible.sync="dialog.maintainer" width="1000px">
+    <div>
+      <div id="firm">
+        <div class="title-search query-form" style="padding: 10px; margin-bottom: 10px;">
+          <el-input
+            placeholder="输入厂家名称进行查找"
+            v-model="search"
+            size="small"
+            style="width:300px; margin-right: 10px;"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="filterSearch">查找</el-button>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table class="data-table" border ref="maintenance" :data="tableData" style="width: 100%" height="300px">
+            <el-table-column header-align='center' label="维修商名称">
+              <template slot-scope="scope">
+                <el-tooltip :content="scope.row.name" placement="top">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.name}}</el-radio>
+                </el-tooltip>
+              </template>
+            </el-table-column>
+            <el-table-column header-align='center' prop="website" label="网址"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].name" label="联系人"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].phone" label="联系电话"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].fax" label="传真"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].email" label="电子邮件"></el-table-column>
+          </el-table>
+        </el-radio-group>
+        <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
+        </div>        
+      </div>
+    </div>
+    <div slot="footer">
+          <el-button
+            type="primary"
+            @click="getChange"
+          >确 定</el-button>
+        </div>
+  </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"
+
+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") {
+          this.allData = tools.deepCopy(res.data.content.maintenance)
+          this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+          this.page.total = this.allData.length
+        } else {
+          this.$message.error("请求失败:" + res.data.resultMsg)
+        }
+      })
+    },
+
+    //分页改变
+    changePage() {
+      this.pagination(this.page.currentPage, this.page.size, this.allData)
+    },
+
+    //发生修改
+    getChange() {
+      if (!!this.radio) {
+        console.log(this.radio, "radio")
+        this.$emit("changeMaintainer", this.radio)
+        this.dialog.maintainer = false
+      } 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: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.maintainer) {
+          this.getData()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#firm {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 92 - 0
src/components/business_space/dialogs/list/paramDetails.vue

@@ -0,0 +1,92 @@
+<template>
+  <el-dialog width="400px" title="型号参数" :visible.sync="isLoad.paramShow" append-to-body>
+    <h3 class="lag-h3">当前型号: {{data.brand || "--"}} - {{data.name || "--"}}</h3>
+    <div style="max-height: 400px;overflow-y:auto;">
+      <p
+        class="saga-poent"
+        v-for="item in labelArr"
+        v-if="!!data.infos && data.infos[item.infoPointCode]"
+      >{{item.infoPointName}}:{{data.infos ? data.infos[item.infoPointCode] || "--" : "--"}}</p>
+    </div>
+  </el-dialog>
+</template>
+<script>
+
+import { getSpaceHeader } from "@/api/scan/request"
+import { mapGetters, mapActions } from "vuex"
+
+export default {
+  props: {
+    isLoad: {
+      type: Object,
+      default: function () {
+        return {
+          paramShow: false
+        }
+      }
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {
+        }
+      }
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      labelArr: []
+    }
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    getData() {
+      let param = {
+        ProjId: this.projectId,
+        code: this.data.eqFamily
+      }
+      getSpaceHeader(param).then(res => {
+        if (res.data.Result == "success") {
+          this.labelArr = res.data.Content.map(item => {
+            if (item.firstTag == "台账信息") {
+              return item
+            } else {
+              return undefined
+            }
+          }).filter(d => d)
+        } else {
+          this.$message.error("请求失败:" + res.data.ResultMsg)
+        }
+      }).catch(_ => {
+        this.$message.error("请求失败")
+      })
+    }
+  },
+  watch: {
+    isLoad: {
+      deep: true,
+      handler: function () {
+        if (this.isLoad.paramShow) {
+          this.getData()
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.lag-h3 {
+  height: 35px;
+  line-height: 35px;
+  font-size: 20px;
+  font-weight: 500;
+  margin-bottom: 8px;
+}
+.saga-poent {
+  line-height: 28px;
+}
+</style>

+ 140 - 0
src/components/business_space/dialogs/list/picDialog.vue

@@ -0,0 +1,140 @@
+<!--
+    上传图片的弹窗
+-->
+
+<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>
+</template>
+<script>
+import uploadImgs from "@/components/business_space/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()
+    },
+
+    panoramaItem(images) {
+      this.panoramaArr = images
+      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)
+      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()
+        }
+      }
+    }
+  }
+};
+</script>
+<style>
+</style>

+ 167 - 0
src/components/business_space/dialogs/list/supplierDialog.vue

@@ -0,0 +1,167 @@
+<!--
+    supplier 选择供应商
+
+-->
+<template>
+  <el-dialog title="选择型号" :visible.sync="dialog.supplier" width="1000px">
+    <div>
+      <div id="firm">
+        <div class="title-search query-form" style="padding:10px; margin-bottom: 10px;">
+          <el-input
+            placeholder="输入厂家名称进行查找"
+            v-model="search"
+            size="small"
+            style="width:300px; margin-right:10px;"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="filterSearch">查找</el-button>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table border class='data-table' ref="supplier" :data="tableData" style="width: 100%" height="300px">
+            <el-table-column header-align='center' label="供应商名称">
+              <template slot-scope="scope">
+                <el-tooltip :content="scope.row.name" placement="top">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.name}}</el-radio>
+                </el-tooltip>
+              </template>
+            </el-table-column>
+            <el-table-column header-align='center' prop="website" label="网址"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].name" label="联系人"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].phone" label="联系电话"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].fax" label="传真"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].email" label="电子邮件"></el-table-column>
+          </el-table>
+        </el-radio-group>
+        <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
+        </div>        
+      </div>
+    </div>
+    <div slot="footer">
+          <el-button
+            type="primary"
+            @click="getChange"
+          >确 定</el-button>
+        </div>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/common/myPagination";
+import { mapGetters, mapActions } from "vuex";
+import { getLib } from "@/api/scan/request"
+import tools from "@/utils/scan/tools"
+
+export default {
+  components: {
+    myPagination
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          supplier: 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": ["supplier"] }).then(res => {
+        if (res.data.result == "success") {
+          this.allData = tools.deepCopy(res.data.content.supplier)
+          this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+          this.page.total = this.allData.length
+        } else {
+          this.$message.error("请求失败:" + res.data.resultMsg)
+        }
+      })
+    },
+
+    //分页改变
+    changePage() {
+      this.pagination(this.page.currentPage, this.page.size, this.allData)
+    },
+
+    //发生修改
+    getChange() {
+      if (!!this.radio) {
+        this.$emit("changeSupplier", this.radio)
+        this.dialog.supplier = false
+      } 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: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.supplier) {
+          this.getData()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#firm {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 163 - 0
src/components/business_space/dialogs/list/supplyDialog.vue

@@ -0,0 +1,163 @@
+<!--
+    supply 供应合同选择
+-->
+<template>
+  <el-dialog title="选择供应合同" :visible.sync="dialog.supply" width="600px">
+    <el-tabs type="border-card">
+      <el-tab-pane>
+        <span slot="label">选择供应合同</span>
+        <div id="firm">
+          <el-radio-group v-model="radio" style="width:100%;">
+            <el-table :data="tableData" style="width: 100%" height="300px">
+              <el-table-column label="合同编号">
+                <template slot-scope="scope">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row}}</el-radio>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-radio-group>
+          <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="pageChange" style="margin-top:10px;"></my-pagination>
+        </div> 
+          <div class="footer">
+            <el-button
+              type="primary"
+              style="display:block;margin: 10px auto 0;"
+              @click="setData"
+            >确 定</el-button>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane>
+        <span slot="label">新建供应合同</span>
+        <el-form label-width="80px" :rules="rules" :model="formData" ref="ruleForm">
+          <el-form-item label="供应合同" prop="name">
+            <el-input v-model="formData.name"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
+            <el-button @click="resetForm('ruleForm')">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </el-tab-pane>
+    </el-tabs>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/common/myPagination";
+import { mapGetters, mapActions } from "vuex";
+import { getListForSupplier } from "@/api/scan/request"
+import tools from "@/utils/scan/tools"
+
+export default {
+  components: {
+    myPagination
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          supply: true
+        };
+      }
+    },
+    id: {
+      type: [Number, String],
+      default: 0
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      radio: "",
+      formData: {
+        name: ""
+      },
+      rules: {
+        name: { required: true, message: '请输入保单号', trigger: 'blur' },
+      },
+      tableData: [],
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      },
+      allData: []
+    };
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    submitForm(formName) {
+      let _this = this
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          _this.$emit("change", this.formData.name)
+          this.dialog.supply = false
+        } else {
+          return false;
+        }
+      });
+    },
+    resetForm() {
+      this.$refs.ruleForm.resetFields();
+    },
+
+    setData() {
+      this.$emit("change", this.radio)
+      this.dialog.supply = false
+    },
+
+    //获取列表
+    getList() {
+      this.radio = ""
+      let _this = this
+      this.page = {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      }
+      if (!!this.id) {
+        let param = {
+          data: {
+            projectId: this.projectId,
+            venderId: this.id
+          },
+          ProjId: this.projectId,
+          secret: this.secret,
+        }
+        getListForSupplier(param, res => {
+          _this.$refs.ruleForm.resetFields()
+          _this.allData = res.contractId || []
+          _this.page.total = _this.allData.length
+          //分页
+          _this.pageChange()
+        })
+      }
+    },
+    pageChange() {
+      this.tableData = tools.pagination(this.page.currentPage, this.page.size, this.allData)
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function (val) {
+        if (this.dialog.supply) {
+          this.getList()
+        }
+      }
+    }
+  }
+};
+</script>

+ 318 - 0
src/components/business_space/dialogs/list/systemType.vue

@@ -0,0 +1,318 @@
+<!--
+    systemType 设备所属类型
+-->
+<template>
+  <el-dialog title="所属系统实例" :visible.sync="dialog.systemType" width="600px">
+    <div>
+      <div id="systemType">
+        <div class="title-search" style="margin-bottom: 10px;" v-if="type != 'read' ">
+          <el-input
+            placeholder="输入名称或编码进行查询"
+            v-model="search"
+            size="small"
+            style="width:300px;margin-right: 10px"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="searchChecked">查找</el-button>
+        </div>
+        <el-table
+          :data="tableData"
+          @selection-change="handleSelectionChange"
+          style="width: 100%"
+          height="400px"
+          ref="multipleTable"
+        >
+          <el-table-column
+            v-if="type != 'read' "
+            type="selection"
+            :reserve-selection="true"
+            :disabled="true"
+            width="55"
+          ></el-table-column>
+          <el-table-column label="系统名称">
+            <template slot-scope="scope">{{scope.row.infos.SysLocalName || scope.row.infos.SysName}}</template>
+          </el-table-column>
+          <el-table-column label="本地编码">
+            <template slot-scope="scope">{{scope.row.infos.SysLocalID || '--'}}</template>
+          </el-table-column>
+          <el-table-column label="专业">
+            <template slot-scope="scope">{{getName(scope.row.category)}}</template>
+          </el-table-column>
+          <el-table-column label="详情">
+            <template slot-scope="scope">
+              <el-button @click="lookDeatils(scope.row)" type="text">详情</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <div class="footer" v-if="type != 'read' ">
+          <el-button
+            type="primary"
+            @click="getChange"
+            style="display:block;margin: 10px auto 0;"
+          >确 定</el-button>
+        </div>
+      </div>
+    </div>
+    <el-dialog
+      title="系统详情"
+      :visible.sync="iframeShow"
+      v-if="iframeShow"
+      width="500px"
+      append-to-body
+    >
+      <iframe
+        id="google_ads_frame2"
+        name="google_ads_frame2"
+        frameborder="0"
+        :src="iframeSrc"
+        marginwidth="0"
+        marginheight="0"
+        vspace="0"
+        hspace="0"
+        style="width:100%;height:500px;"
+        allowtransparency="true"
+        scrolling="no"
+        allowfullscreen="true"
+      ></iframe>
+    </el-dialog>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/common/myPagination";
+import { mapGetters, mapActions } from "vuex";
+import { getLib, getAllbusiness, getEqCode, getRelation } from "@/api/scan/request"
+import tools from "@/utils/scan/tools"
+
+export default {
+  components: {
+    myPagination
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          systemType: true
+        };
+      }
+    },
+    graphyId: {
+      type: String,
+      default: ""
+    },
+    infos: {
+      type: String,
+      default: ""
+    },
+    type: {
+      type: String,
+      default: "read"
+    },
+    //默认值
+    list: {
+      type: [Array]
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      tableData: [
+      ],
+      systemList: [],
+      allData: [],
+      multipleSelection: [],
+      changeData: [],
+      iframeSrc: "",
+      iframeShow: false
+    };
+  },
+  created() {
+  },
+  mounted() { },
+  methods: {
+    searchChecked() {
+      let data = []
+      this.allData.map(item => {
+        if (item.category.indexOf(this.search) > -1 || (item.infos.SysLocalName && item.infos.SysLocalName.indexOf(this.search) > -1)) {
+          data.push(item)
+        }
+      })
+      this.tableData = data
+      this.changeData = this.multipleSelection
+    },
+
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+      if (this.changeData.length) {
+        this.multipleSelection = this.changeData
+        this.changeData = []
+      }
+    },
+
+    //设置默认
+    toggleSelection(rows) {
+      if (rows) {
+        rows.forEach(row => {
+          this.$refs.multipleTable.toggleRowSelection(row);
+        });
+      } else {
+        this.$refs.multipleTable.clearSelection();
+      }
+    },
+
+    getChange() {
+      if (this.multipleSelection.length >= 2) {
+        this.$confirm("确定关联多个系统?").then(_ => {
+          this.$emit("change", this.multipleSelection)
+          this.dialog.systemType = false
+        }).catch(_ => {
+        })
+      } else {
+        this.$emit("change", this.multipleSelection)
+        this.dialog.systemType = false
+      }
+    },
+
+    getName(code) {
+      if (!!code) {
+        let codeC = code.substring(0, 2), name = ""
+        this.systemList.map(item => {
+          if (item.code == codeC) {
+            name = item.class
+          }
+        })
+        return name
+      } else {
+        return "--"
+      }
+    },
+
+    //获取设备族
+    getEquipmentFamily() {
+      getEqCode().then(res => {
+        if (res.data.Result == "success") {
+          this.systemList = res.data.Content
+          this.getData()
+        } else {
+          this.$message.error("请求错误" + res.data.ResultMsg)
+        }
+      }).catch(_ => {
+        this.$message.error("请求错误")
+      })
+    },
+
+    getData() {
+      let param = param = {
+        ProjId: this.projectId,
+        secret: this.secret,
+        data: {
+          criteria: {
+            type: ["Sy"]
+          }
+        }
+      }
+      getAllbusiness(param).then(res => {
+        if (res.data.Result == "success") {
+          if (this.type == "read" && !!this.infos) {
+            this.getRelation(res.data.Content)
+          } else {
+            this.allData = res.data.Content
+            this.tableData = res.data.Content
+            console.log(this.$refs, "refs", this.list, "list", this.graphyId, "graphy")
+            this.$refs.multipleTable.clearSelection();
+            this.getSelected(this.list, this.allData)
+          }
+        } else {
+          this.$message.error("请求错误:" + res.data.ResultMsg)
+        }
+      }).catch(_ => {
+        this.$message.error("请求错误")
+      })
+    },
+
+    //查询id对应系统
+    getRelation(table) {
+      getRelation({
+        ProjId: this.projectId,
+        secret: this.secret,
+        criterias: {
+          criteria: {
+            "to_id": this.infos,
+            "graph_id": this.graphyId
+          }
+        }
+      }).then(Response => {
+        let data = Response.data.Content
+        if (Response.data.Result == "success") {
+          if (table && table.length && data && data.length) {
+            let lastData = tools.getSameItems(table, "id", data, "from_id")
+            console.log(lastData)
+            this.tableData = lastData
+          } else {
+            this.tableData = []
+          }
+        } else {
+          this.$message.error("请求错误" + Response.data.ResultMsg)
+        }
+      }).catch(_ => {
+        this.$message.error("请求错误")
+      })
+    },
+
+    //设置默认选中项
+    getSelected(list, all) {
+      let map = []
+      if (all && all.length && list && list.length) {
+        all.map((item, index) => {
+          list.map(child => {
+            if (item.id == child.id) {
+              this.$refs.multipleTable.toggleRowSelection(item)
+            }
+          })
+        })
+      }
+    },
+
+    //点击详情
+    lookDeatils(infos) {
+      this.iframeSrc =
+        // process.env.BASE_URL +
+        window.__systemConf.BASE_URL +
+        ":8889/#/details?perjectId=" +
+        this.projectId +
+        "&secret=" +
+        this.secret +
+        "&FmId=" +
+        infos.id +
+        "&type=1&code=" +
+        infos.category.substring(2, 4);
+      this.iframeShow = true;
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.systemType) {
+          this.getEquipmentFamily()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#systemType {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 55 - 0
src/components/business_space/dialogs/list/uploadImgDialog.vue

@@ -0,0 +1,55 @@
+<!--
+    上传图片的弹窗
+-->
+
+<template>
+  <el-dialog title="上传图片" :visible.sync="dialog.uploadImgs" width="500px">
+      <div class="max-height: 500px; overflow-y: auto;">
+          <upload-imgs :readOnly="read" :keysArr="deepcopy(keysArr)" @change="changeItem" max="2"></upload-imgs>
+      </div>
+    
+  </el-dialog>
+</template>
+<script>
+import uploadImgs from "@/components/business_space/lib/uploadImgsName";
+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: {
+    deepcopy(obj) {
+      return JSON.parse(JSON.stringify(obj));
+    },
+    changeItem(file) {
+      this.$emit("changeFile", file)
+    }
+  },
+};
+</script>
+<style>
+</style>

+ 163 - 0
src/components/business_space/dialogs/noModelDialog.vue

@@ -0,0 +1,163 @@
+<template>
+    <el-dialog
+        :visible.sync="isShow.dialogVisible"
+        :close-on-click-modal="false"
+        :close-on-press-escape="false"
+        :show-close="false"
+        :width="width"
+    >
+        <span slot="title">{{title}}</span>
+        <!-- <slot name="body"></slot> -->
+        <el-tree :props="treeArr" :data="data" @node-click="floorClick" :highlight-current="true"></el-tree>
+        <span slot="footer" class="dialog-footer my">
+            <el-button @click="close">取 消</el-button>
+            <el-button type="primary" @click="confirm">确 定</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import {
+    getBuildSelect, //根据项目ID获得建筑列表
+    getSpaceFloor //根据建筑id获取楼层id
+} from "@/api/scan/request";
+
+import tools from '@/utils/scan/tools'
+
+import {
+    mapGetters,
+    mapActions
+} from "vuex";
+export default {
+    props: {
+        width: {
+            type: String,
+            default: "40%"
+        },
+        title: {
+            type: String,
+            default: "头部信息"
+        },
+        isShow: {
+            type: Object
+        },
+        param: {
+            type: Object
+        }
+    },
+    computed: {
+        ...mapGetters("layout", [
+            "projectId",
+            "secret",
+            "userId"
+        ])
+    },
+    data() {
+        return {
+            treeArr: {
+                label: "name", //label的名字
+                children: "children", //如果有下一级children和isLeaf存在
+            },
+            data: null,
+            proj: null,
+            mess: null
+        };
+    },
+    created() {
+        // this.getNodes()
+    },
+    methods: {
+        //确定
+        confirm() {
+            if (!!this.mess) {
+                this.isShow.dialogVisible = false;
+                this.$emit("close", this.mess);
+            } else {
+                this.$message("请选择楼层");
+            }
+        },
+        //取消
+        close() {
+            if (!!this.mess) {
+                this.isShow.dialogVisible = false;
+            } else {
+                this.$message("请选择楼层");
+            }
+        },
+        changeArr(arr) {
+            return arr.map(item => {
+                if (item.floors && item.floors.length) {
+                    return {
+                        code: item.id,
+                        name: item.infos.BuildLocalName,
+                        children: item.floors.map(i => {
+                            return {
+                                code: i.id,
+                                name: (i.infos.FloorLocalName || i.infos.FloorName || "未知") + this.myMess(i),
+                                map: i.infos.FloorMap || null,
+                                affected: i.affected,
+                                isChilren: 2,
+                                buildCode: item.id,
+                                buildName: item.infos.BuildLocalName,
+                                shunxu: i.infos.FloorSequenceID || 0
+                            }
+                        })
+                    }
+                } else {
+                    return {
+                        code: item.id,
+                        name: item.infos.BuildLocalName,
+                        children: null,
+                        isChilren: 1,
+                    }
+                }
+            })
+        },
+
+        myMess(i) {
+            if (i.affected) {
+                return "(该业务空间受元空间变化影响)"
+            } else {
+                if (i.infos.FloorMap) {
+                    return ''
+                } else {
+                    return "(请初始化平面图)"
+                }
+            }
+        },
+        //点击节点懒加载
+        // getNodes() { // 物理世界 已无接口
+        //     let param = {
+        //         ProjId: this.projectId,
+        //         UserId: this.UserId,
+        //         secret: this.secret
+        //     };
+        //     getSpaceFloor(param).then(res => {
+        //         if (res.data.Result == 'success') {
+        //             let data = this.changeArr(res.data.Content).map(item => {
+        //                 if (item.children && item.children.length) {
+        //                     item.children = tools.sortArr(item.children, "shunxu", false)
+        //                 }
+        //                 return item
+        //             })
+        //             this.data = data
+        //         } else {
+        //             this.$message.error(res.data.ResultMsg)
+        //         }
+        //     }).catch(() => {
+        //         this.$message.error("请求出错")
+        //     })
+        // },
+
+        //子节点被点击
+        floorClick(data) {
+            if (data.isChilren == 2) {
+                this.mess = data
+            } else { }
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 57 - 0
src/components/business_space/dialogs/notRelated.vue

@@ -0,0 +1,57 @@
+<template>
+  <el-dialog :visible.sync="isShow.notRelated" :width="width">
+    <span slot="title">{{title}}</span>
+    <business-table
+      ref="business"
+      @createSuccess="createSuccess"
+      :type="list[0].id ? 'relevance' : 'no'"
+    ></business-table>
+  </el-dialog>
+</template>
+
+<script>
+import businessTable from "@/components/business_space/table/businessTable";
+
+export default {
+  components: {
+    businessTable
+  },
+  props: {
+    width: {
+      type: String,
+      default: "45%"
+    },
+    title: {
+      type: String,
+      default: "未关联元空间的业务空间"
+    },
+    isShow: {
+      type: Object
+    },
+    param: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      list: [{}]
+    };
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    getIdList(list, build, graphy, code) {
+      this.list = list;
+      console.log(this.list)
+      this.$nextTick(() => {
+        this.$refs.business.getData(list, build, graphy, code);
+      });
+    },
+    createSuccess() {
+      this.$emit("createSuccess")
+    }
+  }
+};
+</script>
+<style>
+</style>

+ 114 - 0
src/components/business_space/lib/cascaders/assets.vue

@@ -0,0 +1,114 @@
+<template>
+  <div id="cascaderMap">
+    <span class="buildFloor" style="padding-right: 12px;">设备族</span>
+    <el-cascader
+      placeholder="请选择"
+      :options="options"
+      v-model="value"
+      :props="props"
+      filterable
+      :style="isWidth ? '' : 'width:160px;'"
+      size="small"
+      @change="changeVal"
+      change-on-select
+    ></el-cascader>
+  </div>
+</template>
+<script>
+import { getEquipmentFamily } from "@/api/scan/request";
+export default {
+  name: "getCode",
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      value: [],
+      options: [],
+      props: {
+        value: "code",
+        label: "facility"
+      },
+      falg: true,
+      content: []
+    };
+  },
+  created() {
+    this.getData();
+  },
+  mounted() { },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      let value = {}
+      this.options.map(item => {
+        if (item.code == val) {
+          value = item
+        }
+      })
+      this.value = val
+      this.$emit("change", value)
+    },
+    async getData() {
+      let _this = this
+      await getEquipmentFamily(res => {
+        _this.options = _this.changeArr(res.Content)
+        if (!!this.value && this.value.length) {
+          let value = {}
+          this.options.map(item => {
+            if (item.code == this.value[0]) {
+              value = item
+            }
+          })
+          this.$emit("change", value)
+        }
+        if (!_this.falg) {
+          _this.changeList()
+        }
+      })
+    },
+    changeArr(arr) {
+      let data = [];
+      arr.map(item => {
+        data.push({ code: item.code, facility: item.name, disabled: false })
+      });
+      return data;
+    },
+    pushData(content) {
+      this.content = content
+      if (this.options.length) {
+        this.falg = true
+        this.changeList()
+      } else {
+        this.falg = false
+      }
+    },
+    changeList() {
+      this.options.map(item => {
+        item.disabled = true
+        this.content.map(child => {
+          if (item.code == child) {
+            item.disabled = false
+          }
+        })
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 120 - 0
src/components/business_space/lib/cascaders/system.vue

@@ -0,0 +1,120 @@
+<template>
+  <div id="cascaderMap">
+    <span class="buildFloor" style="padding-right: 12px;">所属专业系统类型</span>
+    <el-cascader
+      placeholder="请选择"
+      :options="options"
+      v-model="value"
+      :props="props"
+      filterable
+      :style="isWidth ? '' : 'width:160px;'"
+      size="small"
+      @change="changeVal"
+      change-on-select
+    ></el-cascader>
+  </div>
+</template>
+<script>
+import { getEqCode } from "@/api/scan/request";
+export default {
+  name: "getCode",
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      value: [],
+      options: [],
+      props: {
+        value: "code",
+        label: "facility"
+      },
+      falg: true,
+      content: []
+    };
+  },
+  created() {
+    this.getData();
+  },
+  mounted() { },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      let value = {}
+      this.options.map(item => {
+        if (item.code == val) {
+          value = item
+        }
+      })
+      this.$emit("change", value)
+    },
+    getData() {
+      getEqCode().then(res => {
+        console.log(res.data)
+        this.options = this.changeArr(res.data.Content);
+        if (!!this.value && this.value.length) {
+          let value = {}
+          this.options.map(item => {
+            if (item.code == this.value[0]) {
+              value = item
+            }
+          })
+          this.$emit("change", value)
+        }
+        if (!this.falg) {
+          this.changeList()
+        }
+      });
+    },
+    changeArr(arr) {
+      let data = [];
+      arr.map(item => {
+        if (item.content && item.content.length) {
+          return item.content.map(children => {
+            data.push({ code: children.code, facility: children.system });
+          });
+        }
+      });
+      return data;
+    },
+    //上级页面传入content
+    pushData(content) {
+      this.content = content
+      if (this.options.length) {
+        this.falg = true
+        this.changeList()
+      } else {
+        this.falg = false
+      }
+    },
+
+    //修改list
+    changeList() {
+      this.options.map(item => {
+        item.disabled = true
+        this.content.map(child => {
+          if (item.code == child) {
+            item.disabled = false
+          }
+        })
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascaderMap {
+  float: left;
+  margin-left: 10px;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 72 - 0
src/components/business_space/lib/detailsDia.vue

@@ -0,0 +1,72 @@
+<template>
+  <el-dialog :title="title" append-to-body class="iframe" :visible.sync="dialog.details" width="500px">
+    <iframe :id="id" name="google_ads_frame2" frameborder="0" width="100%" height="300px" :src="iframeSrc" marginwidth="0" marginheight="0" vspace="0"
+      hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true"></iframe>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      id: 'google_ads_frame2' + new Date().getTime()
+    }
+  },
+  props: {
+    iframeSrc: {
+      type: String,
+      default: ""
+    },
+    title: {
+      type: String,
+      default: "详情"
+    },
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          details: false
+        }
+      }
+    },
+    setData: {
+      type: [Array, String],
+      default: function () {
+        return []
+      }
+    }
+  },
+  methods: {
+    setMess() {
+      this.$nextTick(_ => {
+        let iframe = document.getElementById(this.id)
+        iframe.onload = () => {
+          let arr = this.setData.map(i => ({
+            key: i.key,
+            name: i.name,
+            type: i.type
+          }))
+          iframe.contentWindow.postMessage(arr, "*")
+        }
+      })
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.details) {
+          this.setMess()
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#google_ads_frame2 {
+  height: 300px;
+  overflow: auto;
+}
+</style>
+

+ 123 - 0
src/components/business_space/lib/floorCascader.vue

@@ -0,0 +1,123 @@
+<template>
+  <div id="buildFloor">
+    <span class="buildFloor" style="padding-right: 12px;">所属建筑楼层</span>
+    <el-cascader
+      placeholder="请选择建筑楼层"
+      :options="options"
+      v-model="value"
+      filterable
+      size="small"
+      :style="isWidth ? '' : 'width:160px;'"
+      @change="changeCascader"
+    ></el-cascader>
+  </div>
+</template>
+<script>
+
+import { getSpaceFloor } from '@/api/request'
+import { mapGetters, mapActions } from "vuex";
+
+export default {
+  props: {
+    isWidth: {
+      type: Boolean,
+      default: true
+    },
+    type: {
+      type: String,
+      default: "yes"
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      options: [
+      ],
+      param: {
+        ProjId: this.projectId,
+        secret: this.secret
+      },
+      value: ['all']
+    };
+  },
+  created() {
+    // this.getData()
+  },
+  mounted() { },
+  methods: {
+    //获取数据
+    // getData() { // 物理世界 已无接口
+    //   getSpaceFloor(this.param).then(res => {
+    //     if (res.data.Result == 'success') {
+    //       let data = this.changeArr(res.data.Content)
+    //       data.unshift({
+    //         value: "all",
+    //         label: "全部"
+    //       }, {
+    //           value: "noKnow",
+    //           label: "未明确建筑的设备"
+    //         })
+    //       data.map(item => {
+    //         if (!!item.children) {
+    //           item.children.unshift({
+    //             value: 'noKnow',
+    //             label: "未明确楼层的设备"
+    //           })
+    //           item.children.unshift({
+    //             value: "all",
+    //             label: "全部"
+    //           })
+    //         }
+    //         return item
+    //       })
+    //       this.options = data
+    //     } else {
+    //       this.$message.error(res.data.ResultMsg)
+    //     }
+    //   }).catch(() => {
+    //     this.$message.error("请求出错")
+    //   })
+    // },
+    //将数组转换成optiosn格式
+    changeArr(arr) {
+      return arr.map(item => {
+        if (item.floors && item.floors.length && this.type == "yes") {
+          return {
+            value: item.id,
+            label: item.infos.BuildLocalName,
+            children: item.floors.map(i => {
+              return {
+                value: i.id,
+                label: i.infos.FloorLocalName,
+              }
+            })
+          }
+        } else {
+          return {
+            value: item.id,
+            label: item.infos.BuildLocalName,
+            children: null,
+            isChilren: 1,
+          }
+        }
+      })
+    },
+
+    //改变item
+    changeCascader(value) {
+      this.$emit("change", value)
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#buildFloor {
+  float: left;
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 315 - 0
src/components/business_space/lib/formInput.vue

@@ -0,0 +1,315 @@
+<!--
+A1	手工填写-单个-数字-无单位
+A2	手工填写-单个-数字-有单位
+A3	手工填写-多个-数字-无单位
+A4	手工填写-多个-数字-有单位
+A5	手工填写-单个-数字范围-无单位
+A6	手工填写-单个-数字范围-有单位
+A7	手工填写-多个-数字范围-无单位
+A8	手工填写-多个-数字范围-有单位
+B1	手工填写-单个-文本
+B2	手工填写-多个-文本
+C1	手工填写-单个-日期时间值
+C2	手工填写-单个-日期时间段
+C3	手工填写-多个-日期时间值
+C4	手工填写-多个-日期时间段
+C5	手工填写-单个-日期值
+C6	手工填写-单个-日期段
+C7	手工填写-多个-日期值
+C8	手工填写-多个-日期段
+C9	手工填写-单个-时间值
+C10	手工填写-单个-时间段
+C11	手工填写-多个-时间值
+C12	手工填写-多个-时间段
+D1	字典选择-单个-单选
+D2	字典选择-单个-多选
+D3	字典选择-多个-单选
+D4	字典选择-多个-多选
+E1	字典布尔选择-单个
+E2	字典布尔选择-多个
+F1	上传-单个文件 -->
+
+<template>
+  <el-form
+    :label-position="'right'"
+    :labelWidth="width + 'px'"
+    :model="formLabelAlign"
+    ref="form"
+    @submit.native.prevent
+  >
+    <el-form-item :label="label" :rules="isRule ? { required: true, message: '不能为空'} : {}">
+      <!-- 普通输入类型 -->
+      <el-input
+        size="small"
+        v-if="!isShow && (type == 'default' || type == 'B1')"
+        v-model="formLabelAlign.name"
+        style="width: 9rem;"
+        @change="onSubmit"
+        @keyup.enter.native="onSubmit"
+      >
+        <template slot="append" v-if="unit">{{unit}}</template>
+      </el-input>
+      <el-input
+        type="number"
+        v-if="!isShow && (type == 'A1' || type == 'A2')"
+        v-model="formLabelAlign.name"
+        style="width: 9rem;"
+        @change="onSubmit"
+        @keyup.enter.native="onSubmit"
+      >
+        <template slot="append" v-if="unit">{{unit}}</template>
+      </el-input>
+      <!-- date类型 -->
+      <el-date-picker
+        v-if="!isShow && (type == 'year' || type == 'C5')"
+        v-model="formLabelAlign.name"
+        type="date"
+        value-format="yyyy-MM-dd"
+        @change="onSubmit"
+        :clearable="false"
+        placeholder="选择日期"
+      ></el-date-picker>
+      <!-- 级联选择 -->
+      <el-cascader
+        v-if="!isShow && (type == 'cascader' || type == 'D1')"
+        :options="typeArr"
+        v-model="formLabelAlign.name"
+        @change="onSubmit"
+        :props="props"
+      ></el-cascader>
+      <!-- 日期到分 -->
+      <el-date-picker
+        v-if="!isShow && type == 'C1'"
+        v-model="formLabelAlign.name"
+        type="datetime"
+        value-format="yyyy-MM-dd HH:MM"
+        @change="onSubmit"
+        :clearable="false"
+        placeholder="选择日期"
+      ></el-date-picker>
+      <!-- 输入文本框 -->
+      <el-input
+        v-if="!isShow && type == 'B2'"
+        type="textarea"
+        :rows="2"
+        @change="onSubmit"
+        @keyup.enter.native="onSubmit"
+        placeholder="请输入内容"
+        v-model="formLabelAlign.name"
+      ></el-input>
+      <!-- 日期 -->
+      <el-date-picker
+        v-if="!isShow && type == 'C6'"
+        v-model="formLabelAlign.name"
+        type="datetimerange"
+        range-separator="至"
+        start-placeholder="开始日期"
+        end-placeholder="结束日期"
+        value-format="yyyy-MM-dd HH:MM"
+        @change="onSubmit"
+        :clearable="false"
+        placeholder="选择日期"
+      ></el-date-picker>
+      <!-- 点击确定 -->
+      <i
+        v-if="!isShow  && (type == 'default' || type == 'B1')"
+        class="el-input__icon el-icon-check hover"
+        @click="onSubmit"
+      ></i>
+      <!-- 显示基本内容 -->
+      <span v-if="isShow" @click="changeItem" class="hover">
+        {{ filterArr(formLabelAlign.name) }} {{unit}}
+        <i class="el-icon-edit" v-if="type != 'X'"></i>
+      </span>
+      <slot name="mess"></slot>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script>
+export default {
+  name: "ownerInput",
+  props: {
+    type: {
+      type: String,
+      default: "default"
+    }, //类型
+    value: [String, Number, Array], //value值
+    label: String, //label值,从父级传入
+    isRule: Boolean, //是否需要规则
+    keys: [String, Number], //
+    typeArr: [Array, String], //当其为级联或者下拉时传入
+    unit: {
+      //单位
+      type: String,
+      default: ""
+    },
+    width: {
+      type: Number,
+      default: 100
+    }
+  },
+
+  data() {
+    return {
+      formLabelAlign: {
+        name: ""
+      },
+      key: "",
+      isShow: true,
+      props: {
+        label: "name",
+        value: "code",
+        children: "content"
+      } //修改默认数据格式
+    };
+  },
+
+  methods: {
+    //点击确定或者url
+    onSubmit() {
+      if (this.formLabelAlign.name == "" || this.formLabelAlign.name == []) {
+        this.$message.error("请确定值不为空");
+      } else {
+        this.isShow = true;
+        if (this.type == 'cascader' || this.type == 'D1') {
+          let data = this.formLabelAlign.name
+          this.$emit("change", data[data.length - 1], this.keys);
+        } else {
+          this.$emit("change", this.formLabelAlign.name, this.keys);
+        }
+      }
+    },
+
+    //点击文案出现输入
+    changeItem() {
+      if (this.type == "X") {
+        this.$message('该信息点不支持编辑')
+        return;
+      } else {
+        this.isShow = false;
+      }
+    },
+
+    //对数组中的空数组去除
+    toMyNeed(arr) {
+      return arr.map(res => {
+        let param = {};
+        if (res.content && res.content.length != 0) {
+          param.content = this.toMyNeed(res.content);
+        }
+        param.name = res.name;
+        param.code = res.code;
+        return param;
+      });
+    },
+
+    //获取级联选中的值
+    getCascaderObj(val, opt) {
+      let data = this.getMyVal(val, opt, 'name')
+      data.length > 1 ? data = data.join('/') : data = data.join('')
+      return data
+    },
+
+    getMyVal(val, content, code) {
+      let data = []
+      if (content && content.length) {
+        for (let i = 0; i < content.length; i++) {
+          if (content[i].code == val) {
+            data.push(content[i][code])
+            break
+          } else {
+            if (content[i].content && content.length) {
+              for (let j = 0; j < content[i].content.length; j++) {
+                if (content[i].content[j].code == val) {
+                  data.push(content[i][code])
+                  data.push(content[i].content[j][code])
+                  break
+                } else {
+                  if (content[i].content[j].content && content[i].content[j].content.length) {
+                    for (let k = 0; k < content[i].content[j].content.length; k++) {
+                      if (content[i].content[j].content[k].code == val) {
+                        data.push(content[i][code])
+                        data.push(content[i].content[j][code])
+                        data.push(content[i].content[j].content[k][code])
+                        break
+                      } else {
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      if (!data.length) {
+        data = null
+      }
+      return data
+    },
+
+    getMap(val, opt) {
+      return opt.map(function (value, index, array) {
+        for (var itm of opt) {
+          if (itm.code == value.code) {
+            opt = itm.content;
+            return itm;
+          }
+        }
+        return null;
+      });
+    },
+
+    //数组过滤
+    filterArr(val) {
+      let value = ""; //最后输出的文案
+      let isNeedType = this.type == 'cascader' || this.type == 'D1'
+      if (this.type == 'C6') {
+        value = value != "" ? val[0] + '至' + val[1] : "--"
+      } else if (this.type == 'cascader' || this.type == 'D1') {
+        if (val && val.length) {
+          value = this.getCascaderObj(val[val.length - 1], this.typeArr, 'name') || "--";
+        }
+      } else {
+        value = val || "--";
+      }
+      return value;
+    }
+  },
+
+  created() {
+    if (typeof (this.typeArr) == Object) {
+      this.typeArr = this.toMyNeed(this.typeArr)
+    }
+    if (this.type == 'cascader' || this.type == 'D1') {
+      if (this.value == '' || this.value == undefined) {
+        this.formLabelAlign.name = []
+      } else {
+        this.formLabelAlign.name = this.getMyVal(this.value, this.typeArr, 'code');
+      }
+    } else {
+      this.formLabelAlign.name = this.value;
+    }
+    this.key = this.label;
+  },
+
+  watch: {
+    label() { }
+  }
+};
+</script>
+
+<style lang="less">
+.hover:hover {
+  cursor: pointer;
+  color: #409eff;
+}
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+  -webkit-appearance: none;
+}
+input[type="number"] {
+  -moz-appearance: textfield;
+}
+</style>

+ 183 - 0
src/components/business_space/lib/lookImages.vue

@@ -0,0 +1,183 @@
+<!--
+    上传图片的弹窗
+-->
+
+<template>
+  <el-dialog title="上传图片" :visible.sync="dialog.lookPic" v-if="dialog.lookPic" width="500px">
+    <div style="max-height:500px;overflow-y:auto;">
+      <el-tabs type="border-card">
+        <el-tab-pane>
+          <span slot="label">图片</span>
+          <div style="width:500px;max-height:500px;">
+            <div v-if="picArrs.length">
+              <iframe
+                id="google_ads_frame3"
+                name="google_ads_frame3"
+                frameborder="0"
+                width="100%"
+                height="500px"
+                :src="iframeSrc"
+                marginwidth="0"
+                marginheight="0"
+                vspace="0"
+                hspace="0"
+                allowtransparency="true"
+                scrolling="no"
+                allowfullscreen="true"
+              ></iframe>
+            </div>
+            <div v-if="!picArrs.length">暂无图片</div>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane v-if="videoArr.length">
+          <span slot="label">视频</span>
+          <div style="width:500px;">
+            <div
+              v-for=" (item,index) in videoArr "
+              :key="index"
+              style="width:200px;height:200px;float:left;margin: 5px;"
+            >
+              <video
+                width="100%"
+                height="100%"
+                :src="
+                '/image-service/common/image_get?systemId=dataPlatform&key='+item.key"
+                controls
+                :poster="'/image-service/common/image_get?systemId=dataPlatform&key='+ item.key +'&width=200'"
+              ></video>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </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 {
+          lookPic: true
+        };
+      }
+    },
+    keysArr: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    read: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      picArrs: [],
+      panoramaArr: [],
+      videoArr: [],
+      videoPicArr: [],
+      changeKeys: [],
+      iframeSrc: ""
+    };
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    imageItem(images) {
+      this.picArrs = images
+      this.change()
+    },
+
+    panoramaItem(images) {
+      this.panoramaArr = images
+      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)
+    },
+
+    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 = []
+      }
+      if (this.picArrs.length) {
+        this.$nextTick(_ => {
+          this.iframeSrc = window.__systemConf.BASE_URL +":8890/photo-View.html"
+          // process.env.BASE_URL + ":8890/photo-View.html"
+          // this.iframeSrc = process.env.BASE_URL + "/photo-View.html"
+          let iframe = document.getElementById("google_ads_frame3")
+          console.log(iframe)
+          iframe.onload = () => {
+            console.log("onload")
+            iframe.contentWindow.postMessage(this.picArrs, "*")
+          }
+        })
+      }
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.lookPic) {
+          this.fatherTochild()
+        }
+      }
+    }
+  }
+};
+</script>
+<style>
+</style>

+ 58 - 0
src/components/business_space/lib/myPagination.vue

@@ -0,0 +1,58 @@
+<!--
+    props:{
+        size: 当前页的页数,
+        sizes: 下拉的条数,
+        total: 总条数,
+        currentPage: 当前页
+    }
+    @change 发生改变
+-->
+<template>
+    <div class="block">
+        <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page.sync="page.currentPage"
+        :page-sizes="page.sizes"
+        :page-size="page.size"
+        :small="true"
+        :layout=" isSmall ? 'total, sizes, prev, pager, next, jumper' : 'prev, pager, next'"
+        :total="page.total">
+        </el-pagination>
+    </div>
+</template>
+<script>
+export default {
+  name: "pagination",
+  props: {
+    page: {
+      type: Object
+    },
+    isSmall:{
+      type:Boolean,
+      default: true
+    }
+  },
+  methods: {
+    //当前条数发生改变
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.change()
+    },
+    //当前页发生改变
+    handleCurrentChange(val) {
+      this.page.currentPage = val;
+      this.change()
+    },
+    //发生改变
+    change() {
+      this.$emit("change");
+    }
+  }
+};
+</script>
+<style>
+.block{
+  margin-top: 5px;
+}
+</style>

+ 63 - 0
src/components/business_space/lib/qrcode.vue

@@ -0,0 +1,63 @@
+<template>
+  <el-dialog
+    title="二维码"
+    v-if="dialog.qrcode"
+    custom-class="custom-dialog"
+    :visible.sync="dialog.qrcode"
+    width="500px"
+  >
+    <div>
+      <div id="qrcode">
+        <img
+          style="width:200px;height:200px;margin:auto;display:block;"
+          :src="'/image-service/common/file_get/'+ qrcodeUrl +'?systemId=dataPlatform'"
+          alt="二维码"
+        >
+      </div>
+    </div>
+  </el-dialog>
+</template>
+<script>
+// import { qrcanvas } from "qrcanvas";
+export default {
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          qrcode: false
+        };
+      }
+    },
+    qrcodeUrl: {
+      default: ""
+    }
+  },
+  data() {
+    return {};
+  },
+  created() { },
+  mounted() {
+  },
+  methods: {
+    // getCanvas(id) {
+    //     let canvas = qrcanvas({
+    //         cellSize: 8,
+    //         data: 'http://service.sagacloud.cn/qrcode/' + 'Pea3a31168a30d4056acda3a56e557940b'
+    //     });
+    //     canvas.style.margin = "auto"
+    //     canvas.style.display = "block"
+    //     this.$nextTick(() => {
+    //         document.getElementById("qrcode").innerHTML = null;
+    //         document.getElementById("qrcode").appendChild(canvas);
+    //     });
+    // }
+  }
+};
+</script>
+<style lang="less" scoped>
+#qrcode {
+    height: 300px;
+    overflow: auto;
+}
+</style>

+ 252 - 0
src/components/business_space/lib/uploadFiles.vue

@@ -0,0 +1,252 @@
+<!--
+  上传组件
+  type: 类型,默认image
+  identify: key值,通过val获取
+  disabled: 是否可用
+  index: 父组件的下标
+  imageIndex: 图片下标
+  isShow: 图片的显示
+ -->
+<template>
+  <div id="saga-upload">
+    <div id="uploadFile">
+      <el-upload
+        class="upload-file"
+        action drag
+        :http-request="uploadAndSubmit"
+        :show-file-list="false">
+        <el-button size="small" :type="isShow ===1 ? 'text':'primary'" v-if="!readOnly">点击上传</el-button>
+        <div slot="tip" class="el-upload__tip" v-if="(isShow !== 1 || isShow == undefined) && !readOnly">请上传文件,且不大于50M</div>
+      </el-upload>
+      <div v-show="item && filesArr.length" v-for="(item,index) in filesArr" :key="item.key">
+        <p class="file-list">
+          <span class="file-name" :title="item.name">{{item.name}}</span>
+          <i title="下载" class="el-icon-download" style="margin-left:10px; cursor:pointer" @click="download(item)"></i>
+          <i v-if="!readOnly" title="删除" class="el-icon-close delete-icon" style="margin-left:10px; cursor:pointer" @click="deleteFile(index,item)"></i>
+        </p>
+      </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
+      },
+      isShow: {
+        type: Number
+      },
+      contextKey: {
+        type: [String, Object]
+      },
+      defined: null
+    },
+    data() {
+      return {
+        filesArr: []
+      };
+    },
+    created() {
+      this.fileFalg()
+    },
+    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 = []
+        }
+      },
+
+      resetFile() {
+        this.filesArr = []
+      },
+
+
+      //点击下载
+      download(item) {
+        if (item.Key) {
+          let a = document.createElement("a");
+          a.href = `/image-service/common/file_get/${item.key}?systemId=dataPlatform`;
+          a.download = `${item.name}`;
+          a.click();
+          document.body.removeChild(a);
+        } else {
+          this.$message({
+            message: "无该获取该文件资源链接!",
+            type: "error"
+          });
+        }
+      },
+
+      //删除图片
+      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 size = item.file.size;
+        if( size > 50*1024*1024 ) { //文件大于50M
+          this.$message.error('文件不可大于50M,请重新上传')
+          return false
+        }
+        else {
+          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
+          let CreateTime = tools.formatDate(new Date(file.lastModified))
+          reader.onloadstart = function () {
+            // 这个事件在读取开始时触发
+          };
+          reader.onprogress = function (p) {
+            // 这个事件在读取进行中定时触发
+
+          };
+          reader.onUploadProgress = function (progressEvent) {
+            let percent = (progressEvent.loaded / progressEvent.total * 100) | 0
+            //调用onProgress方法来显示进度条,需要传递个对象 percent为进度值
+            uploader.onProgress({percent: percent})
+          }
+          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) {
+                    let fileObject = {
+                      key: key.split("=")[1],
+                      type,
+                      name: file.name,
+                      createTime: CreateTime,
+                      systemId: 'dataPlatform'
+                    }
+                    vm.filesArr.push(fileObject);
+
+                    if(vm.isShow === 1) {
+                      let oFile = {}
+                      oFile[vm.contextKey] = vm.filesArr
+                      vm.$emit("change", oFile, vm.defined);
+                    } else {
+                      vm.$emit("change", vm.filesArr, vm.defined);
+                    }
+                  } else {
+                    this.$message.error(res.data.ResultMsg)
+                  }
+                }
+              };
+            }
+          };
+          reader.readAsArrayBuffer(file);
+        }
+      }
+    },
+    watch: {
+      keysArr: function (val) {
+        this.fileFalg()
+      }
+    }
+  };
+</script>
+
+<style lang="less">
+  #saga-upload {
+    .dill-image {
+      position: absolute;
+      right: 0;
+      top: 0;
+      font-size: 20px;
+    }
+
+    .el-upload-dragger {
+      width: 180px;
+      height: 180px;
+    }
+
+    img {
+      position: absolute;
+      top: 0;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      width: 100%;
+      height: 100%;
+    }
+
+    #uploadFile {
+      .upload-file {
+        overflow: hidden;
+        .el-upload-dragger {
+          width: inherit;
+          height: inherit;
+          border: none;
+        }
+      }
+      .file-list {
+        .file-name {
+          display: inline-block;
+          width: 400px;
+          font-size: 12px;
+          color: #409eff;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          vertical-align: top;
+          cursor: pointer;
+        }
+        .file-name:hover {
+          color: #66b1ff;
+        }
+      }
+    }
+  }
+</style>

+ 109 - 0
src/components/business_space/lib/uploadImg.vue

@@ -0,0 +1,109 @@
+<template>
+    <el-upload
+    class="avatar-uploader"
+    :http-request="uploadAndSubmit"
+    :show-file-list="false"
+    accept="image/*"
+    action=""
+    drag
+    style="position: relation"
+    >
+        <i class="el-icon-plus avatar-uploader-icon"></i>
+    </el-upload>
+</template>
+
+<script>
+export default {
+  props: {
+    keyName: {
+      type: String,
+      default: ""
+    }
+  },
+  methods: {
+    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]
+
+      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/image_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true&key=" +
+              file.uid + '.' + type
+            /*, async, default to true */
+          );
+          //xhr.overrideMimeType("application/octet-stream");
+          xhr.send(reader.result);
+          xhr.onreadystatechange = function() {
+            if (xhr.readyState == 4) {
+              if (xhr.status == 200) {
+                vm.$emit("getKey", file.uid + '.' + type, vm.keyName);
+              }
+            }
+          };
+        }
+      };
+      reader.readAsArrayBuffer(file);
+    }
+  }
+};
+</script>
+
+<style lang="less">
+.point-pic {
+  .avatar-uploader {
+    height: 180px;
+    width: 180px;
+    overflow: hidden;
+    .el-upload {
+      width: 100%;
+      height: 100%;
+      .el-upload-dragger{
+        width: 100%;
+        height: 100%;
+        .el-icon-plus{
+          display: block;
+          width: 20px;
+          height: 20px;
+          font-size: 20px;
+          margin: 80px;
+        }
+      }
+    }
+  }
+}
+.el-dialog__body{
+  max-height: 600px;
+  overflow-y: auto;
+}
+</style>

+ 321 - 0
src/components/business_space/lib/uploadImgs.vue

@@ -0,0 +1,321 @@
+<!--
+    @param keysArr 承接数组
+    @param readOnly  删除按钮是否显示,上传是否显示
+    @param max     上传最大数限制
+    @click change  承接数组发生变化时触发函数
+-->
+<template>
+  <div id="sagaUploads">
+    <div class="saga-upload-images">
+      <div v-if="type != 'video'" class="point-image" v-for="(item,index) in imagesArr">
+        <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
+        <img :src="imageGetUrl + '&key=' +item.key" alt v-load>
+      </div>
+      <div v-if="type == 'video'" class="point-image" v-for="(item,index) in imagesArr">
+        <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
+        <video
+          width="100%"
+          height="100%;"
+          :src="imageGetUrl + '&key=' +item.key"
+          controls="controls"
+        >您的浏览器不支持 video 标签。</video>
+      </div>
+      <div v-if="!readOnly && imagesArr.length < max" style="float:left;">
+        <el-upload
+          class="avatar-uploader"
+          :http-request="uploadAndSubmit"
+          :show-file-list="false"
+          :accept="accept"
+          action
+          drag
+          style="position: relation"
+        >
+          <i class="el-icon-plus avatar-uploader-icon"></i>
+        </el-upload>
+        <video style="display:none;" id="video" controls/>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import tools from "@/utils/scan/tools";
+export default {
+  props: {
+    keysArr: {
+      type: [Array, String]
+    },
+    readOnly: {
+      type: Boolean,
+      default: false
+    },
+    max: {
+      type: [Number, String],
+      default: 6
+    },
+    accept: {
+      type: String,
+      default: "image/*"
+    },
+    type: {
+      type: String,
+      default: "image"
+    },
+    defined: null,
+    videoPicArr: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    }
+  },
+  data() {
+    return {
+      baseUrl: "",
+      imageGetUrl: "/image-service/common/image_get?systemId=dataPlatform",
+      imageUploadUrl: "/image-service/common/image_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true",
+      imagesArr: []
+    };
+  },
+  created() {
+    this.imageFalg();
+  },
+  methods: {
+    //判断是否为空
+    imageFalg() {
+      let type = typeof this.keysArr;
+      console.log(this.keysArr)
+      if (type == "string") {
+        this.imagesArr = [this.keysArr];
+      } else {
+        this.imagesArr = tools.deepCopy(this.keysArr);
+      }
+
+      if (!this.keysArr) {
+        this.imagesArr = [];
+      }
+    },
+
+    //删除图片
+    delImage(i, key) {
+      if (this.type == "video") {
+        this.videoPicArr = this.videoPicArr.map(item => {
+          if (item.substring(0, item.length - 3) == this.imagesArr[i].substring(0, this.imagesArr[i].length - 3)) {
+            return undefined
+          } else {
+            return item
+          }
+        }).filter(p => p)
+      }
+      this.imagesArr.splice(i, 1);
+      this.$emit("change", this.imagesArr, this.defined, this.videoPicArr);
+    },
+
+    //上传
+    uploadAndSubmit(item, key) {
+      // var form = document.forms["demoForm"];
+
+      // if (form["file"].files.length > 0) {
+      // 寻找表单域中的 <input type="file" ... /> 标签
+      // var file = form["file"].files[0];
+
+      console.log("lalala", item)
+      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 uploadKey = file.uid
+      if (!!key) {
+        uploadKey = key
+      }
+
+      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 */
+            vm.imageUploadUrl + "&key=" + uploadKey + "." + type
+            /*, async, default to true */
+          );
+          //xhr.overrideMimeType("application/octet-stream");
+          xhr.send(reader.result);
+          xhr.onreadystatechange = function () {
+            if (xhr.readyState == 4) {
+              if (xhr.status == 200) {
+                if (vm.type == 'image') {
+                  vm.imagesArr.push(
+                    uploadKey + "." + type
+                  );
+                }
+                if (type == 'mp4') {
+                  vm.imagesArr.push(
+                    uploadKey + "." + type
+                  );
+                  vm.creatImg(vm.imageGetUrl + "&key=" + uploadKey + "." + type, uploadKey)
+                }
+                console.log(vm.type, type)
+                if (vm.type == "video" && type == "png") {
+                  console.log("触发时评上传图片回调")
+                  vm.videoPicArr.push(uploadKey + "." + type)
+                }
+                vm.$emit("change", vm.imagesArr, vm.defined, vm.videoPicArr);
+              }
+            }
+          };
+        }
+      };
+      reader.readAsArrayBuffer(file);
+    },
+    dataURLtoBlob: function (dataURI, type) {
+      var binary = atob(dataURI.split(',')[1]);
+      var array = [];
+      for (var i = 0; i < binary.length; i++) {
+        array.push(binary.charCodeAt(i));
+      }
+      return new Blob([new Uint8Array(array)], { type: type });
+    },
+
+    creatImg(reader, key) {
+      var videoDom = document.getElementById('video');
+      videoDom.src = reader;
+      let vm = this
+      videoDom.onloadeddata = function () {
+        // 这里可以打印视频时长
+        // 这里取得视频封面
+        var canvas = document.createElement('canvas');
+        canvas.width = 300;
+        canvas.height = 300 * this.videoHeight / this.videoWidth;
+        canvas.getContext('2d').drawImage(this, 0, 0, canvas.width, canvas.height);
+        //将canvas的base64位图片转换成图片png的file
+        var blob = vm.dataURLtoBlob(canvas.toDataURL('image/png'), "image/png")
+        //将其转换成file对象
+        var file = new File([blob], "video_image.png", { type: "image/png", lastModified: Date.now() })//blob转file
+        vm.uploadAndSubmit({ file: file }, key)
+      }
+    },
+  },
+  watch: {
+    keysArr: function (val) {
+      this.imageFalg();
+    }
+  },
+  //自定义指令
+  directives: {
+    load: function (el) {
+      let imgDom = document.createElement("img");
+      imgDom.style.position = "absolute";
+      imgDom.style.top = "-999px";
+      imgDom.style.opacity = 0;
+      imgDom.src = el.src;
+      el.src = "";
+      imgDom.onload = () => {
+        let width = imgDom.width;
+        let height = imgDom.height;
+        if (width > height) {
+          el.style.height = "100%";
+          el.style.width = "auto";
+          el.style.position = "absolute";
+          el.style.left = "50%";
+          el.style.top = "0";
+          el.style.transform = "translateX(-50%)";
+          el.style.webkitTransform = "translateX(-50%) translateY(0)";
+          el.style.MozTransform = "translateX(-50%) translateY(0)";
+          el.style.msTransform = "translateX(-50%) translateY(0)";
+          el.style.OTransform = "translateX(-50%) translateY(0)";
+        } else if (width < height) {
+          el.src = imgDom.src;
+          el.style.width = "100%";
+          el.style.height = "auto";
+          el.style.position = "absolute";
+          el.style.top = "50%";
+          el.style.left = "0";
+          el.style.transform = "translateY(-50%) translateX(0)";
+          el.style.webkitTransform = "translateY(-50%) translateX(0)";
+          el.style.MozTransform = "translateY(-50%) translateX(0)";
+          el.style.msTransform = "translateY(-50%) translateX(0)";
+          el.style.OTransform = "translateY(-50%) translateX(0)";
+        } else {
+          el.style.width = "100%";
+          el.style.height = "100%";
+          el.style.position = "absolute";
+          el.style.top = "0";
+          el.style.left = "0";
+          el.style.transform = "translateY(0) translateX(0)";
+          el.style.webkitTransform = "translateY(0) translateX(0)";
+          el.style.MozTransform = "translateY(0) translateX(0)";
+          el.style.msTransform = "translateY(0) translateX(0)";
+          el.style.OTransform = "translateY(0) translateX(0)";
+        }
+        el.src = imgDom.src;
+      };
+    }
+  }
+};
+</script>
+<style lang="less">
+#sagaUploads {
+  overflow: hidden;
+  .avatar-uploader {
+    height: 180px;
+    width: 180px;
+    overflow: hidden;
+    .el-upload {
+      width: 180px;
+      height: 180px;
+      .el-upload-dragger {
+        width: 180px;
+        height: 180px;
+        .el-icon-plus {
+          display: block;
+          width: 20px;
+          height: 20px;
+          font-size: 20px;
+          margin: 80px;
+        }
+      }
+    }
+  }
+  .point-image {
+    width: 180px;
+    height: 180px;
+    float: left;
+    position: relative;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    border: 1px solid #ccc;
+    overflow: hidden;
+    img {
+      z-index: 11;
+    }
+    i {
+      position: absolute;
+      bottom: 10px;
+      right: 10px;
+      background-color: #fff;
+      padding: 5px;
+      cursor: pointer;
+      z-index: 66;
+    }
+  }
+}
+</style>

+ 396 - 0
src/components/business_space/lib/uploadImgsName.vue

@@ -0,0 +1,396 @@
+<!--
+    @param keysArr 承接数组
+    @param readOnly  删除按钮是否显示,上传是否显示
+    @param max     上传最大数限制
+    @click change  承接数组发生变化时触发函数
+-->
+<template>
+  <div id="sagaUploads" :style="{marginLeft:(isShow && imagesArr.length>2) ? '157px':'',marginTop:(isShow && imagesArr.length>2) ? '-25px':''}">
+    <div class="saga-upload-images">
+      <div v-if="type != 'video'" class="point-view" v-for="(item,index) in imagesArr">
+        <div class="point-image">
+          <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
+          <img @click="lookImg" :src="imageGetUrl + '&key=' +item.key" alt v-load>
+        </div>
+        <p v-if="readOnly" >{{item.name}}</p>
+        <form-input v-else :label="''" @change="getName" :keys="index" :value="item.name" :width="10"></form-input>
+      </div>
+      <div v-if="type == 'video'" class="point-view" v-for="(item,index) in imagesArr">
+        <div class="point-image">
+          <i v-if="!readOnly" class="el-icon-delete" @click="delImage(index,item)"></i>
+          <video
+            width="100%"
+            height="100%;"
+            :src="imageGetUrl + '&key=' +item.key"
+            controls="controls"
+          >您的浏览器不支持 video 标签。</video>
+        </div>
+        <p v-if="readOnly" >{{item.name}}</p>
+        <form-input v-else :label="''" @change="getName" :keys="index" :value="item.name" :width="10"></form-input>
+      </div>
+      <div v-if="!readOnly" style="float:left;">
+        <el-upload
+          class="avatar-uploader"
+          :http-request="uploadAndSubmit"
+          :show-file-list="false"
+          :accept="accept"
+          action
+          drag
+          style="position: relative"
+        >
+          <i class="el-icon-plus avatar-uploader-icon"></i>
+        </el-upload>
+        <video style="display:none;" id="video" controls/>
+      </div>
+    </div>
+    <details-dialog :title="'图片'" :iframeSrc="iframeSrc" :dialog="dialog" :setData="imagesArr"></details-dialog>
+  </div>
+</template>
+<script>
+import tools from "@/utils/scan/tools";
+import formInput from "@/components/business_space/lib/formInput"
+import detailsDialog from "@/components/business_space/lib/detailsDia"
+
+export default {
+  components: {
+    formInput,
+    detailsDialog
+  },
+  props: {
+    keysArr: {
+      type: [Array, String]
+    },
+    readOnly: {
+      type: Boolean,
+      default: false
+    },
+    max: {
+      type: [Number, String],
+      default: 6
+    },
+    accept: {
+      type: String,
+      default: "image/*"
+    },
+    type: {
+      type: String,
+      default: "image"
+    },
+    contextKey: {
+      type: [String, Object]
+    },
+    isShow: {
+      type: [Number, String]
+    },
+      defined: null,
+      videoPicArr: {
+        type: Array,
+        default: function () {
+          return []
+        }
+      }
+    },
+    data() {
+      return {
+        baseUrl: "",
+        imageGetUrl: "/image-service/common/image_get?systemId=dataPlatform",
+        imageUploadUrl: "/image-service/common/image_upload?systemId=dataPlatform&secret=9e0891a7a8c8e885&overwrite=true",
+        imagesArr: [],
+        iframeSrc: "",
+        dialog: {
+          details: false
+        }
+      };
+    },
+    created() {
+      this.imageFalg();
+    },
+    methods: {
+      getName(name, index) {
+        this.imagesArr[index].name = name
+        if (this.isShow === 1) {
+          let oFile = {}
+          oFile[this.contextKey] = this.imagesArr
+          this.$emit("change", oFile, this.defined, this.videoPicArr);
+
+        } else {
+          this.$emit("change", this.imagesArr, this.defined, this.videoPicArr);
+
+        }
+      },
+    //判断是否为空
+    imageFalg() {
+      let type = typeof this.keysArr;
+      if (type == "string") {
+        this.imagesArr = [this.keysArr];
+      } else {
+        this.imagesArr = tools.copyArr(this.keysArr);
+      }
+
+      if (!this.keysArr) {
+        this.imagesArr = [];
+      }
+    },
+
+    //查看图片
+    lookImg() {
+      this.dialog.details = true
+      this.iframeSrc = window.__systemConf.BASE_URL +":8890/photo-View.html"
+      //process.env.BASE_URL + ":8890/photo-View.html"
+      // this.iframeSrc = process.env.BASE_URL + "/photo-View.html"
+    },
+
+    //删除图片
+    delImage(i, key) {
+      if (this.type == "video") {
+        this.videoPicArr = this.videoPicArr.map(item => {
+          if (item.key.substring(0, item.length - 3) == this.imagesArr[i].key.substring(0, this.imagesArr[i].length - 3)) {
+            return undefined
+          } else {
+            return item
+          }
+        }).filter(p => p)
+      }
+      this.imagesArr.splice(i, 1);
+      this.$emit("change", this.imagesArr, this.defined, this.videoPicArr);
+    },
+
+    //上传
+    uploadAndSubmit(item, key) {
+      // 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 CreateTime = tools.formatDate(new Date(file.lastModified))
+
+      let uploadKey = file.uid
+      if (!!key) {
+        uploadKey = key
+      }
+
+      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 */
+            vm.imageUploadUrl + "&key=" + uploadKey + "." + type
+            /*, async, default to true */
+          );
+          //xhr.overrideMimeType("application/octet-stream");
+          xhr.send(reader.result);
+          xhr.onreadystatechange = function () {
+            if (xhr.readyState == 4) {
+              if (xhr.status == 200) {
+                if (vm.type == 'image') {
+                  vm.imagesArr.push({
+                    name: uploadKey + '',
+                    key: uploadKey + "." + type,
+                    systemId: "dataPlatform",
+                    type: "image",
+                    createTime: CreateTime
+                  });
+                }
+                if (type == 'mp4') {
+                  vm.imagesArr.push({
+                    name: uploadKey + '',
+                    key: uploadKey + "." + type,
+                    systemId: "dataPlatform",
+                    type: "video",
+                    createTime: CreateTime
+                  });
+                  vm.creatImg(vm.imageGetUrl + "&key=" + uploadKey + "." + type, uploadKey)
+                }
+                if (vm.type == "video" && type == "png") {
+                  vm.videoPicArr.push({
+                    name: uploadKey + '',
+                    key: uploadKey + "." + type,
+                    systemId: "dataPlatform",
+                    type: "image_video",
+                    createTime: CreateTime
+                  })
+                }
+                if (vm.isShow === 1) {
+                  let oFile = {}
+                  oFile[vm.contextKey] = vm.imagesArr
+                  vm.$emit("change", oFile, vm.defined, vm.videoPicArr);
+                } else {
+                  vm.$emit("change", vm.imagesArr, vm.defined, vm.videoPicArr);
+
+                }
+              }
+            }
+          };
+        }
+      };
+      reader.readAsArrayBuffer(file);
+    },
+    dataURLtoBlob(dataURI, type) {
+      var binary = atob(dataURI.split(',')[1]);
+      var array = [];
+      for (var i = 0; i < binary.length; i++) {
+        array.push(binary.charCodeAt(i));
+      }
+      return new Blob([new Uint8Array(array)], { type: type });
+    },
+
+    creatImg(reader, key) {
+      var videoDom = document.getElementById('video');
+      videoDom.src = reader;
+      let vm = this
+      videoDom.onloadeddata = function () {
+        // 这里可以打印视频时长
+        // 这里取得视频封面
+        var canvas = document.createElement('canvas');
+        canvas.width = 300;
+        canvas.height = 300 * this.videoHeight / this.videoWidth;
+        canvas.getContext('2d').drawImage(this, 0, 0, canvas.width, canvas.height);
+        //将canvas的base64位图片转换成图片png的file
+        var blob = vm.dataURLtoBlob(canvas.toDataURL('image/png'), "image/png")
+        //将其转换成file对象
+        var file = new File([blob], "video_image.png", { type: "image/png", lastModified: Date.now() })//blob转file
+        vm.uploadAndSubmit({ file: file }, key)
+      }
+    },
+  },
+  watch: {
+    keysArr: function (val) {
+      this.imageFalg();
+    }
+  },
+  //自定义指令
+  directives: {
+    load: function (el) {
+      let imgDom = document.createElement("img");
+      imgDom.style.position = "absolute";
+      imgDom.style.top = "-999px";
+      imgDom.style.opacity = 0;
+      imgDom.src = el.src;
+      el.src = "";
+      imgDom.onload = () => {
+        let width = imgDom.width;
+        let height = imgDom.height;
+        if (width > height) {
+          el.style.height = "100%";
+          el.style.width = "auto";
+          el.style.position = "absolute";
+          el.style.left = "50%";
+          el.style.top = "0";
+          el.style.transform = "translateX(-50%)";
+          el.style.webkitTransform = "translateX(-50%) translateY(0)";
+          el.style.MozTransform = "translateX(-50%) translateY(0)";
+          el.style.msTransform = "translateX(-50%) translateY(0)";
+          el.style.OTransform = "translateX(-50%) translateY(0)";
+        } else if (width < height) {
+          el.src = imgDom.src;
+          el.style.width = "100%";
+          el.style.height = "auto";
+          el.style.position = "absolute";
+          el.style.top = "50%";
+          el.style.left = "0";
+          el.style.transform = "translateY(-50%) translateX(0)";
+          el.style.webkitTransform = "translateY(-50%) translateX(0)";
+          el.style.MozTransform = "translateY(-50%) translateX(0)";
+          el.style.msTransform = "translateY(-50%) translateX(0)";
+          el.style.OTransform = "translateY(-50%) translateX(0)";
+        } else {
+          el.style.width = "100%";
+          el.style.height = "100%";
+          el.style.position = "absolute";
+          el.style.top = "0";
+          el.style.left = "0";
+          el.style.transform = "translateY(0) translateX(0)";
+          el.style.webkitTransform = "translateY(0) translateX(0)";
+          el.style.MozTransform = "translateY(0) translateX(0)";
+          el.style.msTransform = "translateY(0) translateX(0)";
+          el.style.OTransform = "translateY(0) translateX(0)";
+        }
+        el.src = imgDom.src;
+      };
+    }
+  }
+};
+</script>
+<style lang="less">
+#sagaUploads {
+  /deep/ .el-upload--text {
+    box-sizing: border-box;
+  }
+
+  overflow: hidden;
+
+  .avatar-uploader {
+    /*height: 180px;*/
+    /*width: 180px;*/
+    /*overflow: hidden;*/
+
+    .el-upload {
+      /*width: 180px;*/
+      /*height: 180px;*/
+
+      .el-upload-dragger {
+        width: 180px !important;
+        height: 180px !important;
+        .el-icon-plus {
+          display: block;
+          width: 20px;
+          height: 20px;
+          font-size: 20px;
+          margin: 80px;
+        }
+      }
+    }
+  }
+  .point-view {
+    float: left;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    overflow: hidden;
+    height: 240px;
+  }
+  .point-image {
+    width: 180px;
+    height: 180px;
+    position: relative;
+    border: 1px solid #ccc;
+    overflow: hidden;
+    img {
+      z-index: 11;
+    }
+    i {
+      position: absolute;
+      bottom: 10px;
+      right: 10px;
+      background-color: #fff;
+      padding: 5px;
+      cursor: pointer;
+      z-index: 66;
+    }
+  }
+}
+</style>

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

@@ -0,0 +1,278 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="addEqDialog">
+    <el-row class="filters">
+      <el-col :span="9">
+        <el-input placeholder="输入设备名称或设备本地编码进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="15">
+        <span style="margin-left:10px;">所属楼层</span>
+        <el-cascader @change="getTableData" v-model="floor" :options="options" :props="props"></el-cascader>
+        <el-checkbox style="margin-left:10px;" @change="getTableData" v-model="showType" label="只显示在当前业务空间中的设备"></el-checkbox>
+      </el-col>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.localName||scope.row.name||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="localId" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="equipCategory.name" :label="`${inSpaceType}类`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="linkOtherSpace" label="已关联其他业务空间" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="toDetail(scope.$index, scope.row)" type="primary" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange" @current-change="handleCurrentChange"
+        :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper"
+        :total="page.total"></el-pagination>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  getSpaceEquip,
+  // buildingQuery, //数据中心-建筑查询
+  notEqInSpaceQuery, //没有和当前空间绑定的设备
+  notEqForSpaceQuery, //未服务当前空间的设备
+  eqInSpaceCreate, //设备所在业务空间--创建关系
+  eqForSpaceCreate, //设备服务业务空间--创建关系
+  getEqNotInSpace, //空间内没有和空间关联的设备
+  getEqNotForSpace, //空间内没有服务空间的设备
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import { buildingQuery } from '@/api/object/build';
+export default {
+  components: {
+
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      title: "添加设备",
+      keycode: '', //输入查询条件
+      options: [], //建筑楼层级联
+      floor: [], // 选中的建筑楼层
+      showType: false, //是否只显示在当前业务空间中的设备
+      inSpaceType: '设备',
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      selections: [], // 选中项
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      props: { //自定义字段
+        value: "id",
+        label: "localName",
+        children: "floor"
+      },
+    };
+  },
+  props: {
+    type: {}, //Equipment--EquipmentFor
+    spaceId: {},
+    zone: {}, //分区类型
+  },
+  created() {
+    this.getBuilding();
+  },
+  methods: {
+    // 获取项目下建筑
+    getBuilding() {
+      let pa = {
+        cascade: [{ name: 'floor', orders: 'floorSequenceID desc' }],
+        orders: "localName asc",
+      }
+      buildingQuery(pa, res => {
+        this.options = res.content.map(t => {
+          if (t.floor) {
+            t.floor = t.floor.map(item => {
+              return item;
+            })
+          } else {
+            t.floor = []
+          }
+          t.floor.unshift({ id: 'all', localName: '全部' }, { id: 'isNull', localName: '未明确楼层' })
+          return t;
+        })
+        this.options.unshift({ id: 'all', localName: '全部' }, { id: 'isNull', localName: '未明确楼层' })
+      })
+    },
+    // 显示弹窗
+    showDialog() {
+      this.dialogVisible = true;
+      this.tableData = [];
+      this.getTableData();
+    },
+    // 获取列表数据
+    getTableData() {
+      this.loading = true
+      let pa = {
+        data: {
+          cascade: [{ name: "equipCategory" }],
+          filters: '',
+          pageNumber: this.page.pageNumber,
+          pageSize: this.page.pageSize,
+          orders: 'id asc'
+        },
+        type: this.zone,
+        spaceId: this.spaceId
+      }
+      if (this.floor[0] == 'isNull') {
+        pa.data.filters += `buildingId isNull`
+      } else if (this.floor[0] && this.floor[0] != 'all') {
+        pa.data.filters += `buildingId='${this.floor[0]}'`
+      }
+      if (this.floor[1] == 'isNull') {
+        pa.data.filters += `;floorId isNull`
+      } else if (this.floor[1] && this.floor[1] != 'all') {
+        pa.data.filters += `;floorId='${this.floor[1]}'`
+      }
+      if (this.keycode != '') {
+        pa.data.filters += `;name contain "${this.keycode}" or localName contain "${this.keycode}" or localId contain "${this.keycode}"`
+      }
+      // 删除首尾分号
+      pa.data.filters = pa.data.filters.replace(/(^;)|(;$)/g, '');
+      if (pa.data.filters == '') {
+        delete pa.data.filters
+      }
+      if (this.showType) {
+        if (this.type == "equipment") {
+          // pa.data.Cascade.push({ Name: "zoneSpaceInBase" })
+          pa.data.cascade = [{ name: "equipCategory" }];
+          getEqNotInSpace(pa, res => {
+            this.loading = false
+            this.getDataSuc(res, 'ZoneSpaceBaseIn')
+          })
+        } else {
+          // pa.data.Cascade.push({ Name: "zoneSpaceForBase" })
+          pa.data.cascade = [{ name: "equipCategory" }];
+          getEqNotForSpace(pa, res => {
+            this.loading = false
+            this.getDataSuc(res, 'ZoneSpaceBaseFor')
+          })
+        }
+      } else {
+        if (this.type == "equipment") {
+          pa.data.cascade.push({ name: "zoneSpaceInBase" })
+          notEqInSpaceQuery(pa, res => {
+            this.loading = false
+            this.getDataSuc(res, 'ZoneSpaceBaseIn')
+          })
+        } else {
+          pa.data.cascade.push({ name: "zoneSpaceForBase" })
+          notEqForSpaceQuery(pa, res => {
+            this.loading = false
+            this.getDataSuc(res, 'ZoneSpaceBaseFor')
+          })
+        }
+      }
+    },
+    // 获取列表成功回调
+    getDataSuc(res, zonespacebase) {
+      let response = res.content && res.content.map(t => {
+        let otherSpace = [];
+        if (t[zonespacebase] && t[zonespacebase].length) {
+          t[zonespacebase].map(item => {
+            otherSpace.push(item.localName || item.name)
+          })
+        }
+        t.linkOtherSpace = otherSpace.join(',');
+        return t;
+      })
+      this.tableData = res.content;
+      this.page.total = res.total;
+    },
+    //选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    // 确认 保存关系
+    savaRelation() {
+      let pa = {
+        data: {
+          spaceId: this.spaceId,
+          equipIdList: []
+        },
+        type: this.zone
+      }
+      this.selections.map(t => {
+        pa.data.equipIdList.push(t.id)
+      })
+      if (this.type == "equipment") {
+        eqInSpaceCreate(pa, res => {
+          this.successCallback()
+        })
+      } else {
+        eqForSpaceCreate(pa, res => {
+          this.successCallback()
+        })
+      }
+    },
+    // 关联成功回调
+    successCallback() {
+      this.$message.success('关联成功');
+      this.$emit('refresh');
+      this.dialogVisible = false;
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 查看详情
+    toDetail() {
+      this.$message('开发中')
+    }
+  },
+  watch: {
+    showType(n) {
+
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#addEqDialog {
+  .filters {
+    margin-bottom: 10px;
+    /deep/ .el-input__inner {
+      vertical-align: baseline;
+    }
+  }
+  .table-box {
+    height: 350px;
+  }
+}
+</style>

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

@@ -0,0 +1,112 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="800px" id="addSyDialog">
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.localName||scope.row.name||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="localId" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="toDetail(scope.$index, scope.row)" type="primary" plain>查看详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+
+<script>
+import {
+  notSyInSpaceQuery, //没有和当前空间绑定的系统
+  syInSpaceCreate, //系统所在业务空间--创建关系
+} from "@/api/scan/request";
+export default {
+  data() {
+    return {
+      title: '添加空间内的系统',
+      inSpaceType: '系统',
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      selections: [], // 选中项
+    }
+  },
+  props: {
+    type: {}, //equipment--equipmentFor
+    spaceId: {},
+    zone: {}, //分区类型 
+  },
+  methods: {
+    // 显示
+    showDialog() {
+      this.dialogVisible = true;
+      this.tableData = [];
+      this.getTableData();
+    },
+    // 选中项修改
+    handleSelectionChange(val) {
+      this.selections = val;
+    },
+    // 确认
+    savaRelation() {
+      let pa = {
+        data: {
+          spaceId: this.spaceId,
+          sysIdList: []
+        },
+        type: this.zone
+      }
+      this.selections.map(t => {
+        pa.data.sysIdList.push(t.id)
+      })
+      syInSpaceCreate(pa, res => {
+        this.$message.success('关联成功');
+        this.$emit('refresh');
+        this.dialogVisible = false;
+      })
+    },
+    // 获取表格数据
+    getTableData() {
+      let pa = {
+        data: {
+          pageSize: 200,
+          orders: 'id asc'
+        },
+        type: this.zone,
+        spaceId: this.spaceId
+      }
+      notSyInSpaceQuery(pa, res => {
+        this.tableData = res.content;
+      })
+    },
+    // 查看详情
+    toDetail() {
+      this.$message('开发中')
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#addSyDialog {
+  .table-box {
+    height: 350px;
+  }
+}
+</style>

+ 136 - 0
src/components/business_space/newAddDialogs/roomInFloorDialog.vue

@@ -0,0 +1,136 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="800px" id="addSyDialog">
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle" ref="multipleTable" border>
+        <el-table-column label="业务空间名称" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.localName||scope.row.name||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="所属建筑" show-overflow-tooltip min-width="100" class-name="mutiCol">
+          <template slot-scope="scope">
+            <div>
+              <div v-for="(t,i) in scope.row.floorList" :key="i" class="muti">
+                {{t.building.localName||t.building.name}}
+              </div>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="SysLocalID" label="所属楼层" show-overflow-tooltip min-width="100" class-name="mutiCol">
+          <template slot-scope="scope">
+            <div>
+              <div v-for="t in scope.row.floorList" :key="t.id" class="muti">
+                {{t.localName||t.name}}
+              </div>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="50" align='center' class-name="mutiCol">
+          <template slot-scope="scope">
+            <div>
+              <div v-for="t in scope.row.floorList" :key="t.id" class="muti">
+                <el-radio v-model="scope.row.selected" :label="t">{{''}}</el-radio>
+              </div>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">取 消</el-button>
+      <el-button size="small" type="primary" @click="savaRelation">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+<script>
+import {
+  getSpaceBdFlData, // 属于多建筑楼层的空间数据
+  updateRelateInSpAndBuild, //保存业务空间与建筑楼层关系
+} from "@/api/scan/request";
+export default {
+  data() {
+    return {
+      title: '请选择业务空间所属建筑',
+      inSpaceType: '系统',
+      dialogVisible: false,
+      tableData: [],
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      selections: [], // 选中项
+    }
+  },
+  props: {
+    type: {}, //equipment--equipmentFor
+    spaceId: {},
+    zone: {}, //分区类型 
+  },
+  methods: {
+    // 显示
+    showDialog() {
+      this.dialogVisible = true;
+      this.tableData = [];
+      this.getTableData();
+    },
+    // 确认
+    savaRelation() {
+      let arr = [];
+      this.tableData.forEach(t => {
+        if (t.selected) {
+          arr.push({
+            spaceId: t.id,
+            id: t.selected.floorId,
+            type: t.classCode
+          })
+        }
+      })
+      if (arr.length) {
+        updateRelateInSpAndBuild(arr, res => {
+          this.$emit('relaSuc');
+          this.$message.success('关联成功');
+          this.dialogVisible = false;
+        })
+      } else {
+        this.$message.warning('请选择关联建筑楼层');
+      }
+    },
+    // 获取表格数据
+    getTableData() {
+      let pa = {
+        cascade: [
+          { Name: "floorList", cascade: [{ name: 'building' }] }
+        ],
+        pageSize: 1000
+      }
+      getSpaceBdFlData(pa, res => {
+        this.tableData = res.content;
+      })
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#addSyDialog {
+  .table-box {
+    height: 350px;
+    /deep/ .mutiCol {
+      padding: 0;
+      & > div {
+        padding: 0;
+      }
+    }
+    .muti {
+      line-height: 32px;
+      padding: 0 10px;
+      & + .muti {
+        border-top: 1px solid #ebeef5;
+      }
+    }
+  }
+}
+</style>

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

@@ -0,0 +1,185 @@
+<template>
+  <el-row id="canvas-actions-box" :class="{'isEdit':config.isEdit}">
+    <!-- <div :class="{'active':active=='move'}">
+      <i class="iconfont icon-move" @click="moveCanvas"></i>
+    </div> -->
+    <div v-if="config.isEdit&&config.groupSelect" :class="{'active':active=='groupSelect'}" @click="groupSelect">
+      <i class="iconfont icon-shuxingxuanze"></i>
+    </div>
+    <div @click="fitToWindow">
+      <i class="iconfont icon-maximize"></i>
+    </div>
+    <div v-if="!config.isEdit">
+      <el-dropdown size="mini" placement="top-start" @command="handleCommand">
+        <i class="el-icon-download" style="font-size:20px;color:#fff;"></i>
+        <el-dropdown-menu slot='dropdown'>
+          <el-dropdown-item command="savePng">保存为png</el-dropdown-item>
+          <el-dropdown-item command="saveSvg">保存为svg</el-dropdown-item>
+          <el-dropdown-item command="saveJson">保存为Json</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+    <div v-if="config.isEdit&&config.divide" :class="{'active':active=='divide'}" @click="divide">
+      <el-dropdown size="mini" placement="top-start" @command="handleDivideCommand" :hide-on-click="false">
+        <i class="iconfont icon-edit1"></i>
+        <el-dropdown-menu slot='dropdown'>
+          <el-dropdown-item command="savePng">
+            吸附 <el-switch v-model="isSwitch"></el-switch>
+          </el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </div>
+    <div v-if="config.isEdit&&config.divide" @click="clearDivide">
+      <i class="iconfont icon-Erase"></i>
+    </div>
+    <!-- <div v-if="config.isEdit" @click="undo">
+      <i class="iconfont icon-Cancel"></i>
+    </div>
+    <div v-if="config.isEdit" @click="redo">
+      <i class="iconfont icon-Anti-cancel"></i>
+    </div> -->
+    <div @click="reduce">
+      <i class="iconfont icon-narrow"></i>
+    </div>
+    <div class="line">
+      <el-slider tooltip-class="tooltip-class" :min="min" v-model="sliderVal" :show-tooltip="false" @input="scale" :max="max"></el-slider>
+    </div>
+    <div @click="plus">
+      <i class="iconfont icon-zoom"></i>
+    </div>
+  </el-row>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      sliderVal: 1, // 滑块值
+      active: '',
+      min: 1,
+      max: 1000,
+      everyScale: 1, // 每份的放大倍数
+      isSwitch: false, // 是否开启吸附
+    }
+  },
+  props: {
+    config: {
+      type: Object,
+      default: {
+        isEdit: false,
+        divide: true,
+        groupSelect: false
+      }
+    }
+  },
+  computed: {
+  },
+  methods: {
+    // 移动画布
+    // moveCanvas() {
+    //   this.active = this.active != "move" ? "move" : '';
+    //   this.$emit('move', this.active == 'move');
+    // },
+    //
+    groupSelect() {
+      this.active = 'groupSelect';
+      this.$emit('groupSelect');
+    },
+    // 适配大小
+    fitToWindow() {
+      this.$emit('fit');
+    },
+    // 下拉菜单
+    handleCommand(command) {
+      this.$emit(command)
+    },
+    // 是否开启吸附
+    handleDivideCommand(commond) {
+      this.$emit('changeAbsorb', this.isSwitch);
+    },
+    // 切割编辑
+    divide() {
+      this.active = 'divide';
+      this.$emit('divide');
+    },
+    // 清除编辑
+    clearDivide() {
+      this.active = '';
+      this.$emit('clearDivide');
+    },
+    // 撤销
+    undo() {
+      this.$emit('undo');
+    },
+    // 反撤销
+    redo() {
+      this.$emit('redo');
+    },
+    // 减
+    reduce() {
+      this.sliderVal /= 1.1;
+      if (this.sliderVal < this.min) {
+        this.sliderVal = this.min;
+      }
+      this.scale(this.sliderVal);
+    },
+    // 缩放
+    scale(val) {
+      // 换算
+      let scale = val * this.everyScale / 10;
+      this.$emit('scale', scale);
+    },
+    // 加
+    plus() {
+      this.sliderVal *= 1.1;
+      if (this.sliderVal > this.maxScale) {
+        this.sliderVal = this.maxScale;
+      }
+      this.scale(this.sliderVal);
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#canvas-actions-box {
+  // min-width: 542px;
+  & > div {
+    float: left;
+    font-size: 20px;
+    padding: 0 10px;
+    color: #fff;
+    background-color: #6da60f;
+    i {
+      cursor: pointer;
+      color: #fff;
+    }
+  }
+  & > div:active {
+    background-color: #4b7902;
+  }
+  & > div.active {
+    background-color: #4b7902;
+  }
+  &.isEdit > div {
+    background-color: #02a7f0;
+  }
+  &.isEdit > div:active {
+    background-color: #027db4;
+  }
+  &.isEdit > div.active {
+    background-color: #027db4;
+  }
+  & > div.line {
+    width: 200px;
+    height: 40px;
+    padding: 0;
+    /deep/.el-slider__runway {
+      margin: 18px 0;
+      height: 4px;
+      .el-slider__bar {
+        background-color: #fff;
+        height: 4px;
+      }
+    }
+  }
+}
+</style>

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

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

File diff suppressed because it is too large
+ 1547 - 0
src/components/business_space/newGraphy/graphy.vue


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

@@ -0,0 +1,184 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogVisible" width="900px" id="unRelateBSP">
+    <el-row class="filters">
+      <el-col :span="9">
+        <el-input placeholder="输入业务空间名称进行查询" v-model="keycode" clearable @keyup.enter.native="getTableData">
+          <i slot="suffix" class="el-input__icon el-icon-search" @click="getTableData"></i>
+        </el-input>
+      </el-col>
+      <el-col :span="15">
+        <span style="margin-left:10px;">所属楼层</span>
+        <el-cascader @change="getTableData" v-model="floor" :options="options" :props="props"></el-cascader>
+      </el-col>
+    </el-row>
+    <div class="table-box">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading"
+                :header-cell-style="headerStyle">
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{ scope.row.localName || scope.row.name || '' }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="BNAME" label="所属建筑" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="FNAME" label="所属楼层" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100" v-if="isAction">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="createRelation(scope.row)" type="primary" plain>关联平面图</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <el-pagination class="fr" v-show="tableData && tableData.length" @size-change="handleSizeChange"
+                     @current-change="handleCurrentChange"
+                     :current-page="page.pageNumber" :page-sizes="page.pageSizes" :page-size="page.pageSize"
+                     layout="total, sizes, prev, pager, next, jumper"
+                     :total="page.total"></el-pagination>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  // buildingQuery,
+  zoneQuery
+} from "@/api/scan/request"
+import { buildingQuery } from '@/api/object/build';
+
+export default {
+  name: "unRelateBSP",
+  data() {
+    return {
+      title: '未关联平面图的业务空间',
+      inSpaceType: '业务空间',
+      dialogVisible: false,
+      loading: false,
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      keycode: '',
+      tableData: [],
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      floor: ['all'], // 级联建筑楼层
+      props: { //自定义字段
+        value: "id",
+        label: "localName",
+        children: "floor"
+      },
+      bfData: {}, //建筑楼层id =>名称
+      options: [], //级联
+    };
+  },
+  props: {
+    isAction: false, //是否显示操作按钮
+    code: String
+  },
+  created() {
+    this.getBuilding()
+  },
+  methods: {
+    // 显示弹窗
+    showDialog(buildFloor) {
+      if (buildFloor) {
+        this.floor = buildFloor;
+      }
+      this.dialogVisible = true;
+      this.getTableData();
+    },
+    // 关联平面图
+    createRelation(row) {
+      this.$emit('createFromUnrelated', row);
+      this.dialogVisible = false;
+    },
+    // 分页条数
+    handleSizeChange(val) {
+      this.page.pageSize = val;
+      this.page.pageNumber = 1;
+      this.getTableData();
+    },
+    // 页码
+    handleCurrentChange(val) {
+      this.page.pageNumber = val;
+      this.getTableData();
+    },
+    // 获取项目下建筑
+    getBuilding() {
+      let pa = {
+        cascade: [{ name: 'floor', orders: 'floorSequenceID desc' }],
+        orders: "localName asc",
+      }
+      buildingQuery(pa, res => {
+        this.options = res.content.map(t => {
+          this.bfData[t.id] = t.localName;
+          if (t.floor) {
+            t.floor = t.floor.map(item => {
+              this.bfData[item.id] = item.localName;
+              return item;
+            })
+          } else {
+            t.floor = []
+          }
+          t.floor.unshift({ id: 'all', localName: '全部' }, { id: 'isNull', localName: '未明确楼层' })
+          return t;
+        })
+        this.options.unshift({ id: 'all', localName: '全部' }, { id: 'isNull', localName: '未明确建筑' })
+      })
+    },
+    // 查询未关联平面图的业务空间(项目下+当前分区)
+    getTableData() {
+      let pa = {
+        zoneType: this.code,
+        filters: `outline isNull`,
+        orders: "createTime desc, id asc",
+        pageSize: this.page.pageSize,
+        pageNumber: this.page.pageNumber
+      }
+
+      if (this.floor[0] == 'isNull') {
+        pa.buildingId = `isnull`
+      } else if (this.floor[0] && this.floor[0] != 'all') {
+        pa.buildingId = this.floor[0]
+      }
+      if (this.floor[1] == 'isNull') {
+        pa.floorId = `isnull`
+      } else if (this.floor[1] && this.floor[1] != 'all') {
+        pa.floorId = this.floor[1]
+      }
+      if (this.keycode != '') {
+        pa.filters += `;localName contain "${this.keycode}" or name contain "${this.keycode}"`
+      }
+      zoneQuery(pa, res => {
+        this.page.total = res.total;
+        this.tableData = res.content.map(t => {
+          t.BNAME = this.bfData[t.buildingId];
+          t.FNAME = this.bfData[t.floorId];
+          return t;
+        })
+      })
+    }
+  },
+};
+</script>
+<style lang="less" scoped>
+#unRelateBSP {
+  .filters {
+    margin-bottom: 10px;
+
+    /deep/ .el-input__inner {
+      vertical-align: baseline;
+    }
+  }
+
+  .table-box {
+    height: 350px;
+  }
+}
+</style>

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

@@ -0,0 +1,183 @@
+<template>
+  <div id="eqInSp">
+    <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 v-show="type=='Equipment'">按空间计算</el-button>
+      </el-tooltip>
+    </el-row>
+    <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>
+              {{scope.row.localName||scope.row.name||''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="localId" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column :label="`${inSpaceType}类`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.equipCategory?scope.row.equipCategory.name:''}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="删除关系" placement="left">
+              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);lineHeight:20px;">
+            <i class="icon-wushuju iconfont"></i>
+            {{type=='Equipment'?`可前往“全部关系总览”中,按坐标计算${typeToTips[type]}`:'无数据'}}
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <!-- 添加设备弹窗 -->
+    <addEquipDialog ref="addEqDialog" :type="type" :spaceId="params.RoomID" :zone="params.zone" @refresh='getTableData'></addEquipDialog>
+  </div>
+</template>
+
+<script>
+import {
+  zoneQuery,
+  eqInSpaceDelete, //设备所在业务空间--删除关系
+  eqForSpaceDelete, //设备服务业务空间--删除关系
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addEquipDialog from "@/components/business_space/newAddDialogs/addEquipDialog"
+export default {
+  components: {
+    addEquipDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: '设备',
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [], //列表数据
+      typeToTips: {
+        Equipment: '空间内的设备',
+        EquipmentFor: '服务于空间的设备',
+      },
+      hidden: true,
+    };
+  },
+  props: {
+    params: {},
+    type: {}
+  },
+  created() {
+    this.getTableData()
+    this.changeContentStyle();
+  },
+  methods: {
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let pa = {
+          data: [{
+            equipId: row.id,
+            spaceId: row.spaceId
+          }],
+          type: this.params.zone
+        }
+        if (this.type == 'equipment') {
+          this.deleteEqInSpace(pa);
+        } else {
+          this.deleteEqForSpace(pa);
+        }
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除设备所在空间关系
+    deleteEqInSpace(pa) {
+      eqInSpaceDelete(pa, res => {
+        this.$message.success('删除成功')
+        this.getTableData()
+      })
+    },
+    // 删除设备服务空间关系
+    deleteEqForSpace(pa) {
+      eqForSpaceDelete(pa, res => {
+        this.$message.success('删除成功')
+        this.getTableData()
+      })
+    },
+    // 改变pagesize
+    handleSizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.getTableData();
+    },
+    // 改变pageno
+    handleCurrentChange(pageNo) {
+      this.page.pageNumber = pageNo;
+      this.getTableData();
+    },
+    // 获取列表数据
+    getTableData() {
+      this.loading = true;
+      let pa = {
+        filters: `id='${this.params.RoomID}'`,
+        cascade: [
+          {
+            name: this.type.replace(this.type[0], this.type[0].toLowerCase()),
+            cascade: [{ name: 'equipCategory' }]
+          }
+        ],
+        zoneType: this.params.zone
+      }
+      zoneQuery(pa, res => {
+        this.loading = false;
+        this.tableData = res.content[0][this.type] || []
+        this.tableData.map(t => {
+          t.spaceId = res.content[0].id
+          return t;
+        })
+      })
+    },
+    // 添加设备
+    add() {
+      this.$refs.addEqDialog.floor = this.params.buildFloorSelectd;
+      this.$refs.addEqDialog.showDialog()
+    },
+    changeContentStyle() {
+      this.$route.name == "spaceLedger" ? this.hidden = false : this.hidden = true;
+    }
+  },
+  watch: {
+    type() {
+      this.getTableData()
+    },
+    params() {
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#eqInSp {
+  height: 100%;
+  .table-box {
+    margin-top: 10px;
+    height: calc(100% - 50px);
+  }
+}
+</style>

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

@@ -0,0 +1,148 @@
+<template>
+  <div id="eqInSp">
+    <el-row v-show="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">
+      <el-table :data="tableData" style="width: 100%" height="100%" v-loading="loading" :header-cell-style="headerStyle">
+        <el-table-column :label="`${inSpaceType}名称`" show-overflow-tooltip min-width="100">
+          <template slot-scope="scope">
+            <div>
+              {{scope.row.localName||scope.row.name}}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="localId" :label="`${inSpaceType}本地编码`" show-overflow-tooltip min-width="100"></el-table-column>
+        <el-table-column prop="action" label="操作" min-width="100">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="删除关系" placement="left">
+              <el-button size="mini" @click="handleDelete(scope.$index, scope.row)" type="danger" plain icon="el-icon-delete"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <template slot="empty">
+          <div style="height: 60%;transform: translateY(50%);lineHeight:20px;">
+            <i class="icon-wushuju iconfont"></i>
+            可前往“全部关系总览”中,按坐标计算{{typeToTips[type]}}
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <addSystemDialog ref="addSyDialog" :type="type" :spaceId="params.RoomID" :zone="params.zone" @refresh='getTableData'></addSystemDialog>
+  </div>
+</template>
+
+<script>
+import {
+  zoneQuery,
+  syInSpaceDelete
+} from "@/api/scan/request";
+import { mapGetters } from "vuex";
+import addSystemDialog from "@/components/business_space/newAddDialogs/addSystemDialog";
+export default {
+  components: {
+    addSystemDialog
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      inSpaceType: '系统',
+      headerStyle: {
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      }, // 列表样式
+      loading: false, // loading
+      tableData: [], //列表数据
+      typeToTips: {
+        generalSystem: '空间内的系统',
+      },
+      hidden: true,
+      loading: false
+    };
+  },
+  props: {
+    params: {},
+    type: {}
+  },
+  created() {
+    this.getTableData();
+    this.changeContentStyle();
+  },
+  methods: {
+    // 删除关系
+    handleDelete(index, row) {
+      this.$confirm("确认删除该关系?", "提示", {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let pa = {
+          data: [{
+            sysId: row.id,
+            spaceId: row.spaceId
+          }],
+          type: this.params.zone
+        }
+        this.deleteSyInSpace(pa)
+      }).catch(() => {
+        this.$message("取消删除")
+      })
+    },
+    // 删除关系
+    deleteSyInSpace(pa) {
+      syInSpaceDelete(pa, res => {
+        this.$message.success('删除成功');
+        this.getTableData();
+      })
+    },
+    // 获取列表数据
+    getTableData() {
+      this.loading = true;
+      let pa = {
+        Cascade: [{ Name: "generalSystem" }],
+        Filters: `id="${this.params.RoomID}"`,
+        ZoneType: this.params.zone
+      }
+      zoneQuery(pa, res => {
+        this.loading = false;
+        this.tableData = res.content[0].generalSystem || [];
+        this.tableData.map(t => {
+          t.spaceId = res.content[0].id;
+          return t;
+        })
+      })
+    },
+    // 添加系统
+    add() {
+      this.$refs.addSyDialog.showDialog()
+    },
+    changeContentStyle() {
+      // 在辅助屏不显示添加按钮,动态设置高度
+      this.$route.name == "spaceLedger" ? this.hidden = false : this.hidden = true;
+    }
+  },
+  watch: {
+    type() {
+      this.getTableData()
+    },
+    params() {
+      this.getTableData()
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#eqInSp {
+  height: 100%;
+  .table-box {
+    margin-top: 10px;
+    height: calc(100% - 50px);
+  }
+}
+</style>

+ 569 - 0
src/components/business_space/table/addEquip.vue

@@ -0,0 +1,569 @@
+<template>
+  <div>
+    <div class="search" style="margin-bottom:10px;">
+      <div>
+        <el-input
+          placeholder="输入设备名称或设备本地编码进行查询"
+          style="width:300px;float:left;margin-right:10px;"
+          v-model="search.filter"
+          clearable
+        ></el-input>
+        <el-button @click="filterBox" plain>查 找</el-button>
+      </div>
+      <div style="margin-top:10px;">
+        <span>所属楼层</span>
+        <el-cascader
+          @change="filterBox"
+          v-model="search.floor"
+          :options="optionsWithDisabled"
+        ></el-cascader>
+        <el-checkbox
+          style="margin-left:20px;"
+          @change="filterBox"
+          :checked="search.checkbox"
+          label="只显示在当前业务空间中的设备"
+        ></el-checkbox>
+      </div>
+    </div>
+    <el-table
+      ref="multipleTable"
+      :data="tableData"
+      v-loading="isLoading"
+      tooltip-effect="dark"
+      class="data-table border"
+      height="300"
+      style="width: 100%"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55"></el-table-column>
+      <el-table-column width="180" label="设备名称">
+        <template slot-scope="scope">
+          <span>
+            <el-tooltip
+              :content="scope.row.infos.EquipLocalName ||scope.row.infos.EquipName"
+              placement="top"
+            >
+              <span>{{scope.row.infos.EquipLocalName || scope.row.infos.EquipName | cutString(15)}}</span>
+            </el-tooltip>
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column width="180" label="设备本地编码">
+        <template slot-scope="scope">
+          <span>
+            <el-tooltip :content="scope.row.infos.EquipLocalID || '--'" placement="top">
+              <span>{{scope.row.infos.EquipLocalID || "--" | cutString(15)}}</span>
+            </el-tooltip>
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column width="160" label="设备类">
+        <template slot-scope="scope">
+          <span>
+            <span>{{getName(scope.row.category)}}</span>
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column width="160" label="已关联其他业务空间">
+        <template slot-scope="scope">
+          <span>
+            <el-tooltip :content="changeArray(scope.row.spaceName)" placement="top">
+              <span>{{changeArray(scope.row.spaceName) | cutString(6)}}</span>
+            </el-tooltip>
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作">
+        <template slot-scope="scope">
+          <el-button plain @click="lockDetails(scope.row)">设备详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-dialog width="40%" title="设备详情" :visible.sync="innerVisible" append-to-body>
+      <iframe height="400px" width="100%" :src="iframeSrc"></iframe>
+    </el-dialog>
+    <div class="right" v-if="tableData.length">
+        <my-pagination :page="page" @change="pageChange"></my-pagination>
+    </div>
+    <div class="el-dialog__footer">
+        <span class="dialog-footer">
+            <el-button@click="clearBox">取 消</el-button>
+            <el-button type="primary" @click="addReal">确 定</el-button>
+        </span>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  getSpaceEquip,
+  searchCode,
+  getEqCode,
+  getSpaceFloor,
+  createRelation,
+  getGraphyId,
+  getEquipSearch,
+  getListForBuss
+} from "@/api/scan/request";
+import myPagination from "@/components/common/myPagination.vue";
+import tools from "@/utils/scan/tools";
+import {
+    mapGetters,
+    mapActions
+} from "vuex";
+export default {
+  name: "equip-table",
+  components: {
+    myPagination
+  },
+  computed: {
+        ...mapGetters("layout", [
+            "projectId",
+            "secret",
+            "userId"
+        ])
+    },
+  data() {
+    return {
+      search: {
+        filter: "",
+        checkbox: false,
+        floor: [],
+        leiArr: []
+      },
+      innerVisible: false,
+      iframeSrc: "",
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 400,
+        currentPage: 1
+      },
+      optionsWithDisabled: [],
+      tableData: [],
+      allData: [], //全部的数据
+      multipleSelection: [],
+      list: {},
+      build: {},
+      graphyId: "",
+      isLoading: false,
+      activeTabType: null,
+    };
+  },
+  created() {
+    // this.getData();
+    this.getEqCode();
+    // this.getFloor();
+  },
+  methods: {
+    getEqCode() {
+      getEqCode()
+        .then(res => {
+          if (res.data.Result == "success") {
+            this.EqCode = res.data.Content;
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch(() => {
+          this.$message.error("请求失败");
+        });
+    },
+    changeArray(val) {
+      if (val instanceof Array) {
+        return val.join(",");
+      } else {
+        return "--";
+      }
+    },
+    clearBox() {
+      this.$refs.multipleTable.clearSelection();
+    },
+    //获取设备关系
+    getGraphyId() {
+      let param = {
+        type: this.type,
+        ProjId: this.projectId, //项目id
+        secret: this.secret
+      };
+      getGraphyId(param)
+        .then(res => {
+          if (res.data.Result == "success") {
+            this.graphyId = res.data.graph_id;
+            this.getEquip()
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch(() => {
+          this.$message.error("请求错误");
+        });
+    },
+    //获取楼层
+    // getFloor() { // 物理世界 已无接口
+    //   let param = {
+    //     ProjId: this.projectId,
+    //     UserId: this.userId,
+    //     secret: this.secret
+    //   };
+    //   getSpaceFloor(param)
+    //     .then(res => {
+    //       if (res.data.Result == "success") {
+    //         this.optionsWithDisabled = this.changeArr(res.data.Content);
+    //         this.optionsWithDisabled = this.optionsWithDisabled.map(item => {
+    //           if (item.children && item.children.length) {
+    //             item.children.unshift({
+    //               value: "no",
+    //               label: "未指定楼层的设备"
+    //             });
+    //           } else {
+    //             item.children = [{
+    //               value: "no",
+    //               label: "未指定楼层的设备"
+    //             }];
+    //           }
+    //           return item;
+    //         });
+    //       } else {
+    //         this.$message.error(res.data.ResultMsg);
+    //       }
+    //     })
+    //     .catch(() => {
+    //       this.$message.error("请求出错");
+    //     });
+    // },
+    getName(code) {
+      let text = "",
+        myClass = code.substring(0, 2),
+        system = code.substring(2, 4),
+        last = code.substring(2, 6);
+      if (this.EqCode && this.EqCode.length) {
+        this.EqCode.map(item => {
+          if (item.code == myClass) {
+            item.content.map(i => {
+              if (i.code == system) {
+                i.content.map(e => {
+                  if ((e.code == last)) {
+                    text = e.facility;
+                  }
+                });
+              }
+            });
+          }
+        });
+      }
+      return text;
+    },
+    //工具函数,获取下拉列表
+    changeArr(arr) {
+      return arr.map(item => {
+        if (item.floors && item.floors.length) {
+          return {
+            value: item.id,
+            label: item.infos.BuildLocalName || "--",
+            children: item.floors.map(i => {
+              return {
+                value: i.id,
+                label: i.infos.FloorLocalName || "--"
+              };
+            })
+          };
+        } else {
+          return {
+            value: item.id,
+            label: item.infos.BuildLocalName || "--",
+            children: null
+          };
+        }
+      });
+    },
+    /**
+     * 过滤条件
+     */
+    filterBox(val) {
+      if (typeof val == "boolean") {
+        this.search.checkbox = val;
+      }
+      if (this.search.checkbox) {
+        this.getEquip()
+      } else {
+        if (!!this.search.filter) {
+          searchCode({
+            key: this.search.filter
+          })
+            .then(res => {
+              if (res.data.Result == "success") {
+                this.search.leiArr = res.data.Content;
+                this.getEquip();
+              } else {
+                this.$message.error(res.data.ResultMsg);
+              }
+            })
+            .catch(() => {
+              this.$message.error("请求出错");
+            });
+        } else {
+          this.getEquip();
+        }
+      }
+    },
+    /**
+     * 删除
+     * @param row 点击的当条数据
+     */
+    deleteSpace(row) { },
+    /**
+     * 获取数据
+     * @param data 由上级页面传入,初始化table表格
+     */
+    getData(list, build, type, activeTabType) {
+      this.activeTabType = activeTabType
+      this.list = list;
+      this.build = build;
+      this.search.floor = [build.buildCode, build.code];
+      this.type = type
+      this.getGraphyId();
+      this.page = {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      };
+      this.getEquip();
+    },
+    //获取数据
+    getEquip() {
+      this.isLoading = true;
+      let relType = ""
+      if (this.activeTabType.rel_type == 99) {
+        relType = "1"
+      } else {
+        if (this.activeTabType.rel_type > 9) {
+          relType = (this.activeTabType.rel_type * 100).toString()
+        } else {
+          relType = '0' + this.activeTabType.rel_type * 100
+        }
+      }
+      if (this.type == "EquipinSpace" && this.activeTabType.rel_type == 99) {
+        if (this.search.checkbox) {
+          this.isLoading = false
+          this.tableData = []
+          this.page.total = 0
+        } else {
+          if (!this.search.filter) {
+            this.search.leiArr = []
+          }
+          let param = {
+            data: {
+              limit: {
+                // 可选
+                skip: this.page.size * (this.page.currentPage - 1), // 跳过多少数据
+                count: this.page.size // 查询跳过300条数据之后的50条 (默认按照创建时间从大-->小排序)
+              },
+              criteria: {
+                building: this.search.floor[0], //建筑
+                floor: this.search.floor[1] == "no" ? null : this.search.floor[1], // 选填, 指定楼层id
+                name: this.search.filter, // 选填, 模糊搜索指定信息点的值
+                type: this.search.leiArr.length ? this.search.leiArr : ["Eq"],
+                space: this.list.id, // 必填, 指定业务空间id
+                excludeGraphType: this.type,
+                excludeRelType: relType,
+                isGeneralZone: true,
+                type: ["Eq"] // 必填, 查询类型, 允许四位编码的详细设备类
+              }
+            },
+            ProjId: this.projectId, //项目id
+            secret: this.secret
+          };
+          getEquipSearch(param)
+            .then(res => {
+              if (res.data.Result == "success") {
+                this.page.total = res.data.TotalCount;
+                this.tableData = res.data.Content;
+                this.isLoading = false;
+              } else {
+                this.$message.error(res.data.ResultMsg);
+              }
+            })
+            .catch(() => this.$message.error("请求失败"));
+        }
+      } else {
+        if (this.search.checkbox) {
+          let param = {
+            data: {
+              limit: {
+                // 可选
+                skip: this.page.size * (this.page.currentPage - 1), // 跳过多少数据
+                count: this.page.size // 查询跳过300条数据之后的50条 (默认按照创建时间从大-->小排序)
+              },
+              criteria: {
+                building: this.search.floor[0], //建筑
+                floor: this.search.floor[1] == "no" ? null : this.search.floor[1], // 选填, 指定楼层id
+                name: this.search.filter, // 选填, 模糊搜索指定信息点的值
+                type: this.search.leiArr.length ? this.search.leiArr : ["Eq"],
+                space: this.list.id, // 必填, 指定业务空间id
+                excludeGraphType: this.type,
+                excludeRelType: relType
+              }
+            },
+            ProjId: this.projectId, //项目id
+            secret: this.secret
+          };
+          getListForBuss(param, res => {
+            this.page.total = res.TotalCount;
+            this.tableData = res.Content;
+            this.isLoading = false;
+          })
+        } else {
+          let param = {
+            data: {
+              limit: {
+                // 可选
+                skip: this.page.size * (this.page.currentPage - 1), // 跳过多少数据
+                count: this.page.size // 查询跳过300条数据之后的50条 (默认按照创建时间从大-->小排序)
+              },
+              criteria: {
+                building: this.search.floor[0], //建筑
+                floor: this.search.floor[1] == "no" ? null : this.search.floor[1], // 选填, 指定楼层id
+                name: this.search.filter, // 选填, 模糊搜索指定信息点的值
+                type: this.search.leiArr.length ? this.search.leiArr : ["Eq"],
+                space: this.list.id, // 必填, 指定业务空间id
+                excludeGraphType: this.type,
+                excludeRelType: relType,
+                type: ["Eq"] // 必填, 查询类型, 允许四位编码的详细设备类
+              }
+            },
+            ProjId: this.projectId, //项目id
+            secret: this.secret
+          };
+          getEquipSearch(param)
+            .then(res => {
+              if (res.data.Result == "success") {
+                this.page.total = res.data.TotalCount;
+                this.tableData = res.data.Content;
+                this.isLoading = false;
+              } else {
+                this.$message.error(res.data.ResultMsg);
+              }
+            })
+            .catch(() => this.$message.error("请求失败"));
+        }
+      }
+    },
+    /**
+     * 分页函数
+     * @param pageNo   当前页数
+     * @param pageSize 当前条数
+     * @param array    全部数据
+     */
+    pagination(pageNo, pageSize, array) {
+      let offset = (pageNo - 1) * pageSize;
+      return offset + pageSize >= array.length ?
+        array.slice(offset, array.length) :
+        array.slice(offset, offset + pageSize);
+    },
+    /**
+     * 查看详情
+     * @param row 点击的当条数据
+     */
+    lockDetails(row) {
+      this.innerVisible = true;
+      this.iframeSrc = this.iframeSrc =
+        // process.env.BASE_URL + 
+        window.__systemConf.BASE_URL +
+        ":8889/#/details?perjectId=" +
+        this.projectId +
+        "&secret=" +
+        this.secret +
+        "&FmId=" +
+        row.id +
+        "&type=0&code=" +
+        row.category.substring(2, 6);
+    },
+    pageChange() {
+      this.getEquip();
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    //添加关系,点击确定按钮
+    addReal() {
+      if (this.multipleSelection && this.multipleSelection.length) {
+        let param = {
+          data: {
+            criterias: []
+          },
+          ProjId: this.projectId, //项目id
+          secret: this.secret
+        };
+        let falg = false;
+        if (!!!this.activeTabType) {
+          this.$message.error("没有rel_type")
+        }
+        this.multipleSelection.map(item => {
+          let rel_type = ""
+          if (this.activeTabType.rel_type < 10) {
+            rel_type = '0' + (this.activeTabType.rel_type * 100)
+          } else {
+            rel_type = (this.activeTabType.rel_type * 100).toString()
+          }
+          param.data.criterias.push({
+            from_id: item.id,
+            to_id: this.list.id,
+            graph_id: this.graphyId,
+            rel_type: this.activeTabType.rel_type == "99" ? "1" : rel_type
+          });
+          if (!!item.spaceName) {
+            falg = true;
+          }
+        });
+        if (falg) {
+          this.$confirm("选择的部分设备不在业务空间中确定添加?", "删除", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+            .then(() => {
+              this.createReal(param);
+            })
+            .catch(() => {
+              this.$message({
+                type: "info",
+                message: "已取消添加"
+              });
+              this.clearBox();
+            });
+        } else {
+          this.createReal(param);
+        }
+      } else {
+        this.$message.error("请选择设备再确定关联");
+      }
+    },
+    createReal(param) {
+      createRelation(param)
+        .then(res => {
+          if (res.data.Result == "success") {
+            this.$message.success("添加成功");
+            this.getEquip();
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch(() => {
+          this.$message.error("请求出错");
+        });
+    }
+  },
+  filters: {
+    cutString: function (str, len) {
+      //length属性读出来的汉字长度为1
+      if (!!str && typeof str == "string" && str.length > len) {
+        return str.substring(0, len) + "...";
+      } else {
+        return str || "--";
+      }
+    }
+  }
+};
+</script>

+ 248 - 0
src/components/business_space/table/businessTable.vue

@@ -0,0 +1,248 @@
+<template>
+  <div>
+    <div style="margin-bottom: 15px;">
+      <el-input
+        placeholder="请输入内容"
+        @blur="querySearch"
+        size="small"
+        v-model="search"
+        class="input-with-select"
+      >
+        <el-button slot="append" @click="querySearch" icon="el-icon-search"></el-button>
+      </el-input>
+    </div>
+    <div>
+        <el-table
+            :data="tableData"
+            height="300"
+            :stripe="true"
+            border
+            class="data-table border"
+            v-loading="isLoading"
+            style="width: 100%"
+            >
+            <el-table-column label="业务空间名称">
+                <template slot-scope="scope">
+                <span>
+                    <el-tooltip
+                    :content="scope.row.infos.RoomLocalName || scope.row.infos.RoomName"
+                    placement="top"
+                    >
+                    <span>{{scope.row.infos.RoomLocalName || scope.row.infos.RoomName | cutString(8)}}</span>
+                    </el-tooltip>
+                </span>
+                </template>
+            </el-table-column>
+            <el-table-column v-if="type == 'relevance'" label="操作">
+                <template slot-scope="scope">
+                <el-button @click="deleteSpace(scope.row)">关联平面图</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+    </div>
+    <div class="right" v-if="tableData.length">
+        <my-pagination :page="page" @change="pageChange"></my-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getBussines2, createRelation } from "@/api/scan/request";
+import myPagination from "@/components/common/myPagination.vue";
+import { mapGetters, mapActions } from "vuex";
+export default {
+  name: "equip-table",
+  components: {
+    myPagination
+  },
+  computed: {
+            ...mapGetters("layout", [
+                "projectId",
+                "secret",
+                "userId"
+            ])
+        },
+  props: {
+    type: {
+      type: String,
+      default: "default"
+    }
+  },
+  data() {
+    return {
+      page: {
+        size: 50,
+        sizes: [50, 100, 150, 200],
+        total: 1,
+        currentPage: 1
+      },
+      tableData: [],
+      allData: null,
+      search: "",
+      list: {},
+      graphy: "",
+      isLoading: false,
+      code: null
+    };
+  },
+  created() { },
+  methods: {
+    getData(list, build, graphy, code) {
+      this.isLoading = true;
+      this.list = list;
+      this.graphy = graphy;
+      this.code = code
+      getBussines2(
+        //       {
+        //     data: {
+        //       criteria: {
+        //         id: build.code,
+        //         graphId: graphy,
+        //         relType: !!code ? code.rel_type : "99",
+        //         exclude: "false",
+        //         side: 1,
+        //         type: [code.code]
+        //       }
+        //     },
+        //     ProjId: this.projectId,
+        //     secret: this.secret
+        //   }
+        {
+          data: {
+            criteria: {
+              id: build.code,
+              // graphId: this.graphyId,
+              // relType: this.spaceType.rel_type,
+              // exclude: false,
+              // side: 1,
+              type: [code.code],
+              "exclude": [            // 可选, 只查询指定图/关系中的对象
+                {
+                  "graphId": graphy,
+                  "graphType": code.code,
+                  "relType": !!code ? code.rel_type : "99",
+                  "side": "toId",
+                  // "fromId": "",                 // 选填
+                  // "toId": ""                    // 选填
+                }
+              ]
+            },
+          },
+          ProjId: this.projectId,
+          secret: this.secret
+        })
+        .then(res => {
+          if (res.data.Result == "success") {
+            this.allData = res.data.Content || [];
+            this.page.total = this.allData.length;
+            this.tableData = this.pagination(
+              this.page.currentPage,
+              this.page.size,
+              this.allData
+            );
+            this.isLoading = false;
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch((err) => {
+          console.log(err)
+          // this.$message.error("请求出错");
+        });
+    },
+    /**
+     * 分页函数
+     * @param pageNo   当前页数
+     * @param pageSize 当前条数
+     * @param array    全部数据
+     */
+    pagination(pageNo, pageSize, array) {
+      let offset = (pageNo - 1) * pageSize;
+      return offset + pageSize >= array.length
+        ? array.slice(offset, array.length)
+        : array.slice(offset, offset + pageSize);
+    },
+
+    //搜索
+    querySearch() {
+      var restaurants = this.allData;
+      var results = this.search
+        ? restaurants.filter(this.createFilter(this.search))
+        : restaurants;
+      this.page.total = results.length;
+      this.tableData = this.tableData = this.pagination(
+        this.page.currentPage,
+        this.page.size,
+        results
+      );
+    },
+    createFilter(queryString) {
+      return restaurant => {
+        return (
+          restaurant.infos.RoomLocalName.indexOf(queryString) > -1
+        );
+      };
+    },
+    /**
+     * 删除
+     * @param row 点击的当条数据
+     */
+    deleteSpace(row) {
+      let param = {
+        data: {
+          criterias: []
+        },
+        ProjId: this.projectId,
+        secret: this.secret
+      };
+      this.list.map(item => {
+        param.data.criterias.push({
+          from_id: item.id, //必填,object id
+          to_id: row.id, //必填,object id
+          graph_id: this.graphy, //必填,图实例id
+          rel_type: this.code.rel_type
+        });
+      });
+      createRelation(param)
+        .then(res => {
+          if (res.data.Result == "success") {
+            this.$message.success("关联成功");
+            this.$emit("createSuccess");
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch(() => {
+          this.$message.error("请求失败");
+        });
+    },
+    /**
+     * 查看详情
+     * @param row 点击的当条数据
+     */
+    lockDetails(row) { },
+    pageChange() {
+      this.tableData = this.pagination(
+        this.page.currentPage,
+        this.page.size,
+        this.allData
+      );
+    }
+  },
+  filters: {
+    cutString: function (str, len) {
+      //length属性读出来的汉字长度为1
+      if (!!str && typeof str == "string" && str.length > len) {
+        return str.substring(0, len) + "...";
+      } else {
+        return str || "--";
+      }
+    }
+  }
+};
+</script>
+<style>
+/* .el-table tr th { */
+  /* background: #fafafa !important; */
+/* } */
+</style>

+ 368 - 0
src/components/business_space/table/equipTable.vue

@@ -0,0 +1,368 @@
+<template>
+    <div>
+        <el-tabs v-model="activeRelation" @tab-click="changeTabs">
+            <el-tab-pane v-for=" (item,index) in relationList" :key="index" :label="item.name" :name="item.code">
+                <el-table :data="tableData" height="300" class="data-table border" :stripe="true" border size="small" v-loading="isLoading" style="width: 100%">
+                    <el-table-column width="180" label="设备名称">
+                        <template slot-scope="scope">
+                            <span>
+                                <el-tooltip :content="scope.row.infos.EquipName" placement="top">                                 
+                                <span>{{scope.row.infos.EquipLocalName || scope.row.infos.EquipName | cutString(15)}}</span>
+                                </el-tooltip>
+                            </span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column width="160" label="设备类">
+                        <template slot-scope="scope">
+                            <span>
+                                <span>{{getName(scope.row.category)}}</span>
+                            </span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作">
+                        <template slot-scope="scope">
+                            <el-button plain @click="lockDetails(scope.row)">详情</el-button>
+                            <el-button v-if="scope.row.inSpace" plain type="danger" @click="deleteSpace(scope.row)">从空间移除</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <div class="right" v-show="tableData.length">
+                    <my-pagination :page="page" @change="pageChange"></my-pagination>
+                </div>
+            </el-tab-pane>
+        </el-tabs>
+        <el-dialog width="40%" title="设备详情" :visible.sync="innerVisible" append-to-body>
+        <iframe height="400px" width="100%" :src="iframeSrc"></iframe>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+    import myPagination from "@/components/common/myPagination.vue";
+    import {
+        getSpaceEquip,
+        getEqCode,
+        deleteRelation,
+        getGraphyId,
+        getSysToEq
+    } from "@/api/scan/request";
+    import {
+        mapGetters,
+        mapActions
+    } from "vuex";
+    export default {
+        name: "equip-table",
+        components: {
+            myPagination
+        },
+        computed: {
+            ...mapGetters("layout", [
+                "projectId",
+                "secret",
+                "userId"
+            ])
+        },
+        props: {
+            param: {
+                type: Object
+            },
+            activeTabType: {
+                type: Object,
+                default: function() {
+                    return {
+                        "code": "GeneralZone",
+                        "name": "默认分区",
+                        "rel_type": "99"
+                    }
+                }
+            }
+        },
+        data() {
+            return {
+                page: {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                },
+                tableData: [],
+                data: {},
+                EqCode: [],
+                innerVisible: false,
+                iframeSrc: "",
+                title: "",
+                graphyId: "",
+                isLoading: false,
+                relationList: [{
+                    name: "空间内的设备",
+                    code: "EquipinSpace"
+                }, {
+                    name: "服务于空间的设备",
+                    code: "EquipforSpace"
+                }, {
+                    name: "其他关系的设备",
+                    code: "EquipXSpace"
+                }],
+                activeRelation: "EquipinSpace",
+                CalcUrl: {
+                    "code": "GeneralZone",
+                    "name": "默认分区",
+                    "rel_type": "99"
+                },
+                relType: 0
+            };
+        },
+        created() {
+            this.getEqCode();
+        },
+        methods: {
+            changeTabs() {
+                let param = {
+                    data: {
+                        limit: {
+                            // 可选
+                            skip: this.page.size * (this.page.currentPage - 1), // 跳过多少数据
+                            count: this.page.size // 查询跳过300条数据之后的50条 (默认按照创建时间从大-->小排序)
+                        },
+                        criteria: {
+                            space: this.data.id, // 必填, 指定业务空间id
+                            type: ["Eq"] // 必填, 查询类型, 允许四位编码的详细设备类
+                        }
+                    },
+                    ProjId: this.projectId, //项目id
+                    secret: this.secret
+                };
+                this.isLoading = true
+                if (this.CalcUrl.rel_type == 99 && this.activeRelation == "EquipinSpace") {
+                    this.dataChange(param);
+                } else {
+                    this.getRlations()
+                }
+            },
+            getEqCode() {
+                getEqCode()
+                    .then(res => {
+                        if (res.data.Result == "success") {
+                            this.EqCode = res.data.Content;
+                        } else {
+                            this.$message.error(res.data.ResultMsg);
+                        }
+                    })
+                    .catch(() => {
+                        this.$message.error("请求失败");
+                    });
+            },
+            getGraphyId(row) {
+                let param = {
+                    type: this.activeRelation,
+                    ProjId: this.projectId, //项目id
+                    secret: this.secret
+                };
+                getGraphyId(param)
+                    .then(res => {
+                        if (res.data.Result == "success") {
+                            this.graphyId = res.data.graph_id;
+                            this.deleteOwn(row)
+                        } else {
+                            this.$message.error(res.data.ResultMsg);
+                        }
+                    })
+                    .catch(() => {
+                        this.$message.error("请求错误");
+                    });
+            },
+            getRlations() {
+                this.isLoading = true
+                this.relType = 0
+                if (this.CalcUrl.rel_type == 99) {
+                    this.relType = "1"
+                } else {
+                    if (this.CalcUrl.rel_type > 9) {
+                        this.relType = (this.CalcUrl.rel_type * 100).toString()
+                    } else {
+                        this.relType = '0' + (this.CalcUrl.rel_type * 100)
+                    }
+                }
+                let param = {
+                    data: {
+                        "limit": { // 可选
+                            skip: this.page.size * (this.page.currentPage - 1), // 跳过多少数据
+                            count: this.page.size // 查询跳过300条数据之后的50条 (默认按照创建时间从大-->小排序)
+                        },
+                        criteria: {
+                            graphType: this.activeRelation,
+                            relType: this.relType,
+                            toId: this.data.id,
+                            fromId: this.data.fromId,
+                            type: ["Eq"]
+                        }
+                    },
+                    ProjId: this.projectId, //项目id
+                    secret: this.secret
+                }
+                getSysToEq(param, res => {
+                    this.tableData = res.Content.map(item => {
+                        item.inSpace = true
+                        return item
+                    })
+                    this.page.total = res.TotalCount;
+                    this.isLoading = false
+                })
+            },
+            deleteOwn(row) {
+                let param = {
+                    data: {
+                        criterias: [{
+                            from_id: row.id, //选填
+                            to_id: this.data.id, //选填
+                            graph_id: this.graphyId, //选填
+                            rel_type: this.relType
+                        }]
+                    },
+                    ProjId: this.projectId, //项目id
+                    secret: this.secret
+                };
+                this.$confirm("正在删除设备关系, 是否继续?", "删除", {
+                        confirmButtonText: "确定",
+                        cancelButtonText: "取消",
+                        type: "warning"
+                    })
+                    .then(() => {
+                        deleteRelation(param)
+                            .then(res => {
+                                if (res.data.Result == "success") {
+                                    this.$message.success("删除成功");
+                                    this.change();
+                                } else {
+                                    this.$message.error(res.data.ResultMsg);
+                                }
+                            })
+                            .catch(() => {
+                                this.$message.error("请求出错");
+                            });
+                    })
+                    .catch(() => {
+                        this.$message("取消删除");
+                    });
+            },
+            getName(code) {
+                let text = "",
+                    myClass = code.substring(0, 2),
+                    system = code.substring(2, 4),
+                    last = code.substring(2, 6);
+                if (this.EqCode && this.EqCode.length) {
+                    this.EqCode.map(item => {
+                        if (item.code == myClass) {
+                            item.content.map(i => {
+                                if (i.code == system) {
+                                    i.content.map(e => {
+                                        if ((e.code == last)) {
+                                            text = e.facility;
+                                        }
+                                    });
+                                }
+                            });
+                        }
+                    });
+                }
+                return text;
+            },
+            /**
+             * 删除
+             * @param row 点击的当条数据
+             */
+            deleteSpace(row) {
+                this.getGraphyId(row)
+            },
+            /**
+             * 获取数据
+             * @param data 由上级页面传入,初始化table表格
+             */
+            getData(data, type) {
+                this.activeRelation = "EquipinSpace"
+                this.CalcUrl = type
+                this.page = {
+                    size: 50,
+                    sizes: [10, 30, 50, 100, 150, 200],
+                    total: 0,
+                    currentPage: 1
+                };
+                this.data = data;
+                this.change();
+            },
+            change() {
+                let param = {
+                    data: {
+                        limit: {
+                            // 可选
+                            skip: this.page.size * (this.page.currentPage - 1), // 跳过多少数据
+                            count: this.page.size // 查询跳过300条数据之后的50条 (默认按照创建时间从大-->小排序)
+                        },
+                        criteria: {
+                            space: this.data.id, // 必填, 指定业务空间id
+                            type: ["Eq"] // 必填, 查询类型, 允许四位编码的详细设备类
+                        }
+                    },
+                    ProjId: this.projectId, //项目id
+                    secret: this.secret
+                };
+                this.isLoading = true
+                if (this.CalcUrl.rel_type == 99) {
+                    this.dataChange(param);
+                } else {
+                    this.getRlations()
+                }
+            },
+            dataChange(param) {
+                getSpaceEquip(param)
+                    .then(res => {
+                        if (res.data.Result == "success") {
+                            this.page.total = res.data.TotalCount;
+                            this.tableData = res.data.Content;
+                            this.isLoading = false
+                        } else {
+                            this.$message.error(res.data.ResultMsg);
+                        }
+                    })
+                    .catch(() => this.$message.error("请求失败"));
+            },
+            /**
+             * 查看详情
+             * @param row 点击的当条数据
+             */
+            lockDetails(row) {
+                this.innerVisible = true;
+                this.iframeSrc = this.iframeSrc =
+                    // "http://172.16.0.181:8889/#/details?perjectId=" +
+                    // process.env.BASE_URL + 
+                    window.__systemConf.BASE_URL +
+                    ":8889/#/details?perjectId=" +
+                    this.projectId +
+                    "&secret=" +
+                    this.secret +
+                    "&FmId=" +
+                    row.id +
+                    "&type=0&code=" +
+                    row.category.substring(2, 6);
+            },
+            pageChange() {
+                this.change();
+            }
+        },
+        filters: {
+            cutString: function(str, len) {
+                //length属性读出来的汉字长度为1
+                if (!!str && typeof str == "string" && str.length > len) {
+                    return str.substring(0, len) + "...";
+                } else {
+                    return str || "--";
+                }
+            }
+        }
+    };
+</script>
+<style>
+    /* .el-table tr th { */
+        /* background: #fafafa !important; */
+    /* } */
+</style>

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

@@ -0,0 +1,61 @@
+<!--
+    props:{
+        size: 当前页的页数,
+        sizes: 下拉的条数,
+        total: 总条数,
+        currentPage: 当前页
+    }
+    @change 发生改变
+-->
+<template>
+    <div class="block">
+        <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page.sync="page.currentPage"
+        :page-sizes="page.sizes"
+        :page-size="page.size"
+        :layout=" isSmall ? 'total, sizes, prev, pager, next, jumper' : 'prev, pager, next'"
+        :total="page.total">
+        </el-pagination>
+    </div>
+</template>
+<script>
+export default {
+  name: "pagination",
+  props: {
+    page: {
+      type: Object
+    },
+    isSmall:{
+      type:Boolean,
+      default: true
+    }
+  },
+  methods: {
+    //当前条数发生改变
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.page.currentPage = 1;
+      this.change()
+    },
+    //当前页发生改变
+    handleCurrentChange(val) {
+      this.page.currentPage = val;
+      this.change()
+    },
+    //发生改变
+    change() {
+      this.$emit("change");
+    }
+  }
+};
+</script>
+<style>
+.el-pagination button, .el-pagination span:not([class*=suffix]) {
+    vertical-align: middle;
+}
+.block{
+  /* margin-top: 5px; */
+}
+</style>

+ 203 - 0
src/components/dialogs/changeRea.vue

@@ -0,0 +1,203 @@
+<!--
+    changeRea 厂商
+-->
+<template>
+  <el-dialog title="关联资产" :visible.sync="dialog.changeRea" width="800px">
+    <div>
+      <div id="changeRea">
+        <div class="title-search" style="margin-bottom: 10px;">
+          <floor-cascader @change="changeFloor"></floor-cascader>
+          <el-input placeholder="输入本地名称或本地编码查询" v-model="search" size="small" style="width:250px;marginLeft:30px;"
+                    clearable></el-input>
+          <el-button @click="getPropertyData" size="small">查找</el-button>
+        </div>
+        <!-- <div>
+          <floor-cascader @change="changeFloor"></floor-cascader>
+        </div> -->
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table :data="tableData" style="width: 100%" height="300px">
+            <el-table-column label="资产名称" show-overflow-tooltip>
+              <template slot-scope="scope">
+                <el-radio :label="scope.row.id" :ref="scope.row.id" :value="scope.row.localName || scope.row.name">
+                  {{ scope.row.localName }}
+                </el-radio>
+              </template>
+            </el-table-column>
+            <el-table-column label="本地编码">
+              <template slot-scope="scope">{{ scope.row.localId }}</template>
+            </el-table-column>
+            <el-table-column prop="name" label="所在楼层">
+              <template slot-scope="scope">
+                {{
+                  scope.row.building ? scope.row.building.localName ? scope.row.building.localName : '' : ''
+                }}-{{ scope.row.floor ? scope.row.floor.localName ? scope.row.floor.localName : '' : '' }}
+              </template>
+            </el-table-column>
+            <el-table-column label="设备族">
+              <template slot-scope="scope">
+                {{ scope.row.equipFamilyList[0].familyName }}
+              </template>
+            </el-table-column>
+            <el-table-column label="安装位置">
+              <template slot-scope="scope">
+                {{ scope.row.infos ? scope.row.infos.installLocation ? scope.row.infos.installLocation : "--" : "--" }}
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-radio-group>
+        <my-pagination :page="page" @change="changed" style="margin-top:10px;"></my-pagination>
+        <div class="footer">
+          <el-button type="primary" @click="clickTrue" style="display:block;margin: 10px auto 0;">确 定</el-button>
+        </div>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/ledger/components/lib/myPagination";
+// import { queryProperty } from "@/api/scan/request"
+import ScanController from "@/controller/ScanController";
+import floorCascader from "@/components/ledger/components/lib/floorCascader";
+import { mapGetters, mapActions } from "vuex"
+
+export default {
+  components: {
+    myPagination,
+    floorCascader
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          changeRea: true
+        };
+      }
+    },
+    category: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      radio: "",
+      tableData: [],
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      },
+      mess: {},
+      codeListCode: [],
+    };
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"])
+  },
+  mounted() {
+  },
+  methods: {
+    //确认选择
+    clickTrue() {
+      if (this.radio) {
+        this.$emit('changeProperty', { propertyId: this.radio, linkEquipLocalName: this.$refs[this.radio].value });
+        this.dialog.changeRea = false;
+      } else {
+        this.$message("请先选择资产")
+      }
+    },
+    //所在建筑楼层修改
+    changeFloor(val) {
+      this.mess = {
+        buildId: val[0] || "",
+        floorId: val[1] || ""
+      }
+      this.getPropertyData()
+    },
+    //分页修改
+    changed() {
+      this.getPropertyData()
+    },
+    //弹窗显示时
+    changePage() {
+      this.page = {
+        size: 50,
+        sizes: [10, 30, 50, 100],
+        total: 0,
+        currentPage: 1
+      }
+      this.getPropertyData()
+    },
+    //查询表数据
+    getPropertyData() {
+      let param = {
+        cascade: [
+          {
+            name: "equipFamilyList",
+            projection: ["family", "familyName"]
+          },
+          {
+            name: "building",
+            projection: ["localName", "name", "id"]
+          },
+          {
+            name: "floor",
+            projection: ["localName", "name", "id"]
+          }
+        ],
+        filters: `equipId isNull;family="${this.category.assetType}"`,
+        pageNumber: this.page.currentPage,
+        pageSize: this.page.size
+      }
+      //建筑id
+      if (this.mess.buildId == "noKnow") {
+        param.filters += `;buildingId isNull`
+      } else if (this.mess.buildId && this.mess.buildId != "all") {
+        param.filters += `;buildingId='${this.mess.buildId}'`
+      }
+      //楼层id
+      if (this.mess.floorId == "noKnow") {
+        param.filters += `;floorId isNull`
+      } else if (this.mess.floorId && this.mess.floorId != "all") {
+        param.filters += `;floorId='${this.mess.floorId}'`
+      }
+      //名称和编码
+      if (this.search) {
+        param.filters += `;name contain '${this.search}' || localName contain '${this.search}' || localId contain '${this.search}'`
+      }
+      ScanController.queryProperty(param, res => {
+        this.tableData = res.content
+        this.page.total = res.total
+      })
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.changeRea) {
+          this.changePage()
+          this.radio = ""
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#changeRea {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 151 - 0
src/components/dialogs/config/infoPoint.vue

@@ -0,0 +1,151 @@
+<template>
+  <el-dialog title="按条件批量配置" :visible.sync="dialog.config" @close="handleClose" width="900px">
+    <el-form ref="dataForm" :model="form" label-width="90px">
+      <el-form-item label="方案:">
+        <el-radio-group v-model="form.schemeId">
+          <el-radio label="schemeZero">全新设定</el-radio>
+          <el-radio label="schemeOne">预置方案</el-radio>
+          <el-radio label="schemeTwo">万达专用方案</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item v-show="form.schemeId == 'schemeZero'" label="优先级:">
+        <el-checkbox-group v-model="form.priorityList">
+          <template v-for="item in priorityList">
+            <el-checkbox :key="item.priority" :label="item.priority" name="priority" v-if="item.name">
+              {{ item.name }}
+            </el-checkbox>
+          </template>
+        </el-checkbox-group>
+      </el-form-item>
+      <el-form-item v-show="form.schemeId == 'schemeZero'" label="一级标签:">
+        <el-checkbox-group v-model="form.firstNameList">
+          <el-checkbox style="width:99px;" v-for="(item, index) in firstNameList" :key="index" :label="item.firstName"
+                       name="firstTag"></el-checkbox>
+        </el-checkbox-group>
+      </el-form-item>
+      <el-form-item v-show="form.schemeId == 'schemeZero'" label="二级标签:">
+        <span style="color:#bbb;font-size:12px;">二级标签暂未提供,如确实需要请联系产品添加。</span>
+      </el-form-item>
+    </el-form>
+    <div slot="footer">
+      <el-button @click="dialog.config = false">取 消</el-button>
+      <el-button type="primary" @click="onSubmit" :loading="loading">确 认</el-button>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import {mapGetters, mapActions} from "vuex"
+import {setInfoPoint, getDataDictionary} from "@/api/dict";
+
+export default {
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          config: false
+        };
+      }
+    }
+  },
+  data() {
+    return {
+      form: {
+        schemeId: 'schemeZero',
+        priorityList: [],
+        firstNameList: []
+      },
+      firstNameList: [],
+      priorityList: [],
+      loading: false
+    };
+  },
+  created() {
+    this.getInfos()
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"])
+  },
+  methods: {
+    getInfos() {
+      let params1 = {
+        distinct: true,
+        filters: "firstName != ''",
+        orders: "firstName desc",
+        pageNumber: 1,
+        pageSize: 1000,
+        projection: ["firstName"]
+      }, params2 = {
+        distinct: true,
+        filters: "priority != '';priority != 'null'",
+        orders: "priority desc",
+        pageNumber: 1,
+        pageSize: 1000,
+        projection: ["priority"]
+      };
+      let promise1 = new Promise((resolve, reject) => {
+        getDataDictionary(params1, res => {
+          resolve(res)
+        })
+      })
+      let promise2 = new Promise((resolve, reject) => {
+        getDataDictionary(params2, res => {
+          resolve(res)
+        })
+      })
+      Promise.all([promise1, promise2]).then(values => {
+        this.firstNameList = values[0].content
+        this.priorityList = values[1].content.map(item => {
+          switch (item.priority) {
+            case "S":
+              item.name = `(${item.priority})关键信息`;
+              break;
+            case "M":
+              item.name = `(${item.priority})次要信息`
+              break
+            case "R":
+              item.name = `(${item.priority})次要信息`;
+              break
+            default:
+              break
+          }
+          return item
+        })
+      })
+    },
+    //确定
+    onSubmit() {
+      let params = {}
+      this.loading = true
+      if (this.form.schemeId == 'schemeZero') {
+        params = this.form
+      } else {
+        params = {
+          schemeId: this.form.schemeId
+        }
+      }
+      setInfoPoint(params, res => {
+        this.form.schemeId = 'schemeZero'
+        this.form.firstNameList = []
+        this.form.priorityList = []
+        this.dialog.config = false
+        this.loading = false
+        this.$emit('configInfo')
+      })
+    },
+    //弹窗关闭回调
+    handleClose() {
+      this.form.schemeId = 'schemeZero'
+      this.form.firstNameList = []
+      this.form.priorityList = []
+      this.loading = false
+    }
+  }
+};
+</script>
+<style lang="scss">
+.el-dialog__body {
+  max-height: 420px;
+  overflow-y: auto;
+}
+</style>

+ 206 - 0
src/components/dialogs/detailsDialog.vue

@@ -0,0 +1,206 @@
+<template>
+  <el-dialog :visible.sync="isShow.details" :width="width">
+    <span slot="title">
+      <span v-show="step == 1">{{title}}</span>
+      <span v-show="step == 1" style="float:right;margin-right:40px;">
+        <el-button class="saga-padding0" @click="step = 3" type="text">编辑信息</el-button>
+        <!-- <el-button class="saga-padding0" @click="addMyEquip" type="text">添加设备</el-button> -->
+        <el-dropdown @command="addMyEquip" trigger="click">
+          <span class="el-dropdown-link" style="color: #409EFF">添加设备</span>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item command="EquipinSpace">空间内的设备</el-dropdown-item>
+            <el-dropdown-item command="EquipforSpace">服务于空间的设备</el-dropdown-item>
+            <el-dropdown-item command="EquipXSpace">其他关系的设备</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+        <el-button class="saga-padding0" @click="delSpace" type="text">删除该业务空间</el-button>
+      </span>
+      <span v-show="step == 2 || step == 3">
+        <el-button type="text" @click="goBack" icon="el-icon-arrow-left"></el-button>
+      </span>
+    </span>
+    <div id="detailsDialog" v-show="step == 1">
+      <p class="influence-p">{{list.name}}</p>
+      <el-tabs type="border-card">
+        <el-tab-pane label="空间详情">
+          <div class="saga-details">
+            <iframe height="400px" v-if="isShow.details" width="100%" :src="iframeSrc"></iframe>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane label="与空间相关联的设备">
+          <div>
+            <equip-table ref="myEquip"></equip-table>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+    <div v-show="step == 2">
+      <add-equip :activeTabType="activeTabType" ref="addEquip"></add-equip>
+    </div>
+    <div id="detailsDialog" v-if="step == 3">
+      <iframe v-if="step == 3" height="400px" width="100%" :src="iframeSrc2"></iframe>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import Vue from "vue"
+import {
+  Dropdown,
+  DropdownMenu,
+  DropdownItem} from "element-ui"
+Vue.use(Dropdown)
+Vue.use(DropdownMenu)
+Vue.use(DropdownItem)
+
+import { delManySpace } from "@/api/scan/request";
+import { mapGetters, mapActions } from "vuex";
+import equipTable from "@/components/table/equipTable";
+import addEquip from "@/components/table/addEquip";
+
+export default {
+  components: {
+    equipTable,
+    addEquip
+  },
+  props: {
+    width: {
+      type: String,
+      default: "70%"
+    },
+    title: {
+      type: String,
+      default: "头部信息"
+    },
+    isShow: {
+      type: Object
+    },
+    param: {
+      type: Object
+    },
+    activeTabType: {
+      type: Object,
+      default: function () {
+        return {
+          "code": "GeneralZone",
+          "name": "默认分区",
+          "rel_type": "99"
+        }
+      }
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      step: 1,
+      data: null,
+      proj: null,
+      activeName: "1",
+      list: {},
+      iframeSrc: "",
+      iframeSrc2: "",
+      buildMess: ""
+    };
+  },
+  created() { },
+  methods: {
+    handleClick() { },
+    getData(list, buildMess) {
+      this.step = 1;
+      this.list = list;
+      this.buildMess = buildMess;
+      this.$nextTick(() => {
+        this.$refs.myEquip.getData(list, this.activeTabType);
+      });
+      let perjectId = this.projectId,
+        secret = this.secret;
+      this.iframeSrc =
+        // process.env.BASE_URL +
+        window.__systemConf.BASE_URL +
+        ":8889/#/details?perjectId=" +
+        perjectId +
+        "&secret=" +
+        secret +
+        "&FmId=" +
+        list.id +
+        "&type=0&code=" + this.activeTabType.code;
+      this.iframeSrc2 =
+        // process.env.BASE_URL +
+        window.__systemConf.BASE_URL +
+        ":8889/#/changeMess?perjectId=" +
+        perjectId +
+        "&secret=" +
+        secret +
+        "&id=" +
+        list.id +
+        "&type=" + this.activeTabType.code;
+    },
+    addMyEquip(str) {
+      this.step = 2;
+      this.$nextTick(() => {
+        console.log(this.activeTabType)
+        this.$refs.addEquip.getData(this.list, this.buildMess, str, this.activeTabType);
+      });
+    },
+    goBack() {
+      this.step = 1;
+      this.$refs.myEquip.getData(this.list, this.activeTabType);
+    },
+    delSpace() {
+      this.$confirm("此操作将永久删除该业务空间, 是否继续?", "删除", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          let param = {
+            ProjId: this.projectId,
+            secret: this.secret,
+            data: {
+              criteria: {
+                ids: [this.list.id]
+              }
+            }
+          };
+          delManySpace(param)
+            .then(res => {
+              if (res.data.Result == "success") {
+                this.$message({
+                  type: "success",
+                  message: "删除成功!"
+                });
+                this.$emit("del");
+              } else {
+                this.$message.error(res.data.ResultMsg);
+              }
+            })
+            .catch(() => {
+              this.$message.error("请求发生错误");
+            });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除"
+          });
+        });
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#detailsDialog {
+  .el-tabs__content {
+    max-height: 400px;
+  }
+  .influence-p {
+    height: 40px;
+    line-height: 40px;
+    font-size: 17px;
+    margin-bottom: 10px;
+  }
+}
+</style>

+ 147 - 0
src/components/dialogs/facilityDialog.vue

@@ -0,0 +1,147 @@
+<template>
+  <el-dialog :visible.sync="isShow.facility" :width="width">
+    <span slot="title">
+      <span v-show="step == 1">业务空间详情</span>
+      <!-- <span v-show="step == 1" @click="addMyEquip" style="float: right; margin-right: 40px;">
+        <el-button class="saga-padding0" type="text">添加设备</el-button>
+      </span>-->
+      <span v-show="step == 1" style="float: right; margin-right: 40px;">
+        <el-dropdown @command="addMyEquip" trigger="click">
+          <span class="el-dropdown-link" style="color: #409EFF">添加设备</span>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item command="EquipinSpace">空间内的设备</el-dropdown-item>
+            <el-dropdown-item command="EquipforSpace">服务于空间的设备</el-dropdown-item>
+            <el-dropdown-item command="EquipXSpace">其他关系的设备</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </span>
+      <span v-show="step == 2">
+        <el-button class="saga-padding0" @click="goBack" type="text" icon="el-icon-arrow-left"></el-button>
+      </span>
+    </span>
+    <div id="detailsDialog" v-show="step == 1">
+      <p class="influence-p">{{data.infos.RoomLocalName || data.infos.RoomName || '--'}}</p>
+      <equip-table :activeTabType="activeTabType" ref="myEquip" :param="myDia"></equip-table>
+    </div>
+    <div v-show="step == 2">
+      <add-equip ref="addEquip"></add-equip>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import Vue from "vue"
+import {
+  Dropdown,
+  DropdownMenu,
+  DropdownItem} from "element-ui"
+Vue.use(Dropdown)
+Vue.use(DropdownMenu)
+Vue.use(DropdownItem)
+import equipTable from "@/components/table/equipTable";
+import addEquip from "@/components/table/addEquip";
+import { mapGetters, mapActions } from "vuex";
+
+export default {
+  components: {
+    equipTable,
+    addEquip
+  },
+  props: {
+    width: {
+      type: String,
+      default: "60%"
+    },
+    title: {
+      type: String,
+      default: "头部信息"
+    },
+    isShow: {
+      type: Object
+    },
+    param: {
+      type: Object
+    },
+    activeTabType: {
+      type: Object,
+      default: function () {
+        return {
+          "code": "GeneralZone",
+          "name": "默认分区",
+          "rel_type": "99"
+        }
+      }
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      step: 1,
+      data: { infos: {} },
+      proj: null,
+      activeName: "1",
+      myDia: {
+        id: 'Sp11010800034c251365d66111e8bf0a15b159c8e729',
+        ProjId: this.projectId,
+        secret: this.secret
+      },
+      buildMess: {},
+    };
+  },
+  created() { },
+  methods: {
+    handleClick() { },
+    getData(data, buildMess) {
+      this.data = data
+      this.buildMess = buildMess
+      console.log(this.data)
+      this.step = 1
+      this.$nextTick(() => {
+        this.$refs.myEquip.getData(this.data, this.activeTabType)
+      })
+    },
+    goBack() {
+      this.step = 1
+      this.$refs.myEquip.getData(this.data, this.activeTabType)
+    },
+    delSpace() {
+      this.$confirm('此操作将永久删除该业务空间, 是否继续?', '删除', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$message({
+          type: 'success',
+          message: '删除成功!'
+        });
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消删除'
+        });
+      });
+    },
+    addMyEquip(str) {
+      console.log(this.data, this.buildMess)
+      this.step = 2
+      this.$refs.addEquip.getData(this.data, this.buildMess, str, this.activeTabType)
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#detailsDialog {
+  .el-tabs__content {
+    max-height: 400px;
+  }
+  .influence-p {
+    height: 40px;
+    line-height: 40px;
+    font-size: 17px;
+    margin-bottom: 10px;
+  }
+}
+</style>

+ 144 - 0
src/components/dialogs/influenceDialog.vue

@@ -0,0 +1,144 @@
+<template>
+    <el-dialog
+    :visible.sync="isShow.influence"
+    :center="true"
+    :width="width">
+    <span slot="title">{{title}}</span>
+    <div id="influenceDialog">
+        <p class="influence-p">受元空间变化影响,部分业务空间需重新划分</p>
+        <el-tabs type="border-card">
+          <el-tab-pane v-for="(item,index) in tabsList" v-if="index == 0">
+            <span slot="label">{{item.name}}</span>
+            <p style="line-height:30px;font-size:20px;margin-bottom: 20px;">受影响的业务空间</p>
+            <div v-for="i in mess">
+              <p style="line-height:20px;margin-left:10px;">{{i.localName || '--'}} - {{i.id || '--'}}</p>
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+    </div>
+    <span slot="footer" class="dialog-footer center">
+        <el-button type="primary" @click="confirm">我知道了</el-button>
+    </span>
+    </el-dialog>
+</template>
+<script>
+import { getAllMess, deleteNotice } from "@/api/scan/request";
+import { mapGetters, mapActions } from "vuex";
+export default {
+  props: {
+    width: {
+      type: String,
+      default: "40%"
+    },
+    title: {
+      type: String,
+      default: "提示"
+    },
+    isShow: {
+      type: Object
+    },
+    param: {
+      type: Object
+    },
+    tabsList: {
+      type: Array,
+      default: []
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      data: null,
+      proj: null,
+      activeName: "1",
+      allMess: [], //所有提示
+      mess: [], //实际提示
+      build: {}
+    };
+  },
+  created() {
+    this.getAllMess();
+  },
+  methods: {
+    //我知道了
+    confirm() {
+      let ids = [];
+      if (!!this.allMess[this.build.code]) {
+        this.allMess[this.build.code].map(item => {
+          ids.push(item.RoomID);
+        });
+      }
+      let param = {
+        data: {
+          ids: ids
+        },
+        ProjId: this.projectId,
+        secret: this.secret
+      };
+      deleteNotice(param)
+        .then(res => {
+          if (res.data.Result == "success") {
+            this.isShow.influence = false;
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch(() => {
+          this.$message.error("请求失败");
+        });
+    },
+    getData(build) {
+      this.build = build;
+      this.mess = this.allMess[build.code];
+    },
+    getAllMess() {
+      getAllMess({
+        ProjId: this.projectId,
+        secret: this.secret
+      })
+        .then(res => {
+          if (res.data.Result == "success") {
+            // this.allMess = res.data.Content
+            this.changeMsg(res.data.Content);
+            console.log(this.allMess);
+          } else {
+            this.$message.error(res.data.ResultMsg);
+          }
+        })
+        .catch(() => {
+          this.$message.error("请求错误");
+        });
+    },
+
+    //获取楼层信息
+    changeMsg(arr) {
+      arr.map(item => {
+        if (!!this.allMess[item.location.floor]) {
+          this.allMess[item.location.floor].push(item.infos);
+        } else {
+          this.allMess[item.location.floor] = [];
+          this.allMess[item.location.floor].push(item.infos);
+        }
+      });
+    },
+    handleClick() {}
+  }
+};
+</script>
+
+<style lang="less">
+#influenceDialog {
+  .el-tabs__content {
+    max-height: 200px;
+    overflow-y: auto;
+  }
+  .influence-p {
+    height: 40px;
+    line-height: 40px;
+    font-size: 17px;
+    margin-bottom: 10px;
+  }
+}
+</style>

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

@@ -0,0 +1,567 @@
+<template>
+    <el-dialog :title="'批量维护信息点 - ' + mess.name" width="65%" top="10vh" :visible.sync="batchDialog" class="batchContainer">
+        <el-steps :active="active" simple align-center>
+            <el-step @click.native="active = 0" title="填写需维护的信息点" />
+            <el-step @click.native="active = 1" title="选择批量维护的对象实例" />
+        </el-steps>
+        <hr />
+        <div v-show="active === 0" style="height: 555px; overflow: auto">
+            <section>
+                <p class="text-message">维护多选枚举类型信息点</p>
+                <span class="small">请选择需维护的信息点</span>
+                <el-form ref="ruleForm" :model="formData" :inline="true" :label-position="'left'">
+                    <div
+                        v-for="item in tableHeader"
+                        v-show="
+                            item.dataType === 'MENUM' || (item.dataType == 'ENUM' && item.multiple) || (item.dataType == 'BOOLEAN' && item.multiple)
+                        "
+                        :key="item.code"
+                        style="width: 50%; display: inline-block"
+                    >
+                        <el-form-item
+                            :label="item.name"
+                            :prop="item.code"
+                            v-if="
+                                item.dataType === 'MENUM' ||
+                                (item.dataType == 'ENUM' && item.multiple) ||
+                                (item.dataType == 'BOOLEAN' && item.multiple)
+                            "
+                            :class="{
+                                FloorTypeSelect:
+                                    item.dataType == 'MENUM' ||
+                                    (item.dataType == 'ENUM' && item.multiple) ||
+                                    (item.dataType == 'BOOLEAN' && item.multiple),
+                            }"
+                        >
+                            <el-select v-model="formData[item.path]" collapse-tags multiple placeholder="请选择">
+                                <el-option
+                                    v-for="opt in formatDataSource(item.dataSource)"
+                                    :key="`${item.code}-${opt.Code}`"
+                                    :label="opt.Name"
+                                    :value="opt.Code"
+                                >
+                                </el-option>
+                            </el-select>
+                        </el-form-item>
+                    </div>
+                </el-form>
+            </section>
+            <!-- 维护有多个值的信息 -->
+            <section>
+                <p class="text-message">维护有多个值的信息点</p>
+                <span class="small">选择值的更新方式</span>
+                <el-radio-group v-model="radio">
+                    <el-radio :label="1">以增量方式维护</el-radio>
+                    <el-radio :label="2">以覆盖方式维护</el-radio>
+                </el-radio-group>
+                <div style="margin: 15px"></div>
+                <div class="checkbox">
+                    <p v-for="item in newEnclosure" :key="item.code">
+                        <el-checkbox v-model="form[item.path]"> </el-checkbox>
+                        <span style="cursor: pointer">{{ item.name }}</span>
+                        <el-button @click="multiple(item.path)" type="text">请选择</el-button>
+                        <span class="text-color" v-for="i in item.value" :key="i.key">{{ i.name | filterImgName }}</span>
+                    </p>
+                </div>
+            </section>
+        </div>
+        <div v-show="active === 1" class="all-message">
+            <el-row class="filters">
+                <el-col :span="7" style="width: 268px">
+                    <el-input
+                        placeholder="输入设备名称、设备本地编码、数字化交付编码进行查询"
+                        v-model="keycode"
+                        @clear="inputMsg"
+                        clearable
+                        @keyup.enter.native="inputMsg"
+                    >
+                        <i slot="suffix" class="el-input__icon el-icon-search" @click="inputMsg"></i>
+                    </el-input>
+                </el-col>
+                <el-col :span="8.5" style="padding: 0 0">
+                    <floor-cascader ref="buildFloor" @change="changeFloor" style="margin-left: 15px"></floor-cascader>
+                </el-col>
+            </el-row>
+            <el-table
+                ref="multipleTable"
+                :data="tableData"
+                height="460"
+                tooltip-effect="dark"
+                style="width: 100%; margin-bottom: 10px"
+                @selection-change="handleSelectionChange"
+            >
+                <el-table-column type="selection" width="55" />
+                <el-table-column label="设备本地名称">
+                    <template slot-scope="scope">{{ scope.row.localName }}</template>
+                </el-table-column>
+                <el-table-column prop="localId" label="设备本地编码" />
+                <el-table-column :label="`数字化交付编码`" show-overflow-tooltip>
+                    <template slot-scope="scope">
+                        <div>{{ scope.row.infos ? (scope.row.infos.digitalDeliveryID ? scope.row.infos.digitalDeliveryID : "") : "" }}</div>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="build" label="所属建筑楼层" show-overflow-tooltip />
+            </el-table>
+            <my-pagination @change="getAllData" :page="page"></my-pagination>
+        </div>
+        <div slot="footer" class="dialog-footer">
+            <el-button v-show="active === 0" class="next-step" @click="next">下一步 </el-button>
+            <el-button v-show="active === 1" @click="active = 0" style="margin-right: 10px">上 一 步 </el-button>
+            <el-button v-show="active === 1" type="primary" :loading="loading" @click="maintenanceSelect">维护已选 </el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import myPagination from "@/components/ledger/components/lib/myPagination";
+import floorCascader from "@/components/ledger/components/lib/floorCascader";
+// import { queryUpdate, updateEquip } from "@/api/scan/request";
+// import { queryEquip } from "@/api/object/equip";
+import ScanController from "@/controller/ScanController";
+import Equip from "@/controller/equipController";
+import tools from "@/utils/toolUtils";
+import scanTools from "@/utils/scan/tools";
+
+export default {
+    name: "batchDialog",
+    props: ["mess", "tableHeader", "information", "newEnclosure"],
+    components: { myPagination, floorCascader },
+    data() {
+        return {
+            formData: {},
+            form: {},
+            batchDialog: false, //dialog
+            loading: false, //批量维护加载状态
+            active: 0, //进度条
+            radio: 1, //1增加,2覆盖
+            checkedFile: [], //多项
+            multipleSelection: [], //checkbox选择的对象数组
+            allObject: [], //设备数据
+            deviceList: [], //过滤全选数据
+            keycode: "", // 设备检索关键字
+            Buildfloor: ["all"], //建筑楼层
+            page: {
+                size: 100,
+                sizes: [100, 200, 500, 1000],
+                total: 0,
+                currentPage: 1,
+            },
+            videoModel: {
+                archive: false,
+                checkReport: false,
+                drawing: false,
+                installDrawing: false,
+                insuranceFile: false,
+                installPic: false,
+                nameplate: false,
+                pic: false,
+            },
+        };
+    },
+    watch: {
+        information() {
+            return this.information;
+        },
+        newEnclosure: {
+            immediate: true,
+            handler(val) {
+                this.newEnclosure = val;
+            },
+        },
+        batchDialog: {
+            immediate: true,
+            handler(val) {
+                if (val) {
+                    this.active = 0;
+                    this.page.pageSize = 1;
+                    this.keycode = "";
+                    this.Buildfloor = ["all"];
+                    this.$nextTick(() => {
+                        this.$refs.buildFloor && this.$refs.buildFloor.setValue(["all"]);
+                    });
+                    this.getEquipData();
+                }
+            },
+        },
+    },
+    created() {
+        this.$forceUpdate();
+    },
+    computed: {
+        tableData() {
+            this.allObject.map((item) => {
+                let build = "";
+                if (item.building && item.floor) {
+                    build = item.building.localName + " - " + item.floor.localName;
+                } else if (item.building) {
+                    build = item.building.localName;
+                } else if (item.floor) {
+                    build = item.floor.localName;
+                } else {
+                    build = "-";
+                }
+                item.build = build;
+                return item;
+            });
+            return this.allObject;
+        },
+    },
+    filters: {
+        filterImgName(value) {
+            if (value && value.length > 16) {
+                return value.substring(0, 12) + "...";
+            } else {
+                return value;
+            }
+        },
+        filterImgNames(value) {
+            if (value && value.length > 16) {
+                return value.substring(0, 16) + "...";
+            } else {
+                return value;
+            }
+        },
+    },
+    methods: {
+        /**
+         * 格式化下拉数据
+         */
+        formatDataSource(dataSource) {
+            return dataSource ? scanTools.formatDataSource(dataSource) : [];
+        },
+        next() {
+            //下一步按钮
+            let flag = false; // formData的值是否维护
+            Object.keys(this.formData).forEach((key) => {
+                if (this.formData[key].length) {
+                    flag = true;
+                }
+            });
+            if (!flag && !Object.keys(this.form).length) {
+                this.$message({
+                    message: "请维护信息后再操作!",
+                    type: "warning",
+                });
+                return false;
+            }
+            this.active++;
+        },
+        /**
+         * 获取设备信息
+         */
+        getEquipData() {
+            if (!!this.mess.deviceId) {
+                //   查询step2
+                let params = {
+                    cascade: [
+                        {
+                            name: "property",
+                        },
+                        {
+                            Name: "building",
+                            Projection: ["localName", "name", "id"],
+                        },
+                        {
+                            Name: "floor",
+                            Projection: ["localName", "name", "id"],
+                        },
+                    ],
+                    filters: `classCode='${this.mess.deviceId}'`,
+                    pageSize: this.page.size,
+                    orders: "createTime desc, id desc",
+                    pageNumber: this.page.currentPage,
+                    projection: ["buildingId", "floorId", "classCode", "localName", "localID", "id", "bimId"],
+                };
+                if (this.Buildfloor[0] == "noKnow") {
+                    params.filters += `;buildingId isNull`;
+                } else if (this.Buildfloor[0] && this.Buildfloor[0] != "all") {
+                    params.filters += `;buildingId='${this.Buildfloor[0]}'`;
+                }
+                if (this.Buildfloor[1] == "noKnow") {
+                    params.filters += `;floorId isNull`;
+                } else if (this.Buildfloor[1] && this.Buildfloor[1] != "all") {
+                    params.filters += `;floorId='${this.Buildfloor[1]}'`;
+                }
+                if (this.keycode != "") {
+                    params.filters += `;localName contain '${this.keycode}' or localId contain '${this.keycode}' or infos.digitalDeliveryID contain '${this.keycode}'`;
+                }
+                Equip.queryEquip(params, (res) => {
+                    this.multipleSelection = [];
+                    this.allObject = res.content;
+                    this.page.total = res.total;
+                });
+            }
+        },
+        /**
+         * 检索关键字
+         */
+        inputMsg() {
+            this.page.pageNumber = 1;
+            this.getEquipData();
+        },
+        /**
+         * 切换建筑楼层
+         */
+        changeFloor(value) {
+            this.Buildfloor = value;
+            this.page.pageNumber = 1;
+            this.getEquipData();
+        },
+        maintenanceSelect() {
+            //维护已选
+            if (!this.multipleSelection.length) {
+                this.$message({
+                    message: "还没有选择实例哦",
+                    type: "warning",
+                });
+                return false;
+            }
+
+            let arr = [];
+            this.multipleSelection.forEach((item) => {
+                let id = item.id;
+                arr.push({ id });
+            });
+
+            // let single = {};
+            let param = {};
+            this.newEnclosure.forEach(({ path, value }) => (param[path] = value));
+            let newValuable = [];
+            this.newEnclosure.filter((i) => this.form[i.path] && i.value).forEach(({ code, value }) => (newValuable[code] = value));
+
+            console.log(newValuable, "多选信息");
+
+            if (this.radio === 1) {
+                //组装数据,根据是覆盖该是增量,1是增量
+                //    1:单选数据
+                let formData = tools.formatData(this.formData);
+                let arr1 = this.deepCopy(arr).map((item) => ({
+                    ...item,
+                    ...formData,
+                }));
+                // 附件数据
+                let arr2 = this.deepCopy(arr).map((item) => ({
+                    ...item,
+                    ...newValuable,
+                }));
+                this.upDataDevice(1, arr1, arr2);
+            } else if (this.radio === 2) {
+                let param = {};
+                this.newEnclosure.forEach(({ path, value }) => (param[path] = value));
+                let pa = Object.assign(param, this.formData);
+                pa = tools.formatData(pa);
+                let arr3 = this.deepCopy(arr).map((item) => ({
+                    ...item,
+                    ...pa,
+                }));
+                this.upDataDevice(2, arr3);
+            } else {
+                this.closeDialog();
+            }
+        },
+        upDataDevice(type, data1, data2) {
+            this.loading = true;
+            let param = { content: data1 };
+            let param1 = { content: data2 };
+            if (type === 1) {
+                //增量
+                let filterParam = this.filterCheck(param, "sole");
+                let filterParam1 = this.filterCheck(param1, "multiple");
+                if (filterParam) {
+                    ScanController.updateEquip(param, (res) => {
+                        if (res.result === "success") {
+                            this.loading = false;
+                            this.$emit("upDataDevice");
+                        } else {
+                            this.$message.error(res.message);
+                        }
+                        this.closeDialog();
+                    });
+                }
+                if (filterParam1) {
+                    param1.content.map((i) => {
+                        i.equipId = i.id;
+                        delete i.id;
+                        return i;
+                    });
+                    setTimeout(() => {
+                        ScanController.queryUpdate(param1, (res) => {
+                            if (res.result === "success") {
+                                this.loading = false;
+                                this.$emit("upDataDevice");
+                            } else {
+                                this.$message.error(res.message);
+                            }
+                            this.closeDialog();
+                        });
+                    });
+                }
+                if (!filterParam && !filterParam1) {
+                    this.loading = false;
+                    this.closeDialog();
+                }
+            } else if (type === 2) {
+                //覆盖
+                let filterParams = this.filterCheck(param, "sole");
+                console.log("filterParams", filterParams);
+                console.log(param);
+                if (filterParams) {
+                    ScanController.updateEquip(param, (res) => {
+                        if (res.result === "success") {
+                            this.loading = false;
+                            this.$emit("upDataDevice");
+                        } else {
+                            this.$message.error(res.message);
+                        }
+                        this.closeDialog();
+                    });
+                } else {
+                    this.loading = false;
+                    this.closeDialog();
+                }
+            }
+        },
+        filterCheck(arr, type) {
+            if (type === "sole") {
+                for (let i of arr.content) {
+                    for (let j in i.infos) {
+                        if (Array.isArray(i.infos[j]) && i.infos[j].length < 1) {
+                            delete i.infos[j];
+                        }
+                    }
+                    return Object.keys(i.infos).length;
+                }
+            } else if (type === "multiple") {
+                let nArr = [];
+                arr.content.forEach((i) => {
+                    let { id, ...value } = i;
+                    nArr.push({ infos: value });
+                });
+                for (let j of nArr) {
+                    return Object.keys(j.infos).length;
+                }
+            }
+        },
+        closeDialog() {
+            //关闭弹窗,返回初始状态
+            this.batchDialog = false;
+            this.clearData();
+        },
+        clearData() {
+            this.active = 0;
+            this.radio = 1; //返回到默认增量
+            // 清空formData数据
+            this.formData = {};
+            //清空附件信息
+            for (let i in this.form) {
+                this.form[i] = false;
+            }
+            this.newEnclosure.map((i) => {
+                this.$set(i, "value", []);
+            });
+        },
+        handleSelectionChange(val) {
+            this.multipleSelection = val;
+        },
+        getAllData() {
+            this.getEquipData();
+        },
+        multiple(val) {
+            this.$emit("multiples", val);
+        },
+
+        deepCopy(obj) {
+            return JSON.parse(JSON.stringify(obj));
+        },
+    },
+};
+</script>
+
+<style scoped lang="less">
+.batchContainer {
+    /deep/ .el-dialog__body {
+        padding-top: 10px;
+    }
+
+    /deep/ .FloorTypeSelect .el-form-item__content {
+        width: 200px;
+    }
+    /deep/ .el-table-column--selection .cell {
+        padding: 0;
+    }
+
+    /deep/ .el-step__description {
+        margin: 2% 0;
+    }
+
+    .text-color {
+        color: #409eff;
+    }
+
+    .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;
+        }
+    }
+
+    .next-step {
+        display: block;
+        float: right;
+    }
+
+    .filters {
+        margin: 10px 0;
+    }
+
+    .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;
+    }
+    .dialog-footer {
+        height: 32px;
+    }
+
+    .all-message {
+        overflow: hidden;
+
+        button {
+            float: right;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
+}
+</style>

+ 142 - 0
src/components/dialogs/list/filesDialog.vue

@@ -0,0 +1,142 @@
+<!--
+    上传文件的弹窗
+-->
+
+<template>
+  <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/components/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;
+          case 'infos.insuranceFile': //保险文件
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.archive': //设备文档
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.checkReport': //安装质检报告
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.maintainManual': //维修保养手册
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.approachingAcceptance': //进场验收单
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.acceptanceReport': //验收报告
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.operationManual': //操作说明书
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.originalCertificate': //原厂证明
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.testReport': //检测报告
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.productCertification': //产品合格证
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.installInstruction': //安装说明书
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.drawing': //设备图纸
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.installDrawing': //安装图纸
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.supplierContract': //供应合同
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.designIDGraph': //安装图纸
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+          case 'infos.fanCharacterCurve': //供应合同
+            this.$emit("changeFile", info, this.firmDataType, file)
+            break
+        }
+      } else {
+        this.$emit("changeFile", file, this.firmDataType)
+      }
+    },
+    deepCopy(obj) {
+      return JSON.parse((JSON.stringify(obj)))
+    }
+  },
+};
+</script>
+<style>
+</style>

+ 193 - 0
src/components/dialogs/list/guaranteeDialog.vue

@@ -0,0 +1,193 @@
+<!--
+    guarantee 保单选择
+-->
+
+<!--
+    guarantee 供应合同选择
+-->
+<template>
+  <el-dialog title="选择保单" :visible.sync="dialog.guarantee" width="600px">
+    <el-tabs type="border-card">
+      <el-tab-pane>
+        <span slot="label">选择保单</span>
+        <div id="firm">
+          <el-radio-group v-model="radio" style="width:100%;">
+            <el-table :data="tableData" style="width: 100%" height="300px">
+              <el-table-column label="保单号">
+                <template slot-scope="scope">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.insuranceNo}}</el-radio>
+                </template>
+              </el-table-column>
+              <el-table-column label="下载">
+                <template slot-scope="scope">
+                  <el-button type="text">下载</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-radio-group>
+          <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" style="margin-top:10px;"></my-pagination>
+        </div> 
+          <div class="footer">
+            <el-button
+              type="primary"
+              @click="getSelect"
+              style="display:block;margin: 10px auto 0;"
+            >确 定</el-button>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane>
+        <span slot="label">新建保单</span>
+        <el-form label-width="80px" :rules="rules" :model="formData" ref="ruleForm">
+          <el-form-item label="保单号:" prop="name">
+            <el-input v-model="formData.name"></el-input>
+          </el-form-item>
+          <el-form-item label="保险文件">
+            <upload-files @change="changeFiles" ref="files" :keysArr="keysArr" :max="max"></upload-files>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
+            <el-button @click="resetForm('ruleForm')">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </el-tab-pane>
+    </el-tabs>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/ledger/lib/myPagination";
+import uploadFiles from '@/components/ledger/lib/uploadFiles'
+import { getListForGuarantee, createGuarantee } from "@/api/scan/request"
+import { mapGetters, mapActions } from "vuex"
+import tools from "@/utils/scan/tools"
+export default {
+  components: {
+    myPagination,
+    uploadFiles
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          guarantee: true
+        };
+      }
+    },
+    id: {
+      type: [Number, String],
+      default: 0
+    }
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      radio: "",
+      formData: {
+        name: ""
+      },
+      rules: {
+        name: { required: true, message: '请输入保单号', trigger: 'blur' },
+      },
+      tableData: [],
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 400,
+        currentPage: 1
+      },
+      keysArr: [],
+      max: 1,
+      allData: []
+    };
+  },
+  created() { },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"])
+  },
+  mounted() { },
+  methods: {
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.createGree()
+        } else {
+          return false;
+        }
+      });
+    },
+    changeFiles(val) {
+      this.keysArr = val
+    },
+    resetForm() {
+      this.$refs.ruleForm.resetFields();
+    },
+    //新建保单
+    createGree() {
+      let param = {
+        data: {
+          venderId: this.id,
+          insuranceNo: this.formData.name,
+          projectId: this.projectId,
+          contractFile: this.keysArr[0]
+        }
+      }
+      let _this = this
+      createGuarantee(param, res => {
+        _this.$emit("change", param.data)
+        _this.dialog.guarantee = false
+      })
+    },
+    getList() {
+      this.radio = ""
+      let _this = this
+      this.page = {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      }
+      if (!!this.id) {
+        let param = {
+          data: {
+            projectId: this.projectId,
+            venderId: this.id
+          }
+        }
+        getListForGuarantee(param, res => {
+          _this.$refs.ruleForm.resetFields()
+          _this.$refs.files.resetFile()
+          _this.allData = res.content || []
+          _this.page.total = _this.allData.length
+          //   //分页
+          _this.pageChange()
+        })
+      }
+    },
+
+    getSelect() {
+      this.$emit("change", this.radio)
+      this.dialog.guarantee = false
+    },
+    pageChange() {
+      this.tableData = tools.pagination(this.page.currentPage, this.page.size, this.allData)
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function (val) {
+        if (this.dialog.guarantee) {
+          this.getList()
+        }
+      }
+    }
+  }
+
+};
+</script>

+ 173 - 0
src/components/dialogs/list/insurerDialog.vue

@@ -0,0 +1,173 @@
+<!--
+    maintenance 选择供应商
+
+-->
+<template>
+  <el-dialog title="选择保险公司" :visible.sync="dialog.insurer" width="1000px">
+    <div>
+      <div id="firm">
+        <div class="title-search query-form" style="padding: 10px;margin-bottom: 10px;">
+          <el-input
+            placeholder="输入厂家名称进行查找"
+            v-model="search"
+            size="small"
+            style="width:300px; margin-right: 10px;"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="filterSearch">查找</el-button>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table class="data-table" border ref="maintenance" :data="tableData" style="width: 100%" height="300px">
+            <el-table-column header-align='center' label="保险公司名称">
+              <template slot-scope="scope">
+                <el-tooltip :content="scope.row.name" placement="top">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.name}}</el-radio>
+                </el-tooltip>
+              </template>
+            </el-table-column>
+            <el-table-column header-align='center' prop="website" label="网址"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].name" label="联系人"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].phone" label="联系电话"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].fax" label="传真"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].email" label="电子邮件"></el-table-column>
+          </el-table>
+        </el-radio-group>
+        <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
+        </div>
+      </div>
+    </div>
+    <div slot="footer">
+          <el-button
+            type="primary"
+            @click="getChange"
+          >确 定</el-button>
+        </div>
+  </el-dialog>
+</template>
+<script>
+    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: {
+    myPagination
+  },
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        insurer: true
+                    };
+                }
+            },
+            firmDataType: {
+                type: String
+            }
+        },
+        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") {
+                        this.allData = tools.deepCopy(res.data.content.insurance)
+                        this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+                        this.page.total = this.allData.length
+                    } else {
+                        this.$message.error("请求失败:" + res.data.resultMsg)
+                    }
+                })
+            },
+
+            //分页改变
+            changePage() {
+                this.pagination(this.page.currentPage, this.page.size, this.allData)
+            },
+
+            //发生修改
+            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: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.insurer) {
+          this.getData()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#firm {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 172 - 0
src/components/dialogs/list/maintainerDialog.vue

@@ -0,0 +1,172 @@
+<!--
+    maintenance 选择维修商
+
+-->
+<template>
+  <el-dialog title="选择维修商" :visible.sync="dialog.maintainer" width="1000px">
+    <div>
+      <div id="firm">
+        <div class="title-search query-form" style="padding: 10px; margin-bottom: 10px;">
+          <el-input
+            placeholder="输入厂家名称进行查找"
+            v-model="search"
+            size="small"
+            style="width:300px; margin-right: 10px;"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="filterSearch">查找</el-button>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table class="data-table" border ref="maintenance" :data="tableData" style="width: 100%" height="300px">
+            <el-table-column header-align='center' label="维修商名称">
+              <template slot-scope="scope">
+                <el-tooltip :content="scope.row.name" placement="top">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.name}}</el-radio>
+                </el-tooltip>
+              </template>
+            </el-table-column>
+            <el-table-column header-align='center' prop="website" label="网址"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].name" label="联系人"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].phone" label="联系电话"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].fax" label="传真"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].email" label="电子邮件"></el-table-column>
+          </el-table>
+        </el-radio-group>
+        <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
+        </div>
+      </div>
+    </div>
+    <div slot="footer">
+          <el-button
+            type="primary"
+            @click="getChange"
+          >确 定</el-button>
+        </div>
+  </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"
+
+    export default {
+        components: {
+    myPagination
+  },
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        maintainer: true
+                    };
+                }
+            },
+            firmDataType: {
+                type: String
+            }
+        },
+        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") {
+                        this.allData = tools.deepCopy(res.data.content.maintenance)
+                        this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+                        this.page.total = this.allData.length
+                    } else {
+                        this.$message.error("请求失败:" + res.data.resultMsg)
+                    }
+                })
+            },
+
+            //分页改变
+            changePage() {
+                this.pagination(this.page.currentPage, this.page.size, this.allData)
+            },
+
+            //发生修改
+            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: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.maintainer) {
+          this.getData()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#firm {
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 80 - 0
src/components/dialogs/list/menum.vue

@@ -0,0 +1,80 @@
+<!-- 多选枚举类型数据维护 -->
+<template>
+    <el-dialog :title="`编辑 <${infoName}>`" :visible.sync="dialog.menum" width="670px">
+        <el-row style="margin-top: 20px">
+            <el-select v-model="value" multiple placeholder="请选择" style="width: 100%">
+                <el-option v-for="item in options" :key="item.Code" :label="item.Name" :value="item.Code"> </el-option>
+            </el-select>
+        </el-row>
+        <span slot="footer" class="dialog-footer">
+            <el-button @click="dialog.menum = false">取 消</el-button>
+            <el-button type="primary" @click="handleClickUpdate">确 认</el-button>
+        </span>
+    </el-dialog>
+</template>
+<script>
+import tools from "@/utils/scan/tools";
+
+export default {
+    props: {
+        dialog: {
+            type: Object,
+            default: function () {
+                return {
+                    menum: true,
+                };
+            },
+        },
+        updateInput: {
+            type: [Array, String],
+            default: [],
+        },
+        updateInfoData: {
+            type: [Object],
+            default: {},
+        },
+    },
+    data() {
+        return {
+            value: [],
+        };
+    },
+    computed: {
+        options() {
+            return this.updateInfoData.dataSource ? tools.formatDataSource(this.updateInfoData.dataSource) : [];
+        },
+        // 信息点名称
+        infoName() {
+            return this.updateInfoData.name || "";
+        },
+    },
+    methods: {
+        formatValue(value) {
+            if (value instanceof Array) {
+                return JSON.parse(JSON.stringify(value));
+            } else if (typeof value === "string" && value !== "") {
+                return value.split(",");
+            } else {
+                return [];
+            }
+        },
+        // 确认修改
+        handleClickUpdate() {
+            this.$emit("change", this.value);
+        },
+    },
+    watch: {
+        dialog: {
+            deep: true,
+            handler() {
+                if (this.dialog.menum) {
+                    this.value = this.formatValue(this.updateInput);
+                }
+            },
+        },
+    },
+};
+</script>
+
+<style lang="less">
+</style>

+ 92 - 0
src/components/dialogs/list/paramDetails.vue

@@ -0,0 +1,92 @@
+<template>
+  <el-dialog width="400px" title="型号参数" :visible.sync="isLoad.paramShow" append-to-body>
+    <h3 class="lag-h3">当前型号: {{data.brand || "--"}} - {{data.name || "--"}}</h3>
+    <div style="max-height: 400px;overflow-y:auto;">
+      <p
+        class="saga-poent"
+        v-for="item in labelArr"
+        v-if="!!data.infos && data.infos[item.infoPointCode]"
+      >{{item.infoPointName}}:{{data.infos ? data.infos[item.infoPointCode] || "--" : "--"}}</p>
+    </div>
+  </el-dialog>
+</template>
+<script>
+
+import { getSpaceHeader } from "@/api/scan/request"
+import { mapGetters, mapActions } from "vuex";
+
+export default {
+  props: {
+    isLoad: {
+      type: Object,
+      default: function () {
+        return {
+          paramShow: false
+        }
+      }
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {
+        }
+      }
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"]),
+  },
+  data() {
+    return {
+      labelArr: []
+    }
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    getData() {
+      let param = {
+        ProjId: this.projectId,
+        code: this.data.eqFamily
+      }
+      getSpaceHeader(param).then(res => {
+        if (res.data.Result == "success") {
+          this.labelArr = res.data.Content.map(item => {
+            if (item.firstTag == "台账信息") {
+              return item
+            } else {
+              return undefined
+            }
+          }).filter(d => d)
+        } else {
+          this.$message.error("请求失败:" + res.data.ResultMsg)
+        }
+      }).catch(_ => {
+        this.$message.error("请求失败")
+      })
+    }
+  },
+  watch: {
+    isLoad: {
+      deep: true,
+      handler: function () {
+        if (this.isLoad.paramShow) {
+          this.getData()
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.lag-h3 {
+  height: 35px;
+  line-height: 35px;
+  font-size: 20px;
+  font-weight: 500;
+  margin-bottom: 8px;
+}
+.saga-poent {
+  line-height: 28px;
+}
+</style>

+ 170 - 0
src/components/dialogs/list/picDialog.vue

@@ -0,0 +1,170 @@
+<!--
+    上传图片的弹窗
+-->
+
+<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"
+
+        />
+      </div>
+      <!--          max="6"-->
+      <div>
+        <h3>视频</h3>
+        <upload-imgs
+            :accept="'video/*'"
+            type="video"
+            :keysArr="videoArr"
+            @change="videoItem"
+            :videoPicArr="videoPicArr"
+            :readOnly="read"
+        />
+        <!--              max="2"-->
+      </div>
+    </div>
+  </el-dialog>
+</template>
+<script>
+  import uploadImgs from "@/components/ledger/components/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()
+      },
+
+      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)
+        if (this.firmDataType === 'dialog') {
+          // this.information.pic.Pic = this.changeKeys
+          // this.$emit("change", this.information, this.firmDataType)
+          // this.$emit("change", this.information, this.firmDataType, this.changeKeys)
+          this.$emit("change", this.infoType, this.firmDataType, this.changeKeys)
+        } 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()
+          }
+        }
+      }
+    }
+  };
+</script>
+<style>
+</style>

+ 174 - 0
src/components/dialogs/list/supplierDialog.vue

@@ -0,0 +1,174 @@
+<!--
+    supplier 选择供应商
+
+-->
+<template>
+  <el-dialog title="选择供应商" :visible.sync="dialog.supplier" width="1000px">
+    <div>
+      <div id="firm">
+        <div class="title-search query-form" style="padding: 10px;margin-bottom: 10px;">
+          <el-input
+            placeholder="输入厂家名称进行查找"
+            v-model="search"
+            size="small"
+            style="width:300px; margin-right: 10px;"
+            clearable
+          ></el-input>
+          <el-button size="small" @click="filterSearch">查找</el-button>
+        </div>
+        <el-radio-group v-model="radio" style="width:100%;">
+          <el-table class="data-table" border ref="supplier" :data="tableData" style="width: 100%" height="300px">
+            <el-table-column header-align='center' label="供应商名称" >
+              <template slot-scope="scope">
+                <el-tooltip :content="scope.row.name" placement="top">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row.name}}</el-radio>
+                </el-tooltip>
+              </template>
+            </el-table-column>
+            <el-table-column header-align='center' prop="website" label="网址"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].name" label="联系人"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].phone" label="联系电话"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].fax" label="传真"></el-table-column>
+            <el-table-column header-align='center' prop="contacts[0].email" label="电子邮件"></el-table-column>
+          </el-table>
+        </el-radio-group>
+        <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="changePage" style="margin-top:10px;"></my-pagination>
+        </div>
+      </div>
+    </div>
+    <div slot="footer" class="footer">
+          <el-button
+            type="primary"
+            @click="getChange"
+          >确 定</el-button>
+        </div>
+  </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"
+
+    export default {
+        components: {
+    myPagination
+  },
+        props: {
+            dialog: {
+                type: Object,
+                default: function () {
+                    return {
+                        supplier: true
+                    };
+                }
+            },
+            firmDataType: {
+                type: String
+            }
+        },
+        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") {
+                        this.allData = tools.deepCopy(res.data.content.supplier)
+                        this.tableData = this.pagination(this.page.currentPage, this.page.size, this.allData)
+                        this.page.total = this.allData.length
+                    } else {
+                        this.$message.error("请求失败:" + res.data.resultMsg)
+                    }
+                })
+            },
+
+            //分页改变
+            changePage() {
+                this.pagination(this.page.currentPage, this.page.size, this.allData)
+            },
+
+            //发生修改
+            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: {
+    dialog: {
+      deep: true,
+      handler: function () {
+        if (this.dialog.supplier) {
+          this.getData()
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less">
+#firm {
+    height: 455px;
+    overflow-y: auto;
+  .el-table thead {
+    tr {
+      th {
+        background-color: #f5f7fa;
+      }
+    }
+  }
+}
+</style>

+ 163 - 0
src/components/dialogs/list/supplyDialog.vue

@@ -0,0 +1,163 @@
+<!--
+    supply 供应合同选择
+-->
+<template>
+  <el-dialog title="选择供应合同" :visible.sync="dialog.supply" width="600px">
+    <el-tabs type="border-card">
+      <el-tab-pane>
+        <span slot="label">选择供应合同</span>
+        <div id="firm">
+          <el-radio-group v-model="radio" style="width:100%;">
+            <el-table :data="tableData" style="width: 100%" height="300px">
+              <el-table-column label="合同编号">
+                <template slot-scope="scope">
+                  <el-radio v-model="radio" :label="scope.row">{{scope.row}}</el-radio>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-radio-group>
+          <div class="right" style="background: #fff;">
+            <p style="height:40px;line-height:40px;text-align:center;color:#9E9E9E; float: left;">
+                找不到想要的型号? 赶快去
+                <i style="color:#46B0FF;cursor: pointer;">厂家库</i>维护吧
+            </p>
+            <my-pagination :page="page" @change="pageChange" style="margin-top:10px;"></my-pagination>
+        </div>
+          <div class="footer">
+            <el-button
+              type="primary"
+              style="display:block;margin: 10px auto 0;"
+              @click="setData"
+            >确 定</el-button>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane>
+        <span slot="label">新建供应合同</span>
+        <el-form label-width="80px" :rules="rules" :model="formData" ref="ruleForm">
+          <el-form-item label="供应合同" prop="name">
+            <el-input v-model="formData.name"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
+            <el-button @click="resetForm('ruleForm')">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </el-tab-pane>
+    </el-tabs>
+  </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/ledger/lib/myPagination";
+import { getListForSupplier } from "@/api/scan/request"
+import tools from "@/utils/scan/tools"
+import { mapGetters, mapActions } from "vuex";
+
+export default {
+  components: {
+    myPagination
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          supply: true
+        };
+      }
+    },
+    id: {
+      type: [Number, String],
+      default: 0
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId", "secret", "userId"])
+  },
+  data() {
+    return {
+      search: "", //搜索文案
+      radio: "",
+      formData: {
+        name: ""
+      },
+      rules: {
+        name: { required: true, message: '请输入保单号', trigger: 'blur' },
+      },
+      tableData: [],
+      page: {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      },
+      allData: []
+    };
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    submitForm(formName) {
+      let _this = this
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          _this.$emit("change", this.formData.name)
+          this.dialog.supply = false
+        } else {
+          return false;
+        }
+      });
+    },
+    resetForm() {
+      this.$refs.ruleForm.resetFields();
+    },
+
+    setData() {
+      this.$emit("change", this.radio)
+      this.dialog.supply = false
+    },
+
+    //获取列表
+    getList() {
+      this.radio = ""
+      let _this = this
+      this.page = {
+        size: 50,
+        sizes: [10, 30, 50, 100, 150, 200],
+        total: 0,
+        currentPage: 1
+      }
+      if (!!this.id) {
+        let param = {
+          data: {
+            projectId: this.projectId,
+            venderId: this.id
+          },
+          ProjId: this.projectId,
+          secret: this.secret,
+        }
+        getListForSupplier(param, res => {
+          _this.$refs.ruleForm.resetFields()
+          _this.allData = res.contractId || []
+          _this.page.total = _this.allData.length
+          //分页
+          _this.pageChange()
+        })
+      }
+    },
+    pageChange() {
+      this.tableData = tools.pagination(this.page.currentPage, this.page.size, this.allData)
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function (val) {
+        if (this.dialog.supply) {
+          this.getList()
+        }
+      }
+    }
+  }
+};
+</script>

+ 284 - 0
src/components/dialogs/list/systemType.vue

@@ -0,0 +1,284 @@
+<!--
+    systemType 设备所属类型
+-->
+<template>
+    <el-dialog title="所属系统实例" :visible.sync="dialog.systemType" width="900px">
+        <div>
+            <div id="systemType">
+                <div class="title-search query-form" style="padding: 10px; margin-bottom: 10px" v-if="type != 'read'">
+                    <el-row>
+                        <el-col :span="10">
+                            <span>系统所属建筑</span>
+                            <el-select v-model="buildId" placeholder="请选择" @change="getTableData">
+                                <el-option v-for="item in options" :key="item.id" :label="item.localName" :value="item.id"> </el-option>
+                            </el-select>
+                        </el-col>
+                        <el-col :span="14">
+                            <el-input
+                                placeholder="输入名称或编码进行查询"
+                                v-model="search"
+                                size="small"
+                                style="width: 300px; margin-right: 10px"
+                                clearable
+                            ></el-input>
+                            <el-button size="small" @click="getTableData">查找</el-button>
+                        </el-col>
+                    </el-row>
+                </div>
+                <el-table
+                    class="data-table"
+                    border
+                    row-key="id"
+                    :data="tableData"
+                    @selection-change="handleSelectionChange"
+                    style="width: 100%"
+                    ref="multipleTable"
+                >
+                    <el-table-column v-if="type != 'read'" type="selection" :reserve-selection="true" :disabled="true" width="55"></el-table-column>
+                    <el-table-column label="系统名称" header-align="center">
+                        <template slot-scope="scope">{{ scope.row.localName || scope.row.name }}</template>
+                    </el-table-column>
+                    <el-table-column label="本地编码" header-align="center">
+                        <template slot-scope="scope">{{ scope.row.localId || "--" }}</template>
+                    </el-table-column>
+                    <el-table-column label="系统类型" prop="categoryName" header-align="center"></el-table-column>
+                    <el-table-column label="详情" header-align="center" width="100" align="center">
+                        <template slot-scope="scope">
+                            <el-button @click="lookDeatils(scope.row)" type="text">详情</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </div>
+        </div>
+        <span slot="footer" class="dialog-footer" v-if="type != 'read'">
+            <el-button type="primary" @click="getChange">确 定</el-button>
+        </span>
+        <el-dialog title="系统详情" :visible.sync="iframeShow" v-if="iframeShow" width="500px" append-to-body>
+            <iframe
+                id="google_ads_frame2"
+                name="google_ads_frame2"
+                frameborder="0"
+                :src="iframeSrc"
+                marginwidth="0"
+                marginheight="0"
+                vspace="0"
+                hspace="0"
+                style="width: 100%; height: 500px"
+                allowtransparency="true"
+                scrolling="no"
+                allowfullscreen="true"
+            ></iframe>
+        </el-dialog>
+    </el-dialog>
+</template>
+<script>
+import myPagination from "@/components/ledger/components/lib/myPagination";
+// import { querySysLinkBuild, buildingQuery, equipLinkSys } from "@/api/scan/request"
+import ScanController from "@/controller/ScanController";
+import { mapGetters } from 'vuex'
+
+export default {
+    components: {
+        myPagination
+    },
+    props: {
+        dialog: {
+            type: Object,
+            default: function () {
+                return {
+                    systemType: true
+                };
+            }
+        },
+        graphyId: {
+            type: String,
+            default: ""
+        },
+        device: {},
+        curDevice: {
+            default: ''
+        },//设备id
+        type: {
+            type: String,
+            default: "read"
+        },
+        list: {
+            type: [Array]
+        }
+    },
+    data() {
+        return {
+            search: "", //搜索文案
+            tableData: [],
+            systemList: [],
+            linkSystemData: [],
+            multipleSelection: [],
+            iframeSrc: "",
+            iframeShow: false,
+            buildId: 'all', //查询条件
+            options: [], //系统所属建筑
+        };
+    },
+    computed: {
+        ...mapGetters("layout", ["projectId", "secret", "userId"])
+    },
+    mounted() {
+    },
+    methods: {
+        //获取查询条件-建筑
+        getData() {
+            let param = {
+                orders: "localName asc",
+                pageNumber: 1,
+                pageSize: 1000
+            }
+            ScanController.buildingQuery(param, res => {
+                if (res.result == 'success') {
+                    let data = res.content;
+                    data.unshift({
+                        id: "all",
+                        localName: "全部"
+                    }, {
+                        id: "noKnow",
+                        localName: "未明确建筑的系统"
+                    })
+                    this.options = data
+                } else {
+                    this.$message.error(res.message)
+                }
+            })
+        },
+        handleSelectionChange(val) {
+            this.multipleSelection = val;
+        },
+        //设置默认
+        toggleSelection(rows) {
+            if (this.$refs.multipleTable) {
+                this.$refs.multipleTable.clearSelection();
+            }
+            if (rows.length && this.list.length) {
+                rows.map(row => {
+                    this.list.map(t => {
+                        if (row.id == t.id) {
+                            this.$refs.multipleTable.toggleRowSelection(row)
+                        }
+                    })
+                })
+            }
+        },
+        //确认
+        getChange() {
+            this.createRelatSys()
+            this.$emit("change", this.multipleSelection)
+            this.dialog.systemType = false
+            this.multipleSelection = []
+        },
+        //点击详情
+        lookDeatils(infos) {
+            this.$message("开发中...")
+        },
+        //根据设备类型-查询系统关联专业
+        getTableData() {
+            let param = {
+                data: {
+                    filters: `classCode="${this.device.deviceId.substring(0, 4)}"`,
+                    pageNumber: 1,
+                    pageSize: 1000
+                }
+            }
+            //建筑id
+            if (this.buildId === "noKnow") {
+                param.buildingId = 1;
+            } else if (this.buildId && this.buildId != "all") {
+                param.buildingId = this.buildId;
+            }
+            //输入的查询条件
+            if (this.search) {
+                param.data.filters += `;localName contain "${this.search}" or localId contain "${this.search}"`
+            }
+            ScanController.querySysLinkBuild(param, res => {
+                this.tableData = res.content
+                this.toggleSelection(res.content)
+            })
+        },
+        getSystemTableData() {
+            const sysIdList = this.linkSystemData.map(sys => {
+                return sys.id
+            })
+            if (sysIdList.length) {
+                let param = {
+                    data: {
+                        filters: `id in ${JSON.stringify(sysIdList)}`,
+                        pageNumber: 1,
+                        pageSize: 1000
+                    }
+                }
+                ScanController.querySysLinkBuild(param, res => {
+                    this.tableData = res.content
+                })
+            } else {
+                this.tableData = [];
+            }
+        },
+        //获取关联的系统
+        getLinkSystemData() {
+            this.linkSystemData = this.list ? JSON.parse(JSON.stringify(this.list)) : []
+            if (this.type == 'read') {
+                this.getSystemTableData();
+            }
+        },
+        //添加设备关联系统关系
+        createRelatSys() {
+            if (this.curDevice) {//有即为编辑
+                let param = {
+                    equipId: this.curDevice,
+                    sysIdList: []
+                }
+                this.multipleSelection.map(t => {
+                    param.sysIdList.push(t.id)
+                })
+                ScanController.equipLinkSys(param, res => {
+                    this.multipleSelection = []
+                })
+            }
+        }
+    },
+    watch: {
+        dialog: {
+            deep: true,
+            handler() {
+                if (this.dialog.systemType) {
+                    this.getData()
+                    this.tableData = [];
+                    if (this.type == 'read') {
+                        this.getLinkSystemData()
+                    } else {
+                        this.getLinkSystemData()
+                        this.getTableData()
+                    }
+                }
+            }
+        },
+        projectId() {
+            this.buildId = 'all';
+            this.options = [];
+            this.getData()
+        }
+    }
+};
+</script>
+
+<style lang="less">
+#systemType {
+    height: 455px;
+    overflow-y: auto;
+
+    .el-table thead {
+        tr {
+            th {
+                background-color: #f5f7fa;
+            }
+        }
+    }
+}
+</style>

+ 95 - 0
src/components/dialogs/list/uploadImgDialog.vue

@@ -0,0 +1,95 @@
+<!--
+    上传图片的弹窗
+-->
+
+<template>
+  <el-dialog title="上传图片" :visible.sync="dialog.uploadImgs" width="500px">
+    <div style="max-height: 500px; overflow-y: auto;">
+        <upload-imgs :readOnly="read" :keysArr="deepcopy(keysArr)" @change="changeItem" max="2"></upload-imgs>
+    </div>
+  </el-dialog>
+</template>
+<script>
+  import uploadImgs from "@/components/ledger/components/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) {
+      return JSON.parse(JSON.stringify(obj));
+    },
+    changeItem(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
+              case 'infos.installPic':
+                this.$emit("changeFile", info, this.firmDataType, file)
+                break
+              case 'infos.nameplate':
+                this.$emit("changeFile", info, this.firmDataType, file)
+                break
+            }
+        } else {
+            this.$emit("changeFile", file)
+        }
+
+    }
+  },
+};
+</script>
+<style>
+</style>

+ 161 - 0
src/components/dialogs/noModelDialog.vue

@@ -0,0 +1,161 @@
+<template>
+    <el-dialog
+        :visible.sync="isShow.dialogVisible"
+        :close-on-click-modal="false"
+        :close-on-press-escape="false"
+        :show-close="false"
+        :width="width"
+    >
+        <span slot="title">{{title}}</span>
+        <!-- <slot name="body"></slot> -->
+        <el-tree :props="treeArr" :data="data" @node-click="floorClick" :highlight-current="true"></el-tree>
+        <span slot="footer" class="dialog-footer my">
+            <el-button @click="close">取 消</el-button>
+            <el-button type="primary" @click="confirm">确 定</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import {
+    getBuildSelect, //根据项目ID获得建筑列表
+    getSpaceFloor //根据建筑id获取楼层id
+} from "@/api/scan/request";
+import {mapGetters, mapActions} from "vuex";
+import tools from '@/utils/scan/tools'
+export default {
+    props: {
+        width: {
+            type: String,
+            default: "40%"
+        },
+        title: {
+            type: String,
+            default: "头部信息"
+        },
+        isShow: {
+            type: Object
+        },
+        param: {
+            type: Object
+        }
+    },
+    data() {
+        return {
+            treeArr: {
+                label: "name", //label的名字
+                children: "children", //如果有下一级children和isLeaf存在
+            },
+            data: null,
+            proj: null,
+            mess: null
+        };
+    },
+    created() {
+        this.param.ProjId = this.projectId
+        this.param.secret = this.secret
+        this.param.UserId = this.userId
+        // this.getNodes()
+    },
+    computed: {
+        ...mapGetters("layout", [
+            "projectId",
+            "secret",
+            "userId"
+        ])
+    },
+    methods: {
+        //确定
+        confirm() {
+            if (!!this.mess) {
+                this.isShow.dialogVisible = false;
+                this.$emit("close", this.mess);
+            } else {
+                this.$message("请选择楼层");
+            }
+        },
+        //取消
+        close() {
+            if (!!this.mess) {
+                this.isShow.dialogVisible = false;
+            } else {
+                this.$message("请选择楼层");
+            }
+        },
+        changeArr(arr) {
+            return arr.map(item => {
+                if (item.floors && item.floors.length) {
+                    return {
+                        code: item.id,
+                        name: item.infos.BuildLocalName,
+                        children: item.floors.map(i => {
+                            return {
+                                code: i.id,
+                                name: (i.infos.FloorLocalName || i.infos.FloorName || "未知") + this.myMess(i),
+                                map: i.infos.FloorMap || null,
+                                affected: i.affected,
+                                isChilren: 2,
+                                buildCode: item.id,
+                                buildName: item.infos.BuildLocalName,
+                                shunxu: i.infos.FloorSequenceID || 0
+                            }
+                        })
+                    }
+                } else {
+                    return {
+                        code: item.id,
+                        name: item.infos.BuildLocalName,
+                        children: null,
+                        isChilren: 1,
+                    }
+                }
+            })
+        },
+
+        myMess(i) {
+            if (i.affected) {
+                return "(该业务空间受元空间变化影响)"
+            } else {
+                if (i.infos.FloorMap) {
+                    return ''
+                } else {
+                    return "(请初始化平面图)"
+                }
+            }
+        },
+        //点击节点懒加载
+        // getNodes() { // 物理世界 已无接口
+        //     let param = {
+        //         ProjId: this.param.ProjId,
+        //         UserId: this.param.UserId,
+        //         secret: this.param.secret
+        //     };
+        //     getSpaceFloor(param).then(res => {
+        //         if (res.data.Result == 'success') {
+        //             let data = this.changeArr(res.data.Content).map(item => {
+        //                 if (item.children && item.children.length) {
+        //                     item.children = tools.sortArr(item.children, "shunxu", false)
+        //                 }
+        //                 return item
+        //             })
+        //             this.data = data
+        //         } else {
+        //             this.$message.error(res.data.ResultMsg)
+        //         }
+        //     }).catch(() => {
+        //         this.$message.error("请求出错")
+        //     })
+        // },
+
+        //子节点被点击
+        floorClick(data) {
+            if (data.isChilren == 2) {
+                this.mess = data
+            } else { }
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 57 - 0
src/components/dialogs/notRelated.vue

@@ -0,0 +1,57 @@
+<template>
+  <el-dialog :visible.sync="isShow.notRelated" :width="width">
+    <span slot="title">{{title}}</span>
+    <business-table
+      ref="business"
+      @createSuccess="createSuccess"
+      :type="list[0].id ? 'relevance' : 'no'"
+    ></business-table>
+  </el-dialog>
+</template>
+
+<script>
+import businessTable from "@/components/table/businessTable";
+
+export default {
+  components: {
+    businessTable
+  },
+  props: {
+    width: {
+      type: String,
+      default: "45%"
+    },
+    title: {
+      type: String,
+      default: "未关联元空间的业务空间"
+    },
+    isShow: {
+      type: Object
+    },
+    param: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      list: [{}]
+    };
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    getIdList(list, build, graphy, code) {
+      this.list = list;
+      console.log(this.list)
+      this.$nextTick(() => {
+        this.$refs.business.getData(list, build, graphy, code);
+      });
+    },
+    createSuccess() {
+      this.$emit("createSuccess")
+    }
+  }
+};
+</script>
+<style>
+</style>

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

@@ -131,7 +131,8 @@ import {
   queryProperty,
   updateProperty
 } from "@/api/scan/request";
-import {getDataDictionary} from "@/api/dict";
+// import {getDataDictionary} from "@/api/dict";
+import Dic from "@/controller/dicController";
 import tools from "@/utils/scan/tools"
 import handsonUtils from "@/utils/scan/hasontableUtils"
 import showTools from "@/utils/handsontable/notShow"
@@ -280,7 +281,7 @@ export default {
           type: this.mess.deviceId,
           orders: "sort asc, name desc",
         };
-        getDataDictionary(params, res => {
+        Dic.getDataDictionary(params, res => {
           this.tableHeader = res.content;
           this.codeToDataSource = {}
           this.tableHeader.forEach(item => {

+ 22 - 20
src/components/ledger/components/handsontables/device.vue

@@ -142,31 +142,33 @@
     </div>
 </template>
 <script>
-import { BeatchQueryParam, deleteEquip, getEquipBelongs, updateEquip } from "@/api/scan/request";
-import { getEquipTableCon } from "@/api/object/equip";
-import { getDataDictionary, deliveredInfos } from "@/api/dict";
-
+// import { BeatchQueryParam, deleteEquip, getEquipBelongs, updateEquip } from "@/api/scan/request";
+import ScanController from "@/controller/ScanController";
+// import { getEquipTableCon } from "@/api/object/equip";
+import Equip from "@/controller/equipController";
+// import { getDataDictionary, deliveredInfos } from "@/api/dict";
+import Dic from "@/controller/dicController";
 import tools from "@/utils/scan/tools";
 import handsonUtils from "@/utils/hasontableUtils";
 import showTools from "@/utils/handsontable/notShow";
 import text from "@/utils/handsontable/mainText";
-import myCascader from "@/components/ledger/lib/cascader";
+import myCascader from "@/components/ledger/components/lib/cascader";
 import buildFloor from "@/utils/handsontable/buildFloorData";
-
-import qrcode from "@/components/ledger/lib/qrcode";
-import bimDialog from "@/components/ledger/lib/bimDialog";
+import BuildController from "@/controller/buildController";
+import qrcode from "@/components/ledger/components/lib/qrcode";
+import bimDialog from "@/components/ledger/components/lib/bimDialog";
 import uploadFilesDialog from "@/components/dialogs/list/filesDialog";
 import uploadImgDialog from "@/components/dialogs/list/uploadImgDialog";
 import picDialog from "@/components/dialogs/list/picDialog";
 import menum from "@/components/dialogs/list/menum";
 import batchDialog from "@/components/dialogs/list/batchDialog";
 import systemType from "@/components/dialogs/list/systemType";
-import myPagination from "@/components/ledger/lib/myPagination";
-import detailsDialog from "@/components/ledger/lib/detailsDia";
+import myPagination from "@/components/ledger/components/lib/myPagination";
+import detailsDialog from "@/components/ledger/components/lib/detailsDia";
 import changeRea from "@/components/dialogs/changeRea";
 import { mapGetters } from "vuex";
 //图片查看
-import lookPic from "@/components/ledger/lib/lookImages";
+import lookPic from "@/components/ledger/components/lib/lookImages";
 import Handsontable from "handsontable-pro";
 import "handsontable-pro/dist/handsontable.full.css";
 import lStorage from "@/utils/localStorage";
@@ -193,7 +195,7 @@ export default {
         menum,
     },
     created() {
-        buildFloor.getData(this.buildFloorData);
+        BuildController.getData(this.buildFloorData);
     },
     activated() {
         if (!this.$route.meta.isBack) {
@@ -403,7 +405,7 @@ export default {
             } else if (this.mess.floorId && this.mess.floorId != "all") {
                 params.floorId = `${this.mess.floorId}`;
             }
-            deliveredInfos(params, (res) => {
+            Dic.deliveredInfos(params, (res) => {
                 this.tableHeader = res.content;
                 this.codeToDataSource = {};
                 this.tableHeader.forEach((item) => {
@@ -435,7 +437,7 @@ export default {
                 type: classCode,
                 orders: "sort asc, name desc",
             };
-            getDataDictionary(params, (res) => {
+            Dic.getDataDictionary(params, (res) => {
                 this.tableHeader = res.content;
                 this.codeToDataSource = {};
                 this.tableHeader.forEach((item) => {
@@ -497,7 +499,7 @@ export default {
                     param.filters += `;localName contain '${this.mess.keyWord}' || localId contain '${this.mess.keyWord}' || cADID contain '${this.mess.keyWord}' || infos.digitalDeliveryID contain '${this.mess.keyWord}'`;
                 }
 
-                getEquipTableCon(param, (res) => {
+                Equip.getEquipTableCon(param, (res) => {
                     this.loading = false;
                     this.showParts = res.message == "1" ? true : false; // 判断是否显示包含的部件列
                     this.tableData = res.content.map((item) => {
@@ -548,7 +550,7 @@ export default {
                 }
             });
             if (param.data.length) {
-                BeatchQueryParam(param, (res) => {
+                ScanController.BeatchQueryParam(param, (res) => {
                     if (!this.onlyRead) {
                         return false;
                     }
@@ -891,7 +893,7 @@ export default {
         },
         // 删除设备
         async removeDevice(param) {
-            await deleteEquip(param, (res) => {
+            await ScanController.deleteEquip(param, (res) => {
                 this.$message.success("删除成功");
                 this.$emit("close", { code: this.deleteCode });
                 // this.getTableData()
@@ -953,7 +955,7 @@ export default {
                     param.content.push(item);
                 }
             });
-            updateEquip(param, (res) => {});
+            ScanController.updateEquip(param, (res) => {});
         },
         //修改设备类型
         changeCader() {
@@ -965,7 +967,7 @@ export default {
                         pageSize: 50,
                     },
                 };
-                getEquipBelongs(param, (res) => {
+                ScanController.getEquipBelongs(param, (res) => {
                     if (res.content.length) {
                         this.deviceType.assetType = res.content[0].family;
                         this.deviceType.assetName = res.content[0].familyName;
@@ -1408,7 +1410,7 @@ export default {
     watch: {
         projectId() {
             this.buildFloorData = [];
-            buildFloor.getData(this.buildFloorData);
+            BuildController.getData(this.buildFloorData);
             this.tableData = [];
             this.mess.deviceId = null;
             this.page.total = 0;

+ 3 - 2
src/components/ledger/components/lib/bimDialog.vue

@@ -32,7 +32,8 @@
 import noAllDataFloor from './noAllDataFloor'
 import { FloorView, LocationPointScene } from '@saga-web/cad-engine/lib'
 import { SPoint } from '@saga-web/draw/lib'
-import { updateEquip } from '@/api/scan/request'
+// import { updateEquip } from '@/api/scan/request'
+import ScanController from '@/controller/ScanController'
 import { SGraphItem } from '@saga-web/graph/lib'
 
 export default {
@@ -214,7 +215,7 @@ export default {
             ],
             projection: ['bimLocation', 'buildingId', 'floorId'],
           }
-          updateEquip(param, (res) => {
+          ScanController.updateEquip(param, (res) => {
             if (res.result == 'success') {
               this.$message.success('保存成功')
               this.handleClose('update')

+ 7 - 4
src/components/ledger/components/lib/cascader.vue

@@ -13,8 +13,11 @@
 </template>
 <script>
 import { mapGetters } from 'vuex';
-import { queryEquip } from "@/api/object/equip";
-import { queryPhysicsAllType } from "@/api/dict";
+// import { queryEquip } from "@/api/object/equip";
+
+// import { queryPhysicsAllType } from "@/api/dict";
+import Dic from '@/controller/dicController';
+import Equip from '@/controller/equipController';
 
 export default {
   name: "getCode",
@@ -105,12 +108,12 @@ export default {
       }
 
       let promise2 = new Promise((resolve, reject) => {
-        queryEquip(param2, res => {
+        Equip.queryEquip(param2, res => {
           resolve(res)
         })
       })
       let promise1 = new Promise((resolve, reject) => {
-        queryPhysicsAllType(param1, res => {
+        Dic.queryPhysicsAllType(param1, res => {
           resolve(res)
         })
       })

+ 9 - 6
src/components/ledger/components/lib/dynamicDialog.vue

@@ -55,9 +55,12 @@
 </template>
 
 <script>
-import storage from "@/framework/utils/storage";
-import { baseUrl, dataCenter } from "@/api/scan/config.js";
-import { queryDownloadsKey } from "@/api/scan/request";
+// import storage from "@/framework/utils/storage";
+import storage from "@/utils/storageUtil";
+// import { baseUrl, dataCenter } from "@/api/scan/config.js";
+import ScanUtil from "@/utils/scanUtil";
+// import { queryDownloadsKey } from "@/api/scan/request";
+import ScanController from "@/controller/ScanController";
 import { mapGetters } from "vuex";
 
 export default {
@@ -68,8 +71,8 @@ export default {
             messageKey: "",
             historyKey: "",
             activities: [],
-            baseUrl: baseUrl,
-            dataCenter: dataCenter,
+            baseUrl: ScanUtil.baseUrl,
+            dataCenter: ScanUtil.datacenter,
         };
     },
     computed: {
@@ -96,7 +99,7 @@ export default {
                 orders: "createTime desc",
                 pageSize: 1,
             };
-            queryDownloadsKey(params, (res) => {
+            ScanController.queryDownloadsKey(params, (res) => {
                 if (res.result === "success" && res.content && res.content.length && res.content[0].key) {
                     this.historyKey = res.content[0].key;
                 } else {

+ 3 - 2
src/components/ledger/components/lib/equipCascader.vue

@@ -19,7 +19,8 @@
 </template>
 <script>
 import { mapGetters } from "vuex";
-import { getEquipLkSys } from "@/api/dict";
+// import { getEquipLkSys } from "@/api/dict";
+import Dic from "@/controller/dicController";
 
 export default {
     name: "getCode",
@@ -107,7 +108,7 @@ export default {
                 }
                 params.filters = params.filters.slice(1);
             }
-            getEquipLkSys(params, (res) => {
+            Dic.getEquipLkSys(params, (res) => {
                 if (res.content) {
                     this.options = res.content;
                 } else {

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

@@ -6,8 +6,10 @@
 </template>
 <script>
     import tools from "@/utils/scan/tools";
-    import { buildingQuery } from '@/api/object/build';
-    import { floorQuery } from '@/api/object/floor';
+    // import { buildingQuery } from '@/api/object/build';
+    import Builder from "@/controller/buildController";
+    // import { floorQuery } from '@/api/object/floor';
+    import Floor from "@/controller/floorController";
     import { mapGetters, mapActions } from "vuex";
 
     export default {
@@ -76,12 +78,12 @@
                     pageSize: 1000
                 }
                 let promise1 = new Promise((resolve, reject) => {
-                    buildingQuery(buildParams, res => {
+                    Builder.buildingQuery(buildParams, res => {
                         resolve(res)
                     })
                 })
                 let promise2 = new Promise((resolve, reject) => {
-                    floorQuery(floorParams, res => {
+                    Floor.floorQuery(floorParams, res => {
                         resolve(res)
                     })
                 })

+ 13 - 9
src/components/ledger/components/lib/linkassets.vue

@@ -33,10 +33,14 @@
 </template>
 <script>
 
-import { zoneQuery, TypePartsDie } from '@/api/scan/request'
-import { queryPhysicsAllType } from '@/api/dict'
-import { buildingQuery } from '@/api/object/build'
-import { floorQuery } from '@/api/object/floor'
+// import { zoneQuery, TypePartsDie } from '@/api/scan/request'
+// import { queryPhysicsAllType } from '@/api/dict'
+import Dic from '@/controller/dicController'
+import Builder from '@/controller/buildController'
+import Floor from '@/controller/floorController'
+import ScanController from '@/controller/ScanController'
+// import { buildingQuery } from '@/api/object/build'
+// import { floorQuery } from '@/api/object/floor'
 
 import { mapGetters } from "vuex"
 
@@ -86,7 +90,7 @@ export default {
     //获取未关联资产的设备或部件类型
     getPartsDieType() {
       let _this = this
-      TypePartsDie(res => {       
+      ScanController.TypePartsDie(res => {       
         _this.deviceTypeList = res.content
       })
     },
@@ -112,12 +116,12 @@ export default {
         ]
       }
       let promise1 = new Promise((resolve, reject) => {
-        buildingQuery(buildParams, res => {
+        Builder.buildingQuery(buildParams, res => {
           resolve(res)
         })
       })
       let promise2 = new Promise((resolve, reject) => {
-        floorQuery(floorParams, res => {
+        Floor.floorQuery(floorParams, res => {
           resolve(res)
         })
       })
@@ -170,7 +174,7 @@ export default {
       let params = {
         type: "space"
       }
-      queryPhysicsAllType(params, res => {
+      Dic.queryPhysicsAllType(params, res => {
         if (res.content) {
 					this.zoneList = res.content.filter(item => {
 						if (item.name !== item.aliasName) {
@@ -240,7 +244,7 @@ export default {
               params.buildingId = this.buildFloor[0];
             }
           }
-          zoneQuery(params, res => {
+          ScanController.zoneQuery(params, res => {
             nodes = nodes.concat(res.content.map(item => ({
               value: item.id,
               label: item.localName ? item.localName : item.name

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

@@ -53,7 +53,7 @@
   </el-dialog>
 </template>
 <script>
-  import uploadImgs from "@/components/ledger/lib/uploadImgsName";
+  import uploadImgs from "@/components/ledger/components/lib/uploadImgsName";
 
   export default {
   components: {

+ 6 - 4
src/components/ledger/components/lib/noAllDataFloor.vue

@@ -8,8 +8,10 @@
 <script>
 import tools from "@/utils/scan/tools"
 // import { floorQuery, buildingQuery } from '@/api/scan/request'
-import { buildingQuery } from '@/api/object/build'
-import { floorQuery } from '@/api/object/floor'
+// import { buildingQuery } from '@/api/object/build'
+import BuildController from "@/controller/buildController"
+import FloorController from "@/controller/floorController"
+// import { floorQuery } from '@/api/object/floor'
 
 import { mapGetters, mapActions } from "vuex"
 
@@ -79,12 +81,12 @@ export default {
         pageSize: 1000
       }
       let promise1 = new Promise((resolve, reject) => {
-        buildingQuery(buildParams, res => {
+        BuildController.buildingQuery(buildParams, res => {
           resolve(res)
         })
       })
       let promise2 = new Promise((resolve, reject) => {
-        floorQuery(floorParams, res => {
+        FloorController.floorQuery(floorParams, res => {
           resolve(res)
         })
       })

+ 11 - 8
src/components/ledger/components/lib/staticDialog.vue

@@ -55,9 +55,12 @@
 </template>
 
 <script>
-import storage from "@/framework/utils/storage";
-import { baseUrl, dataCenter } from "@/api/scan/config.js";
-import { queryDownloadsKey, equipTemplate } from "@/api/scan/request";
+// import storage from "@/framework/utils/storage";
+import storage from "@/utils/storageUtil";
+// import { baseUrl, dataCenter } from "@/api/scan/config.js";
+import ScanUtil from "@/utils/scanUtil";
+// import { queryDownloadsKey, equipTemplate } from "@/api/scan/request";
+import ScanController from "@/controller/ScanController";
 import { mapGetters } from "vuex";
 
 export default {
@@ -68,8 +71,8 @@ export default {
             messageKey: "",
             historyKey: "",
             activities: [],
-            baseUrl: baseUrl,
-            dataCenter: dataCenter,
+            baseUrl: ScanUtil.baseUrl,
+            dataCenter: ScanUtil.dataCenter,
         };
     },
     computed: {
@@ -96,8 +99,8 @@ export default {
                 orders: "createTime desc",
                 pageSize: 1,
             };
-            queryDownloadsKey(params, (res) => {
-                queryDownloadsKey(params, (res) => {
+            ScanController.queryDownloadsKey(params, (res) => {
+                ScanController.queryDownloadsKey(params, (res) => {
                     if (res.result === "success" && res.content && res.content.length && res.content[0].key) {
                         this.historyKey = res.content[0].key;
                     } else {
@@ -231,7 +234,7 @@ export default {
          * 台账信息导入模板
          */
         downloadEquipTemplate() {
-            equipTemplate(
+            ScanController.equipTemplate(
                 {},
                 (res) => {
                     console.log("下载台账信息导入模板");

+ 15 - 14
src/components/ledger/components/tableTransfers.vue

@@ -75,16 +75,17 @@
 </template>
 <script>
 import myPagination from "@/components/common/myPagination";
-import floorCascader from "@/components/ledger/lib/floorCascader";
-import cascader from "@/components/ledger/lib/cascader";
+import floorCascader from "@/components/ledger/components/lib/floorCascader";
+import cascader from "@/components/ledger/components/lib/cascader";
 
-import {
-  getEquipNotInSys,
-  getEquipInSys,
-  getEquipBelongs,
-  sysLinkEquip,
-  sysUnlinkEquip
-} from "@/api/scan/request"
+// import {
+//   getEquipNotInSys,
+//   getEquipInSys,
+//   getEquipBelongs,
+//   sysLinkEquip,
+//   sysUnlinkEquip
+// } from "../api/scan/request"
+import ScanController from "@/controller/ScanController";
 import {
   mapGetters,
   mapActions
@@ -173,7 +174,7 @@ export default {
           ]
         }
       }
-      getEquipBelongs(param, res => {
+      ScanController.getEquipBelongs(param, res => {
         this.List = this.formatOptions(res.content)
       })
     },
@@ -245,7 +246,7 @@ export default {
       } else {
         delete param.data.Filters;
       }
-      getEquipNotInSys(param, res => {
+      ScanController.getEquipNotInSys(param, res => {
         this.tableData = res.Content
         this.pages1.total = res.Total
         this.isLoading1 = false
@@ -263,7 +264,7 @@ export default {
       if (this.search2 != '') {
         param.Filters += `;EquipLocalName contain '${this.search2}' || EquipName contain '${this.search2}'`
       }
-      getEquipInSys(param, res => {
+      ScanController.getEquipInSys(param, res => {
         this.table2Data = res.Content
         this.pages2.total = res.Total
         this.isLoading2 = false
@@ -293,7 +294,7 @@ export default {
           SysID: t.SysID
         }
       })
-      sysUnlinkEquip(tempIDs, res => {
+      ScanController.sysUnlinkEquip(tempIDs, res => {
         this.$message.success('修改关联关系成功')
         this.getAllTable()
       })
@@ -304,7 +305,7 @@ export default {
         sysId: this.id,
         equipIdList: arr
       }
-      sysLinkEquip(param, res => {
+      ScanController.sysLinkEquip(param, res => {
         this.$message.success('修改关联关系成功')
         this.getAllTable()
       })

+ 14 - 12
src/components/ledger/facility/index.vue

@@ -39,15 +39,17 @@
     </div>
 </template>
 <script>
-import sagaTitle from "../components/ledger/lib/title";
-import floorCascader from "../components/ledger/lib/floorCascader";
-import myCascader from "../components/ledger/lib/equipCascader";
-import hansonTable from "../components/ledger/handsontables/device";
-import tableTransfers from "../components/ledger/tableTransfers";
-import linkassetsDialog from "../components/ledger/lib/linkassets";
-import { countEquip } from "../api/object/equip";
-import dynamicDialog from "../components/ledger/lib/dynamicDialog";
-import staticDialog from "../components/ledger/lib/staticDialog";
+import sagaTitle from "../components/lib/title";
+import floorCascader from "../components/lib/floorCascader";
+import myCascader from "../components/lib/equipCascader";
+import hansonTable from "../components/handsontables/device";
+import tableTransfers from "../components/tableTransfers";
+import linkassetsDialog from "../components/lib/linkassets";
+// import { countEquip } from "../api/object/equip";
+import Equip from "@/controller/equipController";
+import { Facility } from "@/controller/facilityController";
+import dynamicDialog from "../components/lib/dynamicDialog";
+import staticDialog from "../components/lib/staticDialog";
 import { mapGetters } from "vuex";
 
 export default {
@@ -93,7 +95,7 @@ export default {
         };
     },
     computed: {
-        ...mapGetters("layout", ["projectId", "projects", "secret", "userId"]),
+        ...mapGetters('layout', ["projectId", "projects", "secret", "userId"]),
     },
     created() {
         this.param.ProjId = this.projectId;
@@ -176,10 +178,10 @@ export default {
             let param = {
                 filters: "not propertyId isnull",
             };
-            countEquip({}, (res) => {
+            Equip.countEquip({}, (res) => {
                 this.mess.name[0].num = res.count;
             });
-            countEquip(param, (res) => {
+            Equip.countEquip(param, (res) => {
                 this.mess.name[1].num = res.count;
             });
         },

+ 18 - 0
src/controller/ScanController.ts

@@ -0,0 +1,18 @@
+class ScanController {
+  static async getEquipNotInSys() {}
+  static async getEquipInSys() {}
+  static async getEquipBelongs() {}
+  static async sysLinkEquip() {}
+  static async BeatchQueryParam() {}
+  static async deleteEquip() {}
+  static async updateEquip() {}
+  static async zoneQuery() {}
+  static async TypePartsDie() {}
+  static async queryDownloadsKey() {}
+  static async equipTemplate() {}
+  static async queryProperty() {}
+  static async querySysLinkBuild() {}
+  static async equipLinkSys() {}
+  static async getAllProject(params?: any, fn?: any) {}
+}
+export default ScanController;

+ 146 - 0
src/controller/buildController.ts

@@ -0,0 +1,146 @@
+import FloorController from "./floorController";
+class BuildController {
+  static async buildingQuery(params) {}
+  static async getData(buildFloorData) {
+    let data,
+      buildParams = {
+        pageNumber: 1,
+        pageSize: 1000,
+        orders: "localName asc",
+        projection: ["id", "localName"],
+      },
+      floorParams = {
+        orders: "floorSequenceID desc",
+        pageNumber: 1,
+        pageSize: 1000,
+        projection: ["buildingId", "id", "localName", "floorSequenceID"],
+      };
+
+    // let promise1 = new Promise((resolve, reject) => {
+    //   this.buildingQuery(buildParams, res => {
+    //     resolve(res)
+    //   })
+    // })
+    // let promise2 = new Promise((resolve, reject) => {
+    //   floorQuery(floorParams, res => {
+    //     resolve(res)
+    //   })
+    // })
+
+    Promise.all([
+      this.buildingQuery(buildParams),
+      FloorController.floorQuery(floorParams),
+    ]).then(function (values: any) {
+      // console.log(values);
+      return;
+      let builData = values[0].content,
+        floorData = values[1].content;
+      data = builData.map((build) => {
+        return {
+          value: build.id,
+          label: build.localName,
+        };
+      });
+      data.unshift({
+        value: "",
+        label: "未明确建筑",
+      });
+      data.forEach((build) => {
+        floorData.forEach((floor) => {
+          if (build.value == floor.buildingId && floor.id && floor.localName) {
+            if (build.children) {
+              build.children.push({
+                value: floor.id,
+                label: floor.localName,
+              });
+            } else {
+              build.children = [];
+              build.children.push(
+                {
+                  value: "",
+                  label: "未明确楼层",
+                },
+                {
+                  value: floor.id,
+                  label: floor.localName,
+                }
+              );
+            }
+          }
+        });
+      });
+      data.forEach((item) => {
+        if (item.children && item.children.length) {
+          item.children.forEach((child) => {
+            if (child.value != "") {
+              buildFloorData.push({
+                Code: item.value + "-" + child.value,
+                Name: item.label + "-" + child.label,
+              });
+            } else {
+              buildFloorData.push({
+                Code: item.value,
+                Name: item.label + "-" + child.label,
+              });
+            }
+          });
+        } else {
+          buildFloorData.push({
+            Code: item.value,
+            Name: item.label,
+          });
+        }
+      });
+    });
+    // buildingQuery(buildParams, res => {
+    //   let builData = res.Content
+    //   data = builData.map(build => {
+    //       return {
+    //           value: build.BuildID,
+    //           label: build.BuildLocalName
+    //       }
+    //   })
+    //   data.unshift({
+    //     value: "",
+    //     label: "未明确建筑的设备"
+    //   })
+    //   floorQuery(floorParams, res => {
+    //       let floorData = res.Content
+    //       data.forEach(build => {
+    //           floorData.forEach(floor => {
+    //               if (build.value == floor.BuildID && floor.FloorID && floor.FloorLocalName) {
+    //                   if (build.children) {
+    //                       build.children.push({
+    //                           value: floor.FloorID,
+    //                           label: floor.FloorLocalName
+    //                       })
+    //                   } else {
+    //                       build.children = []
+    //                       build.children.push({
+    //                           value: "",
+    //                           label: "未明确楼层的设备"
+    //                       })
+    //                   }
+    //               }
+    //           })
+    //       })
+    //       data.forEach(item => {
+    //         if (item.children && item.children.length) {
+    //           item.children.forEach(child => {
+    //             buildFloorData.push({
+    //               Code: item.value + "-" + child.value,
+    //               Name: item.label + "-" + child.label
+    //             })
+    //           })
+    //         } else {
+    //           buildFloorData.push({
+    //             Code: item.value,
+    //             Name: item.label
+    //           })
+    //         }
+    //       })
+    //   })
+    // })
+  }
+}
+export default BuildController;

+ 8 - 0
src/controller/dicController.ts

@@ -0,0 +1,8 @@
+class Dic {
+  static async getDataDictionary() {}
+  static async deliveredInfos() {}
+  static async getEquipLkSys() {}
+  static async queryPhysicsAllType() {}
+}
+
+export default Dic;

+ 7 - 0
src/controller/equipController.ts

@@ -0,0 +1,7 @@
+class Equip {
+  static async getEquipTableCon() {}
+  static async queryEquip() {}
+  static async countEquip() {}
+}
+
+export default Equip;

+ 7 - 0
src/controller/facilityController.ts

@@ -0,0 +1,7 @@
+import { baseHttpUtils } from "@/utils/http/baseHttpUtils";
+export class Facility {
+  http: baseHttpUtils;
+  async countEquip() {
+    console.log(this.http);
+  }
+}

+ 4 - 0
src/controller/floorController.ts

@@ -0,0 +1,4 @@
+class FloorController {
+  static async floorQuery(params?: any) {}
+}
+export default FloorController;

File diff suppressed because it is too large
+ 42 - 0
src/data/deviceList.js


+ 209 - 0
src/data/mapTable.js

@@ -0,0 +1,209 @@
+export const State = {
+  '-5': '已撕码',
+  '-4': '现场未找到',
+  '-3': '现场已找到-隐蔽工程未贴码',
+  '-2': '现场已找到-距离太远未贴码',
+  '-1': '现场已找到-只验证未贴码',
+  '0': '现场已找到-正常贴码',
+  '1': '待现场验证',
+  '2': '撕码任务',
+  '3': '换码任务'
+}
+
+export const Family = {
+  "AHA": "空气源热泵",
+  "CLA": "吊顶",
+  "WGA": "风力发电装置",
+  "HEA": "换热器",
+  "WBA": "防水板",
+  "MAA": "手动报警按钮",
+  "SBA": "气体灭火启动瓶",
+  "CDA": "水加药装置",
+  "PAA": "燃气调压箱",
+  "SEA": "火灾探测器",
+  "DPA": "位移传感器",
+  "WTB": "水箱",
+  "SDB": "防火排烟阀",
+  "TCA": "伴热电缆",
+  "CRA": "门禁读卡器",
+  "ESA": "扶梯",
+  "OHA": "室外消火栓",
+  "TLC": "坐便器",
+  "DGA": "柴油发电机",
+  "SUA": "供水机组",
+  "CPB": "控制面板",
+  "HSA": "高压开关柜",
+  "FTA": "泡沫储罐组",
+  "TUA": "全程水处理仪",
+  "VDB": "图像传感器",
+  "SAA": "分体空调",
+  "AHB": "空调机组",
+  "DSB": "显示屏",
+  "APA": "空气净化器",
+  "FCB": "变频器",
+  "TUC": "直饮水处理机组",
+  "PNA": "嵌板",
+  "PSB": "巡更棒",
+  "IBA": "伴热保温器",
+  "TPA": "温度传感器",
+  "SKA": "洗碗槽",
+  "SPE": "蹲便器",
+  "EHA": "电热水器",
+  "STA": "自助终端机",
+  "PSD": "停车位",
+  "EXA": "交换机",
+  "WSA": "盥洗盆",
+  "EEA": "电度传感器",
+  "VMA": "监视器",
+  "FLA": "流量传感器",
+  "AAA": "抗浮锚杆",
+  "VDA": "真空脱气机",
+  "SDA": "软化水装置",
+  "ARA": "扶手",
+  "STC": "化粪池",
+  "CBB": "组合式传感器",
+  "OTA": "冷却塔",
+  "RCA": "雨水收集设备",
+  "SUB": "喷灌机组",
+  "ELB": "应急照明灯具",
+  "CBA": "燃煤锅炉",
+  "BGA": "气体灭火瓶组",
+  "SNA": "喷头",
+  "HDB": "干手机",
+  "CMA": "摄像头",
+  "ELA": "直梯",
+  "APB": "油烟净化器",
+  "HDA": "加湿器",
+  "CPA": "充电桩",
+  "PVA": "预作用报警阀组",
+  "AVA": "调节阀",
+  "BPA": "母线插接箱",
+  "DOA": "除味装置",
+  "FEB": "广播前端设备",
+  "PLB": "桩",
+  "CTC": "帘",
+  "STB": "蓄冷热槽",
+  "FCA": "风机盘管",
+  "IHA": "即时加热器",
+  "IUA": "室内机",
+  "PPA": "水泵",
+  "HFA": "硬件防火墙",
+  "XXX": "其他",
+  "TFA": "变压器",
+  "FNA": "风机",
+  "GHB": "燃气热水器",
+  "RVA": "减压阀",
+  "LSB": "漏电探测器",
+  "GLA": "车位引导灯",
+  "IOA": "风口",
+  "CPC": "集水坑",
+  "MFA": "消声器",
+  "CPE": "组件",
+  "GBA": "燃气锅炉",
+  "SDC": "声音传感器",
+  "SPC": "扬声器",
+  "KLA": "龙骨",
+  "CFA": "定压补水装置",
+  "MPA": "机械车位",
+  "EBA": "电锅炉",
+  "SNB": "气体灭火喷头",
+  "LPA": "液化石油气瓶",
+  "FHA": "地板采暖设备",
+  "CUA": "控制箱",
+  "BPC": "地埋管",
+  "OSA": "隔油池",
+  "DSA": "直流屏",
+  "OUA": "室外机",
+  "PFA": "人流量传感器",
+  "TSA": "水箱消毒器",
+  "FGA": "速通门",
+  "HBA": "消火栓箱",
+  "FUA": "新风机组",
+  "ALA": "声光报警器",
+  "CCA": "离心式冷水机组",
+  "WVA": "湿式报警阀组",
+  "HTB": "热量传感器",
+  "CVA": "燃气切断阀",
+  "SED": "强电线路",
+  "GHA": "地源热泵",
+  "CTA": "浓度传感器",
+  "FBA": "燃油锅炉",
+  "PDA": "车位检测器",
+  "EDA": "电梯基坑",
+  "SPD": "速度传感器",
+  "RSA": "中继台",
+  "DVA": "干式报警阀组",
+  "HAA": "辅热设备",
+  "RTA": "路由器",
+  "WEA": "弱电线路",
+  "MTA": "电机",
+  "DRA": "硬盘录像机",
+  "SEC": "入侵报警探测器",
+  "SPB": "潜污泵",
+  "LPB": "联动琴台",
+  "EIA": "疏散指示灯牌",
+  "WMA": "消防水炮设备",
+  "SPA": "太阳能电池板",
+  "PTA": "压力罐",
+  "ATA": "信号放大天线",
+  "PCA": "水泵接合器",
+  "DCA": "分集水器",
+  "CFC": "泳池循环过滤机组",
+  "SEB": "燃气探测器",
+  "RHA": "湿度传感器",
+  "HTA": "主机",
+  "ETA": "末端试水装置",
+  "ECA": "灭火剂容器",
+  "GTA": "进出闸机",
+  "WTA": "对讲机",
+  "ILA": "保温层",
+  "APC": "无线AP点位",
+  "GSA": "气体管道",
+  "IPA": "综合保护装置",
+  "GDA": "梁",
+  "PLA": "播放器",
+  "RDA": "散热器",
+  "ETB": "电梯曳引机",
+  "ORA": "餐饮除油成套设备",
+  "RLA": "继电器",
+  "EPA": "预埋件",
+  "ACA": "吸收式冷水机组",
+  "TLB": "电话",
+  "FAA": "地板空调器",
+  "LTA": "灯具",
+  "FRA": "防火卷帘门",
+  "FEA": "前端设备",
+  "SCA": "螺杆式冷水机组",
+  "PSC": "压力传感器",
+  "USA": "紫外线消毒器",
+  "BFA": "生物质炊暖炉",
+  "TLA": "工具",
+  "LUA": "污废水一体式提升机组",
+  "CPD": "巡更通讯座",
+  "ACB": "热风幕",
+  "FEC": "灭火器",
+  "SVA": "安全阀",
+  "LSA": "低压开关柜",
+  "PCB": "静压箱",
+  "CAA": "定风量箱",
+  "OVA": "通断阀",
+  "VRA": "变频多联机",
+  "ACC": "空压机",
+  "BPB": "备用电源",
+  "WHA": "水源热泵",
+  "CVB": "止回阀",
+  "FDA": "滤毒除湿机",
+  "LQA": "液体管道",
+  "BDA": "主体",
+  "RWA": "坡道",
+  "DWA": "低压配电抽屉",
+  "CSA": "垫层",
+  "CTB": "涂层",
+  "URA": "小便器",
+  "VAA": "变风量箱",
+  "SCB": "太阳能集热器",
+  "PSA": "稳压设备",
+  "TUB": "中水处理机组",
+  "BTA": "浴缸",
+  "CFB": "水景循环过滤机组"
+}

+ 358 - 0
src/data/menus.js

@@ -0,0 +1,358 @@
+export default [{
+    "id": "platform",
+    "name": "平台管理",
+    "orders": 1,
+    "appId": "adm",
+    "url": "/platform",
+    "type": "menu",
+    "disabled": true
+  },
+  {
+    "id": "project_manag",
+    "name": "项目管理",
+    "orders": 2,
+    "parentId": "platform",
+    "appId": "adm",
+    "url": "/platform/project",
+    "type": "menu",
+    "icon": "icon-project-o"
+  },
+  {
+    "id": "personnel_manag",
+    "name": "人员管理",
+    "orders": 3,
+    "parentId": "platform",
+    "appId": "adm",
+    "url": "/platform/user",
+    "type": "menu",
+    "icon": "icon-renyuanguanli"
+  },
+  {
+    "id": "role_manag",
+    "name": "角色管理",
+    "orders": 4,
+    "parentId": "platform",
+    "appId": "adm",
+    "url": "/platform/role",
+    "type": "menu",
+    "icon": "icon-jiaoseguanli"
+  },
+  {
+    "id": "ready",
+    "name": "前期准备",
+    "orders": 5,
+    "appId": "adm",
+    "type": "menu",
+    "disabled": true
+  },
+  {
+    "id": "build_floor",
+    "name": "建筑楼层管理",
+    "orders": 6,
+    "parentId": "ready",
+    "appId": "adm",
+    "url": "/ready/buildfloor",
+    "type": "menu",
+    "icon": "icon-jianzhu"
+  },
+  {
+    "id": "modelrule",
+    "name": "模型识别规则管理",
+    "orders": 7,
+    "parentId": "ready",
+    "appId": "adm",
+    "url": "/ready/modelrule",
+    "type": "menu",
+    "icon": "icon-jianzhu"
+  },
+  {
+    "id": "appuser",
+    "name": "扫楼App用户管理",
+    "orders": 8,
+    "parentId": "ready",
+    "appId": "adm",
+    "url": "/ready/appuser",
+    "type": "menu",
+    "icon": "icon-app4"
+  },
+  {
+    "id": "information",
+    "name": "信息收集",
+    "orders": 9,
+    "appId": "adm",
+    "type": "menu",
+    "disabled": true
+  },
+  {
+    "id": "model",
+    "name": "模型管理",
+    "orders": 10,
+    "parentId": "information",
+    "appId": "adm",
+    "url": "/model",
+    "type": "menu",
+    "icon": "icon-moxing___",
+    "menuChildrens": [{
+        "id": "model_file",
+        "name": "模型文件管理",
+        "orders": 11,
+        "parentId": "model",
+        "appId": "adm",
+        "url": "/model/file",
+        "type": "menu"
+      },
+      {
+        "id": "model_report",
+        "name": "模型质量报告",
+        "orders": 12,
+        "parentId": "model",
+        "appId": "adm",
+        "url": "/model/report",
+        "type": "menu"
+      }
+    ]
+  },
+  {
+    "id": "point",
+    "name": "系统集成",
+    "orders": 13,
+    "parentId": "information",
+    "appId": "adm",
+    "url": "/point",
+    "type": "menu",
+    "icon": "icon-xitong",
+    "menuChildrens": [{
+        "id": "pointsetting",
+        "name": "子系统点位接入",
+        "orders": 14,
+        "parentId": "point",
+        "appId": "adm",
+        "url": "/point/pointsetting",
+        "type": "menu"
+      },
+      {
+        "id": "dynamicdata",
+        "name": "配置动参从点位取值",
+        "orders": 15,
+        "parentId": "point",
+        "appId": "adm",
+        "url": "/point/dynamicdata",
+        "type": "menu"
+      },
+      {
+        "id": "report",
+        "name": "系统集成成果管理",
+        "orders": 16,
+        "parentId": "point",
+        "appId": "adm",
+        "url": "/point/report",
+        "type": "menu"
+      },
+      {
+        "id": "testing",
+        "name": "系统集成监测",
+        "orders": 17,
+        "parentId": "point",
+        "appId": "adm",
+        "url": "/point/testing",
+        "type": "menu"
+      },
+      {
+        "id": "point_tool",
+        "name": "系统工具库",
+        "orders": 18,
+        "parentId": "point",
+        "appId": "adm",
+        "url": "/point/tool",
+        "type": "menu"
+      }
+    ]
+  },
+  {
+    "id": "scanbuilding",
+    "name": "扫楼作业",
+    "orders": 19,
+    "parentId": "information",
+    "appId": "adm",
+    "url": "/floor",
+    "type": "menu",
+    "icon": "icon-shanglou",
+    "menuChildrens": [{
+        "id": "floor_task",
+        "name": "现场任务管理",
+        "orders": 20,
+        "parentId": "scanbuilding",
+        "appId": "adm",
+        "url": "/floor/task",
+        "type": "menu"
+      },
+      {
+        "id": "floor_data",
+        "name": "现场数据整理",
+        "orders": 21,
+        "parentId": "scanbuilding",
+        "appId": "adm",
+        "url": "/floor/data",
+        "type": "menu",
+        "menuChildrens": [{
+          "id": "floor_plan",
+          "name": "位置标签整理",
+          "orders": 1,
+          "parentId": "floor_data",
+          "appId": "adm",
+          "url": "/floor/plan",
+          "type": "menu"
+        }]
+      },
+      {
+        "id": "abnormalprop",
+        "name": "扫楼报告",
+        "orders": 22,
+        "parentId": "scanbuilding",
+        "appId": "adm",
+        "url": "/floor/abnormalprop",
+        "type": "menu"
+      },
+      {
+        "id": "floor_log",
+        "name": "扫楼日志查看",
+        "orders": 23,
+        "parentId": "scanbuilding",
+        "appId": "adm",
+        "url": "/floor/log",
+        "type": "menu"
+      }
+    ]
+  },
+  {
+    "id": "ledger",
+    "name": "台账管理",
+    "orders": 24,
+    "parentId": "information",
+    "appId": "adm",
+    "url": "/ledger",
+    "type": "menu",
+    "icon": "icon-taizhangzhangbushezhi",
+    "menuChildrens": [{
+        "id": "equipment",
+        "name": "设备台账",
+        "orders": 25,
+        "parentId": "ledger",
+        "appId": "adm",
+        "url": "/ledger/facility",
+        "type": "menu"
+      },
+      {
+        "id": "system",
+        "name": "系统台账",
+        "orders": 26,
+        "parentId": "ledger",
+        "appId": "adm",
+        "url": "/ledger/list",
+        "type": "menu"
+      },
+      {
+        "id": "space",
+        "name": "业务空间台账",
+        "orders": 27,
+        "parentId": "ledger",
+        "appId": "adm",
+        "url": "/ledger/spacelist",
+        "type": "menu"
+      },
+      {
+        "id": "shaft",
+        "name": "竖井台账",
+        "orders": 28,
+        "parentId": "ledger",
+        "appId": "adm",
+        "url": "/ledger/cenotelist",
+        "type": "menu"
+      },
+      {
+        "id": "tenant",
+        "name": "租户台账",
+        "orders": 29,
+        "parentId": "ledger",
+        "appId": "adm",
+        "url": "/ledger/rentlist",
+        "type": "menu"
+      },
+      {
+        "id": "datareport",
+        "name": "数据质量报告",
+        "orders": 30,
+        "parentId": "ledger",
+        "appId": "adm",
+        "url": "/ledger/datareport",
+        "type": "menu"
+      }
+    ]
+  },
+  {
+    "id": "relation",
+    "name": "关系维护并计算",
+    "orders": 31,
+    "appId": "adm",
+    "type": "menu",
+    "disabled": true
+  },
+  {
+    "id": "overview",
+    "name": "全部关系总览",
+    "orders": 32,
+    "parentId": "relation",
+    "appId": "adm",
+    "url": "/relation/overview",
+    "type": "menu",
+    "icon": "icon-jiqixuexi-"
+  },
+  {
+    "id": "deliver",
+    "name": "数据项目化交付",
+    "orders": 33,
+    "appId": "adm",
+    "url": "/deliver",
+    "type": "menu",
+    "disabled": true
+  },
+  {
+    "id": "synclog",
+    "name": "数据同步日志",
+    "orders": 34,
+    "parentId": "deliver",
+    "appId": "adm",
+    "url": "/synclog",
+    "type": "menu",
+    "icon": "icon-Log"
+  },
+  {
+    "id": "draw",
+    "name": "绘图工具",
+    "orders": 35,
+    "appId": "adm",
+    "url": "/draw",
+    "type": "menu",
+    "disabled": true
+  },
+  {
+    "id": "topo",
+    "name": "拓扑图",
+    "orders": 36,
+    "parentId": "draw",
+    "appId": "adm",
+    "url": "/draw/topo",
+    "type": "menu",
+    "icon": "icon-topology"
+  },
+  {
+    "id": "plane",
+    "name": "平面图",
+    "orders": 37,
+    "parentId": "draw",
+    "appId": "adm",
+    "url": "/draw/plane",
+    "type": "menu",
+    "icon": "icon-pingmiantu"
+  }
+];

+ 394 - 0
src/data/old.js

@@ -0,0 +1,394 @@
+export default [    
+    //数字化交付相关
+    {
+        path: '/projgroup',
+        name: '数字化交付相关',
+        disabled: true,
+    },
+    // 项目化配置
+    {
+        path: '/proj',
+        name: '项目基础设置',
+        icon: 'el-icon-fa-bank',
+        children: [           
+            {
+                path: '/proj/collectsetting',
+                name: '项目需采集的信息点',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }, 
+            // {
+            //     path: '/proj/custominfo',
+            //     name: '自定义信息点',
+            //     icon: 'el-icon-fa-user',
+            //     opts: [
+            //         {
+            //             name: '查看',
+            //             basic: true,
+            //             permission: 'system:role:query'
+            //         }
+            //     ]
+            // }, 
+            {
+                path: '/proj/floorinfo',
+                name: '楼层信息管理',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            },
+            {
+                path: '/floor/appuser',
+                name: '扫楼App用户管理',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }
+        ]
+    },
+    // 模型管理
+    {
+        path: '/model',
+        name: '模型管理',
+        icon: 'el-icon-fa-bank',
+        children: [
+            {
+                path: '/model/file',
+                name: '模型文件管理',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }, {
+                path: '/model/noentity',
+                name: '未实体化模型清单',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }, {
+                path: '/model/beforemodel',
+                name: '待建模清单',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }, {
+                path: '/model/modelrule',
+                name: '拓扑检查',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }, {
+                path: '/model/beacon',
+                name: '信标清单',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }
+        ]
+    },
+        // 系统集成
+        {
+            path: '/point',
+            name: '系统集成',
+            icon: 'el-icon-fa-bank',
+            children: [
+                {
+                    path: '/point/pointsetting',
+                    name: '点位表配置工具',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                }, {
+                    path: '/point/dynamicdata',
+                    name: '动态数据关联',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                }
+            ]
+        },
+    //扫楼作业
+    {
+        path: '/floor',
+        name: '扫楼作业',
+        icon: 'el-icon-fa-bank',
+        children: [
+            {
+                path: '/floor/data',
+                name: '扫楼数据管理',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            },
+            {
+                path: '/floor/plan',
+                name: '楼层平面图管理',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            },
+            {
+                path: '/floor/abnormalprop',
+                name: '异常资产清单',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            },
+            {
+                path: '/floor/log',
+                name: '扫楼日志查看',
+                icon: 'el-icon-fa-user',
+                opts: [
+                    {
+                        name: '查看',
+                        basic: true,
+                        permission: 'system:role:query'
+                    }
+                ]
+            }
+        ]
+    },
+        //台账管理
+        {
+            path: '/ledger',
+            name: '台账管理',
+            icon: 'el-icon-fa-bank',
+            children: [
+                {
+                    path: '/ledger/facility',
+                    name: '设备清单',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                },
+                {
+                    path: '/ledger/property',
+                    name: '资产清单',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                },
+                {
+                    path: '/ledger/cenotelist',
+                    name: '竖井清单',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                },
+                {
+                    path: '/ledger/dimension',
+                    name: '元空间管理',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                }, 
+                {
+                    path: '/ledger/rubbish',
+                    name: '垃圾数据检查',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                }, 
+                {
+                    path: '/ledger/updowncheck',
+                    name: '上下级关系检查',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                }                
+                
+            ]
+        },
+    //业务相关
+    {
+        path: '/busgroup',
+        name: '业务相关',
+        disabled: true,
+    },
+        //业务空间管理
+        {
+            path: '/business',
+            name: '业务空间管理',
+            icon: 'el-icon-fa-bank',
+            children: [
+                {
+                    path: '/business/spacelist',
+                    name: '业务空间清单',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                },
+            ]
+        },
+        //租户管理
+        {
+            path: '/rent',
+            name: '租户管理',
+            icon: 'el-icon-fa-bank',
+            children: [
+                {
+                    path: '/rent/rentlist',
+                    name: '租户清单',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                },
+                // {
+                //     path: '/ren',
+                //     name: '二级页面',
+                //     icon: 'el-icon-fa-user',
+                //     children: [
+                //         {
+                //             path: '/fewfewgf',
+                //             name: '三级页面1-1',
+                //             icon: '',
+                //             opts: [
+                //                 {
+                //                     name: '查看',
+                //                     basic: true,
+                //                     permission: 'system:role:query'
+                //                 }
+                //             ]
+                //         },
+                //         {
+                //             path: '/ledger/cenoteadd',
+                //             name: '三级页面1-2',
+                //             icon: '',
+                //             opts: [
+                //                 {
+                //                     name: '查看',
+                //                     basic: true,
+                //                     permission: 'system:role:query'
+                //                 }
+                //             ]
+                //         }
+                //     ]
+                // }
+            ]
+        },
+        //系统管理
+        {
+            path: '/system',
+            name: '系统管理',
+            icon: 'el-icon-fa-bank',
+            children: [
+                {
+                    path: '/system/list',
+                    name: '系统清单',
+                    icon: 'el-icon-fa-user',
+                    opts: [
+                        {
+                            name: '查看',
+                            basic: true,
+                            permission: 'system:role:query'
+                        }
+                    ]
+                },
+            ]
+        },
+   
+]

+ 40 - 26
src/router/system.js

@@ -1,30 +1,44 @@
-import {logicConfig} from '@/logicConfig'
-import layoutMain from '@/Main.vue'
+import { logicConfig } from "@/logicConfig";
+import layoutMain from "@/Main.vue";
 //登录页
-import login from '@/components/frame/login.vue'
+import login from "@/components/frame/login.vue";
 //系统图
-import systemGraph from '@/components/systemGraph'
+import systemGraph from "@/components/systemGraph";
 //系统图编辑页面
-import systemGraphEdit from '@/components/systemGraph/edit'
+import systemGraphEdit from "@/components/systemGraph/edit";
 
-export default [{
-  path: logicConfig.routerNameConfig.loginRouteName,
-  name: '登录页',
-  component: login
-}, {
-  path: '/',
-  name: '首页',
-  component: layoutMain
-}, {
-  path: logicConfig.routerNameConfig.systemGraphName,
-  name: '系统图',
-  component: layoutMain,
-  children: [{
-    path:'/',
-    component: systemGraph
-  }]
-},{
-  path: logicConfig.routerNameConfig.systemGraphEditName,
-  name: '系统图编辑器',
-  component: systemGraphEdit,
-}]
+import facilityLedger from "@/components/ledger/facility/index";
+
+export default [
+  {
+    path: logicConfig.routerNameConfig.loginRouteName,
+    name: "登录页",
+    component: login,
+  },
+  {
+    path: "/",
+    name: "首页",
+    component: layoutMain,
+  },
+  {
+    path: logicConfig.routerNameConfig.systemGraphName,
+    name: "系统图",
+    component: layoutMain,
+    children: [
+      {
+        path: "/",
+        component: systemGraph,
+      },
+      {
+        path: "/ledger/facility",
+        name: "设备台账",
+        component: facilityLedger,
+      },
+    ],
+  },
+  {
+    path: logicConfig.routerNameConfig.systemGraphEditName,
+    name: "系统图编辑器",
+    component: systemGraphEdit,
+  },
+];

+ 7 - 2
src/store/index.js

@@ -1,5 +1,6 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
+import layout from './modules/layout'
 Vue.use(Vuex)
 
 export default new Vuex.Store({
@@ -17,7 +18,9 @@ export default new Vuex.Store({
         //项目信息{id:'',name:'',groupCode:''}
         projects: [],
         //选择的项目信息
-        selectProject: {}
+        selectProject: {},
+        // token
+        ssoToken: ''
     },
     getters: {},
     mutations: {
@@ -89,5 +92,7 @@ export default new Vuex.Store({
         }
     },
     actions: {},
-    modules: {}
+    modules: {
+        layout
+    }
 })

+ 251 - 0
src/store/modules/layout.ts

@@ -0,0 +1,251 @@
+// import {
+//     getAllProject
+//   } from "@/api/scan/request";
+import ScanController from "@/controller/ScanController";
+import { userController } from "@/controller/userController";
+// import {
+//   getUserInfo,getUserInfoByUserId
+// } from "@/api/system/persagy-sso-server";
+import tools from "@/utils/scan/tools";
+// import storage from '@/framework/utils/storage'
+import storage from "@/utils/storageUtil";
+import lStorage from "@/utils/localStorage";
+import store from "@/store";
+
+const KEY_MENU_SELECTED = "menu_selected";
+const KEY_PROJECT_SELECTED = "global_project_selected";
+const KEY_PAGE_BRANDCRUMB = "page_brandcrumb";
+
+export default {
+  namespaced: true,
+  state: {
+    sidebarClosed: false,
+    sidebarSelected: "", // sidebar选中的选项
+    // userInfo: null, //{ username: 'admin' },
+    userInfo: {
+      userName: "yanruolan",
+      userId: "06328a53c69a41bb8f5bb1a552c6e8d6",
+    },
+    permissions: {
+      "system:role:delete": true,
+      "system:role:create": true,
+      "system:role:query": true,
+      "system:role:setOpts": true,
+    },
+    menus: [], //系统菜单列表
+    projectId: "",
+    projectName: "",
+    group_code: "",
+    // projects: project["14"],
+    projects: [],
+    breadcrumb: [],
+    uploaderList: [], //当前上传文件列表
+    secret: "", //项目密码
+    userId: "", //用户id
+    // userId: "06328a53c69a41bb8f5bb1a552c6e8d6", //用户id
+    rowEdit: false, //表格数据变化
+    errorReport: [], //扫楼错误报告
+  },
+  getters: {
+    sidebarClosed: (state) => state.sidebarClosed,
+    secret: (state) => state.secret,
+    userId: (state) => state.userId,
+    sidebarSelected: (state) => {
+      // if (!state.pageSidebarSelected) {
+      //     let menu = storage.get(KEY_MENU_SELECTED)
+      //     if (menu) {
+      //         state.pageSidebarSelected = menu
+      //     }
+      // }
+      // return state.pageSidebarSelected
+      return state.sidebarSelected;
+    },
+    userInfo: (state) => state.userInfo,
+    permissions: (state) => state.permissions,
+    menus: (state) => state.menus,
+    projects: (state) => state.projects,
+    uploaderList: (state) => state.uploaderList,
+    projectId: (state) => {
+      if (!state.projectId) {
+        let pid = storage.get(KEY_PROJECT_SELECTED);
+        if (pid) {
+          state.projectId = pid;
+        } else if (state.projects && state.projects.length) {
+          state.projectId = state.projects[0].id;
+        }
+      }
+      return state.projectId;
+    },
+    projectName: (state) => state.projectName,
+    group_code: (state) => state.group_code,
+    breadcrumb: (state) => {
+      if (!state.breadcrumb) {
+        let arr = storage.get(KEY_PAGE_BRANDCRUMB);
+        if (arr) {
+          state.breadcrumb = arr;
+        }
+      }
+      return state.breadcrumb;
+    },
+  },
+  mutations: {
+    setRowEdit: (state, val) => (state.rowEdit = val),
+    setErrorReport: (state, val) => (state.errorReport = val),
+    setSidebarClosed: (state, val) => (state.sidebarClosed = val),
+    setUserInfo: (state, val) => (state.userInfo = val),
+    setGroupCode: (state, val) => (state.group_code = val),
+    setUserId: (state, val) => (state.userId = val),
+    setSidebarSelected: (state, val) => {
+      state.sidebarSelected = val;
+      storage.set(KEY_MENU_SELECTED, val);
+      lStorage.set("screen_data", {
+        path: val,
+        data: {},
+      });
+    },
+    setProjects: (state, val) => (state.projects = val),
+    setprojectId: (state, val) => {
+      lStorage.remove("cacheInfo"); //待删除(删除用户浏览器无用缓存)
+      let cacheInfo = lStorage.get("historyInfo")
+        ? lStorage.get("historyInfo")
+        : {};
+      state.projectId = val;
+      lStorage.set("projectId", val);
+      if (cacheInfo[state.userInfo.userName]) {
+        // cacheInfo[state.userInfo.userName].projectId = val
+        cacheInfo[state.userInfo.userName] = [
+          ...new Set([val, ...cacheInfo[state.userInfo.userName]]),
+        ].slice(0, 3);
+        lStorage.set("historyInfo", cacheInfo);
+      } else {
+        cacheInfo[state.userInfo.userName] = [val];
+        lStorage.set("historyInfo", cacheInfo);
+      }
+      storage.set(KEY_PROJECT_SELECTED, val);
+      state.projects.map((item) => {
+        if (item.id == val) {
+          state.secret = item.pwd;
+          state.projectName = item.name;
+          state.group_code = item.group_code;
+          lStorage.set("group_code", item.group_code);
+          lStorage.set("secret", item.pwd);
+        }
+      });
+    },
+    setMenus: (state, val) => (state.menus = val),
+    setUploaderList: (state, val) => {
+      state.uploaderList = val ? val : [];
+    },
+  },
+  actions: {
+    setRowEdit(contentx, value) {
+      contentx.commit("setRowEdit", value);
+    },
+    setErrorReport(contentx, value) {
+      contentx.commit("setErrorReport", value);
+    },
+    /**
+     * @info 获取全部项目
+     */
+    getAllProject({ state }) {
+      return new Promise((resolve, reject) => {
+        ScanController.getAllProject(
+          {
+            pageNumber: 1,
+            pageSize: 1000,
+          },
+          (res) => {
+            if (res.result === "success" && res.content && res.content.length) {
+              state.projects = [];
+              // if (res.content[0] && res.content[0].id) {
+              //     state.projectId = res.content[0].id
+              //     state.projectName = res.content[0].localName || res.content[0].name || ""
+              //     state.secret = res.content[0].secret || ""
+              // }
+              res.content.forEach((proj) =>
+                state.projects.push({
+                  id: proj.id,
+                  name: proj.localName || proj.name || "",
+                  pwd: proj.secret || "",
+                  group_code: proj.groupCode || "",
+                })
+              );
+              resolve(res);
+            } else {
+              reject();
+            }
+          }
+        );
+      });
+    },
+    /**
+     * 根据登录返回code获取用户信息和项目信息
+     */
+    loadUserInfo({ state }) {
+      return new Promise(async (resolve, reject) => {
+        /**
+         * 改为调用运维平台的根据用户ID获取用户信息的接口
+         * nh 2021.10.25
+         */
+        let userId = store.state.ssoToken
+          ? store.state.ssoToken
+          : lStorage.get("ssoToken");
+
+        let pd = lStorage.get("ssoPd");
+        const user = new userController();
+        var infoData = await user.getUserInfoById();
+        if (infoData.result === "success") {
+          const data: any = (infoData.content || [])[0] || {};
+          state.userInfo = {
+            userName: data.userName,
+            userId: data.userId,
+          };
+          state.userId = data.userId;
+          state.projects = []; //初始化项目列表
+          storage.set("user_name", data.userName);
+          storage.set("user_id", data.userId);
+          // 获取系统菜单成功
+          if (data.authorizations && data.authorizations.length) {
+            var menuArr = tools.formatMenu(data.authorizations);
+            state.menus = menuArr;
+          } else {
+            state.menus = [];
+          }
+
+          // 获取项目信息成功
+          if (data.projects && data.projects.length) {
+            // 设置项目列表
+            data.projects.forEach((proj) =>
+              state.projects.push({
+                id: proj.projectId,
+                name: proj.projectLocalName,
+                pwd: proj.secret ? proj.secret : "",
+                group_code: proj.groupCode,
+              })
+            );
+          }
+          resolve(infoData);
+        } else {
+          state.userInfo = {
+            userName: "yanruolan",
+            userId: "06328a53c69a41bb8f5bb1a552c6e8d6",
+          };
+          resolve(infoData);
+        }
+        return;
+      });
+    },
+    setBreadcrumb: {
+      root: true,
+      handler({ state, commit }, val) {
+        let label = val[0].label;
+        if (label === "消息中心") {
+          commit("setSidebarSelected", "message"); // 当进入消息中心页面的时候不选中导航栏
+        }
+        state.breadcrumb = [];
+        state.breadcrumb = val;
+        storage.set(KEY_PAGE_BRANDCRUMB, val);
+      },
+    },
+  },
+};

+ 146 - 0
src/utils/handsontable/buildFloorData.js

@@ -0,0 +1,146 @@
+// import { buildingQuery } from '@/api/object/build';
+// import { floorQuery } from '@/api/object/floor';
+// import BuildController from '@/controlls/buildController'
+
+// const buildFloor = {
+//   getData: function (buildFloorData) {
+//     let data, buildParams = {
+//         pageNumber: 1,
+//         pageSize: 1000,
+//         orders: "localName asc",
+//         projection: [
+//             "id",
+//             "localName"
+//         ]
+//     }, floorParams = {
+//         orders: "floorSequenceID desc",
+//         pageNumber: 1,
+//         pageSize: 1000,
+//         projection: [
+//             "buildingId",
+//             "id",
+//             "localName",
+//             "floorSequenceID"
+//         ]
+//     }
+
+//     let promise1 = new Promise((resolve, reject) => {
+//       buildingQuery(buildParams, res => {
+//         resolve(res)
+//       })
+//     })
+//     let promise2 = new Promise((resolve, reject) => {
+//       floorQuery(floorParams, res => {
+//         resolve(res)
+//       })
+//     })
+
+//     Promise.all([promise1, promise2]).then(function(values) {
+//       let builData = values[0].content, floorData = values[1].content
+//       data = builData.map(build => {
+//           return {
+//               value: build.id,
+//               label: build.localName
+//           }
+//       })
+//       data.unshift({
+//         value: "",
+//         label: "未明确建筑"
+//       })
+//       data.forEach(build => {
+//         floorData.forEach(floor => {
+//           if (build.value == floor.buildingId && floor.id && floor.localName) {
+//             if (build.children) {
+//               build.children.push({
+//                 value: floor.id,
+//                 label: floor.localName
+//               })
+//             } else {
+//               build.children = []
+//               build.children.push({
+//                 value: "",
+//                 label: "未明确楼层"
+//               },{
+//                 value: floor.id,
+//                 label: floor.localName 
+//               })
+//             }
+//           }
+//         })
+//       })
+//       data.forEach(item => {
+//         if (item.children && item.children.length) {
+//           item.children.forEach(child => {
+//             if (child.value != "") {
+//               buildFloorData.push({
+//                 Code: item.value + "-" + child.value,
+//                 Name: item.label + "-" + child.label
+//               })
+//             } else {
+//               buildFloorData.push({
+//                 Code: item.value,
+//                 Name: item.label + "-" + child.label
+//               })
+//             }
+//           })
+//         } else {
+//           buildFloorData.push({
+//             Code: item.value,
+//             Name: item.label
+//           })
+//         }
+//       })
+//     })
+//     // buildingQuery(buildParams, res => {
+//     //   let builData = res.Content
+//     //   data = builData.map(build => {
+//     //       return {
+//     //           value: build.BuildID,
+//     //           label: build.BuildLocalName
+//     //       }
+//     //   })
+//     //   data.unshift({
+//     //     value: "",
+//     //     label: "未明确建筑的设备"
+//     //   })
+//     //   floorQuery(floorParams, res => {
+//     //       let floorData = res.Content
+//     //       data.forEach(build => {
+//     //           floorData.forEach(floor => {
+//     //               if (build.value == floor.BuildID && floor.FloorID && floor.FloorLocalName) {
+//     //                   if (build.children) {
+//     //                       build.children.push({
+//     //                           value: floor.FloorID,
+//     //                           label: floor.FloorLocalName
+//     //                       })
+//     //                   } else {
+//     //                       build.children = []
+//     //                       build.children.push({
+//     //                           value: "",
+//     //                           label: "未明确楼层的设备"
+//     //                       })
+//     //                   }
+//     //               }
+//     //           })
+//     //       })
+//     //       data.forEach(item => {
+//     //         if (item.children && item.children.length) {
+//     //           item.children.forEach(child => {
+//     //             buildFloorData.push({
+//     //               Code: item.value + "-" + child.value,
+//     //               Name: item.label + "-" + child.label
+//     //             })
+//     //           })
+//     //         } else {
+//     //           buildFloorData.push({
+//     //             Code: item.value,
+//     //             Name: item.label
+//     //           })
+//     //         }
+//     //       })
+//     //   })
+//     // })
+//   }
+// }
+
+// export default buildFloor

+ 16 - 0
src/utils/handsontable/dataTypeMap.js

@@ -0,0 +1,16 @@
+/**
+ * 枚举数据字典返回的数字类型(dataType)
+ * 
+ * @author haojianlong <haojianlong@sagacloud.cn>
+*/
+const dataTypeMap = {
+  STRING: 'STRING', // 字符串
+  ATTACHMENT: 'ATTACHMENT', // 文件
+  DOUBLE: 'DOUBLE', // 数字 浮点
+  DATETIME: 'DATETIME', //时间
+  ENUM: 'ENUM', // 单选枚举
+  BOOLEAN: 'BOOLEAN', // 布尔
+  MENUM: 'MENUM', // 多选枚举
+  INTEGER: 'INTEGER', // 整数
+}
+export default dataTypeMap

+ 221 - 0
src/utils/handsontable/delType.js

@@ -0,0 +1,221 @@
+import tools from "@/utils/scan/tools"
+let tagsFun = (instance, td, row, col, prop, value, cellProperties) => {
+    if (!!value) {
+        let arr = value || [],
+            dom = ``;
+        arr = arr.sort()
+        arr.map((item, index) => {
+            if (index > 2) {
+
+            } else if (index == 2) {
+                dom += '<span>...</span>'
+            } else {
+                dom += `<span style="display: inline-block;line-height:20px;height: 20px;box-sizing:border-box;padding: 0px 10px;background: #FFF5E4;border: 1px solid #F5A623;border-radius: 100px;font-size: 12px;color: #F5A623;text-align: center;margin: 4px 4px 0 0;">${item}</span>`
+            }
+        })
+        td.innerHTML = dom
+        return td;
+    }
+    return td
+}
+
+let switchRenderer = (instance, td, row, col, prop, value, cellProperties) => {
+    // td.innerHTML = value
+    if (value) {
+        td.innerHTML = `<div role="switch" class="el-switch is-checked" aria-checked="true"><input type="checkbox" name="" true-value="true" class="el-switch__input"><!----><span class="el-switch__core" style="width: 40px; border-color: rgb(19, 206, 102); background-color: rgb(19, 206, 102);"></span><!----></div>`
+    } else {
+        td.innerHTML = `<span class="el-switch__core" style="width: 40px; border-color: #dcdfe6; background-color: #dcdfe6;"></span>`
+    }
+    return td
+}
+
+
+/**
+ *
+ * @param {表头数组} arr
+ * @param {添加的参数} '
+ *
+ * @returns {对应数组} arr
+ */
+
+export function showTypes(arr, infosKey = '') {
+    let data = arr.map(item => {
+        if (item.FirstTag == "控制参数" ||
+            item.FirstTag == "设定参数" ||
+            item.FirstTag == "运行参数") {
+            return undefined
+        }
+        if (item.InfoPointCode == "bimLocation") {
+            return undefined
+        }
+        if (item.Visible) {
+            //固定不显示的code
+            // if (!showTools.cantShow(item.InfoPointCode)) {
+            //     return undefined
+            // }
+
+            if (item.InfoPointCode == "edit") {
+                return {
+                    data: "Infos." + item.InfoPointCode,
+                    renderer: lookQRCode,
+                    readOnly: true
+                }
+            }
+
+            //图片类型
+            if (
+                item.InfoPointCode == "InstallPic" ||
+                item.InfoPointCode == "InstallDrawing" ||
+                item.InfoPointCode == "Nameplate" ||
+                item.InfoPointCode == "Pic" ||
+                item.InfoPointCode == "Drawing"
+            ) {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    // renderer: text.picType,
+                    readOnly: true
+                }
+            }
+
+            //文件类型
+            if (item.InfoPointCode == "InsuranceFile" ||
+                item.InfoPointCode == "Archive" ||
+                item.InfoPointCode == "CheckReport") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    // renderer: text.fileType,
+                    readOnly: true
+                }
+            }
+
+            if (item.InputMode == "D1") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    renderer: tools.customDropdownRenderer,
+                    editor: "chosen",
+                    chosenOptions: {
+                        // multiple: true,//多选
+                        data: item.DataSource || ""
+                    }
+                };
+            } else if (item.InputMode == "A1" || item.InputMode == "A2") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    type: "numeric",
+                    numericFormat: {
+                        pattern: "0,0.00"
+                            // culture: 'de-DE' // use this for EUR (German),
+                            // more cultures available on http://numbrojs.com/languages.html
+                    }
+                };
+            } else if (item.InputMode == "C5") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    type: "date",
+                    dateFormat: "YYYY-MM-DD",
+                    correctFormat: true
+                };
+            } else if (
+                item.InputMode == "B1" ||
+                item.InputMode == "L" ||
+                item.InputMode == "L1" ||
+                item.InputMode == "L2"
+            ) {
+                return {
+                    data: infosKey + item.InfoPointCode
+                };
+            } else if (
+                item.InputMode == "X" ||
+                item.InputMode == "F2"
+                // item.InputMode == "L1" ||
+                // item.InputMode == "L2"
+            ) {
+                //   return undefined
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    readOnly: true
+                };
+            } else if (item.InputMode == "D2") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    // renderer: tools.customDropdownRenderer,
+                    editor: "chosen",
+                    chosenOptions: {
+                        multiple: true, //多选
+                        data: item.DataSource || ""
+                    }
+                };
+            } else if (item.InputMode == "Own") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    // renderer: text.idType,
+                }
+            } else if (item.InputMode == "myOwn") {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    renderer: tagsFun,
+                }
+            } else if (item.InputMode == 'select') {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    renderer: tools.customDropdownRenderer,
+                    editor: "chosen",
+                    chosenOptions: {
+                        // multiple: true,//多选
+                        data: item.DataSource || ""
+                    }
+                }
+            } else if (item.InputMode == 'switchBtn') {
+                return {
+                    data: infosKey + item.InfoPointCode,
+                    renderer: switchRenderer,
+                    readOnly: true
+                }
+            } else {
+                return undefined;
+            }
+        } else {
+            return undefined
+        }
+
+    }).filter(item => item);
+    return data
+}
+
+export function changeHeader(arr) {
+    let data = arr.map(item => {
+        // if (falg) {
+        if (item.FirstTag == "控制参数" ||
+            item.FirstTag == "设定参数" ||
+            item.FirstTag == "运行参数") {
+            return undefined
+        }
+        // }
+
+        if (item.InfoPointCode == "BIMLocation") {
+            return undefined
+        }
+        // if (
+        //     readArr.indexOf(item.InputMode) > -1
+        // ) {
+        if (item.Visible) {
+            if (!item.Unit) {
+                return item.InfoPointName;
+            } else {
+                return item.InfoPointName + "(" + item.Unit + ")";
+            }
+        } else {
+            return undefined
+        }
+        // } else {
+        //     return undefined;
+        // }
+    }).filter(d => d);
+    return data
+}
+let lookQRCode = (instance, td, row, col, prop, value, cellProperties) => {
+    td.style.color = "#409EFF";
+    td.style.cursor = "pointer";
+    td.innerHTML = "编辑"
+    return td
+}

+ 36 - 0
src/utils/handsontable/fillterField.js

@@ -0,0 +1,36 @@
+const data = {
+  equipment: { //设备
+    onlyRead: [],
+    edit: []
+  },
+  tenant: { //租户
+    onlyRead: [],
+    edit: []
+  },
+  shaft: { //竖井
+    onlyRead: [],
+    edit: []
+  },
+  parts: { //部件
+    onlyRead: [],
+    edit: []
+  },
+  property:{ //资产
+    onlyRead: [],
+    edit: []
+  },
+  system:{ //系统
+    onlyRead: [],
+    edit: []
+  },
+  space:{//业务空间
+    onlyRead: [
+      "outline"
+    ],
+    edit: [
+      "outline"
+    ]
+  }
+}
+
+export default data

+ 160 - 0
src/utils/handsontable/mainText.js

@@ -0,0 +1,160 @@
+const text = {
+    // 只读模式 or 编辑模式
+    readOnly: false,
+    //图片类型
+    picType: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (value instanceof Array && value.length > 0) {
+            let i = 0
+            value.map(item => {
+                // if (item.type == "image" || item.type == "video") {
+                    i++
+                // }
+            })
+            td.innerHTML = "已上传:" + i;
+        } else {
+            td.innerHTML = text.readOnly?'':'点击上传'
+        }
+        return td;
+    },
+    // 文件类型
+    fileType: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (value instanceof Array && value.length > 0) {
+            td.innerHTML = "已上传:" + value.length;
+        } else {
+            td.innerHTML = text.readOnly?'':'点击上传'
+        }
+        return td;
+    },
+    //系统类型
+    systemList: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (value instanceof Array && value.length > 0) {
+            if (value.length == 1) {
+                td.innerHTML = (value[0].localName || value[0].name)? (value[0].localName || value[0].name) : (value[0].infos.localName || value[0].infos.name || "")
+            } else {
+                let text = ""
+                for (let i = 0; i < value.length; i++) {
+                    if (!!value[i].localName || !!value[i].name) {
+                        if (i == value.length) {
+                            text += value[i].localName || value[i].name
+                        } else {
+                            text = value[i].localName || value[i].name + "、" + text
+                        }
+                    } else {
+                        if (i == value.length) {
+                            text += value[i].infos.localName || value[i].infos.name
+                        } else {
+                            text = value[i].infos.localName || value[i].infos.name + "、" + text
+                        }
+                    }
+                }
+                td.innerHTML = text.substring(0, 40) + "..."
+            }
+        } else {
+            td.innerHTML = "无关联系统"
+        }
+        return td;
+    },
+    //建筑类型
+    buildingList: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (value instanceof Array && value.length > 0) {
+            if (value.length == 1) {
+                td.innerHTML = (value[0].localName || value[0].name)? (value[0].localName || value[0].name) : (value[0].infos.localName || value[0].infos.name || "")
+            } else {
+                let text = ""
+                for (let i = 0; i < value.length; i++) {
+                    if (!!value[i].localName || !!value[i].name) {
+                        if (i == value.length) {
+                            text += value[i].localName || value[i].name
+                        } else {
+                            text = value[i].localName || value[i].name + "、" + text
+                        }
+                    } else {
+                        if (i == value.length) {
+                            text += value[i].infos.localName || value[i].infos.name
+                        } else {
+                            text = value[i].infos.localName || value[i].infos.name + "、" + text
+                        }
+                    }
+                }
+                td.innerHTML = text.substring(0, 40) + "..."
+            }
+        } else {
+            td.innerHTML = "无所属建筑"
+        }
+        return td;
+    },
+    //四大厂商
+    idType: (instance, td, row, col, prop, value, cellProperties) => {
+        let html = ''
+        let Manufacturer = instance.getDataAtRowProp(row,'infos.manufacturer') || '空',
+            Brand = instance.getDataAtRowProp(row,'infos.brand') || '空',
+            Specification = instance.getDataAtRowProp(row,'infos.specification') || '空';
+        switch (prop){
+            case 'dpManufacturerId':
+                html = Manufacturer + '/' + Brand + '/' + Specification
+                break;
+            case 'dpSupplierId':
+                html = instance.getDataAtRowProp(row,'infos.supplier')
+                break;
+            case 'dpMaintainerId':
+                html = instance.getDataAtRowProp(row,'infos.maintainer')
+                break;
+            case 'dpInsurerId':
+                html = instance.getDataAtRowProp(row,'infos.insurer')
+                break;
+            default:
+                break;
+        }
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (!!value) {
+            // let data = value.split("-")[1] || "空名"
+            td.innerHTML = html
+        } else {
+            td.innerHTML = "点击选择"
+        }
+        return td
+    },
+
+    //查看二维码
+    lookQRCode: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        td.innerHTML = "查看二维码"
+        return td
+    },
+
+    //系统所属建筑楼层
+    sysInBuildFloor: (instance, td, row, col, prop, value, cellProperties) => {
+        td.style.color = "#409EFF";
+        td.style.cursor = "pointer";
+        if (value instanceof Array && value.length > 0) {
+            let text = ""
+            for (let i = 0; i < value.length; i++) {
+                if(value[i].BuildID && value[i].FloorID){
+                    text += `${value[i].BuildLocalName || value[i].BuildName}-${value[i].FloorLocalName || value[i].FloorName }、`
+                } else {
+                    text += `${value[i].BuildLocalName || value[i].BuildName}、`
+                }
+            }
+            text = text.substring(0,text.length-1);
+            if(text.length>15){
+                text = text.substring(0,15)+ "...";
+            }
+            td.innerHTML = text;
+        } else {
+            td.innerHTML = "无所属建筑楼层"
+        }
+        return td;
+    },
+}
+
+export default text

+ 592 - 0
src/utils/handsontable/notShow.js

@@ -0,0 +1,592 @@
+// 不显示的信息点数组
+import text from "@/utils/handsontable/mainText"
+import tools from "@/utils/scan/tools"
+import fieldData from "@/utils/handsontable/fillterField"
+import dataTypeMap from "./dataTypeMap"
+
+//在编辑模式下并且勾选隐藏自动填充的信息点不显示的字段
+let noShowArr = [
+  "specification",
+  "serviceLife"
+]
+//在编辑模式下不显示的字段
+let cantShow = [
+  "EquipQRCode",
+  "EquipID",
+  "EquipName",
+  "BIMLocation",
+  "Brand",
+  "Specification",
+  "Manufacturer",
+  "Supplier",
+  "SupplierContactor",
+  "SupplierPhone",
+  "SupplierEmail",
+  "SupplierWeb",
+  "SupplierFax",
+  "Maintainer",
+  "MaintainerContactor",
+  "MaintainerPhone",
+  "MaintainerEmail",
+  "MaintainerWeb",
+  "Principal",
+  "MaintainerFax",
+  "Insurer",
+  "InsurerContactor",
+  "InsurerPhone",
+  "InsurerEmail",
+  "InsurerWeb",
+  "InsurerFax",
+  "InsuranceFile",
+  "EquipID",
+  "EquipName",
+  "SpaceCount",
+  "SpaceList",
+  "TenantID",
+  "ShaftID"
+]
+
+//台账编辑页面不显示的厂商信息
+let firmArr = [
+  "brand", //品牌
+  "specification", //设备型号
+  "manufacturer", //生产厂家
+  "supplier", //供应商单位名称
+  "supplierContactor", //供应商联系人
+  "supplierPhone", //供应商联系电话
+  "supplierEmail", //供应商电子邮件
+  "supplierWeb", //供应商网址
+  "supplierFax", //供应商传真
+  "maintainer", //维修商单位名称
+  "maintainerContactor", //维修商联系人
+  "maintainerPhone", //维修商联系电话
+  "maintainerEmail", //维修商电子邮件
+  "maintainerWeb", //维修商网址
+  "maintainerFax", //维修商传真
+  "insurer", //保险公司名称
+  "insurerContactor", //保险公司联系人
+  "insurerPhone", //保险公司联系电话
+  'insurerEmail', //保险公司电子邮件
+  "insurerWeb", //保险公司网址
+  "insurerFax", //保险公司传真
+  // "dpManufacturerId",//品牌型号Id
+  // "dpSupplierId",//供应商信息Id
+  // "dpMaintainerId",//维修商信息Id
+  // "dpInsurerId"//保险公司信息Id
+]
+
+// 将映射表枚举值转为数组
+const mapToArr = () => {
+  const arr = []
+  for (let key in dataTypeMap) {
+    arr.push(dataTypeMap[key])
+  }
+  return arr;
+}
+const showTools = {
+  inputModeArr: mapToArr(),
+  cantShow: (code) => {
+    let falg = true
+    cantShow.map(item => {
+      if (item == code) {
+        falg = false
+      }
+    })
+    return falg
+  },
+  fixedNoShowField: (noShowList, code) => {
+    let flag = true
+    noShowList.map(item => {
+      if (item == code) {
+        flag = false
+      }
+    })
+    return flag
+  },
+  isShow: (code) => {
+    let falg = true
+    noShowArr.map(item => {
+      if (item == code) {
+        falg = false
+      }
+    })
+    return falg
+  },
+  arrToArr(arr, showType) {
+    let first = 0,
+      scound = 0,
+      three = 0,
+      four = 0
+    arr.find(function (value, index, arr) {
+      let flag = (showType != "Visible" || value.visible)
+      if (
+        ((value.code == "brand" && flag) ||
+          (value.code == "specification" && flag) ||
+          (value.code == "manufacturer" && flag)) && !first
+      ) {
+        first = index
+      }
+      if (
+        ((value.code == "supplier" && flag) ||
+          (value.code == "supplierContactor" && flag) ||
+          (value.code == "supplierEmail" && flag) ||
+          (value.code == "supplierWeb" && flag) ||
+          (value.code == "supplierFax" && flag) ||
+          (value.code == "supplierPhone" && flag)) && !scound
+      ) {
+        scound = index
+      }
+      if (
+        ((value.code == "maintainer" && flag) ||
+          (value.code == "maintainerContactor" && flag) ||
+          (value.code == "maintainerPhone" && flag) ||
+          (value.code == "maintainerEmail" && flag) ||
+          (value.code == "maintainerWeb" && flag) ||
+          (value.code == "maintainerFax" && flag)) && !three
+      ) {
+        three = index
+      }
+      if (
+        ((value.code == "insurer" && flag) ||
+          (value.code == "insurerContactor" && flag) ||
+          (value.code == "insurerPhone" && flag) ||
+          (value.code == "insurerEmail" && flag) ||
+          (value.code == "insurerWeb" && flag) ||
+          (value.code == "insurerFax" && flag)) && !four
+      ) {
+        four = index
+      }
+    })
+    let numList = [first, scound, three, four]
+    numList.reverse().map((item, index) => {
+      if (item) {
+        if (index == 0) {
+          arr.splice(item, 0, {
+            category: 'STATIC',
+            dataType: "STRING",
+            firstName: "基本信息",
+            aliasCode: "dpInsurerId",
+            aliasName: "保险公司信息",
+            name: "保险公司信息",
+            code: "dpInsurerId",
+            origCode: "dpInsurerId",
+            origDataType: "Str",
+            path: "dpInsurerId",
+            priority: "S",
+            editable: true,
+            visible: true
+          })
+        } else if (index == 1) {
+          arr.splice(item, 0, {
+            category: 'STATIC',
+            dataType: "STRING",
+            firstName: "基本信息",
+            aliasCode: "dpMaintainerId",
+            aliasName: "维修商信息",
+            name: "维修商信息",
+            code: "dpMaintainerId",
+            origCode: "dpMaintainerId",
+            origDataType: "Str",
+            path: "dpMaintainerId",
+            priority: "S",
+            editable: true,
+            visible: true
+          })
+        } else if (index == 2) {
+          arr.splice(item, 0, {
+            category: 'STATIC',
+            dataType: "STRING",
+            firstName: "基本信息",
+            aliasCode: "dpSupplierId",
+            aliasName: "供应商信息",
+            name: "供应商信息",
+            code: "dpSupplierId",
+            origCode: "dpSupplierId",
+            origDataType: "Str",
+            path: "dpSupplierId",
+            priority: "S",
+            editable: true,
+            visible: true
+          })
+        } else if (index == 3) {
+          arr.splice(item, 0, {
+            category: 'STATIC',
+            dataType: "STRING",
+            firstName: "基本信息",
+            aliasCode: "dpManufacturerId",
+            aliasName: "生产厂家/品牌/型号",
+            name: "生产厂家/品牌/型号",
+            code: "dpManufacturerId",
+            origCode: "dpManufacturerId",
+            origDataType: "Str",
+            path: "dpManufacturerId",
+            priority: "S",
+            editable: true,
+            visible: true
+          })
+        }
+      }
+    })
+    return arr
+  },
+  /**
+   *
+   * @param {*} arr 原始表头数组
+   * @param {*} type 对应表格的模块类型
+   * @param {*} onlyRead 是否只读
+   * @param {*} showType 查看类型(全部;只看要采集的信息;隐藏部分信息)
+   * @param {*} taizhang 是否是台账类型(默认为false)
+   *
+   */
+  headerTextFilter(arr, type, onlyRead, showType, taizhang = false) {
+    // if (taizhang && !onlyRead) {
+    //   arr = this.arrToArr(arr, showType)
+    // }
+    let data = arr.map(item => {
+      // if (type == "property" && item.firstTag == "RunParam") { //资产台账不显示运行参数
+      //     return undefined
+      // }
+      if (onlyRead) { //只读模式
+        if (!this.filterUnshow(onlyRead, type, item.code)) { //过滤固定不显示字段
+          return undefined
+        }
+        if (showType == "Visible" && item.visible) { //只看要采集的信息
+          return this.isUnit(item)
+        } else if (showType == "all") { //显示全部
+          return this.isUnit(item)
+        } else {
+          return undefined
+        }
+      } else { //编辑模式
+        // if (taizhang && !this.filterFirm(item.code)) {
+        //   return undefined
+        // }
+        if (!this.filterUnshow(onlyRead, type, item.code)) { //过滤固定不显示字段
+          return undefined
+        }
+        if (showType == "Visible" && item.visible) { //只看要采集的信息
+          return this.isUnit(item)
+        } else if (showType == "all") { //显示全部
+          return this.isUnit(item)
+        } else if (showType == "partInfo" && item.visible && this.isShow(item.code)) { //隐藏部分厂家信息(***需维护不显示列表***)
+          // if (item.FirstName == "控制参数" || item.FirstName == "设定参数" || item.FirstName == "运行参数") {
+          if (item.firstTag == "techParam") { //技术参数
+            return undefined
+          } else {
+            return this.isUnit(item)
+          }
+        } else {
+          return undefined
+        }
+
+      }
+    }).filter(d => d)
+    return data
+  },
+  headerTypeFilter(arr, type, onlyRead, showType, taizhang = false) {
+    // if (taizhang && !onlyRead) {
+    //   arr = this.arrToArr(arr, showType)
+    // }
+    text.readOnly = onlyRead;
+    let data = arr.map(item => {
+      // if (type == "property" && item.firstTag == "runParam") { //资产台账不显示运行参数
+      //     return undefined
+      // }
+      if (onlyRead) { //只读模式
+        if (!this.filterUnshow(onlyRead, type, item.code)) { //过滤固定不显示字段
+          return undefined
+        }
+        if (showType == "Visible" && item.visible) { //只看要采集的信息
+          return this.textFormat(item, onlyRead)
+        } else if (showType == "all") { //显示全部
+          return this.textFormat(item, onlyRead)
+        } else {
+          return undefined
+        }
+      } else { //编辑模式
+        // if (taizhang && !this.filterFirm(item.code)) {
+        //   return undefined
+        // }
+        if (!this.filterUnshow(onlyRead, type, item.code)) { //过滤固定不显示字段
+          return undefined
+        }
+        if (showType == "Visible" && item.visible) { //只看要采集的信息
+          return this.inputModeFilter(item, onlyRead)
+        } else if (showType == "all") { //显示全部
+          return this.inputModeFilter(item, onlyRead)
+        } else if (showType == "partInfo" && item.visible && this.isShow(item.code)) { //隐藏部分厂家信息(***需维护不显示列表***)
+          // if (item.FirstName == "控制参数" || item.FirstName == "设定参数" || item.FirstName == "运行参数") {
+          if (item.firstTag == "techParam") { //技术参数
+            return undefined
+          } else {
+            return this.inputModeFilter(item, onlyRead)
+          }
+        } else {
+          return undefined
+        }
+      }
+    }).filter(d => d)
+    return data
+  },
+  isUnit(item) {
+    if (!item.unit || item.unit == "") {
+      return item.name;
+    } else {
+      return item.name + "(" + item.unit + ")";
+    }
+  },
+  textFormat(item, onlyRead) {
+    if (
+      // item.code == "EquipQRCode" ||
+      // item.code == "RoomQRCode"
+      item.code == "defaultQRCode"
+    ) {
+      return {
+        data: item.path,
+        renderer: text.lookQRCode,
+        readOnly: onlyRead
+      }
+    }
+
+    //图片类型
+    if (
+      item.code == "installPic" ||
+      item.code == "nameplate" ||
+      item.code == "systemChart" ||
+      item.code == "pic"
+    ) {
+      return {
+        data: item.path,
+        renderer: text.picType,
+        readOnly: onlyRead
+      }
+    }
+    //文件类型
+    if (item.code == "insuranceFile" ||
+      item.code == "archive" ||
+      item.code == "checkReport" ||
+      item.code == "maintainManual" ||
+      item.code == "approachingAcceptance" ||
+      item.code == "acceptanceReport" ||
+      item.code == "operationManual" ||
+      item.code == "originalCertificate" ||
+      item.code == "testReport" ||
+      item.code == "productCertification" ||
+      item.code == "installInstruction" ||
+      item.code == "supplierContract" ||
+      item.code == "drawing" ||
+      item.code == "installDrawing" ||
+      item.code == "designIDGraph" ||
+      item.code == "fanCharacterCurve"
+    ) {
+      return {
+        data: item.path,
+        renderer: text.fileType,
+        readOnly: onlyRead
+      }
+    }
+    if (item.category == 'STATIC') {
+      if ((item.dataType == dataTypeMap.ENUM && !item.multiple) || (item.dataType == dataTypeMap.BOOLEAN && !item.multiple)) { //单选输入(单数)
+        return {
+          data: item.path,
+          renderer: tools.customDropdownRenderer,
+          editor: "chosen",
+          readOnly: onlyRead,
+          chosenOptions: {
+            data: item.dataSource ? tools.formatDataSource(item.dataSource) : ""
+          }
+        };
+      } else if ((item.dataType == dataTypeMap.MENUM) || (item.dataType == dataTypeMap.ENUM && item.multiple) || (item.dataType == dataTypeMap.BOOLEAN && item.multiple)) { //多选输入(多选枚举,单选枚举复数)
+        return {
+          data: item.path,
+          renderer: tools.multipleDropdownRenderer,
+          readOnly: onlyRead,
+          chosenOptions: item.dataSource ? tools.formatDataSource(item.dataSource) : ""
+        };
+      } else if (item.dataType == dataTypeMap.DOUBLE || item.dataType == dataTypeMap.INTEGER) { // 数字输入
+        return {
+          data: item.path,
+          type: "numeric",
+          readOnly: onlyRead,
+          numericFormat: {
+            pattern: "0,0.00"
+          }
+        };
+      } else if (item.dataType == dataTypeMap.DATETIME) { // 日期输入
+        return {
+          data: item.path,
+          type: "date",
+          dateFormat: "YYYYMMDD",
+          readOnly: onlyRead,
+          correctFormat: true
+        };
+      } else if (item.dataType == dataTypeMap.STRING) { // 文本输入
+        return {
+          data: item.path,
+          readOnly: onlyRead
+        }
+      } else { //(未支持的输入方式)暂不支持编辑
+        return {
+          data: item.path,
+          readOnly: onlyRead
+        }
+      }
+    } else { // 动态信息点
+      return {
+        data: item.path,
+        readOnly: onlyRead
+      }
+    }
+  },
+  inputModeFilter(item, onlyRead) {
+    if (
+      // item.code == "EquipQRCode" ||
+      // item.code == "RoomQRCode"
+      item.code == "defaultQRCode"
+    ) {
+      return {
+        data: item.path,
+        renderer: text.lookQRCode,
+        readOnly: onlyRead
+      }
+    }
+
+    //图片类型
+    if (
+      item.code == "installPic" ||
+      item.code == "nameplate" ||
+      item.code == "systemChart" ||
+      item.code == "pic"
+    ) {
+      return {
+        data: item.path,
+        renderer: text.picType,
+        readOnly: onlyRead
+      }
+    }
+
+    //文件类型
+    if (item.code == "insuranceFile" ||
+      item.code == "archive" ||
+      item.code == "checkReport" ||
+      item.code == "maintainManual" ||
+      item.code == "approachingAcceptance" ||
+      item.code == "acceptanceReport" ||
+      item.code == "operationManual" ||
+      item.code == "originalCertificate" ||
+      item.code == "testReport" ||
+      item.code == "productCertification" ||
+      item.code == "installInstruction" ||
+      item.code == "supplierContract" ||
+      item.code == "drawing" ||
+      item.code == "installDrawing" ||
+      item.code == "designIDGraph" ||
+      item.code == "fanCharacterCurve"
+    ) {
+      return {
+        data: item.path,
+        renderer: text.fileType,
+        readOnly: onlyRead
+      }
+    }
+
+    //四大厂商
+    // if (
+    //   item.code == "dpSupplierId" ||
+    //   item.code == "dpMaintainerId" ||
+    //   item.code == "dpInsurerId" ||
+    //   item.code == "dpManufacturerId"
+    // ) {
+    //   return {
+    //     data: item.path,
+    //     renderer: text.idType,
+    //     readOnly: onlyRead
+    //   }
+    // }
+    if (!item.category) {
+      console.log('新版字典无输入类型', item)
+    }
+    if (item.category == 'STATIC') {
+      if ((item.dataType == dataTypeMap.ENUM && !item.multiple) || (item.dataType == dataTypeMap.BOOLEAN && !item.multiple)) { //单选输入(单数)
+        return {
+          data: item.path,
+          renderer: tools.customDropdownRenderer,
+          editor: "chosen",
+          readOnly: onlyRead,
+          chosenOptions: {
+            data: item.dataSource ? tools.formatDataSource(item.dataSource) : ""
+          }
+        };
+      } else if ((item.dataType == dataTypeMap.MENUM) || (item.dataType == dataTypeMap.ENUM && item.multiple) || (item.dataType == dataTypeMap.BOOLEAN && item.multiple)) { //多选输入(多选枚举,单选枚举复数)
+        return {
+          data: item.path,
+          renderer: tools.multipleDropdownRenderer,
+          readOnly: onlyRead,
+          chosenOptions: item.dataSource ? tools.formatDataSource(item.dataSource) : ""
+        };
+      } else if (item.dataType == dataTypeMap.DOUBLE || item.dataType == dataTypeMap.INTEGER) { // 数字输入
+        return {
+          data: item.path,
+          type: "numeric",
+          readOnly: onlyRead,
+          numericFormat: {
+            pattern: "0,0.00"
+          }
+        };
+      } else if (item.dataType == dataTypeMap.DATETIME) { // 日期输入
+        return {
+          data: item.path,
+          type: "date",
+          dateFormat: item.formater || "YYYYMMDD",
+          readOnly: onlyRead,
+          correctFormat: true
+        };
+      } else if (item.dataType == dataTypeMap.STRING) { // 文本输入
+        return {
+          data: item.path,
+          readOnly: onlyRead
+        }
+      } else { // (未支持的输入方式)暂不支持编辑
+        return {
+          data: item.path,
+          readOnly: onlyRead
+        }
+      }
+    } else { // 动态信息点
+      return {
+        data: item.path,
+        readOnly: onlyRead
+      }
+    }
+  },
+  filterUnshow: (onlyRead, type, code) => {
+    let falg = true,
+      data = fieldData[type]
+    if (onlyRead) {
+      data.onlyRead.map(item => {
+        if (item == code) {
+          falg = false
+        }
+      })
+      return falg
+    } else {
+      data.edit.map(item => {
+        if (item == code) {
+          falg = false
+        }
+      })
+      return falg
+    }
+  },
+  filterFirm: (code) => {
+    let falg = true
+    firmArr.map(item => {
+      if (item == code) {
+        falg = false
+      }
+    })
+    return falg
+  }
+}
+
+export default showTools

+ 78 - 0
src/utils/hasontableUtils.js

@@ -0,0 +1,78 @@
+const handsonUtils = {
+    /**
+     * 获取被排序后的数组
+     *
+     * @param changeData 发生改变的数据
+     * @param source     数组
+     *
+     * @return array     经过排序后或者经过搜索后的数组
+     */
+    getParam: function(changeData, source, hot, trimmedArr) {
+        function arrayUnique(arr, name){ //去重
+            var hash = {};
+            return arr.reduce(function(item, next) {
+                hash[next[name]] ? '' : hash[next[name]] = true && item.push(next);
+                return item;
+            }, []);
+        }
+        let newData = arrayUnique(changeData, 0)
+        let param = "";
+        //被筛选过后的数组
+        // let trimmedArr = this.trimmedRows();
+        //是否启用了排序
+        let isSort = hot.getPlugin("columnSorting").isSorted();
+        if (trimmedArr.length && isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            param = newData.map(item => {
+                return hot.getSourceDataAtRow(trimmedArr[sortArr[item[0]]]);
+            });
+        } else if (isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            param = newData.map(item => {
+                return hot.getSourceDataAtRow(sortArr[item[0]]);
+            });
+        } else if (trimmedArr.length) {
+            param = newData.map(item => {
+                return hot.getSourceDataAtRow(trimmedArr[item[0]]);
+            });
+        } else {
+            param = newData.map(item => {
+                return hot.getSourceDataAtRow(item[0]);
+            });
+        }
+        return param;
+    },
+
+    /**
+     * 
+     * @param {handsontable修改参数} changeData 
+     * @param {*} source 
+     * @param {handsontabele实例} hot 
+     * @param {排序数组} trimmedArr
+     * 
+     * @return 修改数值的前一个对象 
+     */
+    getUnshiftParam: function(changeData, source, hot, trimmedArr) {
+        //是否启用了排序
+        let isSort = hot.getPlugin("columnSorting").isSorted();
+        if (trimmedArr.length && isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            return hot.getSourceDataAtRow(trimmedArr[sortArr[changeData[0][0] - 1]])
+        } else if (isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            return hot.getSourceDataAtRow(sortArr[changeData[0][0] - 1])
+        } else if (trimmedArr.length) {
+            //进行了筛选
+            return hot.getSourceDataAtRow(trimmedArr[changeData[0][0] - 1])
+        } else {
+            //没有进行排序和筛选
+            return hot.getSourceDataAtRow(changeData[0][0] - 1);
+        }
+    },
+}
+
+export default handsonUtils

+ 52 - 48
src/utils/http/httpUtils.ts

@@ -3,59 +3,63 @@
  * nh 2021.12.23
  */
 
-import { axiosUtils } from "./axiosUtils"
+import { axiosUtils } from "./axiosUtils";
 import { toolUtils } from "../toolUtils";
 
 export class httpUtils extends axiosUtils {
-    protected constructor(baseUrl: string) {
-        super();
-        this.baseUrl = baseUrl;
-    };
+  protected constructor(baseUrl: string) {
+    super();
+    this.baseUrl = baseUrl;
+  }
 
+  //根域名地址
+  private _baseUrl = "";
+  private set baseUrl(val: string) {
+    this._baseUrl = val;
+  }
+  private get baseUrl() {
+    return this._baseUrl;
+  }
 
-    //根域名地址
-    private _baseUrl = '';
-    private set baseUrl(val: string) {
-        this._baseUrl = val;
-    }
-    private get baseUrl() {
-        return this._baseUrl;
-    }
+  private async send(url: string, data: any, superFnName: string) {
+    var newUrl = toolUtils.getBaseHttpUrl(this.baseUrl, url);
+    return await super[superFnName](newUrl, data);
+  }
 
-    private async send(url: string, data: any, superFnName: string) {
-        var newUrl = toolUtils.getBaseHttpUrl(this.baseUrl, url);
-        return await super[superFnName](newUrl, data);
-    };
+  /**
+   * get请求
+   * @param url
+   * @param data
+   * @returns
+   */
+  public async getRequest(url: string, data: any) {
+    return await this.send(url, data, "getRequest");
+  }
 
-    /**
-     * get请求
-     * @param url 
-     * @param data 
-     * @returns 
-     */
-    public async getRequest(url: string, data: any) {
-        return await this.send(url, data, 'getRequest');
-    };
+  /**
+   * post请求
+   * @param url
+   * @param data
+   * @returns
+   */
+  public async postRequest(url: string, data: any) {
+    return await this.send(url, data, "postRequest");
+  }
 
-    /**
-     * post请求
-     * @param url 
-     * @param data 
-     * @returns 
-     */
-    public async postRequest(url: string, data: any) {
-        return await this.send(url, data, 'postRequest');
-    };
-
-    /**
-     * 自定义请求
-     * @param url 
-     * @param headers 
-     * @param data 
-     * @param method get | post  默认post
-     * @returns 
-     */
-    protected async customRequest(url: string, headers: any, data: any, method: string) {
-        return await super.customRequest(url, headers, data, method);
-    }
-}
+  /**
+   * 自定义请求
+   * @param url
+   * @param headers
+   * @param data
+   * @param method get | post  默认post
+   * @returns
+   */
+  protected async customRequest(
+    url: string,
+    headers: any,
+    data: any,
+    method: string
+  ) {
+    return await super.customRequest(url, headers, data, method);
+  }
+}

+ 33 - 0
src/utils/localStorage.js

@@ -0,0 +1,33 @@
+const PREFIX = '_sagacloud_admin_store_'
+const loaclStorage = window.localStorage
+
+export default {
+    set(key, value, fn) {
+        let _value = null
+        try {
+            _value = JSON.stringify(value)
+        } catch (e) {
+            _value = value
+        }
+        loaclStorage.setItem(PREFIX + key, _value)
+        fn && fn()
+    },
+    get(key, fn) {
+        if (!key) {
+            return null
+        }
+        if (typeof key === 'object') {
+            throw new Error('key不能是一个对象。')
+        }
+        var _value = loaclStorage.getItem(PREFIX + key)
+        if (_value !== null) {
+            try {
+                return JSON.parse(_value)
+            } catch (e) {}
+        }
+        return _value
+    },
+    remove(key) {
+        loaclStorage.removeItem(PREFIX + key)
+    }
+}

+ 43 - 0
src/utils/scan/cutHeader.js

@@ -0,0 +1,43 @@
+//处理头部函数
+export default function cutHeader(arr) {
+    let first = {}
+        //一级循环出来一级标签
+    arr.map(item => {
+            if (!!first[item.FirstTag] && first[item.FirstTag].length) {} else {
+                first[item.FirstTag] = []
+            }
+            first[item.FirstTag].push(item)
+        })
+        // 循环出第二级标签
+    let sound = []
+    for (let key in first) {
+        let obj = {
+            FirstTag: key,
+            details: {}
+        }
+        first[key].map(item => {
+            if (!!obj.details[item.SecondTag] && obj.details[item.SecondTag].length) {
+
+            } else {
+                obj.details[item.SecondTag] = []
+            }
+            obj.details[item.SecondTag].push(item)
+        })
+        sound.push(obj)
+    }
+    // 循环出制定的数据结构
+    let newArr = sound.map(item => {
+        let copyarr = Object.assign(item.details, {})
+        for (let k in item.details) {
+            if (item.details instanceof Array) {} else {
+                item.details = []
+            }
+            item.details.push({
+                SecondTag: k,
+                details: copyarr[k]
+            })
+        }
+        return item
+    })
+    return newArr
+}

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


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