he wei
2025-04-23 b9bd29a1a81f6f7de479e3cc3fdfe3d85fc660bf
src/views/dashboard/index.vue
@@ -1,217 +1,219 @@
<script setup name="Dashboard">
   import { defineComponent } from 'vue';
   import HdwCard from '@/components/HdwCard/index.vue';
   import LedNum from '@/components/LedNum/index.vue';
   import mapChart from "@/components/echarts/mapChart.vue";
   import pie from "@/components/echarts/pie.vue";
   import bar from "@/components/echarts/bar.vue";
   import groupBar from "@/components/echarts/groupBar.vue";
  import { defineComponent } from 'vue';
  import ycCard from '@/components/ycCard/index.vue';
  import LedNum from '@/components/LedNum/index.vue';
  import mapChart from "@/components/echarts/mapChart.vue";
  import pie from "@/components/echarts/pie.vue";
  import bar from "@/components/echarts/bar.vue";
  import groupBar from "@/components/echarts/groupBar.vue";
  import valuePanel from './components/valuePanel.vue';
  import valuePanel2 from './components/valuePanel2.vue';
   import { ref, watchEffect } from 'vue';
   import useWebsocket from '@/hooks/useWebsocket';
  import { ref, watchEffect } from 'vue';
  import useWebsocket from '@/hooks/useWebsocket';
   const { message: listMessage } = useWebsocket('home');
  const { message: listMessage } = useWebsocket('home');
   const stationNum = ref(0);
   const chartData = ref([]);
   const map = ref();
   const typePie = ref();
   const prodPie = ref();
   const testBar = ref();
   const useageRateChart = ref();
  const stationNum = ref(0);
  const chartData = ref([]);
  const map = ref();
  const typePie = ref();
  const prodPie = ref();
  const testBar = ref();
  const useageRateChart = ref();
   let lockDatas = ref([]);
   const rateList = ref([]);
   const rateType = ref('month');
  let lockDatas = ref([]);
  const rateList = ref([]);
  const rateType = ref('month');
   // "offLineNum": 6,
   //       "unLoadNum": 5,
   //       "sumLinf": 7,
   //       "openNum": 0,
   //       "onlineNum": 1,
   //       "closeNum": 2
  // "offLineNum": 6,
  //       "unLoadNum": 5,
  //       "sumLinf": 7,
  //       "openNum": 0,
  //       "onlineNum": 1,
  //       "closeNum": 2
   const offLine_num = ref(0);
   const unLoad_num = ref(0);
   const sumLinf_num = ref(0);
   const open_num = ref(0);
   const online_num = ref(0);
   const close_num = ref(0);
   const rtData = ref([]);
   const alarmData = ref([]);
  const offLine_num = ref(0);
  // const unLoad_num = ref(0);
  const sumLinf_num = ref(0);
  const open_num = ref(0);
  const online_num = ref(0);
  const close_num = ref(0);
  const rtData = ref([]);
  const alarmData = ref([]);
   watchEffect(() => {
      if (listMessage.value) {
         const { resScreenBox, resErrorCtlLog, resAllCtlLog, resLockState, resReport, resAllAinf } = JSON.parse(listMessage.value)?.data;
         console.log('resScreenBox, resErrorCtlLog, resAllCtlLog, resLockState, resReport', resScreenBox, resErrorCtlLog, resAllCtlLog, resLockState, resReport, '=============');
  watchEffect(() => {
    if (listMessage.value) {
      const { resScreenBox, resErrorCtlLog, resAllCtlLog, resLockState, resReport, resAllAinf } = JSON.parse(listMessage.value)?.data;
      console.log('resScreenBox, resErrorCtlLog, resAllCtlLog, resLockState, resReport', resScreenBox, resErrorCtlLog, resAllCtlLog, resLockState, resReport, '=============');
         let locks = [];
         let _offLine = 0,
            _unLoad = 0,
            _sumLinf = 0,
            _open = 0,
            _online = 0,
            _close = 0;
      let locks = [];
      let _offLine = 0,
        // _unLoad = 0,
        _sumLinf = 0,
        _open = 0,
        _online = 0,
        _close = 0;
         if (resLockState.code && resLockState.data) {
            let _list = resLockState.data2;
            locks = _list.allLinfs.filter(v => v.longitude || v.latitude);
            _offLine = _list.offLineNum;
            _unLoad = _list.unLoadNum;
            _sumLinf = _list.sumLinf;
            _open = _list.openNum;
            _online = _list.onlineNum;
            _close = _list.closeNum;
         }
      if (resLockState.code && resLockState.data) {
        let _list = resLockState.data2;
        locks = _list.allLinfs.filter(v => v.longitude || v.latitude);
        _offLine = _list.offLineNum;
        // _unLoad = _list.unLoadNum;
        _sumLinf = _list.sumLinf;
        _open = _list.openNum;
        _online = _list.onlineNum;
        _close = _list.closeNum;
      }
         offLine_num.value = _offLine;
         unLoad_num.value = _unLoad;
         sumLinf_num.value = _sumLinf;
         open_num.value = _open;
         online_num.value = _online;
         close_num.value = _close;
      offLine_num.value = _offLine;
      // unLoad_num.value = _unLoad;
      open_num.value = _open;
      online_num.value = _online;
      close_num.value = _close;
      sumLinf_num.value = _sumLinf;
         lockDatas.value = locks;
      lockDatas.value = locks;
         if (resAllCtlLog.code && resAllCtlLog.data) {
            let _list = resAllCtlLog.data2.map(v => ({
               ...v,
               state: v.ctlResult ? '开锁成功' : '开锁失败'
            }));
            rtData.value = _list;
         }
         if (resErrorCtlLog.code && resErrorCtlLog.data) {
            let _list = resErrorCtlLog.data2.map(v => ({
               ...v,
               state: v.ctlResult ? '开锁成功' : '开锁失败'
            }));
            alarmData.value = _list;
         }
      if (resAllCtlLog.code && resAllCtlLog.data) {
        let _list = resAllCtlLog.data2.map(v => ({
          ...v,
          state: v.ctlResult ? '开锁成功' : '开锁失败'
        }));
        rtData.value = _list;
      }
      if (resErrorCtlLog.code && resErrorCtlLog.data) {
        let _list = resErrorCtlLog.data2.map(v => ({
          ...v,
          state: v.ctlResult ? '开锁成功' : '开锁失败'
        }));
        alarmData.value = _list;
      }
         let _rateList = [];
         if (resReport.code && resReport.data) {
            _rateList = resReport.data2;
         }
         rateList.value = _rateList;
      let _rateList = [];
      if (resReport.code && resReport.data) {
        _rateList = resReport.data2;
      }
      rateList.value = _rateList;
         let area_num = 0;
         if (resAllAinf.code && resAllAinf.data) {
            area_num = resAllAinf.data2;
         }
      let area_num = 0;
      if (resAllAinf.code && resAllAinf.data) {
        area_num = resAllAinf.data2.stationNum;
      }
         stationNum.value = area_num;
      stationNum.value = area_num;
         if (resScreenBox.code && resScreenBox.data) {
            let { product, type } = resScreenBox.data2;
            let prodData = formatPieData(product);
            let typeData = formatPieData(type);
      if (resScreenBox.code && resScreenBox.data) {
        let { product, type } = resScreenBox.data2;
        let prodData = formatPieData(product);
        let typeData = formatPieData(type);
            typePie.value.updateChart(typeData.sData);
            prodPie.value.updateChart(prodData.sData);
         }
        typePie.value.updateChart(typeData.sData);
        prodPie.value.updateChart(prodData.sData);
      }
         updateMap();
         updateStateChart();
         updateUseageRateChart();
      }
   });
      updateMap();
      updateStateChart();
      updateUseageRateChart();
    }
  });
   function updateStateChart() {
      let labels = ['锁具', '未安装', '开锁', '关锁', '在线', '离线'];
      let datas = [sumLinf_num.value, unLoad_num.value, open_num.value, close_num.value, online_num.value, offLine_num.value];
      testBar.value.updateChart(labels, datas);
   }
  function updateStateChart() {
    let labels = ['锁具', '开锁', '关锁', '在线', '离线'];
    let datas = [sumLinf_num.value, open_num.value, close_num.value, online_num.value, offLine_num.value];
    testBar.value.updateChart(labels, datas);
  }
   /**
    * 格式化数据  取前4 剩下的为其他
    */
   function formatPieData(data) {
      let res = { sData: [] };
      let arr = Object.keys(data)
         .map((v) => ({ name: v, value: data[v] }))
         .sort((a, b) => {
            return b.value - a.value;
         });
      let total = 0;
      arr.map(v => {
         total += v.value * 1;
      });
  /**
   * 格式化数据  取前4 剩下的为其他
   */
  function formatPieData(data) {
    let res = { sData: [] };
    let arr = Object.keys(data)
      .map((v) => ({ name: v, value: data[v] }))
      .sort((a, b) => {
        return b.value - a.value;
      });
    let total = 0;
    arr.map(v => {
      total += v.value * 1;
    });
      if (arr.length <= 5) {
         res.sData = arr;
      } else {
         let name = "其他";
         let value = 0;
         let otherList = [];
         arr.splice(4).forEach((v) => {
            value += v.value * 1;
            let percent = (total ? v.value / total : 0).toFixed(4);
            otherList.push({
               name: v.name,
               value: v.value,
               percent: (percent * 100).toFixed(2) + "%"
            });
         });
    if (arr.length <= 5) {
      res.sData = arr;
    } else {
      let name = "其他";
      let value = 0;
      let otherList = [];
      arr.splice(4).forEach((v) => {
        value += v.value * 1;
        let percent = (total ? v.value / total : 0).toFixed(4);
        otherList.push({
          name: v.name,
          value: v.value,
          percent: (percent * 100).toFixed(2) + "%"
        });
      });
         res.sData = arr;
         res.sData.push({ name, value });
      }
      return res;
   }
      res.sData = arr;
      res.sData.push({ name, value });
    }
    return res;
  }
   function updateMap() {
      const getColor = (onLine) => ["#aaa", "#0f0"][onLine];
      let data = lockDatas.value;
      map.value.updateChart(
         data.map((v) => {
            return {
               ...v,
               label: v.lockName,
               color: getColor(v.lockOnline),
               points: [v.longitude, v.latitude],
               // 无实际意义
               value: 100,
            };
         })
      );
   }
  function updateMap() {
    const getColor = (onLine) => ["#aaa", "#0f0"][onLine];
    let data = lockDatas.value;
    map.value.updateChart(
      data.map((v) => {
        return {
          ...v,
          label: v.lockName,
          color: getColor(v.lockOnline),
          points: [v.longitude, v.latitude],
          // 无实际意义
          value: 100,
        };
      })
    );
  }
   function updateUseageRateChart() {
      // 获取当前的日期对象
      let currentDate = new Date();
      // 获取月份数(0 表示一月,11 表示十二月)
      let month = currentDate.getMonth() + 1;
      // 获取季度数
      let quarter = Math.ceil(month / 3);
      let type = rateType.value;
      let _list = rateList.value;
      let list = [];
      switch (type) {
         case 'month':
            list = _list.map(v => ({
               label: v.lockName, value: v['month' + month]
            })).sort((a, b) => b.value - a.value);
            break;
         case 'quarter':
            list = _list.map(v => ({
               label: v.lockName, value: v['quarter' + quarter]
            })).sort((a, b) => b.value - a.value);
            break;
         case 'year':
            list = _list.map(v => ({
               label: v.lockName, value: v.yearCount
            })).sort((a, b) => b.value - a.value);
            break;
      }
  function updateUseageRateChart() {
    // 获取当前的日期对象
    let currentDate = new Date();
    // 获取月份数(0 表示一月,11 表示十二月)
    let month = currentDate.getMonth() + 1;
    // 获取季度数
    let quarter = Math.ceil(month / 3);
    let type = rateType.value;
    let _list = rateList.value;
    let list = [];
    switch (type) {
      case 'month':
        list = _list.map(v => ({
          label: v.lockName, value: v['month' + month]
        })).sort((a, b) => b.value - a.value);
        break;
      case 'quarter':
        list = _list.map(v => ({
          label: v.lockName, value: v['quarter' + quarter]
        })).sort((a, b) => b.value - a.value);
        break;
      case 'year':
        list = _list.map(v => ({
          label: v.lockName, value: v.yearCount
        })).sort((a, b) => b.value - a.value);
        break;
    }
      let labels = list.slice(0, 5).map(v => v.label);
      let datas = list.slice(0, 5).map(v => v.value);
    let labels = list.slice(0, 5).map(v => v.label);
    let datas = list.slice(0, 5).map(v => v.value);
      useageRateChart.value.updateChart(labels, datas);
   }
    useageRateChart.value.updateChart(labels, datas);
  }
