浏览代码

样式调整

dedsudiyu 1 周之前
父节点
当前提交
91acf2ec63
共有 3 个文件被更改,包括 168 次插入46 次删除
  1. 21 13
      src/components/EnvMonitorStats.vue
  2. 14 7
      src/components/EquipmentStats.vue
  3. 133 26
      src/components/SecurityMonitor.vue

+ 21 - 13
src/components/EnvMonitorStats.vue

@@ -24,11 +24,20 @@
       <!-- 仪表盘 + 设备列表 -->
       <div class="device-middle">
         <div ref="gauge" class="gauge-chart"></div>
-        <div class="device-list-row">
-          <div class="device-list-item" v-for="item in devices" :key="item.name">
-            <div class="dli-icon">{{ item.icon }}</div>
-            <div class="dli-num">{{ item.value }}</div>
-            <div class="dli-name">{{ item.name }}</div>
+        <div style="flex:1;display:flex;flex-direction:column;gap:12px">
+          <div style="display:flex;gap:12px">
+            <div class="device-list-item" style="flex:1" v-for="item in devicesRow1" :key="item.name">
+              <div class="dli-icon">{{ item.icon }}</div>
+              <div class="dli-num">{{ item.value }}</div>
+              <div class="dli-name">{{ item.name }}</div>
+            </div>
+          </div>
+          <div style="display:flex;gap:12px;justify-content:center">
+            <div class="device-list-item" style="flex:0 0 calc(33.33% - 6px)" v-for="item in devicesRow2" :key="item.name">
+              <div class="dli-icon">{{ item.icon }}</div>
+              <div class="dli-num">{{ item.value }}</div>
+              <div class="dli-name">{{ item.name }}</div>
+            </div>
           </div>
         </div>
       </div>
@@ -52,6 +61,10 @@ export default {
       pollTimer: null
     }
   },
