Pārlūkot izejas kodu

Merge branch 'report' into dev

yangjunjing 5 gadi atpakaļ
vecāks
revīzija
daaa87b75b

+ 27 - 0
src/api/model/report.js

@@ -0,0 +1,27 @@
+import httputils from '@/api/scan/httpUtil'
+import { Message } from 'element-ui';
+import axios from 'axios'
+const baseUrl = '/modelapi';
+
+// 导出模型问题报告
+export function exportReport(params, success) {
+    httputils.postJson(`${baseUrl}/upload-json-zip/upload`, params, success)
+}
+
+// 查询楼层列表
+export function queryFloorList(params, success) {
+    return httputils.postJson(`${baseUrl}/model-floor/query-list`, params, success)
+}
+
+// 获取项目下所有模型文件夹
+export function queryModel(params, success) {
+    return httputils.postJson(`${baseUrl}/model-folder/query`, params, success)
+}
+
+export function queryReportList(params, success) {
+    return httputils.postJson(`${baseUrl}/report/list/non-blocking`, params, success)
+}
+
+export function queryLostReportList(params, success) {
+    return httputils.postJson(`${baseUrl}/model-floor/query-list-missing`, params, success)
+}

+ 78 - 1
src/api/scan/request.js

@@ -1,5 +1,5 @@
 import fetch from './fetch'
-import {api, baseUrl, business, physics, venders, zone} from './config.js'
+import { api, baseUrl, business, physics, venders, zone } from './config.js'
 import http from './httpUtil'
 
 let arithmetic = '/arithmetic'
@@ -748,6 +748,12 @@ export function EqToAssets(param, success) {
     http.postJson(url, data, success)
 }
 