</script>
@@ -220,43 +222,38 @@
    <div class="dashboard-left">
      <div class="left-content-list">
        <div class="left-content-item">
          <hdw-card is-full title="屏柜类型">
          <yc-card is-full title="屏柜类型">
            <pie ref="typePie"></pie>
          </hdw-card>
          </yc-card>
        </div>
        <div class="left-content-item">
          <hdw-card is-full title="设备工作状态">
          <yc-card is-full title="设备工作状态">
            <bar ref="testBar" unit="套"></bar>
          </hdw-card>
          </yc-card>
        </div>
        <div class="left-content-item last">
          <hdw-card is-full title="环境状态">
          <yc-card is-full title="环境状态">
            <div class="env">
              <!-- 烟感 -->
              <div class="item">
              <value-panel2 label="烟感" :value="0"></value-panel2>
              <value-panel2 label="温度" unit="℃" color="#efa10b" :value="0"></value-panel2>
              <value-panel2 label="湿度" color="#55c587" :value="0"></value-panel2>
              <!-- <div class="item">
                <div class="label">烟感</div>
                <div class="value">0</div>
              </div>
              <!-- 温度 -->
              <div class="item">
                <div class="label">温度</div>
                <div class="value">0</div>
              </div>
              <!-- 湿度 -->
              <div class="item">
                <div class="label">湿度</div>
                <div class="value">0</div>
              </div>
              </div> -->
            </div>
          </hdw-card>
          </yc-card>
        </div>
      </div>
    </div>
    <div class="dashboard-middle">
      <div class="middle-content-wrapper">
        <hdw-card>
        <yc-card>
          <div class="number-list-wrapper">
            <div class="number-item">
            <value-panel label="机房" :value="stationNum"></value-panel >
            <value-panel label="锁具" color="#efa10b" :value="sumLinf_num"></value-panel >
            <!-- <div class="number-item">
              <div class="number-label">区域</div>
              <div class="number-value">
                <led-num color="#f00" :num="stationNum"></led-num>
