<script lang="ts" setup name="Statistics"> import { getCurrentInstance, ref } from 'vue' import type { Ref } from 'vue' import type { DateModelType } from 'element-plus' import dayjs from 'dayjs' import type { MonitorListInfo, StationListInfo } from '../alarm/alarm-interface' import type { DateReturn, ITableData, TypeReturn } from './statistics-interface' import LineChart from '@/components/Echart/LineChart.vue' import BarChartHorizontal from '@/components/Echart/BarChartHorizontal.vue' import BarChartVertical from '@/components/Echart/BarChartVertical.vue' import type { lineDataI } from '@/components/Echart/echart-interface' import { getAlarmDateStatistics, getAlarmTypeStatistics, getStationStatistics } from '@/api/ptz/statistics' import { getStationList } from '@/api/ptz/station' import { getDevList } from '@/api/ptz/dev' // 每个展示块高度 const blockHeight = ref(300) const blockWidth = ref(400) const devTableLoading = ref(false) const devBarLoading = ref(false) const alarmDateLoading = ref(false) const alarmTypeLoading = ref(false) const timeRange = ref<[DateModelType, DateModelType]>(['', '']) // 默认查询条件 const defaultQuery = { stationId: '', monitorId: '', startTime: '', endTime: '', } const listQuery = reactive({ ...defaultQuery }) const stationList: Ref<StationListInfo[]> = ref([]) const monitorList: Ref<MonitorListInfo[]> = 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 devBarData: Ref<lineDataI[]> = ref([]) const devBarYDataMax = ref() const alarmDateXData: Ref<string[]> = ref([]) const alarmDateData: Ref<lineDataI[]> = ref([]) const alarmDateYDataMax = ref() const alarmTypeXData: Ref<string[]> = ref([]) const alarmTypeData: Ref<lineDataI[]> = ref([]) const alarmTypeYDataMax = ref() function fetchStationList() { getStationList().then((res) => { stationList.value = res.data }) } function changeStation() { listQuery.monitorId = '' getDevList(listQuery.stationId).then((res) => { monitorList.value = res.data }) } function getDevData() { devTableLoading.value = true devBarLoading.value = true getStationStatistics().then((res) => { devTableData.value = res.data const tValue = res.data.map((item: ITableData) => Number(item.total)) const onValue = res.data.map((item: ITableData) => Number(item.online)) const offValue = res.data.map((item: ITableData) => Number(item.offline)) // devBarYDataMax.value = Math.max(tValue) //> 10 ? Math.max(tValue) : 10 console.log(Math.max(tValue)) devBarData.value = [{ name: '在线', data: onValue }, { name: '离线', data: offValue }] devBarXData.value = res.data.map((item: ITableData) => item.stationName) devTableLoading.value = false devBarLoading.value = false }) // const res = [{ // stationId: '111', // stationName: '场站一', // total: '22', // online: '11', // offline: '3' // }, { // stationId: '112', // stationName: '场站二', // total: '33', // online: '21', // offline: '11' // }] // devTableData.value = res // const tValue = res.map((item: ITableData) => Number(item.total)) // const onValue = res.map((item: ITableData) => Number(item.online)) // const offValue = res.map((item: ITableData) => Number(item.offline)) // devBarYDataMax.value = Math.max(tValue) > 10 ? Math.max(tValue) : 10 // devBarData.value = [{ name: '在线', data: onValue, color: '#543211' }, { name: '离线', data: offValue }] // devBarXData.value = res.map((item: ITableData) => item.stationName) // devTableLoading.value = false // devBarLoading.value = false } function getAlarmDate() { alarmDateLoading.value = true getAlarmDateStatistics(listQuery).then((res) => { const yValue = res.data.map((item: DateReturn) => Number(item.num)) alarmDateYDataMax.value = Math.max(yValue) > 10 ? Math.max(yValue) : 10 alarmDateXData.value = res.data.map((item: TypeReturn) => item.date) alarmDateData.value = [{ name: '报警数', data: yValue }] alarmDateLoading.value = false }) } function getAlarmType() { alarmTypeLoading.value = true getAlarmTypeStatistics(listQuery).then((res) => { const yValue = res.data.map((item: TypeReturn) => Number(item.num)) alarmTypeYDataMax.value = Math.max(yValue) > 10 ? Math.max(yValue) : 10 alarmTypeXData.value = res.data.map((item: TypeReturn) => item.type) alarmTypeData.value = [{ name: '报警数', data: yValue }] alarmTypeLoading.value = false }) } // 搜索按钮 function search() { if (timeRange.value) { listQuery.startTime = timeRange.value[0] as string || '' listQuery.endTime = timeRange.value[1] as string || '' } getAlarmDate() getAlarmType() } // 搜索重置 function clear() { Object.assign(listQuery, defaultQuery) listQuery.startTime = dayjs(Date.now() - 7 * 24 * 60 * 60 * 1000).format('YYYY-MM-DD HH:mm:ss') listQuery.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss') timeRange.value = [listQuery.startTime, listQuery.endTime] search() } function calcBlockSize() { // 计算工作台区域高度 - 顶部-面包屑-边距 const bodyHeight = document.body.clientHeight - 60 - 50 - 20 blockHeight.value = bodyHeight > 610 ? (bodyHeight - 10) / 2 : 300 blockWidth.value = (document.body.clientWidth - 180 - 20 - 20) } window.addEventListener('resize', () => { calcBlockSize() }) onBeforeMount(() => { calcBlockSize() }) onMounted(() => { getDevData() listQuery.startTime = dayjs(Date.now() - 7 * 24 * 60 * 60 * 1000).format('YYYY-MM-DD HH:mm:ss') listQuery.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss') timeRange.value = [listQuery.startTime, listQuery.endTime] fetchStationList() search() }) </script> <template> <app-container> <div class="device-bench"> <el-row :gutter="10"> <el-col :span="10"> <bench-col v-loading="devBarLoading" icon="icon-bar1" title="设备统计" :height="blockHeight"> <bar-chart-horizontal :x-axis-data="devBarXData" :width="`${blockWidth * 10 / 24 - 10}px`" :data="devBarData" :max="devBarYDataMax" /> </bench-col> </el-col> <el-col :span="14"> <search-area @search="search"> <search-item> <el-select v-model="listQuery.stationId" placeholder="所在场站" clearable style="width: 130px;" @change="changeStation" > <el-option v-for="item in stationList" :key="item.id" :label="item.stationName" :value="item.id" /> </el-select> </search-item> <search-item> <el-select v-model="listQuery.monitorId" clearable style="width: 160px;" :disabled="listQuery.stationId === ''" :placeholder="listQuery.stationId === '' ? '请先选择所在场站' : '选择设备'" > <el-option v-for="item in monitorList" :key="item.id" :label="item.monitorName" :value="item.id" /> </el-select> </search-item> <search-item> <el-date-picker v-model="timeRange" type="datetimerange" range-separator="到" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始时间" end-placeholder="结束时间" style="width: 350px;" :clearable="false" /> </search-item> </search-area> <bench-col v-loading="alarmDateLoading" icon="icon-line" title="报警趋势分析" :height="`${blockHeight - 45}px`" style="margin-top: -10px;" > <line-chart :x-axis-data="alarmDateXData" :width="`${blockWidth * 14 / 24 - 10}px`" :data="alarmDateData" unit="次" /> </bench-col> </el-col> </el-row> </div> <div class="device-bench" style="margin-top: 10px;"> <el-row :gutter="10"> <el-col :span="8"> <bench-col v-loading="devTableLoading" icon="icon-book" title="设备统计" path-url="" :style="{ height: blockHeight }" :height="blockHeight" > <el-table :data="devTableData" :height="blockHeight - 60" style="width: 100%; height: 100%;" stripe header-row-class-name="bench-table-header" row-class-name="bench-table-row" class="bench-table" > <el-table-column v-for="item in devTableHead" :key="item.value" :prop="item.value" align="center" :label="item.text" :width="item.width" /> </el-table> </bench-col> </el-col> <el-col :span="16"> <bench-col v-loading="alarmTypeLoading" icon="icon-bar" title="各类报警统计" :height="blockHeight"> <bar-chart-vertical :x-axis-data="alarmTypeXData" :width="`${blockWidth * 16 / 24 - 10}px`" :data="alarmTypeData" 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; } </style>