dedsudiyu 1 개월 전
부모
커밋
895f6a3494
41개의 변경된 파일4597개의 추가작업 그리고 8개의 파일을 삭제
  1. 4 4
      .env.production
  2. 19 0
      package-lock.json
  3. 2 0
      package.json
  4. BIN
      public/models/BxiaoQu.glb
  5. BIN
      public/models/NxiaoQu.glb
  6. BIN
      public/models/demo1.glb
  7. BIN
      public/models/demo2.glb
  8. BIN
      public/models/demo_b.glb
  9. BIN
      public/models/demo_n.glb
  10. BIN
      public/models/xiaoQuB.glb
  11. BIN
      public/models/xiaoQuN.glb
  12. BIN
      public/png/alarm.png
  13. BIN
      public/png/img_yjbge@1x.png
  14. BIN
      public/png/noAlarm.png
  15. 27 0
      src/App.vue
  16. 35 0
      src/api/index.js
  17. BIN
      src/assets/ZDimages/img_sbzsbg@1x.png
  18. BIN
      src/assets/ZDimages/img_syssjbg@1x.png
  19. BIN
      src/assets/ZDimages/img_syssjbg_kx@1x.png
  20. BIN
      src/assets/ZDimages/img_syssjbg_sy@1x.png
  21. BIN
      src/assets/ZDimages/img_syssjbg_yc@1x.png
  22. BIN
      src/assets/ZDimages/img_whptjfx_bg@1x.png
  23. BIN
      src/assets/ZDimages/img_yjczbg.png
  24. BIN
      src/assets/ZDimages/img_zysb_sjbg@1x.png
  25. BIN
      src/assets/ZDimages/img_zysb_tbbjl@1x.png
  26. BIN
      src/assets/ZDimages/img_zysb_tbbjr@1x.png
  27. BIN
      src/assets/ZDimages/map_back.png
  28. BIN
      src/assets/fonts/AlimamaShuHeiTi-Bold.ttf
  29. BIN
      src/assets/fonts/SOURCEHANSANSCN.OTF
  30. BIN
      src/assets/fonts/YouSheBiaoTiHei.ttf
  31. 1 0
      src/main.js
  32. 4 4
      src/views/home.vue
  33. 581 0
      src/views/newSafetyOverview/index.vue
  34. 935 0
      src/views/newSafetyOverview/pageComponent/canvasMap.vue
  35. 178 0
      src/views/newSafetyOverview/pageComponent/centerNumData.vue
  36. 791 0
      src/views/newSafetyOverview/pageComponent/laboratoryData.vue
  37. 301 0
      src/views/newSafetyOverview/pageComponent/resourceAndEquipmentStatistics.vue
  38. 408 0
      src/views/newSafetyOverview/pageComponent/secondaryCollegeUnitLaboratoryStatistics.vue
  39. 379 0
      src/views/newSafetyOverview/pageComponent/statisticalAnalysisOfHazardSources.vue
  40. 609 0
      src/views/newSafetyOverview/pageComponent/statisticalAnalysisOfHazardousChemicals.vue
  41. 323 0
      src/views/newSafetyOverview/pageComponent/subComponents.vue

+ 4 - 4
.env.production

@@ -24,13 +24,13 @@ VUE_APP_VERSION_DIFFERENCE_FIELD = 'kuangYeDaXue_nanHu'
 # ####################外网接口配置####################
 
 # 现场
-VUE_APP_BASE_API = 'labcontrol.nwafu.edu.cn/api'
+# VUE_APP_BASE_API = 'labcontrol.nwafu.edu.cn/api'
 
 # 1.8外网地址
 # VUE_APP_BASE_API = 'lab.zjznai.com/labTest'
 
 # 43外网地址
-# VUE_APP_BASE_API = 'lab.zjznai.com/labapp'
+VUE_APP_BASE_API = 'lab.zjznai.com/labapp'
 
 # 开发人员地址
 # VUE_APP_BASE_API = '192.168.1.24:8080'
@@ -38,13 +38,13 @@ VUE_APP_BASE_API = 'labcontrol.nwafu.edu.cn/api'
 # ####################内网接口配置####################
 
 # 现场
-VUE_APP_BASE_LOCAL_API = '172.16.0.65/api'
+# VUE_APP_BASE_LOCAL_API = '172.16.0.65/api'
 
 # 1.8内网地址
 # VUE_APP_BASE_LOCAL_API = '192.168.1.8/api'
 
 # 43内网地址
-# VUE_APP_BASE_LOCAL_API = '192.168.1.43/api'
+VUE_APP_BASE_LOCAL_API = '192.168.1.43/api'
 
 # 开发人员地址
 # VUE_APP_BASE_LOCAL_API = '192.168.1.24:8080'

+ 19 - 0
package-lock.json

@@ -3845,6 +3845,11 @@
         }
       }
     },
+    "claygl": {
+      "version": "1.3.0",
+      "resolved": "https://mirrors.huaweicloud.com/repository/npm/claygl/-/claygl-1.3.0.tgz",
+      "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ=="
+    },
     "clean-css": {
       "version": "4.2.4",
       "resolved": "https://registry.npmmirror.com/clean-css/download/clean-css-4.2.4.tgz?cache=0&sync_timestamp=1634992314911&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fclean-css%2Fdownload%2Fclean-css-4.2.4.tgz",
@@ -5603,6 +5608,15 @@
         }
       }
     },
+    "echarts-gl": {
+      "version": "2.0.9",
+      "resolved": "https://mirrors.huaweicloud.com/repository/npm/echarts-gl/-/echarts-gl-2.0.9.tgz",
+      "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==",
+      "requires": {
+        "claygl": "^1.2.1",
+        "zrender": "^5.1.1"
+      }
+    },
     "echarts-liquidfill": {
       "version": "3.1.0",
       "resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-3.1.0.tgz",
@@ -15024,6 +15038,11 @@
         "safe-buffer": "^5.0.1"
       }
     },
+    "tween.js": {
+      "version": "16.6.0",
+      "resolved": "https://mirrors.huaweicloud.com/repository/npm/tween.js/-/tween.js-16.6.0.tgz",
+      "integrity": "sha512-IIhm0VsiBxNJO+WsXUvjcq+u3sKfOwSu67Yh9T5xSpXb2eHHi9+uZDDGBc7uMXjfud0bYiLkYCEb7JXIGXi5KA=="
+    },
     "tweetnacl": {
       "version": "0.14.5",
       "resolved": "https://registry.nlark.com/tweetnacl/download/tweetnacl-0.14.5.tgz?cache=0&sync_timestamp=1624607953624&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftweetnacl%2Fdownload%2Ftweetnacl-0.14.5.tgz",

+ 2 - 0
package.json

@@ -47,6 +47,7 @@
     "clipboard": "2.0.6",
     "core-js": "3.8.1",
     "echarts": "^5.3.0",
+    "echarts-gl": "^2.0.9",
     "echarts-liquidfill": "^3.1.0",
     "element-ui": "2.15.5",
     "file-saver": "^2.0.4",
@@ -70,6 +71,7 @@
     "sortablejs": "1.10.2",
     "spark-md5": "^3.0.1",
     "three": "^0.148.0",
+    "tween.js": "^16.6.0",
     "vue": "2.6.12",
     "vue-count-to": "1.0.13",
     "vue-cropper": "^0.5.5",

BIN
public/models/BxiaoQu.glb


BIN
public/models/NxiaoQu.glb


BIN
public/models/demo1.glb


BIN
public/models/demo2.glb


BIN
public/models/demo_b.glb


BIN
public/models/demo_n.glb


BIN
public/models/xiaoQuB.glb


BIN
public/models/xiaoQuN.glb


BIN
public/png/alarm.png


BIN
public/png/img_yjbge@1x.png


BIN
public/png/noAlarm.png


+ 27 - 0
src/App.vue

@@ -124,4 +124,31 @@
     font-weight: normal;
     font-style: normal;
   }
+  @font-face {
+    font-family: 'AlimamaShuHeiTi';
+    src: url('./assets/fonts/AlimamaShuHeiTi-Bold.ttf') format('truetype'); /* 标题 */
+    font-weight: normal;
+    font-style: normal;
+    /*
+    font-family: AlimamaShuHeiTi;
+    */
+  }
+  @font-face {
+    font-family: 'YouSheBiaoTiHei';
+    src: url('./assets/fonts/YouSheBiaoTiHei.ttf') format('truetype'); /* 数字 */
+    font-weight: normal;
+    font-style: normal;
+    /*
+    font-family: YouSheBiaoTiHei;
+    */
+  }
+  @font-face {
+    font-family: 'SOURCEHANSANSCN';
+    src: url('./assets/fonts/SOURCEHANSANSCN.OTF') format('truetype'); /* 正文 */
+    font-weight: normal;
+    font-style: normal;
+    /*
+    font-family: SOURCEHANSANSCN;
+    */
+  }
 </style>

+ 35 - 0
src/api/index.js

@@ -401,3 +401,38 @@ export function laboratoryBigViewHazardStatistics (query) {
     params: query
   })
 }
+/* 新安全总览 */
+//全校实验室实时统计数量
+export function laboratorySubRelInfoLabStateStatisticsAll (query) {
+  return request({
+    url: '/laboratory/subRelInfo/labStateStatisticsAll',
+    method: 'get',
+    params: query
+  })
+}
+//全校实验室实时统计数量
+export function laboratorySubRelInfoGetLabTypeStatistics (query) {
+  return request({
+    url: '/laboratory/subRelInfo/getLabTypeStatistics',
+    method: 'get',
+    params: query
+  })
+}
+
+//实验室危险源种类数量
+export function chemicalStockHazardClassStatistics (query) {
+  return request({
+    url: '/chemical/stock/hazardClassStatistics',
+    method: 'get',
+    params: query
+  })
+}
+
+//危险源统计分析
+export function chemicalStockHazMartClassStatistics (query) {
+  return request({
+    url: '/chemical/stock/hazMartClassStatistics',
+    method: 'get',
+    params: query
+  })
+}

BIN
src/assets/ZDimages/img_sbzsbg@1x.png


BIN
src/assets/ZDimages/img_syssjbg@1x.png


BIN
src/assets/ZDimages/img_syssjbg_kx@1x.png


BIN
src/assets/ZDimages/img_syssjbg_sy@1x.png


BIN
src/assets/ZDimages/img_syssjbg_yc@1x.png


BIN
src/assets/ZDimages/img_whptjfx_bg@1x.png


BIN
src/assets/ZDimages/img_yjczbg.png


BIN
src/assets/ZDimages/img_zysb_sjbg@1x.png


BIN
src/assets/ZDimages/img_zysb_tbbjl@1x.png


BIN
src/assets/ZDimages/img_zysb_tbbjr@1x.png


BIN
src/assets/ZDimages/map_back.png


BIN
src/assets/fonts/AlimamaShuHeiTi-Bold.ttf


BIN
src/assets/fonts/SOURCEHANSANSCN.OTF


BIN
src/assets/fonts/YouSheBiaoTiHei.ttf


+ 1 - 0
src/main.js

@@ -17,6 +17,7 @@ import Pagination from "@/components/Pagination";
 
 // 引入echarts
 import * as echarts from 'echarts'
+import "echarts-gl";
 Vue.prototype.$echarts = echarts
 
 

+ 4 - 4
src/views/home.vue

@@ -15,7 +15,7 @@
       </div>
     </div>
     <!--安全总览-->
-    <safetyOverview v-if="pageType === 1"></safetyOverview>
+    <newSafetyOverview v-if="pageType === 1"></newSafetyOverview>
     <!--设备资源-->
     <resourceDevice v-if="pageType === 2"></resourceDevice>
     <!--三维模型-->
@@ -31,7 +31,7 @@
   import dimensionalModel from "./dimensionalModel/index.vue";
   import emergencyManagement from "./emergencyManagement/index.vue";
   import resourceDevice from "./resourceDevice/index.vue";
-  import safetyOverview from "./safetyOverview/index.vue";
+  import newSafetyOverview from "./newSafetyOverview/index.vue";
   import videoSurveillance from "./videoSurveillance/index.vue";
   import { getToken,removeToken } from '@/utils/auth'
   import planAlarm from "@/components/planAlarm/planAlarm.vue";
@@ -41,7 +41,7 @@
       dimensionalModel,
       emergencyManagement,
       resourceDevice,
-      safetyOverview,
+      newSafetyOverview,
       videoSurveillance,
       planAlarm,
     },
