修改异常数据页面、修改有功功率趋势分析页面接口

This commit is contained in:
GGJ
2025-04-08 16:33:07 +08:00
parent 69aece65c1
commit 3d5c73b268
20 changed files with 2605 additions and 879 deletions

View File

@@ -1,4 +1,3 @@
<!--业务用户管理界面-->
<template>
<div>
<TableHeader date-picker ref="TableHeaderRef">
@@ -22,7 +21,7 @@
<template v-slot:operation></template>
</TableHeader>
<div class="card-list pt10">
<div class="card-list pt10" v-loading="loading">
<div class="monitoringPoints">
<el-card style="height: 200px">
<template #header>
@@ -38,9 +37,9 @@
<span class="divBox_num" style="color: #57bc6e">{{ monitoringPoints.runNum }}</span>
</div>
<div class="divBox" style="width: 200px">
<span class="iconfont icon-igw-f-warning-data" style="color: #fca955"></span>
<span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span>
<span class="divBox_title">异常测点数</span>
<span class="divBox_num" style="color: #fca955">
<span class="divBox_num" style="color: #ff6600">
{{ monitoringPoints.abnormalNum }}
</span>
</div>
@@ -67,7 +66,14 @@
</div>
</template>
<div class="mb5" style="height: 40px">
<el-segmented style="height: 100%" v-model="segmented" :options="segmentedList" block />
<el-segmented style="height: 100%" v-model="segmented" :options="segmentedList" block>
<template #default="scope">
<div >
<div class="segmentedIcon">0</div>
<div>{{ scope.item.label }}</div>
</div>
</template>
</el-segmented>
</div>
<div class="header">
<span style="width: 170px; text-align: left">指标名称</span>
@@ -77,7 +83,7 @@
<div :style="indicatorHeight" style="overflow-y: auto">
<div v-for="o in abnormal" class="abnormal mb10">
<span style="width: 170px; height: 24px" class="iconDiv">
<div :style="{ backgroundColor: o.ids.length > 0 ? '#ff9800' : '' }"></div>
<div :style="{ backgroundColor: o.ids.length > 0 ? '#FF9100' : '' }"></div>
{{ o.targetName }}
</span>
<span style="flex: 1; text-align: center">
@@ -86,9 +92,10 @@
</span>
<span style="width: 90px; text-align: center">
<span
style="color: #ff9800; cursor: pointer; text-decoration: underline"
style="color: #388e3c"
:class="` ${o.ids.length > 0 ? 'text-red' : ''}`"
class="text"
@click="quantityClick(o)"
@click="quantityClick(o, 0)"
>
{{ o.ids.length }}
</span>
@@ -130,7 +137,58 @@
</el-form-item>
</el-form>
<!--表格-->
<Table ref="tableRef"></Table>
<div :style="{ height: tableStore.table.height }" v-loading="tableStore.table.loading">
<vxe-table height="auto" :data="tableStore.table.data" v-bind="defaultAttribute" ref="tableRef">
<vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }">
<span>
{{
(tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize +
rowIndex +
1
}}
</span>
</template>
</vxe-column>
<vxe-column field="monitorName" title="监测点名称">
<template #default="{ row }">
<span class="table_name">
{{ row.monitorName }}
</span>
</template>
</vxe-column>
<vxe-column field="devName" title="所属终端名称">
<template #default="{ row }">
<span class="table_name">
{{ row.devName }}
</span>
</template>
</vxe-column>
<vxe-column field="stationName" title="所属电站">
<template #default="{ row }">
<span class="table_name">
{{ row.stationName }}
</span>
</template>
</vxe-column>
<vxe-column field="objType" title="监测对象类型" :formatter="formatter"></vxe-column>
<vxe-column field="objName" title="监测对象名称" :formatter="formatter"></vxe-column>
<vxe-column field="voltageLevel" title="电压等级"></vxe-column>
<vxe-column field="abnormalDay" title="异常天数">
<template #default="{ row }">
<span class="table_name" @click="quantityClick(row, 1)">
{{ row.abnormalDay }}
</span>
</template>
</vxe-column>
<vxe-column field="abnormalDay" title="严重度">
<template #default="{ row }">
<el-tag type="warning" v-if="row.severity == 0">预警</el-tag>
<el-tag type="danger" v-if="row.severity == 1">告警</el-tag>
</template>
</vxe-column>
</vxe-table>
</div>
</el-card>
</div>
<anomalyDetails ref="anomalyDetailsRef" />
@@ -142,6 +200,7 @@ import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import MyEchart from '@/components/echarts/MyEchart.vue'
@@ -153,30 +212,31 @@ const anomalyDetailsRef = ref()
const dictData = useDictData()
//字典获取监督对象类型
const objTypeList: any = ref([])
const pageHeight = mainHeight(155)
const pageHeight = mainHeight(157)
const indicatorHeight = mainHeight(507)
const tableRef = ref()
const monitoringPoints = ref({
runNum: 0,
abnormalNum: 0
})
const tableRef = ref()
const percentage = ref({})
const loading = ref(false)
const TableHeaderRef = ref()
const abnormal: any = ref([])
const mapList: any = ref([])
const segmented = ref(1)
const time = ref(['', ''])
const segmentedList = [
{
label: '基础数据',
label: '基础指标',
value: 1
},
{
label: '稳态数据',
label: '稳态指标',
value: 2
},
{
label: '暂态数据',
label: '暂态指标',
value: 3
}
]
@@ -184,87 +244,13 @@ const tableStore = new TableStore({
url: '/device-boot/dataVerify/getMonitorVerifyData',
method: 'POST',
showPage: false,
filename: '异常数据',
filename: '异常数据统计',
publicHeight: 530,
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
title: '监测点名称',
field: 'monitorName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '所属终端名称',
field: 'devName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '所属电站',
field: 'stationName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '监测对象类型',
field: 'objType'
},
{
title: '监测对象名称',
field: 'objName'
},
{ title: '电压等级', field: 'voltageLevel' },
{
title: '异常天数',
field: 'abnormalDay',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '严重度',
field: 'severity',
render: 'tag',
custom: {
0: 'warning',
1: 'danger'
},
replaceValue: {
0: '预警',
1: '告警'
}
},
// {
// title: '操作',
// width: '120',
// render: 'buttons',
// buttons: [
// {
// name: 'edit',
// title: '工单',
// type: 'primary',
// icon: 'el-icon-Plus',
// render: 'basicButton',
// click: row => {}
// }
// ]
// }
],
column: [],
beforeSearchFun: () => {
loading.value = true
time.value = [tableStore.table.params.startTime, tableStore.table.params.endTime]
},
loadCallback: () => {
// console.log('🚀 ~ abnormal.value:', tableStore.table.data)
monitoringPoints.value.runNum = tableStore.table.data.runNum //总数
@@ -275,13 +261,14 @@ const tableStore = new TableStore({
tableStore.table.data = tableStore.table.data.monitorAlarmInfo
echart()
loading.value = false
}
})
const options = ref({})
const echart = () => {
percentage.value = {
color: ['#ff9800'],
color: ['#FF9100'],
options: {
dataZoom: null,
toolbox: {
@@ -312,13 +299,42 @@ const echart = () => {
series: [
{
name: '异常占比',
name: '异常总数',
type: 'bar',
barWidth: 12,
data: [((monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100).toFixed(2)],
data: [100],
z: 0,
zlevel: 0,
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 1,
color: '#57bc6e' // 100% 处的颜色
}
],
global: false // 缺省为 false
}
}
}
},
{
name: '异常占比',
type: 'bar',
barWidth: 13,
data: [
(monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100 == 0
? ''
: ((monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100).toFixed(2)
],
z: 0,
zlevel: 0,
itemStyle: {
normal: {
color: {
@@ -330,11 +346,11 @@ const echart = () => {
colorStops: [
{
offset: 0,
color: '#FD6E6A' // 0% 处的颜色
color: '#FF9100' // 0% 处的颜色
},
{
offset: 1,
color: '#ff9800' // 100% 处的颜色
color: '#FF9100' // 100% 处的颜色
}
],
global: false // 缺省为 false
@@ -353,7 +369,7 @@ const echart = () => {
// symbolMargin: 300,
symbol: 'rect',
symbolClip: true,
symbolSize: [2, 15],
symbolSize: [2, 20],
symbolPosition: 'start',
symbolOffset: [0, 0],
data: [100],
@@ -361,9 +377,9 @@ const echart = () => {
zlevel: 0
},
{
name: '机器故障率',
name: '',
type: 'bar',
barGap: '-125%',
barGap: '-110%',
data: [100],
barWidth: 18,
@@ -381,7 +397,7 @@ const echart = () => {
}
options.value = {
title: {
text: `监测点异常情况(${mapList.value[0].time} ~ ${mapList.value[mapList.value.length - 1].time})`
text: `监测点异常统计(${mapList.value[0].time} ~ ${mapList.value[mapList.value.length - 1].time})`
},
xAxis: {
name: '时间',
@@ -405,7 +421,7 @@ const echart = () => {
name: '数量' // 给X轴加单位
},
grid: {},
color: ['#FF9100'],
options: {
series: [
{
@@ -426,8 +442,9 @@ tableStore.table.params.objType = ''
tableStore.table.params.alarmDayLimit = 5
tableStore.table.params.warnDayLimit = 1
const quantityClick = (e: any) => {
anomalyDetailsRef.value.open(e)
const quantityClick = (e: any, num: number) => {
if (num == 0 && e.ids?.length == 0) return
anomalyDetailsRef.value.open(e, time.value, num)
}
// 更新
const MonitorVerify = () => {
@@ -438,9 +455,25 @@ const MonitorVerify = () => {
tableStore.table.loading = false
})
}
const formatter = (row: any) => {
return row.cellValue || '/'
}
// 导出
const onExport = () => {
tableStore.table.allFlag = true
tableRef.value?.exportData({
filename: tableStore.table.filename, // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: tableStore.table.data, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
})
}
onMounted(() => {
TableHeaderRef.value.setDatePicker([
@@ -577,7 +610,7 @@ provide('tableStore', tableStore)
font-weight: 600;
div:nth-child(2) {
font-size: 16px;
color: #fca955;
color: #ff6600;
}
}
@@ -586,8 +619,26 @@ provide('tableStore', tableStore)
}
:deep(.el-segmented__item, ) {
clip-path: polygon(10% 0, 100% 0, 90% 100%, 0 100%);
position: relative
}
:deep(.el-segmented) {
clip-path: polygon(4% 0, 100% 0, 96% 100%, 0 100%);
}
.text-red {
color: #ff9100 !important;
cursor: pointer;
text-decoration: underline;
}
.segmentedIcon {
position: absolute;
top: 1px;
left: 100px;
height: 18px !important;
line-height: 19px;
padding: 0 4px;
font-size: 12px;
background: #ff9100;
color: #fff;
border-radius: 8px;
}
</style>

View File

@@ -1,7 +1,6 @@
<!--业务用户管理界面-->
<template>
<div>
<TableHeader date-picker>
<TableHeader date-picker ref="TableHeaderRef">
<template v-slot:select>
<el-form-item label="对象类型">
<el-select
@@ -22,7 +21,7 @@
<template v-slot:operation></template>
</TableHeader>
<div class="card-list pt10">
<div class="card-list pt10" v-loading="loading">
<div class="monitoringPoints">
<el-card style="height: 200px">
<template #header>
@@ -38,9 +37,9 @@
<span class="divBox_num" style="color: #57bc6e">{{ monitoringPoints.runNum }}</span>
</div>
<div class="divBox" style="width: 200px">
<span class="iconfont icon-yichang" style="color: #ff0000"></span>
<span class="iconfont icon-yichang" style="color: #FFBF00"></span>
<span class="divBox_title">告警测点数</span>
<span class="divBox_num" style="color: #ff0000">
<span class="divBox_num" style="color: #FFBF00">
{{ monitoringPoints.abnormalNum }}
</span>
</div>
@@ -66,9 +65,7 @@
<span>告警指标统计</span>
</div>
</template>
<div class="mb5" style="height: 40px">
<el-segmented style="height: 100%" v-model="segmented" :options="segmentedList" block />
</div>
<div class="header">
<span style="flex: 1; text-align: left">指标名称</span>
@@ -77,15 +74,16 @@
<div :style="indicatorHeight" style="overflow-y: auto">
<div v-for="o in abnormal" class="abnormal mb10">
<span style="flex: 1; height: 24px" class="iconDiv">
<div :style="{ backgroundColor: o.ids.length > 0 ? '#ff9800' : '' }"></div>
<div :style="{ backgroundColor: o.ids.length > 0 ? '#FFBF00' : '' }"></div>
{{ o.targetName }}
</span>
<span style="width: 110px; text-align: center">
<span
style="color: #ff9800; cursor: pointer; text-decoration: underline"
style="color: #388e3c"
:class="` ${o.ids.length > 0 ? 'text-red' : ''}`"
class="text"
@click="quantityClick(o)"
@click="quantityClick(o, 0)"
>
{{ o.ids.length }}
</span>
@@ -122,12 +120,64 @@
/>
</el-form-item>
<el-form-item class="form_but">
<el-button type="primary" icon="el-icon-Refresh">更新</el-button>
<el-button type="primary" icon="el-icon-Download">导出</el-button>
<el-button type="primary" @click="MonitorVerify" icon="el-icon-Refresh">更新</el-button>
<el-button type="primary" @click="onExport" icon="el-icon-Download">导出</el-button>
</el-form-item>
</el-form>
<!--表格-->
<Table ref="tableRef"></Table>
<div :style="{ height: tableStore.table.height }" v-loading="tableStore.table.loading">
<vxe-table height="auto" :data="tableStore.table.data" v-bind="defaultAttribute" ref="tableRef">
<vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }">
<span>
{{
(tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize +
rowIndex +
1
}}
</span>
</template>
</vxe-column>
<vxe-column field="monitorName" title="监测点名称">
<template #default="{ row }">
<span class="table_name">
{{ row.monitorName }}
</span>
</template>
</vxe-column>
<vxe-column field="devName" title="所属终端名称">
<template #default="{ row }">
<span class="table_name">
{{ row.devName }}
</span>
</template>
</vxe-column>
<vxe-column field="stationName" title="所属电站">
<template #default="{ row }">
<span class="table_name">
{{ row.stationName }}
</span>
</template>
</vxe-column>
<vxe-column field="objType" title="监测对象类型" :formatter="formatter"></vxe-column>
<vxe-column field="objName" title="监测对象名称" :formatter="formatter"></vxe-column>
<vxe-column field="voltageLevel" title="电压等级"></vxe-column>
<vxe-column field="abnormalDay" title="告警天数">
<template #default="{ row }">
<span class="table_name" @click="quantityClick(row, 1)">
{{ row.abnormalDay }}
</span>
</template>
</vxe-column>
<vxe-column field="abnormalDay" title="严重度">
<template #default="{ row }">
<el-tag type="warning" v-if="row.severity == 0">预警</el-tag>
<el-tag type="danger" v-if="row.severity == 1">告警</el-tag>
</template>
</vxe-column>
</vxe-table>
</div>
<!-- <Table ref="tableRef"></Table> -->
</el-card>
</div>
<alarmDetails ref="alarmDetailsRef" />
@@ -139,178 +189,63 @@ import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import MyEchart from '@/components/echarts/MyEchart.vue'
import alarmDetails from './alarmDetails.vue'
import { useConfig } from '@/stores/config'
import { getMonitorLimitDataDay } from '@/api/device-boot/dataVerify'
import { queryFirstNode } from '@/api/auth'
const alarmDetailsRef = ref()
const dictData = useDictData()
//字典获取监督对象类型
const objTypeList: any = ref([])
const pageHeight = mainHeight(155)
const indicatorHeight = mainHeight(507)
const tableRef = ref()
const pageHeight = mainHeight(157)
const indicatorHeight = mainHeight(462)
const monitoringPoints = ref({
runNum: 0,
abnormalNum: 0
})
const tableRef = ref()
const percentage = ref({})
const loading = ref(false)
const TableHeaderRef = ref()
const abnormal: any = ref([])
const mapList: any = ref([])
const segmented = ref(1)
const segmentedList = [
{
label: '基础数据',
value: 1
},
{
label: '稳态数据',
value: 2
},
{
label: '暂态数据',
value: 3
}
]
const time = ref(['', ''])
const tableStore = new TableStore({
url: '/device-boot/dataVerify/getMonitorVerifyData',
url: '/device-boot/dataVerify/getMonitorLimitData',
method: 'POST',
showPage: false,
publicHeight: 480,
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
title: '监测点名称',
field: 'monitorName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '所属终端名称',
field: 'devName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">测试终端</div>`
// `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '所属电站',
field: 'stationName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '监测对象类型',
field: 'objType',
formatter: (row, column) => {
return `测试光伏电站`
}
},
{
title: '监测对象名称',
field: 'objName',
formatter: (row, column) => {
return `测试对象`
}
},
{ title: '电压等级', field: 'voltageLevel' },
{
title: '告警天数',
field: 'abnormalDay',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '严重度',
field: 'severity',
render: 'tag',
custom: {
0: 'warning',
1: 'danger'
},
replaceValue: {
0: '预警',
1: '告警'
}
},
{
title: '操作',
width: '120',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '工单',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {}
}
]
}
],
filename: '稳态告警统计',
publicHeight: 530,
column: [],
beforeSearchFun: () => {
loading.value = true
time.value = [tableStore.table.params.startTime, tableStore.table.params.endTime]
},
loadCallback: () => {
console.log('🚀 ~ abnormal.value:', tableStore.table.data)
// console.log('🚀 ~ abnormal.value:', tableStore.table.data)
monitoringPoints.value.runNum = tableStore.table.data.runNum //总数
monitoringPoints.value.abnormalNum = tableStore.table.data.abnormalNum //告警测点数
abnormal.value = tableStore.table.data.targetList
mapList.value = tableStore.table.data.mapList
tableStore.table.allData = tableStore.table.data.monitorAlarmInfo
tableStore.table.data = tableStore.table.data.monitorAlarmInfo
echart()
loading.value = false
}
})
const options = ref({
title: {
text: '监测点告警情况(2025-03-01~2025-03-10)'
},
legend: {
show: false
},
xAxis: {
name: '时间',
axisLine: {
show: true
},
data: ['03-01', '03-02', '03-03', '03-04', '03-05', '03-06', '03-07', '03-08', '03-09', '03-10']
},
yAxis: {
name: '数量' // 给X轴加单位
},
grid: {},
options: {
series: [
{
name: '告警监测点数量',
type: 'bar',
data: [11, 11, 11, 11, 0, 0, 0, 0, 0, 0]
}
]
}
})
const options = ref({})
const echart = () => {
percentage.value = {
color: ['#ff9800'],
color: ['#FFBF00'],
options: {
dataZoom: null,
toolbox: {
@@ -318,8 +253,8 @@ const echart = () => {
},
grid: {
top: '0%',
left: '2%',
right: '2%',
left: '0%',
right: '0%',
bottom: '0%'
},
tooltip: {
@@ -340,11 +275,41 @@ const echart = () => {
],
series: [
{
name: '告警总数',
type: 'bar',
barWidth: 12,
data: [100],
z: 0,
zlevel: 0,
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 1,
color: '#57bc6e' // 100% 处的颜色
}
],
global: false // 缺省为 false
}
}
}
},
{
name: '告警占比',
type: 'bar',
barWidth: 12,
data: [((monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100).toFixed(2)],
data: [
((monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100) == 0
? ''
: ((monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100).toFixed(2)
],
z: 0,
zlevel: 0,
@@ -359,11 +324,11 @@ const echart = () => {
colorStops: [
{
offset: 0,
color: '#ff0007' // 0% 处的颜色
color: '#FFBF00' // 0% 处的颜色
},
{
offset: 1,
color: '#E22331' // 100% 处的颜色
color: '#FFBF00' // 100% 处的颜色
}
],
global: false // 缺省为 false
@@ -382,7 +347,7 @@ const echart = () => {
// symbolMargin: 300,
symbol: 'rect',
symbolClip: true,
symbolSize: [2, 15],
symbolSize: [2, 20],
symbolPosition: 'start',
symbolOffset: [0, 0],
data: [100],
@@ -390,9 +355,9 @@ const echart = () => {
zlevel: 0
},
{
name: '机器故障率',
name: '',
type: 'bar',
barGap: '-125%',
barGap: '-110%',
data: [100],
barWidth: 18,
@@ -408,16 +373,92 @@ const echart = () => {
]
}
}
options.value = {
title: {
text: `监测点告警统计(${mapList.value[0].time} ~ ${mapList.value[mapList.value.length - 1].time})`
},
xAxis: {
name: '时间',
axisLine: {
show: true
},
data: mapList.value.map(item => item.time),
axisLabel: {
formatter: function (value) {
let time = ''
if (value.slice(-2) == '01') {
time = value
} else {
time = value.slice(5, 10)
}
return time
}
}
},
yAxis: {
name: '数量' // 给X轴加单位
},
grid: {},
color: ['#FFBF00'],
options: {
series: [
{
name: '告警监测点数量',
type: 'bar',
data: mapList.value.map(item => item.val)
// mapList.value.map(item => ({
// value: [item.time, item.val]
// }))
}
]
}
}
}
tableStore.table.params.deptId = dictData.state.area[0].id
tableStore.table.params.objType = ''
tableStore.table.params.alarmDayLimit = 5
tableStore.table.params.warnDayLimit = 1
const quantityClick = (e: any) => {
alarmDetailsRef.value.open(e)
const quantityClick = (e: any, num: number) => {
if (num == 0 && e.ids?.length == 0) return
alarmDetailsRef.value.open(e, time.value, num)
}
// 更新
const MonitorVerify = () => {
tableStore.table.loading = true
getMonitorLimitDataDay(tableStore.table.params).then(res => {
tableStore.table.data = res.data
tableStore.table.allData = res.data
tableStore.table.loading = false
})
}
const formatter = (row: any) => {
return row.cellValue || '/'
}
// 导出
const onExport = () => {
tableRef.value?.exportData({
filename: tableStore.table.filename, // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: tableStore.table.data, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
})
}
onMounted(() => {
TableHeaderRef.value.setDatePicker([
{ label: '年份', value: 1 },
{ label: '季度', value: 2 },
{ label: '月份', value: 3 }
])
queryFirstNode({ type: 0 }).then(res => {
objTypeList.value = res.data
})
@@ -437,8 +478,9 @@ provide('tableStore', tableStore)
.statistics {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-bottom: 10px;
.divBox {
margin: 0 10px 10px 0;
width: 200px;
height: 70px;
padding: 10px;
@@ -464,7 +506,7 @@ provide('tableStore', tableStore)
background-color: #eef8f0;
}
&:nth-child(2) {
background-color: #ffd7d7;
background-color: #fff6ed;
}
&:nth-child(3) {
background-color: #e5f8f6;
@@ -546,7 +588,7 @@ provide('tableStore', tableStore)
font-weight: 600;
div:nth-child(2) {
font-size: 16px;
color: #ff0000;
color: #FFBF00;
}
}
@@ -559,4 +601,9 @@ provide('tableStore', tableStore)
:deep(.el-segmented) {
clip-path: polygon(4% 0, 100% 0, 96% 100%, 0 100%);
}
.text-red {
color: #FFBF00 !important;
cursor: pointer;
text-decoration: underline;
}
</style>

View File

@@ -1,37 +1,51 @@
<template>
<el-dialog draggable width="1300px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<el-dialog draggable width="1200px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<div style="display: flex">
<div :style="height1" class="mr10" style="width: 450px">
<vxe-table height="auto" :data="TableData" v-bind="defaultAttribute">
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="time" title="日期">
<template #default="{ row }">
<span class="time">{{ row.time }}</span>
</template>
</vxe-column>
<vxe-column field="name" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="fz" title="告警时间(分钟)" width="80px"></vxe-column>
</vxe-table>
</div>
<el-tabs v-model="activeName" type="border-card" style="width: 820px">
<el-tab-pane :label="`变电站1 > 测试监测点1_告警指标详情`" name="first">
<div :style="height">
<vxe-table height="auto" :data="TableData1" v-bind="defaultAttribute">
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="time" title="时间" min-width="120px"></vxe-column>
<vxe-column field="indexType" title="指标类型" min-width="100px"></vxe-column>
<vxe-column field="phase" title="相别" width="60px"></vxe-column>
<vxe-column field="range" title="合理范围" min-width="60px"></vxe-column>
<vxe-column field="max" title="最大" width="60px"></vxe-column>
<vxe-column field="min" title="最小" width="60px"></vxe-column>
<vxe-column field="average" title="平均" width="60px"></vxe-column>
<vxe-column field="cp95" title="CP95" width="60px"></vxe-column>
</vxe-table>
</div>
</el-tab-pane>
</el-tabs>
<div :style="height1" class="mr10 box" style="width: 450px">
<vxe-table
height="auto"
:data="TableData"
v-bind="defaultAttribute"
ref="tableRef"
:row-config="{ isCurrent: true, isHover: true }"
@current-change="currentChangeEvent"
>
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="date" title="日期"></vxe-column>
<vxe-column field="monitorName" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="timeSum" title="告警时间(分钟)" width="80px"></vxe-column>
</vxe-table>
</div>
<div :style="height" style="width: 720px" v-loading="loading1">
<vxe-table
height="auto"
:data="TableData1.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
v-bind="defaultAttribute"
>
<vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }">
<span>{{ (pageNum - 1) * pageSize + rowIndex + 1 }}</span>
</template>
</vxe-column>
<vxe-column field="time" title="时间" width="150px"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="100px"></vxe-column>
<vxe-column field="phaseType" title="相别" width="60px"></vxe-column>
<vxe-column field="type" title="数据类型" width="105px" :formatter="formatter1"></vxe-column>
<vxe-column field="val" title="值" width="85px" :formatter="formatter"></vxe-column>
</vxe-table>
<div class="table-pagination">
<el-pagination
v-model:currentPage="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100, 200]"
background
layout="sizes,total, ->, prev, pager, next, jumper"
:total="TableData1.length"
></el-pagination>
</div>
</div>
</div>
</el-dialog>
</template>
@@ -40,139 +54,79 @@ import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ElMessage } from 'element-plus'
import TableStore from '@/utils/tableStore' // 若不是列表页面弹框可删除
import { monitorLimitTable, monitorLimitTableDetail } from '@/api/device-boot/dataVerify'
import { mainHeight } from '@/utils/layout'
const dialogVisible = ref(false)
const height1 = mainHeight(-110, 2)
const height = mainHeight(10, 2)
const tableRef = ref()
const title = ref('')
const activeName = 'first'
const TableData = ref([
{
time: '2025-01-01',
name: '测试监测点1',
fz: 100
},
{
time: '2025-01-01',
name: '测试监测点2',
fz: 100
},
{
time: '2025-01-01',
name: '测试监测点3',
fz: 100
},
{
time: '2025-01-01',
name: '测试监测点4',
fz: 100
}
])
const TableData1 = ref([
{
num: 1,
time: '2025/01/01 11:10:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: '/',
min: '/',
average: 60,
cp95: '/'
},
{
num: 2,
time: '2025/01/01 11:20:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: '/',
min: '/',
average: 60,
cp95: '/'
},
{
num: 3,
time: '2025/01/01 11:30:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: 65,
min: 60,
average: 62,
cp95: 61
},
{
num: 4,
time: '2025/01/01 11:40:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: 65,
min: 60,
average: 62,
cp95: 61
},
{
num: 5,
time: '2025/01/01 11:50:00',
indexType: '相电压',
phase: 'A',
range: '42.5~57.5',
max: '/',
min: 290,
average: '/',
cp95: '/'
},
{
num: 6,
time: '2025/01/01 12:10:00',
indexType: '相电压',
phase: 'B',
range: '42.5~57.5',
max: 220,
min: 290,
average: 220,
cp95: 220
},
{
num: 7,
time: '2025/01/01 12:20:00',
indexType: '相电压',
phase: 'C',
range: '42.5~57.5',
max: '/',
min: 290,
average: '/',
cp95: '/'
},
{
num: 8,
time: '2025/01/01 12:30:00',
indexType: '相电压',
phase: 'A',
range: '42.5~57.5',
max: 220,
min: 290,
average: 220,
cp95: 220
}
])
const open = (data: anyObj) => {
title.value = data.targetName + '_告警详情展示'
const loading1 = ref(false)
const TableData = ref([])
const TableData1 = ref([])
const pageNum = ref(1)
const pageSize = ref(20)
const numKey = ref(0)
const targetKey = ref('')
const open = (data: anyObj, time: string[], num: number) => {
// title.value = (num == 0 ? data.targetName : data.monitorName) + '_告警详情展示'
title.value = '告警监测点详情'
numKey.value = num
targetKey.value = data.key
TableData.value = []
monitorLimitTable({
monitorIds: num == 0 ? data.ids : [data.monitorId],
targetKey: num == 0 ? data.key : '',
searchBeginTime: time[0],
searchEndTime: time[1]
}).then(res => {
TableData.value = res.data
tableRef.value.setCurrentRow(TableData.value[0])
currentChangeEvent()
})
dialogVisible.value = true
}
const currentChangeEvent = () => {
loading1.value = true
let data = tableRef.value.getCurrentRecord()
TableData1.value = []
monitorLimitTableDetail({
monitorIds: [data.monitorId],
searchBeginTime: data.date,
targetKey: numKey.value == 0 ? targetKey.value : ''
})
.then(res => {
TableData1.value = res.data
loading1.value = false
pageNum.value = 1
})
.catch(() => {
loading1.value = false
})
}
const formatter1 = (row: any) => {
return row.cellValue == null ? '/' : row.cellValue
}
const formatter = (row: any) => {
return row.cellValue == null ? '/' : (row.cellValue - 0).toFixed(2)
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.time {
color: var(--el-color-primary);
cursor: pointer;
text-decoration: underline;
text-underline-offset: 4px;
.table-pagination {
height: 58px;
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
:deep(.box) {
.row--current {
background-color: var(--el-color-primary-light-8) !important;
}
}
</style>

View File

@@ -1,37 +1,53 @@
<template>
<el-dialog draggable width="1300px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<el-dialog draggable width="1400px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<div style="display: flex">
<div :style="height1" class="mr10" style="width: 450px">
<vxe-table height="auto" :data="TableData" v-bind="defaultAttribute">
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="time" title="日期">
<template #default="{ row }">
<span class="time">{{ row.time }}</span>
</template>
</vxe-column>
<vxe-column field="name" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="fz" title="异常时间(分钟)" width="80px"></vxe-column>
</vxe-table>
</div>
<el-tabs v-model="activeName" type="border-card" style="width: 820px">
<el-tab-pane :label="`变电站1 > 测试监测点1_异常指标详情`" name="first">
<div :style="height">
<vxe-table height="auto" :data="TableData1" v-bind="defaultAttribute">
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="time" title="时间" min-width="120px"></vxe-column>
<vxe-column field="indexType" title="指标类型" min-width="100px"></vxe-column>
<vxe-column field="phase" title="相别" width="60px"></vxe-column>
<vxe-column field="range" title="合理范围" min-width="60px"></vxe-column>
<vxe-column field="max" title="最大" width="60px"></vxe-column>
<vxe-column field="min" title="最小" width="60px"></vxe-column>
<vxe-column field="average" title="平均" width="60px"></vxe-column>
<vxe-column field="cp95" title="CP95" width="60px"></vxe-column>
</vxe-table>
</div>
</el-tab-pane>
</el-tabs>
<div :style="height1" class="mr10 box" style="width: 450px">
<vxe-table
height="auto"
:data="TableData"
v-bind="defaultAttribute"
ref="tableRef"
:row-config="{ isCurrent: true, isHover: true }"
@current-change="currentChangeEvent"
>
<vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="date" title="日期"></vxe-column>
<vxe-column field="monitorName" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="timeSum" title="异常时间(分钟)" width="80px"></vxe-column>
</vxe-table>
</div>
<div :style="height" style="width: 920px" v-loading="loading1">
<vxe-table
height="auto"
:data="TableData1.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
v-bind="defaultAttribute"
>
<vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }">
<span>{{ (pageNum - 1) * pageSize + rowIndex + 1 }}</span>
</template>
</vxe-column>
<vxe-column field="time" title="时间" width="150px"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="100px"></vxe-column>
<vxe-column field="phaseType" title="相别" width="60px"></vxe-column>
<vxe-column field="rangeDesc" title="合理范围" min-width="60px"></vxe-column>
<vxe-column field="max" title="最大" width="85px" :formatter="formatter"></vxe-column>
<vxe-column field="min" title="最小" width="85px" :formatter="formatter"></vxe-column>
<vxe-column field="avg" title="平均" width="85px" :formatter="formatter"></vxe-column>
<vxe-column field="cp95" title="CP95" width="85px" :formatter="formatter"></vxe-column>
</vxe-table>
<div class="table-pagination">
<el-pagination
v-model:currentPage="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100, 200]"
background
layout="sizes,total, ->, prev, pager, next, jumper"
:total="TableData1.length"
></el-pagination>
</div>
</div>
</div>
</el-dialog>
</template>
@@ -40,139 +56,76 @@ import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ElMessage } from 'element-plus'
import TableStore from '@/utils/tableStore' // 若不是列表页面弹框可删除
import { monitorAbnormalTable, monitorAbnormalTableDetail } from '@/api/device-boot/dataVerify'
import { mainHeight } from '@/utils/layout'
const dialogVisible = ref(false)
const height1 = mainHeight(-110, 2)
const height = mainHeight(10, 2)
const tableRef = ref()
const title = ref('')
const activeName = 'first'
const TableData = ref([
{
time: '2025-01-01',
name: '测试监测点1',
fz: 100
},
{
time: '2025-01-01',
name: '测试监测点2',
fz: 100
},
{
time: '2025-01-01',
name: '测试监测点3',
fz: 100
},
{
time: '2025-01-01',
name: '测试监测点4',
fz: 100
}
])
const TableData1 = ref([
{
num: 1,
time: '2025/01/01 11:10:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: '/',
min: '/',
average: 60,
cp95: '/'
},
{
num: 2,
time: '2025/01/01 11:20:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: '/',
min: '/',
average: 60,
cp95: '/'
},
{
num: 3,
time: '2025/01/01 11:30:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: 65,
min: 60,
average: 62,
cp95: 61
},
{
num: 4,
time: '2025/01/01 11:40:00',
indexType: '频率',
phase: 'T',
range: '42.5~57.5',
max: 65,
min: 60,
average: 62,
cp95: 61
},
{
num: 5,
time: '2025/01/01 11:50:00',
indexType: '相电压',
phase: 'A',
range: '42.5~57.5',
max: '/',
min: 290,
average: '/',
cp95: '/'
},
{
num: 6,
time: '2025/01/01 12:10:00',
indexType: '相电压',
phase: 'B',
range: '42.5~57.5',
max: 220,
min: 290,
average: 220,
cp95: 220
},
{
num: 7,
time: '2025/01/01 12:20:00',
indexType: '相电压',
phase: 'C',
range: '42.5~57.5',
max: '/',
min: 290,
average: '/',
cp95: '/'
},
{
num: 8,
time: '2025/01/01 12:30:00',
indexType: '相电压',
phase: 'A',
range: '42.5~57.5',
max: 220,
min: 290,
average: 220,
cp95: 220
}
])
const open = (data: anyObj) => {
title.value = data.targetName + '_异常详情展示'
const loading1 = ref(false)
const TableData = ref([])
const TableData1 = ref([])
const pageNum = ref(1)
const pageSize = ref(20)
const numKey = ref(0)
const targetKey = ref('')
const open = (data: anyObj, time: string[], num: number) => {
// title.value = (num == 0 ? data.targetName : data.monitorName) + '_异常监测点详情'
title.value ='异常监测点详情'
TableData.value = []
numKey.value = num
targetKey.value = data.key
monitorAbnormalTable({
monitorIds: num == 0 ? data.ids : [data.monitorId],
targetKey: num == 0 ? data.key : '',
searchBeginTime: time[0],
searchEndTime: time[1]
}).then(res => {
TableData.value = res.data
tableRef.value.setCurrentRow(TableData.value[0])
currentChangeEvent()
})
dialogVisible.value = true
}
const currentChangeEvent = () => {
loading1.value = true
let data = tableRef.value.getCurrentRecord()
TableData1.value = []
monitorAbnormalTableDetail({
monitorIds: [data.monitorId],
searchBeginTime: data.date,
targetKey: numKey.value == 0 ? targetKey.value : ''
})
.then(res => {
TableData1.value = res.data
loading1.value = false
pageNum.value = 1
})
.catch(() => {
loading1.value = false
})
}
const formatter = (row: any) => {
return row.cellValue == null ? '/' : (row.cellValue - 0).toFixed(2)
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.time {
color: var(--el-color-primary);
cursor: pointer;
text-decoration: underline;
text-underline-offset: 4px;
.table-pagination {
height: 58px;
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
:deep(.box) {
.row--current {
background-color: var(--el-color-primary-light-8) !important;
}
}
</style>

View File

@@ -0,0 +1,562 @@
<!--业务用户管理界面-->
<template>
<div>
<TableHeader date-picker>
<template v-slot:select>
<el-form-item label="对象类型">
<el-select
v-model="tableStore.table.params.objType"
clearable
style="width: 100%"
placeholder="请选择对象类型"
>
<el-option
v-for="item in objTypeList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</template>
<template v-slot:operation></template>
</TableHeader>
<div class="card-list pt10">
<div class="monitoringPoints">
<el-card style="height: 200px">
<template #header>
<div class="card-header">
<span>监测点统计</span>
</div>
</template>
<div>
<div class="statistics">
<div class="divBox">
<span class="iconfont icon-qiyezongshu" style="color: #57bc6e"></span>
<span class="divBox_title">监测点总数</span>
<span class="divBox_num" style="color: #57bc6e">{{ monitoringPoints.runNum }}</span>
</div>
<div class="divBox" style="width: 200px">
<span class="iconfont icon-yichang" style="color: #ff0000"></span>
<span class="divBox_title">告警测点数</span>
<span class="divBox_num" style="color: #ff0000">
{{ monitoringPoints.abnormalNum }}
</span>
</div>
</div>
<div class="echartTitle">
<div>告警占比</div>
<div>
{{
isNaN((monitoringPoints.abnormalNum / monitoringPoints.runNum) * 100)
? 0
: ((monitoringPoints.abnormalNum / monitoringPoints.runNum) * 100).toFixed(2)
}}%
</div>
</div>
<div style="height: 30px">
<MyEchart :options="percentage"></MyEchart>
</div>
</div>
</el-card>
<el-card class="mt10">
<template #header>
<div class="card-header">
<span>告警指标统计</span>
</div>
</template>
<div class="mb5" style="height: 40px">
<el-segmented style="height: 100%" v-model="segmented" :options="segmentedList" block />
</div>
<div class="header">
<span style="flex: 1; text-align: left">指标名称</span>
<span style="width: 110px">告警测点数</span>
</div>
<div :style="indicatorHeight" style="overflow-y: auto">
<div v-for="o in abnormal" class="abnormal mb10">
<span style="flex: 1; height: 24px" class="iconDiv">
<div :style="{ backgroundColor: o.ids.length > 0 ? '#ff9800' : '' }"></div>
{{ o.targetName }}
</span>
<span style="width: 110px; text-align: center">
<span
style="color: #ff9800; cursor: pointer; text-decoration: underline"
class="text"
@click="quantityClick(o)"
>
{{ o.ids.length }}
</span>
</span>
</div>
</div>
</el-card>
</div>
<el-card class="detail ml10" :style="pageHeight">
<template #header>
<div class="card-header">
<span>告警详情统计</span>
</div>
</template>
<div style="height: 350px">
<MyEchart :options="options"></MyEchart>
</div>
<el-form :inline="true" class="form">
<el-form-item label="告警持续天数"></el-form-item>
<el-form-item label="告警阀值(天)">
<el-input-number
v-model="tableStore.table.params.alarmDayLimit"
:min="0"
:step="1"
step-strictly
/>
</el-form-item>
<el-form-item label="预警阀值(天)">
<el-input-number
v-model="tableStore.table.params.warnDayLimit"
:min="0"
:step="1"
step-strictly
/>
</el-form-item>
<el-form-item class="form_but">
<el-button type="primary" icon="el-icon-Refresh">更新</el-button>
<el-button type="primary" icon="el-icon-Download">导出</el-button>
</el-form-item>
</el-form>
<!--表格-->
<Table ref="tableRef"></Table>
</el-card>
</div>
<alarmDetails ref="alarmDetailsRef" />
</div>
</template>
<script setup lang="ts">
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref } from 'vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import MyEchart from '@/components/echarts/MyEchart.vue'
import alarmDetails from './alarmDetails.vue'
import { useConfig } from '@/stores/config'
import { queryFirstNode } from '@/api/auth'
const alarmDetailsRef = ref()
const dictData = useDictData()
//字典获取监督对象类型
const objTypeList: any = ref([])
const pageHeight = mainHeight(155)
const indicatorHeight = mainHeight(507)
const tableRef = ref()
const monitoringPoints = ref({
runNum: 0,
abnormalNum: 0
})
const percentage = ref({})
const abnormal: any = ref([])
const segmented = ref(1)
const segmentedList = [
{
label: '基础数据',
value: 1
},
{
label: '稳态数据',
value: 2
},
{
label: '暂态数据',
value: 3
}
]
const tableStore = new TableStore({
url: '/device-boot/dataVerify/getMonitorVerifyData',
method: 'POST',
showPage: false,
publicHeight: 480,
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
title: '监测点名称',
field: 'monitorName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '所属终端名称',
field: 'devName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">测试终端</div>`
// `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '所属电站',
field: 'stationName',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '监测对象类型',
field: 'objType',
formatter: (row, column) => {
return `测试光伏电站`
}
},
{
title: '监测对象名称',
field: 'objName',
formatter: (row, column) => {
return `测试对象`
}
},
{ title: '电压等级', field: 'voltageLevel' },
{
title: '告警天数',
field: 'abnormalDay',
type: 'html',
formatter: (row, column) => {
return `<div class="table_name">${row.cellValue}</div>`
}
},
{
title: '严重度',
field: 'severity',
render: 'tag',
custom: {
0: 'warning',
1: 'danger'
},
replaceValue: {
0: '预警',
1: '告警'
}
},
{
title: '操作',
width: '120',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '工单',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {}
}
]
}
],
loadCallback: () => {
console.log('🚀 ~ abnormal.value:', tableStore.table.data)
monitoringPoints.value.runNum = tableStore.table.data.runNum //总数
monitoringPoints.value.abnormalNum = tableStore.table.data.abnormalNum //告警测点数
abnormal.value = tableStore.table.data.targetList
tableStore.table.data = tableStore.table.data.monitorAlarmInfo
echart()
}
})
const options = ref({
title: {
text: '监测点告警情况(2025-03-01~2025-03-10)'
},
legend: {
show: false
},
xAxis: {
name: '时间',
axisLine: {
show: true
},
data: ['03-01', '03-02', '03-03', '03-04', '03-05', '03-06', '03-07', '03-08', '03-09', '03-10']
},
yAxis: {
name: '数量' // 给X轴加单位
},
grid: {},
options: {
series: [
{
name: '告警监测点数量',
type: 'bar',
data: [11, 11, 11, 11, 0, 0, 0, 0, 0, 0]
}
]
}
})
const echart = () => {
percentage.value = {
color: ['#ff9800'],
options: {
dataZoom: null,
toolbox: {
show: false
},
grid: {
top: '0%',
left: '2%',
right: '2%',
bottom: '0%'
},
tooltip: {
show: false
},
legend: {
show: false
},
yAxis: {
show: false,
data: ['']
},
xAxis: [
{
show: false,
type: 'value'
}
],
series: [
{
name: '告警占比',
type: 'bar',
barWidth: 12,
data: [((monitoringPoints.value.abnormalNum / monitoringPoints.value.runNum) * 100).toFixed(2)],
z: 0,
zlevel: 0,
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: '#ff0007' // 0% 处的颜色
},
{
offset: 1,
color: '#E22331' // 100% 处的颜色
}
],
global: false // 缺省为 false
}
}
}
},
{
type: 'pictorialBar',
itemStyle: {
normal: {
color: '#fff'
}
},
symbolRepeat: 50,
// symbolMargin: 300,
symbol: 'rect',
symbolClip: true,
symbolSize: [2, 15],
symbolPosition: 'start',
symbolOffset: [0, 0],
data: [100],
z: 1,
zlevel: 0
},
{
name: '机器故障率',
type: 'bar',
barGap: '-125%',
data: [100],
barWidth: 18,
itemStyle: {
normal: {
color: 'transparent',
barBorderColor: 'rgb(148,217,249)',
barBorderWidth: 1
}
},
z: 2
}
]
}
}
}
tableStore.table.params.deptId = dictData.state.area[0].id
tableStore.table.params.objType = ''
tableStore.table.params.alarmDayLimit = 5
tableStore.table.params.warnDayLimit = 1
const quantityClick = (e: any) => {
alarmDetailsRef.value.open(e)
}
onMounted(() => {
queryFirstNode({ type: 0 }).then(res => {
objTypeList.value = res.data
})
// 加载数据
tableStore.index()
})
tableStore.table.params.name = ''
provide('tableStore', tableStore)
</script>
<style lang="scss" scoped>
.card-list {
display: flex;
.monitoringPoints {
width: 440px;
position: relative;
.statistics {
display: flex;
flex-wrap: wrap;
.divBox {
margin: 0 10px 10px 0;
width: 200px;
height: 70px;
padding: 10px;
display: flex;
.iconfont {
font-size: 40px;
margin-right: 5px;
}
.divBox_title {
font-weight: 550;
}
.divBox_num {
font-size: 20px;
font-weight: 550;
margin-left: auto;
font-family: AlimamaDongFangDaKai;
}
align-items: center;
// text-align: center;
border-radius: 5px;
&:nth-child(1) {
background-color: #eef8f0;
}
&:nth-child(2) {
background-color: #ffd7d7;
}
&:nth-child(3) {
background-color: #e5f8f6;
}
}
}
}
.detail {
flex: 1;
}
.abnormal {
width: 100%;
background-color: #f3f6f9;
border-radius: 5px;
display: flex;
// justify-content: space-between;
align-items: center;
padding: 5px 0px 5px 10px;
.iconDiv {
display: flex;
align-items: center;
div {
width: 4px;
height: 18px;
margin-right: 5px;
background-color: var(--el-color-primary);
}
}
.text {
font-weight: 700;
font-size: 16px;
font-family: 'Source Code Pro', monospace;
// font-feature-settings: 'tnum';
}
}
}
.header {
display: flex;
text-align: center;
font-weight: 700;
padding: 5px;
}
:deep(.el-card__header) {
padding: 10px;
span {
font-weight: 600;
}
}
:deep(.el-card__body) {
padding: 10px;
}
.iconFont {
font-size: 18px;
display: inline-block;
vertical-align: middle;
}
.form {
position: relative;
.form_but {
position: absolute;
right: -22px;
}
}
.card-header {
font-size: 16px;
}
:deep(.table_name) {
color: var(--el-color-primary);
cursor: pointer;
text-decoration: underline;
text-underline-offset: 4px;
}
.echartTitle {
display: flex;
justify-content: space-between;
font-size: 14px;
font-weight: 600;
div:nth-child(2) {
font-size: 16px;
color: #ff0000;
}
}
:deep(.el-segmented__item-selected, ) {
clip-path: polygon(10% 0, 100% 0, 90% 100%, 0 100%);
}
:deep(.el-segmented__item, ) {
clip-path: polygon(10% 0, 100% 0, 90% 100%, 0 100%);
}
:deep(.el-segmented) {
clip-path: polygon(4% 0, 100% 0, 96% 100%, 0 100%);
}
</style>

View File

@@ -1,8 +1,8 @@
<template>
<div class="default-main">
<el-tabs type="border-card" v-model="activeName">
<el-tab-pane label="异常数据统计" name="1"><abnormal v-if="activeName == '1'"/></el-tab-pane>
<el-tab-pane label="稳态告警统计" name="2"><alarm v-if="activeName == '2'"/></el-tab-pane>
<el-tab-pane label="异常数据统计" name="1"><abnormal v-if="activeName == '1'" /></el-tab-pane>
<el-tab-pane label="稳态告警统计" name="2"><alarm v-if="activeName == '2'" /></el-tab-pane>
</el-tabs>
</div>
</template>

View File

@@ -29,6 +29,7 @@ const info = () => {
options.value = {
xAxis: {
type: 'value',
data:[10,100,200,300,400,500,600,700,800,900,1000],
axisLabel: {
show: true,
textStyle: {
@@ -43,7 +44,8 @@ const info = () => {
},
axisLine: {
show: true
}
},
},
grid: {
top: '10'
@@ -60,7 +62,8 @@ const info = () => {
},
splitLine: {
show: false
}
},
},
dataZoom: null,
series: [
@@ -70,11 +73,11 @@ const info = () => {
color: function (params) {
return params.value >= 90
? '#009900'
: params.value >= 60
: params.value >= 80
? '#77DA63'
: params.value >= 70
? '#FFCC00'
: params.value > 0
? '#CC0000'
: '#CCC'
: '#CC0000'
}
},