소스 검색

增加关系总览页面

qule 3 년 전
부모
커밋
0cd463174a

+ 1 - 1
public/systemConf.js

@@ -41,7 +41,7 @@ var __systemConf = {
       "id": "CADtuzhiguanli",
       "name": "CAD核查图纸管理",
       "orders": 7,
-      "url": "/systemGraph11",
+      "url": "/deliver/cadDrawingManage",
       "icon": "icon-topology"
     }]
   }, {

+ 24 - 0
src/components/cadDrawingManage/index.vue

@@ -0,0 +1,24 @@
+<!--
+ * @Author: ql
+ * @Date: 2022-01-11 14:46:04
+ * @LastEditTime: 2022-01-11 17:32:34
+ * @LastEditors: Please set LastEditors
+ * @FilePath: \adm-frontend\src\components\cadDrawingManage\index.vue
+-->
+<template>
+  <div>
+      <div>
+        
+      </div>
+  </div>
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style>
+
+</style>

+ 536 - 0
src/components/old-adm/relation/components/overview/CardList.vue

@@ -0,0 +1,536 @@
+<template>
+  <div>
+    <div
+      :key="index"
+      v-for="(item,index) in content"
+    >
+      <p class="slave-relation-title">{{ item.graphTypeName }}
+        <span>(主要连接对象按照标准字典显示)</span>
+      </p>
+      <section
+        :key="child.graphTypeId"
+        class="container"
+        v-for="(child,childIndex) in item.childGraphicTypeList"
+      >
+        <p class="relation-text">
+          <span class="iconfont icon-juxing"></span>
+          <span @click="toDetail(child)" style="cursor:pointer;">
+            {{ child.graphTypeName }}
+            <i class="icon-zuzhiguanxi iconfont"/></span>
+          <span class="pic-code">图类型编码:{{ child.graphTypeCode }}</span>
+          <el-tooltip
+            v-if="child.Note"
+            :content="child.Note"
+            placement="top">
+            <i
+              @click="explain"
+              class="icon-shuoming iconfont"
+            />
+          </el-tooltip>
+        </p>
+
+        <el-row :gutter="24">
+          <el-col
+            :key="relation.Id"
+            :span="8"
+            v-for="(relation,relIndex) in child.relationTypeProjectList"
+          >
+            <el-card
+              class="card "
+              shadow="hover"
+              style="position: relative;"
+
+            >
+              <!-- border:none-->
+              <!--              <div v-show="relation.cardDisabled || relation.ComputationalState === 3 " class="mask"></div>-->
+              <div v-show="relation.computationalState === 3 " class="mask"></div>
+              <div style="overflow: hidden;">
+                <el-tooltip
+                  :content="relation.relationTypeName"
+                  placement="top"
+                >
+                  <p class="relation-title reset-test reset-title">{{ relation.relationTypeName }}</p>
+                </el-tooltip>
+                <el-tooltip
+                  :content="relation.relationTypeCode"
+                  placement="top"
+                >
+                  <p class="asc reset-title reset-test">边类型编码:{{ relation.relationTypeCode }}</p>
+                </el-tooltip>
+                <p class="relation-title-icon reset-test fr">
+                  <el-tooltip
+                    v-if="relation.note"
+                    :content="relation.note"
+                    placement="top"
+                    style="z-index: 3;position:relative;"
+                  >
+                    <i class="iconfont icon-warn icon"/>
+                  </el-tooltip>
+                </p>
+              </div>
+              <article>
+                <el-row>
+                  <el-col :span="13">
+                    <div class="grid-content">
+                      <p class="object">主要连接对象</p>
+                      <el-tooltip
+                        :content="relation.conneObject"
+                        placement="top"
+                      >
+                        <p class="group reset-title">{{ relation.conneObject }}</p>
+                      </el-tooltip>
+                    </div>
+                  </el-col>
+                  <el-col :span="2">
+                    <div class="grid-content">
+                      <p class="thread"></p>
+                    </div>
+                  </el-col>
+                  <el-col :span="9">
+                    <div class="grid-content ">
+                      <p class="line-number">连接数量</p>
+                      <p :class="relation.count > 0? 'line-number-show' :'line-number-hide'">{{ relation.count }}</p>
+
+                    </div>
+                  </el-col>
+                </el-row>
+                <p class="last-computed">
+                  <!--  <span v-show="relation.ComputationalState === 3 || relation.ComputationalState === 4">关系计算中...</span>-->
+                  <!--                  <span v-show="relation.cardDisabled || relation.ComputationalState === 3">关系计算中...</span>-->
+                  <span v-show="relation.computationalState === 3">关系计算中...</span>
+                  <span v-show="relation.computationalState === 5">计算失败</span>
+                  <span
+                    v-show="relation.computationalState !== 3  && relation.computingTime">最后一次计算时间 {{ relation.computingTime }}</span>
+                  <el-tooltip
+                    :content="relation.computationalState === 2 ? '关系变更,请重新计算':'启动计算'"
+                    placement="top"
+                  >
+                    <el-badge
+                      class="item float-right"
+                      :is-dot="relation.computationalState === 2 || relation.computationalState === 5"
+                    >
+                      <el-button
+                        @click="computed(relation)"
+                        :disabled="!relation.source && !relation.automatic "
+                        circle
+                        type="primary"
+                        plain
+                        icon="iconfont icon-changyongtubiao-mianxing-"
+                        class="sm-button"
+                      >
+                        <!--style="background: #000;color: #fff"-->
+                      </el-button>
+                    </el-badge>
+                  </el-tooltip>
+                  <el-tooltip
+                    content="手动编辑"
+                    placement="top"
+                  >
+                    <el-button
+                      :disabled="relation.manual === 1"
+                      :style="{'border':(relation.manual=== 1? '1px solid #DCDFE6' :'')}"
+                      @click="manual(relation)"
+                      circle
+                      class="float-right sm-button"
+                      type="primary"
+                      plain
+                      icon="iconfont icon-bianji"
+
+                    >
+                    </el-button>
+
+                  </el-tooltip>
+                  <el-tooltip
+                    content="设定设备对象源/末端"
+                    placement="top"
+                    v-if="relation.source"
+                  >
+                    <el-button
+                      @click="equipment(relation)"
+                      type="primary"
+                      plain
+                      circle
+                      class="float-right sm-button"
+                      icon="iconfont icon-23 "
+                      style="transform: rotate(90deg);"
+                    >
+                    </el-button>
+                  </el-tooltip>
+                </p>
+              </article>
+            </el-card>
+          </el-col>
+        </el-row>
+      </section>
+    </div>
+    <RelationMaintain
+      :values="values"
+      :source="source"
+      ref="maintain"
+      :isComputed="isComputed"
+      :ManualMaintenance="ManualMaintenance"
+      :TableVisibleMoreLoading="TableVisibleMoreLoading"
+      @openComputed="openComputed"
+      @RelationType="RelationType"
+      @calcSpecialUpdate="calcSpecialUpdate"
+    />
+  </div>
+
+</template>
+
+<script>
+import RelationMaintain from './Modal/RelationMaintain'
+
+export default {
+  name: "cardList",
+  props: {
+    content: Array,
+    source: Array,
+    TableVisibleMoreLoading: Boolean,
+		computingNum: Number,
+    // cardDisabled: Boolean
+  },
+  data() {
+    return {
+      values: {
+        title: '关系维护',
+        cancel: '取消',
+        confirm: '确定',
+        back: '返回',
+        preservation: '保存',
+        promptly: '立即计算',
+        placeholder: '请选择',
+        download: '下载模板(含数据)',
+        done: '完成',
+        underDesign: '高级配置页面正在设计中。。。',
+        autoComputed: '根据现有数据自动计算',
+        existComputed: '根据现有数据自动计算',
+        existTitle: '计算方向使用的源端和末端如下:',
+        originEquipment: '源端设备类:',
+        endEquipment: '末端设备类:',
+        device: '', //提示引导内容
+        tips: '', //请前往以下功能页面维护
+        optionTips: '', //请下载最新最新 xxxx 数据进行手动维护
+        currentNum: '当前关系数量:',
+        lastTime: '', //最后更新时间为
+        uploadTxt: '将Excel文件拖到此处,或<em>单击上传Excel文件<em>',
+        uploadTips: '上传的Excel数据将完全覆盖当前关系表(关系表先前数据不会保留)',
+        inHand: '数据文件处理中...',
+        dataFailed: '数据文件验证失败',
+        allUpdateSuccess: 'xxxx全部更新成功',
+        portionUpdateSuccess: ' xxxx关系部分更新成功',
+        downloadFile: ' 下载报告文件',
+        equipmentSetting: ''
+      },
+      isComputed: {}, // 当前要计算的对象
+      ManualMaintenance: {},//手动编辑对象
+    }
+  },
+  created() {
+  },
+  computed: {},
+
+  methods: {
+    explain() {
+      // alert('explain click')
+    },
+    RelationType() {
+      // this.cardDisabled = true
+      this.$emit('RelationType', this.isComputed.relationType, this.isComputed.zoneType, this.isComputed)
+    },
+    calcSpecialUpdate(params) {
+        this.$emit("calcSpecialUpdate", params, this.isComputed);
+    },
+    computed(relation) {
+			if (this.computingNum >= 5) {
+				this.$message.info("当前计算过多,稍等一下");
+				return false;
+			}
+      this.isComputed = relation // 当前要计算的对象
+      if (relation.relationType) {
+        this.$emit('calcSpecial', relation)
+        if (relation.source) {
+          this.values.existComputed = `根据现有数据自动计算 <${ relation.relationTypeName }>`
+          this.$refs.maintain.dialogTableVisibleMore = true
+          this.$refs.maintain.showCascader(relation)
+          this.$refs.maintain.handleSourceQuery()
+
+        } else {
+          this.values.autoComputed = `根据现有数据自动计算 <${ relation.relationTypeName }>`
+          this.$refs.maintain.dialogTableVisible = true
+        }
+      } else {
+        this.$message.warning("设计中")
+        return false
+      }
+    },
+    equipment(relation) { //配置源端末端
+      this.values.equipmentSetting = `${ relation.relationTypeName } 源末端关系设置`
+      this.$refs.maintain.dialogEquipmentOpen(relation)
+      this.$refs.maintain.handleSourceQuery()
+    },
+    manual(relation) {
+      let { manual, prompting, relationTypeName, computingTime } = relation;
+      let device = prompting && prompting.split(','),
+        tips = `请前往以下功能页面维护 <${ relationTypeName }>`,
+        optionTips = `请下载当前最新 <${ relationTypeName }> 数据进行手动维护`,
+        lastTime = `最后更新时间为 ${ computingTime ? computingTime : '' }`
+
+      if (manual === 2) {
+        this.values = { ...this.values, device, tips }
+        this.$refs.maintain.dialogManualTip = true
+      }
+      if (manual === 3) {
+        // if (relation.RelManualType) {
+        if (relation.relationType) {
+          this.values = { ...this.values, optionTips, lastTime }
+          // this.$refs.maintain.dialogManualOption = true //导出excel 弹窗
+          this.$router.push({
+            path: "relationShip"
+          })
+          console.log(relation, 'relation')
+          localStorage.setItem('RelManualType', relation.relManualType)
+          localStorage.setItem('RelationTypeName', relation.relationTypeName)
+          localStorage.setItem('RelationType', relation.relationType)
+          localStorage.setItem('ZoneType', relation.zoneType ? relation.zoneType : '')
+          localStorage.setItem('MainObject', relation.mainObject)
+          localStorage.setItem('FromObject', relation.fromObject)
+          localStorage.setItem('count', relation.count)
+          localStorage.setItem('ComputingTime', relation.computingTime ? relation.computingTime : '')
+        } else {
+          this.$message.warning("设计中")
+          return false
+        }
+      }
+      this.ManualMaintenance = relation
+    },
+
+    openComputed(result) {
+      this.$emit('openComputed', result)
+    },
+
+    //空间连接关系详情
+    toDetail(detail) {
+      return
+      this.$router.push({
+        name: 'relationDetail',
+        query: {
+          type: detail.graphTypeCode,
+          RelationTypeProjectList: detail.relationTypeProjectList
+        }
+      })
+    }
+  },
+  components: { RelationMaintain }
+}
+</script>
+
+<style lang="less" scoped>
+@color-text: #333;
+@font-big: 600;
+@font-small: 12px;
+@font-code: #AAAAAA;
+@pos-relative: relative;
+@pos-absolute: absolute;
+@pos-zero: 0;
+@5px: 5px;
+
+.slave-relation-title {
+  color: @font-code;
+  font-weight: 600;
+  border-bottom: 1px dashed @font-code;
+  padding-bottom: @5px;
+}
+
+.container {
+  @media (max-width: 1500px) {
+    .relation-title {
+      max-width: 160px;
+    }
+
+    .group {
+      white-space: normal !important;
+    }
+
+    .asc {
+      max-width: 108px;
+    }
+
+    .thread {
+      margin-left: 5px !important;
+    }
+
+    /deep/ .el-card__body {
+      padding: 18px !important;
+    }
+
+    .sm-button {
+      height: 30px;
+      width: 30px;
+      text-align: center;
+      padding: 0;
+    }
+
+  }
+
+  .el-row {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
+  .el-col {
+    border-radius: 4px;
+  }
+
+  .grid-content {
+    border-radius: 4px;
+    min-height: 36px;
+
+    .thread {
+      border-left: 1px solid @font-code;
+      margin-left: 10px;
+      min-height: 36px;
+      margin-top: 6px;
+    }
+  }
+
+  .row-bg {
+    padding: 10px 0;
+    background-color: #f9fafc;
+  }
+
+  .reset-title {
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+
+  .reset-test {
+    float: left;
+    text-align: center;
+    height: 40px;
+    line-height: 40px;
+  }
+
+  .fr {
+    float: right;
+  }
+
+  .el-card {
+    margin: 10px 0;
+  }
+
+  .relation-text {
+    overflow: hidden;
+    margin-top: 10px;
+    /*text-indent: 10px;*/
+    margin-left: -3px;
+    font-weight: @font-big;
+
+    .pic-code {
+      font-size: @font-small;
+      color: @font-code;
+      margin-left: @5px;
+      font-weight: 400;
+    }
+  }
+
+  .card {
+    position: @pos-relative;
+
+  }
+
+  .mask {
+    background: rgba(255, 255, 255, .6);
+    position: @pos-absolute;
+    top: @pos-zero;
+    left: @pos-zero;
+    right: @pos-zero;
+    bottom: @pos-zero;
+    user-select: none;
+    z-index: 2
+  }
+
+  .relation-title {
+    font-size: 20px;
+    font-weight: @font-big;
+    margin-right: 10px;
+
+    .icon {
+      display: block;
+      float: right;
+      color: #555;
+      font-size: 18px;
+    }
+  }
+
+  .relation-title-icon {
+    font-size: 20px;
+    font-weight: @font-big;
+    overflow: hidden;
+
+    .icon {
+      display: block;
+      float: right;
+      color: #555;
+      font-size: 18px;
+    }
+  }
+
+  .asc {
+    font-size: @font-small;
+    color: @font-code;
+  }
+
+  .object {
+    font-size: @font-small;
+    color: @font-code;
+    font-weight: @font-big;
+  }
+
+  .group {
+    color: @color-text;
+    font-weight: @font-big;
+  }
+
+  .line-number {
+    font-size: @font-small;
+    color: @font-code;
+    font-weight: @font-big;
+  }
+
+  .line-number-show {
+    color: @color-text;
+    font-weight: @font-big;
+  }
+
+  .line-number-hide {
+    color: @font-code;
+    font-weight: @font-big;
+  }
+
+
+  article {
+    overflow: hidden;
+  }
+
+  .last-computed {
+    overflow: hidden;
+    color: @font-code;
+
+    .float-right {
+      float: right;
+      margin-left: @5px;
+    }
+
+    /deep/ .is-dot {
+      margin-top: 7px;
+      margin-right: @5px;
+    }
+
+  }
+}
+</style>

+ 590 - 0
src/components/old-adm/relation/components/overview/Modal/RelationMaintain.vue

@@ -0,0 +1,590 @@
+<template>
+  <div class="relation-maintain">
+    <!--计算无需配置源末端的关系时提示-->
+    <el-dialog
+      :title="values.title"
+      :visible.sync="dialogTableVisible"
+    >
+      <span class="font-big">{{ values.autoComputed }}</span>
+      <footer
+        slot="footer"
+        class="dialog-footer "
+      >
+        <el-button @click="dialogTableVisible = false">{{ values.cancel }}</el-button>
+        <el-button
+          type="primary"
+          @click="promptly"
+        >{{ values.promptly }}
+        </el-button>
+      </footer>
+    </el-dialog>
+    <!-- 计算需配置源末端的关系且已配置时提示-->
+    <el-dialog
+      :title="values.title"
+      :visible.sync="dialogTableVisibleMore"
+    >
+      <div
+        v-loading="TableVisibleMoreLoading"
+        style="overflow:hidden"
+      >
+        <p class="font-big">{{ values.existComputed }}</p>
+        <p class="exist-title">{{ values.existTitle }}</p>
+        <el-row :gutter="20" style="margin-bottom: 20px">
+          <el-col :span="12">
+            <p>源端设备类:</p>
+            <el-select
+              v-model="setValue"
+              placeholder="请选择"
+              :props="props"
+              multiple
+              disabled
+            >
+              <el-option
+                v-for="(item,index) in setOriginOption"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+                disabled
+              />
+            </el-select>
+          </el-col>
+          <el-col :span="12">
+            <p>末端设备类:</p>
+            <el-select
+              v-model="setEndValue"
+              placeholder="请选择"
+              :props="props"
+            >
+              <el-option
+                v-for="(item,index) in setEndOptions"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+                disabled
+              />
+            </el-select>
+          </el-col>
+        </el-row>
+        <footer
+          slot="footer"
+          class="dialog-footer "
+          style="float: right"
+        >
+          <el-button @click="dialogTableVisibleMore = false">{{ values.cancel }}</el-button>
+          <el-button
+            type="primary"
+            @click="computedUpdate"
+          >{{ values.promptly }}
+          </el-button>
+        </footer>
+      </div>
+    </el-dialog>
+    <el-dialog
+      :title="values.title"
+      :visible.sync="dialogEquipment"
+    >
+      <h4>{{ values.equipmentSetting }}</h4>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <p>源端设备类:</p>
+          <el-tooltip placement="top" :disabled="!sourceSideList.length">
+						<div slot="content">
+							<ul>
+								<li  v-for="item in sourceSideList" :key="item.sourceType">
+									{{`${oraginOption.find(e => e.value === item.sourceType)? oraginOption.find(e => e.value === item.sourceType).label : ""}:${item.sourceCount}个`}}
+								</li>
+							</ul>
+						</div>
+            <el-select
+                v-model="value"
+                placeholder="请选择"
+                multiple
+                @change="changeVal"
+            >
+                <el-option
+                v-for="item in oraginOption"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+                />
+            </el-select>
+        	</el-tooltip>
+        </el-col>
+        <el-col :span="12">
+          <p>末端设备类:</p>
+          <el-select
+            v-model="endValue"
+            placeholder="请选择"
+          >
+            <el-option
+              v-for="item in endOption"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+              disabled
+            />
+          </el-select>
+        </el-col>
+      </el-row>
+      <footer
+        slot="footer"
+        class="dialog-footer"
+      >
+        <el-button @click="dialogEquipment = false">{{ values.cancel }}</el-button>
+
+        <el-button
+          type="primary"
+          @click="handleAddSource"
+          :disabled="disabled"
+        >{{ values.preservation }}
+        </el-button>
+      </footer>
+    </el-dialog>
+    <!--手动编辑:提示引导-->
+    <el-dialog
+      :title="values.title"
+      :visible.sync="dialogManualTip"
+    >
+      <p class="font-big">{{ values.tips }}</p>
+      <p
+        class="font-big"
+        v-for="item in values.device"
+      >{{ item }}</p>
+      <footer
+        slot="footer"
+        class="dialog-footer "
+      >
+        <el-button @click="dialogManualTip = false">{{ values.confirm }}
+        </el-button>
+      </footer>
+    </el-dialog>
+    <!--手动编辑:手动维护-->
+    <el-dialog
+      :title="values.title"
+      :visible.sync="dialogManualOption"
+    >
+      <p class="option-tip">{{ values.optionTips }}</p>
+      <el-row :span="24">
+        <el-col :span="8">
+          <p>
+            <i class="iconfont icon-doc-line"/>
+            {{ values.currentNum }} 0
+          </p>
+
+          <a :href="downloadProject('excel')">
+            <el-button
+              type="primary"
+              class="mt-10"
+            >
+              {{ values.download }}
+            </el-button>
+          </a>
+        </el-col>
+        <el-col :span="10">
+          {{ values.lastTime }}
+        </el-col>
+      </el-row>
+      <el-upload
+        class="upload-demo"
+        drag
+        :action="`${baseUrl}${dataCenter}/graphic/import`"
+        multiple
+        :show-file-list='false'
+        name="file"
+        :headers="headers"
+        :data="dataId"
+        :on-progress="progress"
+        :on-success="success"
+        :on-error="error"
+
+
+        accept="xlsx,xls"
+      >
+        <i class="el-icon-upload"/>
+        <div
+          class="el-upload__text"
+          v-html="values.uploadTxt"
+        />
+        <div class="upload__tip danger" slot="tip">{{ values.uploadTips }}</div>
+      </el-upload>
+    </el-dialog>
+    <!--手动编辑:手动维护.process结束-->
+    <el-dialog
+      :title="values.title"
+      :visible.sync="dialogProcess"
+    >
+      <div class="block">
+        <el-timeline>
+          <el-timeline-item
+            v-for="(activity, index) in activities"
+            :key="index"
+            :icon="activity.icon"
+            :type="activity.type"
+            :color="activity.color"
+            :size="activity.size"
+          >
+            {{ activity.content }}
+          </el-timeline-item>
+        </el-timeline>
+      </div>
+      <!--            下载报告-->
+      <a :href="downloadProject('report')">
+        <el-button>{{ values.downloadFile }}</el-button>
+      </a>
+      <footer
+        slot="footer"
+        class="dialog-footer "
+      >
+        <el-button @click="errBack">{{ values.back }}</el-button>
+        <el-button
+          type="primary"
+          @click="finish"
+        >{{ values.done }}
+        </el-button>
+      </footer>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {mapGetters} from 'vuex'
+import storage from '@/utils/storageUtil'
+// import {addSource, sourceQuery} from "@/api/relation/api";
+import deviceList from "@/data/old-adm/deviceList"
+import { baseUrl, dataCenter } from '@/utils/scanUtil'
+import Relation from '@/controller/old-adm/relationController'
+
+const { addSource, sourceQuery } = Relation
+
+export default {
+  name: "RelationMaintain",
+  props: ['values', 'isComputed', 'source', 'TableVisibleMoreLoading', 'ManualMaintenance'],
+  created() {
+  },
+  mounted() {
+
+  },
+  data() {
+    return {
+      dialogTableVisible: false,
+      dialogTableVisibleMore: false,
+      dialogEquipment: false,
+      dialogManualTip: false,
+      dialogManualOption: false,
+      dialogProcess: false,
+      originEquipment: [],
+      endEquipment: [],
+      props: {
+        multiple: true,
+        label: 'FamilyName',
+        value: 'lId',
+        children: 'Items',
+
+      },
+      activities: [{
+        content: '数据文件处理中..',
+        size: 'large',
+        type: 'primary',
+        icon: 'el-icon-check',
+        color: '#0bbd87'
+      }, {
+        content: '数据处理成功',
+        color: '#0bbd87',
+        icon: 'el-icon-check',
+        size: 'large',
+        type: 'primary',
+      }],
+      vals: [],
+      val: [],
+      idArr: [],//存储所有选择的id
+      secondary: [],//单独存储二级数据
+      list: [],//获取后台数据,重新组合,添加唯一标识和源端标识
+      resultOrigin: [],//最终传给后台的源端数据
+      resultEnd: [],//最终传给后台的末端数据
+      ops: [],
+      filterOps: [],//为清空第二个选择器
+      isResouceShow: 0,
+      RelationTypeName: '',//卡片名称
+      value: [],
+      oraginOption: [],
+      endValue: [],
+      endOption: [],
+      setValue: [],
+      setOriginOption: [],
+      setEndValue: [],
+      setEndOptions: [],
+	    sourceSideList: [],
+      disabled: false,
+			baseUrl: baseUrl,
+      dataCenter: dataCenter
+    }
+  },
+
+  computed: {
+    ...mapGetters('layout', ['projectId']),
+    headers() {
+      return {
+        //头信息中的 ProjectId 改为 projectId    nh-2021.11.25
+        'projectId': this.projectId,
+        'Comming': 'adm',
+        'Account': storage.get("user_name")
+      }
+    },
+    dataId() {
+      return {
+        relType: this.ManualMaintenance.RelationType || '',
+        zoneType: this.ManualMaintenance.ZoneType || '',
+        projectId: this.projectId
+      }
+    },
+    disOptions() {
+      let arr = this.list.length && this.deepCopy(this.list).map(item => {
+        item.Items.length && item.Items.map(i => {
+          if (this.idArr.includes(i.lId)) {
+            i.disabled = true
+          }
+          return i
+        })
+        return item
+      })
+      this.filterOps = arr
+      return arr
+    },
+  },
+  methods: {
+    deepCopy(obj) {
+      return JSON.parse(JSON.stringify(obj))
+    },
+    //查询原末端回显数据
+    handleSourceQuery() {
+      let param = {
+        // filters: `projectId='${this.projectId}';calcName='${this.RelationTypeName}'`
+        calcName: this.RelationTypeName
+      }
+      sourceQuery(param, res => {
+        this.value = []
+        this.setValue = []
+				this.sourceSideList = res.content ? res.content : [];
+        res.content && res.content.forEach(({sourceType}) => sourceType && this.value.push(sourceType))
+        //启动计算
+        res.content && res.content.forEach(({sourceType}) => sourceType && this.setValue.push(sourceType))
+        // this.setOriginOption = this.oraginOption.forEach(i => this.setValue.includes(i.value))
+        this.changeVal(this.value)
+        this.setValue && this.handleSetValue()
+      })
+    },
+    dialogEquipmentOpen(relation) { //设定源末端
+      this.RelationTypeName = relation.relationTypeName
+      this.oraginOption = deviceList[relation.relationTypeName] && deviceList[relation.relationTypeName].filter(i => i.select)
+      this.data = deviceList[relation.relationTypeName]
+      this.disabled = this.data != undefined ? false : true
+      // console.log(this.data, relation.RelationTypeName)
+      this.dialogEquipment = true
+
+    },
+    changeVal(val) {
+      //  末端展示数据
+      this.endOption = this.data && this.data.filter(i => !val.includes(i.value))
+      //  启动计算末端展示数据
+      // this.setEndOptions = this.data && this.data.filter(i => !val.includes(i.value))
+
+      this.sourceList = []
+      val.forEach(i => this.sourceList.push({
+        sourceType: i,
+        projectId: this.projectId,
+        calcName: this.RelationTypeName
+      }))
+    },
+
+    handleAddSource() { //保存设备类
+      let params = {}
+      if (this.sourceList.length) {
+        params = {
+          content: this.sourceList
+        }
+
+      } else {
+        params = {
+          content: [{
+            projectId: this.projectId,
+            calcName: this.RelationTypeName
+          }]
+        }
+      }
+      addSource(params, res => {
+        this.$message.success('保存成功')
+      })
+      this.dialogEquipment = false
+    },
+    // showCascader() {
+    //   ++this.isResouceShow
+    //   let copy = this.deepCopy(this.source)
+    //   copy.forEach(item => {
+    //     item.Items.forEach(child => {
+    //       child.lId = this.list.length
+    //       this.list.push(child)
+    //       child.Items.forEach(i => {
+    //         i.lId = i.Id + i.BlockId
+    //         i.IsSource == true && this.ops.push([child.lId, i.lId])
+    //         i.IsSource == false && this.filterOps.push([child.lId, i.lId])
+    //       })
+    //     })
+    //   })
+    // },
+    showCascader(relation) {
+      this.RelationTypeName = relation.relationTypeName
+
+
+    },
+    handleSetValue() {
+      let device = deviceList[this.RelationTypeName]
+      this.setOriginOption = device && device.filter(i => this.setValue.includes(i.value))
+      this.setEndOptions = device && device.filter(i => !this.setValue.includes(i.value))
+    },
+    downloadProject(str) {
+      let relType = this.ManualMaintenance.RelationType ? `&relType=${this.ManualMaintenance.RelationType}` : ''
+      let zoneType = this.ManualMaintenance.ZoneType ? `&zoneType=${this.ManualMaintenance.ZoneType}` : null
+      let url;
+      if (str === 'excel') {
+        relType = this.ManualMaintenance.RelationType ? `&relType=${this.ManualMaintenance.RelationType}` : ''
+        // url = `${baseUrl}${dataCenter}/graphic/export?code=对象ID${relType}${zoneType}`
+        if (zoneType) {
+          url = `${baseUrl}${dataCenter}/graphic/export?projectId=${this.projectId}${relType}${zoneType}&code=对象ID`
+
+        } else {
+          url = `${baseUrl}${dataCenter}/graphic/export?projectId=${this.projectId}${relType}&code=对象ID`
+        }
+      } else {
+        url = `${baseUrl}${dataCenter}/graphic/report-downloads?projectId=${this.projectId}${relType}${zoneType}`
+      }
+      return url
+    },
+    progress(event, file, fileList) {
+      // console.log(event.file, fileList)
+    },
+    success(event, file, fileList) {
+      this.dialogManualOption = true
+      this.dialogProcess = true
+
+    },
+    error(event, file, fileList) {
+      this.dialogManualOption = true
+      this.dialogProcess = true
+
+    },
+    errBack() {
+      this.dialogProcess = false
+    },
+    finish() {
+      this.dialogProcess = false
+      this.dialogManualOption = false
+    },
+
+    promptly() {
+
+      if (this.isComputed.automatic && !this.isComputed.source) { //需要自动计算并且不需要配置云末端
+        this.$emit('RelationType', this.isComputed.RelationType, this.isComputed.ZoneType)
+      }
+      this.dialogTableVisible = false
+    },
+    sourceOptions(val) {
+      // this.ops = val
+      this.idArr = val.map(item => item[1])
+      this.deepCopy(this.list).forEach(item => this.secondary.push(...item.Items))
+      let filterList = this.secondary.filter(item => this.idArr.includes(item.lId))
+      //接口需要的数据格式
+      filterList.forEach(item => {
+        let {BlockId, BuildingId, Domain, Id, MepSystemType, ProjectId, Type, Statistics} = item
+        this.resultOrigin.push({
+          BlockId,
+          BuildingId,
+          Domain,
+          // Id,
+          MepSystemType,
+          ProjectId,
+          Source: true,
+          SourceId: Id,
+          SourceType: Type,
+          Statistics
+        })
+      })
+    },
+    endOptions(val) {
+      this.idArr = val.map(item => item[1])
+      this.deepCopy(this.list).forEach(item => this.secondary.push(...item.Items))
+      let filterList = this.secondary.filter(item => this.idArr.includes(item.lId))
+      //接口需要的数据格式
+      filterList.forEach(item => {
+        let {BlockId, BuildingId, Domain, Id, MepSystemType, ProjectId, Type, Statistics} = item
+        this.resultEnd.push({
+          BlockId,
+          BuildingId,
+          Domain,
+          // Id,
+          MepSystemType,
+          ProjectId,
+          Source: false,
+          SourceId: Id,
+          SourceType: Type,
+          Statistics
+        })
+      })
+    },
+    computedUpdate() {
+      this.dialogTableVisibleMore = false
+      let params = {
+        projectId: this.projectId,
+        relationType: this.isComputed.relationType
+      }
+      this.$emit("calcSpecialUpdate", params);
+    },
+  }
+}
+</script>
+
+<style scoped lang="less">
+.relation-maintain {
+  .mt-10 {
+    margin-top: 10px;
+  }
+
+  .danger {
+    color: #d9001b;
+  }
+
+  .font-big {
+    font-weight: 600;
+  }
+
+
+  .exist-title {
+    font-size: 12px;
+    color: #AAAAAA;
+  }
+
+  .option-tip {
+    font-size: 18px;
+    font-weight: 600;
+  }
+
+  .upload-demo {
+    margin: 20px 0;
+
+  }
+
+  /deep/ .el-upload-dragger {
+    width: 600px;
+    margin: 0 auto;
+  }
+}
+</style>
+
+
+
+
+
+
+
+
+
+

+ 199 - 0
src/components/old-adm/relation/components/overview/Modal/getCascader.vue

@@ -0,0 +1,199 @@
+<template>
+  <div id="cascader-group">
+    <el-row :gutter="20">
+      <el-col :span="12">
+        <p>源端设备类:</p>
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+          :props="props"
+          multiple
+          disabled
+        >
+          <el-option
+            v-for="item in oraginOption"
+            :key="item.code"
+            :label="item.facility"
+            :value="item.code"
+            disabled
+          />
+        </el-select>
+      </el-col>
+      <el-col :span="12">
+        <p>末端设备类:</p>
+        <el-select
+          v-model="endValue"
+          placeholder="请选择"
+          :props="props"
+        >
+          <el-option
+            v-for="item in endOptions"
+            :key="item.code"
+            :label="item.facility"
+            :value="item.code"
+            disabled
+          />
+        </el-select>
+      </el-col>
+    </el-row>
+
+
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+import { getEquipBelongs } from "@/api/scan/request";
+import { queryEquip } from "@/api/object/equip"
+
+import { sourceQuery } from "@/api/relation/api";
+
+export default {
+  name: "getCascader",
+  props: {
+    all: {
+      type: Boolean,
+      default: false,
+    },
+    RelationTypeName: {
+      type: String
+    },
+    number: {
+      type: Number
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      value: "",
+      endValue: '',
+      options: [],
+      oraginOption: [],
+      endOptions: [],
+      props: {
+        value: "code",
+        label: "facility"
+      },
+      falg: true,
+      content: [],
+
+    };
+  },
+  created() {
+    this.getData();
+  },
+  watch: {
+    projectId() {
+      this.value = '';
+      this.getData();
+    },
+    RelationTypeName() {
+      this.getData();
+    },
+    number() {
+      this.getData();
+    }
+  },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      this.endOptions = this.options.filter(i => !val.includes(i.code))
+      this.$emit("change", val)
+    },
+    //获取当前项目下的设备类型(只拿到编码-需要过滤)
+    getData() {
+      let param2 = {
+        distinct: true,
+        pageNumber: 1,
+        pageSize: 500,
+        projection: ["classCode"]
+      }
+      let param1 = {
+        data: {
+          distinct: true,
+          orders: "equipName asc",
+          pageNumber: 1,
+          pageSize: 500,
+          projection: [
+            "equipCode", "equipName"
+          ]
+        }
+      }
+      let param3 = {
+        // Filters: `ProjectId='${this.projectId}';CalcName='${this.RelationTypeName}'`
+        calcName: this.RelationTypeName
+
+      }
+      let promise2 = new Promise((resolve, reject) => {
+        queryEquip(param2, res => {
+          resolve(res)
+        })
+      })
+      let promise1 = new Promise((resolve, reject) => {
+        getEquipBelongs(param1, res => {
+          resolve(res)
+        })
+      })
+      let promise3 = new Promise((resolve, reject) => { //回显
+        sourceQuery(param3, res => {
+          resolve(res)
+        })
+      })
+      Promise.all([promise1, promise2, promise3]).then((res) => {
+        let allData = res[0], data = res[1], arr = res[2].content
+        this.options = this.formatOptions(allData.content)
+        if (!this.all) {
+          this.content = data.content.map(t => {
+            return t.classCode
+          });
+          this.filterForOptions();
+        }
+        if (this.value) {
+          this.changeVal(this.value)
+        }
+        if (arr) {
+          this.value = []
+          arr.forEach(({ sourceType }) => this.value.push(sourceType))
+          this.oraginOption = this.options.filter(i => this.value.includes(i.code))
+          this.endOptions = this.options.filter(i => !this.value.includes(i.code))
+        }
+      })
+    },
+    //格式化options数据
+    formatOptions(arr) {
+      let data = [];
+      arr.map(t => {
+        let temp = {};
+        temp.code = t.equipCode;
+        temp.facility = t.equipName;
+        data.push(temp)
+      })
+      return data;
+    },
+    //过滤
+    filterForOptions() {
+      this.options = this.options.filter(item => {
+        if (this.content.indexOf(item.code) > -1) {
+          return item
+        }
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascader-group {
+  /*float: left;*/
+  /*margin-left: 10px;*/
+  /*display: inline-block;*/
+
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 190 - 0
src/components/old-adm/relation/components/overview/Modal/setCascader.vue

@@ -0,0 +1,190 @@
+<template>
+  <div id="cascader-group">
+    <el-row :gutter="20">
+      <el-col :span="12">
+        <p>源端设备类:</p>
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+          :props="props"
+          multiple
+          @change="changeVal">
+          <el-option
+            v-for="item in options"
+            :key="item.code"
+            :label="item.facility"
+            :value="item.code"
+          />
+        </el-select>
+      </el-col>
+      <el-col :span="12">
+        <p>末端设备类:</p>
+        <el-select
+          v-model="endValue"
+          placeholder="请选择"
+          :props="props"
+        >
+          <el-option
+            v-for="item in endOptions"
+            :key="item.code"
+            :label="item.facility"
+            :value="item.code"
+            disabled
+          />
+        </el-select>
+      </el-col>
+    </el-row>
+
+
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex';
+import { getEquipBelongs } from "@/api/scan/request";
+import { queryEquip } from "@/api/object/equip"
+import { sourceQuery } from "@/api/relation/api";
+
+export default {
+  name: "setCascader",
+  props: {
+    all: {
+      type: Boolean,
+      default: false,
+    },
+    RelationTypeName: {
+      type: String
+    },
+
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  data() {
+    return {
+      value: "",
+      endValue: '',
+      options: [],
+      endOptions: [],
+      props: {
+        value: "code",
+        label: "facility"
+      },
+      falg: true,
+      content: [],
+
+    };
+  },
+  created() {
+    this.getData();
+  },
+  watch: {
+    projectId() {
+      this.value = '';
+      this.getData();
+    },
+    RelationTypeName() {
+      this.getData();
+    },
+
+  },
+  methods: {
+    setValue(val) {
+      this.value = val
+    },
+    //修改val
+    changeVal(val) {
+      this.endOptions = this.options.filter(i => !val.includes(i.code))
+      this.$emit("change", val)
+    },
+    //获取当前项目下的设备类型(只拿到编码-需要过滤)
+    getData() {
+      let param2 = {
+        distinct: true,
+        pageNumber: 1,
+        pageSize: 500,
+        projection: ["classCode"]
+      }
+      let param1 = {
+        data: {
+          distinct: true,
+          orders: "equipName asc",
+          pageNumber: 1,
+          pageSize: 500,
+          projection: [
+            "equipCode", "equipName"
+          ]
+        }
+      }
+      let param3 = {
+        // Filters: `ProjectId='${this.projectId}';CalcName='${this.RelationTypeName}'`
+        calcName: this.RelationTypeName
+
+      }
+      let promise2 = new Promise((resolve, reject) => {
+        queryEquip(param2, res => {
+          resolve(res)
+        })
+      })
+      let promise1 = new Promise((resolve, reject) => {
+        getEquipBelongs(param1, res => {
+          resolve(res)
+        })
+      })
+      let promise3 = new Promise((resolve, reject) => { //回显
+        sourceQuery(param3, res => {
+          resolve(res)
+        })
+      })
+      Promise.all([promise1, promise2, promise3]).then((res) => {
+        let allData = res[0], data = res[1], arr = res[2].content
+        this.options = this.formatOptions(allData.content)
+        if (!this.all) {
+          this.content = data.content.map(t => {
+            return t.classCode
+          });
+          this.filterForOptions();
+        }
+        if (this.value) {
+          this.changeVal(this.value)
+        }
+        if (arr) {
+          this.value = []
+          arr.forEach(({ sourceType }) => this.value.push(sourceType))
+          this.endOptions = this.options.filter(i => !this.value.includes(i.code))
+        }
+      })
+    },
+    //格式化options数据
+    formatOptions(arr) {
+      let data = [];
+      arr.map(t => {
+        let temp = {};
+        temp.code = t.equipCode;
+        temp.facility = t.equipName;
+        data.push(temp)
+      })
+      return data;
+    },
+    //过滤
+    filterForOptions() {
+      this.options = this.options.filter(item => {
+        if (this.content.indexOf(item.code) > -1) {
+          return item
+        }
+      })
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+#cascader-group {
+  /*float: left;*/
+  /*margin-left: 10px;*/
+  /*display: inline-block;*/
+
+  .buildFloor {
+    color: #999999;
+    font-size: 14px;
+  }
+}
+</style>

+ 398 - 0
src/components/old-adm/relation/overview/detail/index.vue

@@ -0,0 +1,398 @@
+<template>
+  <div id="spaceRelation">
+    <el-row>
+      <el-col :span="0.5">
+        <el-button size="small" type="default" icon="el-icon-back" @click="goback"></el-button>
+      </el-col>
+      <el-col :span="0.5">
+        <span style="margin:0 10px;">建筑楼层</span>
+        <el-cascader placeholder="请选择建筑楼层" :options="options" v-model="buildFloor" filterable size="small" @change="changeCascader" :props="props">
+        </el-cascader>
+      </el-col>
+      <el-col :span="0.5">
+        <span style="margin:0 10px;">业务空间类型</span>
+        <el-select placeholder="请选择" v-model="zoneType" @change="getBusinessSpace">
+          <el-option v-for="item in tabsList" :key="item.Code" :label="item.Name" :value="item.Code">
+          </el-option>
+        </el-select>
+      </el-col>
+      <el-col :span="0.5" style="float:right;" v-show='0'>
+        <span style="margin-right:10px;">当前状态 {{description}}</span>
+        <el-button @click="cancel">取消</el-button>
+        <el-button @click="removeRelation">清除</el-button>
+        <el-button @click="removeAll">清除所有</el-button>
+        <el-button @click="addRelation">添加</el-button>
+        <el-button type="primary" @click="saveRelation">保存</el-button>
+      </el-col>
+    </el-row>
+    <div class="canvas-container" v-loading="canvasLoading" ref="graphy">
+      <div v-show="!FloorMap" style="display:flex;align-items:center;justify-content:center;height:100%;">
+        <div class="center" style="flex:1">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div v-show="FloorMap" class="canvas-box">
+        <canvas id="floorCanvas" :width="canvasWidth" :height="canvasHeight" ref="canvas" tabindex="0"></canvas>
+        <!-- 底部操作按钮 -->
+        <el-row class="canvas-actions-box">
+          <canvasFun @fit="fit" @scale="scale" :config="config" ref="canvasFun"></canvasFun>
+        </el-row>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import {
+  // buildingQuery, //数据中心-建筑查询
+  zoneQueryOutline, // 业务空间查询
+  queryDictionaryHead, //空间类型查询
+  createSpaceNeighborhood, //创建邻接关系
+  querySpaceNeighborhood, // 查询邻接关系
+  delSpaceNeighborhood, //删除选中
+  delFloorNeighborhood, //删除所有
+} from "@/api/scan/request";
+import { buildingQuery } from '@/api/object/build';
+import { SColor, SPoint } from "@saga-web/draw/lib";
+import { RelationScene, FloorView } from "@saga-web/cad-engine/lib";
+import canvasFun from "@/components/business_space/newGraphy/canvasFun"
+import floorCascader from "@/components/ledger/lib/floorCascader";
+import { colorArr } from "@/utils/spaceColor"
+export default {
+  components: {
+    floorCascader,
+    canvasFun
+  },
+  data() {
+    return {
+      view: '',
+      scene: '',
+      canvasWidth: 800,
+      canvasHeight: 600,
+      canvasLoading: false,
+      FloorMap: '',
+      options: [],
+      buildFloor: [],
+      tabsList: [],
+      zoneType: 'GeneralZone',
+      props: {
+        value: 'BuildID',
+        label: 'BuildLocalName',
+        children: 'floor'
+      },
+      idToFloor: {},
+      config: {
+        isEdit: false,
+        divide: false,
+        groupSelect: false
+      },
+      description: '无'
+    }
+  },
+  created() {
+    //图类型编码
+    this.type = this.$route.query.type;
+    this.init();
+  },
+  mounted() {
+    this.canvasWidth = this.$refs.graphy.offsetWidth - 20;
+    this.canvasHeight = this.$refs.graphy.offsetHeight - 20;
+  },
+  methods: {
+    //初始化
+    init() {
+      this.getBuilding();
+      this.getTypes();
+    },
+    changeCascader(val) {
+      if (val.length > 1) {
+        let floor = this.idToFloor[val[1]];
+        if (floor.StructureInfo && floor.StructureInfo.FloorMap) {
+          this.FloorMap = floor.StructureInfo.FloorMap;
+          this.initGraphy();
+        } else {
+          this.FloorMap = '';
+        }
+      } else {
+        this.FloorMap = '';
+      }
+    },
+    // 保存邻接关系
+    saveRelation() {
+      let relationList = this.scene.relationList;
+      let pa = {
+        Content: []
+      }
+      if (relationList.length) {
+        pa.Content = relationList.map(t => {
+          return {
+            FloorId: this.buildFloor[1],
+            GraphType: this.type,
+            LocationOne: `${t.startPoint.x},${-t.startPoint.y}`,
+            LocationTwo: `${t.lastPoint.x},${-t.lastPoint.y}`,
+            SpaceIdOne: t.startZone,
+            SpaceIdTwo: t.endZone,
+            ZoneType: this.zoneType
+          }
+        })
+      }
+      this.createRela(pa)
+    },
+    clearRelation() {
+      if (this.scene) {
+        this.scene.removeAllRelation()
+      }
+    },
+    //
+    cancel() {
+      this.scene.removeRelationFlag = false;
+      this.scene.createRelateFlag = false;
+      this.scene.isAbsorbing = false;
+      this.description = '无'
+    },
+    //
+    removeRelation() {
+      this.scene.removeRelationFlag = true;
+      this.scene.createRelateFlag = false;
+      this.scene.isAbsorbing = false;
+      this.description = '清除'
+    },
+    //
+    addRelation() {
+      this.scene.createRelateFlag = true;
+      this.scene.removeRelationFlag = false;
+      this.scene.isAbsorbing = true;
+      this.description = '添加'
+    },
+    //
+    removeAll() {
+      let temp = {
+        FloorId: this.buildFloor[1],
+        ZoneType: this.zoneType,
+        GraphType: this.type
+      }
+      delFloorNeighborhood(temp, res => {
+        this.$message.success('删除成功');
+        this.clearRelation();
+      })
+    },
+    canvasClick(item, event) {
+      console.log(item);
+      item.selected = false;
+    },
+    initGraphy() {
+      this.clearGraphy()
+      this.scene = new RelationScene();
+      this.canvasLoading = true;
+      this.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.FloorMap}`).then(res => {
+        this.canvasLoading = false;
+        if (res == 'error') {
+          this.FloorMap = '';
+          console.log('数据解析异常');
+          return;
+        }
+        this.view.scene = this.scene;
+        this.view.fitSceneToView();
+        this.scene.isSpaceSelectable = false;
+        this.getBusinessSpace();
+        this.view.minScale = this.view.scale;
+        if (this.$refs.canvasFun) {
+          this.$refs.canvasFun.everyScale = this.view.scale;
+        }
+      })
+    },
+    // 清空场景并初始化视图
+    clearGraphy() {
+      if (this.view) {
+        this.view.scene = null;
+        return
+      }
+      this.view = new FloorView('floorCanvas')
+    },
+    // canvas 获取焦点
+    focus() {
+      document.getElementById(`floorCanvas`).focus()
+    },
+    // 适配底图到窗口
+    fit() {
+      this.view.fitSceneToView()
+    },
+    // 缩放
+    scale(val) {
+      if (!this.view) {
+        return;
+      }
+      let scale = this.view.scale;
+      this.view.scaleByPoint(val / scale, this.canvasWidth / 2, this.canvasHeight / 2);
+    },
+    goback() {
+      this.$router.push({ name: 'overView' })
+    },
+    // 获取项目下建筑
+    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 => {
+              item.BuildID = item.id;
+              item.BuildLocalName = item.localName;
+              this.idToFloor[item.id] = item;
+              return item;
+            })
+          } else {
+            t.floor = []
+          }
+          return t;
+        })
+      })
+    },
+    // 业务空间分区类型
+    getTypes() {
+      let pa = {
+        Filters: `parentId='Space'`
+      }
+      queryDictionaryHead(pa, res => {
+        this.tabsList = res.Content.map(t => {
+          if (t.Name == "元空间") {
+            return undefined;
+          }
+          return t;
+        }).filter(item => item);
+      })
+    },
+    getRelations() {
+      let pa = {
+        Filters: `FloorId='${this.buildFloor[1]}';GraphType='${this.type}';ZoneType='${this.zoneType}'`
+      }
+      querySpaceNeighborhood(pa, res => {
+        let tempArr = res.Content.map(t => {
+          let p1 = t.LocationOne.split(',');
+          let p2 = t.LocationTwo.split(',');
+          return {
+            LocationOne: new SPoint(p1[0], -p1[1]),
+            LocationTwo: new SPoint(p2[0], -p2[1]),
+            SpaceIdOne: t.SpaceIdOne,
+            SpaceIdTwo: t.SpaceIdTwo,
+          }
+        })
+        this.clearRelation();
+        this.scene.addAllRelaPoint(tempArr);
+        this.canvasLoading = false;
+      })
+    },
+    // 获取当前分区下的业务空间
+    getBusinessSpace() {
+      this.canvasLoading = true
+      let pa = {
+        Filters: `not RoomID isNull`,
+        Orders: "createTime desc, RoomID asc",
+        PageSize: 1000,
+        ZoneType: this.zoneType
+      }
+      if (this.buildFloor.length && this.buildFloor.length > 1) {
+        pa.BuildingId = this.buildFloor[0];
+        pa.FloorId = this.buildFloor[1];
+      } else {
+        this.$message.warning("请选择建筑楼层");
+      }
+      zoneQueryOutline(pa, res => {
+        // 所有业务空间
+        this.businessSpaceList = res.Content;
+        // 已关联元空间的业务空间
+        this.BSPRelaISPList = [];
+        res.Content.map(t => {
+          if (t.Outline && t.Outline.length) {
+            this.BSPRelaISPList.push(t)
+          }
+        })
+        // 绘制业务空间
+        let tempArr = this.BSPRelaISPList.map((t, i) => {
+          if (t.FloorId == this.buildFloor[1] && t.ObjectType == this.zoneType) {
+            return {
+              RoomLocalName: t.RoomLocalName,
+              OutLine: t.Outline,
+              RoomID: t.RoomID,
+              Color: colorArr[i % colorArr.length],
+            }
+          } else {
+            console.log('internet slow')
+            return undefined;
+          }
+        }).filter(item => item)
+        this.scene.removeAllZone();
+        this.scene.addZoneList(tempArr);
+        this.scene.click(this, this.canvasClick)
+        // 绘制关系
+        this.getRelations();
+      })
+    },
+    // 创建邻接关系
+    createRela(param) {
+      console.log(param)
+      createSpaceNeighborhood(param, res => {
+        this.$message.success('创建成功')
+      })
+    }
+  },
+  watch: {
+    projectId() {
+      this.FloorMap = '';
+      this.init();
+    },
+    "view.scale": {
+      handler(n) {
+        if (this.$refs.canvasFun) {
+          let s = n * 10 / this.view.minScale
+          this.$refs.canvasFun.sliderVal = s > 1000 ? 1000 : s;
+        }
+      }
+    },
+    "scene.curRemoveItem": {
+      handler(n) {
+        if (n) {
+          let pa = [{
+            GraphType: this.type,
+            ZoneType: this.zoneType,
+            SpaceIdOne: n.startZone,
+            SpaceIdTwo: n.endZone
+          }]
+          delSpaceNeighborhood(pa, res => {
+            this.$message.success('删除成功');
+          })
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+#spaceRelation {
+  /deep/ .el-input__inner {
+    vertical-align: baseline;
+  }
+  .canvas-container {
+    position: relative;
+    width: calc(100% - 22px;);
+    height: calc(100% - 64px);
+    margin-top: 10px;
+    padding: 10px;
+    background-color: #fff;
+    border: 1px solid #e4e4e4;
+    .canvas-box {
+      width: 100%;
+      height: 100%;
+    }
+    .canvas-actions-box {
+      position: absolute;
+      bottom: 20px;
+      left: 50%;
+      transform: translateX(-50%);
+      z-index: 999;
+    }
+  }
+}
+</style>

+ 218 - 0
src/components/old-adm/relation/overview/index.vue

@@ -0,0 +1,218 @@
+<template>
+  <div style="overflow: hidden auto" v-loading="loading">
+    <cardList
+      :content="content"
+      :source="source"
+      :TableVisibleMoreLoading="TableVisibleMoreLoading"
+      :computingNum="computingNum"
+      @calcSpecial="calcSpecial"
+      @openComputed="openComputed"
+      @RelationType="RelationType"
+      @calcSpecialUpdate="calcSpecialUpdate"
+    />
+  </div>
+</template>
+
+<script>
+import CardList from "@/components/old-adm/relation/components/overview/CardList";
+// import {
+//   blockQuery,
+//   blockSource,
+//   businessSpaceAll,
+//   calcSpecial,
+//   graphic,
+//   graphicNumber,
+//   sysDirection
+// } from "../../../api/relation/api";
+import relation from '@/controller/old-adm/relationController'
+import { mapGetters } from "vuex";
+import { logicConfig } from "@/logicConfig";
+const {
+  blockQuery,
+  blockSource,
+  businessSpaceAll,
+  calcSpecial,
+  graphic,
+  graphicNumber,
+  sysDirection
+} = relation
+export default {
+  data() {
+    return {
+      content: [],
+      countNumber: [],
+      loading: false,
+      source: [], //源端数据
+      currentRelationTypeName: "", //当前点击卡片的RelationTypeName
+      TableVisibleMoreLoading: false,
+      computingNum: 0, //正在计算的关系数量
+    };
+  },
+  created() {
+		this.computingNum = 0;
+    this.init();
+  },
+  watch: {
+    projectId() {
+      this.init();
+    }
+  },
+  computed: {
+    ...mapGetters("layout", ["projectId"])
+  },
+  mounted() {
+  },
+  components: { 
+    CardList 
+  },
+  methods: {
+    init() {
+      this.loading = true;
+      let dataNumber = {
+        projectId: this.projectId
+      };
+      const promise1 = new Promise((resolve, reject) => {
+        graphic(dataNumber, res => {
+          resolve(res)
+        })
+      })
+      const promise2 = new Promise((resolve, reject) => {
+        graphicNumber(dataNumber, res => {
+          resolve(res)
+        })
+      })
+      Promise.all([promise1, promise2]).then(values => {
+        this.countNumber = values[1].content;
+        this.content = values[0].content;
+        this.transform(this.content, this.countNumber);
+        this.loading = false;
+      })
+    },
+    updateState() {
+        this.loading = true;
+        let dataNumber = {
+            projectId: this.projectId
+        };
+        graphic(dataNumber, res => {
+            if (res.result === "success") {
+                this.content = res.content;
+                this.transform(this.content, this.countNumber);
+                this.loading = false;
+            } else {
+                this.$message.error(res.message);
+                this.loading = false;
+            }
+        })
+    },
+    transform(list1, list2) {
+      let countInfo = {}; // { graphTypeName: { Id: count } }
+      list2.forEach(item => {
+        countInfo[item.graphTypeName] = countInfo[item.graphTypeName] || {};
+        let rList = item.relationTypeProjectList;
+        rList.forEach(r => {
+          countInfo[item.graphTypeName][r.id] = r.count;
+        });
+      });
+      let changeList = [];
+      list1.forEach(item => {
+        // 这里保存的是引用
+        if (item.childGraphicTypeList) {
+          changeList.push(...item.childGraphicTypeList);
+        }
+      });
+      changeList.length &&
+      changeList.forEach(item => {
+        let name = item.graphTypeName;
+        let rList = item.relationTypeProjectList;
+        rList.forEach(r => {
+          r.count = countInfo[name][r.id];
+          // this.$set(r, 'cardDisabled', false)
+        });
+      });
+    },
+    RelationType(relation_type, zone_type, obj) {
+      let param = {
+        relation_type,
+        zone_type,
+        proId: {
+          projectId: this.projectId
+        }
+      };
+      this.computingNum++;
+      businessSpaceAll(param).then(res => {
+        this.computingNum--;
+        if (res.result != logicConfig.resultObj.success) {
+          this.$message({
+            message: "计算失败",
+            type: "error"
+          });
+        }
+        
+        this.init();
+      }).catch(err => {
+        console.log({err})
+      });
+      // todo
+      obj.computationalState = 3
+      setTimeout(() => {
+        this.updateState();
+      })
+    },
+    /**
+     * 计算需更新的关系
+     */
+    calcSpecialUpdate(params, obj) {
+			this.computingNum++;
+			calcSpecial(params, res => {
+				this.computingNum--;
+				if (res.result === "failure") {
+					this.$message.success('计算失败')
+				}
+				this.init();
+			})
+			obj.computationalState = 3
+			setTimeout(() => {
+				this.updateState();
+			})
+    },
+    statusCard() {
+
+    },
+    calcSpecial(relation) {
+      this.currentRelationTypeName = relation.RelationTypeName;
+    },
+
+    openComputed(result) {
+      let param = {
+        // BuildingId: '',
+        domain: "DomainPiping",
+        mepSystemType: "冷冻水供水管",
+        projectId: this.projectId,
+        sourceList: result
+      };
+      blockSource(param, res => {
+        //覆盖源端数据
+        //确定流向
+        result.forEach(i => {
+          let { blockId, buildingId, domain, source } = i;
+          this.DataSorting(blockId, buildingId, domain, source);
+        });
+      });
+    },
+    DataSorting(BlockId, BuildingId, Domain, source) {
+      let param = {
+        blockId: BlockId,
+        domain: Domain,
+        source,
+        buildingId: BuildingId,
+        systemName: this.currentRelationTypeName
+      };
+      sysDirection(param, res => {
+        this.init();
+      });
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+</style>

+ 106 - 0
src/controller/old-adm/relationController.ts

@@ -0,0 +1,106 @@
+import { baseHttpUtils } from "@/utils/http/baseHttpUtils";
+import { customHttpUtils } from '@/utils/http/customHttpUtils'
+import ScanUtil from '@/utils/scanUtil'
+import storage from '@/utils/storageUtil'
+import lstorage from '@/utils/old-adm/localStorage'
+ 
+export default class Relation{
+    static http = new baseHttpUtils();
+
+    /**
+     * @description: 添加源设备
+     * @param {*}
+     * @return {*}
+     */
+    static async addSource(params, fn) {
+        const res = await Relation.http.postRequest('/datacenter/mep-system-calc/source/add', params);
+        return fn ? fn(res) : res   
+    }
+    /**
+     * @description: 查看源设备
+     * @param {*} params
+     * @param {*} fn
+     * @return {*}
+     */    
+    static async sourceQuery(params, fn) {
+        const res = await Relation.http.postRequest(`/datacenter/mep-system-calc/source/query?calcName=${params.calcName}`, params);
+        return fn ? fn(res) : res   
+    }
+
+    /**
+     * @description:  获取源末端 2
+     * @param {*} params
+     * @param {*} fn
+     * @return {*}
+     */    
+    static async blockQuery(params, fn) {
+        const res = await Relation.http.postRequest(`/datacenter/graphic/connected-block-query`, params);
+        return fn ? fn(res) : res   
+    }
+    /**
+     * @description:  获取源末端 3
+     * @param {*} params
+     * @param {*} fn
+     * @return {*}
+     */    
+     static async blockSource(params, fn) {
+        const res = await Relation.http.postRequest(`/datacenter/graphic/replace-connected-block-source`, params);
+        return fn ? fn(res) : res   
+    }
+    /**
+     * @description:  建筑下的业务空间
+     * @param {*} params
+     * @param {*} fn
+     * @return {*}
+     */    
+     static async businessSpaceAll(params) {
+        const { relation_type, zone_type, proId } = params;
+        let userName = storage.get("user_name");
+        let ProjectId = lstorage.get("projectId");
+        let objectTypes = zone_type ? "?objectTypes=" + zone_type : ''
+        const url = (window as any).__systemConf.baseServiceUrl +  `${ScanUtil.datacenter}/relation-calc/${relation_type}${objectTypes}`
+        // const headers = { 'projectId': ProjectId, 'Comming': 'adm', 'Account': userName };
+        const customHttp =  new customHttpUtils();
+        
+        return await customHttp.customRequest(url, {}, proId, 'post');
+
+    }
+    /**
+     * @description: 管网系统设备分块 1
+     * @param {*} params
+     * @param {*} fn
+     * @return {*}
+     */    
+    static async calcSpecial(params, fn) {
+        const res = await Relation.http.postRequest(`/datacenter/calc_special/sys-block?relationType=${params.relationType}`, params);
+        return fn ? fn(res) : res
+    }
+   /**
+    * @description: 查询总览
+    * @param {*}
+    * @return {*}
+    */    
+    static async graphic(param, fn) {
+        const res = await Relation.http.postRequest(`${ScanUtil.datacenter}/graphic/overview`, param);
+        return fn ? fn(res) : res
+    }
+    /**
+    * @description: 查询总览数量
+    * @param {*}
+    * @return {*}
+    */    
+     static async graphicNumber(param, fn) {
+        const res = await Relation.http.postRequest(`${ScanUtil.datacenter}/graphic/query-count`, param);
+        return fn ? fn(res) : res
+    }
+    /**
+    * @description: 管网系统确定流向 4
+    * @param {*}
+    * @return {*}
+    */    
+     static async sysDirection(param, fn) {
+        let buildId = param.BuildingId ? `BuildingId=${param.BuildingId}&` : ''
+        const res = await Relation.http.postRequest(`${ScanUtil.datacenter}/calc_special/sys-direction?BlockId=${param.BlockId}&${buildId}Domain=${param.Domain}&SystemName=${param.SystemName}&isSource=${param.isSource}`, param);
+        return fn ? fn(res) : res
+    }
+}

+ 3 - 1
src/logicConfig/index.ts

@@ -16,7 +16,9 @@ export class logicConfig {
         //系统图编辑器主页面路由名称
         systemGraphName:'/systemGraph',
         //系统图编辑页面路由名称
-        systemGraphEditName:'/systemGraphEdit'
+        systemGraphEditName:'/systemGraphEdit',
+        // 现场交付工具-> CAD核查图纸管理路由
+        cadDrawingManageRoute: 'cadDrawingManage'
     };
     public static get routerNameConfig() {
         return this._routerNameConfig;

+ 25 - 2
src/router/system.js

@@ -13,6 +13,12 @@ import systemLedger from '@/components/old-adm/ledger/system/index';
 import batchPointAssets from '@/components/old-adm/ledger/facility/batchPoint' //批量维护设备位置
 import buildFloor from '@/components/old-adm/ready/buildfloor/index'
 
+// 全部关系总览
+import overView from '@/components/old-adm/relation/overview'
+
+//cad核查图纸管理
+import cadDrawingManage from '@/components/cadDrawingManage'
+
 export default [
   {
     path: logicConfig.routerNameConfig.loginRouteName,
@@ -58,9 +64,14 @@ export default [
       },
       {
         path: "/ledger/list",
-        name: "设备台账",
+        name: "系统台账",
         component: systemLedger,
-      }
+      },
+      {
+        path: '/relation/overview',
+        name: "全部关系总览",
+        component: overView,
+      },
     ],
   },
   {
@@ -68,4 +79,16 @@ export default [
     name: "系统图编辑器",
     component: systemGraphEdit,
   },
+  {
+    path: '/deliver',
+    name: '现场交付工具',
+    component: layoutMain,
+    children: [
+      {
+        path: logicConfig.routerNameConfig.cadDrawingManageRoute,
+        name: 'CAD核查图纸管理',
+        component: cadDrawingManage
+      }
+    ]
+  }
 ];