dedsudiyu 6 hónapja
szülő
commit
5582b1e39a

+ 4 - 2
src/api/index.js

@@ -8,9 +8,11 @@ export function iotCameraGetPreviewURLs(query) {
     params: query
   })
 }
-export function chemicalStockHazardClassStatistics (query) {
+
+//获取当前正在发生的预案
+export function laboratoryBigViewSelectTriggerInfo(query) {
   return request({
-    url: '/chemical/stock/hazardClassStatistics',
+    url: '/laboratory/bigView/selectTriggerInfo',
     method: 'get',
     params: query
   })

+ 46 - 0
src/api/yiLi.js

@@ -0,0 +1,46 @@
+import request from '@/utils/requestYiLi'
+import md5 from 'js-md5';
+
+// 登录方法YiLi
+export function loginYiLi() {
+  return request({
+    url: '/oauth/token?grant_type=client_credentials',
+    method: 'post',
+    data: {},
+  })
+}
+
+// 设施状态概览
+export function dashboardsFacilitiesStatusOverview(query) {
+  return request({
+    url: '/dashboards/facilities/status-overview',
+    method: 'get',
+    params: query
+  })
+}
+
+// 设施使用率及二级单位统计
+export function dashboardsFacilitiesUsageStats(query) {
+  return request({
+    url: '/dashboards/facilities/usage-stats',
+    method: 'get',
+    params: query
+  })
+}
+
+// 设施列表信息
+export function dashboardsResearchUsage(query) {
+  return request({
+    url: "/dashboards/research/usage?"+query,
+    method: 'get',
+  })
+}
+
+// 设施列表信息
+export function dashboardsMediaAnnouncements(query) {
+  return request({
+    url: "/dashboards/media-announcements",
+    method: 'get',
+    params: query
+  })
+}

+ 32 - 2
src/utils/auth.js

@@ -1,9 +1,11 @@
 import { login } from "@/api/login";
+import { loginYiLi } from "@/api/yiLi";
 import Cookies from 'js-cookie'
 
 const TokenKey = 'System-Platform-55-Token';
-
 const ExpiresInKey = 'System-Platform-55-Expires-In';
+const TokenKeyYiLi = 'System-Platform-55-Token-YiLi';
+const ExpiresInKeyYiLi = 'System-Platform-55-Expires-In-YiLi';
 
 export function getToken() {
   return Cookies.get(TokenKey)
@@ -32,6 +34,34 @@ export function removeExpiresIn() {
 export function autoLogin() {
   login().then(res => {
     setToken(res.data.token)
-    this.$set(this,'showPage',true);
+  });
+}
+
+export function getTokenYiLi() {
+  return Cookies.get(TokenKeyYiLi)
+}
+
+export function setTokenYiLi(token) {
+  return Cookies.set(TokenKeyYiLi, token)
+}
+
+export function removeTokenYiLi() {
+  return Cookies.remove(TokenKeyYiLi)
+}
+
+export function getExpiresInYiLi() {
+  return Cookies.get(ExpiresInKeyYiLi) || -1
+}
+
+export function setExpiresInYiLi(time) {
+  return Cookies.set(ExpiresInKeyYiLi, time)
+}
+
+export function removeExpiresInYiLi() {
+  return Cookies.remove(ExpiresInKeyYiLi)
+}
+export function autoLoginYiLi() {
+  loginYiLi().then(res => {
+    setTokenYiLi(res.access_token);
   });
 }

+ 49 - 0
src/utils/index.js

@@ -116,6 +116,55 @@ export function judgmentNetworkReturnAddress() {
     return (userIp>=begin) && (userIp<=end);
   }
 }
+// 判断当前用户网络 外网/内网 返回接口地址
+export function judgmentNetworkReturnAddressYiLi() {
+  /*判断是否是内网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?process.env.VUE_APP_BASE_LOCAL_API_YILI:process.env.VUE_APP_BASE_API_YILI;
+  /*获取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);
+  }
+}
 // 日期格式化
 export function parseTime(time, pattern) {
   if (arguments.length === 0 || !time) {

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 179 - 895
src/utils/mapList.js


+ 151 - 0
src/utils/requestYiLi.js

@@ -0,0 +1,151 @@
+import axios from 'axios'
+import { MessageBox, Message, Loading } from 'element-ui'
+import router from '@/router'
+import { autoLoginYiLi,getTokenYiLi } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { tansParams,judgmentNetworkReturnAddressYiLi } from "@/utils/index";
+
+// let secret = 'kKxkf%$lzKKxxPxu174';
+let secret = 'broad:kKxkf%$lzKKxxPxu174';
+let encoded = btoa(unescape(encodeURIComponent(secret)));
+
+//判定http或者https
+let urlText = window.location.href.split('://')[0]+'://';
+
+//弹窗状态开关
+let messageData = null;
+
+// 公共接口加载弹层数据
+let loadingInstance = {};
+let options = {
+  spinner:"",
+  background: 'rgba(255, 255, 255, 0)'
+};
+let loadingCount = 0;
+
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+// 创建axios实例
+const service = axios.create({
+  // axios中请求配置有baseURL选项,表示请求URL公共部分
+  baseURL: urlText+judgmentNetworkReturnAddressYiLi(),
+  // 超时
+  timeout: 10000
+})
+// request拦截器
+service.interceptors.request.use(config => {
+  // 弹层相关
+  loadingInstance = Loading.service(options)
+  // 是否需要设置 token
+  const isToken = (config.headers || {}).isToken === false
+  if(config.url == '/oauth/token?grant_type=client_credentials'){
+    config.headers['Authorization'] = 'Basic '+encoded
+  }else{
+    if (getTokenYiLi() && !isToken) {
+      config.headers['Authorization'] = 'Bearer '+getTokenYiLi()
+    }
+  }
+  // get请求映射params参数
+  if (config.method === 'get' && config.params) {
+    let url = config.url + '?' + tansParams(config.params);
+    url = url.slice(0, -1);
+    config.params = {};
+    config.url = url;
+  }
+  // 弹层相关
+  loadingCount ++;
+  return config
+}, error => {
+  // 弹层相关
+  loadingCount --;
+  if(loadingCount===0){
+    loadingInstance.close();
+  }
+  Promise.reject(error)
+})
+
+// 响应拦截器
+service.interceptors.response.use(res => {
+    // 弹层相关
+    loadingCount --;
+    if(loadingCount===0) {
+      loadingInstance.close();
+    }
+    // 未设置状态码则默认成功状态
+    const code = res.data.code || 200;
+    // 获取错误信息
+    const msg = errorCode[code] || res.data.message || errorCode['default']
+    if (code === 500) {
+      if(!messageData){
+        messageData = Message({
+          message: msg,
+          type: 'error',
+          offset:100
+        })
+        setTimeout(function(){
+          messageData = null
+        },1000);
+      }
+      return res.data
+    }else if(code == 5002){
+      autoLoginYiLi();
+    }else if(code != 200) {
+      if(!messageData){
+        messageData = Message({
+          message: msg,
+          type: 'error',
+          offset:100
+        })
+        setTimeout(function(){
+          messageData = null
+        },1000);
+      }
+      return Promise.reject(new Error(msg))
+    }else {
+      return res.data
+    }
+  },
+  error => {
+    // 弹层相关
+    loadingCount --;
+    if(loadingCount===0){
+      loadingInstance.close();
+    }
+    let { message } = error;
+    if (message == "Network Error") {
+      message = "服务连接异常";
+    }
+    else if (message.includes("timeout")) {
+      message = "系统接口请求超时";
+    }
+    else if (message.includes("Request failed with status code")) {
+      console.log('message',message)
+      if(message.substr(message.length - 3) == 401){
+        console.log('message',message)
+        autoLoginYiLi();
+      }else{
+        messageData = Message({
+          message: message,
+          type: 'error',
+          offset:100
+        })
+        setTimeout(function(){
+          messageData = null
+        },1000);
+      }
+      return Promise.reject(error)
+    }
+    if(!messageData){
+      messageData = Message({
+        message: message,
+        type: 'error',
+        duration: 5 * 1000,
+        offset:100
+      })
+      setTimeout(function(){
+        messageData = null
+      },1000);
+    }
+    return Promise.reject(error)
+  }
+)
+export default service

+ 30 - 0
src/views/components/alarmComponent.vue

@@ -0,0 +1,30 @@
+<!--报警信息-->
+<template>
+  <div class="alarmComponent">
+
+  </div>
+</template>
+<script>
+  export default {
+    name: 'alarmComponent',
+    data () {
+      return {
+
+      }
+    },
+    created(){
+
+    },
+    mounted(){
+
+    },
+    methods:{
+
+    },
+  }
+</script>
+<style scoped lang="scss">
+  .alarmComponent{
+
+  }
+</style>

+ 147 - 12
src/views/components/mapComponent.vue

@@ -17,16 +17,16 @@
         <img v-if="item.status == 1" src="@/assets/ZDimages/icon_fj_kx@1x.png">
         <img v-if="item.status == 2" src="@/assets/ZDimages/icon_fj_sy@1x.png">
         <img v-if="item.status == 3" src="@/assets/ZDimages/icon_bjt_wx@1x.png">
-        <p>{{item.roomNum}}</p>
+        <p>{{item.roomNumName}}</p>
       </div>
       <div class="map-build-user-box" v-if="item.status == 1 || item.status == 2">
         <div>
           <img src="@/assets/ZDimages/icon_bjt_xy@1x.png">
-          <p>{{item.buildName}}</p>
+          <p>{{item.userOrgName}}</p>
         </div>
         <div>
           <img src="@/assets/ZDimages/icon_bjt_syr@1x.png">
-          <p>{{item.adminName}}</p>
+          <p>{{item.rentUserName}}</p>
         </div>
       </div>
       <img class="door-img" src="@/assets/ZDimages/icon_door.png">
@@ -35,24 +35,58 @@
   </div>
 </template>
 <script>
+  import {
+    laboratoryBigViewSelectTriggerInfo,
+  } from "@/api/index";
+  import {
+    dashboardsResearchUsage,
+    dashboardsMediaAnnouncements,
+  } from "@/api/yiLi";
   import { getFloorMap } from '@/utils/mapList'
 
   export default {
     name: 'mapComponent',
     data() {
       return {
+        //地图数据
         mapData: {},
-        checkIndex: 0
+        //选中index
+        checkIndex: 0,
+        //通知切换时间
+        // noticeSwitchTime:600000,
+        noticeSwitchTime:6000,
+        //房间展示切换时间
+        // subSwitchTime:30000,
+        subSwitchTime:3000,
+        //通知开启状态
+        noticeType:false,
+        //报警开启状态
+        alarmType:false,
+        //通知定时器
+        noticeTimer:null,
+        //实验室切换定时器
+        subTimer:null,
+        //实验室详情开启状态
+        subInfoType:false,
       }
     },
     created() {
 
     },
     mounted() {
-      this.initialize()
+      /*
+      轮播规则
+      获取通知列表如果有列表按照配置时间 开启关闭内容轮播完毕后获取新数据 实验室详情展开时 关闭详情 显示通知
+      房间列表列表按照配置时间轮播 一轮结束后获取新数据
+      点击房间详情后停止轮播
+      获取报警信息时如果适配到房间 则刷新报警状态轮播自动停止
+      报警结束后刷新报警状态 轮播继续
+      */
+      this.initialize(true)
     },
     methods: {
-      initialize() {
+      //初始化
+      initialize(type) {
         let text = window.location.href
         let urlList = text.split('?')[1].split('&')
         let codeData = {}
@@ -60,12 +94,51 @@
           codeData[item.split('=')[0]] = item.split('=')[1]
         })
         let list = getFloorMap(codeData.floorId)
-        for (let i = 0; i < list.list.length; i++) {
-          list.list[i].adminName = '人员' + i
-          list.list[i].buildName = '学院' + i
-          list.list[i].status = 1
+        this.dashboardsResearchUsage(list,type);
+      },
+      //获取楼层房间数据
+      dashboardsResearchUsage(list,type){
+        let text = ''
+        for(let i=0;i<list.list.length;i++){
+          if(i==0){
+            text = text + 'roomNames=' +list.list[i].roomNumName
+          }else{
+            text = text + '&roomNames=' +list.list[i].roomNumName
+          }
         }
-        this.$set(this, 'mapData', list)
+        dashboardsResearchUsage(text).then(res => {
+          for(let i=0;i<res.data.length;i++){
+            for(let o=0;o<list.list.length;o++){
+              if(list.list[o].roomNumName == res.data[i].roomNumValue){
+                list.list[o] = {...list.list[o],...res.data[i]};
+                list.list[o].status = list.list[o].runningStateName == '维修' ? '3':(list.list[o].stateName == '租用'?'2':'1')
+                list.list[o].rentUserName = !list.list[o].userName?'':(list.list[o].userName.indexOf('-') != -1?list.list[o].userName.split('-')[0]:list.list[o].userName)
+              }
+            }
+          }
+          this.$set(this, 'mapData', list)
+          //推送数据到实验室组件
+          this.getSubData({alarmType:false});
+          if(type){
+            //获取通知数据
+            this.dashboardsMediaAnnouncements();
+            //获取报警信息
+            this.laboratoryBigViewSelectTriggerInfo();
+            //开启MQTT订阅
+            //开启实验室轮播
+            this.subTimerFunction();
+          }
+        });
+      },
+      //获取选中实验室数据
+      getSubData(item){
+        let obj = JSON.parse(JSON.stringify(this.mapData.list[this.checkIndex]));
+        obj.alarmType = item.alarmType
+        obj.usageRate = this.accMul(obj.usageRate,100)+'';
+        obj.data8 = [];
+        obj.data9 = [];
+        //查询实验室传感器信息 合并 数据 传给 房间组件展示
+        this.$parent.setVideoData(obj);
       },
       //匹配楼层ID
       getFloorId(floorId) {
@@ -78,7 +151,69 @@
         } else if (floorId == process.env.VUE_APP_FLOOR_ID_8 || floorId == process.env.VUE_APP_FLOOR_ID_9 || floorId == process.env.VUE_APP_FLOOR_ID_10) {
           return 4
         }
-      }
+      },
+      /*************** 获取通知相关 ***************/
+      dashboardsMediaAnnouncements(){
+        dashboardsMediaAnnouncements().then(res => {
+          if(res.data){
+            console.log('有')
+            //有通知消息流程
+          }else{
+            console.log('无')
+            //没有通知消息流程
+          }
+        })
+      },
+      /*************** 获取报警相关 ***************/
+      laboratoryBigViewSelectTriggerInfo(){
+        laboratoryBigViewSelectTriggerInfo().then(res => {
+
+        })
+      },
+      /*************** 定时器相关 ***************/
+      noticeTimerFunction(){
+        const self = this;
+        self.noticeTimer = window.setInterval(checkNoticeUpdates, this.noticeSwitchTime);
+        async function checkNoticeUpdates() {
+          //没有报警
+          if(!self.alarmType){
+
+          }
+        }
+      },
+      subTimerFunction(){
+        const self = this;
+        self.subTimer = window.setInterval(checkSubUpdates, this.subSwitchTime);
+        async function checkSubUpdates() {
+          //没有报警 且 没有展示通知
+          if(!self.alarmType && !self.noticeType && !self.subInfoType){
+            if(self.checkIndex<self.mapData.list.length-1){
+              self.$set(self,'checkIndex', self.checkIndex+1);
+              self.getSubData({alarmType:false});
+            }else{
+              self.$set(self,'checkIndex', 0);
+              self.initialize(false)
+            }
+          }
+        }
+      },
+      //乘法
+      accMul(arg1,arg2){
+        var m=0,s1=arg1.toString(),s2=arg2.toString();
+        try{m+=s1.split(".")[1].length}catch(e){}
+        try{m+=s2.split(".")[1].length}catch(e){}
+        return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
+      },
+    },
+    beforeDestroy() {
+      //清除定时器
+      clearInterval(this.noticeTimer);
+      clearInterval(this.subTimer);
+    },
+    destroyed() {
+      //清除定时器
+      clearInterval(this.noticeTimer);
+      clearInterval(this.subTimer);
     }
   }
 </script>