@@ -125,7 +125,7 @@
       .logo-img{
         width:350px;
         height:77px;
-        margin:50px 0 0 60px;
+        margin:40px 0 0 60px;
       }
       .title-box{
         flex:1;

+ 581 - 0
src/views/newSafetyOverview/index.vue

@@ -0,0 +1,581 @@
+<!-- 安全总览 -->
+<template>
+  <div class="newSafetyOverview">
+    <!--背景遮罩层-->
+    <img class="map-back-img" src="@/assets/ZDimages/map_back.png">
+    <!--背景地图-->
+    <canvasMap  ref="canvasMap" class="canvasMap-box"></canvasMap>
+    <!--左侧-->
+    <div class="left-max-big-box">
+      <laboratoryData></laboratoryData>
+      <secondaryCollegeUnitLaboratoryStatistics></secondaryCollegeUnitLaboratoryStatistics>
+      <subComponents></subComponents>
+    </div>
+    <!--中间-->
+    <div class="center-max-big-box">
+      <div class="center-top-button-max-box">
+        <img class="position-img position-img-1" src="@/assets/ZDimages/img_bg_cdo@1x.png">
+        <img class="position-img position-img-2" src="@/assets/ZDimages/img_bg_xz@1x.png">
+        <img class="position-img position-img-3" src="@/assets/ZDimages/img_bg_zc@1x.png">
+        <img class="position-img position-img-4" src="@/assets/ZDimages/img_bg_zc@1x.png">
+        <img class="position-img position-img-5" src="@/assets/ZDimages/img_bg_zc@1x.png">
+        <img class="position-img position-img-6" src="@/assets/ZDimages/img_bg_zc@1x.png">
+        <img class="position-img position-img-7" src="@/assets/ZDimages/img_bg_cdo@1x.png">
+        <p class="null-p"></p>
+        <p class="button-check-p">安全总览</p>
+        <p class="button-p" @click="goPage(2)">资源设备</p>
+        <p class="button-p" @click="goPage(3)">三维模型</p>
+        <p class="button-p" @click="goPage(4)">视频监控</p>
+        <p class="button-p" @click="goPage(5)">应急管控</p>
+        <p class="null-p"></p>
+      </div>
+      <centerNumData></centerNumData>
+    </div>
+    <!--右侧-->
+    <div class="right-max-big-box">
+      <statisticalAnalysisOfHazardSources></statisticalAnalysisOfHazardSources>
+      <statisticalAnalysisOfHazardousChemicals></statisticalAnalysisOfHazardousChemicals>
+      <resourceAndEquipmentStatistics></resourceAndEquipmentStatistics>
+    </div>
+  </div>
+</template>
+<script>
+  import mqtt from 'mqtt'
+  import {
+    laboratoryBigViewSelectTriggerInfo,
+  } from "@/api/index";
+  import laboratoryData from "./pageComponent/laboratoryData.vue";
+  import secondaryCollegeUnitLaboratoryStatistics from "./pageComponent/secondaryCollegeUnitLaboratoryStatistics.vue";
+  import subComponents from "./pageComponent/subComponents.vue";
+  import statisticalAnalysisOfHazardSources from "./pageComponent/statisticalAnalysisOfHazardSources.vue";
+  import statisticalAnalysisOfHazardousChemicals from "./pageComponent/statisticalAnalysisOfHazardousChemicals.vue";
+  import resourceAndEquipmentStatistics from "./pageComponent/resourceAndEquipmentStatistics.vue";
+  import centerNumData from "./pageComponent/centerNumData.vue";
+  import canvasMap from "./pageComponent/canvasMap.vue";
+  export default {
+    name: 'index',
+    components: {
+      laboratoryData,
+      secondaryCollegeUnitLaboratoryStatistics,
+      subComponents,
+      statisticalAnalysisOfHazardSources,
+      statisticalAnalysisOfHazardousChemicals,
+      resourceAndEquipmentStatistics,
+      centerNumData,
+      canvasMap,
+    },
+    data () {
+      return {
+        //预案MQTT
+        planOpic:'lab/risk/plan/change',
+        planClient:{},
+        //预案数据
+        alarmPropsData:{},
+        //校区模型关系
+        schoolModelList:[
+          // {school:'B',	name:'5号楼',	buildId:'101093843117592833',buildIdList:[],},
+          {school:'B',	name:'6B教学楼',	buildId:'101093843117592815',buildIdList:[],},
+          {school:'B',	name:'中心实验楼',	buildId:'101093843117592829',buildIdList:[],},
+          {school:'B',	name:'信息工程学院教学楼',	buildId:'101093843117592812',buildIdList:[],},
+          {school:'B',	name:'养虫楼',	buildId:'101093843117592805',buildIdList:[],},
+          {school:'B',	name:'农业机械实验室平房',	buildId:'101093843117592807',buildIdList:[],},
+          {school:'B',	name:'农药研究所',	buildId:'101093843117592804',buildIdList:[],},
+          {school:'B',	name:'动物中心B座',	buildId:'101093843117592785',buildIdList:[],},
+          {school:'B',	name:'动物中心实验楼A',	buildId:'101093843117592765',buildIdList:[],},
+          {school:'B',	name:'动物中心实验楼B',	buildId:'101093843117592764',buildIdList:[],},
+          {school:'B',	name:'动物科技学院楼',	buildId:'101093843117592831',buildIdList:[],},
+          {school:'B',	name:'动科楼',	buildId:'101093843117592832',buildIdList:[],},
+          {school:'B',	name:'北1号教学楼',	buildId:'101093843117592802',buildIdList:[],},
+          {school:'B',	name:'北2号教学楼',	buildId:'101093843117592813',buildIdList:[],},
+          {school:'B',	name:'北3号教学楼',	buildId:'101093843117592782',buildIdList:[],},
+          {school:'B',	name:'北4号教学楼',	buildId:'101093843117592781',buildIdList:[],},
+          {school:'B',	name:'北5号教学楼',	buildId:'101093843117592783',buildIdList:['101093843117592783','101093843117592833'],},
+          {school:'B',	name:'北6号教学楼',	buildId:'101093843117592814',buildIdList:[],},
+          {school:'B',	name:'北7号教学楼',	buildId:'101093843117592816',buildIdList:[],},
+          {school:'B',	name:'危化品服务中心',	buildId:'101093843117592826',buildIdList:[],},
+          // {school:'B',	name:'原农一站办公楼',	buildId:'101093843117592811',buildIdList:[],},
+          // {school:'B',	name:'工程训练中心楼',	buildId:'101093843117592808',buildIdList:[],},
+          // {school:'B',	name:'教学办公楼',	buildId:'101093843117592806',buildIdList:[],},
+          // {school:'B',	name:'未知实验室	',buildId:'1855791848753147906',buildIdList:[],},
+          // {school:'B',	name:'机械及液压实验室平房',	buildId:'101093843117592810',buildIdList:[],},
+          {school:'B',	name:'机电锻铸车间',	buildId:'101093843117592809',buildIdList:['101093843117592809','101093843117592811','101093843117592808','101093843117592806','1855791848753147906','101093843117592810'],},
+          // {school:'B',	name:'水利与建筑工程学院',	buildId:'101093843117592788',buildIdList:[],},
+          // {school:'B',	name:'水利与建筑工程学院A',	buildId:'101093843117592766',buildIdList:[],},
+          // {school:'B',	name:'水利与建筑工程学院B',	buildId:'101093843117592768',buildIdList:[],},
+          // {school:'B',	name:'水利与建筑工程学院C',	buildId:'101093843117592769',buildIdList:[],},
+          // {school:'B',	name:'水利与建筑工程学院D',	buildId:'101093843117592767',buildIdList:[],},
+          {school:'B',	name:'水工厅', buildId:'1871736666456633346',buildIdList:['1871736666456633346','101093843117592788','101093843117592766','101093843117592768','101093843117592769','101093843117592767'],},
+          {school:'B',	name:'水工水力学实验大厅', buildId:'1871729400227606529',buildIdList:[],},
+          {school:'B',	name:'理科综合实验楼A',	buildId:'101093843117592774',buildIdList:['101093843117592774','101093843117592779','101093843117592775','101093843117592776','101093843117592780'],},
+          // {school:'B',	name:'理科综合实验楼B',	buildId:'101093843117592779',buildIdList:[],},
+          // {school:'B',	name:'理科综合实验楼C',	buildId:'101093843117592775',buildIdList:[],},
+          // {school:'B',	name:'理科综合实验楼D',	buildId:'101093843117592776',buildIdList:[],},
+          // {school:'B',	name:'理科综合实验楼E',	buildId:'101093843117592780',buildIdList:[],},
+          {school:'B',	name:'老昆虫博物馆',	buildId:'101093843117592786',buildIdList:[],},
+          {school:'B',	name:'食品楼',	buildId:'101093843117592789',buildIdList:['101093843117592789','101093843117592771','101093843117592770','101093843117592772','101093843117592773'],},
+          // {school:'B',	name:'食品楼A',	buildId:'101093843117592771',buildIdList:[],},
+          // {school:'B',	name:'食品楼B',	buildId:'101093843117592770',buildIdList:[],},
+          // {school:'B',	name:'食品楼C',	buildId:'101093843117592772',buildIdList:[],},
+          // {school:'B',	name:'食品楼D',	buildId:'101093843117592773',buildIdList:[],},
+          {school:'N',	name:'农科楼(农学院)',	buildId:'101084081109864872',buildIdList:['101084081109864872','101084081109864874','101084081109864873','101093843117592803'],},
+          // {school:'N',	name:'农科楼(园艺学院)',	buildId:'101084081109864874',buildIdList:[],},
+          // {school:'N',	name:'农科楼(植物保护学院)',	buildId:'101084081109864873',buildIdList:[],},
+          // {school:'N',	name:'农科楼(资源环境学院)',	buildId:'101093843117592803',buildIdList:[],},
+          {school:'N',	name:'农科院子校教学楼(初中)',	buildId:'101093843117592823',buildIdList:[],},
+          {school:'N',	name:'南2号教学楼',	buildId:'101093843117592817',buildIdList:[],},
+          {school:'N',	name:'南3号教学楼',	buildId:'101093843117592820',buildIdList:[],},
+          {school:'N',	name:'南校子校楼',	buildId:'101093843117592800',buildIdList:[],},
+          {school:'N',	name:'南校水保楼',	buildId:'101093843117592801',buildIdList:[],},
+          {school:'N',	name:'家畜生物学重点实验室楼',	buildId:'101093843117592787',buildIdList:[],},
+          {school:'N',	name:'木艺坊',	buildId:'101093843117592819',buildIdList:[],},
+          {school:'N',	name:'林学院实验楼',	buildId:'101093843117592818',buildIdList:[],},
+          {school:'N',	name:'科研主楼',	buildId:'101093843117592784',buildIdList:[],},
+          {school:'N',	name:'科研楼',	buildId:'101093843117592822',buildIdList:[],},
+          {school:'N',	name:'经管园林楼(文科楼)A',	buildId:'101093843117592777',buildIdList:[],},
+          {school:'N',	name:'经管园林楼(文科楼)C',	buildId:'101093843117592778',buildIdList:[],},
+          {school:'N',	name:'草业与草原楼',	buildId:'101093843117592825',buildIdList:[],},
+          {school:'N',	name:'林学院实验楼',	buildId:'101093843117592821',buildIdList:[],},
+          {school:'旱研院校区',	name:'农一站科研楼',	buildId:'101093843117592827',buildIdList:[],},
+          {school:'旱研院校区',	name:'农机一站平房',	buildId:'101093843117592828',buildIdList:[],},
+          {school:'校外',	name:'农三站科研办公楼',	buildId:'101093843117592790',buildIdList:[],},
+          {school:'校外',	name:'器材楼',	buildId:'101093843117592792',buildIdList:[],},
+          {school:'水保所校区',	name:'人工降雨实验大厅',	buildId:'101093843117592793',buildIdList:[],},
+          {school:'水保所校区',	name:'南校区农科楼',	buildId:'101093843117592799',buildIdList:[],},
+          {school:'水保所校区',	name:'国家重点实验室西楼',	buildId:'101093843117592798',buildIdList:[],},
+          {school:'水保所校区',	name:'水保所人工干旱环境气候室工程',	buildId:'101093843117592795',buildIdList:[],},
+          {school:'水保所校区',	name:'水保所国家重点实验室楼',	buildId:'101093843117592794',buildIdList:[],},
+          {school:'水保所校区',	name:'水保所科研大楼',	buildId:'101093843117592797',buildIdList:[],},
+          {school:'水保所校区',	name:'水保所西区科研楼',	buildId:'101093843117592796',buildIdList:[],},
+          {school:'老附中校区',	name:'附中实验楼',	buildId:'101093843117592830',buildIdList:[],},
+          {school:'老附中校区',	name:'附中教学楼',	buildId:'101093843117592791',buildIdList:[],},
+        ],
+      }
+    },
+    created () {
+
+    },
+    mounted () {
+      //判断是否已有预警MQTT链接
+      if(!this.planClient.unsubscribe){
+        this.offPlanMQTT('on');
+      }
+      //查询是否有预案发生
+      this.laboratoryBigViewSelectTriggerInfo();
+    },
+    methods: {
+      demo(){
+        console.log('demo')
+        // let list = [{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592777",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101084081109864872",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592817",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592820",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592787",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592819",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592784",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592825",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592821",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592821",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },{
+        //   "subName": "分子设计育种实验室",
+        //   "riskPlanName": "温度测试预案",
+        //   "eventStartTime": "2025-03-12T10:42:18",
+        //   "deptName": "草业学院",
+        //   "schoolName": "南校区",
+        //   "buildId": "101093843117592821",
+        //   "buildName": "草业与草原楼",
+        //   "floorName": "1层",
+        //   "roomNum": "109",
+        //   "classLevelName": "Ⅲ级",
+        //   "classLevelColor": "#FFBB00",
+        // },];
+        let list = [{
+          "subName": "分子设计育种实验室",
+          "riskPlanName": "温度测试预案",
+          "eventStartTime": "2025-03-12T10:42:18",
+          "deptName": "草业学院",
+          "schoolName": "南校区",
+          "buildId": "101093843117592809",
+          "buildName": "草业与草原楼",
+          "floorName": "1层",
+          "roomNum": "109",
+          "classLevelName": "Ⅲ级",
+          "classLevelColor": "#FFBB00",
+          "school":'B'
+        },{
+          "subName": "分子设计育种实验室",
+          "riskPlanName": "温度测试预案",
+          "eventStartTime": "2025-03-12T10:42:18",
+          "deptName": "草业学院",
+          "schoolName": "南校区",
+          "buildId": "101093843117592809",
+          "buildName": "草业与草原楼",
+          "floorName": "1层",
+          "roomNum": "109",
+          "classLevelName": "Ⅲ级",
+          "classLevelColor": "#FFBB00",
+          "school":'B'
+        }]
+        let obj = {
+          "subName": "分子设计育种实验室",
+          "riskPlanName": "温度测试预案",
+          "eventStartTime": "2025-03-12T10:42:18",
+          "deptName": "草业学院",
+          "schoolName": "南校区",
+          "buildId": "101093843117592809",
+          "buildName": "草业与草原楼",
+          "floorName": "1层",
+          "roomNum": "109",
+          "classLevelName": "Ⅲ级",
+          "classLevelColor": "#FFBB00",
+          "school":'B'
+        };
+        this.$refs['canvasMap'].alarmTrigger(list,obj,obj.school);
+      },
+      demo1(){
+        this.$refs['canvasMap'].alarmOff();
+      },
+      //页面切换
+      goPage(type){
+        this.$parent.pageCheck(type);
+      },
+      checkComponentType(type){
+        this.$set(this,'pageType',type);
+      },
+      //预案-MQTT连接
+      offPlanMQTT(type){
+        let self = this;
+        if(self.planClient.unsubscribe){
+          self.planClient.unsubscribe(self.planOpic, error => {
+            if (error) {
+              // console.log('mqtt关闭连接错误:', error)
+            }
+          })
+          self.planClient.end();
+          this.$set(this,'planClient',{});
+        }
+        //判断传入参数如果存在 发起一次新的连接
+        if(type){
+          this.planMQTT();
+        }
+      },
+      //预案-MQTT订阅
+      planMQTT(){
+        let self = this;
+        this.planClient = mqtt.connect(localStorage.getItem('mqttUrl'), {
+          username: localStorage.getItem('mqttUser'),
+          password:localStorage.getItem('mqttPassword')
+        });
+        this.planClient.on("connect", e =>{
+          this.planClient.subscribe(self.planOpic, (err) => {
+            if (!err) {
+              // console.log("预案-订阅成功:" + self.planOpic);
+            }else{
+              // console.log("预案-连接错误:" + err);
+            }
+          });
+        });
+        this.planClient.on("message", (topic, message) => {
+          if (message){
+            //获取预案数据
+            this.laboratoryBigViewSelectTriggerInfo();
+          }
+        });
+      },
+      //查询当前正在发生的预案
+      laboratoryBigViewSelectTriggerInfo(){
+        let self = this;
+        laboratoryBigViewSelectTriggerInfo().then(response => {
+          if(response.data[0]){
+            response.data.forEach((item)=>{
+              item.triggerUploadData = JSON.parse(item.triggerUploadData);
+              item.alarmText = item.riskPlanName.split('预案');
+              item.alarmText = item.alarmText[0].split('预警');
+              item.alarmText = item.alarmText[0]+'预警';
+              //修正楼栋ID用于匹配本地数据
+              self.schoolModelList.forEach((minItem)=>{
+                if(minItem.buildIdList[0]){
+                  minItem.buildIdList.forEach((minItemMin)=>{
+                    if(item.buildId == minItemMin){
+                      item.buildId = minItem.buildId;
+                    }
+                  })
+                }
+              })
+            })
+            //报警提示title信息
+            this.$set(this,'alarmTitle',response.data[response.data.length-1].alarmText);
+            //报警窗口数据
+            this.$set(this,'alarmPropsData',response.data[response.data.length-1]);
+            //报警窗口开启
+            this.$set(this,'pageType',2);
+            this.$set(this,'deptVideoType',false);
+            //判断报警楼栋属于南北校区
+            setTimeout(function(){
+              self.schoolModelList.forEach((item)=>{
+                if(item.buildId == response.data[response.data.length-1].buildId){
+                  self.$refs['canvasMap'].alarmTrigger(response.data,response.data[response.data.length-1],item.school);
+                }
+              })
+            },1500);
+            //报警声音
+            if(this.audioType){
+              /* 报警音频播放 */
+              const audio = this.$refs.audioPlayer;
+              // 尝试静音自动播放
+              audio.play().catch(() => {
+                // 如果失败,延迟 2 秒再次尝试(趁浏览器未完全冻结)
+                setTimeout(() => audio.play(), 2000);
+              });
+              // 延迟 3 秒后尝试取消静音(需浏览器允许)
+              setTimeout(() => {
+                audio.muted = false;
+              }, 3000);
+            }
+          }else{
+            //报警结束
+            this.$set(this,'pageType',1);
+            this.$set(this,'deptVideoType',false);
+            setTimeout(function(){
+              self.$refs['canvasMap'].alarmOff();
+            },1500);
+          }
+        })
+      },
+    },
+    beforeDestroy() {
+      let self = this;
+      // MQTT预警
+      self.offPlanMQTT();
+    },
+    destroyed() {
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .newSafetyOverview{
+    padding:0 62px;
+    height:1409px;
+    display: flex;
+    //地图背景遮罩
+    .map-back-img{
+      position: absolute;
+      z-index:11;
+      width:2594px;
+      height:1320px;
+      top: 122px;
+      left: 64px;
+    }
+    //地图
+    .canvasMap-box{
+      z-index: 10;
+    }
+    //左侧
+    .left-max-big-box{
+      width:652px;
+      padding-top:10px;
+      z-index: 15;
+    }
+    //中间
+    .center-max-big-box{
+      width:1293px;
+      position: relative;
+      z-index: 15;
+      .center-top-button-max-box{
+        width:911px;
+        position: absolute;
+        left:50%;
+        margin:0 -456px;
+        height:60px;
+        display: flex;
+        .position-img-1{
+          position:absolute;
+          top:0;
+          left:0;
+        }
+        .position-img-2{
+          position:absolute;
+          top:0;
+          left:83px;
+        }
+        .position-img-3{
+          position:absolute;
+          top:0;
+          left:228px;
+        }
+        .position-img-4{
+          position:absolute;
+          top:0;
+          left:374px;
+        }
+        .position-img-5{
+          position:absolute;
+          top:0;
+          left:520px;
+        }
+        .position-img-6{
+          position:absolute;
+          top:0;
+          left:666px;
+        }
+        .position-img-7{
+          position:absolute;
+          top:0;
+          left:814px;
+        }
+        .null-p{
+          flex:1;
+        }
+        .button-p{
+          z-index:5;
+          cursor: pointer;
+          font-family: Source Han Sans, Source Han Sans;
+          width:145px;
+          font-size:24px;
+          font-weight:700;
+          line-height:60px;
+          text-align: center;
+          background: -webkit-linear-gradient(0deg, #FFFFFF, #FFFFFF); /* Chrome, Safari */
+          background: linear-gradient(0deg, #FFFFFF, #FFFFFF); /* 标准语法 */
+          -webkit-background-clip: text; /* Chrome, Safari */
+          background-clip: text;
+          -webkit-text-fill-color: transparent; /* Chrome, Safari */
+          color: transparent; /* 其他浏览器 */
+        }
+        .button-check-p{
+          z-index:5;
+          cursor: pointer;
+          font-family: Source Han Sans, Source Han Sans;
+          width:145px;
+          font-weight:700;
+          font-size:24px;
+          line-height:24px;
+          height:24px;
+          margin-top:18px;
+          text-align: center;
+          background: -webkit-linear-gradient(0deg, #34e4ff, #FFFFFF); /* Chrome, Safari */
+          background: linear-gradient(0deg, #34e4ff, #FFFFFF); /* 标准语法 */
+          -webkit-background-clip: text; /* Chrome, Safari */
+          background-clip: text;
+          -webkit-text-fill-color: transparent; /* Chrome, Safari */
+          color: transparent; /* 其他浏览器 */
+        }
+      }
+    }
+    //右侧
+    .right-max-big-box{
+      width:652px;
+      padding-top:10px;
+      z-index: 15;
+    }
+  }
+</style>

+ 935 - 0
src/views/newSafetyOverview/pageComponent/canvasMap.vue

@@ -0,0 +1,935 @@
+<!-- 模型地图 -->
+<template>
+  <div>
+    <div class="canvasMap" ref="container"></div>
+  </div>
+</template>
+
+<script>
+  import * as THREE from 'three';
+  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
+  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
+  import TWEEN from 'tween.js';
+  import { CSS2DRenderer, CSS2DObject, } from "three/examples/jsm/renderers/CSS2DRenderer";
+  export default {
+    data() {
+      return {
+        boxWidth:2594,
+        // boxHeight:1320,
+        boxHeight:1240,
+        animationId: null,  // 存储动画帧ID
+        model:null,
+        rotateType:true,
+        subModels: [],
+        houses:[],
+        textures: [], // 预加载的贴图选项
+        scene: null,
+        camera: null,
+        renderer: null,
+        controls: null,
+        labelRenderer:null,
+        // initialCameraPosition: new THREE.Vector3(0.265357272970017,1.0753467424793826,0.29965000584249346),//旋转-距离-俯角
+        initialCameraPosition: new THREE.Vector3(0.5,0.60,0.5),//旋转-距离-俯角
+        /*
+        {"x":0.2509298883560245,"y":1.2088432847403026,"z":0.19985043873282318}
+        {"x":0.265357272970017,"y":1.0753467424793826,"z":0.29965000584249346}
+        */
+        initialControlsTarget: new THREE.Vector3(0, 0, 0),
+        /*本地管理数据*/
+        modelBuildingList:[
+          {school:'B',	name:'5号楼',	buildId:'101093843117592833',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'6B教学楼',	buildId:'101093843117592815',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'中心实验楼',	buildId:'101093843117592829',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'信息工程学院教学楼',	buildId:'101093843117592812',centerValue:'101093843117592812',valueList:['101093843117592812'],alarmType:false,},
+          {school:'B',	name:'养虫楼',	buildId:'101093843117592805',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'农业机械实验室平房',	buildId:'101093843117592807',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'农药研究所',	buildId:'101093843117592804',centerValue:'101093843117592804',valueList:['101093843117592804'],alarmType:false,},
+          {school:'B',	name:'动物中心B座',	buildId:'101093843117592785',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'动物中心实验楼A',	buildId:'101093843117592765',centerValue:'101093843117592765',valueList:['101093843117592765'],alarmType:false,},
+          {school:'B',	name:'动物中心实验楼B',	buildId:'101093843117592764',centerValue:'101093843117592764',valueList:['101093843117592764'],alarmType:false,},
+          {school:'B',	name:'动物科技学院楼',	buildId:'101093843117592831',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'动科楼',	buildId:'101093843117592832',centerValue:'101093843117592832',valueList:['101093843117592832'],alarmType:false,},
+          {school:'B',	name:'北1号教学楼',	buildId:'101093843117592802',centerValue:'101093843117592802',valueList:['101093843117592802'],alarmType:false,},
+          {school:'B',	name:'北2号教学楼',	buildId:'101093843117592813',centerValue:'101093843117592813',valueList:['101093843117592813'],alarmType:false,},
+          {school:'B',	name:'北3号教学楼',	buildId:'101093843117592782',centerValue:'101093843117592782',valueList:['101093843117592782'],alarmType:false,},
+          {school:'B',	name:'北4号教学楼',	buildId:'101093843117592781',centerValue:'101093843117592781',valueList:['101093843117592781'],alarmType:false,},
+          {school:'B',	name:'北5号教学楼',	buildId:'101093843117592783',centerValue:'101093843117592833',valueList:['101093843117592833'],alarmType:false,},
+          {school:'B',	name:'北6号教学楼',	buildId:'101093843117592814',centerValue:'101093843117592814',valueList:['101093843117592814'],alarmType:false,},
+          {school:'B',	name:'北7号教学楼',	buildId:'101093843117592816',centerValue:'101093843117592816',valueList:['101093843117592816'],alarmType:false,},
+          {school:'B',	name:'危化品服务中心',	buildId:'101093843117592826',centerValue:'101093843117592826-03',valueList:['101093843117592826-01','101093843117592826-02','101093843117592826-03','101093843117592826-04','101093843117592826-05'],alarmType:false,},
+          {school:'B',	name:'原农一站办公楼',	buildId:'101093843117592811',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'工程训练中心楼',	buildId:'101093843117592808',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'教学办公楼',	buildId:'101093843117592806',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'未知实验室	',buildId:'1855791848753147906',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'机械及液压实验室平房',	buildId:'101093843117592810',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'机电锻铸车间',	buildId:'101093843117592809',centerValue:'101093843117592809',valueList:['101093843117592809'],alarmType:false,},
+          {school:'B',	name:'水利与建筑工程学院',	buildId:'101093843117592788',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'水利与建筑工程学院A',	buildId:'101093843117592766',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'水利与建筑工程学院B',	buildId:'101093843117592768',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'水利与建筑工程学院C',	buildId:'101093843117592769',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'水利与建筑工程学院D',	buildId:'101093843117592767',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'水工厅', buildId:'1871736666456633346',centerValue:'1871736666456633346',valueList:['1871736666456633346'],alarmType:false,},
+          {school:'B',	name:'水工水力学实验大厅', buildId:'1871729400227606529',centerValue:'1871729400227606529-01',valueList:['1871729400227606529-01','1871729400227606529-02'],alarmType:false,},
+          {school:'B',	name:'理科综合实验楼A',	buildId:'101093843117592774',centerValue:'101093843117592774',valueList:['101093843117592774'],alarmType:false,},
+          {school:'B',	name:'理科综合实验楼B',	buildId:'101093843117592779',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'理科综合实验楼C',	buildId:'101093843117592775',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'理科综合实验楼D',	buildId:'101093843117592776',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'理科综合实验楼E',	buildId:'101093843117592780',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'老昆虫博物馆',	buildId:'101093843117592786',centerValue:'101093843117592786',valueList:['101093843117592786'],alarmType:false,},
+          {school:'B',	name:'食品楼',	buildId:'101093843117592789',centerValue:'101093843117592789',valueList:['101093843117592789'],alarmType:false,},
+          {school:'B',	name:'食品楼A',	buildId:'101093843117592771',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'食品楼B',	buildId:'101093843117592770',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'食品楼C',	buildId:'101093843117592772',centerValue:'',valueList:[],alarmType:false,},
+          {school:'B',	name:'食品楼D',	buildId:'101093843117592773',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'农科楼(农学院)',	buildId:'101084081109864872',centerValue:'101084081109864872',valueList:['101084081109864872'],alarmType:false,},
+          {school:'N',	name:'农科楼(园艺学院)',	buildId:'101084081109864874',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'农科楼(植物保护学院)',	buildId:'101084081109864873',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'农科楼(资源环境学院)',	buildId:'101093843117592803',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'农科院子校教学楼(初中)',	buildId:'101093843117592823',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'南2号教学楼',	buildId:'101093843117592817',centerValue:'101093843117592817',valueList:['101093843117592817'],alarmType:false,},
+          {school:'N',	name:'南3号教学楼',	buildId:'101093843117592820',centerValue:'101093843117592820',valueList:['101093843117592820'],alarmType:false,},
+          {school:'N',	name:'南校子校楼',	buildId:'101093843117592800',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'南校水保楼',	buildId:'101093843117592801',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'家畜生物学重点实验室楼',	buildId:'101093843117592787',centerValue:'101093843117592787',valueList:['101093843117592787'],alarmType:false,},
+          {school:'N',	name:'木艺坊',	buildId:'101093843117592819',centerValue:'101093843117592819',valueList:['101093843117592819'],alarmType:false,},
+          {school:'N',	name:'林学院实验楼',	buildId:'101093843117592818',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'科研主楼',	buildId:'101093843117592784',centerValue:'101093843117592784',valueList:['101093843117592784'],alarmType:false,},
+          {school:'N',	name:'科研楼',	buildId:'101093843117592822',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'经管园林楼(文科楼)A',	buildId:'101093843117592777',centerValue:'101093843117592777',valueList:['101093843117592777'],alarmType:false,},
+          {school:'N',	name:'经管园林楼(文科楼)C',	buildId:'101093843117592778',centerValue:'',valueList:[],alarmType:false,},
+          {school:'N',	name:'草业与草原楼',	buildId:'101093843117592825',centerValue:'101093843117592825',valueList:['101093843117592825'],alarmType:false,},
+          {school:'N',	name:'林学院实验楼',	buildId:'101093843117592821',centerValue:'101093843117592821',valueList:['101093843117592821'],alarmType:false,},
+          {school:'旱研院校区',	name:'农一站科研楼',	buildId:'101093843117592827',centerValue:'',valueList:[],alarmType:false,},
+          {school:'旱研院校区',	name:'农机一站平房',	buildId:'101093843117592828',centerValue:'',valueList:[],alarmType:false,},
+          {school:'校外',	name:'农三站科研办公楼',	buildId:'101093843117592790',centerValue:'',valueList:[],alarmType:false,},
+          {school:'校外',	name:'器材楼',	buildId:'101093843117592792',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'人工降雨实验大厅',	buildId:'101093843117592793',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'南校区农科楼',	buildId:'101093843117592799',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'国家重点实验室西楼',	buildId:'101093843117592798',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'水保所人工干旱环境气候室工程',	buildId:'101093843117592795',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'水保所国家重点实验室楼',	buildId:'101093843117592794',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'水保所科研大楼',	buildId:'101093843117592797',centerValue:'',valueList:[],alarmType:false,},
+          {school:'水保所校区',	name:'水保所西区科研楼',	buildId:'101093843117592796',centerValue:'',valueList:[],alarmType:false,},
+          {school:'老附中校区',	name:'附中实验楼',	buildId:'101093843117592830',centerValue:'',valueList:[],alarmType:false,},
+          {school:'老附中校区',	name:'附中教学楼',	buildId:'101093843117592791',centerValue:'',valueList:[],alarmType:false,},
+        ],
+        // 本地
+        modelsUrlN:'/models/NxiaoQu.glb',
+        modelsUrlB:'/models/BxiaoQu.glb',
+        alarmUrl:'/png/alarm.png',
+        noAlarmUrl:'/png/noAlarm.png',
+        // 本地部署
+        // modelsUrlN:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/models/NxiaoQu.glb':'/labAppTest/largeScreen/models/NxiaoQu.glb',
+        // modelsUrlB:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/models/BxiaoQu.glb':'/labAppTest/largeScreen/models/BxiaoQu.glb',
+        // alarmUrl:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/png/alarm.png':'/labAppTest/largeScreen/png/alarm.png',
+        // noAlarmUrl:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/png/noAlarm.png':'/labAppTest/largeScreen/png/noAlarm.png',
+        // 线上部署
+        // modelsUrlN:'/largeScreen/models/NxiaoQu.glb',
+        // modelsUrlB:'/largeScreen/models/BxiaoQu.glb',
+        // alarmUrl:'/largeScreen/png/alarm.png',
+        // noAlarmUrl:'/largeScreen/png/noAlarm.png',
+        //当前校区状态
+        schoolType:'',
+      };
+    },
+
+    mounted() {
+      this.initThree();
+      this.loadModel('N');
+      this.loadAssets();
+      window.addEventListener('resize', this.onWindowResize);
+    },
+
+    beforeDestroy() {
+      // 停止动画循环
+      if (this.animationId) {
+        cancelAnimationFrame(this.animationId);
+      }
+      // 销毁Three.js相关资源
+      this.disposeThreeResources();
+      // 停止所有补间动画
+      TWEEN.removeAll();
+      // 移除事件监听器
+      window.removeEventListener('resize', this.onWindowResize);
+      this.renderer.dispose();
+    },
+
+    methods: {
+      //初始化
+      initThree() {
+        // 初始化场景
+        this.scene = new THREE.Scene();
+        //场景背景色
+        this.scene.background = new THREE.Color(0x000F14);
+        // 初始化渲染器
+        this.renderer = new THREE.WebGLRenderer({ antialias: true });
+        // 主渲染器尺寸设置
+        this.renderer = new THREE.WebGLRenderer({ antialias: true });
+        this.renderer.setSize(this.boxWidth, this.boxHeight);  // 固定尺寸
+        this.$refs.container.appendChild(this.renderer.domElement);
+        // 初始化相机时使用存储的位置
+        this.camera = new THREE.PerspectiveCamera(
+          75,
+          // window.innerWidth / window.innerHeight,
+          this.boxWidth / this.boxHeight,
+          0.1,
+          1000
+        );
+        this.camera.position.copy(this.initialCameraPosition);
+
+        // 初始化控制器时存储初始目标
+        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
+        this.controls.target.copy(this.initialControlsTarget);
+        this.labelRenderer = new CSS2DRenderer();
+        this.labelRenderer.setSize(this.boxWidth, this.boxHeight);
+        this.labelRenderer.domElement.style.position = 'absolute';
+        this.labelRenderer.domElement.style.top = '0';
+        this.labelRenderer.domElement.style.pointerEvents = 'none';//注释后 锁死鼠标视角
+        this.$refs.container.appendChild(this.labelRenderer.domElement);
+
+        // 初始化控制器
+        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
+        this.controls.enableDamping = true;
+        this.controls.dampingFactor = 0.05;
+
+        // 添加灯光
+        const ambientLight = new THREE.AmbientLight(0xffffff, 1);
+        this.scene.add(ambientLight);
+
+        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+        directionalLight.position.set(-1.5, 2, -1.5);
+        this.scene.add(directionalLight);
+
+        // 启动动画循环
+        this.animate();
+      },
+      //模型加载
+      loadModel(type) {
+        let self = this;
+        this.$set(this,'schoolType',type);
+        if(type == 'N'){
+          //南校区
+          const loaderN = new GLTFLoader();
+          loaderN.load(self.modelsUrlN, (gltf) => {
+            const model = gltf.scene;
+            this.model = gltf.scene;
+            this.scene.add(model);
+            // 递归查找所有Group
+            const traverseGroups = (obj) => {
+              if (obj.isGroup) {
+                this.registerHouse(obj);
+              }
+              obj.children.forEach(child => traverseGroups(child));
+            };
+            traverseGroups(gltf.scene);
+            // 获取所有子模型并计算中心点
+            model.traverse((child) => {
+              if (child.isGroup) {
+                const center = this.getBoundingBoxCenter(child);
+                this.subModels.push({
+                  name: child.name,
+                  center: center,
+                  originalPosition: child.position.clone(),
+                  mesh: child  // 直接引用mesh对象 用于材质修改
+                });
+              }
+            });
+          });
+        }else if(type == 'B'){
+          //北校区
+          const loaderB = new GLTFLoader();
+          loaderB.load(self.modelsUrlB, (gltf) => {
+            const model = gltf.scene;
+            this.model = gltf.scene;
+            this.scene.add(model);
+            // 递归查找所有Group
+            const traverseGroups = (obj) => {
+              if (obj.isGroup) {
+                this.registerHouse(obj);
+              }
+              obj.children.forEach(child => traverseGroups(child));
+            };
+            traverseGroups(gltf.scene);
+            // 获取所有子模型并计算中心点
+            model.traverse((child) => {
+              if (child.isGroup) {
+                const center = this.getBoundingBoxCenter(child);
+                this.subModels.push({
+                  name: child.name,
+                  center: center,
+                  originalPosition: child.position.clone(),
+                  mesh: child  // 直接引用mesh对象 用于材质修改
+                });
+              }
+            });
+          });
+        }
+        setTimeout(function(){
+          self.buildingApplyTexture([]);
+          // self.buildingColor([]);
+        },500);
+      },
+      /****** 新模型相关方法-开始 *******/
+      // 修改后的 registerHouse 方法
+      registerHouse(group) {
+        const bbox = new THREE.Box3().setFromObject(group);
+        const center = bbox.getCenter(new THREE.Vector3());
+
+        // 记录原始材质
+        const originalMaterials = [];
+        group.traverse(child => {
+          if (child.isMesh) {
+            originalMaterials.push({
+              mesh: child,
+              material: child.material.clone() // 重要:必须克隆原始材质
+            });
+          }
+        });
+
+        this.houses.push({
+          name:group.name,
+          uuid: group.uuid,
+          group: group,
+          screenPosition: new THREE.Vector2(),
+          worldPosition: center,
+          originalMaterials: originalMaterials // 新增原始材质存储
+        });
+      },
+      // 预加载材质和贴图
+      loadAssets() {
+        const textureLoader = new THREE.TextureLoader();
+        this.textures = [
+          textureLoader.load(this.alarmUrl)
+        ];
+      },
+      // 报警样式
+      changeTexture(house) {
+        const texture = this.textures[Math.floor(Math.random() * this.textures.length)];
+        texture.needsUpdate = true;
+
+        house.group.traverse(child => {
+          if (child.isMesh) {
+            child.material.map = texture;
+            child.material.needsUpdate = true;
+          }
+        });
+      },
+      // 恢复正常显示
+      restoreOriginalMaterial(house) {
+        house.originalMaterials.forEach(entry => {
+          entry.mesh.material.dispose(); // 清理当前材质
+          entry.mesh.material = entry.material.clone();
+          entry.mesh.material.needsUpdate = true;
+        });
+      },
+      /****** 新模型相关方法-结束 *******/
+
+      getBoundingBoxCenter(obj) {
+        const box = new THREE.Box3().setFromObject(obj);
+        return box.getCenter(new THREE.Vector3());
+      },
+      onWindowResize() {
+        this.camera.aspect = this.boxWidth / this.boxHeight;
+        this.camera.updateProjectionMatrix();
+        this.renderer.setSize(this.boxWidth, this.boxHeight);
+        this.labelRenderer.setSize(this.boxWidth, this.boxHeight);
+
+      },
+      //动画刷新
+      animate() {
+        if (this.model&&this.rotateType) {
+          this.model.rotation.y += 0.001; // 添加简单旋转动画
+        }else if(this.model&&!this.rotateType){
+          this.model.rotation.y = 0;
+        }
+        // requestAnimationFrame(this.animate);
+        // TWEEN.update();
+        // this.controls.update();
+        // this.renderer.render(this.scene, this.camera);
+        // this.labelRenderer.render(this.scene, this.camera);
+        this.animationId = requestAnimationFrame(this.animate);
+        TWEEN.update();
+        this.controls.update();
+        this.renderer.render(this.scene, this.camera);
+        this.labelRenderer.render(this.scene, this.camera);
+      },
+      //预案关闭
+      alarmOff(){
+        let self = this;
+        self.$set(this,'rotateType',true)
+        if(this.schoolType == 'N'){
+          self.resetCamera();
+          self.del2dText();
+          // self.buildingColor([]);
+          self.buildingApplyTexture([]);
+        }else{
+          //删除所有文字
+          for(let i=0;i<self.scene.children.length;i++){
+            if(self.scene.children[i].isCSS2DObject){
+              self.scene.remove(self.scene.children[i]);
+              i--
+            }
+          }
+          //删除模型数据
+          this.$set(this,'subModels',[]);
+          this.$set(this,'houses',[]);
+          this.scene.children.forEach((item)=>{
+            if(item.type == 'Group'){
+              this.scene.remove(item);
+            }
+          })
+          self.resetCamera();
+          this.delLoadModel('N');
+        }
+      },
+      // 新增恢复视角方法
+      resetCamera() {
+        this.controls.enabled = false;
+        new TWEEN.Tween(this.camera.position)
+          .to(this.initialCameraPosition, 1500)
+          .easing(TWEEN.Easing.Quadratic.InOut)
+          .start();
+
+        new TWEEN.Tween(this.controls.target)
+          .to(this.initialControlsTarget, 1500)
+          .easing(TWEEN.Easing.Quadratic.InOut)
+          .onComplete(() => {
+            this.controls.enabled = true;
+          })
+          .start();
+        this.del2dText();
+      },
+      //删除所有2d文字
+      del2dText(){
+        let self = this;
+        for(let i=0;i<self.scene.children.length;i++){
+          if(self.scene.children[i].isCSS2DObject){
+            this.scene.remove(self.scene.children[i]);
+            i--
+          }
+        }
+      },
+      //预案触发
+      alarmTrigger(list,obj,type){
+        let self = this;
+        self.$set(this,'rotateType',false)
+        //list=所有报警数据 obj=需要聚焦的报警数据 type=报警的校区
+        if(this.schoolType == type){
+          //当前校区
+          self.buildingApplyTexture(list);
+          // self.buildingColor(list);
+          self.focusingLens(obj);
+          //删除所有文字
+          for(let i=0;i<self.scene.children.length;i++){
+            if(self.scene.children[i].isCSS2DObject){
+              self.scene.remove(self.scene.children[i]);
+              i--
+            }
+          }
+          //生成新文字
+          this.alarmTextLabel(list);
+        }else{
+          //其他校区
+          //删除所有文字
+          for(let i=0;i<self.scene.children.length;i++){
+            if(self.scene.children[i].isCSS2DObject){
+              self.scene.remove(self.scene.children[i]);
+              i--
+            }
+          }
+          //删除模型数据
+          this.$set(this,'subModels',[]);
+          this.$set(this,'houses',[]);
+          this.scene.children.forEach((item)=>{
+            if(item.type == 'Group'){
+              self.scene.remove(item);
+            }
+          })
+          //加载新模型
+          this.newLoadModel(list,obj,type);
+        }
+      },
+      //新模型加载
+      newLoadModel(list,obj,type) {
+        let self = this;
+        this.$set(this,'schoolType',type);
+        if(type == 'N'){
+          //南校区
+          const loaderN = new GLTFLoader();
+          loaderN.load(self.modelsUrlN, (gltf) => {
+            const model = gltf.scene;
+            this.model = gltf.scene;
+            this.scene.add(model);
+            // 递归查找所有Group
+            const traverseGroups = (obj) => {
+              if (obj.isGroup) {
+                this.registerHouse(obj);
+              }
+              obj.children.forEach(child => traverseGroups(child));
+            };
+            traverseGroups(gltf.scene);
+            // 获取所有子模型并计算中心点
+            model.traverse((child) => {
+              if (child.isGroup) {
+                const center = this.getBoundingBoxCenter(child);
+                this.subModels.push({
+                  name: child.name,
+                  center: center,
+                  originalPosition: child.position.clone(),
+                  mesh: child  // 直接引用mesh对象 用于材质修改
+                });
+              }
+            });
+          });
+        }else if(type == 'B'){
+          //北校区
+          const loaderB = new GLTFLoader();
+          loaderB.load(self.modelsUrlB, (gltf) => {
+            const model = gltf.scene;
+            this.model = gltf.scene;
+            this.scene.add(model);
+            // 递归查找所有Group
+            const traverseGroups = (obj) => {
+              if (obj.isGroup) {
+                this.registerHouse(obj);
+              }
+              obj.children.forEach(child => traverseGroups(child));
+            };
+            traverseGroups(gltf.scene);
+            // 获取所有子模型并计算中心点
+            model.traverse((child) => {
+              if (child.isGroup) {
+                const center = this.getBoundingBoxCenter(child);
+                this.subModels.push({
+                  name: child.name,
+                  center: center,
+                  originalPosition: child.position.clone(),
+                  mesh: child  // 直接引用mesh对象 用于材质修改
+                });
+              }
+            });
+          });
+        }
+
+        setTimeout(function(){
+          self.focusingLens(obj);
+          self.buildingApplyTexture(list);
+          // self.buildingColor(list);
+          self.alarmTextLabel(list);
+        },1500);
+      },
+      //预案停止模型加载
+      delLoadModel(type) {
+        let self = this;
+        this.$set(this,'schoolType',type);
+        //南校区
+        const loaderN = new GLTFLoader();
+        loaderN.load(self.modelsUrlN, (gltf) => {
+          const model = gltf.scene;
+          this.model = gltf.scene;
+          this.scene.add(model);
+          // 递归查找所有Group
+          const traverseGroups = (obj) => {
+            if (obj.isGroup) {
+              this.registerHouse(obj);
+            }
+            obj.children.forEach(child => traverseGroups(child));
+          };
+          traverseGroups(gltf.scene);
+          // 获取所有子模型并计算中心点
+          model.traverse((child) => {
+            if (child.isGroup) {
+              const center = this.getBoundingBoxCenter(child);
+              this.subModels.push({
+                name: child.name,
+                center: center,
+                originalPosition: child.position.clone(),
+                mesh: child  // 直接引用mesh对象 用于材质修改
+              });
+            }
+          });
+        });
+        setTimeout(function(){
+          self.buildingApplyTexture([]);
+          // self.buildingColor([]);
+        },1500);
+      },
+      //初始化楼栋标记(报警时调用)
+      buildingColor(list){
+        let self = this;
+        //处理基础数据
+        self.modelBuildingList.forEach((maxItem)=>{
+          let num = 0;
+          list.forEach((item)=>{
+            if(maxItem.buildId == item.buildId){
+              num++
+            }
+          })
+          maxItem.alarmType = num != 0;
+        })
+        //处理预警与正常贴图
+        self.modelBuildingList.forEach((maxItem)=>{
+          maxItem.valueList.forEach((bigItem)=>{
+            this.scene.children.forEach((item)=>{
+              if(item.type == 'Group'){
+                item.children.forEach((minItem)=>{
+                  if(minItem.name == bigItem){
+                    if(maxItem.alarmType){
+                      self.applyTexture(self.alarmUrl,minItem);
+                    }else{
+                      self.applyTexture(self.noAlarmUrl,minItem);
+                    }
+                  }
+                })
+              }
+            })
+          })
+        })
+      },
+      buildingApplyTexture(list){
+        let self = this;
+        //处理基础数据
+        self.modelBuildingList.forEach((maxItem)=>{
+          let num = 0;
+          list.forEach((item)=>{
+            if(maxItem.buildId == item.buildId){
+              num++
+            }
+          })
+          maxItem.alarmType = num != 0;
+        })
+        this.$forceUpdate()
+        //处理预警与正常贴图
+        self.modelBuildingList.forEach((maxItem)=>{
+          maxItem.valueList.forEach((bigItem)=>{
+            self.houses.forEach((minItem)=>{
+              if(minItem.name == bigItem){
+                if(maxItem.alarmType){
+                  self.changeTexture(minItem);
+                }else{
+                  self.restoreOriginalMaterial(minItem);
+                }
+              }
+            })
+          })
+        })
+      },
+      //图片材质替换
+      applyTexture(textureName,obj) {
+        const textureLoader = new THREE.TextureLoader();
+        textureLoader.load(
+          textureName, // 图片放在public目录下
+          (texture) => {
+            texture.flipY = false; // 根据图片格式调整
+            obj.traverse((child) => {
+              if (child.isMesh) {
+                // 释放旧纹理资源
+                if (child.material.map) {
+                  child.material.map.dispose();
+                }
+                child.material.map = texture;
+                child.material.needsUpdate = true;
+              }
+            });
+          },
+          undefined,
+          (error) => {
+            console.error('材质加载失败:', error);
+          }
+        );
+      },
+      //材质方法调用
+      changeMaterial(options) {
+        const {
+          modelSelector,    // 支持三种选择方式:名称(name)/索引(index)/'all'
+          materialParams,   // 新材质参数对象
+          keepOriginal = false // 是否保留原始材质
+        } = options;
+
+        const targetMeshes = this.getTargetMeshes(modelSelector);
+
+        targetMeshes.forEach(mesh => {
+          // 创建新材质
+          const newMaterial = this.createMaterial(materialParams);
+
+          // 处理旧材质
+          if (!keepOriginal && mesh.userData.originalMaterial) {
+            mesh.material.dispose();
+          }
+
+          // 应用新材质
+          mesh.material = newMaterial;
+        });
+      },
+      // 辅助方法:获取目标网格
+      getTargetMeshes(selector) {
+        if (selector === 'all') {
+          return this.subModels.map(m => m.mesh);
+        }
+
+        if (typeof selector === 'number') {
+          return [this.subModels[selector].mesh];
+        }
+
+        if (typeof selector === 'string') {
+          return this.subModels
+            .filter(m => m.name === selector)
+            .map(m => m.mesh);
+        }
+
+        return [];
+      },
+      // 材质工厂方法
+      createMaterial(params) {
+        const type = params.type || 'Standard';
+        const baseParams = {
+          color: new THREE.Color(params.color || 0xffffff),
+          map: params.texture ? this.loadTexture(params.texture) : null,
+          transparent: params.transparent || false,
+          opacity: params.opacity || 1.0,
+          ...params
+        };
+
+        switch(type.toLowerCase()) {
+          case 'basic':
+            return new THREE.MeshBasicMaterial(baseParams);
+          case 'phong':
+            return new THREE.MeshPhongMaterial(baseParams);
+          case 'standard':
+            return new THREE.MeshStandardMaterial(baseParams);
+          case 'physical':
+            return new THREE.MeshPhysicalMaterial(baseParams);
+          default:
+            return new THREE.MeshStandardMaterial(baseParams);
+        }
+      },
+      //聚焦镜头查询
+      focusingLens(obj){
+        let self = this;
+        this.modelBuildingList.forEach((maxItem)=>{
+          if(maxItem.buildId == obj.buildId){
+            self.subModels.forEach((bigItem)=>{
+              if(bigItem.name == maxItem.centerValue){
+                self.moveCameraToModel(bigItem,bigItem.name);
+              }
+            })
+          }
+        })
+      },
+      //镜头聚焦方法
+      moveCameraToModel(model,name) {
+        let self = this;
+        // 禁用控制器
+        this.controls.enabled = false;
+
+        // 计算目标位置(模型中心前上方)
+        const targetPosition = new THREE.Vector3()
+          .copy(model.center)
+          .add(new THREE.Vector3(0.2,0.2, 0.2));
+
+        // 动画参数
+        const duration = 1500;
+        const easing = TWEEN.Easing.Quadratic.InOut;
+
+        // 相机位置动画
+        new TWEEN.Tween(this.camera.position)
+          .to(targetPosition, duration)
+          .easing(easing)
+          .start();
+
+        // 控制器目标点动画
+        new TWEEN.Tween(this.controls.target)
+          .to(model.center, duration)
+          .easing(easing)
+          .onComplete(() => {
+            this.controls.enabled = true; // 恢复控制
+          })
+          .start();
+      },
+      //预警文本生成
+      alarmTextLabel(list){
+        let self = this;
+        let newList = [];
+        self.modelBuildingList.forEach((maxItem)=>{
+          list.forEach((item)=>{
+            if(maxItem.buildId == item.buildId){
+              let num = 0;
+              newList.forEach((minItem)=>{
+                if(minItem.buildId == item.buildId){
+                  num++
+                  if(!minItem.textList[1]){
+                    minItem.textList.push(
+                      "<div style='border-top:1px dashed #E90104;margin-top:15px;'>" +
+                      "<p style='color:#FF8400;font-size:24px;line-height:30px;margin-top:19px;'>"+item.riskPlanName+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+this.parseTime(item.eventStartTime,"{y}-{m}-{d} {h}:{i}:{s}")+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+item.floorName+"-"+item.roomNum+"-"+item.deptName+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'><span style='border:1px solid "+item.classLevelColor+";padding:0 10px;margin-right:20px;border-radius:20px;color:"+item.classLevelColor+";'>"+item.classLevelName+"</span>"+item.subName+"</p>"+
+                      "</div>"
+                    )
+                  }else{
+                    minItem.textList.splice(0,1)
+                    minItem.textList.push(
+                      "<div style='border-top:1px dashed #E90104;margin-top:35px;'>" +
+                      "<p style='color:#FF8400;font-size:24px;line-height:30px;margin-top:19px;'>"+item.riskPlanName+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+this.parseTime(item.eventStartTime,"{y}-{m}-{d} {h}:{i}:{s}")+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+item.floorName+"-"+item.roomNum+"-"+item.deptName+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'><span style='border:1px solid "+item.classLevelColor+";padding:0 10px;margin-right:20px;border-radius:20px;color:"+item.classLevelColor+";'>"+item.classLevelName+"</span>"+item.subName+"</p>"+
+                      "</div>"
+                    )
+                  }
+                }
+              })
+              if(num == 0){
+                newList.push(
+                  {
+                    buildId:item.buildId,
+                    centerValue:maxItem.centerValue,
+                    text:"",
+                    //校区-楼栋
+                    titleName:item.schoolName+' - '+item.buildName,
+                    textList:[
+                      "<div>" +
+                      "<p style='color:#FF8400;font-size:24px;line-height:30px;margin-top:19px;'>"+item.riskPlanName+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+this.parseTime(item.eventStartTime,"{y}-{m}-{d} {h}:{i}:{s}")+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+item.floorName+"-"+item.roomNum+"-"+item.deptName+"</p>"+
+                      "<p style='font-size:24px;line-height:30px;margin-top:5px;'><span style='border:1px solid "+item.classLevelColor+";padding:0 10px;margin-right:20px;border-radius:20px;color:"+item.classLevelColor+";'>"+item.classLevelName+"</span>"+item.subName+"</p>"+
+                      "</div>"
+                    ]
+                  }
+                )
+              }
+            }
+          })
+        })
+        //循环定位模型位置并生成textTable
+        newList.forEach((maxItem,maxIndex)=>{
+          maxItem.text = "<div style='z-index:"+maxIndex+";border-radius:20px;padding:20px;color:#ffffff;border:1px solid #E90104;box-shadow: inset 0 0 10px rgba(176, 0, 0, 1);background-color: rgba(187,0,0,0.5)'>"
+          maxItem.text = maxItem.text+"<p style='border-bottom:1px solid #E90104;line-height:30px;padding-bottom:15px;'>"+maxItem.titleName+"</p>";
+          maxItem.textList.forEach((html)=>{
+            maxItem.text = maxItem.text + html
+          })
+          maxItem.text = maxItem.text+"</div>"
+          self.subModels.forEach((bigItem)=>{
+            if(bigItem.name == maxItem.centerValue){
+              forScene(bigItem,maxItem.text);
+            }
+          })
+        })
+        function forScene(model,text){
+          self.scene.children.forEach((item)=>{
+            if(item.type == 'Group'){
+              item.children.forEach((minItem)=>{
+                if(minItem.name == model.name){
+                  self.add2dFont(minItem,model.center,text);
+                }
+              })
+            }
+          })
+        }
+      },
+      //生成css2d文字
+      add2dFont(model,center,text){
+        const labelDiv = document.createElement('div');
+        labelDiv.style.fontSize = '24px';
+        labelDiv.style.width = '560px';
+        labelDiv.style.borderRadius = '10px';
+        labelDiv.style.whiteSpace = "pre-line";
+        labelDiv.innerHTML  = text;
+
+        // 创建 CSS2D 对象并绑定到目标
+        const label = new CSS2DObject(labelDiv);
+        const targetPosition = new THREE.Vector3()
+          .copy(center)
+          .add(new THREE.Vector3(0.09,0.08,-0.1));
+        label.position.set(targetPosition.x,targetPosition.y,targetPosition.z); // 在对象上方 1 单位位置
+        this.scene.add(label);
+      },
+      //内外网地址判定
+      judgmentNetworkReturnAddress() {
+        /*判断是否是内网IP*/
+        // 获取当前页面url
+        var curPageUrl = window.location.href;
+
+        var reg1 = /(http|ftp|https|www):\/\//g;//去掉前缀
+        curPageUrl =curPageUrl.replace(reg1,'');
+
+        var reg2 = /\:+/g;//替换冒号为一点
+        curPageUrl =curPageUrl.replace(reg2,'.');
+
+        curPageUrl = curPageUrl.split('.');//通过一点来划分数组
+
+
+        var ipAddress = curPageUrl[0]+'.'+curPageUrl[1]+'.'+curPageUrl[2]+'.'+curPageUrl[3];
+
+        var isInnerIp = false;//默认给定IP不是内网IP
+        var ipNum = getIpNum(ipAddress);
+        /**
+         * 私有IP:A类  10.0.0.0    -10.255.255.255
+         *       B类  172.16.0.0  -172.31.255.255
+         *       C类  192.168.0.0 -192.168.255.255
+         *       D类   127.0.0.0   -127.255.255.255(环回地址)
+         **/
+        var aBegin = getIpNum("10.0.0.0");
+        var aEnd = getIpNum("10.255.255.255");
+        var bBegin = getIpNum("172.16.0.0");
+        var bEnd = getIpNum("172.31.255.255");
+        var cBegin = getIpNum("192.168.0.0");
+        var cEnd = getIpNum("192.168.255.255");
+        var dBegin = getIpNum("127.0.0.0");
+        var dEnd = getIpNum("127.255.255.255");
+        isInnerIp = isInner(ipNum,aBegin,aEnd) || isInner(ipNum,bBegin,bEnd) || isInner(ipNum,cBegin,cEnd) || isInner(ipNum,dBegin,dEnd);
+        return isInnerIp?true:false;
+        /*获取IP数*/
+        function getIpNum(ipAddress) {
+          var ip = ipAddress.split(".");
+          var a = parseInt(ip[0]);
+          var b = parseInt(ip[1]);
+          var c = parseInt(ip[2]);
+          var d = parseInt(ip[3]);
+          var ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
+          return ipNum;
+        }
+        function isInner(userIp,begin,end){
+          return (userIp>=begin) && (userIp<=end);
+        }
+      },
+      // 资源销毁方法
+      disposeThreeResources() {
+        // 释放几何体和材质
+        this.scene.traverse(child => {
+          if (child.isMesh) {
+            child.geometry.dispose();
+            if (Array.isArray(child.material)) {
+              child.material.forEach(m => m.dispose());
+            } else {
+              child.material.dispose();
+            }
+          }
+        });
+
+        // 释放渲染器
+        this.renderer.dispose();
+        this.labelRenderer.domElement.remove();
+        this.labelRenderer = null;
+
+        // 释放场景和相机
+        this.scene = null;
+        this.camera = null;
+
+        // 释放控制器
+        this.controls.dispose();
+        this.controls = null;
+      },
+    }
+  };
+</script>
+<style scoped lang="scss">
+  .canvasMap{
+    position: absolute;
+    /*top: 122px;*/
+    top: 202px;
+    left: 64px;
+    width: 100%;
+    height: 100%;
+  }
+</style>

+ 178 - 0
src/views/newSafetyOverview/pageComponent/centerNumData.vue

@@ -0,0 +1,178 @@
+<!-- 中央数据显示 -->
+<template>
+    <div class="centerNumData">
+      <div class="centerNumData-page">
+        <div class="num-max-big-box">
+          <p class="num-title-p">今日实验人数</p>
+          <dv-digital-flop :config="labOccupancyCount" class="dvDigitalFlop"/>
+        </div>
+        <div class="num-max-big-box">
+          <p class="num-title-p">今日值日人数</p>
+          <dv-digital-flop :config="dutyCount" class="dvDigitalFlop"/>
+        </div>
+        <div class="num-max-big-box">
+          <p class="num-title-p">今日检查次数</p>
+          <dv-digital-flop :config="checkCount" class="dvDigitalFlop"/>
+        </div>
+        <div class="num-max-big-box">
+          <p class="num-title-p">今日整改次数</p>
+          <dv-digital-flop :config="rectifyCount" class="dvDigitalFlop"/>
+        </div>
+      </div>
+    </div>
+</template>
+<script>
+  const configData1 = {
+    content: '{nt}人',
+    textAlign: 'center',
+    style: {
+      fill: '#fff',
+      fontSize: 36,
+      fontWeight: 220,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#047581', '#A9E9FF'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  const configData2 = {
+    content: '{nt}次',
+    textAlign: 'center',
+    style: {
+      fill: '#fff',
+      fontSize: 36,
+      fontWeight: 220,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#047581', '#A9E9FF'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  import {
+    reportReportBigDataCountStatistics,
+  } from "@/api/index";
+  export default {
+    name: 'centerNumData',
+    data() {
+      return {
+        // 定时器
+        echartsTimer:null,
+        labOccupancyCount: {
+          number: [0],
+          content: configData1.content,
+          textAlign: configData1.textAlign,
+          style: configData1.style
+        },
+        dutyCount: {
+          number: [0],
+          content: configData1.content,
+          textAlign: configData1.textAlign,
+          style: configData1.style
+        },
+        checkCount: {
+          number: [0],
+          content: configData2.content,
+          textAlign: configData2.textAlign,
+          style: configData2.style
+        },
+        rectifyCount: {
+          number: [0],
+          content: configData2.content,
+          textAlign: configData2.textAlign,
+          style: configData2.style
+        },
+      }
+    },
+    created() {
+
+    },
+    mounted() {
+      this.timeFunction()
+      this.getList();
+    },
+    methods: {
+      getList(){
+        reportReportBigDataCountStatistics().then(response => {
+          this.$set(this, 'labOccupancyCount', {
+            number: [response.data.labOccupancyCount],
+            content: configData1.content,
+            textAlign: configData1.textAlign,
+            style: configData1.style
+          })
+          this.$set(this, 'dutyCount', {
+            number: [response.data.dutyCount],
+            content: configData1.content,
+            textAlign: configData1.textAlign,
+            style: configData1.style
+          })
+          this.$set(this, 'checkCount', {
+            number: [response.data.checkCount],
+            content: configData2.content,
+            textAlign: configData2.textAlign,
+            style: configData2.style
+          })
+          this.$set(this, 'rectifyCount', {
+            number: [response.data.rectifyCount],
+            content: configData2.content,
+            textAlign: configData2.textAlign,
+            style: configData2.style
+          })
+        })
+      },
+      //时间定时器
+      timeFunction(){
+        let self = this;
+        this.echartsTimer = window.setInterval(showTime, 180000);
+        function showTime() {
+          self.getList();
+        }
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    }
+  }
+</script>
+<style scoped lang="scss">
+    .centerNumData {
+      width:1293px;
+      position: absolute;
+      bottom: 90px;
+      .centerNumData-page{
+        width:928px;
+        margin:0 auto;
+        display: flex;
+        .num-max-big-box:nth-child(2){
+          margin:0 16px;
+        }
+        .num-max-big-box:nth-child(3){
+          margin-right:16px;
+        }
+        .num-max-big-box{
+          width:220px;
+          height:120px;
+          background: url("../../../assets/ZDimages/img_bg_fwrs@1x.png");
+          .num-title-p{
+            margin-top:10px;
+            line-height:32px;
+            color:#fff;
+            text-align: center;
+            font-size:20px;
+            font-family: SOURCEHANSANSCN;
+          }
+          .dvDigitalFlop{
+            width:220px;
+            line-height:77px;
+            height:77px;
+          }
+        }
+      }
+    }
+</style>

+ 791 - 0
src/views/newSafetyOverview/pageComponent/laboratoryData.vue

@@ -0,0 +1,791 @@
+<!-- 实验室实时数据 -->
+<template>
+  <div class="laboratoryData">
+    <title-page-img-components :propsData="propsData"></title-page-img-components>
+    <div class="laboratoryDataPage">
+      <div class="top-bxo">
+        <div id="laboratoryDataECharts"></div>
+        <div class="position-max-box position-top-left">
+          <p class="position-title">I 级实验室</p>
+          <div class="position-big-box">
+            <dv-digital-flop :config="levelOneCount" class="dvDigitalFlop"/>
+            <p class="position-right-p">间</p>
+          </div>
+        </div>
+        <div class="position-max-box position-top-right">
+          <p class="position-title">II 级实验室</p>
+          <div class="position-big-box">
+            <dv-digital-flop :config="levelTwoCount" class="dvDigitalFlop"/>
+            <p class="position-right-p">间</p>
+          </div>
+        </div>
+        <div class="position-max-box position-bottom-left">
+          <p class="position-title">III 级实验室</p>
+          <div class="position-big-box">
+            <dv-digital-flop :config="levelThreeCount" class="dvDigitalFlop"/>
+            <p class="position-right-p">间</p>
+          </div>
+        </div>
+        <div class="position-max-box position-bottom-right">
+          <p class="position-title">IV 级实验室</p>
+          <div class="position-big-box">
+            <dv-digital-flop :config="levelFourCount" class="dvDigitalFlop"/>
+            <p class="position-right-p">间</p>
+          </div>
+        </div>
+        <div class="position-center-num-box">
+          <p class="position-title">总计</p>
+          <dv-digital-flop :config="labTotal" class="dvDigitalFlop"/>
+        </div>
+      </div>
+      <div class="bottomBox">
+        <div class="back-box back-box-1">
+          <div class="back-min-box">
+            <p>使用</p>
+            <dv-digital-flop :config="useTotal" class="dvDigitalFlop"/>
+            <p>间</p>
+          </div>
+        </div>
+        <div class="back-box back-box-2">
+          <div class="back-min-box">
+            <p>异常</p>
+            <dv-digital-flop :config="exceptionalTotal" class="dvDigitalFlop"/>
+            <p>间</p>
+          </div>
+        </div>
+        <div class="back-box back-box-3">
+          <div class="back-min-box">
+            <p>空闲</p>
+            <dv-digital-flop :config="availableTotal" class="dvDigitalFlop"/>
+            <p>间</p>
+          </div>
+        </div>
+      </div>
+      <div class="bottom-box">
+        <div class="bottom-min-box">
+          <p class="left-p">{{bottomDataName1}}:</p>
+          <dv-digital-flop :config="bottomDataTotal1" class="dvDigitalFlop"/>
+          <p class="right-p">间</p>
+        </div>
+        <div class="bottom-min-box">
+          <p class="left-p">{{bottomDataName2}}:</p>
+          <dv-digital-flop :config="bottomDataTotal2" class="dvDigitalFlop"/>
+          <p class="right-p">间</p>
+        </div>
+        <div class="bottom-min-box">
+          <p class="left-p">{{bottomDataName3}}:</p>
+          <dv-digital-flop :config="bottomDataTotal3" class="dvDigitalFlop"/>
+          <p class="right-p">间</p>
+        </div>
+      </div>
+    </div>
+    <!--<add-page :propsData="propsData" v-if="pageType === 2"></add-page>-->
+  </div>
+</template>
+<script>
+  const configData0 = {
+    content: '{nt}',
+    textAlign: 'center',
+    style: {
+      fill: '#fff',
+      fontSize: 20,
+      fontWeight: 700,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientParams: [0, 0, 0, 30]
+    }
+  }
+  const configData1 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#fff',
+      fontSize: 30,
+      fontWeight: 700,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff', '#F38181'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  const configData2 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#fff',
+      fontSize: 30,
+      fontWeight: 700,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff', '#D8A746'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  const configData3 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#fff',
+      fontSize: 30,
+      fontWeight: 700,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff', '#539FFC'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  const configData4 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#fff',
+      fontSize: 30,
+      fontWeight: 700,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff', '#56A757'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  const configData5 = {
+    content: '{nt}',
+    textAlign: 'center',
+    style: {
+      fill: '#0586FF',
+      fontSize: 16,
+      fontWeight: 700,
+      fontFamily: 'AlimamaShuHeiTi',
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  const configData6 = {
+    content: '{nt}',
+    textAlign: 'center',
+    style: {
+      fill: '#FF8C00',
+      fontSize: 16,
+      fontWeight: 700,
+      fontFamily: 'AlimamaShuHeiTi',
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  const configData7 = {
+    content: '{nt}',
+    textAlign: 'center',
+    style: {
+      fill: '#25D748',
+      fontSize: 16,
+      fontWeight: 700,
+      fontFamily: 'AlimamaShuHeiTi',
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  const configData8 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#0183FA',
+      fontSize: 16,
+      fontWeight: 65,
+      fontFamily: 'AlimamaShuHeiTi',
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  const configData9 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#25D748',
+      fontSize: 16,
+      fontWeight: 65,
+      fontFamily: 'AlimamaShuHeiTi',
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  const configData10 = {
+    content: '{nt}',
+    textAlign: 'right',
+    style: {
+      fill: '#00FFFF',
+      fontSize: 16,
+      fontWeight: 65,
+      fontFamily: 'AlimamaShuHeiTi',
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  import { laboratorySubRelInfoLabStateStatisticsAll,
+    laboratorySubRelInfoGetLabTypeStatistics,} from "@/api/index";
+  import titlePageImgComponents from '@/components/titlePageImgComponents.vue'
+
+  export default {
+    name: 'index',
+    components: {
+      titlePageImgComponents
+    },
+    data() {
+      return {
+        //组件传参
+        propsData: {
+          title: '全校实验室实时统计数量'
+        },
+        //echarts数据
+        echartsBox:null,
+        // 定时器
+        echartsTimer:null,
+        labTotal: {
+          number: [0],
+          content: configData0.content,
+          textAlign: configData0.textAlign,
+          style: configData0.style
+        },
+        levelOneCount: {
+          number: [0],
+          content: configData1.content,
+          textAlign: configData1.textAlign,
+          style: configData1.style
+        },
+        levelTwoCount: {
+          number: [0],
+          content: configData2.content,
+          textAlign: configData2.textAlign,
+          style: configData2.style
+        },
+        levelThreeCount: {
+          number: [0],
+          content: configData3.content,
+          textAlign: configData3.textAlign,
+          style: configData3.style
+        },
+        levelFourCount: {
+          number: [0],
+          content: configData4.content,
+          textAlign: configData4.textAlign,
+          style: configData4.style
+        },
+        useTotal: {
+          number: [0],
+          content: configData5.content,
+          textAlign: configData5.textAlign,
+          style: configData5.style
+        },
+        exceptionalTotal: {
+          number: [0],
+          content: configData6.content,
+          textAlign: configData6.textAlign,
+          style: configData6.style
+        },
+        availableTotal: {
+          number: [0],
+          content: configData7.content,
+          textAlign: configData7.textAlign,
+          style: configData7.style
+        },
+        bottomDataTotal1: {
+          number: [0],
+          content: configData8.content,
+          textAlign: configData8.textAlign,
+          style: configData8.style
+        },
+        bottomDataTotal2: {
+          number: [0],
+          content: configData9.content,
+          textAlign: configData9.textAlign,
+          style: configData9.style
+        },
+        bottomDataTotal3: {
+          number: [0],
+          content: configData10.content,
+          textAlign: configData10.textAlign,
+          style: configData10.style
+        },
+        bottomDataName1:'',
+        bottomDataName2:'',
+        bottomDataName3:'',
+      }
+    },
+    created() {
+
+    },
+    mounted() {
+      this.getList()
+      this.timeFunction();
+    },
+    methods: {
+      getList() {
+        laboratorySubRelInfoLabStateStatisticsAll().then(response => {
+          this.$set(this, 'labTotal', {
+            number: [response.data.labTotal],
+            content: configData0.content,
+            textAlign: configData0.textAlign,
+            style: configData0.style
+          })
+          this.$set(this, 'levelOneCount', {
+            number: [response.data.levelOneCount],
+            content: configData1.content,
+            textAlign: configData1.textAlign,
+            style: configData1.style
+          })
+          this.$set(this, 'levelTwoCount', {
+            number: [response.data.levelTwoCount],
+            content: configData2.content,
+            textAlign: configData2.textAlign,
+            style: configData2.style
+          })
+          this.$set(this, 'levelThreeCount', {
+            number: [response.data.levelThreeCount],
+            content: configData3.content,
+            textAlign: configData3.textAlign,
+            style: configData3.style
+          })
+          this.$set(this, 'levelFourCount', {
+            number: [response.data.levelFourCount],
+            content: configData4.content,
+            textAlign: configData4.textAlign,
+            style: configData4.style
+          })
+          this.$set(this, 'useTotal', {
+            number: [response.data.useTotal],
+            content: configData5.content,
+            textAlign: configData5.textAlign,
+            style: configData5.style
+          })
+          this.$set(this, 'exceptionalTotal', {
+            number: [response.data.exceptionalTotal],
+            content: configData6.content,
+            textAlign: configData6.textAlign,
+            style: configData6.style
+          })
+          this.$set(this, 'availableTotal', {
+            number: [response.data.availableTotal],
+            content: configData7.content,
+            textAlign: configData7.textAlign,
+            style: configData7.style
+          })
+          const optionsData = [
+            {
+              name: 'I级',
+              value: response.data.levelOneCount,
+              itemStyle: {
+                color: '#F38181'
+              }
+            },
+
+            {
+              name: 'II级',
+              value: response.data.levelTwoCount,
+              itemStyle: {
+                color: '#D8A746'
+              }
+            },
+            {
+              name: 'III级',
+              value: response.data.levelThreeCount,
+              itemStyle: {
+                color: '#539FFC'
+              }
+            },
+            {
+              name: 'IIII级',
+              value: response.data.levelFourCount,
+              itemStyle: {
+                color: '#56A757'
+              }
+            }
+          ]
+          this.eChartsMethod(optionsData)
+        })
+        laboratorySubRelInfoGetLabTypeStatistics().then(response => {
+          response.data.forEach((item,index)=>{
+            if(index == 0){
+              this.$set(this,'bottomDataName1',item.subType);
+              this.$set(this, 'bottomDataTotal1', {
+                number: [item.count],
+                content: configData8.content,
+                textAlign: configData8.textAlign,
+                style: configData8.style
+              })
+            }else if(index == 1){
+              this.$set(this,'bottomDataName2',item.subType);
+              this.$set(this, 'bottomDataTotal2', {
+                number: [item.count],
+                content: configData9.content,
+                textAlign: configData9.textAlign,
+                style: configData9.style
+              })
+            }else if(index == 2){
+              this.$set(this,'bottomDataName3',item.subType);
+              this.$set(this, 'bottomDataTotal3', {
+                number: [item.count],
+                content: configData10.content,
+                textAlign: configData10.textAlign,
+                style: configData10.style
+              })
+            }
+          })
+        })
+      },
+      eChartsMethod(optionsData) {
+        // 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
+        function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, height) {
+
+          // 计算
+          let midRatio = (startRatio + endRatio) / 2
+
+          let startRadian = startRatio * Math.PI * 2
+          let endRadian = endRatio * Math.PI * 2
+          let midRadian = midRatio * Math.PI * 2
+
+          // 如果只有一个扇形,则不实现选中效果。
+          if (startRatio === 0 && endRatio === 1) {
+            isSelected = false
+          }
+
+          // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
+          k = typeof k !== 'undefined' ? k : 1 / 3
+
+          // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
+          let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
+          let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0
+
+          // 计算高亮效果的放大比例(未高亮,则比例为 1)
+          let hoverRate = isHovered ? 1.05 : 1
+
+          // 返回曲面参数方程
+          return {
+
+            u: {
+              min: -Math.PI,
+              max: Math.PI * 3,
+              step: Math.PI / 32
+            },
+
+            v: {
+              min: 0,
+              max: Math.PI * 2,
+              step: Math.PI / 20
+            },
+
+            x: function(u, v) {
+              if (u < startRadian) {
+                return offsetX + Math.cos(startRadian) * (1.4 + Math.cos(v) * k) * hoverRate
+              }
+              if (u > endRadian) {
+                return offsetX + Math.cos(endRadian) * (1.4 + Math.cos(v) * k) * hoverRate
+              }
+              return offsetX + Math.cos(u) * (1.4 + Math.cos(v) * k) * hoverRate
+            },
+
+            y: function(u, v) {
+              if (u < startRadian) {
+                return offsetY + Math.sin(startRadian) * (1.4 + Math.cos(v) * k) * hoverRate
+              }
+              if (u > endRadian) {
+                return offsetY + Math.sin(endRadian) * (1.4 + Math.cos(v) * k) * hoverRate
+              }
+              return offsetY + Math.sin(u) * (1.4 + Math.cos(v) * k) * hoverRate
+            },
+
+            z: function(u, v) {
+              if (u < -Math.PI * 0.5) {
+                return Math.sin(u)
+              }
+              if (u > Math.PI * 2.5) {
+                return Math.sin(u)
+              }
+              return Math.sin(v) > 0 ? 1 * height : -1
+            }
+          }
+        }
+
+        // 生成模拟 3D 饼图的配置项
+        function getPie3D(pieData, internalDiameterRatio) {
+
+          let series = []
+          let sumValue = 0
+          let startValue = 0
+          let endValue = 0
+          let legendData = []
+          let k = typeof internalDiameterRatio !== 'undefined' ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3
+
+          // 为每一个饼图数据,生成一个 series-surface 配置
+          for (let i = 0; i < pieData.length; i++) {
+
+            sumValue += pieData[i].value
+
+            let seriesItem = {
+              name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
+              type: 'surface',
+              parametric: true,
+              wireframe: {
+                show: false
+              },
+              pieData: pieData[i],
+              pieStatus: {
+                selected: false,
+                hovered: false,
+                k: k
+              }
+            }
+
+            if (typeof pieData[i].itemStyle != 'undefined') {
+
+              let itemStyle = {}
+
+              typeof pieData[i].itemStyle.color != 'undefined' ? itemStyle.color = pieData[i].itemStyle.color : null
+              typeof pieData[i].itemStyle.opacity != 'undefined' ? itemStyle.opacity = pieData[i].itemStyle.opacity : null
+
+              seriesItem.itemStyle = itemStyle
+            }
+            series.push(seriesItem)
+          }
+
+          // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
+          // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
+          for (let i = 0; i < series.length; i++) {
+            endValue = startValue + series[i].pieData.value
+            series[i].pieData.startRatio = startValue / sumValue
+            series[i].pieData.endRatio = endValue / sumValue
+            series[i].parametricEquation = getParametricEquation(series[i].pieData.startRatio, series[i].pieData.endRatio, false, false, k, 20)
+
+            startValue = endValue
+
+            legendData.push(series[i].name)
+          }
+          return series
+        }
+
+        // const series = getPie3D(optionsData, 0.8, 240, 28, 26, 0.5)
+        const series = getPie3D(optionsData, 1.4, 240, 28, 26, 0.5)
+
+        // 准备待返回的配置项,把准备好的 legendData、series 传入。
+        let option = {
+          legend: {
+            show: false
+          },
+          animation: false,
+          tooltip: {
+            show: false
+          },
+          title: {
+            show: false
+          },
+          labelLine: {
+            show: false
+          },
+          label: {
+            show: false
+          },
+          xAxis3D: {
+            min: -1,
+            max: 1
+          },
+          yAxis3D: {
+            min: -1,
+            max: 1
+          },
+          zAxis3D: {
+            min: -1,
+            max: 1
+          },
+          grid3D: {
+            show: false,
+            boxHeight: 1,
+            //top: '30%',
+            bottom: '50%',
+            viewControl: {
+              distance: 180,
+              alpha: 30,
+              beta: 60,
+
+              autoRotate: false // 自动旋转
+            }
+
+          },
+
+          series: series
+        }
+
+        this.echartsBox = this.$echarts.init(document.getElementById('laboratoryDataECharts'));
+        this.echartsBox.clear();
+        this.echartsBox.setOption(option);
+      },
+      //时间定时器
+      timeFunction(){
+        let self = this;
+        this.echartsTimer = window.setInterval(showTime, 180000);
+        function showTime() {
+          self.getList();
+        }
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .laboratoryData {
+    width: 652px;
+    height: 526px;
+    overflow: hidden;
+    .laboratoryDataPage {
+      width: 650px;
+      height: 467px;
+      padding:20px 46px;
+      background: linear-gradient( 180deg, rgba(4,117,129,0.2) 0%, rgba(0,15,22,0) 100%);
+      .top-bxo {
+        width: 553px;
+        height: 245px;
+        background: url("../../../assets/ZDimages/img_syssjbg@1x.png");
+        background-size: 100%;
+        position: relative;
+        #laboratoryDataECharts {
+          width:320px;
+          height:189px;
+          left:116px;
+          top:0;
+        }
+        .position-max-box {
+          width: 256px;
+          height: 101px;
+          position: absolute;
+          .position-title {
+            color: #fff;
+            font-size: 14px;
+            margin: 24px 0 0 17px;
+          }
+          .position-big-box {
+            display: flex;
+            margin: 15px 0 0 0;
+            .dvDigitalFlop {
+              line-height: 30px;
+              height: 30px;
+              width: 85px;
+            }
+            .position-right-p {
+              font-size: 14px;
+              line-height: 30px;
+              margin-left: 5px;
+              color: #fff;
+            }
+          }
+        }
+        .position-top-left {
+          top: 0;
+          left: 0;
+        }
+        .position-top-right {
+          top: 0;
+          right: 0;
+          .position-title {
+            text-align: right;
+            margin-right:25px;
+          }
+          .dvDigitalFlop {
+            width: 220px !important;
+          }
+        }
+        .position-bottom-left {
+          bottom: 0;
+          left: 0;
+        }
+        .position-bottom-right {
+          bottom: 0;
+          right: 0;
+          .position-title {
+            text-align: right;
+            margin-right:25px;
+          }
+          .dvDigitalFlop {
+            width: 220px !important;
+          }
+        }
+        .position-center-num-box{
+          position: absolute;
+          top:75px;
+          left:170px;
+          .position-title {
+            color: #fff;
+            font-size: 14px;
+            text-align: center;
+          }
+          .dvDigitalFlop {
+            line-height: 30px;
+            height: 30px;
+            width: 210px;
+          }
+        }
+      }
+      .bottomBox {
+        display: flex;
+        .back-box{
+          width:178px;
+          height:110px;
+          .back-min-box{
+            margin-top:38px;
+            margin-left:75px;
+            display: flex;
+            p{
+              color:#fff;
+              font-size:14px;
+              line-height:40px;
+            }
+            .dvDigitalFlop{
+              width:50px;
+              height:45px;
+              line-height:45px;
+            }
+          }
+        }
+        .back-box-1{
+          background: url("../../../assets/ZDimages/img_syssjbg_sy@1x.png");
+          background-size: 100%;
+        }
+        .back-box-2{
+          margin:0 15px;
+          background: url("../../../assets/ZDimages/img_syssjbg_yc@1x.png");
+          background-size: 100%;
+        }
+        .back-box-3{
+          background: url("../../../assets/ZDimages/img_syssjbg_kx@1x.png");
+          background-size: 100%;
+        }
+      }
+      .bottom-box{
+        display: flex;
+        .bottom-min-box:nth-child(2){
+          margin:0 8px;
+        }
+        .bottom-min-box{
+          width:182px;
+          height:50px;
+          background: url("../../../assets/ZDimages/img_yjczbg.png");
+          background-size: 100%;
+          display: flex;
+          .left-p{
+            font-size:14px;
+            color:#fff;
+            text-align: right;
+            line-height: 50px;
+            width:80px;
+          }
+          .right-p{
+            font-size:14px;
+            color:#fff;
+            line-height: 50px;
+            width:27px;
+            margin-left:10px;
+          }
+        }
+      }
+    }
+  }
+</style>

+ 301 - 0
src/views/newSafetyOverview/pageComponent/resourceAndEquipmentStatistics.vue

@@ -0,0 +1,301 @@
+<!-- 特种设备与常规冷热设备 -->
+<template>
+  <div class="resourceAndEquipmentStatistics">
+    <title-page-img-components :propsData="propsData"></title-page-img-components>
+    <div class="resourceAndEquipmentStatisticsPage">
+      <div class="left-box" id="resourceAndEquipmentStatisticsECharts">
+
+      </div>
+      <div class="right-box">
+        <div class="for-max-box" v-for="(item,index) in dataList" :key="index">
+          <div class="for-title-box">
+            <p :class="index==0?'border-color-1':(index==1?'border-color-2':(index==2?'border-color-3':(index==3?'border-color-4':(index==4?'border-color-5':''))))"></p>
+            <p>{{item.name}}</p>
+            <dv-digital-flop :config="item.config" class="dvDigitalFlop" />
+          </div>
+          <div class="for-background"></div>
+        </div>
+      </div>
+      <div class="position-num-box">
+        <p class="position-title">设备总数(台)</p>
+        <dv-digital-flop :config="maxNum" class="position-num" />
+      </div>
+      <p class="position-left-p"></p>
+      <p class="position-right-p"></p>
+    </div>
+    <!--<add-page :propsData="propsData" v-if="pageType === 2"></add-page>-->
+  </div>
+</template>
+<script>
+  const configData = {
+    content: '{nt}%',
+    textAlign :'right',
+    style:{
+      fill:'#fff',
+      fontSize: 20,
+      fontWeight:110,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff','#fff'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith:'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 30],
+    }
+  }
+  const numConfigData = {
+    content: '{nt}',
+    textAlign :'center',
+    style:{
+      fill:'#fff',
+      fontSize: 16,
+      fontWeight:700,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff','#fff'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith:'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 140],
+    }
+  }
+  import { reportReportBsEquipLifeList } from "@/api/index";
+  import titlePageImgComponents from '@/components/titlePageImgComponents.vue'
+  export default {
+    name: 'index',
+    components: {
+      titlePageImgComponents
+    },
+    data () {
+      return {
+        //组件传参
+        propsData:{
+          title:'实验室冷热与特种设备统计',
+        },
+        dataList:[
+          {name:"5年内",value:0,config:{number:[0], content:configData.content,textAlign:configData.textAlign, style:configData.style}},
+          {name:"10年内",value:0,config:{number:[0], content:configData.content,textAlign:configData.textAlign, style:configData.style}},
+          {name:"12年内",value:0,config:{number:[0], content:configData.content,textAlign:configData.textAlign, style:configData.style}},
+          {name:"20年内",value:0,config:{number:[0], content:configData.content,textAlign:configData.textAlign, style:configData.style}},
+          {name:"超期服役",value:0,config:{number:[0], content:configData.content,textAlign:configData.textAlign, style:configData.style}},
+        ],
+        //设备总数
+        maxNum:{number:[0], content:numConfigData.content,textAlign:numConfigData.textAlign, style:numConfigData.style},
+        //echarts数据
+        echartsBox:null,
+        // 定时器
+        echartsTimer:null,
+      }
+    },
+    created () {
+
+    },
+    mounted () {
+      this.getList();
+      this.timeFunction();
+    },
+    methods: {
+      getList(){
+        reportReportBsEquipLifeList().then(response => {
+          let deviceNum = 0;
+          let list = []
+          for (let i = 0; i < response.data.length; i++) {
+            deviceNum = deviceNum+(response.data[i].deviceNum ? response.data[i].deviceNum : 0);
+            list.push({
+              name: response.data[i].lifeInterval ? response.data[i].lifeInterval : '未知',
+              value: response.data[i].deviceNum ? response.data[i].deviceNum : 0,
+              config:{
+                number:[response.data[i].deviceRate?response.data[i].deviceRate:0],
+                content:configData.content,
+                textAlign:configData.textAlign,
+                style:configData.style,
+              }
+            })
+          }
+          this.$set(this, 'dataList', list)
+          this.$set(this, 'maxNum', {
+            number:[deviceNum],
+            content:numConfigData.content,
+            textAlign:numConfigData.textAlign,
+            style:numConfigData.style
+          })
+          this.eChartsMethod(list)
+        })
+      },
+      eChartsMethod(list){
+        let option = {
+          color:['#3BB9FD', '#73BE7F', '#82DEE1', '#F8D2A9', '#FFA0A0'],
+          tooltip: {
+            show: false,
+            trigger: 'item'
+          },
+          legend: {
+            show: false
+          },
+          series: [
+            {
+              name: 'Access From',
+              type: 'pie',
+              radius: ['47%', '60%'],
+              avoidLabelOverlap: false,
+              label: {
+                show: false
+              },
+              emphasis: {
+                show: false,
+                label: {
+                  show: false
+                }
+              },
+              labelLine: {
+                show: false
+              },
+              data: list
+            }
+          ]
+        };
+        this.echartsBox = this.$echarts.init(document.getElementById('resourceAndEquipmentStatisticsECharts'));
+        this.echartsBox.clear();
+        this.echartsBox.setOption(option);
+      },
+      //时间定时器
+      timeFunction(){
+        let self = this;
+        this.echartsTimer = window.setInterval(showTime, 180000);
+        function showTime() {
+          self.getList();
+        }
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .resourceAndEquipmentStatistics{
+    width: 652px;
+    height: 403px;
+    overflow: hidden;
+    .resourceAndEquipmentStatisticsPage{
+      width:652px;
+      height:339px;
+      padding-top:20px ;
+      background: linear-gradient( 180deg, rgba(4,117,129,0.2) 0%, rgba(0,15,22,0) 100%);
+      display: flex;
+      position: relative;
+      .left-box{
+        width:409px;
+        height:339px;
+      }
+      .right-box{
+        width:225px;
+        height:339px;
+        padding-top:30px;
+        .for-max-box{
+          height:50px;
+          width:225px;
+          position: relative;
+          .for-title-box{
+            padding-right:10px;
+            display: flex;
+            p:nth-child(1){
+              width:20px;
+              height:20px;
+              margin:7px 14px;
+              -webkit-border-radius: 50%;
+              -moz-border-radius: 50%;
+              border-radius: 50%;
+            }
+            p:nth-child(2){
+              height: 30px;
+              line-height: 30px;
+              flex:1;
+              color:#fff;
+              font-size:14px;
+              font-family: SOURCEHANSANSCN;
+            }
+            .dvDigitalFlop{
+              height: 30px;
+              line-height: 30px;
+              color:#fff;
+              width:110px;
+              font-family: YouSheBiaoTiHei;
+            }
+            .border-color-1{
+              border:3px solid #3BB9FD;
+            }
+            .border-color-2{
+              border:3px solid #73BE7F;
+            }
+            .border-color-3{
+              border:3px solid #82DEE1;
+            }
+            .border-color-4{
+              border:3px solid #F8D2A9;
+            }
+            .border-color-5{
+              border:3px solid #FFA0A0;
+            }
+          }
+          .for-background{
+            position: absolute;
+            top:35px;
+            left:0;
+            width:225px;
+            height:5px;
+            background-color: #206A9F;
+            /*background: url("../../../assets/ZDimages/img_zysb_sjbg@1x.png");*/
+            -webkit-background-size: 100%;
+            background-size: 100%;
+          }
+        }
+      }
+      .position-left-p{
+        position: absolute;
+        width: 88px;
+        height: 170px;
+        left:22px;
+        top:115px;
+        background: url("../../../assets/ZDimages/img_zysb_tbbjr@1x.png");
+        -webkit-background-size: 100%;
+        background-size: 100%;
+      }
+      .position-right-p{
+        position: absolute;
+        width: 88px;
+        height: 170px;
+        left:298px;
+        top:108px;
+        background: url("../../../assets/ZDimages/img_zysb_tbbjl@1x.png");
+        -webkit-background-size: 100%;
+        background-size: 100%;
+      }
+      .position-num-box{
+        position: absolute;
+        width: 113px;
+        height: 113px;
+        left:148px;
+        top:133px;
+        background: url("../../../assets/ZDimages/img_sbzsbg@1x.png");
+        -webkit-background-size: 100%;
+        background-size: 100%;
+        .position-title{
+          margin-top:45px;
+          text-align: center;
+          color:#fff;
+          font-size:14px;
+          line-height:20px;
+          font-family: SOURCEHANSANSCN;
+        }
+        .position-num{
+          height: 20px;
+          line-height: 20px;
+          color:#fff;
+          font-family: YouSheBiaoTiHei;
+        }
+      }
+    }
+  }
+</style>

+ 408 - 0
src/views/newSafetyOverview/pageComponent/secondaryCollegeUnitLaboratoryStatistics.vue

@@ -0,0 +1,408 @@
+<!-- 二级学院单位实验室统计 -->
+<template>
+  <div class="secondaryCollegeUnitLaboratoryStatistics">
+    <title-page-img-components :propsData="propsData"></title-page-img-components>
+    <div class="secondaryCollegeUnitLaboratoryStatistics-page">
+      <div class="secondaryCollegeUnitLaboratoryStatisticsPage" id="secondaryCollegeUnitLaboratoryStatisticsECharts">
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  import titlePageImgComponents from '@/components/titlePageImgComponents.vue'
+  import { laboratorySubRelInfoLabStateStatisticsAll } from "@/api/index";
+  export default {
+    name: 'index',
+    components: {
+      titlePageImgComponents
+    },
+    data () {
+      return {
+        propsData: {
+          title: '学院单位实验室分级数量'
+        },
+        //echarts数据
+        echartsBox:null,
+        // 定时器
+        echartsTimer:null,
+        minTimer:null,
+        //数据
+        dataList:[],
+        numIndex:0,
+        maxNum: 0,
+      }
+    },
+    created () {
+
+    },
+    mounted () {
+      this.getList();
+      this.timeFunction();
+    },
+    methods: {
+      getList(){
+        laboratorySubRelInfoLabStateStatisticsAll().then(response => {
+          this.$set(this,'numIndex',0);
+          this.$set(this,'maxNum',response.data.labLevelVOList.length-1);
+          response.data.labLevelVOList.forEach((item)=>{
+            item.num = item.levelOneCount + item.levelTwoCount + item.levelThreeCount + item.levelFourCount;
+          })
+          response.data.labLevelVOList = response.data.labLevelVOList.slice().sort((a, b) => b.num - a.num);
+          this.$set(this,'dataList',response.data.labLevelVOList);
+          this.minTimeFunction();
+          // let obj = {
+          //   nameList:[],
+          //   dataListA : [],
+          //   dataListB : [],
+          //   dataListC : [],
+          //   dataListD : [],
+          //   dataListE : [],
+          // };
+          // const maxNum = response.data.labLevelVOList[0].levelOneCount + response.data.labLevelVOList[0].levelTwoCount + response.data.labLevelVOList[0].levelThreeCount + response.data.labLevelVOList[0].levelFourCount
+          // response.data.labLevelVOList.forEach((item)=>{
+          //   let num = item.levelOneCount+item.levelTwoCount+item.levelThreeCount+item.levelFourCount
+          //   obj.nameList.push(item.deptName)
+          //   obj.dataListA.push(item.levelOneCount)
+          //   obj.dataListB.push(item.levelTwoCount)
+          //   obj.dataListC.push(item.levelThreeCount)
+          //   obj.dataListD.push(item.levelFourCount)
+          //   obj.dataListE.push({
+          //     name:num,
+          //     value:maxNum-num
+          //   })
+          // })
+          // this.eChartsMethod(obj);
+        })
+      },
+      minTimeFunction(){
+        let self = this;
+        showTime();
+        if(!this.minTimer){
+          this.minTimer = window.setInterval(showTime, 10000);
+        }
+        function showTime() {
+          if(self.dataList[0]){
+            let newList = [];
+            for(let i=0;i<5;i++){
+              if(self.dataList[self.numIndex]){
+                newList.push(self.dataList[self.numIndex])
+                if(self.numIndex<self.maxNum){
+                  self.numIndex++;
+                }else{
+                  self.numIndex=0;
+                  break
+                }
+              }
+            }
+            let obj = {
+              nameList:[],
+              dataListA : [],
+              dataListB : [],
+              dataListC : [],
+              dataListD : [],
+              dataListE : [],
+            };
+            if(newList[0]){
+              const maxNum = newList[0].levelOneCount + newList[0].levelTwoCount + newList[0].levelThreeCount + newList[0].levelFourCount
+              newList.forEach((item)=>{
+                let num = item.levelOneCount+item.levelTwoCount+item.levelThreeCount+item.levelFourCount
+                obj.nameList.push(item.deptName)
+                obj.dataListA.push(item.levelOneCount)
+                obj.dataListB.push(item.levelTwoCount)
+                obj.dataListC.push(item.levelThreeCount)
+                obj.dataListD.push(item.levelFourCount)
+                obj.dataListE.push({
+                  name:num,
+                  value:maxNum-num
+                })
+              })
+              self.eChartsMethod(obj);
+            }
+          }
+        }
+      },
+      eChartsMethod(obj){
+        let option = {
+          title: {
+            show:false,
+          },
+          tooltip: {
+            show:false,
+            trigger: "axis",
+            axisPointer: {
+              type: "shadow",
+              textStyle: {
+                color: "#fff",
+              },
+            },
+            textStyle: {
+              color: "#fff",
+            },
+            backgroundColor: "background: rgba(255,255,255,0.1);", //设置背景颜色
+            borderColor: "rgba(255,255,255,0.1)",
+            formatter:function (data) {
+              return (data.name )
+            },
+          },
+          legend: {
+            icon:'rect',
+            left: 'center',
+            top:'15',
+            itemGap:55,
+            itemWidth:30,
+            itemHeight:10,
+            show: true,
+            textStyle:{
+              fontSize:14,
+              color:'#fff',
+            },
+            data: [
+              { name: 'I 级', itemStyle: { color: '#F38181' } }, // 设置系列1图例的文字颜色为红色
+              { name: 'II 级', itemStyle: { color: '#D8A746' } }, // 设置系列1图例的文字颜色为红色
+              { name: 'III 级', itemStyle: { color: '#3876E1' } }, // 设置系列1图例的文字颜色为红色
+              { name: 'IV 级', itemStyle: { color: '#56A757' } }  // 设置系列2图例的文字颜色为绿色
+              // 可以继续添加更多系列及其图例颜色配置
+            ],
+          },
+          grid: {
+            left: "10%",
+            right: "10%",
+            bottom: "10%",
+            top: "20%",
+          },
+          xAxis: {
+            type: 'category',
+            data: obj.nameList,
+            axisLabel:{
+              color:'#fff',
+              fontSize:'14',
+            },
+            axisLine:{
+              show:true,
+              lineStyle:{
+                color:'#41A4FF',
+              }
+            },
+            splitLine: {
+              show: false
+            },
+            axisTick: {
+              show: false
+            }
+          },
+          yAxis: {
+            type: 'value',
+            axisLabel:{
+              color:'#fff',
+              fontSize:'14',
+            },
+            axisLine:{
+              show:true,
+              lineStyle:{
+                color:'#41A4FF',
+              }
+            },
+            splitLine: {
+              show: false
+            },
+            axisTick: {
+              show: false
+            }
+          },
+          series: [
+            {
+              name: 'I 级',
+              type: 'bar',
+              barWidth: 16,
+              stack: '数量',
+              data: obj.dataListA,
+              itemStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 0,
+                    y: 1,
+                    x2: 0,
+                    y2: 0,
+                    type: 'linear',
+                    global: false,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: '#D8D8D8',
+                      },
+                      {
+                        offset: 1,
+                        color: '#F38181',
+                      },
+                    ],
+                  },
+                }
+              }
+            },
+            {
+              name: 'II 级',
+              type: 'bar',
+              barWidth:16,
+              stack: '数量',
+              data:  obj.dataListB,
+              itemStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 0,
+                    y: 1,
+                    x2: 0,
+                    y2: 0,
+                    type: 'linear',
+                    global: false,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: '#D8D8D8',
+                      },
+                      {
+                        offset: 1,
+                        color: '#D8A746',
+                      },
+                    ],
+                  },
+                }
+              }
+            },
+            {
+              name: 'III 级',
+              type: 'bar',
+              barWidth: 16,
+              stack: '数量',
+              data:  obj.dataListC,
+              itemStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 0,
+                    y: 1,
+                    x2: 0,
+                    y2: 0,
+                    type: 'linear',
+                    global: false,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: '#D8D8D8',
+                      },
+                      {
+                        offset: 1,
+                        color: '#3876E1',
+                      },
+                    ],
+                  },
+                }
+              }
+            },
+            {
+              name: 'IV 级',
+              type: 'bar',
+              barWidth: 16,
+              stack: '数量',
+              data:  obj.dataListD,
+              itemStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 0,
+                    y: 1,
+                    x2: 0,
+                    y2: 0,
+                    type: 'linear',
+                    global: false,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: '#D8D8D8',
+                      },
+                      {
+                        offset: 1,
+                        color: '#56A757',
+                      },
+                    ],
+                  },
+                }
+              }
+            },
+            {
+              name: '',
+              type: 'bar',
+              barWidth: 16,
+              stack: '数量',
+              data:  obj.dataListE,
+              label: {
+                show: true,
+                position: 'top',
+                textStyle: {
+                  color: '#fff', //更改坐标轴文字颜色
+                  fontSize: '14',
+                },
+                formatter: function (data) {
+                  return (data.name )
+                },
+              },
+              itemStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 0,
+                    y: 1,
+                    x2: 0,
+                    y2: 0,
+                    type: 'linear',
+                    global: false,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: 'rgba(216,216,216,0.1)',
+                      },
+                      {
+                        offset: 1,
+                        color: 'rgba(216,216,216,0.1)',
+                      },
+                    ],
+                  },
+                }
+              }
+            },
+
+          ]
+        };
+        this.echartsBox = this.$echarts.init(document.getElementById('secondaryCollegeUnitLaboratoryStatisticsECharts'));
+        this.echartsBox.clear();
+        this.echartsBox.setOption(option);
+      },
+      //时间定时器
+      timeFunction(){
+        let self = this;
+        this.echartsTimer = window.setInterval(showTime, 180000);
+        function showTime() {
+          self.getList();
+        }
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .secondaryCollegeUnitLaboratoryStatistics{
+    width: 652px;
+    height: 423px;
+    overflow: hidden;
+    .secondaryCollegeUnitLaboratoryStatistics-page{
+      background: linear-gradient( 180deg, rgba(4,117,129,0.2) 0%, rgba(0,15,22,0) 100%);
+      .secondaryCollegeUnitLaboratoryStatisticsPage{
+        height:359px;
+        width:650px;
+      }
+    }
+  }
+</style>

+ 379 - 0
src/views/newSafetyOverview/pageComponent/statisticalAnalysisOfHazardSources.vue

@@ -0,0 +1,379 @@
+<!-- 实验室危险源种类数量 -->
+<template>
+  <div class="statisticalAnalysisOfHazardSources">
+    <title-page-img-components :propsData="propsData"></title-page-img-components>
+    <div class="statisticalAnalysisOfHazardSourcesPage">
+      <div class="title-num-max-box">
+        <div class="num-box">
+          <p>全部危险源</p>
+          <dv-digital-flop :config="hazardTotal" class="dvDigitalFlop"/>
+        </div>
+        <div class="num-box" style="margin-left:20px;">
+          <p>今日新增</p>
+          <dv-digital-flop :config="todayAdded" class="dvDigitalFlop"/>
+        </div>
+      </div>
+      <div id="statisticalAnalysisOfHazardSourcesECharts"></div>
+    </div>
+    <!--<add-page :propsData="propsData" v-if="pageType === 2"></add-page>-->
+  </div>
+</template>
+<script>
+  const configData = {
+    content: '{nt}',
+    textAlign: 'center',
+    style: {
+      fill: '#fff',
+      fontSize: 30,
+      fontWeight: 150,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff', '#FFB31A'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 45]
+    }
+  }
+  import { chemicalStockHazardClassStatistics } from "@/api/index";
+  import titlePageImgComponents from '@/components/titlePageImgComponents.vue'
+  export default {
+    name: 'index',
+    components: {
+      titlePageImgComponents
+    },
+    data () {
+      return {
+        propsData:{
+          title:'实验室危险源种类数量',
+        },
+        hazardTotal: {
+          number: [0],
+          content: configData.content,
+          textAlign: configData.textAlign,
+          style: configData.style
+        },
+        todayAdded: {
+          number: [0],
+          content: configData.content,
+          textAlign: configData.textAlign,
+          style: configData.style
+        },
+        //echarts数据
+        echartsBox:null,
+        // 定时器
+        echartsTimer:null,
+      }
+    },
+    created () {
+
+    },
+    mounted () {
+      this.getList();
+      this.timeFunction();
+    },
+    methods: {
+      getList(){
+        chemicalStockHazardClassStatistics().then(response => {
+          this.$set(this, 'hazardTotal', {
+            number: [response.data.hazardTotal],
+            content: configData.content,
+            textAlign: configData.textAlign,
+            style: configData.style
+          })
+          this.$set(this, 'todayAdded', {
+            number: [response.data.todayAdded],
+            content: configData.content,
+            textAlign: configData.textAlign,
+            style: configData.style
+          })
+          let payload = {
+            id: 'left-center-1',
+            toolTip: false,
+            data: {
+              total: '',
+              data: [],
+              x: [],
+            },
+          };
+          let num = 0;
+          response.data.chemicalStockStatisticsVo.forEach((item)=>{
+            payload.data.x.push(item.chemicalCategory);
+            payload.data.data.push(item.chemicalNumber);
+            num = num + item.chemicalNumber
+          })
+          payload.data.total = num;
+          this.eChartsMethod(payload);
+        })
+      },
+      eChartsMethod(payload){
+        let data = [];
+        const color = [
+          "#43D0FF",
+          "#E7D961",
+          "#49A8FF",
+          "#FF5B5B",
+          "#FFAD69",
+          "#37B028",
+          "#6950a1",
+          "#00a6ac",
+          "#426ab3",
+          "#f58220",
+          "#005831",
+          "#ea66a6",
+          "#84bf96",
+        ];
+        payload.data.x.forEach((item, index) => {
+          data.push({ value: payload.data.data[index], name: item, label: { color: color[index] } });
+        });
+
+        const tooltip = payload.toolTip !== undefined ? payload.toolTip : true;
+        let countdata = payload.data.data.reduce((a, b) => Number(a) + Number(b));
+        let option = {
+          grid: {
+            left: 0,
+            right: 0,
+            bottom: 0,
+            top: 0,
+            containLabel: true,
+          },
+          tooltip: {
+            show: tooltip,
+            backgroundColor: 'rgba(9, 30, 60, 0.6)',
+            extraCssText: 'box-shadow: 0 0 8px rgba(0, 128, 255, 0.27) inset;',
+            borderWidth: 0,
+            confine: false,
+            appendToBody: true,
+            textStyle: {
+              color: '#fff',
+              fontSize: 30,
+            },
+            // 轴触发提示才有效
+            axisPointer: {
+              type: 'shadow',
+            },
+            shadowStyle: {
+              color: 'rgba(157, 168, 245, 0.1)',
+            },
+            formatter: function (parms) {
+              var str =
+                // parms.seriesName + "</br>" +
+                parms.marker + parms.name + " </br>" +
+                "数量:" + parms.data.value + "</br>";
+              // "占比:" + parms.percent + "%";
+              return str;
+            }
+          },
+          legend: {
+            show: false,
+          },
+          series: [
+            {
+              name: payload.title,
+              type: 'pie',
+              roseType: "area", // 展示南丁格尔图
+              radius: ['24%', '75%'],
+              minAngle: 8,
+              itemStyle: {
+                color(params) {
+                  return color[params.dataIndex];
+                },
+              },
+              labelLine: {
+                // length2: 55,
+                length: 10,
+                length2: 160,
+                lineStyle: {
+                  // type: "dashed",
+                  width: 2,
+                },
+              },
+              label: {
+                position: 'outer',
+                alignTo: 'none',
+                bleedMargin: 15,
+                formatter: ' {a|{c}}\n{b|{b}}',
+                padding: -85,
+                rich: {
+                  a: {
+                    padding: [0, 50, 5, 50],
+                    fontSize: 14,
+                    lineHeight: 14,
+                    color: '#fff',
+                    align:'center'
+                  },
+                  b: {
+                    padding: [20, 0, 5, 0],
+                    fontSize: 14,
+                    lineHeight: 14,
+                    color: '#fff',
+                    align:'center'
+                  },
+                },
+              },
+              data,
+            },
+            {
+              //内环
+              type: "pie",
+              radius: ["16%", "19%"],
+              center: ["50%", "50%"],
+              emphasis: {
+                scale: false,
+              },
+              labelLine: {
+                show: false,
+                length: 30,
+                length2: 55,
+              },
+              data: [
+                {
+                  name: "",
+                  value: 0,
+                  itemStyle: {
+                    color: "#00B7FF",
+                  },
+                  tooltip: {
+                    show: false,
+                  },
+                },
+              ],
+            },
+            {
+              type: "pie",
+              radius: ["24%", "90%"],
+              center: ["50%", "50%"],
+              emphasis: {
+                scale: false,
+              },
+              labelLine: {
+                show: false,
+                length: 30,
+                length2: 55,
+              },
+              data: [
+                {
+                  name: "",
+                  value: 0,
+                  itemStyle: {
+                    color: "rgba(0,183,255,0.1)",
+                  },
+                  tooltip: {
+                    show: false,
+                  },
+                },
+              ],
+            },
+            {
+              type: "pie",
+              radius: ["90%", "91%"],
+              center: ["50%", "50%"],
+              emphasis: {
+                scale: false,
+              },
+              labelLine: {
+                show: false,
+                length: 30,
+                length2: 55,
+              },
+              data: [
+                {
+                  name: "",
+                  value: 0,
+                  itemStyle: {
+                    color: "rgba(0,183,255,0.8)",
+                  },
+                  tooltip: {
+                    show: false,
+                  },
+                },
+              ],
+            },
+            {
+              type: "pie",
+              radius: ["97%", "99%"],
+              center: ["50%", "50%"],
+              emphasis: {
+                scale: false,
+              },
+              labelLine: {
+                show: false,
+                length: 30,
+                length2: 55,
+              },
+              data: [
+                {
+                  name: "",
+                  value: 0,
+                  itemStyle: {
+                    color: "rgba(0,183,255,0.8)",
+                  },
+                  tooltip: {
+                    show: false,
+                  },
+                },
+              ],
+            },
+          ],
+        };
+        this.echartsBox = this.$echarts.init(document.getElementById('statisticalAnalysisOfHazardSourcesECharts'));
+        this.echartsBox.clear();
+        this.echartsBox.setOption(option);
+      },
+      //时间定时器
+      timeFunction(){
+        let self = this;
+        this.echartsTimer = window.setInterval(showTime, 180000);
+        function showTime() {
+          self.getList();
+        }
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .statisticalAnalysisOfHazardSources{
+    width: 652px;
+    height: 475px;
+    overflow: hidden;
+    .statisticalAnalysisOfHazardSourcesPage{
+      width: 652px;
+      height: 413px;
+      overflow: hidden;
+      background: linear-gradient( 180deg, rgba(4,117,129,0.2) 0%, rgba(0,15,22,0) 100%);
+      .title-num-max-box{
+        margin-left:110px;
+        margin-top:28px;
+        display: flex;
+        .num-box{
+          display: flex;
+          p{
+            font-family: SOURCEHANSANSCN;
+            color:#fff;
+            padding:0 10px;
+            font-size:14px;
+            height:30px;
+            line-height:30px;
+            text-align: center;
+          }
+          .dvDigitalFlop{
+            width:150px;
+            height:30px;
+            line-height:30px;
+          }
+        }
+      }
+      #statisticalAnalysisOfHazardSourcesECharts{
+        margin-top:50px;
+        width:652px;
+        height:250px;
+      }
+    }
+  }
+</style>

+ 609 - 0
src/views/newSafetyOverview/pageComponent/statisticalAnalysisOfHazardousChemicals.vue

@@ -0,0 +1,609 @@
+<!-- 危化品总量统计分析 -->
+<template>
+  <div class="statisticalAnalysisOfHazardousChemicals">
+    <title-page-img-components :propsData="propsData"></title-page-img-components>
+    <div class="statisticalAnalysisOfHazardousChemicalsPage">
+      <div class="color-max-box">
+        <div>
+          <p class="color1"></p>
+          <p>液体</p>
+        </div>
+        <div>
+          <p class="color2"></p>
+          <p>固体</p>
+        </div>
+      </div>
+      <div class="ECharts-flex-box">
+        <div class="ECharts-left-box">
+          <!--管控-->
+          <div id="statisticalAnalysisOfHazardousChemicalsTopECharts"></div>
+          <p class="back-text-box back-text-box1">管控类危化品</p>
+          <div class="position-num-box">
+            <p>总数</p>
+            <dv-digital-flop :config="control" class="dvDigitalFlop"/>
+          </div>
+        </div>
+        <div class="ECharts-right-box">
+          <!--非管控-->
+          <div id="statisticalAnalysisOfHazardousChemicalsBottomECharts"></div>
+          <p class="back-text-box back-text-box2">非管控类危化品</p>
+          <div class="position-num-box">
+            <p>总数</p>
+            <dv-digital-flop :config="uncontrolled" class="dvDigitalFlop"/>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  const configData = {
+    content: '{nt}',
+    textAlign: 'center',
+    style: {
+      fill: '#fff',
+      fontSize: 16,
+      fontWeight: 200,
+      fontFamily: 'YouSheBiaoTiHei',
+      gradientColor: ['#fff', '#5BC6FF'],
+      gradientType: 'linear',//'linear' | 'radial'
+      gradientWith: 'fill',//'stroke' | 'fill'
+      gradientParams: [0, 0, 0, 20]
+    }
+  }
+  import { chemicalStockHazMartClassStatistics } from '@/api/index'
+  import titlePageImgComponents from '@/components/titlePageImgComponents.vue'
+
+  export default {
+    name: 'index',
+    components: {
+      titlePageImgComponents
+    },
+    data() {
+      return {
+        control: {
+          number: [0],
+          content: configData.content,
+          textAlign: configData.textAlign,
+          style: configData.style
+        },
+        uncontrolled: {
+          number: [0],
+          content: configData.content,
+          textAlign: configData.textAlign,
+          style: configData.style
+        },
+        //组件传参
+        propsData: {
+          title: '实验室危化品存量'
+        },
+        //echarts数据
+        echartsBox1: null,
+        echartsBox2: null,
+        // 定时器
+        echartsTimer: null
+      }
+    },
+    created() {
+
+    },
+    mounted() {
+      this.getList()
+      this.timeFunction()
+    },
+    methods: {
+      getList() {
+        chemicalStockHazMartClassStatistics().then(response => {
+          this.$set(this, 'control', {
+            number: [response.data[1].total],
+            content: configData.content,
+            textAlign: configData.textAlign,
+            style: configData.style
+          })
+          this.$set(this, 'uncontrolled', {
+            number: [response.data[0].total],
+            content: configData.content,
+            textAlign: configData.textAlign,
+            style: configData.style
+          })
+          let payload1 = {
+            id: 'left-center-1',
+            toolTip: false,
+            data: {
+              total: '',
+              data: ['0', '0'],
+              x: ['固体总量(kg)', '液体总量(L)']
+            }
+          }
+          let payload2 = {
+            id: 'left-center-2',
+            toolTip: false,
+            data: {
+              total: '',
+              data: ['0', '0'],
+              x: ['固体总量(kg)', '液体总量(L)']
+            }
+          }
+          let num1 = 0;
+          let num2 = 0;
+          response.data[1].chemicalTotalList.forEach((item)=>{
+            num1 = num2 + item.chemicalsTotal
+            if(item.chemicalsUnit == 'kg'){
+              payload1.data.data[0] = item.chemicalsTotal
+            }
+            if(item.chemicalsUnit == 'L'){
+              payload1.data.data[1] = item.chemicalsTotal
+            }
+          })
+          response.data[0].chemicalTotalList.forEach((item)=>{
+            num2 = num2 + item.chemicalsTotal
+            if(item.chemicalsUnit == 'kg'){
+              payload2.data.data[0] = item.chemicalsTotal
+            }
+            if(item.chemicalsUnit == 'L'){
+              payload2.data.data[1] = item.chemicalsTotal
+            }
+          })
+          payload1.data.total = num1;
+          payload2.data.total = num2;
+          this.eChartsMethod1(payload1)
+          this.eChartsMethod2(payload2)
+        })
+      },
+      eChartsMethod1(payload) {
+        let data = []
+
+        const color = [
+          '#00F7FF',
+          '#008CFF'
+        ]
+        payload.data.x.forEach((item, index) => {
+          data.push({ value: payload.data.data[index], name: item, label: { color: color[index] } })
+        })
+
+        const tooltip = payload.toolTip !== undefined ? payload.toolTip : true
+        let option = {
+          // backgroundColor: 'transparent',
+          grid: {
+            left: 0,
+            right: 0,
+            bottom: 0,
+            top: 0,
+            containLabel: true
+          },
+          tooltip: {
+            show: tooltip,
+            backgroundColor: 'rgba(9, 30, 60, 0.6)',
+            extraCssText: 'box-shadow: 0 0 8px rgba(0, 128, 255, 0.27) inset;',
+            borderWidth: 0,
+            confine: false,
+            appendToBody: true,
+            textStyle: {
+              color: '#fff',
+              fontSize: 30
+            },
+            // 轴触发提示才有效
+            axisPointer: {
+              type: 'shadow'
+            },
+            shadowStyle: {
+              color: 'rgba(157, 168, 245, 0.1)'
+            },
+            formatter: function(parms) {
+              var str =
+                // parms.seriesName + "</br>" +
+                parms.marker + parms.name + ' </br>' +
+                '数量:' + parms.data.value + '</br>'
+              // "占比:" + parms.percent + "%";
+              return str
+            }
+          },
+          legend: {
+            show: false
+          },
+          series: [
+            {
+              name: payload.title,
+              type: 'pie',
+              radius: ['33%', '40%'],
+              startAngle:45,
+              minAngle: 8,
+              padAngle: 2,
+              itemStyle: {
+                borderColor: '#01060C',
+                borderWidth: 2,
+                color(params) {
+                  return color[params.dataIndex]
+                }
+              },
+              labelLine: {
+                // length2: 55,
+                length: 20,
+                length2: 80,
+                lineStyle: {
+                  // type: "dashed",
+                  width: 2
+                }
+              },
+              label: {
+                position: 'outer',
+                alignTo: 'none',
+                bleedMargin: 15,
+                formatter: ' {a|{c}}\n{b|{b}}',
+                padding: -85,
+                rich: {
+                  a: {
+                    padding: [-5, 0, 5, 0],
+                    fontSize: 16,
+                    lineHeight: 16,
+                    color: '#fff',
+                    align:'center'
+                  },
+                  b: {
+                    padding: [20, 0, 5, 0],
+                    fontSize: 14,
+                    lineHeight: 14,
+                    color: '#fff',
+                    align:'center'
+                  }
+                }
+              },
+              data
+            },
+            //刻度
+            {
+              type: 'gauge',
+              center: ['50%', '50%'],
+              radius: '41%', // 1行3个
+              splitNumber: 36,
+              min: 0,
+              max: 100,
+              startAngle: 0,
+              endAngle: 360,
+              //分隔线样式
+              axisTick: {
+                show: false
+              },
+              //刻度样式
+              axisLine: {
+                show: false
+              },
+              //整数分隔线
+              splitLine: {
+                show: true,
+                length: 6,
+                lineStyle: {
+                  color: 'rgba(0, 144, 255, 1)',
+                  width: 2
+                }
+              },
+              //刻度数字
+              axisLabel: {
+                show: false
+              }
+            },
+            {
+              type: 'pie',
+              radius: ['0%', '24%'],
+              center: ['50%', '50%'],
+              emphasis: {
+                scale: false
+              },
+              labelLine: {
+                show: false,
+                length: 30,
+                length2: 55
+              },
+              data: [
+                {
+                  name: '',
+                  value: 0,
+                  itemStyle: {
+                    color: 'rgba(0,183,255,0.1)'
+                  },
+                  tooltip: {
+                    show: false
+                  }
+                }
+              ]
+            }
+          ]
+        }
+        this.echartsBox1 = this.$echarts.init(document.getElementById('statisticalAnalysisOfHazardousChemicalsTopECharts'))
+        this.echartsBox1.clear()
+        this.echartsBox1.setOption(option)
+      },
+      eChartsMethod2(payload) {
+        let data = []
+
+        const color = [
+          '#00F7FF',
+          '#008CFF'
+        ]
+        payload.data.x.forEach((item, index) => {
+          data.push({
+            value: payload.data.data[index],
+            name: item, label: {
+              color: color[index]
+            }
+          })
+        })
+
+        const tooltip = payload.toolTip !== undefined ? payload.toolTip : true
+        let option = {
+          // backgroundColor: 'transparent',
+          grid: {
+            left: 0,
+            right: 0,
+            bottom: 0,
+            top: 0,
+            containLabel: true
+          },
+          tooltip: {
+            show: tooltip,
+            backgroundColor: 'rgba(9, 30, 60, 0.6)',
+            extraCssText: 'box-shadow: 0 0 8px rgba(0, 128, 255, 0.27) inset;',
+            borderWidth: 0,
+            confine: false,
+            appendToBody: true,
+            textStyle: {
+              color: '#fff',
+              fontSize: 30
+            },
+            // 轴触发提示才有效
+            axisPointer: {
+              type: 'shadow'
+            },
+            shadowStyle: {
+              color: 'rgba(157, 168, 245, 0.1)'
+            },
+            formatter: function(parms) {
+              var str =
+                // parms.seriesName + "</br>" +
+                parms.marker + parms.name + ' </br>' +
+                '数量:' + parms.data.value + '</br>'
+              // "占比:" + parms.percent + "%";
+              return str
+            }
+          },
+          legend: {
+            show: false
+          },
+          series: [
+            {
+              name: payload.title,
+              type: 'pie',
+              radius: ['33%', '40%'],
+              startAngle:45,
+              minAngle: 8,
+              padAngle: 2,
+              itemStyle: {
+                borderColor: '#01060C',
+                borderWidth: 2,
+                color(params) {
+                  return color[params.dataIndex]
+                }
+              },
+              labelLine: {
+                // length2: 55,
+                length: 20,
+                length2: 80,
+                lineStyle: {
+                  // type: "dashed",
+                  width: 2
+                }
+              },
+              label: {
+                position: 'outer',
+                alignTo: 'none',
+                bleedMargin: 15,
+                formatter: ' {a|{c}}\n{b|{b}}',
+                padding: -85,
+                rich: {
+                  a: {
+                    padding: [-5, 0, 5, 0],
+                    fontSize: 16,
+                    lineHeight: 16,
+                    color: '#fff',
+                    align:'center'
+                  },
+                  b: {
+                    padding: [20, 0, 5, 0],
+                    fontSize: 14,
+                    lineHeight: 14,
+                    color: '#fff',
+                    align:'center'
+                  }
+                }
+              },
+              data
+            },
+            //刻度
+            {
+              type: 'gauge',
+              center: ['50%', '50%'],
+              radius: '41%', // 1行3个
+              splitNumber: 36,
+              min: 0,
+              max: 100,
+              startAngle: 0,
+              endAngle: 360,
+              //分隔线样式
+              axisTick: {
+                show: false
+              },
+              //刻度样式
+              axisLine: {
+                show: false
+              },
+              //整数分隔线
+              splitLine: {
+                show: true,
+                length: 6,
+                lineStyle: {
+                  color: 'rgba(0, 144, 255, 1)',
+                  width: 2
+                }
+              },
+              //刻度数字
+              axisLabel: {
+                show: false
+              }
+            },
+            {
+              type: 'pie',
+              radius: ['0%', '24%'],
+              center: ['50%', '50%'],
+              emphasis: {
+                scale: false
+              },
+              labelLine: {
+                show: false,
+                length: 30,
+                length2: 55
+              },
+              data: [
+                {
+                  name: '',
+                  value: 0,
+                  itemStyle: {
+                    color: 'rgba(0,183,255,0.1)'
+                  },
+                  tooltip: {
+                    show: false
+                  }
+                }
+              ]
+            }
+          ]
+        }
+        this.echartsBox2 = this.$echarts.init(document.getElementById('statisticalAnalysisOfHazardousChemicalsBottomECharts'))
+        this.echartsBox2.clear()
+        this.echartsBox2.setOption(option)
+      },
+      //时间定时器
+      timeFunction() {
+        let self = this
+        this.echartsTimer = window.setInterval(showTime, 180000)
+
+        function showTime() {
+          self.getList()
+        }
+      }
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer)
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer)
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .statisticalAnalysisOfHazardousChemicals {
+    width: 652px;
+    height: 472px;
+    overflow: hidden;
+    .statisticalAnalysisOfHazardousChemicalsPage {
+      height:409px;
+      position: relative;
+      overflow: hidden;
+      background: linear-gradient( 180deg, rgba(4,117,129,0.2) 0%, rgba(0,15,22,0) 100%);
+      .color-max-box {
+        position: absolute;
+        z-index: 1;
+        top:30px;
+        left:200px;
+        display: flex;
+        overflow: hidden;
+        /*margin: 63px 0 62px 310px;*/
+        div {
+          display: flex;
+          margin-left: 50px;
+          p:nth-child(1) {
+            width: 16px;
+            height: 16px;
+            margin: 0 10px 0 0;
+            border-radius:4px;
+          }
+          p:nth-child(2) {
+            color: #fff;
+            font-size: 14px;
+            line-height: 16px;
+            height: 16px;
+            font-family: SOURCEHANSANSCN;
+          }
+          .color1 {
+            background-color: #008CFF;
+          }
+          .color2 {
+            background-color: #00F7FF;
+          }
+        }
+      }
+      .ECharts-flex-box{
+        height:409px;
+        display: flex;
+        .ECharts-left-box{
+          width:325px;
+          height:360px;
+          position: relative;
+          #statisticalAnalysisOfHazardousChemicalsTopECharts {
+            width:325px;
+            height:360px;
+          }
+        }
+        .ECharts-right-box{
+          width:325px;
+          height:360px;
+          position: relative;
+          #statisticalAnalysisOfHazardousChemicalsBottomECharts {
+            width:325px;
+            height:360px;
+          }
+        }
+      }
+      .back-text-box {
+        position: absolute;
+        width: 154px;
+        height: 117px;
+        line-height: 117px;
+        font-size: 14px;
+        color: #fff;
+        font-family: SOURCEHANSANSCN;
+        background: url("../../../assets/ZDimages/img_whptjfx_bg@1x.png") no-repeat;
+        background-size: 100% 100%;
+        text-align: center;
+        /*margin: 0 391px;*/
+      }
+      .back-text-box1{
+        top:248px;
+        left:84px;
+      }
+      .back-text-box2{
+        top:248px;
+        left:84px;
+      }
+      .position-num-box {
+        position: absolute;
+        top: 168px;
+        left: 62px;
+        p {
+          width: 200px;
+          line-height: 14px;
+          font-size: 14px;
+          text-align: center;
+          color: #fff;
+          font-family: SOURCEHANSANSCN;
+        }
+        .dvDigitalFlop {
+          height: 30px;
+          line-height: 30px;
+          width: 200px;
+        }
+      }
+    }
+  }
+</style>

+ 323 - 0
src/views/newSafetyOverview/pageComponent/subComponents.vue

@@ -0,0 +1,323 @@
+<!-- 实验室使用走势图 -->
+<template>
+    <div class="subComponents">
+      <title-page-img-components :propsData="propsData"></title-page-img-components>
+      <div class="eCharts-max-big-box">
+        <div id="subComponentsECharts"></div>
+      </div>
+    </div>
+</template>
+<script>
+  import {
+    reportReportBigDataLabStateStatistics,
+  } from "@/api/index";
+  import titlePageImgComponents from '@/components/titlePageImgComponents.vue'
+  export default {
+    name: 'subComponents',
+    components: {
+      titlePageImgComponents,
+    },
+    data() {
+      return {
+        propsData:{
+          title:'实验室使用走势图',
+        },
+        //eCharts定时器
+        eChartsTimer:null,
+        deptId:0,
+      }
+    },
+    created() {
+
+    },
+    mounted() {
+      this.getData();
+      this.timedRefresh();
+    },
+    methods: {
+      timedRefresh(){
+        let self = this;
+        this.echartsTimer = window.setInterval(showTime, 180000);
+        function showTime() {
+          self.getList();
+        }
+      },
+      getData(){
+        reportReportBigDataLabStateStatistics({deptId:this.deptId}).then( response => {
+          let hour = [];
+          let useTotal = [];
+          let availableTotal = [];
+          let exceptionalTotal = [];
+          let num = 0;
+          if(response.data.labStateSubs[0]){
+            for(let i=0;i<response.data.labStateSubs.length;i++){
+              hour.push(response.data.labStateSubs[i].hour)
+              useTotal.push(response.data.labStateSubs[i].useTotal)
+              availableTotal.push(response.data.labStateSubs[i].availableTotal)
+              exceptionalTotal.push(response.data.labStateSubs[i].exceptionalTotal)
+              if(response.data.labStateSubs[i].useTotal > num){
+                num = response.data.labStateSubs[i].useTotal;
+              }
+              // if(response.data.labStateSubs[i].availableTotal > num){
+              //   num = response.data.labStateSubs[i].availableTotal;
+              // }
+              if(response.data.labStateSubs[i].exceptionalTotal > num){
+                num = response.data.labStateSubs[i].exceptionalTotal;
+              }
+            }
+          }else{
+            hour = ["0.00", "3.00", "6.00", "9.00", "12.00", "15.00", "18.00", "21.00", "24.00",];
+            useTotal = [0, 0, 0, 0, 0, 0, 0, 0, 0];
+            availableTotal = [0, 0, 0, 0, 0, 0, 0, 0, 0];
+            exceptionalTotal = [0, 0, 0, 0, 0, 0, 0, 0, 0];
+          }
+          this.eChartsMethod(hour,useTotal,availableTotal,exceptionalTotal,num);
+        });
+      },
+      eChartsMethod(hour,useTotal,availableTotal,exceptionalTotal,num){
+        let option = {
+          title: {
+            text: "",
+            textStyle: {
+              fontWeight: "normal",
+              fontSize: 16,
+              color: "#F1F1F3",
+            },
+            left: "6%",
+          },
+          tooltip: {
+            trigger: "axis",
+            textStyle: {
+              fontSize: 18
+            },
+            axisPointer: {
+              lineStyle: {
+                color: "#57617B",
+              },
+            },
+          },
+          legend: {
+            show:false,
+            icon: "rect",
+            itemWidth: 14,
+            itemHeight: 5,
+            itemGap: 13,
+            data: ["使用数量", "空闲数量", "异常数量"],
+            right: "4%",
+            textStyle: {
+              fontSize: 18,
+              color: "#F1F1F3",
+            },
+          },
+          grid: {
+            left: "3%",
+            right: "4%",
+            bottom: "3%",
+            containLabel: true,
+          },
+          xAxis: [
+            {
+              type: "category",
+              boundaryGap: false,
+              axisLabel: {
+                textStyle: {
+                  color: "#ffffff",
+                  fontSize: 18,
+                },
+              },
+              axisLine: {
+                lineStyle: {
+                  color: "#042226",
+                },
+              },
+              data: hour,
+            },
+          ],
+          yAxis: [
+            {
+              type: "value",
+              //以下设置y轴刻度为整数代码  valueDataAll是数组源,从里面找最大值用的
+              axisTick: {
+                show: false,
+              },
+              axisLine: {
+                lineStyle: {
+                  fontSize: 18,
+                  color: "#042226",
+                },
+              },
+              axisLabel: {
+                margin: 10,
+                textStyle: {
+                  color: "#ffffff",
+                  fontSize: 18,
+                },
+              },
+              splitLine: {
+                lineStyle: {
+                  color: "#57617B",
+                },
+              },
+            },
+          ],
+          series: [
+            {
+              name: "使用数量",
+              type: "line",
+              smooth: true,
+              symbol: "circle",
+              symbolSize: 8,
+              lineStyle: {
+                normal: {
+                  width: 2,
+                },
+              },
+              areaStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 1,
+                    y: 0,
+                    x2: 0,
+                    y2: 0,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: "rgba(1,131,250, 1)",
+                      },
+                      {
+                        offset: 1,
+                        color: "rgba(1,131,250, 0)",
+                      },
+                    ],
+                  },
+                  shadowColor: "rgba(0, 0, 0, 0.1)",
+                  shadowBlur: 10,
+                },
+              },
+              itemStyle: {
+                normal: {
+                  color: "rgb(1,131,250)",
+                },
+              },
+              data: useTotal,
+            },
+            // {
+            //   name: "空闲数量",
+            //   type: "line",
+            //   smooth: true,
+            //   symbol: "circle",
+            //   symbolSize: 8,
+            //   lineStyle: {
+            //     normal: {
+            //       width: 2,
+            //     },
+            //   },
+            //   areaStyle: {
+            //     normal: {
+            //       color: {//渐变色
+            //         x: 1,
+            //         y: 0,
+            //         x2: 0,
+            //         y2: 0,
+            //         colorStops: [
+            //           {
+            //             offset: 0,
+            //             color: "rgba(21,130,124, 1)",
+            //           },
+            //           {
+            //             offset: 1,
+            //             color: "rgba(21,130,124, 0)",
+            //           },
+            //         ],
+            //       },
+            //       shadowColor: "rgba(0, 0, 0, 0.1)",
+            //       shadowBlur: 10,
+            //     },
+            //   },
+            //   itemStyle: {
+            //     normal: {
+            //       color: "rgb(21,130,124)",
+            //     },
+            //   },
+            //   data: availableTotal,
+            // },
+            {
+              name: "异常数量",
+              type: "line",
+              smooth: true,
+              symbol: "circle",
+              symbolSize: 8,
+              lineStyle: {
+                normal: {
+                  width: 2,
+                },
+              },
+              areaStyle: {
+                normal: {
+                  color: {//渐变色
+                    x: 1,
+                    y: 0,
+                    x2: 0,
+                    y2: 0,
+                    colorStops: [
+                      {
+                        offset: 0,
+                        color: "rgba(255,132,0, 1)",
+                      },
+                      {
+                        offset: 1,
+                        color: "rgba(255,132,0, 0)",
+                      },
+                    ],
+                  },
+                  shadowColor: "rgba(0, 0, 0, 0.1)",
+                  shadowBlur: 10,
+                },
+              },
+              itemStyle: {
+                normal: {
+                  color: "rgb(255,132,0)",
+                },
+              },
+              data: exceptionalTotal,
+            },
+          ],
+        };
+        if(num < 5){
+          option.yAxis[0].max = 5;
+        }else{
+          option.yAxis[0].min= 0;
+          option.yAxis[0].max= num; // 计算最大值
+          option.yAxis[0].interval= Math.ceil(num / 5); // 平均分为5份
+        }
+        let echartsBox = this.$echarts.init(document.getElementById('subComponentsECharts'));
+        echartsBox.clear();
+        echartsBox.setOption(option);
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    },
+    destroyed() {
+      //清除定时器
+      window.clearInterval(this.echartsTimer);
+    }
+  }
+</script>
+<style scoped lang="scss">
+    .subComponents {
+      width: 652px;
+      height: 401px;
+      overflow: hidden;
+      .eCharts-max-big-box{
+        width: 652px;
+        height: 331px;
+        background: linear-gradient( 180deg, rgba(4,117,129,0.2) 0%, rgba(0,15,22,0) 100%);
+        #subComponentsECharts{
+          width: 642px;
+          height: 311px;
+        }
+      }
+    }
+</style>