2025-10-20 13:25:30 +08:00
|
|
|
<template>
|
|
|
|
|
<div>
|
|
|
|
|
<!--F47曲线 -->
|
2025-11-07 11:28:24 +08:00
|
|
|
<TableHeader :showReset="false" @selectChange="selectChange" datePicker v-if="fullscreen"></TableHeader>
|
2025-10-20 13:25:30 +08:00
|
|
|
<el-descriptions class="mt2" direction="vertical" :column="4" border>
|
|
|
|
|
<el-descriptions-item align="center" label="名称">{{ data.name }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item align="center" label="事件总数">{{ data.gs }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item align="center" label="可容忍">{{ data.krr }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item align="center" label="不可容忍">{{ data.bkrr }}</el-descriptions-item>
|
|
|
|
|
</el-descriptions>
|
|
|
|
|
<my-echart
|
2025-10-28 11:23:17 +08:00
|
|
|
ref="chartRef"
|
2025-10-20 13:25:30 +08:00
|
|
|
class="tall"
|
|
|
|
|
:options="echartList"
|
2025-11-07 11:28:24 +08:00
|
|
|
:style="{ width: prop.width, height: `calc(${prop.height} - 80px - ${headerHeight}px + ${fullscreen ? 0 : 56}px)` }"
|
2025-10-28 11:23:17 +08:00
|
|
|
@chart-click="handleChartClick"
|
2025-10-20 13:25:30 +08:00
|
|
|
/>
|
2025-10-28 11:23:17 +08:00
|
|
|
<el-dialog v-model="isWaveCharts" draggable title="瞬时/RMS波形" append-to-body width="70%">
|
|
|
|
|
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
|
|
|
|
|
@handleHideCharts="isWaveCharts = false" :wp="wp" />
|
|
|
|
|
</el-dialog>
|
2025-10-20 13:25:30 +08:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { ref, onMounted, provide, reactive, watch, h } from 'vue'
|
|
|
|
|
import TableStore from '@/utils/tableStore'
|
|
|
|
|
import MyEchart from '@/components/echarts/MyEchart.vue'
|
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
|
|
import { getTimeOfTheMonth } from '@/utils/formatTime'
|
2025-10-28 11:23:17 +08:00
|
|
|
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue';
|
2025-11-07 11:28:24 +08:00
|
|
|
import TableHeader from '@/components/table/header/index.vue'
|
|
|
|
|
import { useRoute } from 'vue-router'
|
|
|
|
|
import { useTimeCacheStore } from '@/stores/timeCache'
|
|
|
|
|
|
2025-10-20 13:25:30 +08:00
|
|
|
const prop = defineProps({
|
2025-11-07 11:28:24 +08:00
|
|
|
w: { type: String },
|
|
|
|
|
h: { type: String },
|
2025-10-20 13:25:30 +08:00
|
|
|
width: { type: String },
|
|
|
|
|
height: { type: String },
|
|
|
|
|
timeKey: { type: String },
|
|
|
|
|
timeValue: { type: Object }
|
|
|
|
|
})
|
|
|
|
|
|
2025-11-07 11:28:24 +08:00
|
|
|
const headerHeight = ref(57)
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
const timeCacheStore = useTimeCacheStore()
|
|
|
|
|
|
|
|
|
|
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
|
|
|
|
|
headerHeight.value = height
|
|
|
|
|
|
|
|
|
|
// 如果有传入 datePicker 的值
|
|
|
|
|
if (datePickerValue) {
|
|
|
|
|
// 更新表格参数
|
|
|
|
|
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-10-20 13:25:30 +08:00
|
|
|
const echartList = ref({})
|
2025-10-28 11:23:17 +08:00
|
|
|
|
|
|
|
|
const chartRef = ref()
|
|
|
|
|
// 波形
|
|
|
|
|
const isWaveCharts = ref(false)
|
|
|
|
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
|
|
|
|
const wp = ref({})
|
|
|
|
|
|
2025-10-20 13:25:30 +08:00
|
|
|
const OverLimitDetailsRef = ref()
|
|
|
|
|
const data = reactive({
|
|
|
|
|
name: '事件个数',
|
|
|
|
|
gs: 0,
|
|
|
|
|
krr: 0,
|
|
|
|
|
bkrr: 0
|
|
|
|
|
})
|
|
|
|
|
const tableStore: any = new TableStore({
|
|
|
|
|
url: '/user-boot/dept/deptTree',
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
|
|
|
|
showPage: false,
|
|
|
|
|
|
|
|
|
|
column: [],
|
2025-11-07 11:28:24 +08:00
|
|
|
beforeSearchFun: () => {
|
|
|
|
|
// 尝试从缓存获取时间值
|
|
|
|
|
let beginTime, endTime
|
|
|
|
|
|
|
|
|
|
if (fullscreen.value) {
|
|
|
|
|
const cached = timeCacheStore.getCache(route.path)
|
|
|
|
|
if (cached && cached.timeValue) {
|
|
|
|
|
beginTime = cached.timeValue[0]
|
|
|
|
|
endTime = cached.timeValue[1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果缓存中没有则使用默认值
|
|
|
|
|
tableStore.table.params.searchBeginTime = beginTime || prop.timeValue?.[0] || getTimeOfTheMonth(prop.timeKey)[0]
|
|
|
|
|
|
|
|
|
|
tableStore.table.params.searchEndTime = endTime || prop.timeValue?.[1] || getTimeOfTheMonth(prop.timeKey)[1]
|
2025-10-20 13:25:30 +08:00
|
|
|
},
|
|
|
|
|
loadCallback: () => {
|
|
|
|
|
let res = {
|
|
|
|
|
data: { totalNumberOfEvents: 0, voltageToleranceCurveDataList: [] }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const gongData = gongfunction(res.data.voltageToleranceCurveDataList)
|
|
|
|
|
data.gs = res.data.voltageToleranceCurveDataList.length
|
|
|
|
|
data.krr = gongData.pointI.length
|
|
|
|
|
data.bkrr = gongData.pointIun.length
|
|
|
|
|
console.log(gongData)
|
|
|
|
|
echartList.value = {
|
|
|
|
|
// backgroundColor: "#f9f9f9", //地图背景色深蓝
|
|
|
|
|
title: {
|
|
|
|
|
text: `F47曲线`
|
|
|
|
|
},
|
|
|
|
|
legend: {
|
2025-10-28 11:23:17 +08:00
|
|
|
// data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
|
|
|
|
|
data: ['可容忍事件', '不可容忍事件'],
|
|
|
|
|
itemWidth: 10,
|
|
|
|
|
itemHeight: 10,
|
|
|
|
|
itemGap: 15
|
2025-10-20 13:25:30 +08:00
|
|
|
},
|
|
|
|
|
tooltip: {
|
|
|
|
|
trigger: 'item',
|
|
|
|
|
show: true,
|
|
|
|
|
axisPointer: {
|
|
|
|
|
type: 'shadow',
|
|
|
|
|
label: {
|
|
|
|
|
color: '#fff',
|
|
|
|
|
fontSize: 16
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
textStyle: {
|
|
|
|
|
color: '#fff',
|
|
|
|
|
fontStyle: 'normal',
|
|
|
|
|
opacity: 0.35,
|
|
|
|
|
fontSize: 14
|
|
|
|
|
},
|
|
|
|
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
|
|
|
|
borderWidth: 0,
|
|
|
|
|
formatter: function (a: any) {
|
|
|
|
|
var relVal = ''
|
|
|
|
|
relVal = "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
|
|
|
|
|
relVal += "<font style='color:" + "'>持续时间:" + a.value[0] + 's</font><br/>'
|
|
|
|
|
relVal += "<font style='color:" + "'>特征幅值:" + a.value[1].toFixed(2) + '%</font>'
|
|
|
|
|
return relVal
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
xAxis: [
|
|
|
|
|
{
|
|
|
|
|
type: 'log',
|
|
|
|
|
min: 0.001,
|
|
|
|
|
max: 1000,
|
|
|
|
|
splitLine: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
name: 's'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
yAxis: [
|
|
|
|
|
{
|
|
|
|
|
type: 'value',
|
|
|
|
|
max: function (value: any) {
|
|
|
|
|
return value.max + 20
|
|
|
|
|
},
|
|
|
|
|
splitNumber: 10,
|
|
|
|
|
minInterval: 0.1,
|
|
|
|
|
name: '%'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
color: ['#DAA520', 'green', 'red'],
|
|
|
|
|
options: {
|
|
|
|
|
dataZoom: null,
|
|
|
|
|
series: [
|
|
|
|
|
{
|
|
|
|
|
name: '边界线',
|
|
|
|
|
type: 'line',
|
|
|
|
|
data: [
|
|
|
|
|
[0.05, 0],
|
|
|
|
|
[0.05, 50],
|
|
|
|
|
[0.2, 50],
|
|
|
|
|
[0.2, 70],
|
|
|
|
|
[0.5, 70],
|
|
|
|
|
[0.5, 80],
|
|
|
|
|
[10, 80],
|
|
|
|
|
[1000, 80]
|
|
|
|
|
],
|
|
|
|
|
showSymbol: false,
|
|
|
|
|
tooltips: {
|
|
|
|
|
show: false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: '可容忍事件',
|
|
|
|
|
type: 'scatter',
|
|
|
|
|
symbol: 'circle',
|
2025-10-28 11:23:17 +08:00
|
|
|
symbolSize: 8,
|
|
|
|
|
// data: gongData.pointF,
|
|
|
|
|
data: [
|
|
|
|
|
[0.2, 10, '2023-01-01 10:00:00'],
|
|
|
|
|
[0.4, 50, '2023-01-01 11:00:00']
|
|
|
|
|
],
|
|
|
|
|
legendSymbol: 'circle',
|
|
|
|
|
emphasis: {
|
|
|
|
|
focus: 'series',
|
|
|
|
|
itemStyle: {
|
|
|
|
|
borderColor: '#fff',
|
|
|
|
|
borderWidth: 2,
|
|
|
|
|
shadowBlur: 10,
|
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
tooltip: {
|
|
|
|
|
show: true,
|
|
|
|
|
trigger: 'item',
|
|
|
|
|
formatter: function (params: any) {
|
|
|
|
|
return `<strong>可容忍事件</strong><br/>
|
|
|
|
|
持续时间: ${params.value[0]}s<br/>
|
|
|
|
|
特征幅值: ${params.value[1].toFixed(2)}%<br/>
|
|
|
|
|
发生时间: ${params.value[2] || 'N/A'}`
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-20 13:25:30 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: '不可容忍事件',
|
|
|
|
|
type: 'scatter',
|
2025-10-28 11:23:17 +08:00
|
|
|
symbol: 'rect',
|
|
|
|
|
symbolSize: 8,
|
|
|
|
|
data: gongData.pointFun,
|
|
|
|
|
legendSymbol: 'rect'
|
2025-10-20 13:25:30 +08:00
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const tableRef = ref()
|
|
|
|
|
provide('tableRef', tableRef)
|
|
|
|
|
provide('tableStore', tableStore)
|
|
|
|
|
|
|
|
|
|
function gongfunction(arr: any) {
|
|
|
|
|
let standI = 0
|
|
|
|
|
let unstandI = 0
|
|
|
|
|
let standF = 0
|
|
|
|
|
let unstandF = 0
|
|
|
|
|
let total = 0
|
|
|
|
|
let pointIun = []
|
|
|
|
|
let pointI = []
|
|
|
|
|
let pointF = []
|
|
|
|
|
let pointFun = []
|
|
|
|
|
total = arr.length
|
|
|
|
|
if (total == 0) {
|
|
|
|
|
} else {
|
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
|
|
let point = []
|
|
|
|
|
let xx = arr[i].persistTime
|
|
|
|
|
let yy = arr[i].eventValue
|
|
|
|
|
let time = arr[i].time
|
|
|
|
|
let eventId = arr[i].eventId
|
|
|
|
|
// let index =arr[i].eventDetailIndex;
|
|
|
|
|
point = [xx, yy, time, eventId]
|
|
|
|
|
|
|
|
|
|
if (xx <= 0.003) {
|
|
|
|
|
let line = 0
|
|
|
|
|
line = 250 - 30000 * xx
|
|
|
|
|
if (yy > line) {
|
|
|
|
|
unstandI++
|
|
|
|
|
pointIun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
standI++
|
|
|
|
|
pointI.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else if (xx <= 0.02) {
|
|
|
|
|
if (yy > 120) {
|
|
|
|
|
unstandI++
|
|
|
|
|
pointIun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
standI++
|
|
|
|
|
pointI.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else if (xx <= 0.5) {
|
|
|
|
|
if (yy > 120 || yy < 70) {
|
|
|
|
|
unstandI++
|
|
|
|
|
pointIun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
standI++
|
|
|
|
|
pointI.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else if (xx <= 10) {
|
|
|
|
|
if (yy > 110 || yy < 80) {
|
|
|
|
|
unstandI++
|
|
|
|
|
pointIun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
standI++
|
|
|
|
|
pointI.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (yy > 110 || yy < 90) {
|
|
|
|
|
unstandI++
|
|
|
|
|
pointIun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
standI++
|
|
|
|
|
pointI.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (xx < 0.05) {
|
|
|
|
|
standF++
|
|
|
|
|
pointF.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
} else if (xx < 0.2) {
|
|
|
|
|
if (yy > 50) {
|
|
|
|
|
standF++
|
|
|
|
|
pointF.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
unstandF++
|
|
|
|
|
pointFun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else if (xx < 0.5) {
|
|
|
|
|
if (yy > 70) {
|
|
|
|
|
standF++
|
|
|
|
|
pointF.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
unstandF++
|
|
|
|
|
pointFun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (yy > 80) {
|
|
|
|
|
standF++
|
|
|
|
|
pointF.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'green' } }
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
unstandF++
|
|
|
|
|
pointFun.push({
|
|
|
|
|
value: point,
|
|
|
|
|
itemStyle: { normal: { color: 'red' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
standI,
|
|
|
|
|
unstandI,
|
|
|
|
|
pointI,
|
|
|
|
|
pointIun,
|
|
|
|
|
standF,
|
|
|
|
|
unstandF,
|
|
|
|
|
pointF,
|
|
|
|
|
pointFun
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
tableStore.index()
|
|
|
|
|
}, 100)
|
|
|
|
|
})
|
2025-10-28 11:23:17 +08:00
|
|
|
|
|
|
|
|
// 点击事件处理函数
|
|
|
|
|
const handleChartClick = (params: any) => {
|
|
|
|
|
|
|
|
|
|
if (params.seriesName === '可容忍事件') {
|
|
|
|
|
// 处理可容忍事件点击
|
|
|
|
|
ElMessage.info(`点击了可容忍事件: 持续时间${params.value[0]}s, 幅值${params.value[1].toFixed(2)}%`)
|
|
|
|
|
handleTolerableEventClick(params)
|
|
|
|
|
} else if (params.seriesName === '不可容忍事件') {
|
|
|
|
|
// 处理不可容忍事件点击
|
|
|
|
|
ElMessage.info(`点击了不可容忍事件: 持续时间${params.value[0]}s, 幅值${params.value[1].toFixed(2)}%`)
|
|
|
|
|
handleIntolerableEventClick(params)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可容忍事件点击处理函数
|
|
|
|
|
const handleTolerableEventClick = (params: any) => {
|
|
|
|
|
console.log('可容忍事件详情:', params)
|
|
|
|
|
isWaveCharts.value = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 不可容忍事件点击处理函数
|
|
|
|
|
const handleIntolerableEventClick = (params: any) => {
|
|
|
|
|
console.log('不可容忍事件详情:', params)
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 13:25:30 +08:00
|
|
|
watch(
|
|
|
|
|
() => prop.timeKey,
|
|
|
|
|
val => {
|
|
|
|
|
tableStore.index()
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
watch(
|
|
|
|
|
() => prop.timeValue, // 监听的目标(函数形式避免直接传递 props 导致的警告)
|
|
|
|
|
(newVal, oldVal) => {
|
|
|
|
|
tableStore.index()
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
deep: true // 若 timeValue 是对象/数组,需开启深度监听
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const addMenu = () => {}
|
|
|
|
|
</script>
|
|
|
|
|
<style lang="scss" scoped></style>
|