+  computed: {
+    devicesRow1() { return this.devices.slice(0, 3) },
+    devicesRow2() { return this.devices.slice(3) }
+  },
   mounted() {
     this.fetchData()
     this.pollTimer = setInterval(this.fetchData, 5 * 60 * 1000)
@@ -72,9 +85,10 @@ export default {
           this.onlineRate = d.onlineRate
           this.devices = [
             { icon: '🏷️', value: d.tagCount,      name: '电子信息铭牌' },
-            { icon: '🌡️', value: d.sensorCount,   name: '传感器套件' },
             { icon: '⚗️', value: d.terminalCount, name: '化学品智能终端' },
-            { icon: '📷', value: d.cameraCount,   name: '智能摄像设备' }
+            { icon: '🌡️', value: d.sensorCount,   name: '传感器' },
+            { icon: '📷', value: d.cameraCount,   name: '智慧摄像头' },
+            { icon: '📡', value: d.otherCount,    name: '其他智能设备' }
           ]
         }
       } catch (e) {
@@ -301,12 +315,6 @@ export default {
   height: 295px;
 }
 
-.device-list-row {
-  flex: 1;
-  display: grid;
-  grid-template-columns: 1fr 1fr;
-  gap: 12px;
-}
 
 .device-list-item {
   padding: 15px;

+ 14 - 7
src/components/EquipmentStats.vue

@@ -64,6 +64,7 @@ export default {
       totalHours: 0,
       usageRate: 0,
       categories: [],
+      deviceStatus: [],
       usageStatus: [],
       ringChart: null,
       pieStatusChart: null,
@@ -96,11 +97,16 @@ export default {
             name:  c.categoryOneName,
             color: CATEGORY_COLORS[i % CATEGORY_COLORS.length]
           }))
-          this.usageStatus = [
-            { value: d.inUseCount,  name: '使用', color: '#1e90ff' },
-            { value: d.idleCount,   name: '空闲', color: '#00e676' },
-            { value: d.repairCount, name: '维修', color: '#f59e0b' }
-          ]
+          const STATUS_COLORS = { '正常': '#00e676', '维修': '#f59e0b', '报废': '#ef4444' }
+          const USAGE_COLORS  = { '使用': '#1e90ff', '空闲': '#00e676' }
+          this.deviceStatus = (d.deviceStatusList || []).map(s => ({
+            value: s.count, name: s.name,
+            color: STATUS_COLORS[s.name] || '#a8cce8'
+          }))
+          this.usageStatus = (d.usageStatusList || []).map(s => ({
+            value: s.count, name: s.name,
+            color: USAGE_COLORS[s.name] || '#a8cce8'
+          }))
         }
       } catch (e) {
         // 保持默认值
@@ -198,7 +204,7 @@ export default {
     /** 初始化饼图 - 设备状态统计 */
     initPieStatusChart() {
       this.pieStatusChart = echarts.init(this.$refs.pieStatusChart, null, { renderer: 'canvas', devicePixelRatio: 2 })
-      this.pieStatusChart.setOption(this._buildPieOption(this.usageStatus))
+      this.pieStatusChart.setOption(this._buildPieOption(this.deviceStatus))
     },
     /** 初始化饼图 - 使用状态统计 */
     initPieUsageChart() {
@@ -216,6 +222,7 @@ export default {
         backgroundColor: 'transparent',
         tooltip: { trigger: 'item', formatter: '{b}: {c}台 ({d}%)', ...TOOLTIP_CFG },
         legend: {
+          show:false,
           orient: 'vertical', right: '2%', top: 'middle',
           icon: 'circle', itemWidth: 28, itemHeight: 28, itemGap: 28,
           textStyle: { color: '#a8cce8', fontSize: 22 },
@@ -225,7 +232,7 @@ export default {
           type: 'pie', radius: ['36%', '62%'], center: ['38%', '52%'],
           itemStyle: { borderRadius: 5, borderColor: 'rgba(3,14,31,0.5)', borderWidth: 2 },
           label: { show: true, formatter: '{b}\n{c}台', fontSize: 20, color: '#a8cce8', lineHeight: 30 },
-          labelLine: { length: 14, length2: 10, lineStyle: { color: 'rgba(30,144,255,0.4)', width: 2 } },
+          labelLine: { length: 24, length2: 40, lineStyle: { color: 'rgba(30,144,255,0.4)', width: 2 } },
           data: pieData,
           emphasis: { scale: true, scaleSize: 6, itemStyle: { shadowBlur: 25, shadowColor: 'rgba(30,144,255,0.6)' } }
         }]

+ 133 - 26
src/components/SecurityMonitor.vue

@@ -4,32 +4,38 @@
     <div class="monitor-header">
       <span class="monitor-title-cn">&#x1F4F9; &#x5B9E;&#x65F6;&#x76D1;&#x63A7;</span>
       <span class="monitor-title-en">CCTV Live Feed</span>
+      <div class="monitor-button">
+        <p :class="checkButton == 1 ? 'checkButton':'noCheckButton'" @click="buttonClick(1)">默认</p>
+        <p :class="checkButton == 2 ? 'checkButton':'noCheckButton'" @click="buttonClick(2)">全部</p>
+      </div>
       <div class="monitor-status">
         <div class="status-dot green"></div>
         <span class="monitor-status-text">&#x4FE1;&#x53F7;&#x6B63;&#x5E38;</span>
       </div>
     </div>
-
+    <div v-if="checkButton == 1" class="monitor-play-box">
+      <H5PlayerVideo class="for-play-box"  v-for="(item,index) in videoList" :key="index" :videoProps="item"></H5PlayerVideo>
+    </div>
     <!-- Monitor Inner: 2-column grid -->
-    <div class="monitor-inner">
+    <div class="monitor-inner" v-if="checkButton == 2">
       <!-- Left Column: Search + Filter + Tree -->
       <div class="monitor-left">
         <div class="search-box">
           <span class="search-icon">&#x1F50D;</span>
-          <el-input class="video-select" 
+          <el-input class="video-select"
             @keyup.enter.native="handleEnter"
             @clear="handleEnter"
             clearable
-            v-model="queryParams.searchValue" 
+            v-model="queryParams.searchValue"
             type="text" placeholder="搜索楼栋/楼层...." >
           </el-input>
         </div>
 
-        <el-select class="filter-select" 
+        <el-select class="filter-select"
           @change="handleEnter"
           @clear="handleEnter"
           clearable
-          v-model="queryParams.deptId" 
+          v-model="queryParams.deptId"
           placeholder="请选择二级单位">
           <el-option
             v-for="item in options"
@@ -222,7 +228,7 @@ export default {
         searchValue: "",
         deptId: '',
       },
-      deptOptions: [], 
+      deptOptions: [],
       options:[],
       treeId:null,
       defaultKey:null,
@@ -241,17 +247,31 @@ export default {
       //全屏视频参数
       fullVideoProps:{},
       fullVideoType:false,
+      //切换
+      checkButton:1,
     }
   },
   created() {
     // this.fetchCameras()
   },
   mounted() {
-    this.getMonitorTree();
-    this.getDeptDropList();
+    if(this.checkButton == 1){
+      this.getVideoDataOne()
+    }else if(this.checkButton == 2){
+      this.getMonitorTree();
+      this.getDeptDropList();
+    }
   },
   methods: {
-    
+    buttonClick(val){
+      this.$set(this,'checkButton',val);
+      if(val == 1){
+        this.getVideoDataOne()
+      }else if(val == 2){
+        this.getMonitorTree();
+        this.getDeptDropList();
+      }
+    },
     handleEnter(){
       this.getMonitorTree();
     },
@@ -301,8 +321,6 @@ export default {
       }
     },
     nodeClickButton(e,data){
-      console.log('e===>',e);
-      console.log('data===>',data);
       let self = this;
       this.$nextTick(() => {
         if (!e.level||e.level == 2||e.level == 3) {
@@ -470,18 +488,18 @@ export default {
       try {
         const res = await getCameraStream(this.videoQueryParams)
         let list = [];
-        // res.data.total = 100;
-        // res.data.records = [
-        //   {streamUrl:'1', deviceNo:'1'},
-        //   {streamUrl:'2', deviceNo:'2'},
-        //   {streamUrl:'3', deviceNo:'3'},
-        //   {streamUrl:'4', deviceNo:'4'},
-        //   {streamUrl:'5', deviceNo:'5'},
-        //   {streamUrl:'6', deviceNo:'6'},
-        //   {streamUrl:'7', deviceNo:'7'},
-        //   {streamUrl:'8', deviceNo:'8'},
-        //   {streamUrl:'9', deviceNo:'9'},
-        // ];
+        res.data.total = 100;
+        res.data.records = [
+          {streamUrl:'1', deviceNo:'1'},
+          {streamUrl:'2', deviceNo:'2'},
+          {streamUrl:'3', deviceNo:'3'},
+          {streamUrl:'4', deviceNo:'4'},
+          {streamUrl:'5', deviceNo:'5'},
+          {streamUrl:'6', deviceNo:'6'},
+          {streamUrl:'7', deviceNo:'7'},
+          {streamUrl:'8', deviceNo:'8'},
+          {streamUrl:'9', deviceNo:'9'},
+        ];
         for(let i=0;i<res.data.records.length;i++){
           list.push(
             {
@@ -503,6 +521,65 @@ export default {
         console.error('VideoGrid:', e)
       }
     },
+    //指定视频
+    getVideoDataOne(data){
+      let obj = {
+        page:1,
+        pageSize:9,
+        passageway:'',
+        protocol:window.location.href.indexOf('https') !== -1?'wss':'ws',
+        streamType:1,
+        source:4,
+        subIds:data,
+      };
+      this.$nextTick(()=>{
+        this.videoInitializeOne(obj)
+      })
+    },
+    async videoInitializeOne(obj) {
+      let self = this;
+      self.$set(self, 'videoType', false);
+      self.$set(self, 'videoList', []);
+      try {
+        // const res = await getCameraStream(obj)
+        let list = [];
+        let res = {
+          data:{
+            total:100,
+            records:[
+              {streamUrl:'1', deviceNo:'1'},
+              {streamUrl:'2', deviceNo:'2'},
+              {streamUrl:'3', deviceNo:'3'},
+              {streamUrl:'4', deviceNo:'4'},
+              {streamUrl:'5', deviceNo:'5'},
+              {streamUrl:'6', deviceNo:'6'},
+              {streamUrl:'7', deviceNo:'7'},
+              {streamUrl:'8', deviceNo:'8'},
+              {streamUrl:'9', deviceNo:'9'},
+            ]
+          }
+        }
+        for(let i=0;i<res.data.records.length;i++){
+          list.push(
+              {
+                width: 1396, //(宽度:非必传-默认600)
+                height: 810, //(高度:非必传-默认338)
+                url: res.data.records[i].streamUrl,
+                cameraIndexCode: res.data.records[i].deviceNo,
+              }
+          )
+        }
+        this.$set(this,'videoList',list)
+        this.$set(this,'videoTotal',res.data.total);
+        this.$nextTick(()=>{
+          setTimeout(function(){
+            self.$set(self, 'videoType', true);
+          },1000);
+        })
+      } catch (e) {
+        console.error('VideoGrid:', e)
+      }
+    },
     //全屏开启-关闭轮播
     stopTime(cameraIndexCode){
       this.$set(this,'fullVideoProps',{cameraIndexCode:cameraIndexCode});
@@ -611,7 +688,30 @@ export default {
   color: $text-dim;
   margin-left: 10px;
 }
-
+.monitor-button{
+  display: flex;
+  position: absolute;
+  top:15px;
+  right:240px;
+  p{
+    width:160px;
+    height:50px;
+    line-height:48px;
+    font-size:28px;
+    text-align: center;
+    margin-right:20px;
+    border-radius:10px;
+    cursor: pointer;
+  }
+  .checkButton{
+    border:1px solid #00D8FF;
+    color:#00D8FF;
+  }
+  .noCheckButton{
+    border:1px solid #3D6187;
+    color:#3D6187;
+  }
+}
 .monitor-status {
   margin-left: auto;
   display: flex;
@@ -623,7 +723,14 @@ export default {
   font-size: 28px;
   color: $text-dim;
 }
-
+.monitor-play-box{
+  .for-play-box{
+    display:inline-block;
+    width:1398px;
+    height:810px;
+    margin:20px 0 0 20px;
+  }
+}
 // ========== Monitor Inner (2-column grid) ==========
 .monitor-inner {
   flex: 1;