<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>