+//台账中待删除的对象
+export function queryLederDelObject(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/object-delete-count`
+    http.postJson(url, param, success)
+}
+
 //获取设定参数和动态参数
 export function BeatchQueryParam(param, success) {
     let url = `${physics}/parameter/batch_query_param?projectId=${param.ProjId}&secret=${param.secret}`
@@ -767,6 +773,24 @@ export function delBatchList(param, success) {
     http.postJson(url, data, success)
 }
 
+//根据条件查询统计数量
+export function queryCenoteCount(param, success) {
+    let url = `${baseUrl}/datacenter/shaft/count`
+    http.postJson(url, param, success)
+}
+
+//竖井-按功能类型占比
+export function queryShaftFunctionType(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/shaft-functype-count`
+    http.postJson(url, param, success)
+}
+
+//竖井-关联业务空间完成度
+export function ShaftRelationBusinessSpace(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/shaft2sp-count`
+    http.postJson(url, param, success)
+}
+
 //获取竖井类型
 export function getCenoteType(param, success) {
     let url = `${baseUrl}/datacenter/shaft/query-shaft-functype`
@@ -845,6 +869,17 @@ export function getRentTableData(param, success) {
     http.postJson(url, param, success)
 }
 
+//根据条件查询统计数量
+export function queryRentCount(param, success) {
+    let url = `${baseUrl}/datacenter/tenant/count`
+    http.postJson(url, param, success)
+}
+
+export function queryTenantCompletion(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/tenant2sp-count`
+    http.postJson(url, param, success)
+}
+
 //创建租户信息
 export function createRentTableData(param, success) {
     let url = `${baseUrl}/datacenter/tenant/create`
@@ -869,6 +904,24 @@ export function saveRentRelateSpace(param, success) {
     http.postJson(url, param, success)
 }
 
+//根据条件查询分区数量
+export function queryZoneCount(param, success) {
+    let url = `${baseUrl}/datacenter/zonespacebase/count`
+    http.postJson(url, param, success)
+}
+
+//业务空间-各分区占比
+export function queryPartitionRatio(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/sp-objecttype-count`
+    http.postJson(url, param, success)
+}
+
+//业务空间-默认分区功能类型占比
+export function queryDefaultFunTypes(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/general-sp-functype-count`
+    http.postJson(url, param, success)
+}
+
 //扫楼创建资产
 export function createFmList(param, success) {
     let url = `${api}/service/fm/create`
@@ -955,6 +1008,12 @@ export function createPart(param, success) {
     http.postJson(url, param, success)
 }
 
+// 查询部件总数
+export function queryPart(param, success) {
+    let url = `${baseUrl}/datacenter/component/count`;
+    http.postJson(url, param, success)
+}
+
 //设备清单 - 删除部件
 export function deleteParts(param, success) {
     let url = `${baseUrl}/datacenter/component/delete?projectId=${param.projectId}`;
@@ -1656,3 +1715,21 @@ export function getFloorMsgByFloorID(param, success) {
     let url = `${baseUrl}/datacenter/floor/query`
     http.postJson(url, param, success)
 }
+
+// 不能同步到物理世界的关系数据
+export function notSyncRelationData(param, success) {
+    let url = `${baseUrl}/datacenter/statistics/unsyn-relation-count`
+    http.postJson(url, param, success)
+}
+
+// 不能同步到物理世界的对象
+export function notSyncObject(param, success) {
+    let url = `${baseUrl}/equip-component/dict-custom/data-count`
+    http.postJson(url, param, success)
+}
+
+// 岗位和关联的资产信息点值不一致
+export function postRelationInforAtpism(param, success) {
+    let url = `${baseUrl}/datacenter//statistics/eq2pe-count`
+    http.postJson(url, param, success)
+}

+ 1 - 1
src/components/echarts/doughnut.vue

@@ -1,5 +1,5 @@
 <template>
-    <div style="width:100%;height:100%;" :id="id">
+    <div style="width:100%;height:100%;textAlign:center;" :id="id">
     </div>
 </template>
 <script>

+ 91 - 0
src/components/echarts/fanChart.vue

@@ -0,0 +1,91 @@
+<template>
+  <!-- 饼图 -->
+  <div style="width:100%;height:100%;textAlign:center;margin:-15px 0;" :id="id">
+  </div>
+</template>
+<script>
+import echarts from "echarts"
+export default {
+  name: "doughnut",
+  props: {
+    id: {
+      type: String,
+      default: function createRandomId() {
+        return (Math.random() * 10000000).toString(16).substr(0, 4) + '-' + (new Date()).getTime() + '-' + Math.random().toString().substr(2, 5);
+      }
+    },
+    renderData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    type: {},
+    name: "",
+    sum: ""
+  },
+  data() {
+    return {
+      myCharts: null
+    }
+  },
+  created() { },
+  mounted() {
+    this.drawDoughnut()
+  },
+  methods: {
+    drawDoughnut() {
+      let options = {
+        tooltip: {
+          trigger: 'item',
+          formatter: "{a} <br/>{b} : {c} ({d}%)"
+        },
+        series: [
+          {
+            name: '占比',
+            type: 'pie',
+            radius: '55%',
+            center: ['50%', '60%'],
+            data: this.renderData,
+            label: {
+              normal: {
+                show: false
+              },
+              emphasis: {
+                show: false
+              }
+            },
+            labelLine: {
+              normal: {
+                show: false
+              },
+              emphasis: {
+                show: false
+              }
+            }
+          }
+        ]
+      }
+      this.myCharts = echarts.init(document.getElementById(this.id))
+      this.myCharts.setOption(options)
+    },
+    delName(val) {
+      if (!!val && val.length > 3) {
+        return val.substring(0, 3) + '...'
+      } else {
+        return ''
+      }
+    }
+  },
+  watch: {
+    renderData: {
+      deep: true,
+      handler: function () {
+        this.drawDoughnut()
+      }
+    }
+  }
+}
+</script>
+<style>
+</style>

+ 123 - 0
src/components/echarts/reportDoughnut.vue

@@ -0,0 +1,123 @@
+<template>
+  <div style="width:100%;height:100%;textAlign:center;" :id="id">
+  </div>
+</template>
+<script>
+import echarts from "echarts"
+export default {
+  name: "doughnut",
+  props: {
+    id: {
+      type: String,
+      default: function createRandomId() {
+        return (Math.random() * 10000000).toString(16).substr(0, 4) + '-' + (new Date()).getTime() + '-' + Math.random().toString().substr(2, 5);
+      }
+    },
+    renderData: {
+      type: Array,
+      default: function () {
+        return []
+      }
+    },
+    text: {
+      type: String,
+      default: function () {
+        return []
+      }
+    },
+    type: {},
+    name: "",
+    sum: ""
+  },
+  created(){
+  },
+  data() {
+    return {
+      myCharts: null
+    }
+  },
+  created() { },
+  mounted() {
+    this.drawDoughnut()
+  },
+  methods: {
+    drawDoughnut() {
+      let options = {
+        tooltip: {
+          trigger: 'item',
+          formatter: "{b}: ({d}%)"
+        },
+        legend: {
+          show: false,
+          orient: 'vertical',
+          right: 10,
+          top: 30,
+          bottom: 20,
+          data: this.renderData.map(item => {
+            return item.name
+          })
+        },
+        series: [{
+          name: '',
+          type: 'pie',
+          radius: ['40%', '60%'],
+          itemStyle: {
+            normal: {
+              label: {
+                show: this.type != 'left' ? false : true,
+                textStyle: {
+                  color: '#3c4858',
+                  fontSize: "12"
+                },
+                formatter: function (val) { //让series 中的文字进行换行
+                  return val.name.split("-")[0];
+                }
+              },
+              title: {
+                text: 'aaaa'
+              },
+              labelLine: {
+                show: this.type != 'left' ? false : true,
+                lineStyle: {
+                }
+              }
+            },
+            emphasis: {
+              shadowBlur: 5,
+              shadowOffsetX: 0,
+              shadowColor: 'rgba(0, 0, 0, 0.5)',
+              textColor: '#000'
+            }
+          },
+          data: this.renderData
+        }],
+        color: ['#67C23A', 'rgb(225, 243, 216)', 'rgb(244, 244, 245)']
+      }
+      options.graphic = {
+        type: 'text',
+        left: 'center',
+        top: 'center',
+        style: {
+          text: `${this.text|| ''}`,
+          textAlign: 'center',
+          fill: '#000',
+          width: 30,
+          height: 30
+        }
+      }
+      this.myCharts = echarts.init(document.getElementById(this.id))
+      this.myCharts.setOption(options)
+    }
+  },
+  watch: {
+    renderData: {
+      deep: true,
+      handler: function () {
+        this.drawDoughnut()
+      }
+    }
+  }
+}
+</script>
+<style>
+</style>

+ 79 - 0
src/components/ledger/report/datafan.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="saga-fill">
+    <div class="mess-view">
+      <el-tooltip class="item" effect="dark" :content="renderData.tips" placement="bottom-start">
+        <i class="el-icon-info"><span>{{renderData.title}}</span></i>
+      </el-tooltip>
+    </div>
+    <div class="doughnut-view">
+      <fan-chart v-if="renderData.needCountO" type="type" width="200" height="200" :name="renderData.title" :renderData="echartsData" :id="id"></fan-chart>
+      <div v-else class="center">
+        <i class="icon-wushuju iconfont"></i>
+        暂无数据
+      </div>
+    </div>
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+import fanChart from "@/components/echarts/fanChart"
+export default {
+  data() {
+    return {
+      echartsData: []
+    }
+  },
+  created() {
+    this.echartsData = this.renderData.needCountO;
+  },
+  components: {
+    fanChart
+  },
+  methods: {
+  },
+  props: {
+    id: {
+      type: String,
+      default: function createRandomId() {
+        return (Math.random() * 10000000).toString(16).substr(0, 4) + '-' + (new Date()).getTime() + '-' + Math.random().toString().substr(2, 5);
+      }
+    },
+    renderData: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+}
+</script>
+
+<style lang="less" scoped>
+.mess-view {
+  box-sizing: border-box;
+  border-bottom: 1px solid #ddd;
+  padding: 10px 20px 10px 15px;
+  .saga-title {
+    font-size: 14px;
+    color: #333;
+    font-weight: 600;
+    line-height: 14px;
+  }
+  i {
+    span {
+      padding-left: 6px;
+    }
+  }
+}
+.saga-fill {
+  width: 345px;
+  height: 220px;
+  .doughnut-view {
+    height: 165px;
+    width: 100%;
+    padding: 0 5px;
+    box-sizing: border-box;
+  }
+}
+</style>

+ 105 - 0
src/components/ledger/report/dataorigin.vue

@@ -0,0 +1,105 @@
+<template>
+  <div class="saga-fill">
+    <div class="mess-view">
+      <el-tooltip class="item" effect="dark" :content="renderData.tips" placement="bottom-start">
+        <i class="el-icon-info"><span>{{renderData.title}}</span></i>
+      </el-tooltip>
+    </div>
+    <div class="doughnut-view">
+      <report-doughnut v-if="renderData.needCountO && renderData.needCountT" type="type" width="200" height="200" :sum="renderData.sum"
+        :name="renderData.title" :renderData="echartsData" :id="id" :text="renderData.text">
+      </report-doughnut>
+      <div v-else class="center">
+        <i class="icon-wushuju iconfont"></i>
+        暂无数据
+      </div>
+    </div>
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+import reportDoughnut from "@/components/echarts/reportDoughnut"
+export default {
+  name: "dataOrgin",
+  components: {
+    reportDoughnut
+  },
+  props: {
+    id: {
+      type: String,
+      default: function createRandomId() {
+        return (Math.random() * 10000000).toString(16).substr(0, 4) + '-' + (new Date()).getTime() + '-' + Math.random().toString().substr(2, 5);
+      }
+    },
+    renderData: {
+      type: Object,
+      default: function () {
+        return {
+
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      echartsData: []
+    }
+  },
+  created() {
+    this.changeData()
+  },
+  mounted() { },
+  methods: {
+    changeData() {
+      this.echartsData = [
+        {
+          name: this.renderData.contentValueO + this.renderData.needCountO,
+          value: this.renderData.needCountO
+        },
+        {
+          name: this.renderData.contentValueT + this.renderData.needCountT,
+          value: this.renderData.needCountT
+        },
+      ]
+    }
+  },
+  watch: {
+    renderData: {
+      deep: true,
+      handler: function () {
+        this.changeData()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.mess-view {
+  box-sizing: border-box;
+  border-bottom: 1px solid #ddd;
+  padding: 10px 20px 10px 15px;
+  .saga-title {
+    font-size: 14px;
+    color: #333;
+    font-weight: 600;
+    line-height: 14px;
+  }
+  i {
+    span {
+      padding-left: 6px;
+    }
+  }
+}
+.saga-fill {
+  width: 345px;
+  height: 220px;
+  .doughnut-view {
+    height: 165px;
+    width: 100%;
+    padding: 0 5px;
+    box-sizing: border-box;
+  }
+}
+</style>

+ 5 - 1
src/router/system.js

@@ -22,6 +22,8 @@ import repetitionGraphy from '@/views/ready/buildfloor/repetitionGraphy'
 /**模型管理 */
 import modelFile from '@/views/model/file'
 import modelReport from '@/views/model/report'
+import deleted from '@/views/model/report/deleted'
+import supplement from '@/views/model/report/supplement'
 
 /**系统集成 */
 import pointConfig from '@/views/point/config_point'
@@ -171,9 +173,11 @@ export default [{
                 name: 'modelReport',
                 component: modelReport,
                 meta: { keepAlive: false, breadcrumbs: [{ label: '模型管理', path: '/model/file' }, { label: '模型质量报告' }] }
-            }
+            },
         ]
     },
+    { path: '/model/report/deleted', name: 'deleted', component: deleted },
+    { path: '/model/report/supplement', name: 'supplement', component: supplement },
     // 系统集成
     {
         path: '/point',

+ 621 - 266
src/views/ledger/report/index.vue

@@ -1,295 +1,650 @@
 <template>
   <div>
-    <el-row style="margin-top: 30px;">
-      <span>请选择要导出的数据:</span>
-      <el-select v-model="value" placeholder="请选择">
-        <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
-      </el-select>
-      <el-button @click="handleClickDownload" type="primary" :loading="loading" style="margin-left: 15px;">导出Excel</el-button>
-    </el-row>
-    <div style="text-align:center;font-size:25px;margin-top:20%;">当前页面中的为临时功能,完整版正在设计中……</div>
+    <div class="data-display">
+      <ul class="list">
+        <li>
+          <p class="list-num">
+            <i class='el-icon-s-order'></i>
+            {{lederDelObjectCount?lederDelObjectCount:'0'}}
+          </p>
+          <p class="list-text">台账中待删除的对象</p>
+        </li>
+        <li>
+          <p class="list-num">
+            <i class="el-icon-s-help"></i>
+            {{notSyncObjectCount?notSyncObjectCount:'0'}}
+          </p>
+          <p class="list-text">不能同步到物理世界的对象</p>
+        </li>
+        <li>
+          <p class="list-num">
+            <i class="el-icon-s-marketing"></i>
+            {{notSyncDataCount?notSyncDataCount:'0'}}
+          </p>
+          <p class="list-text">不能同步到物理世界的关系数据</p>
+        </li>
+        <li>
+          <p class="list-num">
+            <i class="el-icon-s-release"></i>
+            {{postRelationInforCount?postRelationInforCount:'0'}}
+          </p>
+          <p class="list-text">岗位和关联的资产信息点值不一致</p>
+        </li>
+      </ul>
+    </div>
+    <div class="progress">
+      <p class="basic-statistics">基本统计</p>
+      <div class="data equipment">
+        <!-- 设备:本期只做前三个 -->
+        <span class="contain-title">设备<i>{{`(${equipCount?equipCount:"0"})`}}</i></span>
+        <div class="data-show" v-loading="isLoading" v-if="equipment.length">
+          <div class="show-content" v-for="(item,index) in equipment" :key="index">
+            <data-origin :id="'origin' + index" :renderData="item"></data-origin>
+          </div>
+        </div>
+        <div v-if="!equipment.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div class="data assets">
+        <span class="contain-title">资产<i>{{`(${assetsCount?assetsCount:"0"})`}}</i></span>
+        <div class="data-show" v-loading="isLoading" v-if="assets.length">
+          <div class="show-content" v-for="(item,index) in assets" :key="index">
+            <data-origin :id="'origin' + index" :renderData="item"></data-origin>
+          </div>
+        </div>
+        <div v-if="!assets.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div class="data parts">
+        <span class="contain-title">部件<i>{{`(${partsCount?partsCount:'0'})`}}</i></span>
+        <div v-if="!parts.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div class="data business-space">
+        <span class="contain-title">业务空间<i>{{`(${zoneSpaceCount?zoneSpaceCount:'0'})`}}</i></span>
+        <div class="data-show" v-if="business.length">
+          <div v-for="(item,index) in business" :key="index" class="show-content">
+            <datafan :id="'datafan' + index" :renderData="item"></datafan>
+          </div>
+        </div>
+        <div v-if="!business.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div class="data system">
+        <!-- 系统:本期只查询总数 -->
+        <span class="contain-title">系统<i>{{`(${systemCount?systemCount:'0'})`}}</i></span>
+        <div v-if="!system.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div class="data tenant">
+        <span class="contain-title">租户<i>{{`(${rentantCount?rentantCount:'0'})`}}</i></span>
+        <div class="data-show" v-loading="isLoading" v-if="tenant.length">
+          <div class="show-content" v-for="(item,index) in tenant" :key="index">
+            <data-origin :id="'origin' + item + index" :renderData="item"></data-origin>
+          </div>
+        </div>
+        <div v-if="!tenant.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+      <div class="data shaft">
+        <span class="contain-title">竖井<i>{{`(${shaftCount?shaftCount:'0'})`}}</i></span>
+        <div class="data-show" v-loading="isLoading" v-if="shaft.length">
+          <div class="show-content" v-for="(item,index) in shaft" :key="index">
+            <datafan :id="'origin' + shaft" :renderData="item" v-if="!item.needCountT"></datafan>
+            <data-origin :id="'origin' + item + index" :renderData="item" v-else></data-origin>
+          </div>
+        </div>
+        <div v-if="!shaft.length" class="center" style="height: 60%;transform: translateY(30%);">
+          <i class="icon-wushuju iconfont"></i>
+          暂无数据
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
 <script>
-import jsontoExcel from "@/utils/JOSNToExcel"
-import { State, Family } from "@/data/mapTable"
-import { queryEquip, queryProperty } from "@/api/scan/request"
-import { mapGetters, mapActions } from "vuex"
+import { mapGetters } from "vuex";
+import {
+  getCenoteType,
+  queryLederDelObject,
+  notSyncObject,
+  notSyncRelationData,
+  postRelationInforAtpism,
+  countEquip,
+  countProperty,
+  queryPart,
+  queryZoneCount,
+  queryPartitionRatio,
+  queryDefaultFunTypes,
+  countGeneralSys,
+  queryRentCount,
+  queryTenantCompletion,
+  queryCenoteCount,
+  queryShaftFunctionType,
+  ShaftRelationBusinessSpace,
+  getDataDictionary
+} from "@/api/scan/request";
+import dataOrigin from "@/components/ledger/report/dataorigin";
+import datafan from "@/components/ledger/report/datafan";
+import { queryDataSourceCount, synchronizeProj } from "@/fetch/point_http";
 
 export default {
   data() {
     return {
-      loading: false,
-      value: '',
-      dataList: [],
-      options: [{
-        value: 'header1',
-        label: '已建立关联的设备资产'
-      }, {
-        value: 'header2',
-        label: '未关联资产的设备'
-      }, {
-        value: 'header3',
-        label: '未关联设备的资产'
-      }],
-      header1: [{
-        fieldName: "Building.BuildLocalName",
-        headerName: "建筑"
-      }, {
-        fieldName: "Floor.FloorLocalName",
-        headerName: "楼层"
-      }, {
-        fieldName: "EquipCategory.EquipName",
-        headerName: "设备类"
-      }, {
-        fieldName: "EquipLocalName",
-        headerName: "设备本地名称"
-      }, {
-        fieldName: "EquipLocalID",
-        headerName: "设备本地编码"
-      }, {
-        fieldName: "EquipID",
-        headerName: "设备id"
-      }, {
-        fieldName: "BIMID",
-        headerName: "设备BIMID"
-      }, {
-        fieldName: "Property.EquipFamilyList.0.FamilyName",
-        headerName: "资产设备族"
-      }, {
-        fieldName: "Property.EquipLocalName",
-        headerName: "资产本地名称"
-      }, {
-        fieldName: "Property.EquipLocalID",
-        headerName: "资产本地编码"
-      }, {
-        fieldName: "Property.EquipID",
-        headerName: "资产id"
-      }, {
-        fieldName: "Property.CreateTime",
-        headerName: "资产创建时间"
-      }, {
-        fieldName: "Property.CodeType",
-        headerName: "资产现场验证状态"
-      }],
-      header2: [{
-        fieldName: "Building.BuildLocalName",
-        headerName: "建筑"
-      }, {
-        fieldName: "Floor.FloorLocalName",
-        headerName: "楼层"
-      }, {
-        fieldName: "EquipCategory.EquipName",
-        headerName: "设备类"
-      }, {
-        fieldName: "EquipLocalName",
-        headerName: "设备本地名称"
-      }, {
-        fieldName: "EquipLocalID",
-        headerName: "设备本地编码"
-      }, {
-        fieldName: "EquipID",
-        headerName: "设备id"
-      }, {
-        fieldName: "BIMID",
-        headerName: "设备BIMID"
-      }, {
-        fieldName: "Property.EquipFamilyList.0.FamilyName",
-        headerName: "资产设备族"
-      }, {
-        fieldName: "Property.EquipLocalName",
-        headerName: "资产本地名称"
-      }, {
-        fieldName: "Property.EquipLocalID",
-        headerName: "资产本地编码"
-      }, {
-        fieldName: "Property.EquipID",
-        headerName: "资产id"
-      }, {
-        fieldName: "Property.CreateTime",
-        headerName: "资产创建时间"
-      }, {
-        fieldName: "Property.CodeType",
-        headerName: "资产现场验证状态"
-      }],
-      header3: [{
-        fieldName: "Building.BuildLocalName",
-        headerName: "建筑"
-      }, {
-        fieldName: "Floor.FloorLocalName",
-        headerName: "楼层"
-      }, {
-        fieldName: "Equipment.EquipCategory.EquipName",
-        headerName: "设备类"
-      }, {
-        fieldName: "Equipment.EquipLocalName",
-        headerName: "设备本地名称"
-      }, {
-        fieldName: "Equipment.EquipLocalID",
-        headerName: "设备本地编码"
-      }, {
-        fieldName: "Equipment.EquipID",
-        headerName: "设备id"
-      }, {
-        fieldName: "Equipment.BIMID",
-        headerName: "设备BIMID"
-      }, {
-        fieldName: "EquipFamilyList.0.FamilyName",
-        headerName: "资产设备族"
-      }, {
-        fieldName: "EquipLocalName",
-        headerName: "资产本地名称"
-      }, {
-        fieldName: "EquipLocalID",
-        headerName: "资产本地编码"
-      }, {
-        fieldName: "EquipID",
-        headerName: "资产id"
-      }, {
-        fieldName: "CreateTime",
-        headerName: "资产创建时间"
-      }, {
-        fieldName: "CodeType",
-        headerName: "资产现场验证状态"
-      }
-      ]
+      lederDelObjectCount: null,// 台账中待删除的对象
+      notSyncObjectCount: null,// 不能同步到物理世界的对象
+      notSyncDataCount: null,// 不能同步到物理世界的关系数据
+      postRelationInforCount: null,// 岗位和关联的资产信息点值不一致
+      equipCount: null,// 设备总数
+      equipment: [],// 设备数据
+      assetsCount: null,// 资产总数
+      assets: [],// 资产数据
+      parts: [],// 部件数据
+      partsCount: null,// 部件总数
+      zoneSpaceCount: null,// 业务空间总数
+      zoneType: [// 分区类型
+        {
+          "Code": "GeneralZone",
+          "Name": "默认分区",
+          "Rel_type": "99"
+        },
+        {
+          "Name": "供电分区",
+          "Rel_type": "1",
+          "Code": "PowerSupplyZone"
+        },
+        {
+          "Name": "照明分区",
+          "Rel_type": "2",
+          "Code": "LightingZone"
+        },
+        {
+          "Name": "网络分区",
+          "Rel_type": "3",
+          "Code": "NetworkZone"
+        },
+        {
+          "Code": "AirConditioningZone",
+          "Name": "空调分区",
+          "Rel_type": "4"
+        },
+        {
+          "Name": "采暖分区",
+          "Rel_type": "5",
+          "Code": "HeatingZone"
+        },
+        {
+          "Name": "洁净分区",
+          "Rel_type": "6",
+          "Code": "CleanZone"
+        },
+        {
+          "Name": "生活给水分区",
+          "Rel_type": "7",
+          "Code": "DomesticWaterSupplyZone"
+        },
+        {
+          "Code": "FireZone",
+          "Name": "防火分区",
+          "Rel_type": "8"
+        },
+        {
+          "Name": "安防分区",
+          "Rel_type": "9",
+          "Code": "SecurityZone"
+        },
+        {
+          "Name": "租户分区",
+          "Rel_type": "10",
+          "Code": "TenantZone"
+        },
+        {
+          "Name": '功能分区',
+          'Rel_type': '11',
+          "Code": 'FunctionZone'
+        }
+      ],
+      partProtion: [],// 业务空间-各分区占比数据
+      defaultPart: [],// 业务空间-默认分区功能类型占比数据
+      business: [],// 业务空间数据
+      systemCount: null,// 系统总数
+      system: [],// 系统数据
+      rentantCount: null,// 租户总数
+      tenant: [],// 租户数据
+      shaftCount: null,// 竖井总数
+      shaft: [],// 竖井数据
+      ShaftFunType: null,// 竖井功能类型
+      shaftPartProtion: [],// 竖井-按功能类型占比数据
+      params: null,
+      isLoading: false,
+      color: ["#3485d6", "#a384fc", "#4caf50", "#ff6316", "#fd8bbe", "#03a9f3", "#ea615b"]
+    }
+  },
+  components: {
+    dataOrigin,
+    datafan
+  },
+  mounted() { },
+  created() {
+    this.params = {
+      ProjectId: this.projectId
     }
+    this.getFunctionType();
+    this.getStatisticsCount();
+    this.getEquipCount();
+    this.getAssetsCount();
+    this.getPartsCount();
+    this.getSystemCount();
+    this.getTenantCount();
+    this.getShaftFunType();
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId'])
   },
   methods: {
-    handleClickDownload() {
-      this.loading = true
-      this.dataList = []
-      if (this.value == 'header1') {
-        this.getheader1Data()
-      } else if (this.value == 'header2') {
-        this.getheader2Data()
-      } else if (this.value == 'header3') {
-        this.getheader3Data()
-      }
+    zoneTypeConversion(item) {// 分区类型转换
+      this.zoneType.map(it => {
+        if (item.Name === it.Code) {
+          item.Name = it.Name;
+        }
+      })
     },
-    getheader1Data(pageNum) {
-      pageNum = pageNum ? pageNum : 1
-      let params = {
-        Cascade: [
-          {
-            Name: "equipCategory",
-            Projection: ["EquipCode", "EquipName"]
-          },
-          {
-            Name: "property",
-            Cascade: [
-              {
-                Name: "equipFamilyList",
-                Projection: [ "Family", "FamilyName" ]
-              }
-            ],
-            Projection: ["Family", "EquipLocalName", "EquipLocalID", "EquipID", "CodeType", "CreateTime"]
-          },
-          {
-            Name: "building",
-            Projection: ["BuildLocalName", "BuildName", "BuildID"]
-          },
-          {
-            Name: "floor",
-            Projection: ["FloorLocalName", "FloorName", "FloorID"]
-          }
-        ],
-        Filters: " not propertyId isnull ",
-        Orders: "CreateTime desc, EquipID asc",
-        PageNumber: pageNum,
-        PageSize: 1000,
-        Projection: ["CreateTime", "BuildingId", "FloorId", "Category", "EquipLocalName", "EquipLocalID", "EquipID", "BIMID"]
-      }
-      queryEquip(params, res => {
-        this.dataList = this.dataList.concat(res.Content.map((item) => {
-          item.Property.CodeType = State[item.Property.CodeType]
-          // item.Property.Family = Family[item.Property.Family]
-          return item
-        }))
-        if (res.Total / (res.PageSize * res.PageNumber) > 1) {
-          this.getheader1Data(res.PageNumber + 1)
-        } else {
-          let time = +new Date()
-          this.loading = false
-          jsontoExcel.downloadExl(this.header1, this.dataList, `已建立关联的资产设备-${time}`)
+    functionTypeTranstion(item, type) {// 默认分区功能类型转换
+      type.map(it => {
+        if (item.Name === it.Code) {
+          item.Name = it.Name;
+          this.defaultPart.push({
+            name: item.Name,
+            value: item.Count
+          });
+          // this.defaultPart.map((item, index) => {
+          //   item.itemStyle = {color:this.color}
+          // })
+        }
+        if (it.Content) {
+          this.functionTypeTranstion(item, it.Content)
         }
       })
     },
-    getheader2Data(pageNum) {
-      pageNum = pageNum ? pageNum : 1
+    getFunctionType() {// 获取默认分区功能类型
       let params = {
-        Cascade: [
-          {
-            Name: "equipCategory",
-            Projection: ["EquipCode", "EquipName"]
-          },
-          {
-            Name: "building",
-            Projection: ["BuildLocalName", "BuildName", "BuildID"]
-          },
-          {
-            Name: "floor",
-            Projection: ["FloorLocalName", "FloorName", "FloorID"]
-          }
-        ],
-        Filters: " propertyId isnull ",
-        Orders: "CreateTime desc, EquipID asc",
-        PageNumber: pageNum,
-        PageSize: 1000,
-        Projection: ["CreateTime", "BuildingId", "FloorId", "Category", "EquipLocalName", "EquipLocalID", "EquipID", "BIMID"]
+        ProjectId: this.projectId,
+        type: "GeneralZone",
+        data: {
+          Filters: "InfoPointCode='RoomFuncType'",
+          Projection: ["DataSource", "InfoPointCode"]
+        }
+      }
+      getDataDictionary(params, res => {
+        this.functionType = JSON.parse(res.Content[0].DataSource)
+        this.getZoneSpaceCount();
+      })
+    },
+    toPercent(point) {// 小数转换成百分比
+      if (point == 0) {
+        return 0;
       }
-      queryEquip(params, res => {
-        this.dataList = this.dataList.concat(res.Content)
-        if (res.Total / (res.PageSize * res.PageNumber) > 1) {
-          this.getheader2Data(res.PageNumber + 1)
-        } else {
-          let time = +new Date()
-          this.loading = false
-          jsontoExcel.downloadExl(this.header2, this.dataList, `未关联资产的设备-${time}`)
+      var str = Number(point * 100).toFixed(2);
+      str += "%";
+      return str;
+    },
+    getShaftFunType() {// 获取数据功能类型
+      getCenoteType(this.param, res => {
+        this.ShaftFunType = res.Content;
+        this.getShaftCount();
+      })
+    },
+    shaftFunTypeTranstion(item) {// 竖井功能类型转换
+      this.ShaftFunType.map((it, index) => {
+        if (item.Name === it.Id) {
+          item.Name = it.Name;
         }
       })
     },
-    getheader3Data(pageNum) {
-      pageNum = pageNum ? pageNum : 1
+
+    getStatisticsCount() {// 获取顶部统计数据
       let params = {
-        Cascade: [
-          {
-            Name: "equipFamilyList",
-            Projection: [ "Family", "FamilyName" ]
-          },
-          {
-            Name: "building",
-            Projection: [ "BuildLocalName", "BuildName", "BuildID" ]
-          },
-          {
-            Name: "floor",
-            Projection: [ "FloorLocalName", "FloorName", "FloorID" ]
-          }
-        ],
-        Filters: " EquipmentId isnull ",
-        Orders: "CreateTime desc, EquipID asc",
-        PageNumber: pageNum,
-        PageSize: 1000,
-        Projection: [ "BuildingId", "FloorId", "Family", "EquipLocalName", "EquipLocalID", "EquipID", "CreateTime", "CodeType" ]
+        ProjectId: this.projectId,
+        Filters: "taskState = -1"
       }
-      queryProperty(params, res => {
-        this.dataList = this.dataList.concat(res.Content.map((item) => {
-          item.CodeType = State[item.CodeType]
-          return item
-        }))
-        if (res.Total / (res.PageSize * res.PageNumber) > 1) {
-          this.getheader3Data(res.PageNumber + 1)
-        } else {
-          let time = +new Date()
-          this.loading = false
-          jsontoExcel.downloadExl(this.header3, this.dataList, `未关联设备的资产-${time}`)
-        }
+
+      // 台账中待删除的对象
+      queryLederDelObject(params, res => {
+        this.lederDelObjectCount = res.Count;
+      })
+
+      // 不能同步到物理世界的对象
+      notSyncObject(this.params, res => {
+        this.notSyncObjectCount = res.Count;
+      })
+
+      // 不能同步到物理世界的关系数据
+      notSyncRelationData(this.params, res => {
+        this.notSyncDataCount = res.Count;
+      })
+
+      // 岗位和关联的资产信息点值不一致
+      postRelationInforAtpism(this.params, res => {
+        this.postRelationInforCount = res.Count;
+      })
+    },
+    getNotSyncObject() {
+
+    },
+    getEquipCount() {// 获取设备总数
+      countEquip(this.params, res => {
+        this.equipCount = res.Count;
+        this.getEquipOtherCount();
+      })
+    },
+    getEquipOtherCount() {// 获取设备数据
+      // 未关联资产
+      let param = {
+        ProjectId: this.projectId,
+        Filters: "PropertyId isNull"
+      }
+      countEquip(param, res => {
+        this.equipment.push({
+          title: '未关联资产',
+          tips: '设备未关联资产数量',
+          contentValueO: '未关联',
+          contentValueT: '已关联',
+          text: '',
+          needCountO: res.Count,
+          needCountT: this.equipCount - res.Count,
+          text: `总数${this.equipCount}`
+        })
+      })
+
+      // 现场验证状态占比
+      let par = {
+        ProjectId: this.projectId,
+        Filters: "taskState = 0 or taskState = 1"
+      }
+      countEquip(par, res => {
+        let text = this.toPercent(res.Count / this.equipCount)
+        this.equipment.push({
+          title: '现场验证状态占比',
+          tips: '设备状态为未找到、已找到的数量与设备总数占比',
+          contentValueO: '已验证',
+          contentValueT: '未验证',
+          text: '',
+          needCountO: res.Count,
+          needCountT: this.equipCount - res.Count,
+          text: text
+        })
+        this.getEquipBIMIDCount();
+      })
+    },
+    getEquipBIMIDCount() {// 设备-与模型对应占比
+      let pa = {
+        ProjectId: this.projectId,
+        Filters: "not BimID isNull"
+      }
+      countEquip(pa, res => {
+        let text = this.toPercent(res.Count / this.equipCount)
+        this.equipment.push({
+          title: '与模型对应占比',
+          tips: '"BIM模型中编码"有值的设备数量与设备总数占比',
+          contentValueO: '有BIMID',
+          contentValueT: '无BIMID',
+          text: '',
+          needCountO: res.Count,
+          needCountT: this.equipCount - res.Count,
+          text: text
+        })
+        this.isLoading = false;
+      })
+    },
+    getAssetsCount() {// 获取资产数据
+      countProperty(this.params, res => {
+        // 获取资产总数
+        this.assetsCount = res.Count;
+      })
+
+      // 未关联资产
+      let param = {
+        ProjectId: this.projectId,
+        Filters: " EquipmentId isnull"
+      }
+      countProperty(param, res => {
+        this.assets.push({
+          title: '未关联资产',
+          tips: '资产未关联设备数量',
+          contentValueO: '未关联',
+          contentValueT: '已关联',
+          text: `总数${this.assetsCount}`,
+          needCountO: res.Count,
+          needCountT: this.assetsCount - res.Count
+        })
+      })
+
+      // 现场验证状态占比
+      let par = {
+        ProjectId: this.projectId,
+        Filters: " taskState = 0 or taskState = 1"
+      }
+      countProperty(par, res => {
+        let text = res.Count / this.assetsCount;
+        text = this.toPercent(text);
+        this.assets.push({
+          title: '现场验证状态占比',
+          tips: '资产状态为未找到、已找到的数量与资产总数占比',
+          contentValueO: '已验证',
+          contentValueT: '未验证',
+          text: text,
+          needCountO: res.Count,
+          needCountT: this.assetsCount - res.Count
+        })
+      })
+
+      // 有无坐标占比
+      let pa = {
+        ProjectId: this.projectId,
+        Filters: " not BIMLocation isnull"
+      }
+      countProperty(pa, res => {
+        let text = res.Count / this.assetsCount;
+        text = this.toPercent(text);
+        this.assets.push({
+          title: '有无坐标占比',
+          tips: '有坐标的资产数量百分比',
+          contentValueO: '有坐标',
+          contentValueT: '无坐标',
+          text: text,
+          needCountO: res.Count,
+          needCountT: this.assetsCount - res.Count
+        })
+      })
+    },
+    getPartsCount() {// 获取部件数据
+      queryPart(this.params, res => {
+        this.partsCount = res.Count;
+      })
+    },
+    getZoneSpaceCount() {// 获取业务空间数据
+
+      // 获取业务空间总数
+      queryZoneCount(this.params, res => {
+        this.zoneSpaceCount = res.Count;
+      })
+
+      // 获取业务空间的各分区占比
+      queryPartitionRatio(this.params, res => {
+        res.Content.map(item => {
+          this.zoneTypeConversion(item);
+          this.partProtion.push({
+            name: item.Name,
+            value: item.Count
+          })
+        })
+        this.business.push({
+          title: '各分区占比',
+          tips: '各类型分区实例数量与实例总数占比',
+          needCountO: this.partProtion,
+        })
+      })
+
+      // 获取业务空间默认分区功能类型占比
+      queryDefaultFunTypes(this.params, res => {
+        res.Content.map(item => {
+          this.functionTypeTranstion(item, this.functionType);
+        })
+        this.business.push({
+          title: '默认分区功能类型占比',
+          tips: '默认分区实例的功能区类型占比',
+          needCountO: this.defaultPart,
+        })
+      })
+    },
+    getSystemCount() {// 获取系统数据
+      countGeneralSys(this.params, res => {
+        this.systemCount = res.Count;
+      })
+    },
+    getTenantCount() {// 获取租户数据
+
+      // 获取租户总数
+      queryRentCount(this.params, res => {
+        this.rentantCount = res.Count;
+      })
+
+      // 租户-关联业务空间完成度
+      queryTenantCompletion(this.params, res => {
+        let text = res.Count / this.rentantCount;
+        text = this.toPercent(text);
+        this.tenant.push({
+          title: '关联业务空间完成度',
+          tips: '已关联业务空间的租户数量百分比',
+          contentValueO: '已关联',
+          contentValueT: '未关联',
+          text: '',
+          needCountO: res.Count,
+          needCountT: this.rentantCount - res.Count,
+          text: text
+        })
+      })
+    },
+    getShaftCount() {// 获取竖井数据
+
+      // 获取竖井总数
+      queryCenoteCount(this.params, res => {
+        this.shaftCount = res.Count;
+      })
+
+      // 获取竖井按功能类型占比
+      queryShaftFunctionType(this.params, res => {
+        res.Content.map(item => {
+          this.shaftFunTypeTranstion(item);
+          this.shaftPartProtion.push({
+            name: item.Name,
+            value: item.Count
+          })
+        })
+        this.shaft.push({
+          title: '按功能类型占比',
+          tips: '竖井实例的竖井功能占比',
+          needCountO: this.shaftPartProtion,
+        })
+      })
+
+      // 获取竖井关联业务空间完成度
+      ShaftRelationBusinessSpace(this.params, res => {
+        let text = this.toPercent(res.Count / this.shaftCount);
+        this.shaft.push({
+          title: '关联业务空间完成度',
+          tips: '已关联业务空间的竖井数量百分比',
+          contentValueO: '已关联',
+          contentValueT: '未关联',
+          needCountO: res.Count,
+          needCountT: this.shaftCount - res.Count,
+          text: text
+        })
       })
     }
-  }
+  },
 }
 </script>
 
-<style scoped>
-</style>
+<style lang="scss" scoped>
+.data-display {
+  width: 100%;
+  margin-bottom: 10px;
+  ul {
+    display: flex;
+    li {
+      flex: 1;
+      background: white;
+      border: 1px solid #c9c9c9;
+      text-align: center;
+      padding: 20px;
+      box-sizing: border-box;
+      p {
+        color: #333;
+        i {
+          margin-right: 20px;
+        }
+      }
+      p:nth-child(1) {
+        font-size: 24px;
+      }
+      + li {
+        margin-left: 10px;
+      }
+    }
+  }
+}
+.progress {
+  width: 100%;
+  .basic-statistics {
+    border-bottom: 1px dashed #c9c9c9;
+    padding-bottom: 10px;
+    margin-bottom: 10px;
+  }
+  .data {
+    // background: white;
+    margin-bottom: 20px;
+    height: 280px;
+    .contain-title {
+      height: 30px;
+      line-height: 30px;
+      border-left: 8px solid black;
+      display: inline-block;
+      margin: 8px 8px;
+      font-weight: 600;
+      padding-left: 8px;
+      cursor: default;
+      i {
+        margin-left: 6px;
+        font-weight: normal;
+      }
+    }
+  }
+}
+.data-show {
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+  .show-content {
+    background: white;
+    overflow: hidden;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    border: 1px solid #c9c9c9;
+    border-radius: 5px;
+  }
+}
+</style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 242 - 0
src/views/model/report/deleted.vue


+ 406 - 26
src/views/model/report/index.vue

@@ -1,36 +1,416 @@
 <template>
-    <div>
-      <das-board>
-        <template v-slot:plan>
-          <span>{{plan?plan:"yyyy-mm-dd"}}</span>
-        </template>
-        <template v-slot:finish>
-          <span>{{finish?finish:"yyyy-mm-dd"}}</span>
-        </template>
-        <template v-slot:onLine>
-          <span>{{onLine?onLine:"yyyy-mm-dd"}}</span>
-        </template>
-        <template v-slot:explain>
-          <span>{{explain?explain:"yyyy-mm-dd"}}</span>
-        </template>
-      </das-board>
+  <div>
+    <div class="statistics">
+      <div class="building">
+        <p>建筑模型文件夹:<b>{{ModelFileCount}}</b></p>
+      </div>
+      <div class="includefloor">
+        <p>包含楼层模型文件:<b>{{modelFloorCount}}</b></p>
+      </div>
+      <div class="problematic">
+        <p>检查出问题的楼层模型文件:<b>{{problemCount}}</b></p>
+      </div>
     </div>
+    <div class="main-content">
+      <div class="tab-box">
+        <el-tabs v-model="activeTab" type='card' @tab-click="getData">
+          <template v-for="(item,index) in tableList">
+            <el-tab-pane :name="item.Code" :key="index" :label="item.Name">
+              <span slot="label">
+                <i :class="floorIconType?'msg-icon el-icon-error error-color':'msg-icon el-icon-success success-color'" style="font-size:14px;"></i>
+                <span>{{ item.Name }}</span>
+              </span>
+            </el-tab-pane>
+          </template>
+        </el-tabs>
+      </div>
+      <div class="content-box">
+        <div class="button">
+          <el-link :underline="false" @click="del">需从模型中删除的设备</el-link>
+          <el-link href="" @click="supplement" :underline="false" type="info">模型待补充的设备</el-link>
+          <el-link href="" download="" :underline="false" type="info">导出模型问题报告</el-link>
+        </div>
+        <div class="table" style="width: 100%;height: calc(100% - 47px)">
+          <el-table ref="multipleTable" :data="tableData" stripe height="100%" :header-cell-style="headerStyle" v-loading='loading'>
+            <el-table-column prop="FloorName" label="模型楼层" fixed width="150"></el-table-column>
+            <el-table-column prop="functionNo" label="待删除设备数量" fixed width="150">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.toBeDel" class="item" :type='scope.row.toBeDel?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="" label="待补充设备数量" fixed width="150">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.toBeSupplement" class="item" :type='scope.row.toBeSupplement?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="itemsProblemsCheck" label="有问题的检查项" fixed width="150">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.itemsProblemsCheck" class="item" :type='scope.row.itemsProblemsCheck?"warning":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="ElementRangeCheck" label='构件范围检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.ElementRangeCheck" class="item" :type='scope.row.ElementRangeCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="FamilyNameCheck" label='设备族编码检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.FamilyNameCheck" class="item" :type='scope.row.FamilyNameCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="EquipPartLocationCheck" label='部件所在位置检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.EquipPartLocationCheck" class="item" :type='scope.row.EquipPartLocationCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="ColumnCheck" label='柱边界检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.ColumnCheck" class="item" :type='scope.row.ColumnCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="ConnectorCheck" label='连接件检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.ConnectorCheck" class="item" :type='scope.row.ConnectorCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="SystemNameCheck" label='系统类型名称检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.SystemNameCheck" class="item" :type='scope.row.SystemNameCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="EquipInSpaceCheck" label='未在空间中的设备' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.EquipInSpaceCheck" class="item" :type='scope.row.EquipInSpaceCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="PipeCheck" label='管段检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.PipeCheck" class="item" :type='scope.row.PipeCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="SystemReferEquipCheck" label='管网及相关设备检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.SystemReferEquipCheck" class="item" :type='scope.row.SystemReferEquipCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="ParameterIntegrityCheck" label='Revit族参数完整性检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.ParameterIntegrityCheck" class="item" :type='scope.row.ParameterIntegrityCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <el-table-column prop="XyzOverlapCheck" label='xyz坐标重叠检查' width="200">
+              <template slot-scope="scope">
+                <el-badge :value="scope.row.XyzOverlapCheck" class="item" :type='scope.row.XyzOverlapCheck?"danger":"success"'>
+                </el-badge>
+              </template>
+            </el-table-column>
+            <template slot="empty">
+              <div style="height: 60%;transform: translate(-22%,50%);">
+                <i class="icon-wushuju iconfont"></i>
+                数据暂无
+              </div>
+            </template>
+          </el-table>
+          <el-pagination class="right" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.pageNumber"
+            :page-sizes="page.pageSizes" :page-size="page.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="page.total">
+          </el-pagination>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
+import { mapGetters } from "vuex";
 import dasBoard from "@/views/dasboard/index";
+import request from "@/api/model/file.js";
+import { exportReport, queryFloorList, queryModel, queryReportList, queryLostReportList } from "@/api/model/report.js";
 export default {
-    components: {
-      dasBoard
-    },
-    data() {
-        return {
-          plan: "2019-09-04",
-          finish: "2019-10-17",
-          onLine: "2019-10-30",
-          explain: "模型校验后的数据报告,用于查看上传模型的相关情况。"
+  components: {
+    dasBoard
+  },
+  data() {
+    return {
+      params: null,
+      ModelFileCount: null,// 模型文件夹数量
+      modelFloorCount: null,// 包含楼层模型文件数量
+      problemCount: 0,// 检查出问题的楼层模型文件数量
+      tableList: [], // tab数据
+      tableData: [],// 列表数据
+      activeTab: '', // tab当前选中项
+      headerStyle: { // 列表样式
+        backgroundColor: '#e1e4e5',
+        color: '#2b2b2b',
+        lineHeight: '30px'
+      },
+      page: {
+        pageSize: 50,
+        pageSizes: [10, 20, 50, 100],
+        pageNumber: 1,
+        total: 0
+      },
+      loading: false,
+      lostFloort: {
+        ary: [],
+        Bary: [],
+        Fary: [],
+        regex: /^(B||F)(\d)/
+      },
+      floorIconType: null
+    }
+  },
+  mounted() { },
+  created() {
+    this.params = {
+      ProjectId: this.projectId
+    }
+    this.getModelFileCount();
+    this.getModelFloorCount();
+  },
+  computed: {
+    ...mapGetters('layout', ['projectId'])
+  },
+  methods: {
+    getlostFloors(ary, eng, FloorName) {// 获取缺失楼层
+      let newAry = ary[0];
+      if (newAry.FloorName !== '1') {
+        ary.unshift({ FloorName: `${1}` })
+      }
+      for (let i = 0; i < ary.length; i++) {
+        if (i === ary.length - 1) {
+          break;
+        }
+        let x = ary[i].FloorName;
+        let y = ary[i + 1].FloorName;
+        let z = { FloorName: `${Number(x) + 1}` };
+        if (Number(x) + 1 !== Number(y)) {
+          ary.splice(i + 1, 0, z)
+          i++;
+        }
+      }
+      for (let i = 0; i < ary.length; i++) {
+        ary[i].FloorName = `${eng + ary[i].FloorName}`;
+      }
+      for (let i = 0; i < ary.length; i++) {
+        for (let j = 0; j < FloorName.length; j++) {
+          if (ary[i].FloorName === FloorName[j].FloorName) {
+            break;
+          } else {
+            if (j === FloorName.length - 1) {
+              ary[i].FloorName = `${'丢失' + ary[i].FloorName}`
+            }
+          }
+        }
+      }
+    },
+    getModelFileCount() {// 获取项目下所有模型文件夹
+      let params = {
+        ProjectId: this.projectId,
+      }
+      queryModel(this.params, res => {
+        this.ModelFileCount = res.Content.length;
+        this.tableList = res.Content;
+        this.tableList.map((item, index) => {
+          item.Code = item.Id;
+        })
+        this.activeTab = this.tableList[0].Code;// 默认选中第一个模型文件夹
+        this.getExportReport();
+        this.getModelFloor();
+      });
+    },
+    getModelFloorCount() {// 获取楼层模型文件数量,计算出检查出问题的模型文件
+      queryFloorList(this.params, res => {
+        this.modelFloorCount = res.Total;
+        res.Content.map(item => {
+          if (!item.DataCheckResult) {
+            this.problemCount += 1;
+          }
+        })
+      });
+    },
+    getExportReport() {
+      let params = {
+        ProjectId: this.projectId,
+        Id: this.activeTab
+      }
+      // exportReport(params,res => {
+      //   console.log(res,3958)
+      // });
+    },
+    getData(tab) {// 切换tab时执行
+      this.getExportReport();
+      this.getModelFloor();
+    },
+    getModelFloor() {// 获取当前楼层下的模型楼层
+      let params = {
+        ProjectId: this.projectId,
+        Id: `${this.activeTab}`,
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      queryReportList(params, res => {
+        if (res.Content) {
+          let that = this;
+          this.FloorName = res.Content;
+          this.lostFloort.ary = [];
+          this.lostFloort.Bary = [];
+          this.lostFloort.Fary = [];
+          for (let i = 0; i < this.FloorName.length; i++) {
+            let it = this.FloorName[i];
+            if (this.lostFloort.regex.test(it.FloorName)) {
+              it.FloorName.replace(/^(B||F)(\d)/g, function (a, b, c) {
+                if (b === "B") {
+                  it.FloorName = c;
+                  that.lostFloort.Bary.push(it);
+                } else if (b === "F") {
+                  it.FloorName = c;
+                  that.lostFloort.Fary.push(it);
+                }
+              })
+            } else {
+              this.lostFloort.ary.push(it)
+            }
+          }
+          if (this.lostFloort.Bary.length > 0) {
+            this.getlostFloors(this.lostFloort.Bary, "B", this.FloorName)
+          }
+          if (this.lostFloort.Fary.length > 0) {
+            this.getlostFloors(this.lostFloort.Fary, "F", this.FloorName)
+          }
+          if (this.lostFloort.Bary.length < 0 && this.lostFloort.Fary.length < 0) {
+            this.tableData = res.Content;
+          } else {
+            this.tableData = [...this.lostFloort.ary, ...this.lostFloort.Bary, ...this.lostFloort.Fary]
+          }
+          let i;
+          let j = 0;
+          this.tableData.map(item => {
+            i = 0;
+            for (let key in item) {
+              if (item[key] > 0) {
+                i += 1;
+              }
+            }
+            if (item.ColumnCheck !== undefined) {
+              item.itemsProblemsCheck = i;
+              item.toBeDel = 10;
+              item.toBeSupplement = 6;
+            }
+            if (item.itemsProblemsCheck) {
+              j += 1;
+              this.floorIconType = j;
+            }
+          })
+        } else {
+          this.tableData = [];
         }
+        this.getLostModelFloor();
+      })
+    },
+    getLostModelFloor() {
+      let param = {
+        ProjectId: this.projectId,
+        Filters: `FolderId=${this.activeTab};Status=4`,
+        PageNumber: this.page.pageNumber,
+        PageSize: this.page.pageSize
+      }
+      // queryLostReportList(param, res => {
+      //   console.log(res, 'lost');
+      //   this.LostFloorName = res.Content;
+      //   for (let i = 0; i < this.LostFloorName.length; i++) {
+      //     for (let j = 0; j < this.FloorName.length; j++) {
+      //       if (this.LostFloorName[i].FloorName == this.FloorName.FloorName) {
+      //         continue;
+      //       } else {
+      //         this.FloorName.splice(i, 0, this.LostFloorName[i])
+      //       }
+      //     }
+      //   }
+      //   this.tableData = this.FloorName;
+      // })
     },
-    mounted() {}
+    del() {
+      // 点击需从模型中删除的设备
+      let jumpRouter = this.$router.resolve({ path: '/model/report/deleted' })
+      window.open(jumpRouter.href, '_blank')
+    },
+    supplement() {
+      // 点击模型待补充的设备
+      let jumpRouter = this.$router.resolve({ path: '/model/report/supplement' })
+      window.open(jumpRouter.href, '_blank')
+    },
+    // 切换每页显示数量
+    handleSizeChange(val) {
+      this.page.pageSize = val;
+      this.getModelFloor();
+    },
+    // 切换页码
+    handleCurrentChange(val) {
+      this.page.pageNumber = val;
+      this.getModelFloor();
+    },
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.statistics {
+  display: flex;
+  width: 100%;
+  padding: 20px 0;
+  background: white;
+  margin-bottom: 10px;
+  div {
+    flex: 1;
+    text-align: center;
+    p {
+      b {
+        font-size: 20px;
+        margin-left: 20px;
+      }
+    }
+  }
+}
+.main-content {
+  width: 100%;
+  height: calc(100% - 90px);
+  background: white;
+  .content-box {
+    height: calc(100% - 105px);
+    .table {
+      margin-top: 15px;
+    }
+  }
+}
+.button {
+  padding-left: 10px;
+  .el-link {
+    font-size: 12px;
+    text-decoration: none;
+    color: #606266 !important;
+    padding: 4px 15px;
+    border: 1px solid #dcdfe6;
+    border-radius: 3px;
+    margin-right: 10px;
+  }
+}
+.success-color {
+  color: #67c23a;
+}
+.error-color {
+  color: #f56c6c;
 }
-</script>
+</style>

+ 229 - 0
src/views/model/report/supplement.vue

@@ -0,0 +1,229 @@
+<template>
+  <!-- 待补充页面 -->
+  <div class="box">
+    <ul class="infinite-list" v-infinite-scroll="load" style="overflow:auto">
+      <!-- <li v-for="i in count" class="infinite-list-item"> -->
+      <li class="infinite-list-item">
+        <div class="content-box">
+          <div class="content-top">
+            <div class="details">
+              <h4>{{'四位序列号'}}<el-badge value="待补充" class="item"></el-badge>
+              </h4>
+              <h4>{{"XXXX建筑模型夹"}}-{{"XXX层"}}-{{"待删除设备名称XXXXXXXXXXXXX"}}</h4>
+              <b>标记码:<span @dblclick="copyContent" id="copy">{{'12d13fs13f1sd313'}}</span></b><span class="copy" @click="clickCopy">点击复制</span>
+              <input id="copyContent" type="text" @dblclick="copyContent" style="border:none;opacity:0;position:absolute;top:0;left:0;">
+              <p style="margin-top:30px;">建议使用的Revit族:{{'XXXXXXX'}}</p>
+              <p>设计图纸中编码:{{'XXXXXXX'}}</p>
+              <p><span>设备类型:{{'XXXXXXX'}}</span><span>设备ID:{{'XXXXXXX'}}</span></p>
+              <p><span>资产族:{{'XXXXXXX'}}</span><span>资产ID:{{'XXXXXXX'}}</span></p>
+              <p>现场发现人:{{'XXXXXXX'}}</p>
+            </div>
+            <div class="plan">
+              <p>平面图上的位置:<span>{{`${'('+'X:'+'329'+','+'Y:'+'398'+')'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+          </div>
+          <div class="content-bottom">
+            <div class="photo">
+              <p>铭牌图片:<span>拍摄时间:{{`${'2019'+'年'+'12'+'月'+'56'+'时'+'5'+'分'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+            <div class="photo">
+              <p>设备图片:<span>拍摄时间:{{`${'2019'+'年'+'12'+'月'+'56'+'时'+'5'+'分'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+            <div class="photo">
+              <p>设备图片:<span>拍摄时间:{{`${'2019'+'年'+'12'+'月'+'56'+'时'+'5'+'分'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+            <div class="photo">
+              <p>设备图片:<span>拍摄时间:{{`${'2019'+'年'+'12'+'月'+'56'+'时'+'5'+'分'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+            <div class="photo">
+              <p>设备图片:<span>拍摄时间:{{`${'2019'+'年'+'12'+'月'+'56'+'时'+'5'+'分'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+            <div class="photo">
+              <p>设备图片:<span>拍摄时间:{{`${'2019'+'年'+'12'+'月'+'56'+'时'+'5'+'分'}`}}</span></p>
+              <div class="img-box">
+                <img src="https://hbimg.huabanimg.com/f761a5fd8164882f9bad2dc46da4f5682cfd7c6eabc2-ArjdOX_fw658" alt="">
+              </div>
+            </div>
+          </div>
+        </div>
+      </li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {
+
+  },
+  data() {
+    return {
+      count: 0
+    }
+  },
+  mounted() { },
+  created() {
+
+  },
+  methods: {
+    load() {
+      this.count += 2
+    },
+    copyContent(element) {
+      // 双击复制
+      let content = element.target.innerText;
+      let inputObj = document.getElementById('copyContent');
+      inputObj.value = content;
+      inputObj.select();
+      document.execCommand("Copy");
+      this.$message({
+        message: '复制成功',
+        type: 'success',
+        duration: 1000
+      });
+    },
+    clickCopy() {
+      // 点击复制
+      let target = document.getElementById('copy');
+      let content = target.innerText;
+      let inputObj = document.getElementById('copyContent');
+      inputObj.value = content;
+      inputObj.select();
+      document.execCommand("Copy");
+      this.$message({
+        message: '复制成功',
+        type: 'success',
+        duration: 1000
+      });
+    }
+  }
+}
+</script>
+
+
+<style lang="less" scoped>
+// 取消打印功能默认的左右边距
+@media print {
+  @page {
+    margin-left: 0;
+    margin-right: 0;
+  }
+}
+.box {
+  background: #f2f2f2;
+  margin: 0 auto;
+  ul {
+    .infinite-list-item {
+      margin-bottom: 20px;
+    }
+  }
+  .content-box {
+    width: 1000px;
+    margin: 0 auto;
+    background: white;
+    padding: 10px 4px 10px 20px;
+    box-sizing: border-box;
+    .content-top {
+      display: flex;
+      div {
+        flex: 1;
+      }
+      .details {
+        margin-right: 10px;
+        .el-badge {
+          margin: 10px 0 0 10px;
+        }
+        p {
+          margin-top: 4px;
+          span:nth-child(1) {
+            display: inline-block;
+            width: 200px;
+          }
+        }
+        .copy {
+          color: #409eff;
+          margin-left: 20px;
+        }
+      }
+      .plan {
+        padding-left: 20px;
+        box-sizing: border-box;
+        p {
+          width: 100%;
+          margin: 10px 0 10px 0;
+          span {
+            float: right;
+            padding-right: 20px;
+            box-sizing: border-box;
+          }
+        }
+      }
+    }
+    .content-bottom {
+      width: 100%;
+      margin-top: 20px;
+      overflow: hidden;
+      .photo,
+      .explain {
+        float: left;
+        width: 50%;
+      }
+      .photo {
+        box-sizing: border-box;
+        margin-bottom: 24px;
+        p {
+          margin-bottom: 10px;
+        }
+        span {
+          float: right;
+          padding-right: 20px;
+          box-sizing: border-box;
+        }
+      }
+      .explain {
+        padding-right: 20px;
+        box-sizing: border-box;
+        .el-scrollbar {
+          background: #f2f2f2;
+        }
+        p {
+          margin-bottom: 10px;
+        }
+        .explain-content {
+          padding: 10px;
+          width: 100%;
+          height: 290px;
+          box-sizing: border-box;
+        }
+      }
+    }
+  }
+}
+.img-box {
+  width: 100%;
+  // text-align: center;
+  img {
+    vertical-align: middle;
+    width: 400px;
+    height: 300px;
+  }
+}
+</style>