<!-- Description: 首页 Author: 李亚光 Date: 2025-03-19 --> <script lang="ts" setup name="Dashboard"> import deviceMonitor from './deviceMonitor.vue' import { getMonitorStatistics } from '@/api/home/dashboard/index' const $router = useRouter() const { proxy } = getCurrentInstance() as any const pageWidth = ref(0) // 页面宽度 const calcWidth = () => { // 侧边栏宽度 const siderBar = document.getElementsByClassName('sidebar-container')[0] // 报警按钮宽度 const alarmWidth = proxy.hasPerm('/alarm/current') ? 100 : 0 // 页面布局总宽度 pageWidth.value = window.innerWidth - (siderBar?.offsetWidth || 0) - alarmWidth - 20 - 35 } // 跳转当前报警 const currentAlarm = () => { $router.push({ path: '/alarm/current', }) } // 泄漏监测概括数据 const leakageData = ref({ total: '0', normal: '0', alarm: '0', exception: '0', off: '0' }) // 防外力破坏监测概况数据 const forceData = ref({ total: '0', normal: '0', alarm: '0', exception: '0', off: '0' }) // 隐患监测概况数据 const hiddenData = ref([ { name: '穿越缺陷点', total: '0', normal: '0', alarm: '0', exception: '0', off: '0', value: '1', }, { name: '占压隐患点', total: '0', normal: '0', alarm: '0', exception: '0', off: '0', value: '2', }, { name: '应急监测点', total: '0', normal: '0', alarm: '0', exception: '0', off: '0', value: '3', }, ]) const loading = ref(false) // 获取数据 const fetchData = () => { loading.value = true getMonitorStatistics().then(res => { // 整理数据 const data = res.data for (const i in data) { // 泄漏监测概括数据 for (const y in leakageData.value) { if (i.toLocaleLowerCase().includes('leak') && i.toLocaleLowerCase().includes(y)) { leakageData.value[y] = data[i] } } leakageData.value.off = '958' leakageData.value.total = Number(leakageData.value.off) + Number(leakageData.value.normal) + Number(leakageData.value.alarm) + Number(leakageData.value.exception) // 防外力破坏监测概况数据 for (const y in forceData.value) { if (i.toLocaleLowerCase().includes('damage') && i.toLocaleLowerCase().includes(y)) { forceData.value[y] = data[i] } } // 隐患监测概况数据 for (const y in hiddenData.value) { for (const x in hiddenData.value[y]) { if (i.toLocaleLowerCase().includes('hazard') && i.includes(hiddenData.value[y].value) && i.toLocaleLowerCase().includes(x)) { hiddenData.value[y][x] = data[i] } } } } loading.value = false }).catch(() => { loading.value = false }) } calcWidth() onMounted(() => { fetchData() calcWidth() }) window.addEventListener('resize', calcWidth) onBeforeUnmount(() => { window.removeEventListener('resize', calcWidth) }) </script> <template> <!-- 布局 --> <app-container> <!-- 顶部信息统计 --> <div class="top-container"> <!-- 泄漏监测概况 --> <el-card class="box-card" :style="{ width: pageWidth / 5 + 'px' }"> <template #header> <div class="card-header"> 泄漏监测概况 </div> </template> <div v-loading="loading" class="card-body"> <div class="body-left"> <div class="left-title">监控总数</div> <div class="left-value">{{ leakageData.total }}</div> </div> <div class="body-right"> <div class="right-item"> <div class="item-title"> <span class="normal"></span> <span style="margin-left: 5px;">正常</span> </div> <div class="item-value">{{ leakageData.normal }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="alarm"></span> <span style="margin-left: 5px;">报警</span> </div> <div class="item-value">{{ leakageData.alarm }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="exception"></span> <span style="margin-left: 5px;">故障</span> </div> <div class="item-value">{{ leakageData.exception }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="off"></span> <span style="margin-left: 5px;">离线</span> </div> <div class="item-value">{{ leakageData.off }}</div> </div> </div> </div> </el-card> <!-- 防外力破坏监测概况 --> <el-card class="box-card" :style="{ width: pageWidth / 5 + 'px' }"> <template #header> <div class="card-header"> 防外力破坏监测概况 </div> </template> <div v-loading="loading" class="card-body"> <div class="body-left"> <div class="left-title">监控总数</div> <div class="left-value">{{ forceData.total }}</div> </div> <div class="body-right"> <div class="right-item"> <div class="item-title"> <span class="normal"></span> <span style="margin-left: 5px;">正常</span> </div> <div class="item-value">{{ forceData.normal }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="alarm"></span> <span style="margin-left: 5px;">报警</span> </div> <div class="item-value">{{ forceData.alarm }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="exception"></span> <span style="margin-left: 5px;">故障</span> </div> <div class="item-value">{{ forceData.exception }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="off"></span> <span style="margin-left: 5px;">离线</span> </div> <div class="item-value">{{ forceData.off }}</div> </div> </div> </div> </el-card> <!-- 隐患监测概况 --> <el-card class="box-card" :style="{ width: (pageWidth / 5) * 3 + 'px' }"> <template #header> <div class="card-header"> 隐患监测概况 </div> </template> <div v-loading="loading" class="card-body"> <div class="multiple-item" v-for="item in hiddenData" :key="item.name" :style="{ width: '33%' }"> <div class="body-left"> <div class="left-title">{{ item.name }}</div> <div class="left-value">{{ item.total }}</div> </div> <div class="body-right"> <div class="right-item"> <div class="item-title"> <span class="normal"></span> <span style="margin-left: 5px;">正常</span> </div> <div class="item-value">{{ item.normal }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="alarm"></span> <span style="margin-left: 5px;">报警</span> </div> <div class="item-value">{{ item.alarm }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="exception"></span> <span style="margin-left: 5px;">故障</span> </div> <div class="item-value">{{ item.exception }}</div> </div> <div class="right-item"> <div class="item-title"> <span class="off"></span> <span style="margin-left: 5px;">离线</span> </div> <div class="item-value">{{ item.off }}</div> </div> </div> </div> </div> </el-card> <!-- 当前报警按钮 --> <el-button v-if="proxy.hasPerm('/alarm/current')" class="alarm-btn" type="danger" @click="currentAlarm"> <!-- {{ `当前<br />报警` }} --> <span class="alarm-btn-text">当 前 <br /><br />报 警</span> </el-button> </div> <!-- 设备监控 --> <deviceMonitor /> </app-container> </template> <style lang="scss" scoped> .top-container { width: 100%; height: 150px; // border: 1px solid #000; display: flex; margin-top: 6px; justify-content: space-between; overflow: hidden; ::v-deep(.el-card__body) { padding: 0; } ::v-deep(.el-card__header) { padding: 0; } .normal { color: transparent; display: inline-block; width: 5px; height: 5px; background-color: #00B011; border-radius: 50%; } .alarm { color: transparent; display: inline-block; width: 5px; height: 5px; background-color: #f56c6c; border-radius: 50%; } .exception { color: transparent; display: inline-block; width: 5px; height: 5px; background-color: #FFBA00; border-radius: 50%; } .off { color: transparent; display: inline-block; width: 5px; height: 5px; background-color: #999999; border-radius: 50%; } .box-card { .card-header { text-align: center; font-weight: 700; color: #666; font-size: 18px; padding: 8px 0; } .card-body { display: flex; padding: 8px; .multiple-item { display: flex; } .body-left { width: 33%; display: flex; flex-direction: column; align-items: center; justify-content: space-around; border-right: 1px solid #e4e7ed; padding-top: 8px; padding-bottom: 8; .left-title { color: #A2A2A2; font-weight: 700; } .left-value { color: #0D76D4; font-weight: 700; font-size: 26px; } } .body-right { width: 66%; display: flex; flex-wrap: wrap; align-items: center; .right-item { width: 50%; text-align: center; color: #A2A2A2; .item-title { display: flex; align-items: center; justify-content: center; } .item-value { font-size: 18px; color: #666870; margin-top: 3px; } } } } } .alarm-btn { font-size: 22px; width: 100px; font-weight: 700; height: 150px; } } </style>