Files
admin-govern/src/components/cockpit/listOfMainMonitoringPoints/index.vue
2025-11-18 14:21:31 +08:00

593 lines
21 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>
<!--指标拟合图 -->
<TableHeader :showReset="false" datePicker @selectChange="selectChange" v-if="fullscreen">
<template v-slot:select>
<el-form-item label="监测点">
<el-select
v-model="tableStore.table.params.lineId"
placeholder="请选择监测点"
clearable
style="width: 130px"
>
<el-option
v-for="item in lineList"
:key="item.lineId"
:label="item.name"
:value="item.lineId"
/>
</el-select>
</el-form-item>
<el-form-item label="用户功率">
<el-select
v-model="tableStore.table.params.power"
placeholder="请选择用户功率"
clearable
style="width: 130px"
>
<el-option v-for="item in powerList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="统计类型">
<el-select
style="min-width: 120px !important"
placeholder="请选择"
v-model="tableStore.table.params.valueType"
>
<el-option value="max" label="最大值"></el-option>
<el-option value="min" label="最小值"></el-option>
<el-option value="avg" label="平均值"></el-option>
<el-option value="cp95" label="cp95"></el-option>
</el-select>
</el-form-item>
<el-form-item label="电能质量指标">
<el-select
v-model="tableStore.table.params.indicator"
placeholder="请选择电能质量指标"
clearable
style="width: 130px"
>
<el-option v-for="item in indicatorList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<!-- <el-form-item label="越限情况">
<el-select
v-model="tableStore.table.params.exceedingTheLimit"
placeholder="请选择越限情况"
clearable
style="width: 90px"
>
<el-option
v-for="item in exceedingTheLimitList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item> -->
<el-form-item>
<div v-if="shouldShowHarmonicCount()">
<span class="mr12">{{ getHarmonicTypeName() }}谐波次数</span>
<el-select
v-model="tableStore.table.params.harmonicCount"
placeholder="请选择谐波次数"
style="width: 100px"
class="mr20"
>
<el-option
v-for="num in harmonicCountOptions"
:key="num"
:label="num"
:value="num"
></el-option>
</el-select>
</div>
</el-form-item>
</template>
</TableHeader>
<div v-loading="loading">
<my-echart
class="tall"
:options="echartList"
:style="{
width: prop.width,
height: `calc(${prop.height} - ${headerHeight}px + ${fullscreen ? 0 : 56}px )`
}"
v-if="showEchart"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, watch, h, computed, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { useConfig } from '@/stores/config'
import { useRoute } from 'vue-router'
import { useTimeCacheStore } from '@/stores/timeCache'
import { cslineList, fittingData } from '@/api/harmonic-boot/cockpit/cockpit'
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
import { queryStatistical } from '@/api/system-boot/csstatisticalset'
import { color } from '@/components/echarts/color'
import { ElMessage } from 'element-plus'
const prop = defineProps({
w: { type: [String, Number] },
h: { type: [String, Number] },
width: { type: [String, Number] },
height: { type: [String, Number] },
timeKey: { type: [String, Number] },
timeValue: { type: Object }
})
const config = useConfig()
const lineList: any = ref()
const powerList: any = ref()
const countData: any = ref([])
const countDataCopy: any = ref([])
const showEchart = ref(true)
const chartsList = ref<any>([])
const loading = ref(false)
// 计算是否全屏展示
const fullscreen = computed(() => {
const w = Number(prop.w)
const h = Number(prop.h)
if (!isNaN(w) && !isNaN(h) && w === 12 && h === 6) {
// 执行相应逻辑
return true
} else {
return false
}
})
const exceedingTheLimitList: any = ref([
{
label: '越限',
value: '1'
},
{
label: '不越限',
value: '0'
}
])
const indicatorList = ref()
const initLineList = async () => {
cslineList({}).then(res => {
lineList.value = res.data
if (lineList.value && lineList.value.length > 0) {
tableStore.table.params.lineId = lineList.value[0].lineId
}
})
}
// 判断下拉框是否存在
const onCountChange = (val: any, index: any) => {
if (val.length == 0) {
countData.value[index].count = countData.value[index].countOptions[0]
}
}
const echartList = ref()
// const echartList = ref({
// title: {
// text: '谐波电压总畸变率越限与功率负荷曲线拟合图'
// },
// xAxis: {
// type: 'time',
// axisLabel: {
// formatter: {
// day: '{MM}-{dd}',
// month: '{MM}',
// year: '{yyyy}'
// }
// }
// },
// yAxis: [{}, {}],
// grid: {
// left: '10px',
// right: '20px'
// },
// options: {
// series: [
// {
// // name: '暂降次数',
// type: 'bar',
// name: '有功功率',
// // data: [
// // ['2025-10-16 07:00:00', 10],
// // ['2025-10-16 07:15:00', 10],
// // ['2025-10-16 07:30:00', 10],
// // ['2025-10-16 07:45:00', 10],
// // ['2025-10-16 08:00:00', 30],
// // ['2025-10-16 08:15:00', 50],
// // ['2025-10-16 08:30:00', 60],
// // ['2025-10-16 08:45:00', 70],
// // ['2025-10-16 09:00:00', 100],
// // ['2025-10-16 09:15:00', 120],
// // ['2025-10-16 09:30:00', 130],
// // ['2025-10-16 09:45:00', 140],
// // ['2025-10-16 10:00:00', 160],
// // ['2025-10-16 10:15:00', 160],
// // ['2025-10-16 10:30:00', 130],
// // ['2025-10-16 10:45:00', 120],
// // ['2025-10-16 11:00:00', 140],
// // ['2025-10-16 11:15:00', 80],
// // ['2025-10-16 11:30:00', 70],
// // ['2025-10-16 11:45:00', 90],
// // ['2025-10-16 12:00:00', 60],
// // ['2025-10-16 12:15:00', 60],
// // ['2025-10-16 12:30:00', 60],
// // ['2025-10-16 12:45:00', 60]
// // ],
// data:[],
// itemStyle: {
// normal: {
// //这里是颜色
// color: function (params: any) {
// if (params.value[1] == 0 || params.value[1] == 3.14159) {
// return '#ccc'
// } else {
// return config.layout.elementUiPrimary[0]
// }
// }
// }
// },
// yAxisIndex: 0
// },
// {
// name: '谐波总畸变率',
// type: 'line',
// showSymbol: false,
// smooth: true,
// data: [
// ['2025-10-16 07:00:00', 0],
// ['2025-10-16 07:15:00', 0],
// ['2025-10-16 07:30:00', 0],
// ['2025-10-16 07:45:00', 0],
// ['2025-10-16 08:00:00', 0],
// ['2025-10-16 08:15:00', 0.1],
// ['2025-10-16 08:30:00', 0.1],
// ['2025-10-16 08:45:00', 0.1],
// ['2025-10-16 09:00:00', 1],
// ['2025-10-16 09:15:00', 1],
// ['2025-10-16 09:30:00', 1],
// ['2025-10-16 09:45:00', 1],
// ['2025-10-16 10:00:00', 0.8],
// ['2025-10-16 10:15:00', 0.8],
// ['2025-10-16 10:30:00', 0.8],
// ['2025-10-16 10:45:00', 0.8],
// ['2025-10-16 11:00:00', 0.8],
// ['2025-10-16 11:15:00', 0.1],
// ['2025-10-16 11:30:00', 0.1],
// ['2025-10-16 11:45:00', 0.1],
// ['2025-10-16 12:00:00', 0],
// ['2025-10-16 12:15:00', 0],
// ['2025-10-16 12:30:00', 0],
// ['2025-10-16 12:45:00', 0]
// ],
// yAxisIndex: 1
// }
// ]
// }
// })
const headerHeight = ref(57)
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
headerHeight.value = height
if (datePickerValue && datePickerValue.timeValue) {
// 更新时间参数
tableStore.table.params.searchBeginTime = datePickerValue.timeValue[0]
tableStore.table.params.searchEndTime = datePickerValue.timeValue[1]
}
}
const setEchart = () => {
loading.value = true
// 获取当前选择的功率和指标名称
const powerName = powerList.value?.find((item: any) => item.id === tableStore.table.params.power)?.name || '功率'
const indicatorName = indicatorList.value?.find((item: any) => item.id === tableStore.table.params.indicator)?.name || '电能质量指标'
echartList.value = {
title: {
text: `${indicatorName}${powerName}负荷曲线拟合图`
},
xAxis: {
type: 'time',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
},
yAxis: [{}, {}],
grid: {
left: '10px',
right: '20px'
},
options: {
series: [
{
type: 'bar',
name: powerName, // 动态设置功率名称
data: [],
itemStyle: {
normal: {
color: function (params: any) {
if (params.value[1] == 0 || params.value[1] == 3.14159) {
return '#ccc'
} else {
return config.layout.elementUiPrimary[0]
}
}
}
},
yAxisIndex: 0
},
{
name: indicatorName, // 动态设置指标名称
type: 'line',
showSymbol: false,
smooth: true,
data: [],
yAxisIndex: 1
}
]
}
}
// 检查是否有数据
if (!chartsList.value || chartsList.value.length === 0) {
loading.value = false
showEchart.value = false // 没有数据时隐藏图表
return
}
try {
// 用户功率数据和电能质量数据
let powerData: any[] = []
let qualityData: any[] = []
chartsList.value.forEach((item: any) => {
// 根据统计项ID判断是功率数据还是电能质量数据
if (item.statisticalIndex === tableStore.table.params.power) {
powerData.push(item)
} else if (item.statisticalIndex === tableStore.table.params.indicator) {
qualityData.push(item)
}
})
// 处理功率数据
const processedPowerData = powerData.map((item: any) => {
return [
item.time,
item.statisticalData !== null && item.statisticalData !== undefined
? parseFloat(item.statisticalData.toFixed(2))
: null
]
})
// 处理电能质量数据
const processedQualityData = qualityData.map((item: any) => {
return [
item.time,
item.statisticalData !== null && item.statisticalData !== undefined
? parseFloat(item.statisticalData.toFixed(2))
: null
]
})
// 检查是否有有效数据
const hasPowerData = processedPowerData.length > 0 && processedPowerData.some(item => item[1] !== null)
const hasQualityData = processedQualityData.length > 0 && processedQualityData.some(item => item[1] !== null)
if (!hasPowerData && !hasQualityData) {
showEchart.value = false
loading.value = false
return
}
// 更新图表配置
echartList.value.options.series[0].data = processedPowerData
echartList.value.options.series[1].data = processedQualityData
// 确保图表显示
showEchart.value = true
} catch (error) {
console.error('处理图表数据时出错:', error)
showEchart.value = false
} finally {
loading.value = false
}
}
const initCode = () => {
queryByCode('steady_state_limit_fitting').then(res => {
queryCsDictTree(res.data.id).then(item => {
powerList.value = item.data.filter((item: any) => {
return item.name == '三相总无功功率' || item.name == '三相总有功功率'
})
indicatorList.value = item.data.filter((item: any) => {
return item.name != '三相总无功功率' && item.name != '三相总有功功率'
})
tableStore.table.params.power = powerList.value[0].id
tableStore.table.params.indicator = indicatorList.value[0].id
nextTick(() => {
tableStore.index()
})
})
})
}
const tableStore: any = new TableStore({
url: '/cs-device-boot/csGroup/fittingData',
method: 'POST',
showPage: false,
exportName: '主要监测点列表',
column: [],
beforeSearchFun: () => {
// 设置时间参数
tableStore.table.params.searchBeginTime = tableStore.table.params.searchBeginTime || prop.timeValue?.[0]
tableStore.table.params.searchEndTime = tableStore.table.params.searchEndTime || prop.timeValue?.[1]
// 只有当 lineList 已加载且有数据时才设置默认 lineId
if (!tableStore.table.params.lineId && lineList.value && lineList.value.length > 0) {
tableStore.table.params.lineId = lineList.value[0].lineId
}
// 构建请求参数 lists
let lists: any = []
// 处理用户功率指标
const selectedPower = powerList.value?.find((item: any) => item.id === tableStore.table.params.power)
if (selectedPower) {
lists.push({
statisticalId: tableStore.table.params.power,
valueType: tableStore.table.params.valueType
})
}
// 处理电能质量指标
const selectedIndicator = indicatorList.value?.find(
(item: any) => item.id === tableStore.table.params.indicator
)
if (selectedIndicator) {
let frequencys = ''
if (selectedIndicator.name.includes('谐波含有率')) {
frequencys = tableStore.table.params.harmonicCount
}
lists.push({
statisticalId: tableStore.table.params.indicator,
frequency: frequencys !== null && frequencys !== undefined ? String(frequencys) : ''
})
}
// 将 lists 添加到请求参数中
tableStore.table.params.list = lists
tableStore.table.params.dataLevel = 'Primary'
},
loadCallback: () => {
tableStore.table.height = `calc(${prop.height} - 80px)`
// 数据加载完成后的处理
if (tableStore.table.data && tableStore.table.data.length > 0) {
chartsList.value = JSON.parse(JSON.stringify(tableStore.table.data))
setEchart()
} else if (tableStore.table.data) {
showEchart.value = false
}
}
})
const tableRef = ref()
provide('tableRef', tableRef)
tableStore.table.params.indicator = '1'
tableStore.table.params.exceedingTheLimit = '1'
tableStore.table.params.valueType = 'avg'
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
// 添加谐波次数选项2-50
const harmonicCountOptions = ref(Array.from({ length: 49 }, (_, i) => i + 2))
// 判断是否应该显示谐波次数选择框
const shouldShowHarmonicCount = () => {
if (!tableStore.table.params.indicator || !indicatorList.value) return false
const currentIndicator = indicatorList.value.find((item: any) => item.id === tableStore.table.params.indicator)
return (
currentIndicator &&
(currentIndicator.name.includes('电压谐波含有率') || currentIndicator.name.includes('电流谐波含有率'))
)
}
// 获取谐波类型名称
const getHarmonicTypeName = () => {
const currentIndicator = indicatorList.value.find((item: any) => item.id === tableStore.table.params.indicator)
if (currentIndicator) {
if (currentIndicator.name.includes('电压谐波含有率')) {
return '电压'
} else if (currentIndicator.name.includes('电流谐波含有率')) {
return '电流'
}
}
return ''
}
// 监听指标变化,当指标变化时重置谐波次数
watch(
() => tableStore.table.params.indicator,
newVal => {
if (shouldShowHarmonicCount()) {
// 如果之前没有设置过谐波次数则默认设置为2
if (!tableStore.table.params.harmonicCount) {
tableStore.table.params.harmonicCount = 2
}
} else {
// 如果不是谐波含有率指标,则清除谐波次数设置
tableStore.table.params.harmonicCount = ''
}
}
)
onMounted(() => {
initLineList().then(() => {
// 确保 lineList 加载完成后再初始化其他数据
initCode()
// 只有非全屏时才调用 tableStore.index()
// if (!fullscreen.value) {
// tableStore.index()
// }
})
})
watch(
() => prop.timeKey,
val => {
tableStore.index()
}
)
watch(
() => prop.timeValue,
(newVal, oldVal) => {
// 当外部时间值变化时,更新表格的时间参数
if (newVal && (!oldVal || newVal[0] !== oldVal[0] || newVal[1] !== oldVal[1])) {
tableStore.table.params.searchBeginTime = newVal[0]
tableStore.table.params.searchEndTime = newVal[1]
tableStore.index()
}
},
{
deep: true
}
)
const addMenu = () => {}
</script>
<style lang="scss" scoped>
:deep(.el-select) {
min-width: 80px;
}
</style>