Files
admin-govern/src/components/cockpit/indicatorDistribution/index.vue

447 lines
17 KiB
Vue
Raw Normal View History

<template>
<div>
<!--指标越限概率分布 -->
2025-11-06 16:21:39 +08:00
<TableHeader :showReset="false" @selectChange="selectChange" datePicker v-if="fullscreen">
<template v-slot:select>
2025-11-19 14:07:26 +08:00
<el-form-item label="监测点">
<el-select size="small" v-model="tableStore.table.params.lineId">
2025-11-24 15:12:24 +08:00
<el-option
v-for="item in lineList"
:key="item.lineId"
:label="item.name"
:value="item.lineId"
/>
2025-11-06 16:21:39 +08:00
</el-select>
</el-form-item>
</template>
</TableHeader>
2025-11-19 14:07:26 +08:00
<div v-loading="tableStore.table.loading">
2025-11-18 14:23:06 +08:00
<my-echart
class="tall"
:options="echartList"
:style="{
width: prop.width,
2025-12-04 09:37:38 +08:00
height: `calc(${prop.height} / 2 - ${headerHeight / 2}px + ${fullscreen ? 0 : 28}px )`,
2025-11-18 14:23:06 +08:00
}"
/>
<my-echart
class="mt10"
:options="echartList1"
:style="{
width: prop.width,
height: `calc(${prop.height} / 2 - ${headerHeight / 2}px + ${fullscreen ? 0 : 28}px )`
}"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, watch, h } from 'vue'
import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
2025-11-24 15:12:24 +08:00
import { limitProbabilityData, cslineList } from '@/api/harmonic-boot/cockpit/cockpit'
const prop = defineProps({
2025-11-14 14:09:34 +08:00
w: { type: [String, Number] },
h: { type: [String, Number] },
width: { type: [String, Number] },
height: { type: [String, Number] },
timeKey: { type: [String, Number] },
timeValue: { type: Object }
})
2025-11-24 15:12:24 +08:00
// const options = ref(JSON.parse(window.localStorage.getItem('lineIdList') || '[]'))
2025-11-06 16:21:39 +08:00
2025-11-24 15:12:24 +08:00
const lineList = ref()
2025-11-24 15:12:24 +08:00
const headerHeight = ref(57)
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
headerHeight.value = height
2025-11-14 14:09:34 +08:00
if (datePickerValue && datePickerValue.timeValue) {
// 更新时间参数
tableStore.table.params.searchBeginTime = datePickerValue.timeValue[0]
tableStore.table.params.searchEndTime = datePickerValue.timeValue[1]
}
}
// 计算是否全屏展示
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
}
})
2025-11-19 14:07:26 +08:00
const echartList = ref()
2025-11-10 14:47:18 +08:00
2025-11-19 14:07:26 +08:00
const echartList1 = ref()
const probabilityData = ref()
2025-11-24 15:12:24 +08:00
const initLineList = async () => {
cslineList({}).then(res => {
lineList.value = res.data
tableStore.table.params.lineId = lineList.value[0].lineId
tableStore.index()
})
}
2025-11-19 14:07:26 +08:00
// 越限程度概率分布
const initProbabilityData = () => {
2025-11-24 15:12:24 +08:00
// 只有当 lineList 已加载且有数据时才设置默认 lineId
if (!tableStore.table.params.lineId && lineList.value && lineList.value.length > 0) {
tableStore.table.params.lineId = lineList.value[0].lineId
2025-11-19 14:07:26 +08:00
}
const params = {
searchBeginTime: tableStore.table.params.searchBeginTime || prop.timeValue?.[0],
searchEndTime: tableStore.table.params.searchEndTime || prop.timeValue?.[1],
lineId: tableStore.table.params.lineId
}
limitProbabilityData(params).then((res: any) => {
probabilityData.value = res.data
// 处理接口返回的数据,转换为图表所需格式
if (res.data && Array.isArray(res.data)) {
// 定义指标类型顺序
const indicatorOrder = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
// 按照指定顺序排序数据
const sortedData = [...res.data].sort((a, b) => {
return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName)
})
// 构造 series 数据
const seriesData: any = []
let maxValue: any = 0 // 用于存储数据中的最大值
// 遍历每个越限程度区间0-20%, 20-40%, 40-60%, 60-80%, 80-100%
for (let xIndex = 0; xIndex < 5; xIndex++) {
// 遍历每个指标类型
sortedData.forEach((item, yIndex) => {
// 从 extentGrades 中获取对应区间的值
const extentGrade = item.extentGrades[xIndex]
const value = extentGrade ? (Object.values(extentGrade)[0] as number) : 0
seriesData.push([xIndex, yIndex, value])
// 更新最大值
if (value > maxValue) {
maxValue = value
}
})
}
2025-11-19 14:07:26 +08:00
// 计算 z 轴最大值(最大值加 5
const zAxisMax = Math.ceil(maxValue) + 5
// 构造 yAxis 数据(指标类型名称)
const yAxisData = sortedData.map(item => item.indexName)
echartList.value = {
options: {
backgroundColor: '#fff',
tooltip: {
2025-11-10 14:47:18 +08:00
textStyle: {
2025-11-19 14:07:26 +08:00
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0,
formatter: function (params: any) {
var yIndex = params.value[1] //获取y轴索引
var tips = ''
tips += '指标类型: ' + yAxisData[yIndex] + '</br>'
tips += '越限程度: ' + params.seriesName + '</br>'
tips += '越限次数: ' + params.value[2] + '</br>'
return tips
2025-11-10 14:47:18 +08:00
}
},
2025-11-19 14:07:26 +08:00
title: {
text: '指标越限概率分布',
x: 'center',
2025-11-10 14:47:18 +08:00
textStyle: {
2025-11-19 14:07:26 +08:00
fontSize: 16,
fontWeight: 'normal'
2025-11-10 14:47:18 +08:00
}
},
2025-11-19 14:07:26 +08:00
// 移除或隐藏 visualMap 组件
visualMap: {
show: false, // 设置为 false 隐藏右侧颜色条
min: 0,
// max: 100,
2025-11-24 15:12:24 +08:00
max: zAxisMax, // 使用计算出的最大值加5
2025-11-19 14:07:26 +08:00
inRange: {
color: ['#313695', '#00BB00', '#ff8000', '#d73027', '#a50026']
2025-11-10 14:47:18 +08:00
}
},
2025-11-19 14:07:26 +08:00
// 添加 legend 配置并设置为不显示
legend: {
show: false // 隐藏图例
},
xAxis3D: {
type: 'category',
name: '越限程度',
nameLocation: 'middle',
2025-12-04 09:37:38 +08:00
nameGap: 50,
2025-11-19 14:07:26 +08:00
data: ['0-20%', '20-40%', '40-60%', '60-80%', '80-100%'],
2025-12-04 10:33:48 +08:00
2025-11-10 14:47:18 +08:00
},
2025-11-19 14:07:26 +08:00
yAxis3D: {
type: 'category',
name: '指标类型',
nameLocation: 'middle',
2025-12-04 09:37:38 +08:00
nameGap: 50,
2025-11-19 14:07:26 +08:00
data: yAxisData,
2025-12-04 10:33:48 +08:00
2025-11-19 14:07:26 +08:00
splitLine: {
lineStyle: {
type: 'dashed',
opacity: 0.5
}
}
},
2025-11-19 14:07:26 +08:00
zAxis3D: {
type: 'value',
name: '越限次数',
nameLocation: 'middle',
nameGap: 30,
2025-12-04 10:33:48 +08:00
minInterval: 10,
2025-11-19 14:07:26 +08:00
// max: 100
},
grid3D: {
viewControl: {
projection: 'perspective',
distance: 250,
rotateSensitivity: 10,
zoomSensitivity: 2
},
boxWidth: 150,
boxDepth: 100,
boxHeight: 100,
light: {
main: {
intensity: 1.2
},
ambient: {
intensity: 0.4
}
}
},
series: [
{
type: 'bar3D',
name: '0-20%',
data: seriesData.filter((item: any) => item[0] === 0),
shading: 'realistic',
label: {
show: false
},
itemStyle: {
opacity: 0.9
},
emphasis: {
label: {
show: true,
textStyle: {
fontSize: 14,
color: '#000'
}
},
itemStyle: {
color: '#ff8000'
}
}
},
{
type: 'bar3D',
name: '20-40%',
data: seriesData.filter((item: any) => item[0] === 1),
shading: 'realistic',
label: {
show: false
},
itemStyle: {
opacity: 0.9
},
emphasis: {
label: {
show: true,
textStyle: {
fontSize: 14,
color: '#000'
}
},
itemStyle: {
color: '#ff8000'
}
}
},
{
type: 'bar3D',
name: '40-60%',
data: seriesData.filter((item: any) => item[0] === 2),
shading: 'realistic',
label: {
show: false
},
itemStyle: {
opacity: 0.9
},
emphasis: {
label: {
show: true,
textStyle: {
fontSize: 14,
color: '#000'
}
},
itemStyle: {
color: '#ff8000'
}
}
},
{
type: 'bar3D',
name: '60-80%',
data: seriesData.filter((item: any) => item[0] === 3),
shading: 'realistic',
label: {
show: false
},
itemStyle: {
opacity: 0.9
},
emphasis: {
label: {
show: true,
textStyle: {
fontSize: 14,
color: '#000'
}
},
itemStyle: {
color: '#ff8000'
}
}
},
{
type: 'bar3D',
name: '80-100%',
data: seriesData.filter((item: any) => item[0] === 4),
shading: 'realistic',
label: {
show: false
},
itemStyle: {
opacity: 0.9
},
emphasis: {
label: {
show: true,
textStyle: {
fontSize: 14,
color: '#000'
}
},
itemStyle: {
color: '#ff8000'
}
}
}
]
}
}
}
2025-11-19 14:07:26 +08:00
})
}
const tableStore: any = new TableStore({
2025-12-01 09:33:12 +08:00
url: '/cs-harmonic-boot/limitRateDetailD/limitTimeProbabilityData',
method: 'POST',
showPage: false,
column: [],
beforeSearchFun: () => {
2025-11-14 14:09:34 +08:00
tableStore.table.params.searchBeginTime = tableStore.table.params.searchBeginTime || prop.timeValue?.[0]
tableStore.table.params.searchEndTime = tableStore.table.params.searchEndTime || prop.timeValue?.[1]
2025-11-24 15:12:24 +08:00
// 只有当 lineList 已加载且有数据时才设置默认 lineId
if (!tableStore.table.params.lineId && lineList.value && lineList.value.length > 0) {
tableStore.table.params.lineId = lineList.value[0].lineId
2025-11-19 14:07:26 +08:00
}
},
loadCallback: () => {
2025-11-19 14:07:26 +08:00
// 处理返回的数据,将其转换为图表所需格式
const indexNames: any = [...new Set(tableStore.table.data.map((item: any) => item.indexName))]
const timePeriods = [...new Set(tableStore.table.data.map((item: any) => item.timePeriod))]
// 构建系列数据
const seriesData = indexNames.map((indexName: string) => {
const dataIndex = tableStore.table.data.filter((item: any) => item.indexName === indexName)
return {
name: indexName,
type: 'line',
2025-11-27 14:47:04 +08:00
symbol: 'none',
2025-11-19 14:07:26 +08:00
data: dataIndex.map((item: any) => [item.timePeriod, item.times])
}
})
echartList1.value = {
title: {
text: '越限时间概率分布'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: indexNames
},
xAxis: {
type: 'category',
name: '时间段',
data: timePeriods
},
yAxis: {
type: 'value'
// name: '次数'
},
series: seriesData
}
initProbabilityData()
}
})
provide('tableStore', tableStore)
onMounted(() => {
2025-11-24 15:12:24 +08:00
initLineList()
})
watch(
() => prop.timeKey,
val => {
tableStore.index()
}
)
watch(
2025-11-14 14:09:34 +08:00
() => prop.timeValue,
(newVal, oldVal) => {
2025-11-14 14:09:34 +08:00
// 当外部时间值变化时,更新表格的时间参数
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()
}
},
{
2025-11-14 14:09:34 +08:00
deep: true
}
)
const addMenu = () => {}
</script>
<style lang="scss" scoped></style>