+ 30 - 0
src/views/components/mediaAnnouncementComponent.vue

@@ -0,0 +1,30 @@
+<!--通知公告-->
+<template>
+  <div class="mediaAnnouncementComponent">
+
+  </div>
+</template>
+<script>
+  export default {
+    name: 'mediaAnnouncementComponent',
+    data () {
+      return {
+
+      }
+    },
+    created(){
+
+    },
+    mounted(){
+
+    },
+    methods:{
+
+    },
+  }
+</script>
+<style scoped lang="scss">
+  .mediaAnnouncementComponent{
+
+  }
+</style>

+ 20 - 5
src/views/components/overviewComponent.vue

@@ -33,23 +33,38 @@
   </div>
 </template>
 <script>
+  import { dashboardsFacilitiesStatusOverview } from "@/api/yiLi";
   export default {
     name: 'overviewComponent',
     data () {
       return {
-        data1:'12',
-        data2:'22',
-        data3:'32',
+        data1:'0',
+        data2:'0',
+        data3:'0',
       }
     },
     created(){
 
     },
     mounted(){
-
+      this.dashboardsFacilitiesStatusOverview();
     },
     methods:{
-
+      //设施状态概览
+      dashboardsFacilitiesStatusOverview(){
+        let self = this;
+        dashboardsFacilitiesStatusOverview().then(res => {
+          for(let i=0;i<res.data.types.length;i++){
+            if( res.data.types[i].type == '空闲'){
+              self.$set(self,'data1',res.data.types[i].count);
+            }else if( res.data.types[i].type == '使用中'){
+              self.$set(self,'data2',res.data.types[i].count);
+            }else if( res.data.types[i].type == '维修中'){
+              self.$set(self,'data3',res.data.types[i].count);
+            }
+          }
+        });
+      },
     },
   }
 </script>