@@ -267,7 +264,7 @@
              <div class="number-value">
                <led-num color="#f00" :num="sumLinf_num"></led-num>
              </div>
            </div>
            </div> -->
            <!-- <div class="number-item">
                                  <div class="number-label">电子卡</div>
                                  <div class="number-value">
@@ -275,9 +272,9 @@
                                  </div>
                                </div> -->
          </div>
        </hdw-card>
        </yc-card>
        <div class="map-wrapper">
          <hdw-card is-full>
          <yc-card is-full>
            <map-chart ref="map" @mapMounted="updateMap">
              <template #tools>
                <div class="map-mark">
@@ -292,30 +289,30 @@
                </div>
              </template>
            </map-chart>
          </hdw-card>
          </yc-card>
        </div>
        <div class="dev-real-info">
          <hdw-card title="实时开锁信息" is-full>
            <el-table :data="rtData" style="width: 100%; height: 100%">
          <yc-card title="实时开锁信息" is-full>
            <el-table :data="rtData" stripe  style="width: 100%; height: 100%">
              <el-table-column prop="ctlTime" label="时间" width="180" />
              <el-table-column prop="lockId" label="锁具ID" width="180" />
              <el-table-column prop="lockName" label="锁具名称" />
              <el-table-column prop="state" label="操作状态" />
            </el-table>
          </hdw-card>
          </yc-card>
        </div>
      </div>
    </div>
    <div class="dashboard-right">
      <div class="left-content-list">
        <div class="left-content-item">
          <hdw-card is-full title="屏柜品牌">
          <yc-card is-full title="屏柜品牌">
            <pie ref="prodPie"></pie>
          </hdw-card>
          </yc-card>
  
        </div>
        <div class="left-content-item">
          <hdw-card is-full title="使用频次">
          <yc-card is-full title="使用频次">
            <template #tools>
              <el-radio-group v-model="rateType" size="small">
                <el-radio-button value="month" label="本月"></el-radio-button>
