联调实时数据页面

This commit is contained in:
GGJ
2025-03-13 18:26:03 +08:00
parent 5f125afede
commit bcf9c78fac
23 changed files with 2513 additions and 370 deletions

View File

@@ -2,36 +2,48 @@
<div class="default-main" style="padding: 10px">
<splitpanes :style="height" class="default-theme" id="navigation-splitpanes">
<pane :size="size">
<PointTree ref="pointTree" :default-expand-all="false"
<PointTree
ref="pointTree"
:default-expand-all="false"
:default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []"
:current-node-key="monitoringPoint.state.lineId" :show-checkbox="monitoringPoint.state.showCheckBox"
:default-checked-keys="monitoringPoint.state.lineIds" @check="handleCheckChange"
@node-click="handleNodeClick" @init="handleNodeClick"></PointTree>
:current-node-key="monitoringPoint.state.lineId"
:show-checkbox="monitoringPoint.state.showCheckBox"
:default-checked-keys="monitoringPoint.state.lineIds"
@check="handleCheckChange"
@node-click="handleNodeClick"
@init="handleNodeClick"
></PointTree>
</pane>
<pane>
<div style="position: relative; height: 100%">
<el-tabs v-model="activeName" type="border-card" class="demo-tabs" style="height: 100%">
<el-tabs
v-model="activeName"
type="border-card"
class="demo-tabs"
style="height: 100%"
@tab-change="handleTabChange"
>
<!-- <el-tab-pane label="稳态综合评估" name="1" lazy v-if="!isReload">
<Wentaizonghepinggu />
</el-tab-pane> -->
<el-tab-pane label="稳态指标合格率" name="2" lazy v-if="!isReload">
<Wentaizhibiaohegelv />
<Wentaizhibiaohegelv v-if="activeName == '2'" />
</el-tab-pane>
<el-tab-pane label="稳态数据分析" name="3" lazy v-if="!isReload">
<Wentaishujufenxi />
<Wentaishujufenxi v-if="activeName == '3'" />
</el-tab-pane>
<el-tab-pane label="谐波频谱" name="4" lazy v-if="!isReload">
<Xiebopingpu />
<Xiebopingpu v-if="activeName == '4'" />
</el-tab-pane>
<!-- <el-tab-pane label="告警数据统计" name="5" lazy v-if="!isReload">
<Gaojingshujutongji />
<!-- <el-tab-pane label="告警数据统计" name="5" lazy v-if="!isReload ">
<Gaojingshujutongji v-if=" activeName == '5'"/>
</el-tab-pane> -->
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload">
<Yunxingzhuangtai />
<Yunxingzhuangtai v-if="activeName == '6'" />
</el-tab-pane>
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload">
<Shishishuju v-if="activeName == '7'" />
</el-tab-pane>
<!-- <el-tab-pane label="实时数据" name="7" lazy v-if="!isReload">
<Shishishuju />
</el-tab-pane> -->
</el-tabs>
<!-- <div
class="monitoring-point"
@@ -78,7 +90,9 @@ onMounted(() => {
})
const handleNodeClick = (data: any, node: any) => {
if (data.level === 6) {
console.log('🚀 ~ handleNodeClick ~ data:', data)
monitoringPoint.setValue('lineId', data.id)
monitoringPoint.setValue('pid', data.pids)
monitoringPoint.setValue('lineName', data.alias)
}
}
@@ -88,6 +102,9 @@ const handleCheckChange = (data: any, node: any) => {
node.checkedNodes.filter((item: any) => item.level === 6).map((item: any) => item.id)
)
}
const handleTabChange = () => {
monitoringPoint.setShowCheckBox(false)
}
watch(
() => router.currentRoute.value.query.lineId,
(newLineId, oldLineId) => {

View File

@@ -0,0 +1,345 @@
<template>
<div class="pt50">
<el-button class="shutDown" icon="el-icon-Back" @click="emit('shutDown')">返回</el-button>
<div class="select">
<div class="mr10">谐波次数</div>
<el-select v-model="selectValue" style="width: 100px" @change="loading = true">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<el-tabs type="border-card" v-model="activeName" @tab-change="handleClick" v-loading="loading">
<el-tab-pane v-for="(item, index) in tabsList" :label="item.groupName" :name="index" :key="index">
<div>
<div class="realtrend_top">
<div class="realtrend_table">
<div class="thead_left">
<p style="font-weight: 700; background-color: #f3f6f9">次数()</p>
<p>{{ item.groupName }}{{ item.unit ? '(' + item.unit + ')' : '' }}</p>
</div>
<div class="thead_right">
<div
class="right_cell"
v-for="i in selectValue == '1'
? item.title.filter(num => (activeName == 1 ? num - 0.5 : num) % 2 !== 0)
: selectValue == '2'
? item.title.filter(num => (activeName == 1 ? num - 0.5 : num) % 2 == 0)
: item.title"
:key="index"
>
<p style="background-color: #f3f6f9">
<span>{{ i }}次</span>
</p>
<p>
<span>{{ item.data[`h${i}`] == 0 ? 0 : item.data[`h${i}`] || '/' }}</span>
</p>
</div>
</div>
</div>
</div>
<div class="mt10" :style="height">
<MyEchart ref="barCharts" :options="tabsList[0].echartsData"></MyEchart>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getOverLimitData } from '@/api/device-boot/communicate'
import { mainHeight } from '@/utils/layout'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
const emit = defineEmits(['shutDown'])
const monitoringPoint = useMonitoringPoint()
const options = [
{
value: '3',
label: '全部'
},
{
value: '1',
label: '奇次'
},
{
value: '2',
label: '偶次'
}
]
const height = mainHeight(315)
const barCharts = ref()
const loading = ref(true)
const crossTheLine: any = ref({})
const tabsList: any = ref([
{
id: '6d5470f509ca271d7108a86e83bb283f',
groupName: '谐波电压含有率',
thdDataVOS: null,
thdDataTdVODatas: null,
unit: '%',
title: [
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50
],
data: {},
echartsData: {}
},
{
id: 'ae31115b83f02f03a0d3bd65cb017121',
groupName: '间谐波电压含有率',
thdDataVOS: null,
thdDataTdVODatas: null,
unit: '%',
title: [
0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5,
19.5, 20.5, 21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5, 30.5, 31.5, 32.5, 33.5, 34.5, 35.5, 36.5,
37.5, 38.5, 39.5, 40.5, 41.5, 42.5, 43.5, 44.5, 45.5, 46.5, 47.5, 48.5, 49.5
],
data: {},
echartsData: {}
},
{
id: '8dc260f16280184e2b57d26668dc00b1',
groupName: '谐波电流幅值',
thdDataVOS: null,
thdDataTdVODatas: null,
unit: 'A',
title: [
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50
],
data: {},
echartsData: {}
}
])
const selectValue = ref('1')
const activeName = ref(0)
// 点击tab
const handleClick = (tab: any, event: any) => {
loading.value = true
}
const init = (row: any) => {
let vData: any = {}
let iData: any = {}
let SvData: any = {}
for (let i = 1; i < 50; i++) {
vData[`h${i + 1}`] =
Math.floor(Math.max(...[row.V.A[`V` + i], row.V.B[`V` + i], row.V.C[`V` + i]].map(Number)) * 100) / 100
SvData[`h${i - 0.5}`] =
Math.floor(Math.max(...[row.V.A[`SV_` + i], row.V.B[`SV_` + i], row.V.C[`SV_` + i]].map(Number)) * 100) /
100
iData[`h${i + 1}`] =
Math.floor(Math.max(...[row.I.A[`I` + i], row.I.B[`I` + i], row.I.C[`I` + i]].map(Number)) * 100) / 100
}
SvData[`h49.5`] =
Math.floor(Math.max(...[row.V.A[`SV_50`], row.V.B[`SV_50`], row.V.C[`SV_50`]].map(Number)) * 100) / 100
tabsList.value[0].data = vData
tabsList.value[1].data = SvData
tabsList.value[2].data = iData
let xData =
selectValue.value == '1'
? tabsList.value[activeName.value].title.filter(num => (activeName.value == 1 ? num - 0.5 : num) % 2 !== 0)
: selectValue.value == '2'
? tabsList.value[activeName.value].title.filter(num => (activeName.value == 1 ? num - 0.5 : num) % 2 === 0)
: tabsList.value[activeName.value].title
barCharts.value[activeName.value]?.setOptions({
xAxis: {
data: xData.map(num => `${num}次`)
},
series: [
{
name: tabsList.value[activeName.value].groupName,
type: 'bar',
data: xData.map(num => {
return tabsList.value[activeName.value].data[`h${num}`]
})
},
{
data: xData.map(num => {
return (
crossTheLine.value[
activeName.value == 0
? `uharm${num}`
: activeName.value == 1
? `inuharm${num + 0.5}`
: `iharm${num}`
] || ''
)
})
}
]
})
loading.value = false
}
// 设置ecartsData
const echarts = (num: number) => {
return {
title: {
text: tabsList.value[num].groupName
},
xAxis: {
name: tabsList.value[num].unit,
data: []
},
yAxis: {},
color: ['#2E8B57', '#DAA520'],
options: {
series: [
{
name: tabsList.value[num].groupName,
type: 'bar',
data: []
},
{
name: '国标限值(%)',
type: 'bar',
// label: {
// normal: {
// position: 'top'
// }
// },
data: []
}
]
}
}
}
onMounted(() => {
tabsList.value[0].echartsData = echarts(0)
tabsList.value[0].echartsData = echarts(1)
tabsList.value[0].echartsData = echarts(2)
getOverLimitData({ id: monitoringPoint.state.lineId }).then(res => {
crossTheLine.value = res.data
})
})
defineExpose({
init
})
</script>
<style lang="scss" scoped>
.shutDown {
position: absolute;
right: 10px;
top: 10px;
}
.select {
position: absolute;
top: 10px;
display: flex;
align-items: center;
font-size: 14px;
}
.realtrend_top {
width: 100%;
height: auto;
display: flex;
justify-content: space-between;
align-items: center;
.table {
flex: 1;
// min-height: 80px;
cursor: pointer;
min-height: 90px;
max-height: 170px;
border: 1px solid #eee;
overflow-x: auto;
overflow-y: hidden;
position: relative;
ul {
width: auto;
height: 40px;
display: flex;
li {
flex: none;
width: 100px;
line-height: 40px;
border: 1px solid #eee;
text-align: center;
list-style: none;
}
}
ul:nth-child(1) {
li {
font-weight: 800;
background: #f4f6f9;
}
}
}
// .table::-webkit-scrollbar {
// display: none;
// }
.realtrend_table {
width: 100%;
height: auto;
max-height: 150px;
display: flex;
border: 2px solid #eee;
cursor: pointer;
font-size: 13px;
.thead_left {
width: 150px;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
line-height: 50px;
padding-bottom: 5px;
p {
width: 100%;
height: 100%;
text-align: center;
border: 1px solid #eee;
line-height: 38px;
margin: 0 !important;
}
}
.thead_right {
flex: 1;
align-items: center;
overflow-x: auto;
overflow-y: hidden;
display: flex;
padding-bottom: 5px;
.right_cell {
width: 100%;
display: flex;
flex-direction: column;
p {
flex: none;
min-width: 60px;
height: 100%;
text-align: center;
border: 1px solid #eee;
line-height: 38px;
margin: 0 !important;
}
p:nth-child(1) {
font-weight: 800;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,384 @@
<template>
<div class="pt50">
<el-button class="shutDown" icon="el-icon-Back" @click="emit('shutDown')">返回</el-button>
<div class="select">
<el-form :model="searchForm" id="history_select">
<el-form-item label="稳态指标">
<el-select
multiple
collapse-tags
collapse-tags-tooltip
v-model.trim="searchForm.index"
placeholder="请选择统计指标"
:multiple-limit="3"
value-key="id"
@change="change"
>
<el-option
v-for="(item, index) in indexOptions"
:label="item.name"
:key="index"
:value="item"
></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div v-loading="loading" id="trend">
<div :style="height" v-for="(item, index) in searchForm.index" :key="index">
<MyEchart ref="MyEchartRef" :options="item.echartsData" :isInterVal="true"></MyEchart>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { mainHeight } from '@/utils/layout'
import { timeFormat } from '@/utils/common'
import { useConfig } from '@/stores/config'
import { yMethod } from '@/utils/echartMethod'
import html2canvas from 'html2canvas'
import * as echarts from 'echarts' // 全引入
const config = useConfig()
const props = defineProps({
ptName: {
type: String
}
})
const loading = ref(true)
const emit = defineEmits(['shutDown'])
const searchForm: any = ref({ index: [] })
const timeList = ref([])
const MyEchartRef = ref()
const height = ref(mainHeight(150, 2))
//统计指标
const indexOptions: any = ref([
{
id: 0,
name: '电压总有效值(kV)',
children: [
{ name: 'vRmsA', phase: props.ptName == 'star' ? 'A相' : 'AB相', data: [] },
{ name: 'vRmsB', phase: props.ptName == 'star' ? 'B相' : 'BC相', data: [] },
{ name: 'vRmsC', phase: props.ptName == 'star' ? 'C相' : 'CA相', data: [] }
],
color: ['#FFCC00', '#2E8B57', '#A52a2a'],
unit: 'kV',
data: []
},
{
id: 1,
name: '电流总有效值(A)',
children: [
{ name: 'iRmsA', phase: 'A相', data: [] },
{ name: 'iRmsB', phase: 'B相', data: [] },
{ name: 'iRmsC', phase: 'C相', data: [] }
],
color: ['#FFCC00', '#2E8B57', '#A52a2a'],
unit: 'A',
data: []
},
{
id: 2,
name: '有功功率(kW)',
children:
props.ptName == 'star'
? [
{ name: 'pA', phase: 'A相', data: [] },
{ name: 'pB', phase: 'B相', data: [] },
{ name: 'pC', phase: 'C相', data: [] },
{ name: 'pTot', phase: '总', data: [] }
]
: [{ name: 'pTot', phase: '总', data: [] }],
color: props.ptName == 'star' ? ['#FFCC00', '#2E8B57', '#A52a2a', '#000'] : ['#000'],
unit: 'kW',
data: []
},
{
id: 3,
name: '无功功率(kW)',
children:
props.ptName == 'star'
? [
{ name: 'qA', phase: 'A相', data: [] },
{ name: 'qB', phase: 'B相', data: [] },
{ name: 'qC', phase: 'C相', data: [] },
{ name: 'qTot', phase: '总', data: [] }
]
: [{ name: 'qTot', phase: '总', data: [] }],
color: props.ptName == 'star' ? ['#FFCC00', '#2E8B57', '#A52a2a', '#000'] : ['#000'],
unit: 'kW',
data: []
},
{
id: 4,
name: '基波电压总有效值(kV)',
children: [
{ name: 'v1A', phase: props.ptName == 'star' ? 'A相' : 'AB相', data: [] },
{ name: 'v1B', phase: props.ptName == 'star' ? 'B相' : 'BC相', data: [] },
{ name: 'v1C', phase: props.ptName == 'star' ? 'C相' : 'CA相', data: [] }
],
color: ['#FFCC00', '#2E8B57', '#A52a2a'],
unit: 'kV',
data: []
},
{
id: 5,
name: '基波电流总有效值(A)',
children: [
{ name: 'i1A', phase: 'A相', data: [] },
{ name: 'i1B', phase: 'B相', data: [] },
{ name: 'i1C', phase: 'C相', data: [] }
],
color: ['#FFCC00', '#2E8B57', '#A52a2a'],
unit: 'A',
data: []
},
{
id: 6,
name: '频率(Hz)',
children: [
{ name: 'freq', phase: '频率', data: [] },
{ name: 'freqDev', phase: '频率偏差', data: [] }
],
color: [config.layout.elementUiPrimary[0], '#00BFF5'],
unit: 'Hz',
data: []
},
{
id: 7,
name: '电压不平衡度(%)',
children: [{ name: 'vUnbalance', phase: '电压不平衡度', data: [] }],
color: [config.layout.elementUiPrimary[0]],
unit: '%',
data: []
},
{
id: 8,
name: '电流不平衡度(%)',
children: [{ name: 'iUnbalance', phase: '电流不平衡度', data: [] }],
color: [config.layout.elementUiPrimary[0]],
unit: '%',
data: []
}
])
const change = () => {
height.value = mainHeight(150, searchForm.value.index.length)
// let name = searchForm.value.index.map(item => item.name)
// let list = indexOptions.value.filter(item => !name.includes(item.name))
loading.value = true
searchForm.value.index.forEach((item: any) => {
item.echartsData.xAxis.data = []
item.echartsData.series.forEach((child: any) => {
child.data = []
})
})
// console.log("🚀 ~ change ~ MyEchartRef.value[0]?.getChart():", MyEchartRef.value[0]?.getChart())
}
onMounted(() => {
setEcharts()
searchForm.value.index.push(...[indexOptions.value[0], indexOptions.value[1]])
})
const init = (row: any) => {
// timeList.value.push(timeFormat(row.TIME - 0))
searchForm.value.index.forEach((item: any, index: any) => {
// item.echartsData.xAxis.data.push(timeFormat(row.TIME - 0))
let time = timeFormat(row.TIME - 0)
switch (item.name) {
case '电压总有效值(kV)':
item.echartsData.series[0].data.push([
time,
Math.floor((props.ptName == 'star' ? row.V.A.VRMS : row.V.A.VRMS_LVR) * 100) / 100
])
item.echartsData.series[1].data.push([
time,
Math.floor((props.ptName == 'star' ? row.V.B.VRMS : row.V.B.VRMS_LVR) * 100) / 100
])
item.echartsData.series[2].data.push([
time,
Math.floor((props.ptName == 'star' ? row.V.C.VRMS : row.V.C.VRMS_LVR) * 100) / 100
])
break
case '电流总有效值(A)':
item.echartsData.series[0].data.push([time, Math.floor(row.I.A.IRMS * 100) / 100])
item.echartsData.series[1].data.push([time, Math.floor(row.I.B.IRMS * 100) / 100])
item.echartsData.series[2].data.push([time, Math.floor(row.I.C.IRMS * 100) / 100])
break
case '有功功率(kW)':
if (props.ptName == 'star') {
item.echartsData.series[0].data.push([time, Math.floor(row.PQ.A.P * 100) / 100])
item.echartsData.series[1].data.push([time, Math.floor(row.PQ.B.P * 100) / 100])
item.echartsData.series[2].data.push([time, Math.floor(row.PQ.C.P * 100) / 100])
item.echartsData.series[3].data.push([time, Math.floor(row.PQ.T.P * 100) / 100])
} else {
item.echartsData.series[0].data.push([time, Math.floor(row.PQ.T.P * 100) / 100])
}
break
case '无功功率(kW)':
if (props.ptName == 'star') {
item.echartsData.series[0].data.push([time, Math.floor(row.PQ.A.Q * 100) / 100])
item.echartsData.series[1].data.push([time, Math.floor(row.PQ.B.Q * 100) / 100])
item.echartsData.series[2].data.push([time, Math.floor(row.PQ.C.Q * 100) / 100])
item.echartsData.series[3].data.push([time, Math.floor(row.PQ.T.Q * 100) / 100])
} else {
item.echartsData.series[0].data.push([time, Math.floor(row.PQ.T.Q * 100) / 100])
}
break
case '基波电压总有效值(kV)':
item.echartsData.series[0].data.push([time, Math.floor(row.V.A.V1 * 100) / 100])
item.echartsData.series[1].data.push([time, Math.floor(row.V.B.V1 * 100) / 100])
item.echartsData.series[2].data.push([time, Math.floor(row.V.C.V1 * 100) / 100])
break
case '基波电流总有效值(A)':
item.echartsData.series[0].data.push([time, Math.floor(row.I.A.I1 * 100) / 100])
item.echartsData.series[1].data.push([time, Math.floor(row.I.B.I1 * 100) / 100])
item.echartsData.series[2].data.push([time, Math.floor(row.I.C.I1 * 100) / 100])
break
case '频率(Hz)':
item.echartsData.series[0].data.push([time, Math.floor(row.V.T.FREQ * 100) / 100])
item.echartsData.series[1].data.push([time, Math.floor(row.V.T.DELTA_FREQ * 100) / 100])
break
case '电压不平衡度(%)':
item.echartsData.series[0].data.push([time, Math.floor(row.V.T.V_UNBAN * 100) / 100])
break
case '电流不平衡度(%)':
item.echartsData.series[0].data.push([time, Math.floor(row.I.T.I_UNBAN * 100) / 100])
break
}
item.echartsData.series.forEach((item1: any) => {
if (item1.data.length > 60) {
item1.data.shift()
}
})
let [min, max] = yMethod([].concat(...item.echartsData.series.map(k => k.data).map(k1 => k1.map(k2 => k2[1]))))
item.echartsData.yAxis.min = min
item.echartsData.yAxis.max = max
})
MyEchartRef.value[0]?.setOptions(searchForm.value.index[0].echartsData)
MyEchartRef.value[1]?.setOptions(searchForm.value.index[1].echartsData)
MyEchartRef.value[2]?.setOptions(searchForm.value.index[2].echartsData)
if (loading.value) {
echarts.connect('group')
}
loading.value = false
}
const setEcharts = () => {
indexOptions.value.forEach((item: any, index: any) => {
item.echartsData = {
title: {
text: item.name
},
xAxis: {
name: '时间',
type: 'time',
axisLabel: {
interval: 0, // 强制显示所有标签
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
},
data: []
},
yAxis: {
// type: 'value',
name: item.unit,
splitNumber: 5,
minInterval: 1,
alignTicks: true // 强制对齐刻度
},
toolbox: {
right: 20,
top: 15,
show: index == 0 ? true : false,
feature: {
// 移除默认的 saveAsImage
// saveAsImage: { title: '保存图片' }
myCustomDownload: {
title: '', // 按钮标题
icon: 'path://M892.342857 463.238095l-73.142857-68.266666-258.438095 258.438095V29.257143h-97.52381v624.152381L204.8 394.971429 131.657143 463.238095l380.342857 380.342857zM107.27619 897.219048h804.571429v97.523809H107.27619z', // 自定义图标路径
onclick: function () {
html2canvas(document.getElementById('trend'), {
scale: 1
}).then(function (canvas) {
// 创建a标签实现下载
let creatIMg = document.createElement('a')
creatIMg.download = '实时趋势.png' // 设置下载的文件名,
creatIMg.href = canvas.toDataURL() // 下载url
creatIMg.click()
creatIMg.remove() // 下载之后把创建的元素删除
})
}
}
}
},
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
},
series: []
}
item.children.map((zz: any, zzIndex: any) => {
item.echartsData.series.push({
name: zz.phase,
type: 'line',
increment: true,
itemStyle: {
barBorderRadius: [3, 3, 0, 0],
color: [...item.color][zzIndex]
},
data: [],
smooth: true, // 这里设置平滑曲线
symbol: 'none' // 设置为 'none' 去掉折点小圆
})
})
})
}
onBeforeUnmount(() => {
echarts.disconnect('group')
})
defineExpose({
init
})
</script>
<style lang="scss" scoped>
.shutDown {
position: absolute;
right: 10px;
top: 10px;
}
.select {
position: absolute;
top: 10px;
display: flex;
align-items: center;
font-size: 14px;
}
</style>

View File

@@ -1,57 +1,96 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true">
<el-form-item label="多监测点">
<el-checkbox v-model="checked" @change="checkChange" />
</el-form-item>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="指标类型:">
<el-select v-model="formData.condition" multiple collapse-tags :multiple-limit="5" filterable
placeholder="请选择指标" @change="conditionChange">
<el-option-group v-for="group in indexOptions" :key="group.label" :label="group.label">
<el-option v-for="item in group.options" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item label="数值类型:">
<el-select style="width: 100%" v-model="formData.valueType" placeholder="请选择类型">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-if="showXieBoCiShu">
<el-select style="width: 100%" v-model="formData.harmonic" placeholder="请选择谐波">
<el-option v-for="item in harmonicOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="showJianXieBoCiShu" label="间谐波次数:">
<el-select style="width: 100%" v-model="formData.inHarmonic" placeholder="请选择间谐波">
<el-option v-for="item in inharmonicOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
<div style="flex: 1; overflow-y: scroll" class="mt10">
<my-echart :options="item.option" v-for="item in list" :style="height" />
<div>
<div v-show="view">
<TableHeader ref="tableHeaderRef" :showSearch="false" @selectChange="selectChange">
<template v-slot:select>
<el-form-item label="多监测点">
<el-checkbox v-model="checked" @change="checkChange" />
</el-form-item>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="指标类型:">
<el-select
v-model="formData.condition"
multiple
collapse-tags
:multiple-limit="5"
filterable
placeholder="请选择指标"
@change="conditionChange"
>
<el-option-group v-for="group in indexOptions" :key="group.label" :label="group.label">
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item label="数值类型:">
<el-select style="width: 100%" v-model="formData.valueType" placeholder="请选择类型">
<el-option
v-for="item in typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-show="showXieBoCiShu">
<el-select style="width: 100%" v-model="formData.harmonic" placeholder="请选择谐波">
<el-option
v-for="item in harmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-show="showJianXieBoCiShu" label="间谐波次数:">
<el-select style="width: 100%" v-model="formData.inHarmonic" placeholder="请选择间谐波">
<el-option
v-for="item in inharmonicOptions"
: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="init" icon="el-icon-Search">查询</el-button>
</template>
</TableHeader>
<!-- <el-form :inline="true">
</el-form> -->
<div id="canvas" class="mt10" :style="height1" v-loading="loading">
<my-echart :options="item.option" v-for="item in list" :style="height" @triggerPoint="triggerPoint" />
</div>
</div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
<waveForm ref="waveFormRef" senior @backbxlb="backbxlb" />
</div>
</div>
</template>
<script setup lang="ts">
import { nextTick, onMounted, reactive, ref } from 'vue'
import { nextTick, onMounted, reactive, ref, onBeforeUnmount } from 'vue'
import DatePicker from '@/components/form/datePicker/index.vue'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { indexOptions, harmonicOptions, inharmonicOptions } from '@/utils/dictionary'
import { getHistoryResult } from '@/api/harmonic-boot/harmonic'
import { mainHeight } from '@/utils/layout'
import TableHeader from '@/components/table/header/index.vue'
import { queryEventDetailByEventId } from '@/api/event-boot/highAndLowPressure'
import TableStore from '@/utils/tableStore'
import waveForm from '@/components/echarts/waveForm.vue'
import html2canvas from 'html2canvas'
import * as echarts from 'echarts' // 全引入
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const checked = ref(monitoringPoint.state.showCheckBox)
@@ -75,6 +114,16 @@ const formData = reactive<{
inHarmonic: 1,
ptType: 0
})
const wp = ref({})
const pageHeight = mainHeight(20)
const view = ref(true)
const waveFormRef = ref()
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const tableHeaderRef = ref()
const options = ref({})
const traceability = ref<any>([])
const list = ref<any>([])
@@ -90,6 +139,7 @@ onMounted(() => {
init()
})
const height: any = ref(mainHeight(200, 1))
const height1: any = ref(mainHeight(200))
const checkChange = () => {
if (checked.value) {
monitoringPoint.setShowCheckBox(true)
@@ -111,14 +161,19 @@ const init = () => {
return false
}
})
getHistoryResult(formData).then((res: any) => {
if (directionValue >= 0) {
res.data[directionValue].targetName = '谐波电流方向'
traceability.value = [(res.data as [])[directionValue]]
}
list.value = []
shujuchuli(res)
})
getHistoryResult(formData)
.then((res: any) => {
if (directionValue >= 0) {
res.data[directionValue].targetName = '谐波电流方向'
traceability.value = [(res.data as [])[directionValue]]
}
list.value = []
shujuchuli(res)
loading.value = false
})
.catch(() => {
loading.value = false
})
}
const shujuchuli = (res: any) => {
let shujuData = res.data
@@ -1091,11 +1146,10 @@ const shujuchuli = (res: any) => {
rendering()
}
const rendering = () => {
height.value = mainHeight(200, list.value.length > 1 ? 2 : 1)
height.value = mainHeight(160, list.value.length)
list.value.forEach((item: any) => {
if (item.targetName == '电压不平衡') {
item.valueName = ''
item.legend = item.legend.map((item2: any) => {
if (item2 == '零序电压') {
@@ -1107,7 +1161,6 @@ const rendering = () => {
}
return item2
})
}
let opitonserise: any[] = []
@@ -1335,7 +1388,7 @@ const getEcharts = () => {
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.35)',
backgroundColor: 'rgba(0,0,0,0.55)',
formatter: function (params: any) {
let tips = ''
@@ -1350,39 +1403,39 @@ const getEcharts = () => {
params[i].value[1] > 0
? 'A相谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? 'A相谐波电流方向:无<br/>'
: 'A相谐波电流方向:流出<br/>'
? 'A相谐波电流方向:无<br/>'
: 'A相谐波电流方向:流出<br/>'
} else if (params[i].seriesName == 'B相谐波电流方向') {
tips +=
params[i].value[1] > 0
? 'B相谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? 'B相谐波电流方向:无<br/>'
: 'B相谐波电流方向:流出<br/>'
? 'B相谐波电流方向:无<br/>'
: 'B相谐波电流方向:流出<br/>'
} else if (params[i].seriesName == 'C相谐波电流方向') {
tips +=
params[i].value[1] > 0
? 'C相谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? 'C相谐波电流方向:无<br/>'
: 'C相谐波电流方向:流出<br/>'
? 'C相谐波电流方向:无<br/>'
: 'C相谐波电流方向:流出<br/>'
} else if (params[i].seriesName == '总谐波电流方向') {
tips +=
params[i].value[1] > 0
? '总谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? '总谐波电流方向:无<br/>'
: '总谐波电流方向:流出<br/>'
? '总谐波电流方向:无<br/>'
: '总谐波电流方向:流出<br/>'
} else if (params[i].seriesName == '正序电压(kV)') {
let str = (params[i].value[1] * 1).toString()
let reg = str.indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
let str1 = str.replace(reg, '$1,')
tips += params[i].seriesName.replace("(kV)", "") + ':' + str1 + 'kV<br/>'
tips += params[i].seriesName.replace('(kV)', '') + ':' + str1 + 'kV<br/>'
} else if (params[i].seriesName == '零序电压(V)' || params[i].seriesName == '负序电压(V)') {
let str = (params[i].value[1] * 1).toString()
let reg = str.indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
let str1 = str.replace(reg, '$1,')
tips += params[i].seriesName.replace("(V)", "") + ':' + str1 + 'V<br/>'
tips += params[i].seriesName.replace('(V)', '') + ':' + str1 + 'V<br/>'
} else if (params[i].seriesName !== '正序电压(kV)') {
let str = (params[i].value[1] * 1).toString()
let reg = str.indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
@@ -1407,9 +1460,35 @@ const getEcharts = () => {
return tips
}
},
toolbox: {
right: 20,
top: 15,
show: i == 0 ? true : false,
feature: {
// 移除默认的 saveAsImage
// saveAsImage: { title: '保存图片' }
myCustomDownload: {
title: '', // 按钮标题
icon: 'path://M892.342857 463.238095l-73.142857-68.266666-258.438095 258.438095V29.257143h-97.52381v624.152381L204.8 394.971429 131.657143 463.238095l380.342857 380.342857zM107.27619 897.219048h804.571429v97.523809H107.27619z', // 自定义图标路径
onclick: function () {
html2canvas(document.getElementById('canvas'), {
scale: 1
}).then(function (canvas) {
// 创建a标签实现下载
let creatIMg = document.createElement('a')
creatIMg.download = '稳态数据分析.png' // 设置下载的文件名,
creatIMg.href = canvas.toDataURL() // 下载url
creatIMg.click()
creatIMg.remove() // 下载之后把创建的元素删除
})
}
}
}
},
legend: {
left: '50px',
top: '25px',
right: 50,
top: 25,
verticalAlign: 'top',
enabled: true,
itemDistance: 5,
@@ -1424,7 +1503,7 @@ const getEcharts = () => {
}
},
grid: {
top: '70px',
top: '70px'
},
xAxis: [
{
@@ -1468,7 +1547,7 @@ const getEcharts = () => {
show: true,
onZero: false, //-----------重点
lineStyle: {}
},
}
// splitLine: {
// lineStyle: {
// // 使用深浅的间隔色
@@ -1589,6 +1668,7 @@ const getEcharts = () => {
]
}
})
echarts.connect('group')
}
const conditionChange = () => {
//判断一个指标时
@@ -1725,6 +1805,39 @@ const conditionChange = () => {
{ label: 'cp95值', value: 4 }
]
}
setTimeout(() => {
console.log('🚀 ~ setTimeout ~ tableHeaderRef.value:', tableHeaderRef.value)
tableHeaderRef.value && tableHeaderRef.value?.computedSearchRow()
}, 100)
}
// 点击暂降触发点
const triggerPoint = (data: any) => {
let nameList = monitoringPoint.state.lineName.split('>')
view.value = false
setTimeout(() => {
queryEventDetailByEventId({ eventId: data[2] }).then(res => {
waveFormRef.value.open({
...res.data,
subName: nameList[nameList.length - 2].split('')[0] || nameList[nameList.length - 2],
lineName: nameList[nameList.length - 1].split('_')[1] || nameList[nameList.length - 1]
})
waveFormRef.value.setHeight(220, 180)
})
}, 100)
}
// 计算高度
const selectChange = (flag: boolean) => {
height.value = mainHeight(flag ? 220 : 160, list.value.length)
}
const backbxlb = () => {
view.value = true
}
provide('tableStore', tableStore)
onBeforeUnmount(() => {
echarts.disconnect('group')
})
</script>
<style></style>

View File

@@ -1,19 +1,26 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true">
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="对比">
<el-select v-model="searchType" clearable placeholder="可选择同比、环比">
<el-option v-for="item in searchTypeOptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<TableHeader ref="TableHeaderRef" :showSearch="false">
<template v-slot:select>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="对比">
<el-select v-model="searchType" clearable placeholder="可选择同比、环比">
<el-option
v-for="item in searchTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
</template>
</TableHeader>
<div style="flex: 1" class="mt10" v-loading="loading">
<my-echart :options="options" />
</div>
@@ -26,7 +33,13 @@ import MyEchart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { getSteadyData } from '@/api/harmonic-boot/pollution'
import { gradeColor3 } from '@/components/echarts/color'
import { formatter } from 'element-plus'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
@@ -289,7 +302,7 @@ const init = () => {
})
})
}
provide('tableStore', tableStore)
onMounted(() => {
init()
})

View File

@@ -1,7 +1,8 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true">
<el-form-item label="日期">
<TableHeader ref="TableHeaderRef" :showSearch="false" >
<template v-slot:select>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="指标">
@@ -10,10 +11,13 @@
<el-radio-button :label="1">谐波电流幅值</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
</template>
</TableHeader>
<vxe-table :data="analysisData" v-bind="defaultAttribute">
<vxe-column field="name" title="指标" width="140px"></vxe-column>
<vxe-column
@@ -35,7 +39,13 @@ import MyEchart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { getHarmInHarmData } from '@/api/harmonic-boot/inHarm'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
@@ -107,6 +117,7 @@ const init = () => {
})
})
}
provide('tableStore', tableStore)
onMounted(() => {
init()
})

View File

@@ -1,7 +1,8 @@
<template>
<div style="display: flex; flex-direction: column; height: 100%">
<el-form :inline="true">
<el-form-item label="日期">
<TableHeader ref="TableHeaderRef" :showSearch="false" >
<template v-slot:select>
<el-form-item label="日期">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
<el-form-item label="对比">
@@ -14,10 +15,12 @@
/>
</el-select>
</el-form-item>
<el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" @click="init" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
</template>
</TableHeader>
<div style="flex: 1; display: flex; overflow: hidden" class="mt10" v-loading="loading">
<div style="flex: 1">
<my-echart :options="options1" />
@@ -35,7 +38,13 @@ import MyEchart from '@/components/echarts/MyEchart.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { getProbabilityDistribution } from '@/api/event-boot/monitor'
import { getRunInfoData, getComFlagInfoData } from '@/api/device-boot/communicate'
import TableHeader from '@/components/table/header/index.vue'
import TableStore from '@/utils/tableStore'
const tableStore = new TableStore({
url: '',
method: 'POST',
column: []
})
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const loading = ref(true)
@@ -173,5 +182,6 @@ const handlerOptions2 = (data: any) => {
]
}
}
provide('tableStore', tableStore)
</script>
<style></style>