+ 22 - 80
src/views/components/subComponent.vue

@@ -1,33 +1,34 @@
 <!--实验室信息-->
 <template>
-  <div class="subComponent" @click="getSubData">
+  <div class="subComponent">
     <transition name="slide-fade">
-      <div v-if="newDataShow" class="subComponent-box" :class="newData.data10?'subComponent-box-alarm':''">
+      <div v-if="newDataShow" class="subComponent-box" :class="newData.alarmType?'subComponent-box-alarm':''">
         <!--实验室-->
         <div class="max-big-box-1">
-          <div class="type-p" :class="newData.data1==1?'idle-color':(newData.data1==2?'use-color':(newData.data1==3?'maintenance-color':''))">
-            <p>{{newData.data1==1?'空闲':(newData.data1==2?'使用':(newData.data1==3?'维修':''))}}</p>
+          <div class="type-p" :class="newData.status==1?'idle-color':(newData.status==2?'use-color':(newData.status==3?'maintenance-color':''))">
+            <p>{{newData.status==1?'空闲':(newData.status==2?'使用':(newData.status==3?'维修':''))}}</p>
           </div>
-          <p class="room-p">{{newData.data2}}</p>
+          <p class="room-p">{{newData.roomNumName}}</p>
           <div class="num-box">
             <img src="@/assets/ZDimages/icon_syl@1x.png">
             <p class="text-p">使用率:</p>