@@ -324,17 +321,17 @@
              </el-radio-group>
            </template>
            <bar ref="useageRateChart" :rotate="30" unit="次"></bar>
          </hdw-card>
          </yc-card>
        </div>
        <div class="left-content-item last">
          <hdw-card is-full title="告警统计">
            <el-table :data="alarmData" style="width: 100%; height: 100%">
          <yc-card is-full title="告警统计">
            <el-table :data="alarmData" stripe  style="width: 100%; height: 100%">
              <el-table-column prop="ctlTime" label="时间" width="160" />
              <el-table-column prop="lockId" label="锁具ID" width="90" />
              <el-table-column prop="lockName" label="锁具名称" />
              <el-table-column prop="state" label="操作状态" />
            </el-table>
          </hdw-card>
          </yc-card>
        </div>
      </div>
    </div>
@@ -348,17 +345,19 @@
  height: 100%;
  .dashboard-left {
    width: 500px;
    height: 100%;
  }
  .dashboard-middle {
    // width: 500px;
    flex: 1;
    height: 100%;
  }
  .dashboard-middle {
    flex: 1.12;
    height: 100%;
  }
  .dashboard-right {
    width: 500px;
    // width: 500px;
    flex: 1;
    height: 100%;
  }
}
@@ -464,29 +463,7 @@
  padding: 10px;
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  align-items: center;
  .item {
    flex: 1;
    border-radius: 8px;
    padding: 4px 8px;
    background: #0ff;
    & + .item {
      margin-left: 20px;
    }
      .label {
        color: #333;
       font-weight: bold;
       margin-bottom: 0.4em;
       text-align: center;
      }
      .value {
        background: #000;
        border-radius: 6px;
        padding: 4px 8px;
        color: #fff;
        font-weight: bold;
        text-align: center;
      }
  }
}
</style>