Files
admin-govern/src/views/govern/analyze/APF/index.vue
2026-01-23 09:24:13 +08:00

471 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="default-main analyze-apf" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree @node-click="nodeClick" @init="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
<div class="analyze-apf-right" v-if="formInline.devId">
<div ref="headerRef">
<TableHeader :showSearch="false" ref="tableHeaderRef" @selectChange="selectChange">
<template v-slot:select>
<el-form-item label="时间:">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="统计指标:">
<el-select
style="width: 200px"
v-model.trim="formInline.statisticalId"
filterable
@change="frequencyFlag"
placeholder="请选择"
>
<el-option
v-for="item in zblist"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-show="frequencyShow">
<el-select
v-model.trim="formInline.frequency"
filterable
placeholder="请选择"
style="width: 100px"
>
<el-option
v-for="item in 49"
:key="item + 1"
:label="item + 1"
:value="item + 1"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="值类型:">
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择">
<el-option
v-for="item in typelist"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="search" icon="el-icon-Search">查询</el-button>
<el-button :type="timeControl ? 'primary' : ''" icon="el-icon-Sort" @click="setTimeControl">
缺失数据
</el-button>
</template>
</TableHeader>
</div>
<el-empty description="暂无数据" v-if="!echartsData" style="flex: 1"></el-empty>
<template v-else>
<div :style="echartHeight">
<MyEchart :options="echartsData" />
</div>
</template>
</div>
<el-empty v-else description="请选择设备" class="analyze-apf-right" />
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { mainHeight } from '@/utils/layout'
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
import { getDevCapacity } from '@/api/cs-device-boot/capacity'
import { queryCommonStatisticalByTime } from '@/api/cs-harmonic-boot/stable'
import DatePicker from '@/components/form/datePicker/index.vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { yMethod, completeTimeSeries } from '@/utils/echartMethod'
import TableHeader from '@/components/table/header/index.vue'
const timeControl = ref(false)
defineOptions({
name: 'govern/analyze/APF'
})
const tableHeaderRef = ref()
const headerRef = ref()
const pageHeight = mainHeight(20)
const echartHeight = ref(mainHeight(80))
const loading = ref(false)
const echartsData = ref<any>(null)
const datePickerRef = ref()
const formInline = reactive({
statisticalId: '',
valueType: '',
startTime: '',
endTime: '',
devId: '',
frequency: ''
})
const dataLists = ref<any[]>([])
const timeFlag = ref(true)
const frequencyShow = ref(false)
const devCapacity = ref(0)
const flag = ref(false)
const typelist = [
{
label: '平均值',
value: 'avg'
},
{
label: '最大值',
value: 'max'
},
{
label: '最小值',
value: 'min'
},
{
label: 'CP95值',
value: 'cp95'
}
]
const zblist = ref<any[]>([])
const init = () => {
return new Promise((resolve, reject) => {
queryByCode('Web_Apf').then(res => {
queryCsDictTree(res.data?.id).then(res => {
zblist.value = res.data.map((item: any) => {
return {
value: item.id,
label: item.name,
...item
}
})
formInline.statisticalId = zblist.value[0]?.value
formInline.valueType = typelist[0].value
resolve(null)
})
})
})
}
const deviceTypeChange = (val: any, obj: any) => {
flag.value = true
nodeClick(obj)
}
const nodeClick = async (e: anyObj) => {
if (e.level == 2 && flag.value) {
formInline.devId = e.id
loading.value = true
if (zblist.value.length === 0) {
await init()
}
getDevCapacity(formInline.devId)
.then(res => {
devCapacity.value = res.data
search()
})
.catch(() => {
loading.value = false
})
}
}
const lineStyle = [
{ type: 'solid', width: 3 },
{ type: 'dotted', width: 3 },
{ type: 'dashed', width: 3 }
]
const search = () => {
if (timeFlag.value) {
datePickerRef.value && datePickerRef.value.setInterval(5)
timeFlag.value = false
}
loading.value = true
formInline.startTime = datePickerRef.value.timeValue[0]
formInline.endTime = datePickerRef.value.timeValue[1]
if (!frequencyShow.value) {
formInline.frequency = ''
}
queryCommonStatisticalByTime(formInline)
.then(({ data }: { data: any[] }) => {
dataLists.value = data
setEchart()
loading.value = false
})
.catch(() => {
loading.value = false
})
}
const setEchart = () => {
loading.value = true
let data = JSON.parse(JSON.stringify(dataLists.value))
if (data.length) {
let list = processingOfData(data, 'unit')
echartsData.value = {}
let legend: any[] = []
let xAxis: any[] = []
let yAxis: any[] = []
let series: any[] = []
let color: any[] = []
let title = ''
data.forEach(item => {
if (!xAxis.includes(item.time)) {
xAxis.push(item.time)
}
// if (!legend.includes(item.anotherName)) {
// legend.push(item.anotherName)
// }
})
let units = Object.keys(list)
// console.log('🚀 ~ .then ~ units:', units)
for (let unit in list) {
console.log('🚀 ~ .then ~ unit:', unit)
let [min, max] = yMethod(list[unit].map((item: any) => item.statisticalData))
yAxis.push({
name: unit == 'null' ? '' : unit,
type: 'value',
// max: 10,
min: min,
max: max,
// splitNumber: 5,
// minInterval: 1,
axisLine: {
show: true,
//symbol: ["none", "arrow"],
lineStyle: {
color: '#333'
}
}
})
// processingOfData(list[unit], 'anotherName')
let anotherList = processingOfData(list[unit], 'anotherName')
for (let k in anotherList) {
title = k
let lineName = lineStyle[Object.keys(anotherList).indexOf(k)]
let phaseList = processingOfData(anotherList[k], 'phase')
for (let j in phaseList) {
color.push(j == 'A' ? '#DAA520' : j == 'B' ? '#2E8B57' : j == 'C' ? '#A52a2a' : '#0000CC')
legend.push(
j == 'M' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j
)
series.push({
name: j == 'M' ? k : j == 'A' ? `A相_${k}` : j == 'B' ? `B相_${k}` : j == 'C' ? `C相_${k}` : j,
symbol: 'none',
smooth: true,
type: 'line',
// data: phaseList[j].map(item => [
// item.time,
// Math.floor(item.statisticalData * 100) / 100,
// unit,
// lineName.type
// ]),
data: timeControl.value
? completeTimeSeries(
phaseList[j].map(item => [
item.time,
Math.floor(item.statisticalData * 100) / 100,
unit,
lineName.type
])
)
: phaseList[j].map(item => [
item.time,
Math.floor(item.statisticalData * 100) / 100,
unit,
lineName.type
]),
lineStyle: lineName,
yAxisIndex: unit.indexOf(units)
})
}
}
}
echartsData.value = {
title: {
text: zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
},
tooltip: {
axisPointer: {
type: 'cross',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0,
formatter(params: any) {
const xname = params[0].value[0]
let str = `${xname}<br>`
params.forEach((el: any, index: any) => {
let marker = ''
if (el.value[3] == 'dashed') {
for (let i = 0; i < 3; i++) {
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
}
} else {
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
}
str += `${marker}${el.seriesName.split('(')[0]}${
el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == 'null' ? '' : el.value[2]) : '-'
}<br>`
})
return str
}
},
legend: {
itemWidth: 20,
itemHeight: 20,
itemStyle: { opacity: 0 }, //去圆点
type: 'scroll', // 开启滚动分页
top: 25
// data: legend
},
grid: {
left: '20px',
right: '40px',
bottom: '50px',
top: '80px',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
color: color,
xAxis: {
name: '',
type: 'time',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
// boundaryGap: false,
// data: xAxis,
// axisLabel: {
// formatter: function (value: string) {
// return value.split(' ').join('\n')
// }
// },
// axisLine: {
// show: true,
// // symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// }
},
yAxis: yAxis,
// [
// {
// name: '畸变率:(%)',
// type: 'value',
// // max: 10,
// min: min1,
// max: max1,
// splitNumber: 5,
// minInterval: 1,
// axisLine: {
// show: true,
// //symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// }
// },
// {
// name: '电流:(A)',
// type: 'value',
// min: min,
// max: max,
// splitNumber: 5,
// minInterval: 1,
// splitLine: {
// show: false
// },
// axisLine: {
// show: true,
// //symbol: ["none", "arrow"],
// lineStyle: {
// color: '#333'
// }
// }
// }
// ],
options: {
series: series
}
}
} else {
echartsData.value = null
}
loading.value = false
}
const setTimeControl = () => {
timeControl.value = !timeControl.value
setEchart()
}
const processingOfData = (data: any, type: string) => {
let groupedData: any = {}
data.forEach(item => {
if (!groupedData[item[type]]) {
groupedData[item[type]] = []
}
groupedData[item[type]].push(item)
})
return groupedData
}
const frequencyFlag = () => {
let name = zblist.value.filter(item => item.id == formInline.statisticalId)[0].name
if (name.includes('含有率') || name.includes('幅值')) {
frequencyShow.value = true
formInline.frequency = 2
} else {
frequencyShow.value = false
}
tableHeaderRef.value && tableHeaderRef.value?.computedSearchRow()
}
const selectChange = (flag: boolean) => {
setTimeout(() => {
echartHeight.value = mainHeight(23 + headerRef.value.offsetHeight)
}, 100)
}
</script>
<style lang="scss">
.analyze-apf {
display: flex;
&-right {
height: 100%;
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
display: flex;
flex-direction: column;
}
}
</style>
<style lang="scss" scoped>
.el-select {
min-width: 100px;
}
</style>