-            <p class="for-p"><span v-for="(item,index) in newData.data3" :key="index">{{item}}</span>%</p>
+            <p class="for-p"><span v-for="(item,index) in newData.usageRate" :key="index">{{item}}</span>%</p>
           </div>
         </div>
         <!--类型-->
         <div class="max-big-box-2">
-          <p class="text-p-1">{{newData.data4}}</p>
-          <p class="text-p-2">{{newData.data5}}</p>
-          <p class="text-p-3">今日使用人次{{newData.data6?newData.data6:0}}人</p>
+          <p class="text-p-1">{{newData.equTypeValue}}</p>
+          <p class="text-p-2">{{newData.areaValue}}㎡</p>
+          <p class="text-p-3">今日进入人次{{newData.data6?newData.data6:0}}人</p>
         </div>
         <!--负责人-->
         <div class="max-big-box-3">
           <img src="@/assets/ZDimages/icon_fzr@1x.png">
-          <p>负责人:{{newData.data7}}</p>
+          <p v-if="newData.status==2">使用人:{{newData.userName}}</p>
+          <p v-if="newData.status!=2">负责人:{{newData.headName}}</p>
         </div>
         <!--插座-->
-        <div class="max-big-box-4" :class="newData.data10?'max-big-box-4-alarm':''">
+        <div v-if="newData.data8[0]" class="max-big-box-4" :class="newData.alarmType?'max-big-box-4-alarm':''">
           <img src="@/assets/ZDimages/icon_czyd@1x.png">
           <p class="title-p">插座用电:</p>
           <p class="for-text-p" :class="item.dataType?'for-text-p-alarm':''"
