<script lang="ts" setup name="Statistics" xmlns=""> import { getCurrentInstance, ref } from 'vue' import type { Ref } from 'vue' import type { DateModelType } from 'element-plus' import type { DateReturn, ITableData, TypeReturn } from './statistics-interface' import LineChart from '@/components/Echart/LineChart.vue' import BarChartHorizontal from '@/components/Echart/BarChartHorizontal.vue' import type { lineDataI } from '@/components/Echart/echart-interface' import { areaDev, areaDevOnline, dayDev, getTotal } from '@/api/ycjg/statistics' import PieChart from '@/components/Echart/PieChart.vue'; import sbzxs from '@/assets/images/ycjg/设备在线数.png' import sbzs from '@/assets/images/ycjg/设备总数.png' import sblxl from '@/assets/images/ycjg/设备离线率.png' import BarChartVertical from "@/components/Echart/BarChartVertical.vue"; // 每个展示块高度 const blockHeight = ref(300) const blockWidth = ref(400) const onlineBarLoading = ref(false) const devBarLoading = ref(false) const areaPieLoading = ref(false) const onlineLineLoading = ref(false) const list = ref({ devTotal: '****', onlineNum: '****', onlineRate: '****', }) const showType = ref('柱状图') const timeRange = ref<[DateModelType, DateModelType]>(['', '']) // 默认查询条件 const defaultQuery = { stationId: '', monitorId: '', startTime: '', endTime: '', } const listQuery = reactive({ ...defaultQuery }) const stationList: Ref<any[]> = ref([]) const monitorList: Ref<any[]> = ref([]) const devTableData = ref<ITableData[]>([]) // 设备台账检定提醒表头 const devTableHead = [ { text: '场站名称', value: 'stationName', width: '180' }, { text: '云台数量', value: 'total' }, { text: '在线', value: 'online' }, { text: '离线', value: 'offline' }, ] const total = ref(20) const devBarXData: Ref<string[]> = ref([]) const onlineBarXData: Ref<string[]> = ref([]) const devBarData: Ref<lineDataI[]> = ref([]) const onlineBarData: Ref<lineDataI[]> = ref([]) const devBarYDataMax = ref() const onlineBarYDataMax = ref() const onlineLineDateXData: Ref<string[]> = ref([]) const onlineLineDateData: Ref<lineDataI[]> = ref([]) const alarmDateYDataMax = ref() const alarmTypeXData: Ref<string[]> = ref([]) const alarmTypeData: Ref<lineDataI[]> = ref([]) const alarmTypeYDataMax = ref() const areaPieData: Ref<any[]> = ref([]) function getDevData() { devBarLoading.value = true areaPieLoading.value = true areaDev().then((res) => { const value = res.data.map((item: any) => Number(item.value)) devBarData.value = [{ name: '设备数量', data: value }] devBarYDataMax.value = Math.max(value) > 10 ? Math.max(value) : 10 devBarXData.value = res.data.map((item: any) => item.areaName) areaPieData.value = res.data.map((item: any) => { return { name: item.areaName, value: Number(item.value), } }) devBarLoading.value = false areaPieLoading.value = false }) } function getAreaDevOnline() { onlineBarLoading.value = true areaDevOnline().then((res) => { const value = res.data.map((item: any) => Number(item.value)) onlineBarData.value = [{ name: '设备在线数量', data: value }] onlineBarYDataMax.value = Math.max(value) > 10 ? Math.max(value) : 10 onlineBarXData.value = res.data.map((item: any) => item.areaName) onlineBarLoading.value = false }) } function getDayDev() { onlineLineLoading.value = true dayDev().then((res) => { const onlineValue = res.data.map((item: any) => Number(item.online)) const offlineValue = res.data.map((item: any) => Number(item.offline)) onlineLineDateXData.value = res.data.map((item: any) => item.date) onlineLineDateData.value = [{ name: '离线设备', data: offlineValue }, { name: '在线设备', data: onlineValue }] onlineLineLoading.value = false }) } function calcBlockSize() { // 计算工作台区域高度 - 顶部-面包屑-边距 const bodyHeight = document.body.clientHeight - 60 - 50 - 20 blockHeight.value = (bodyHeight - 100) / 2 blockWidth.value = (document.body.clientWidth - 180 - 20 - 20) } window.addEventListener('resize', () => { calcBlockSize() }) onBeforeMount(() => { calcBlockSize() }) onMounted(() => { getTotal().then((res) => { if (res.code === 200) { list.value = res.data if (list.value.onlineNum === '' || list.value.onlineNum === null || list.value.onlineNum === undefined) { list.value.onlineNum = '0' } // list.value.rate = (Number(list.value.onlineNum) / Number(list.value.devTotal) * 100).toFixed(2) // if (Number.isNaN(list.value.rate)) { // list.value.rate = '****' // } } }) getDevData() getAreaDevOnline() getDayDev() }) </script> <template> <app-container style="background-color: white;overflow: hidden"> <div style="display: flex;height: 90px;text-align: center;width: 100%;justify-content: space-evenly"> <div class="item"> <el-image :src="sbzs" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;">设备总数</div> <div class="num">{{ list.devTotal }}<span class="unit">台</span></div> </div> </div> <div class="item"> <el-image :src="sbzxs" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;">设备在线数</div> <div class="num">{{ list.onlineNum }}<span class="unit">台</span></div> </div> </div> <div class="item"> <el-image :src="sblxl" class="base-map-image" mode="fill" /> <div class="item-text"> <div style="color: #0f67e7;">设备在线率</div> <div class="num">{{ list.onlineRate }}<span class="unit">%</span></div> </div> </div> </div> <div class="device-bench"> <el-row :gutter="10"> <el-col :span="8"> <bench-col v-loading="devBarLoading" icon="icon-bar" title="各地区设备数量" :height="blockHeight"> <bar-chart-vertical style="margin-top: -20px" unit="台" title="各地区设备数量" :x-axis-data="devBarXData" :width="`${blockWidth / 3 - 10}px`" :height="`${blockHeight - 30}px`" :data="devBarData" :max="devBarYDataMax" /> </bench-col> </el-col> <el-col :span="8"> <bench-col v-loading="onlineBarLoading" icon="icon-bar" title="各地区设备在线情况" :height="blockHeight"> <bar-chart-horizontal style="margin-top: -20px" unit="台" title="各地区设备在线情况" :x-axis-data="onlineBarXData" :width="`${blockWidth / 3 - 10}px`" :height="`${blockHeight - 30}px`" :data="onlineBarData" :max="onlineBarYDataMax" /> </bench-col> </el-col> <el-col :span="8"> <bench-col v-loading="areaPieLoading" icon="icon-pie" title="设备区域分布情况" :height="blockHeight"> <pie-chart title="设备区域分布情况" style="margin-top: -20px;" unit="台" :data="areaPieData" :radius="['0%', '70%']" :width="`${blockWidth / 3 - 10}px`" :height="`${blockHeight - 30}px`" /> </bench-col> </el-col> </el-row> </div> <div class="device-bench" style="margin-top: 10px;"> <el-row :gutter="10"> <el-col :span="24"> <bench-col v-loading="onlineLineLoading" icon="icon-line" title="设备在线趋势" :height="blockHeight"> <line-chart :x-axis-data="onlineLineDateXData" :width="`${blockWidth - 10}px`" :data="onlineLineDateData" unit="台" /> </bench-col> </el-col> </el-row> </div> </app-container> </template> <style lang="scss" scoped> .device-bench { width: 100%; height: 100%; box-sizing: border-box; .the-month-total-Data { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: space-around; padding: 0 20px; .title { display: flex; justify-content: space-between; font-weight: 500; margin-bottom: 3px; } .content { width: 100%; .item { display: flex; flex-direction: column; flex: 1; margin-right: 10px; padding: 3px 0; justify-content: center; align-items: center; background-image: linear-gradient(to bottom, #e9f5ff, #3d7eff); border-radius: 8px; &:last-child { margin-right: 0; } } } } .my-equipment { height: 100%; display: flex; flex-direction: column; justify-content: space-around; padding: 20px; .item { height: 40%; display: flex; flex-direction: column; justify-content: center; align-items: center; background-image: linear-gradient(to right, #caddff, #3d7eff); border-radius: 16px; } } } </style> <style lang="scss"> .bench-table { .el-table__header-wrapper { border-radius: 8px; } } .bench-table-header { th { font-weight: normal; font-size: 14px; } } .bench-table-row { border-radius: 8px; } .item{ background-color: #e7f1fd; width: 300px; display: flex; justify-content: left; align-items: center; height: 80px; border-radius: 10px; border: 2px solid #398bff; } .num{ text-shadow: 0 0 5px #0f67e7; color: #0f67e7; font-size: 30px; padding-top: 2px; font-weight: bold; } .unit{ color: #0f67e7; font-size: 14px; margin-left: 3px; } .item-text{ text-shadow: 0 0 2px #0f67e7; flex: 1; text-align: center; font-size: 18px; } .base-map-image{ width: 60px; height: 60px; margin-left: 20px; } </style>