@@ -36,7 +37,7 @@
           </p>
         </div>
         <!--传感器-->
-        <div class="max-big-box-5">
+        <div class="max-big-box-5" v-if="newData.data9[0]">
           <div class="for-box"  :class="item.newDataType?'alarm-box':''"
                v-for="(item,index) in newData.data9" :key="index">
             <div class="img-box">
@@ -65,13 +66,13 @@
       return {
         newDataShow:true,
         newData:{
-          data1:1,
-          data2:'701',
-          data3:'100',
-          data4:'培养架型人工气候室',
-          data5:'19.63㎡',
+          status:1,
+          roomNumName:'701',
+          usageRate:'100',
+          equTypeValue:'培养架型人工气候室',
+          areaValue:'19.63㎡',
           data6:'13',
-          data7:'黎明-13569855478',
+          headName:'黎明-13569855478',
           data8:[
             {
               dataName:'电流',
@@ -118,9 +119,8 @@
               icon:'http://192.168.1.8/statics/2025/08/14/e10a84a5-fcb6-4a96-8211-3ecd9b86b80f.svg',
             },
           ],
-          data10:false,
+          alarmType:false,
         },
-        num:0,
       }
     },
     created(){
@@ -130,66 +130,8 @@
 
     },
     methods:{
-      getSubData(){
-        this.num++
-        let obj = {
-          data1:1,
-          data2:'701',
-          data3:'100',
-          data4:'培养架型人工气候室',
-          data5:'19.63㎡',
-          data6:'13',
-          data7:'黎明-13569855478',
-          data8:[
-            {
-              dataName:'电流',
-              dataValue:'9.8',
-              dataClass:'A',
-              dataType:false,
-            },
-            {
-              dataName:'电压',
-              dataValue:'218',
-              dataClass:'V',
-              dataType:false,
-            },
-            {
-              dataName:'功率',
-              dataValue:'2136',
-              dataClass:'W',
-              dataType:false,
-            },
-          ],
-          data9:[
-            {
-              newDataName:'温度',
-              newDataValue:'65.4',
-              newDataClass:'℃',
-              newDataType:true,
-              newDataStatus:'0',
-              icon:'http://192.168.1.8/statics/2025/08/14/5e95d546-584e-47df-80fd-fa1fe3994295.svg',
-            },
-            {
-              newDataName:'湿度',
-              newDataValue:'66.66',
-              newDataClass:'%RH',
-              newDataType:false,
-              newDataStatus:'0',
-              icon:'http://192.168.1.8/statics/2025/08/14/21b2c8e0-444c-4ee4-8671-d40a17ed611c.svg',
-            },
-            {
-              newDataName:'火灾烟感',
-              newDataValue:'',
-              newDataClass:'',
-              newDataType:false,
-              newDataStatus:'1',
-              icon:'http://192.168.1.8/statics/2025/08/14/e10a84a5-fcb6-4a96-8211-3ecd9b86b80f.svg',
-            },
-          ],
-          data10:false,
-        };
-        obj.data2 = this.num;
-        this.switchBox(obj);
+      getSubData(item){
+        this.switchBox(item);
       },
       switchBox(obj){
         console.log('obj',obj)

+ 162 - 103
src/views/components/usageRateComponent.vue

@@ -2,7 +2,8 @@
 <template>
   <div class="usageRateComponent">
     <p class="title-p">设施使用率排行</p>
-    <dv-scroll-board :config="config" style="width:470px;height:435px" />
+    <dv-scroll-board :config="config" style="width:470px;height:435px" v-if="config.data[0]"/>
+    <p class="position-null-p" v-if="!config.data[0]">暂无数据</p>
     <img class="position-left-top" src="@/assets/ZDimages/img_min_icon.png">
     <img class="position-right-top" src="@/assets/ZDimages/img_min_icon.png">
     <img class="position-left-bottom" src="@/assets/ZDimages/img_min_icon.png">
@@ -10,165 +11,223 @@
   </div>
 </template>
 <script>
+  import { dashboardsFacilitiesUsageStats } from '@/api/yiLi'
+
   export default {
     name: 'usageRateComponent',
-    data () {
+    data() {
       return {
-        wendu_zc : require('@/assets/ZDimages/img_cgq_zc@1x.png'),
-        config:{
-          rowNum:7,
-          headerBGC:'rgba(0,66,138,0.5)',
-          oddRowBGC:'rgba(0,66,138,0.0)',
-          evenRowBGC:'rgba(0,66,138,0.0)',
+        wendu_zc: require('@/assets/ZDimages/img_cgq_zc@1x.png'),
+        config: {
+          rowNum: 7,
+          headerBGC: 'rgba(0,66,138,0.5)',
+          oddRowBGC: 'rgba(0,66,138,0.0)',
+          evenRowBGC: 'rgba(0,66,138,0.0)',
           header: ['', '设施房间', '使用人次', '使用率'],
-          data:[
-            ['<span class="span_1"><span></span></span>','行1列1', '行1列2', '行1列3'],
-            ['<span class="span_2"><span></span></span>','行2列1', '行2列2', '行2列3'],
-            ['<span class="span_3"><span></span></span>','行3列1', '行3列2', '行3列3'],
-            ['<span class="span_num"><span>4</span></span>','行4列1', '行4列2', '行4列3'],
-            ['<span class="span_num"><span>5</span></span>','行4列1', '行4列2', '行4列3'],
-            ['<span class="span_num"><span>6</span></span>','行4列1', '行4列2', '行4列3'],
-            ['<span class="span_num"><span>7</span></span>','行4列1', '行4列2', '行4列3'],
-            ['<span class="span_num"><span>8</span></span>','行4列1', '行4列2', '行4列3'],
-            ['<span class="span_num"><span>9</span></span>','行4列1', '行4列2', '行4列3'],
+          data: [
+            // ['<span class="span_1"><span></span></span>','行1列1', '行1列2', '行1列3'],
+            // ['<span class="span_2"><span></span></span>','行2列1', '行2列2', '行2列3'],
+            // ['<span class="span_3"><span></span></span>','行3列1', '行3列2', '行3列3'],
+            // ['<span class="span_num"><span>4</span></span>','行4列1', '行4列2', '行4列3'],
+            // ['<span class="span_num"><span>5</span></span>','行4列1', '行4列2', '行4列3'],
+            // ['<span class="span_num"><span>6</span></span>','行4列1', '行4列2', '行4列3'],
+            // ['<span class="span_num"><span>7</span></span>','行4列1', '行4列2', '行4列3'],
+            // ['<span class="span_num"><span>8</span></span>','行4列1', '行4列2', '行4列3'],
+            // ['<span class="span_num"><span>9</span></span>','行4列1', '行4列2', '行4列3'],
           ]
         }
       }
     },
-    created(){
+    created() {
 
     },
-    mounted(){
-
-    },
-    methods:{
-
+    mounted() {
+      this.dashboardsFacilitiesUsageStats()
     },
+    methods: {
+      dashboardsFacilitiesUsageStats() {
+        let self = this
+        dashboardsFacilitiesUsageStats().then(res => {
+          let list = []
+          for (let i = 0; i < res.data.monthlyUsage.length; i++) {
+            let obj = {
+              name: res.data.monthlyUsage[i].equTypeName,
+              num: res.data.monthlyUsage[i].equRentingCount,
+              value: res.data.monthlyUsage[i].equRentingCount == 0 ? res.data.monthlyUsage[i].equRentingCount + '%' : self.calculatePercentage(res.data.monthlyUsage[i].equRentingCount, res.data.monthlyUsage[i].equCount, { decimal: 0 })
+            }
+            list.push(obj)
+          }
+          list = this.sortByPercentageDesc(list)
+          let newList = [];
+          for(let i=0;i<list.length;i++){
+            if(i==0){
+              newList.push(['<span class="span_1"><span></span></span>',list[i].name, list[i].num+'', list[i].value])
+            }else if(i==1){
+              newList.push(['<span class="span_2"><span></span></span>',list[i].name, list[i].num+'', list[i].value])
+            }else if(i==1){
+              newList.push(['<span class="span_3"><span></span></span>',list[i].name, list[i].num+'', list[i].value])
+            }else{
+              newList.push(['<span class="span_num"><span>'+(i+1)+'</span></span>',list[i].name, list[i].num+'', list[i].value])
+            }
+          }
+          this.$set(this.config,'data',newList)
+        })
+      },
+      calculatePercentage(numerator, denominator, options = {}) {
+        if (typeof numerator !== 'number' || typeof denominator !== 'number') {
+          throw new TypeError('分子和分母必须是数字')
+        }
+        if (denominator === 0) {
+          throw new Error('分母不能为零')
+        }
+        const { decimal = 2, returnString = true } = options
+        const percentage = (numerator / denominator) * 100
+        const rounded = Math.round(percentage * Math.pow(10, decimal)) / Math.pow(10, decimal)
+        return returnString ? `${rounded}%` : rounded
+      },
+      parsePercentage(percentStr) {
+        return parseFloat(percentStr.replace('%', ''))
+      },
+      sortByPercentageDesc(arr, prop = 'value') {
+        return [...arr].sort((a, b) => {
+          const valA = this.parsePercentage(a[prop])
+          const valB = this.parsePercentage(b[prop])
+          return valB - valA // 降序排序
+        })
+      },
+    }
   }
 </script>
 <style scoped lang="scss">
-  .usageRateComponent{
-    width:530px;
-    height:512px;
-    margin:20px 0 0 20px;
+  .usageRateComponent {
+    width: 530px;
+    height: 512px;
+    margin: 20px 0 0 20px;
     background-image: url("../../assets/ZDimages/img_sssylph@1x.png");
     background-size: 100% 100%;
     position: relative;
-    .title-p{
+    .title-p {
       position: absolute;
-      width:282px;
-      height:36px;
+      width: 282px;
+      height: 36px;
       line-height: 36px;
-      color:#fff;
-      font-size:18px;
+      color: #fff;
+      font-size: 18px;
       font-weight: 700;
       font-family: Source Han Sans, Source Han Sans;
-      padding-left:24px;
+      padding-left: 24px;
+    }
+    .position-null-p {
+      position: absolute;
+      left: 230px;
+      top: 240px;
+      color: #dedede;
+      font-size: 16px;
     }
-    .position-left-top{
+    .position-left-top {
       position: absolute;
-      left:-15px;
-      top:28px;
-      width:42px;
-      height:42px;
-      z-index:1;
+      left: -15px;
+      top: 28px;
+      width: 42px;
+      height: 42px;
+      z-index: 1;
     }
-    .position-right-top{
+    .position-right-top {
       position: absolute;
-      right:-15px;
-      top:-15px;
-      width:42px;
-      height:42px;
-      z-index:1;
+      right: -15px;
+      top: -15px;
+      width: 42px;
+      height: 42px;
+      z-index: 1;
       transform: rotate(90deg);
     }
-    .position-left-bottom{
+    .position-left-bottom {
       position: absolute;
-      left:-15px;
-      bottom:-15px;
-      width:42px;
-      height:42px;
-      z-index:1;
+      left: -15px;
+      bottom: -15px;
+      width: 42px;
+      height: 42px;
+      z-index: 1;
       transform: rotate(270deg);
     }
-    .position-right-bottom{
+    .position-right-bottom {
       position: absolute;
-      right:-14px;
-      bottom:-15px;
-      width:42px;
-      height:42px;
-      z-index:1;
+      right: -14px;
+      bottom: -15px;
+      width: 42px;
+      height: 42px;
+      z-index: 1;
       transform: rotate(180deg);
     }
-    ::v-deep .dv-scroll-board{
-      margin:54px 0 0 30px;
-      .header{
-        .header-item{
-          width:137px!important;
+    ::v-deep .dv-scroll-board {
+      margin: 54px 0 0 30px;
+      .header {
+        .header-item {
+          width: 137px !important;
         }
-        .header-item:nth-child(1){
-          width:50px!important;
+        .header-item:nth-child(1) {
+          width: 50px !important;
         }
-        .header-item:nth-child(3){
+        .header-item:nth-child(3) {
           text-align: center;
         }
-        .header-item:nth-child(4){
+        .header-item:nth-child(4) {
           text-align: right;
         }
       }
-      .row-item{
-        height:50px!important;
-        line-height:50px!important;
-        border-bottom:1px dashed rgba(216,216,216,0.1);
-        .ceil{
-          width:137px!important;
+      .row-item {
+        height: 50px !important;
+        line-height: 50px !important;
+        border-bottom: 1px dashed rgba(216, 216, 216, 0.1);
+        .ceil {
+          width: 137px !important;
         }
-        .ceil:nth-child(1){
-          width:50px!important;
+        .ceil:nth-child(1) {
+          width: 50px !important;
         }
-        .ceil:nth-child(3){
+        .ceil:nth-child(3) {
           text-align: center;
         }
-        .ceil:nth-child(4){
+        .ceil:nth-child(4) {
           text-align: right;
         }
       }
-      .span_1{
-        display:inline-block;
-        width:24px;
-        height:30px;
-        margin:10px 0 0 0;
+      .span_1 {
+        display: inline-block;
+        width: 24px;
+        height: 30px;
+        margin: 10px 0 0 0;
         background-image: url("../../assets/ZDimages/img_pm_a@1x.png");
         background-size: 100% 100%;
       }
-      .span_2{
-        display:inline-block;
-        width:24px;
-        height:30px;
-        margin:10px 0 0 0;
+      .span_2 {
+        display: inline-block;
+        width: 24px;
+        height: 30px;
+        margin: 10px 0 0 0;
         background-image: url("../../assets/ZDimages/img_pm_b.png");
         background-size: 100% 100%;
       }
-      .span_3{
-        display:inline-block;
-        width:24px;
-        height:30px;
-        margin:10px 0 0 0;
+      .span_3 {
+        display: inline-block;
+        width: 24px;
+        height: 30px;
+        margin: 10px 0 0 0;
         background-image: url("../../assets/ZDimages/img_pm_c@1x.png");
         background-size: 100% 100%;
       }
-      .span_num{
-        display:inline-block;
-        width:24px;
-        height:30px;
-        span{
-          display:inline-block;
-          width:20px;
-          height:20px;
-          line-height:20px;
+      .span_num {
+        display: inline-block;
+        width: 24px;
+        height: 30px;
+        span {
+          display: inline-block;
+          width: 20px;
+          height: 20px;
+          line-height: 20px;
           background-color: #0E52C3;
-          border:1px solid #0576FF;
-          border-radius:50%;
+          border: 1px solid #0576FF;
+          border-radius: 50%;
           text-align: center;
         }
       }

+ 60 - 7
src/views/home.vue

@@ -1,29 +1,36 @@
 <template>
   <div class="home">
-    <div class="home-page" v-if="showPage">
+    <div class="home-page" v-if="showPage" v-show="pageType == 1">
       <headComponent></headComponent>
       <div class="top-max-big-box">
-        <videoComponent></videoComponent>
+        <videoComponent ref="videoComponent"></videoComponent>
         <overviewComponent></overviewComponent>
         <usageRateComponent></usageRateComponent>
       </div>
       <div class="bottom-max-big-box">
         <mapComponent></mapComponent>
-        <subComponent></subComponent>
+        <subComponent ref="subComponent"></subComponent>
       </div>
     </div>
+    <mediaAnnouncementComponent v-if="pageType == 2"></mediaAnnouncementComponent>
+    <alarmComponent v-if="alarmType"></alarmComponent>
   </div>
 </template>
 <script>
-  import { chemicalStockHazardClassStatistics } from "@/api/index";
   import { login } from "@/api/login";
-  import { setToken } from '@/utils/auth'
+  import { loginYiLi } from "@/api/yiLi";
+  import { setToken,setTokenYiLi } from '@/utils/auth'
+  //首页组件
   import headComponent from './components/headComponent.vue'
   import videoComponent from './components/videoComponent.vue'
   import overviewComponent from './components/overviewComponent.vue'
   import usageRateComponent from './components/usageRateComponent.vue'
   import mapComponent from './components/mapComponent.vue'
   import subComponent from './components/subComponent.vue'
+  //通知公告
+  import mediaAnnouncementComponent from './components/mediaAnnouncementComponent.vue'
+  //报警信息
+  import alarmComponent from './components/alarmComponent.vue'
   export default {
     name: 'home',
     components: {
@@ -33,10 +40,17 @@
       usageRateComponent,
       mapComponent,
       subComponent,
+      mediaAnnouncementComponent,
+      alarmComponent,
     },
     data () {
       return {
+        //页面开关
         showPage:false,
+        //展示状态
+        pageType:1,
+        //报警开关
+        alarmType:false,
       }
     },
     created(){
@@ -48,11 +62,50 @@
     methods:{
       //获取token
       getToken(){
-        login().then(res => {
-          setToken(res.data.token)
+        login().then(res1 => {
+          setToken(res1.data.token)
+          this.getTokenYiLi();
+        });
+      },
+      //获取YiLi-token
+      getTokenYiLi(){
+        loginYiLi().then(res2 => {
+          setTokenYiLi(res2.access_token);
           this.$set(this,'showPage',true);
         });
       },
+      //获取开发配置
+      getExploitConfig(){
+        getConfigByType({ category: 2, configType: 5 }).then(response => {
+          let obj = JSON.parse(response.data.configValue)
+          //判定http或者https
+          let urlText = window.location.href.split('://')[0]+'://';
+          let outerNet = window.location.href.indexOf(obj.ipIdentify) == -1//true外网 false 内网
+          if(outerNet){//外网
+            //MQTT地址
+            localStorage.setItem('mqttUrl','wss://'+Decrypt(obj.mqttExtranetUrl))
+            //MQTT账号
+            localStorage.setItem('mqttUser',Decrypt(obj.mqttExtranetUser))
+            //MQTT密码
+            localStorage.setItem('mqttPassword',Decrypt(obj.mqttExtranetPassword))
+          }else{
+            //MQTT地址
+            localStorage.setItem('mqttUrl','ws://'+Decrypt(obj.mqttIntranetUrl))
+            //MQTT账号
+            localStorage.setItem('mqttUser',Decrypt(obj.mqttIntranetUser))
+            //MQTT密码
+            localStorage.setItem('mqttPassword',Decrypt(obj.mqttIntranetPassword))
+          }
+        });
+      },
+      //房间组件数据给予
+      setRoomData(item){
+
+      },
+      //视频组件数据给予
+      setVideoData(item){
+        this.$refs.subComponent.getSubData(item);
+      },
     },
     beforeDestroy() {