优化波形

This commit is contained in:
guanj
2026-06-16 08:36:22 +08:00
parent 765507398e
commit 56b8158f4a
25 changed files with 3704 additions and 3437 deletions

View File

@@ -30,7 +30,7 @@ import { downloadFile } from '@/api/system-boot/file'
import { previewFile } from '@/utils/fileDownLoad' import { previewFile } from '@/utils/fileDownLoad'
const { push, options, currentRoute } = useRouter() const { push, options, currentRoute } = useRouter()
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei' const VITE_FLAG = false//import.meta.env.VITE_NAME == 'jibei'
// const url = 'http://192.168.1.22:9009/excelreport' + currentRoute.value.href?.split('?')[1] // const url = 'http://192.168.1.22:9009/excelreport' + currentRoute.value.href?.split('?')[1]
const url = ref('') const url = ref('')
const excelOptions = ref({}) const excelOptions = ref({})

View File

@@ -0,0 +1,322 @@
// 辅助函数
const getMax = (temp, tempA, tempB, tempC) => {
temp = temp > tempA ? temp : tempA
temp = temp > tempB ? temp : tempB
if (tempC !== undefined) {
temp = temp > tempC ? temp : tempC
}
return temp
}
const getMaxTwo = (temp, tempA, tempB) => {
temp = temp > tempA ? temp : tempA
temp = temp > tempB ? temp : tempB
return temp
}
const getMin = (temp, tempA, tempB, tempC) => {
temp = temp < tempA ? temp : tempA
temp = temp < tempB ? temp : tempB
if (tempC !== undefined) {
temp = temp < tempC ? temp : tempC
}
return temp
}
const getMinOpen = (temp, tempA, tempB) => {
temp = temp < tempA ? temp : tempA
temp = temp < tempB ? temp : tempB
return temp
}
// 数据处理函数
const fliteWaveData = (wp, step, iphasicValue, isOpen) => {
const rmsData = wp.listRmsData
const pt = Number(wp.pt) / 1000
const ct = Number(wp.ct)
const titleList = wp.waveTitle
let xishu = pt
let aTitle = '',
bTitle = '',
cTitle = '',
unit = '电压'
let rmsvFirstX = 0,
rmsvFirstY = 0,
rmsvSecondX = 0,
rmsvSecondY = 0,
firstZhou = 'a',
secondeZhou = 'a'
let ifmax = 0,
ifmin = 0,
ismax = 0,
ismin = 0,
rfmax = 0,
rfmin = 0,
rsmax = 0,
rsmin = 0
const shunshiFA = []
const shunshiFB = []
const shunshiFC = []
const shunshiSA = []
const shunshiSB = []
const shunshiSC = []
const rmsFA = []
const rmsFB = []
const rmsFC = []
const rmsSA = []
const rmsSB = []
const rmsSC = []
if (titleList[iphasicValue * step + 1]?.substring(0, 1) !== 'U') {
xishu = ct
unit = '电流'
}
for (let i = 1; i <= iphasicValue; i++) {
switch (i) {
case 1:
aTitle = titleList[iphasicValue * step + i]?.substring(1) || ''
break
case 2:
bTitle = titleList[iphasicValue * step + i]?.substring(1) || ''
break
case 3:
cTitle = titleList[iphasicValue * step + i]?.substring(1) || ''
break
}
}
if (rmsData[0] && rmsData[0][iphasicValue * step + 1] !== undefined) {
rfmax = rmsData[0][iphasicValue * step + 1] * xishu
rfmin = rmsData[0][iphasicValue * step + 1] * xishu
rmsvFirstY = rmsData[0][iphasicValue * step + 1] * xishu
rmsvFirstX = rmsData[0][0]
rsmax = rmsData[0][iphasicValue * step + 1]
rsmin = rmsData[0][iphasicValue * step + 1]
rmsvSecondY = rmsData[0][iphasicValue * step + 1]
rmsvSecondX = rmsData[0][0]
}
for (let rms = 0; rms < rmsData.length; rms++) {
if (!rmsData[rms] || rmsData[rms][iphasicValue * step + 1] === undefined) {
break
}
switch (iphasicValue) {
case 1:
const rmsFirstA = rmsData[rms][iphasicValue * step + 1] * xishu
rmsFA.push([rmsData[rms][0], rmsFirstA])
rfmax = rfmax > rmsFirstA ? rfmax : rmsFirstA
rfmin = rfmin < rmsFirstA ? rfmin : rmsFirstA
if (rfmin < rmsvFirstY) {
rmsvFirstY = rfmin
firstZhou = 'a'
rmsvFirstX = rmsData[rms][0]
}
const rmsSecondA = rmsData[rms][iphasicValue * step + 1]
rmsSA.push([rmsData[rms][0], rmsSecondA])
rsmax = rsmax > rmsSecondA ? rsmax : rmsSecondA
rsmin = rsmin < rmsSecondA ? rsmin : rmsSecondA
if (rsmin < rmsvSecondY) {
rmsvSecondY = rsmin
secondeZhou = 'a'
rmsvSecondX = rmsData[rms][0]
}
break
case 2:
const rmsFirstA2 = rmsData[rms][iphasicValue * step + 1] * xishu
const rmsFirstB2 = rmsData[rms][iphasicValue * step + 2] * xishu
rmsFA.push([rmsData[rms][0], rmsFirstA2])
rmsFB.push([rmsData[rms][0], rmsFirstB2])
rfmax = getMaxTwo(rfmax, rmsFirstA2, rmsFirstB2)
rfmin = getMinOpen(rfmin, rmsFirstA2, rmsFirstB2)
if (rfmin < rmsvFirstY) {
rmsvFirstY = rfmin
if (rfmin === rmsFirstA2) {
firstZhou = 'a'
} else if (rfmin === rmsFirstB2) {
firstZhou = 'b'
}
rmsvFirstX = rmsData[rms][0]
}
const rmsSecondA2 = rmsData[rms][iphasicValue * step + 1]
const rmsSecondB2 = rmsData[rms][iphasicValue * step + 2]
rmsSA.push([rmsData[rms][0], rmsSecondA2])
rmsSB.push([rmsData[rms][0], rmsSecondB2])
rsmax = getMaxTwo(rsmax, rmsSecondA2, rmsSecondB2)
rsmin = getMinOpen(rsmin, rmsSecondA2, rmsSecondB2)
if (rsmin < rmsvSecondY) {
rmsvSecondY = rsmin
if (rsmin === rmsSecondA2) {
secondeZhou = 'a'
} else if (rsmin === rmsSecondB2) {
secondeZhou = 'b'
}
rmsvSecondX = rmsData[rms][0]
}
break
case 3:
const rmsFirstA3 = rmsData[rms][iphasicValue * step + 1] * xishu
const rmsFirstB3 = rmsData[rms][iphasicValue * step + 2] * xishu
const rmsFirstC3 = rmsData[rms][iphasicValue * step + 3] * xishu
rmsFA.push([rmsData[rms][0], rmsFirstA3])
rmsFB.push([rmsData[rms][0], rmsFirstB3])
rmsFC.push([rmsData[rms][0], rmsFirstC3])
rfmax = getMax(rfmax, rmsFirstA3, rmsFirstB3, rmsFirstC3)
rfmin = isOpen
? getMinOpen(rfmin, rmsFirstA3, rmsFirstC3)
: getMin(rfmin, rmsFirstA3, rmsFirstB3, rmsFirstC3)
if (rfmin < rmsvFirstY) {
rmsvFirstY = rfmin
if (rfmin === rmsFirstA3) {
firstZhou = 'a'
} else if (rfmin === rmsFirstB3) {
firstZhou = 'b'
} else {
firstZhou = 'c'
}
rmsvFirstX = rmsData[rms][0]
}
const rmsSecondA3 = rmsData[rms][iphasicValue * step + 1]
const rmsSecondB3 = rmsData[rms][iphasicValue * step + 2]
const rmsSecondC3 = rmsData[rms][iphasicValue * step + 3]
rmsSA.push([rmsData[rms][0], rmsSecondA3])
rmsSB.push([rmsData[rms][0], rmsSecondB3])
rmsSC.push([rmsData[rms][0], rmsSecondC3])
rsmax = getMax(rsmax, rmsSecondA3, rmsSecondB3, rmsSecondC3)
rsmin = isOpen
? getMinOpen(rsmin, rmsSecondA3, rmsSecondC3)
: getMin(rsmin, rmsSecondA3, rmsSecondB3, rmsSecondC3)
if (rsmin < rmsvSecondY) {
rmsvSecondY = rsmin
if (rsmin === rmsSecondA3) {
secondeZhou = 'a'
} else if (rsmin === rmsSecondB3) {
secondeZhou = 'b'
} else {
secondeZhou = 'c'
}
rmsvSecondX = rmsData[rms][0]
}
break
}
}
const instantF = { max: ifmax, min: ifmin }
const instantS = { max: ismax, min: ismin }
const RMSF = { max: rfmax, min: rfmin }
const RMSS = { max: rsmax, min: rsmin }
const RMSFMinDetail = { rmsvFirstX, rmsvFirstY, firstZhou }
const RMSSMinDetail = { rmsvSecondX, rmsvSecondY, secondeZhou }
const shunshiF = { shunshiFA, shunshiFB, shunshiFC }
const shunshiS = { shunshiSA, shunshiSB, shunshiSC }
const RMSFWave = { rmsFA, rmsFB, rmsFC }
const RMSSWave = { rmsSA, rmsSB, rmsSC }
const title = { aTitle, bTitle, cTitle, unit }
return {
instantF,
instantS,
RMSF,
RMSS,
RMSFMinDetail,
RMSSMinDetail,
shunshiF,
shunshiS,
RMSFWave,
RMSSWave,
title,
unit
}
}
// 监听消息
self.onmessage = function (e) {
const { wp, isOpen, value, boxoList, requestId } = e.data
try {
const iphasicValue = wp.iphasic || 1
const picCounts = (wp.waveTitle.length - 1) / iphasicValue
const waveDatas = []
for (let i = 0; i < picCounts; i++) {
const data = fliteWaveData(wp, i, iphasicValue, isOpen, boxoList)
waveDatas.push(data)
}
// 处理标题
let titles = ''
if (boxoList.systemType == 'pms') {
titles =
'变电站名称:' +
boxoList.powerStationName +
' 监测点名称:' +
boxoList.measurementPointName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
(boxoList.featureAmplitude * 100).toFixed(2) +
'%  持续时间:' +
boxoList.duration +
's'
} else if (boxoList.systemType == 'ZL') {
titles =
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
' 监测点名称:' +
boxoList.equipmentName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
boxoList.evtParamVVaDepth +
'% 持续时间:' +
boxoList.evtParamTm +
's'
} else if (boxoList.systemType == 'YPT') {
titles =
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
' 监测点名称:' +
boxoList.lineName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
(boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
boxoList.persistTime +
's'
} else {
titles =
' 变电站名称:' +
boxoList.subName +
' 监测点名称:' +
boxoList.lineName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
(boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
boxoList.duration +
's'
}
// 发送处理结果回主线程
self.postMessage({
requestId,
titles: titles,
success: true,
waveDatas,
time: wp.time,
type: wp.waveType,
severity: wp.yzd,
iphasic: iphasicValue
})
} catch (error) {
self.postMessage({
requestId,
success: false,
error: error.message
})
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,207 @@
// waveData.worker.js
self.addEventListener('message', function (e) {
const { wp, value, iphasic, isOpen, boxoList, requestId } = e.data
// 处理波形数据的函数
const fliteWaveData = (wp, step) => {
// 将原有的fliteWaveData函数实现复制到这里
const shunData = wp.listWaveData
const pt = Number(wp.pt) / 1000
const ct = Number(wp.ct)
const titleList = wp.waveTitle
let xishu = pt
let aTitle = '',
bTitle = '',
cTitle = '',
unit = '电压'
let ifmax = 0,
ifmin = 0,
ismax = 0,
ismin = 0
const shunshiFA = []
const shunshiFB = []
const shunshiFC = []
const shunshiSA = []
const shunshiSB = []
const shunshiSC = []
if (shunData.length > 0) {
if (titleList[iphasic * step + 1]?.substring(0, 1) !== 'U') {
xishu = ct
unit = '电流'
}
for (let i = 1; i <= iphasic; i++) {
switch (i) {
case 1:
aTitle = titleList[iphasic * step + i]?.substring(1) || ''
break
case 2:
bTitle = titleList[iphasic * step + i]?.substring(1) || ''
break
case 3:
cTitle = titleList[iphasic * step + i]?.substring(1) || ''
break
}
}
if (shunData[0][iphasic * step + 1] !== undefined) {
ifmax = shunData[0][iphasic * step + 1] * xishu
ifmin = shunData[0][iphasic * step + 1] * xishu
ismax = shunData[0][iphasic * step + 1]
ismin = shunData[0][iphasic * step + 1]
}
for (let shun = 0; shun < shunData.length; shun++) {
if (shunData[shun][iphasic * step + 1] === undefined) {
break
}
switch (iphasic) {
case 1:
const shunFirstA = shunData[shun][iphasic * step + 1] * xishu
shunshiFA.push([shunData[shun][0], shunFirstA])
ifmax = Math.max(ifmax, shunFirstA)
ifmin = Math.min(ifmin, shunFirstA)
const shunSecondA = shunData[shun][iphasic * step + 1]
shunshiSA.push([shunData[shun][0], shunSecondA])
ismax = Math.max(ismax, shunSecondA)
ismin = Math.min(ismin, shunSecondA)
break
case 2:
const shunFirstA2 = shunData[shun][iphasic * step + 1] * xishu
const shunFirstB2 = shunData[shun][iphasic * step + 2] * xishu
shunshiFA.push([shunData[shun][0], shunFirstA2])
shunshiFB.push([shunData[shun][0], shunFirstB2])
ifmax = Math.max(ifmax, shunFirstA2, shunFirstB2)
ifmin = Math.min(ifmin, shunFirstA2, shunFirstB2)
const shunSecondA2 = shunData[shun][iphasic * step + 1]
const shunSecondB2 = shunData[shun][iphasic * step + 2]
shunshiSA.push([shunData[shun][0], shunSecondA2])
shunshiSB.push([shunData[shun][0], shunSecondB2])
ismax = Math.max(ismax, shunSecondA2, shunSecondB2)
ismin = Math.min(ismin, shunSecondA2, shunSecondB2)
break
case 3:
const shunFirstA3 = shunData[shun][iphasic * step + 1] * xishu
const shunFirstB3 = shunData[shun][iphasic * step + 2] * xishu
const shunFirstC3 = shunData[shun][iphasic * step + 3] * xishu
shunshiFA.push([shunData[shun][0], shunFirstA3])
shunshiFB.push([shunData[shun][0], shunFirstB3])
shunshiFC.push([shunData[shun][0], shunFirstC3])
ifmax = Math.max(ifmax, shunFirstA3, shunFirstB3, shunFirstC3)
ifmin = isOpen
? Math.min(ifmin, shunFirstA3, shunFirstC3)
: Math.min(ifmin, shunFirstA3, shunFirstB3, shunFirstC3)
const shunSecondA3 = shunData[shun][iphasic * step + 1]
const shunSecondB3 = shunData[shun][iphasic * step + 2]
const shunSecondC3 = shunData[shun][iphasic * step + 3]
shunshiSA.push([shunData[shun][0], shunSecondA3])
shunshiSB.push([shunData[shun][0], shunSecondB3])
shunshiSC.push([shunData[shun][0], shunSecondC3])
ismax = Math.max(ismax, shunSecondA3, shunSecondB3, shunSecondC3)
ismin = isOpen
? Math.min(ismin, shunSecondA3, shunSecondC3)
: Math.min(ismin, shunSecondA3, shunSecondB3, shunSecondC3)
break
}
}
}
const instantF = { max: ifmax, min: ifmin }
const instantS = { max: ismax, min: ismin }
const shunshiF = { shunshiFA, shunshiFB, shunshiFC }
const shunshiS = { shunshiSA, shunshiSB, shunshiSC }
const title = { aTitle, bTitle, cTitle, unit }
return { instantF, instantS, shunshiF, shunshiS, title, unit }
}
// 处理标题
let titles = ''
if (boxoList.systemType == 'pms') {
titles =
'变电站名称:' +
boxoList.powerStationName +
' 监测点名称:' +
boxoList.measurementPointName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
(boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
boxoList.duration +
's'
} else if (boxoList.systemType == 'ZL') {
titles =
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
' 监测点名称:' +
boxoList.equipmentName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
boxoList.evtParamVVaDepth +
'% 持续时间:' +
boxoList.evtParamTm +
's'
} else if (boxoList.systemType == 'YPT') {
titles =
(boxoList.engineeringName == undefined ? '' : ' 项目名称:' + boxoList.engineeringName) +
' 监测点名称:' +
boxoList.lineName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
(boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
boxoList.persistTime +
's'
} else {
titles =
'变电站名称:' +
boxoList.subName +
' 监测点名称:' +
boxoList.lineName +
' 发生时刻:' +
boxoList.startTime +
' 暂降(骤升)幅值:' +
(boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
boxoList.duration +
's'
}
const iphasicValue = wp.iphasic || 1
const picCounts = (wp.waveTitle.length - 1) / iphasicValue
const waveDatas = []
for (let i = 0; i < picCounts; i++) {
const data = fliteWaveData(wp, i)
waveDatas.push(data)
}
const time = wp.time
const type = wp.waveType
let severity = wp.yzd
if (severity < 0) {
severity = '/'
type = '/'
}
// 将处理结果发送回主线程
self.postMessage({
requestId,
success: true,
waveDatas,
time,
type,
severity,
titles,
iphasic: iphasicValue
})
})

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
<div v-if="view2"> <div v-if="view2">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 14px; line-height: 30px">值类型选择:</span> <!-- <span style="font-size: 14px; line-height: 30px">值类型选择:</span>
<el-select <el-select
style="min-width: 200px; width: 200px" style="min-width: 200px; width: 200px"
@change="changeView" @change="changeView"
@@ -15,7 +15,11 @@
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
></el-option> ></el-option>
</el-select> </el-select> -->
<el-radio-group v-model.trim="value" @change="changeView">
<el-radio-button label="一次值" :value="1" />
<el-radio-button label="二次值" :value="2" />
</el-radio-group>
<!-- <el-button v-if="view2 && senior" class="ml10" type="primary" @click="AdvancedAnalytics"> <!-- <el-button v-if="view2 && senior" class="ml10" type="primary" @click="AdvancedAnalytics">
高级分析 高级分析
</el-button> --> </el-button> -->
@@ -24,37 +28,18 @@
<el-button @click="backbxlb" icon="el-icon-Back" style="float: right">返回</el-button> <el-button @click="backbxlb" icon="el-icon-Back" style="float: right">返回</el-button>
</el-col> </el-col>
</el-row> </el-row>
<div v-loading="loading" style="height: calc(100vh - 190px)"> <div v-loading="loading" style="height: calc(100vh - 190px)" class="mt10">
<el-tabs v-if="view4" class="default-main" v-model="bxactiveName" @tab-click="bxhandleClick"> <el-tabs v-if="view4" type="border-card" v-model="bxactiveName"
<el-tab-pane @tab-click="bxhandleClick">
label="瞬时波形" <el-tab-pane label="瞬时波形" name="ssbx" class="boxbx pt10 pb10"
name="ssbx" :style="'height:' + bxecharts + ';overflow-y: scroll;'">
class="boxbx pt10 pb10" <shushiboxi ref="shushiboxiRef" v-if="bxactiveName == 'ssbx' && showBoxi" :value="value"
:style="'height:' + bxecharts + ';overflow-y: scroll;'" :parentHeight="parentHeight" :boxoList="boxoList" :wp="wp"></shushiboxi>
>
<shushiboxi
ref="shushiboxiRef"
v-if="bxactiveName == 'ssbx' && showBoxi"
:value="value"
:parentHeight="parentHeight"
:boxoList="boxoList"
:wp="wp"
></shushiboxi>
</el-tab-pane> </el-tab-pane>
<el-tab-pane <el-tab-pane label="RMS波形" class="boxbx pt10 pb10" name="rmsbx"
label="RMS波形" :style="'height:' + bxecharts + ';overflow-y: scroll;'">
class="boxbx pt10 pb10" <rmsboxi ref="rmsboxiRef" v-if="bxactiveName == 'rmsbx' && showBoxi" :value="value"
name="rmsbx" :parentHeight="parentHeight" :boxoList="boxoList" :wp="wp"></rmsboxi>
:style="'height:' + bxecharts + ';overflow-y: scroll;'"
>
<rmsboxi
ref="rmsboxiRef"
v-if="bxactiveName == 'rmsbx' && showBoxi"
:value="value"
:parentHeight="parentHeight"
:boxoList="boxoList"
:wp="wp"
></rmsboxi>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<el-empty v-else description="暂无数据" style="height: calc(100vh - 190px)" /> <el-empty v-else description="暂无数据" style="height: calc(100vh - 190px)" />
@@ -100,7 +85,7 @@ const options = ref([
} }
]) ])
const shushiboxiRef = ref() const shushiboxiRef = ref()
const bxecharts = ref(mainHeight(95).height as any) const bxecharts = ref(mainHeight(145).height as any)
const view2 = ref(true) const view2 = ref(true)
const boxoList: any = ref(null) const boxoList: any = ref(null)
const wp = ref(null) const wp = ref(null)
@@ -128,9 +113,6 @@ const open = async (row: any) => {
}) })
} }
const bxhandleClick = (tab: any) => { const bxhandleClick = (tab: any) => {
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()
if (rmsboxiRef.value) rmsboxiRef.value.backbxlb()
loading.value = true loading.value = true
if (tab.name == 'ssbx') { if (tab.name == 'ssbx') {
bxactiveName.value = 'ssbx' bxactiveName.value = 'ssbx'
@@ -145,8 +127,7 @@ const bxhandleClick = (tab: any) => {
const backbxlb = () => { const backbxlb = () => {
boxoList.value = null boxoList.value = null
wp.value = null wp.value = null
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()
if (rmsboxiRef.value) rmsboxiRef.value.backbxlb()
emit('backbxlb') emit('backbxlb')
} }

View File

@@ -1,24 +1,44 @@
<template> <template>
<div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }"> <div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }">
<vxe-table ref="tableRef" height="auto" :key="key" :data="tableStore.table.data" <vxe-table
v-loading="tableStore.table.loading" v-bind="Object.assign({}, defaultAttribute, $attrs)" ref="tableRef"
@checkbox-all="selectChangeEvent" @checkbox-change="selectChangeEvent" :showOverflow="showOverflow" height="auto"
@sort-change="handleSortChange"> :key="key"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
>
<!-- @sort-change="handleSortChange" -->
<!-- Column 组件内部是 el-table-column --> <!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup"> <template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" /> <GroupColumn :column="tableStore.table.column" />
</template> </template>
<template v-else> <template v-else>
<Column :attr="item" :key="key + '-column'" v-for="(item, key) in tableStore.table.column" <Column
:tree-node="item.treeNode"> :attr="item"
:key="key + '-column'"
v-for="(item, key) in tableStore.table.column"
:tree-node="item.treeNode"
>
<!-- tableStore 预设的列 render 方案 --> <!-- tableStore 预设的列 render 方案 -->
<template v-if="item.render" #default="scope"> <template v-if="item.render" #default="scope">
<FieldRender :field="item" :row="scope.row" :column="scope.column" :index="scope.rowIndex" :key="key + <FieldRender
'-' + :field="item"
item.render + :row="scope.row"
'-' + :column="scope.column"
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '') :index="scope.rowIndex"
" /> :key="
key +
'-' +
item.render +
'-' +
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
"
/>
</template> </template>
</Column> </Column>
</template> </template>
@@ -27,11 +47,16 @@
</div> </div>
<div v-if="tableStore.showPage" class="table-pagination"> <div v-if="tableStore.showPage" class="table-pagination">
<el-pagination :currentPage="tableStore.table.params!.pageNum" :page-size="tableStore.table.params!.pageSize" <el-pagination
:page-sizes="pageSizes" background :currentPage="tableStore.table.params!.pageNum"
:page-size="tableStore.table.params!.pageSize"
:page-sizes="pageSizes"
background
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'" :layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
:total="tableStore.table.total" @size-change="onTableSizeChange" :total="tableStore.table.total"
@current-change="onTableCurrentChange"></el-pagination> @size-change="onTableSizeChange"
@current-change="onTableCurrentChange"
></el-pagination>
</div> </div>
<slot name="footer"></slot> <slot name="footer"></slot>
</template> </template>

View File

@@ -11,25 +11,25 @@
:data="eventList.slice((pageNum - 1) * pageSize, pageNum * pageSize)" :data="eventList.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
> >
<!-- <vxe-column type="seq" width="70px" title="序号"></vxe-column> --> <!-- <vxe-column type="seq" width="70px" title="序号"></vxe-column> -->
<vxe-column field="time" width="180px" sortable title="发生时刻"></vxe-column> <vxe-column field="time" width="180px" sortable title="暂降发生时刻"></vxe-column>
<vxe-column field="lineName" title="监测点"></vxe-column>
<vxe-column field="powerCompany" title="变电站" width="100px"></vxe-column>
<vxe-column field="powerCompany" title="供电公司" width="100px"></vxe-column>
<vxe-column field="persistTime" width="120px" sortable title="持续时间(s)">
<template #default="{ row }">
{{ Math.floor(row.persistTime * 1000) / 1000 }}
</template>
</vxe-column>
<vxe-column field="eventValue" width="160px" sortable title="暂降(骤升)幅值(%)"> <vxe-column field="eventValue" width="160px" sortable title="暂降(骤升)幅值(%)">
<template #default="{ row }"> <template #default="{ row }">
{{ Math.floor(row.eventValue * 10000) / 100 }} {{ Math.floor(row.eventValue * 10000) / 100 }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="persistTime" width="120px" sortable title="持续时间(s)">
<template #default="{ row }">
{{ Math.floor(row.persistTime * 1000) / 1000 }}
</template>
</vxe-column>
<vxe-column field="eventType" width="100px" title="触发类型"> <vxe-column field="eventType" width="100px" title="触发类型">
<template #default="{ row }"> <template #default="{ row }">
{{ event.filter(item => item.id == row.eventType)[0]?.name || '/' }} {{ event.filter(item => item.id == row.eventType)[0]?.name || '/' }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="powerCompany" title="变电站" width="100px"></vxe-column>
<vxe-column field="powerCompany" title="供电公司" width="100px"></vxe-column>
<vxe-column field="lineName" title="监测点"></vxe-column>
</vxe-table> </vxe-table>
<div class="table-pagination mt10"> <div class="table-pagination mt10">
<el-pagination <el-pagination
@@ -100,7 +100,6 @@ const dataSocket = reactive({
const socket = async () => { const socket = async () => {
const url = localStorage.getItem('WebSocketUrl3') || 'null' //'ws://192.168.2.130:10203/event/' const url = localStorage.getItem('WebSocketUrl3') || 'null' //'ws://192.168.2.130:10203/event/'
// const url = 'ws://192.168.1.68:10203/event/' // const url = 'ws://192.168.1.68:10203/event/'
await dataSocket.socketServe.connect(`${url}${adminInfo.id}`) await dataSocket.socketServe.connect(`${url}${adminInfo.id}`)

View File

@@ -0,0 +1,59 @@
const AXIS_DECIMALS = 2
export function roundAxisValue(val: number, decimals = AXIS_DECIMALS): number {
if (!Number.isFinite(val)) return 0
const factor = 10 ** decimals
return Math.round(val * factor) / factor
}
/** Y 轴刻度:最多 2 位小数,末尾 0 去掉(如 1.00 → 10.10 → 0.1 */
export function formatAxisLabel(value: number): string {
if (!Number.isFinite(value)) return '0'
return String(Number(roundAxisValue(value).toFixed(AXIS_DECIMALS)))
}
/** 瞬间波形 Y 轴范围 */
export function calcShuYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } {
const min = Number(dataMin)
const max = Number(dataMax)
if (!Number.isFinite(min) || !Number.isFinite(max)) {
return { min: 0, max: 1 }
}
let axisMax = max * 1.1
let axisMin = min > 0 ? min - min * 0.1 : min * 1.1
if (axisMax <= axisMin) {
const pad = Math.abs(max) * 0.1 || 0.01
axisMax = max + pad
axisMin = min - pad
}
return {
min: roundAxisValue(axisMin),
max: roundAxisValue(axisMax)
}
}
/** RMS 波形 Y 轴范围 */
export function calcRmsYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } {
const min = Number(dataMin)
const max = Number(dataMax)
if (!Number.isFinite(min) || !Number.isFinite(max)) {
return { min: 0, max: 1 }
}
let axisMax = max * 1.06 * 1.1
let axisMin = min - min * 0.2
if (axisMax <= axisMin) {
const pad = Math.abs(max - min) * 0.1 || Math.abs(max) * 0.1 || 0.01
axisMax = max + pad
axisMin = min - pad
}
return {
min: roundAxisValue(axisMin),
max: roundAxisValue(axisMax)
}
}

42
src/utils/waveCache.ts Normal file
View File

@@ -0,0 +1,42 @@
const MAX_CACHE_SIZE = 30
const cache = new Map<string, unknown>()
function dataFingerprint(data: unknown[][] | undefined): string {
if (!data?.length) return '0'
const first = data[0]
const last = data[data.length - 1]
return `${data.length}:${first?.[0]}:${last?.[0]}`
}
export function buildWaveCacheKey(
type: 'shu' | 'rms',
wp: Record<string, any> | undefined,
value: number,
isOpen: boolean,
boxoList: Record<string, any>
): string {
if (!wp) return ''
const waveFp =
type === 'shu' ? dataFingerprint(wp.listWaveData) : dataFingerprint(wp.listRmsData)
const boxoFp = boxoList?.startTime ?? boxoList?.lineName ?? boxoList?.equipmentName ?? ''
return `${type}|${wp.time}|${wp.waveType}|${wp.iphasic}|${value}|${isOpen}|${waveFp}|${boxoFp}`
}
export function getWaveCache<T>(key: string): T | null {
if (!key || !cache.has(key)) return null
const value = cache.get(key) as T
cache.delete(key)
cache.set(key, value)
return value
}
export function setWaveCache(key: string, value: unknown): void {
if (!key) return
if (cache.has(key)) cache.delete(key)
cache.set(key, value)
while (cache.size > MAX_CACHE_SIZE) {
const oldest = cache.keys().next().value
if (oldest !== undefined) cache.delete(oldest)
}
}

View File

@@ -0,0 +1,96 @@
import { toRaw } from 'vue'
type WorkerMessageHandler = (data: any) => void
let shuWorker: Worker | null = null
let rmsWorker: Worker | null = null
/** 递归剥离 Vue 响应式代理,得到可 structuredClone 的纯对象 */
export function toPlainDeep<T>(value: T): T {
const raw = toRaw(value as object) as T
if (Array.isArray(raw)) {
return raw.map(item => toPlainDeep(item)) as T
}
if (raw !== null && typeof raw === 'object') {
const out: Record<string, unknown> = {}
for (const [key, val] of Object.entries(raw)) {
out[key] = toPlainDeep(val)
}
return out as T
}
return raw
}
const BOXO_LIST_KEYS = [
'systemType',
'powerStationName',
'measurementPointName',
'startTime',
'featureAmplitude',
'duration',
'engineeringName',
'equipmentName',
'evtParamVVaDepth',
'evtParamTm',
'lineName',
'persistTime',
'subName'
] as const
export function buildWorkerPayload(
type: 'shu' | 'rms',
wp: Record<string, any>,
boxoList: Record<string, any>,
extras: { requestId: number; value: number; isOpen: boolean; iphasic?: number }
) {
const plainWp = toPlainDeep(wp)
const wpPayload: Record<string, unknown> = {
pt: plainWp.pt,
ct: plainWp.ct,
waveTitle: plainWp.waveTitle,
iphasic: plainWp.iphasic,
time: plainWp.time,
waveType: plainWp.waveType,
yzd: plainWp.yzd
}
if (type === 'shu') {
wpPayload.listWaveData = plainWp.listWaveData
} else {
wpPayload.listRmsData = plainWp.listRmsData
}
const plainBoxo: Record<string, unknown> = {}
const rawBoxo = toPlainDeep(boxoList)
for (const key of BOXO_LIST_KEYS) {
if (rawBoxo[key] !== undefined) {
plainBoxo[key] = rawBoxo[key]
}
}
return {
requestId: extras.requestId,
value: extras.value,
isOpen: extras.isOpen,
iphasic: extras.iphasic,
wp: wpPayload,
boxoList: plainBoxo
}
}
export function getShuWorker(onMessage: WorkerMessageHandler): Worker {
if (!shuWorker) {
shuWorker = new Worker(new URL('../components/echarts/shuWorker.js', import.meta.url))
}
shuWorker.onmessage = e => onMessage(e.data)
shuWorker.onerror = error => console.error('Shu worker error:', error)
return shuWorker
}
export function getRmsWorker(onMessage: WorkerMessageHandler): Worker {
if (!rmsWorker) {
rmsWorker = new Worker(new URL('../components/echarts/rmsWorker.js', import.meta.url))
}
rmsWorker.onmessage = e => onMessage(e.data)
rmsWorker.onerror = error => console.error('Rms worker error:', error)
return rmsWorker
}

View File

@@ -58,7 +58,7 @@ export default class SocketService {
} }
// 处理连接成功事件 // 处理连接成功事件
private handleOpen(): void { private handleOpen(): void {
ElMessage.success('webSocket连接服务端成功了') // ElMessage.success('webSocket连接服务端成功了')
console.log('连接服务端成功了') console.log('连接服务端成功了')
this.connected = true this.connected = true
this.connectRetryCount = 0 this.connectRetryCount = 0
@@ -110,7 +110,7 @@ export default class SocketService {
} }
} else { } else {
this.callBackMapping['message']!({ Flag: false }) this.callBackMapping['message']!({ Flag: false })
ElMessage.error(event.data) // ElMessage.error(event.data)
} }
} }

View File

@@ -50,12 +50,12 @@
min-width="150px" min-width="150px"
show-overflow-tooltip show-overflow-tooltip
></vxe-column> ></vxe-column>
<vxe-column field="startTime" title="暂降发生时刻" min-width="150px"></vxe-column> <vxe-column field="startTime" title="暂降发生时刻" min-width="180px" sortable></vxe-column>
<vxe-column <vxe-column
field="featureAmplitude" field="featureAmplitude"
title="暂降(骤升)幅值(%)" title="暂降(骤升)幅值(%)"
sortable sortable
min-width="150px" min-width="160px"
></vxe-column> ></vxe-column>
<vxe-column <vxe-column
field="advanceReason" field="advanceReason"

View File

@@ -79,7 +79,7 @@ onMounted(() => {
}) })
const urlKey=ref('') const urlKey=ref('')
const VITE_FLAG = import.meta.env.VITE_NAME == 'jibei' const VITE_FLAG = false//import.meta.env.VITE_NAME == 'jibei'
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
// console.log("🚀 ~ handleNodeClick ~ data:", data) // console.log("🚀 ~ handleNodeClick ~ data:", data)
dotList.value = data dotList.value = data

View File

@@ -4,7 +4,13 @@
<TableHeader datePicker area showExport> <TableHeader datePicker area showExport>
<template #select> <template #select>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="输入关键字筛选" clearable maxlength="32" show-word-limit/> <el-input
v-model="tableStore.table.params.searchValue"
placeholder="输入关键字筛选"
clearable
maxlength="32"
show-word-limit
/>
</el-form-item> </el-form-item>
<el-form-item label="统计类型"> <el-form-item label="统计类型">
<el-select <el-select
@@ -127,7 +133,7 @@ const tableStore = new TableStore({
{ field: 'lineName', title: '监测点名称', minWidth: '180' }, { field: 'lineName', title: '监测点名称', minWidth: '180' },
{ field: 'gdName', title: '供电公司', minWidth: '120' }, { field: 'gdName', title: '供电公司', minWidth: '120' },
{ field: 'subName', title: '变电站', minWidth: '150' }, { field: 'subName', title: '变电站', minWidth: '150' },
{ field: 'ip', title: '网络参数' ,width:'120px' }, { field: 'ip', title: '网络参数', width: '120px' },
{ field: 'scale', title: '电压等级', minWidth: '110' }, { field: 'scale', title: '电压等级', minWidth: '110' },
{ {
field: 'advanceType', field: 'advanceType',
@@ -137,7 +143,7 @@ const tableStore = new TableStore({
return row.cellValue || '其他' return row.cellValue || '其他'
} }
}, },
{ {
field: 'eventType', field: 'eventType',
title: '触发类型', title: '触发类型',
minWidth: '120', minWidth: '120',
@@ -180,7 +186,8 @@ const tableStore = new TableStore({
{ field: 'duration', title: '持续时间(s)', minWidth: '100' }, { field: 'duration', title: '持续时间(s)', minWidth: '100' },
{ {
title: '操作',fixed: 'right', title: '操作',
fixed: 'right',
width: '120', width: '120',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
@@ -278,6 +285,7 @@ const download = () => {
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) //释放标签 document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
}) })
} }
</script> </script>

View File

@@ -1,5 +1,6 @@
<template> <template>
<div class="default-main online"> <div class="default-main online">
<div class="online_header"> <div class="online_header">
<TableHeader date-picker ref="tableHeaderRef"> <TableHeader date-picker ref="tableHeaderRef">
<template #select> <template #select>
@@ -54,6 +55,14 @@
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.comFlagStatus" clearable placeholder="请选择通讯状态"
style="width: 100%" >
<el-option label="正常" value="1" />
<el-option label="中断" value="0" />
</el-select>
</el-form-item>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字"></el-input> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字"></el-input>
</el-form-item> </el-form-item>
@@ -313,6 +322,7 @@ tableStore.table.params.statisticalType = []
tableStore.table.params.scale = [] tableStore.table.params.scale = []
tableStore.table.params.manufacturer = [] tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = [] tableStore.table.params.loadType = []
tableStore.table.params.comFlagStatus=''
provide('tableStore', tableStore) provide('tableStore', tableStore)
const tree2List = (list: any, id?: string) => { const tree2List = (list: any, id?: string) => {
//存储结果的数组 //存储结果的数组
@@ -479,13 +489,13 @@ const socket = async (form: any) => {
await dataSocket.socketServe.send(form) await dataSocket.socketServe.send(form)
logList.value.push({ logList.value.push({
type: '', type: '',
time: formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'), time: formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss'),
name: '开始补召,请稍等...', name: '开始补召,请稍等...',
}) })
await dataSocket.socketServe.registerCallBack('message', (res: any) => { await dataSocket.socketServe.registerCallBack('message', (res: any) => {
logList.value.push({ logList.value.push({
type: res.code == 500 ? 'error' : '', type: res.code == 500 ? 'error' : '',
time: formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'), time: formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss'),
name: res.message name: res.message
}) })

View File

@@ -10,39 +10,81 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" <el-input
style="width: 200px" maxlength="32" show-word-limit /> v-model="tableStore.table.params.searchValue"
clearable
placeholder="输入关键字筛选"
style="width: 200px"
maxlength="32"
show-word-limit
/>
</el-form-item> </el-form-item>
<el-form-item label="触发类型"> <el-form-item label="触发类型">
<el-select v-model="tableStore.table.params.waveType" placeholder="请选择触发类型" clearable multiple <el-select
collapse-tags style="width: 100%"> v-model="tableStore.table.params.waveType"
<el-option v-for="item in triggeroptions" :key="item.id" :label="item.name" placeholder="请选择触发类型"
:value="item.id"></el-option> clearable
multiple
collapse-tags
style="width: 100%"
>
<el-option
v-for="item in triggeroptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="是否有波形"> <el-form-item label="是否有波形">
<el-select v-model="tableStore.table.params.fileFlag" placeholder="请选择是否存在波形" clearable <el-select
style="width: 100%"> v-model="tableStore.table.params.fileFlag"
<el-option v-for="item in wareaoptions" :key="item.id" :label="item.label" placeholder="请选择是否存在波形"
:value="item.id"></el-option> clearable
style="width: 100%"
>
<el-option
v-for="item in wareaoptions"
:key="item.id"
:label="item.label"
:value="item.id"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="暂态持续时间(s)"> <el-form-item label="暂态持续时间(s)">
<el-input v-model="tableStore.table.params.persistMin" placeholder="请输入X秒" <el-input
onkeyup="value=value.replace(/[^\d.]/g,'')" clearable style="width: 94px"></el-input> v-model="tableStore.table.params.persistMin"
placeholder="请输入X秒"
onkeyup="value=value.replace(/[^\d.]/g,'')"
clearable
style="width: 94px"
></el-input>
<el-tag style="margin-left: 5px">&lt; 时间数 &lt;</el-tag> <el-tag style="margin-left: 5px">&lt; 时间数 &lt;</el-tag>
<el-input v-model="tableStore.table.params.persistMax" placeholder="请输入X秒" <el-input
onkeyup="value=value.replace(/[^\d.]/g,'')" clearable v-model="tableStore.table.params.persistMax"
style="margin-left: 5px; width: 94px"></el-input> placeholder="请输入X秒"
onkeyup="value=value.replace(/[^\d.]/g,'')"
clearable
style="margin-left: 5px; width: 94px"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="事件严重度"> <el-form-item label="事件严重度">
<el-input v-model="tableStore.table.params.severityMin" placeholder="请输入正负数" <el-input
onkeyup="value=value.replace(/[^\d\.-]/g,'')" clearable style="width: 94px"></el-input> v-model="tableStore.table.params.severityMin"
placeholder="请输入正负数"
onkeyup="value=value.replace(/[^\d\.-]/g,'')"
clearable
style="width: 94px"
></el-input>
<el-tag style="margin-left: 5px">&lt; 严重度 &lt;</el-tag> <el-tag style="margin-left: 5px">&lt; 严重度 &lt;</el-tag>
<el-input v-model="tableStore.table.params.severityMax" placeholder="请输入正负数" <el-input
onkeyup="value=value.replace(/[^\d\.-]/g,'')" clearable v-model="tableStore.table.params.severityMax"
style="margin-left: 5px; width: 94px"></el-input> placeholder="请输入正负数"
onkeyup="value=value.replace(/[^\d\.-]/g,'')"
clearable
style="margin-left: 5px; width: 94px"
></el-input>
</el-form-item> </el-form-item>
<!-- <el-form-item label="触发类型:"> <!-- <el-form-item label="触发类型:">
@@ -53,23 +95,52 @@
</el-select> </el-select>
</el-form-item> --> </el-form-item> -->
<el-form-item label="暂态原因"> <el-form-item label="暂态原因">
<el-select v-model="tableStore.table.params.eventReason" placeholder="请选择暂态原因" clearable <el-select
multiple collapse-tags style="width: 100%"> v-model="tableStore.table.params.eventReason"
<el-option v-for="item in reasonoptions" :key="item.id" :label="item.name" placeholder="请选择暂态原因"
:value="item.id"></el-option> clearable
multiple
collapse-tags
style="width: 100%"
>
<el-option
v-for="item in reasonoptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="暂态核实原因"> <el-form-item label="暂态核实原因">
<el-select v-model="tableStore.table.params.verifyReason" placeholder="请选择暂态核实原因" clearable <el-select
multiple collapse-tags collapse-tags-tooltip> v-model="tableStore.table.params.verifyReason"
<el-option v-for="item in verifyReasonList" :key="item.id" :label="item.name" placeholder="请选择暂态核实原因"
:value="item.id"></el-option> clearable
multiple
collapse-tags
collapse-tags-tooltip
>
<el-option
v-for="item in verifyReasonList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="变电站(监测点)"> <el-form-item label="变电站(监测点)">
<el-cascader v-model="tableStore.table.params.lineIds" :options="options" :props="defaultProps" <el-cascader
collapse-tags-tooltip style="width: 257px" filterable clearable collapse-tags v-model="tableStore.table.params.lineIds"
placeholder="请选择变电站(监测点)" :show-all-levels="true" /> :options="options"
:props="defaultProps"
collapse-tags-tooltip
style="width: 257px"
filterable
clearable
collapse-tags
placeholder="请选择变电站(监测点)"
:show-all-levels="true"
/>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
@@ -146,33 +217,17 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'startTime', title: '暂降发生时刻', minWidth: '200' }, { field: 'startTime', title: '暂降发生时刻', minWidth: '200', sortable: true },
{ field: 'gdName', title: '供电公司', minWidth: '100' },
{ field: 'subName', title: '变电站', minWidth: '200' },
{ field: 'ip', title: '网络参数', width: '120px' },
{ field: 'lineName', title: '监测点', minWidth: '100' },
{ field: 'scale', title: '电压等级(kV)', minWidth: '120' },
{
field: 'verifyReason',
title: '暂态核实原因',
minWidth: '120',
formatter: function (row) {
return verifyReasonList.filter(item => item.id == row.cellValue)[0]?.name || '/' //row.cellValue ? row.cellValue : '/'
}
},
// {
// field: 'verifyReasonDetail', title: '暂降核实原因详情', minWidth: '200', formatter: function (row) {
// return row.cellValue ? row.cellValue : '/'
// }
// },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)', title: '暂降(骤升)幅值(%)',
minWidth: '130', minWidth: '160',
sortable: true,
formatter: (row: any) => { formatter: (row: any) => {
return Math.floor(row.cellValue * 10000) / 100 return Math.floor(row.cellValue * 10000) / 100
} }
}, },
{ field: 'duration', title: '持续时间(s)', minWidth: 120, sortable: true },
{ {
field: 'eventType', field: 'eventType',
title: '触发类型', title: '触发类型',
@@ -182,17 +237,32 @@ const tableStore = new TableStore({
return triggeroptions.filter(item => item.id == row.eventType)[0]?.name return triggeroptions.filter(item => item.id == row.eventType)[0]?.name
} }
}, },
// { field: 'advanceType', title: '触发类型', minWidth: '100', },
{ field: 'advanceReason', title: '暂态原因', minWidth: '100' },
{ {
field: 'depth', field: 'depth',
title: '暂降深度(%)', title: '暂降深度(%)',
minWidth: '100', minWidth: 120,
formatter: ({ row }: any) => formatter: ({ row }: any) =>
row.featureAmplitude < 1 ? 100 - (row.featureAmplitude * 100).toFixed(0) : '/' row.featureAmplitude < 1 ? 100 - (row.featureAmplitude * 100).toFixed(0) : '/'
}, },
{ field: 'duration', title: '持续时间(s)', minWidth: '100' }, { field: 'advanceReason', title: '暂态原因', minWidth: '100' },
{
field: 'verifyReason',
title: '暂态核实原因',
minWidth: '120',
formatter: function (row) {
return verifyReasonList.filter(item => item.id == row.cellValue)[0]?.name || '/' //row.cellValue ? row.cellValue : '/'
}
},
{ field: 'gdName', title: '供电公司', minWidth: '100' },
{ field: 'subName', title: '变电站', minWidth: '200' },
{ field: 'lineName', title: '监测点', minWidth: '100' },
{ field: 'ip', title: '网络参数', width: '120px' },
{ field: 'scale', title: '电压等级(kV)', minWidth: '130', sortable: true },
// { field: 'advanceType', title: '触发类型', minWidth: '100', },
{ {
field: 'severity', field: 'severity',
title: '严重度', title: '严重度',
@@ -201,7 +271,8 @@ const tableStore = new TableStore({
}, },
{ {
title: '操作', fixed: 'right', title: '操作',
fixed: 'right',
width: '150', width: '150',
render: 'buttons', render: 'buttons',
@@ -259,7 +330,7 @@ const tableStore = new TableStore({
} }
], ],
loadCallback: () => { } loadCallback: () => {}
}) })
const options = ref([]) const options = ref([])
const defaultProps = { const defaultProps = {
@@ -353,6 +424,7 @@ const download = () => {
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) //释放标签 document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
}) })
} }
</script> </script>

View File

@@ -3,9 +3,9 @@
<div v-show="view"> <div v-show="view">
<TableHeader datePicker :showReset="false" showExport ref="TableHeaderRef"> <TableHeader datePicker :showReset="false" showExport ref="TableHeaderRef">
<template #select> <template #select>
<!-- <el-form-item label="筛选数据">--> <!-- <el-form-item label="筛选数据">-->
<!-- <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />--> <!-- <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />-->
<!-- </el-form-item>--> <!-- </el-form-item>-->
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Tickets" type="primary" @click="analysis1">分析记录管理</el-button> <el-button icon="el-icon-Tickets" type="primary" @click="analysis1">分析记录管理</el-button>
@@ -29,7 +29,7 @@
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
<el-pagination <el-pagination
class="mt10" class="mt10"
:currentPage="form.pageNum" :currentPage="form.pageNum"
:page-size="form.pageSize" :page-size="form.pageSize"
@@ -39,7 +39,7 @@
:total="total" :total="total"
@size-change="onTableSizeChange" @size-change="onTableSizeChange"
@current-change="onTableCurrentChange" @current-change="onTableCurrentChange"
></el-pagination> ></el-pagination>
</el-dialog> </el-dialog>
</div> </div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view"> <div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
@@ -70,7 +70,7 @@ const loading = ref(false)
const view = ref(true) const view = ref(true)
const view2 = ref(false) const view2 = ref(false)
const TableHeaderRef = ref() const TableHeaderRef = ref()
const waveFormRef = ref() const waveFormRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/advance-boot/process/querySagEventsPage', url: '/advance-boot/process/querySagEventsPage',
method: 'POST', method: 'POST',
@@ -83,19 +83,23 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'startTime', title: '发生时间' }, { field: 'startTime', title: '暂降发生时刻', sortable: true, minWidth: 200 },
{ field: 'duration', title: '持续时间(s)' },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)' title: '暂降(骤升)幅值(%)',
sortable: true,
minWidth: 160
}, },
{ field: 'gdName', title: '供电公司' }, { field: 'duration', title: '持续时间(s)', sortable: true, minWidth: 120 },
{ field: 'subName', title: '变电站' }, { field: 'gdName', title: '供电公司', minWidth: 140 },
{ field: 'lineName', title: '监测点' }, { field: 'subName', title: '变电站', minWidth: 140 },
{ field: 'lineName', title: '监测点', minWidth: 140 },
{ {
field: 'dealFlag', field: 'dealFlag',
title: '暂降特征幅值计算', title: '暂降特征幅值计算',
render: 'tag', render: 'tag',
minWidth: 160,
custom: { custom: {
0: 'warning', 0: 'warning',
1: 'success', 1: 'success',
@@ -115,6 +119,7 @@ const tableStore = new TableStore({
field: 'fileFlag', field: 'fileFlag',
title: '录波文件', title: '录波文件',
render: 'tag', render: 'tag',
minWidth: 140,
custom: { custom: {
0: 'warning', 0: 'warning',
1: 'success' 1: 'success'
@@ -125,7 +130,8 @@ const tableStore = new TableStore({
} }
}, },
{ {
title: '操作',fixed: 'right', title: '操作',
fixed: 'right',
width: '120', width: '120',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
@@ -140,9 +146,9 @@ const tableStore = new TableStore({
render: 'basicButton', render: 'basicButton',
click: async row => { click: async row => {
view.value = false view.value = false
setTimeout(() => { setTimeout(() => {
waveFormRef.value.open(row) waveFormRef.value.open(row)
},100) }, 100)
// row.loading = true // row.loading = true
// boxoList.value = row // boxoList.value = row
// await getMonitorEventAnalyseWave({ id: row.eventId, systemType: 0 }) // await getMonitorEventAnalyseWave({ id: row.eventId, systemType: 0 })
@@ -173,7 +179,7 @@ const tableStore = new TableStore({
} }
], ],
loadCallback: () => { } loadCallback: () => {}
}) })
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
const bxactiveName = ref('ssbx') const bxactiveName = ref('ssbx')
@@ -190,25 +196,21 @@ provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
TableHeaderRef.value.setTheDate(1) TableHeaderRef.value.setTheDate(1)
nextTick(() => { nextTick(() => {
// tableStore.index() // tableStore.index()
TableHeaderRef.value.onComSearch() TableHeaderRef.value.onComSearch()
}) })
}) })
// 分页 // 分页
const onTableSizeChange = (val: number) => { const onTableSizeChange = (val: number) => {
form.value.pageSize = val form.value.pageSize = val
form.value.pageNum = 1 // 改变每页条数时回到第一页 form.value.pageNum = 1 // 改变每页条数时回到第一页
loadAnalysisData() // 重新加载数据 loadAnalysisData() // 重新加载数据
} }
const onTableCurrentChange = (val: number) => { const onTableCurrentChange = (val: number) => {
form.value.pageNum = val form.value.pageNum = val
loadAnalysisData() // 重新加载数据 loadAnalysisData() // 重新加载数据
} }
// 封装数据加载逻辑 // 封装数据加载逻辑
@@ -230,13 +232,12 @@ const loadAnalysisData = async () => {
//分析记录管理 //分析记录管理
const analysis1 = async () => { const analysis1 = async () => {
// 初始化分页参数 // 初始化分页参数
form.value.pageNum = 1 form.value.pageNum = 1
await loadAnalysisData() await loadAnalysisData()
dialogAnalysis.value = true dialogAnalysis.value = true
} }
// 启动关联分析 // 启动关联分析
const firing = () => { const firing = () => {
processEvents({ processEvents({
@@ -257,7 +258,7 @@ const details = (row: any) => {
type: 'success', type: 'success',
message: res.message message: res.message
}) })
// 重新加载当前页的数据 // 重新加载当前页的数据
loadAnalysisData() loadAnalysisData()
}) })
} }
@@ -266,6 +267,4 @@ const backbxlb = () => {
view.value = true view.value = true
view2.value = false view2.value = false
} }
</script> </script>

View File

@@ -3,7 +3,13 @@
<TableHeader datePicker ref="TableHeaderRef"> <TableHeader datePicker ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="筛选数据"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入事件关联分析描述" maxlength="32" show-word-limit/> <el-input
v-model="tableStore.table.params.searchValue"
clearable
placeholder="输入事件关联分析描述"
maxlength="32"
show-word-limit
/>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
@@ -35,25 +41,18 @@
</vxe-table-column> </vxe-table-column>
<vxe-table-column <vxe-table-column
field="startTime" field="startTime"
title="发生时" title="暂降发生时"
align="center" align="center"
sortable
width="200"
:show-overflow="true" :show-overflow="true"
></vxe-table-column> ></vxe-table-column>
<vxe-table-column field="gdName" title="供电公司" align="center"></vxe-table-column> <vxe-table-column field="featureAmplitude" title="暂降(骤升)幅值(%)" sortable align="center" width="160">
<vxe-table-column
field="subName"
:show-overflow="true"
title="变电站"
align="center"
></vxe-table-column>
<vxe-table-column field="lineName" title="监测点" align="center"></vxe-table-column>
<vxe-table-column field="voltageId" title="电压等级(kV)" align="center"></vxe-table-column>
<vxe-table-column field="featureAmplitude" title="暂降(骤升)幅值(%)" align="center" width="140">
<template #default="{ row }"> <template #default="{ row }">
<span>{{ (row.featureAmplitude * 100).toFixed(2) }}</span> <span>{{ (row.featureAmplitude * 100).toFixed(2) }}</span>
</template> </template>
</vxe-table-column> </vxe-table-column>
<vxe-table-column field="duration" title="持续时间(s)" align="center" width="120"></vxe-table-column> <vxe-table-column field="duration" title="持续时间(s)" sortable align="center" width="120"></vxe-table-column>
<vxe-table-column <vxe-table-column
field="advanceType" field="advanceType"
title="触发类型" title="触发类型"
@@ -68,6 +67,15 @@
width="120" width="120"
:formatter="formFilter" :formatter="formFilter"
></vxe-table-column> ></vxe-table-column>
<vxe-table-column field="gdName" title="供电公司" align="center"></vxe-table-column>
<vxe-table-column
field="subName"
:show-overflow="true"
title="变电站"
align="center"
></vxe-table-column>
<vxe-table-column field="lineName" title="监测点" align="center"></vxe-table-column>
<vxe-table-column field="voltageId" title="电压等级(kV)" align="center"></vxe-table-column>
</vxe-table> </vxe-table>
<el-pagination <el-pagination
class="mt10" class="mt10"
@@ -131,7 +139,8 @@ const tableStore = new TableStore({
title: '事件关联分析描述' title: '事件关联分析描述'
}, },
{ {
title: '操作',fixed: 'right', title: '操作',
fixed: 'right',
width: '200', width: '200',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
@@ -176,7 +185,6 @@ const bxcontrast = () => {
} }
} }
// 波形分析 // 波形分析
const source = () => { const source = () => {
queryEventDetailByAssId(form.value).then(res => { queryEventDetailByAssId(form.value).then(res => {
@@ -245,14 +253,14 @@ const exportEvent = () => {
} }
// 导出波形分析 // 导出波形分析
const positioningexport = () => { const positioningexport = () => {
const selectedRecords = positioningtableRef.value.getCheckboxRecords(); const selectedRecords = positioningtableRef.value.getCheckboxRecords()
if (selectedRecords.length === 0) { if (selectedRecords.length === 0) {
ElMessage({ ElMessage({
message: '请先选择要导出的数据!', message: '请先选择要导出的数据!',
type: 'warning' type: 'warning'
}); })
return; return
} }
positioningtableRef.value.exportData({ positioningtableRef.value.exportData({

View File

@@ -27,22 +27,23 @@
<span>{{ (form.pageNum - 1) * form.pageSize + row.rowIndex + 1 }}</span> <span>{{ (form.pageNum - 1) * form.pageSize + row.rowIndex + 1 }}</span>
</template> </template>
</vxe-table-column> </vxe-table-column>
<vxe-table-column field="startTime" title="发生时" align="center" <vxe-table-column field="startTime" title="暂降发生时" align="center" sortable width="200"
:show-overflow="true"></vxe-table-column> :show-overflow="true"></vxe-table-column>
<vxe-table-column field="gdName" title="供电公司" align="center"></vxe-table-column> <vxe-table-column field="featureAmplitude" title="暂降(骤升)幅值(%)" sortable align="center" width="160">
<vxe-table-column field="subName" :show-overflow="true" title="变电站" align="center"></vxe-table-column>
<vxe-table-column field="lineName" title="监测点" align="center"></vxe-table-column>
<vxe-table-column field="voltageId" title="电压等级(kV)" align="center"></vxe-table-column>
<vxe-table-column field="featureAmplitude" title="暂降(骤升)幅值(%)" align="center" width="140">
<template #default="{ row }"> <template #default="{ row }">
<span>{{ (row.featureAmplitude * 100).toFixed(2) }}</span> <span>{{ (row.featureAmplitude * 100).toFixed(2) }}</span>
</template> </template>
</vxe-table-column> </vxe-table-column>
<vxe-table-column field="duration" title="持续时间(s)" align="center" width="120"></vxe-table-column> <vxe-table-column field="duration" title="持续时间(s)" align="center" sortable width="120"></vxe-table-column>
<vxe-table-column field="advanceType" title="触发类型" align="center" width="120" <vxe-table-column field="advanceType" title="触发类型" align="center" width="120"
:formatter="formFilter"></vxe-table-column> :formatter="formFilter"></vxe-table-column>
<vxe-table-column field="advanceReason" title="暂降原因" align="center" width="120" <vxe-table-column field="advanceReason" title="暂降原因" align="center" width="120"
:formatter="formFilter"></vxe-table-column> :formatter="formFilter"></vxe-table-column>
<vxe-table-column field="gdName" title="供电公司" align="center"></vxe-table-column>
<vxe-table-column field="subName" :show-overflow="true" title="变电站" align="center"></vxe-table-column>
<vxe-table-column field="lineName" title="监测点" align="center"></vxe-table-column>
<vxe-table-column field="voltageId" title="电压等级(kV)" align="center"></vxe-table-column>
</vxe-table> </vxe-table>
<el-pagination class="mt10" :currentPage="form.pageNum" :page-size="form.pageSize" <el-pagination class="mt10" :currentPage="form.pageNum" :page-size="form.pageSize"
:page-sizes="[10, 20, 50, 100]" background :layout="'sizes,total, ->, prev, pager, next, jumper'" :page-sizes="[10, 20, 50, 100]" background :layout="'sizes,total, ->, prev, pager, next, jumper'"

View File

@@ -56,34 +56,37 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ title: '变电站名称', field: 'subName', minWidth: '140' }, { title: '暂降发生时刻', field: 'startTime', width: '200', sortable: true, },
{ title: '监测点名称', field: 'lineName', minWidth: '130' },
{ title: '网络参数', field: 'ip', width: '120px' },
{ title: '电压等级(kV)', field: 'voltageScale', width: '120' },
{ title: '暂降发生时刻', field: 'startTime', width: '200' },
// { title: '触发类型', field: 'advanceType', minWidth: '130' },
{ title: '暂降原因', field: 'advanceReason', minWidth: '130' },
{
title: '触发类型',
field: 'eventType',
minWidth: '80',
formatter: (row: any) => {
return eventTypeOptions.find(item => item.id === row.cellValue)?.name || '/'
}
},
{ {
title: '暂降(骤升)幅值(%)', title: '暂降(骤升)幅值(%)',
field: 'featureAmplitude', field: 'featureAmplitude',
minWidth: '140', minWidth: '160',
sortable: true,
formatter: (row: any) => { formatter: (row: any) => {
return Math.floor(row.cellValue * 10000) / 100 return Math.floor(row.cellValue * 10000) / 100
} }
}, },
{ title: '持续时间(s)', field: 'duration', minWidth: '100' }, { title: '持续时间(s)', field: 'duration', minWidth: '120' , sortable: true, },
{
title: '触发类型',
field: 'eventType',
minWidth: '100',
formatter: (row: any) => {
return eventTypeOptions.find(item => item.id === row.cellValue)?.name || '/'
}
},
{ title: '暂降原因', field: 'advanceReason', minWidth: '130' },
{ title: '变电站名称', field: 'subName', minWidth: '140' },
{ title: '监测点名称', field: 'lineName', minWidth: '130' },
{ title: '网络参数', field: 'ip', width: '120px' },
{ title: '电压等级(kV)', field: 'voltageScale', width: '120' },
// { title: '触发类型', field: 'advanceType', minWidth: '130' },
// { title: '严重度', field: 'severity', minWidth: '80' }, // { title: '严重度', field: 'severity', minWidth: '80' },
{ {
title: '操作',fixed: 'right', title: '操作',
fixed: 'right',
width: '180', width: '180',
render: 'buttons', render: 'buttons',
@@ -127,7 +130,6 @@ const tableStore = new TableStore({
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.table.params.lineId = monitoringPoint.state.lineId tableStore.table.params.lineId = monitoringPoint.state.lineId
}, },
loadCallback: () => {} loadCallback: () => {}
}) })
@@ -174,6 +176,7 @@ const download = () => {
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) //释放标签 document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
}) })
} }
</script> </script>

View File

@@ -3,21 +3,21 @@
<div style="height: 40vh"> <div style="height: 40vh">
<vxe-table v-loading="loading" height="auto" auto-resize :data="tableData" v-bind="defaultAttribute"> <vxe-table v-loading="loading" height="auto" auto-resize :data="tableData" v-bind="defaultAttribute">
<vxe-column type="seq" title="序号" width="80px"></vxe-column> <vxe-column type="seq" title="序号" width="80px"></vxe-column>
<vxe-column field="startTime" title="发生时" width="180"></vxe-column> <vxe-column field="startTime" title="暂降发生时" width="200" sortable></vxe-column>
<vxe-column field="duration" title="持续时间(s)" width="100"></vxe-column> <vxe-column field="featureAmplitude" title="暂降(骤升)幅值(%)" width="160" sortable>
<vxe-column field="gdName" title="供电公司" min-width="150"></vxe-column> <template #default="{ row }">
<vxe-column field="subName" title="变电站" min-width="150"></vxe-column> {{ (row.featureAmplitude * 100).toFixed(2) }}
<vxe-column field="lineName" title="监测点" min-width="150"></vxe-column> </template>
</vxe-column>
<vxe-column field="duration" title="持续时间(s)" width="120" sortable></vxe-column>
<vxe-column field="advanceType" title="触发类型" width="100"> <vxe-column field="advanceType" title="触发类型" width="100">
<template #default="{ row }"> <template #default="{ row }">
{{ type.find(item => item.id === row.advanceType)?.name }} {{ type.find(item => item.id === row.advanceType)?.name }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="featureAmplitude" title="暂降(骤升)幅值(%)" width="150"> <vxe-column field="gdName" title="供电公司" min-width="140"></vxe-column>
<template #default="{ row }"> <vxe-column field="subName" title="变电站" min-width="140"></vxe-column>
{{ (row.featureAmplitude * 100).toFixed(2) }} <vxe-column field="lineName" title="监测点名称" min-width="140"></vxe-column>
</template>
</vxe-column>
</vxe-table> </vxe-table>
</div> </div>
</el-dialog> </el-dialog>

View File

@@ -23,14 +23,15 @@
<div style="flex: 1; overflow: hidden"> <div style="flex: 1; overflow: hidden">
<vxe-table height="auto" auto-resize :data="tableData" v-bind="defaultAttribute"> <vxe-table height="auto" auto-resize :data="tableData" v-bind="defaultAttribute">
<vxe-column type="seq" title="序号" width="70px"></vxe-column> <vxe-column type="seq" title="序号" width="70px"></vxe-column>
<vxe-column field="startTime" title="发生时刻" width="200"></vxe-column> <vxe-column field="startTime" title="暂降发生时刻" width="200" sortable></vxe-column>
<vxe-column field="lineName" title="监测点" width="120"></vxe-column> <vxe-column field="featureAmplitude" title="暂降(骤升)幅值(%)" width="160" sortable>
<vxe-column field="featureAmplitude" title="暂降(骤升)幅值(%)">
<template #default="{ row }"> <template #default="{ row }">
{{ row.featureAmplitude.toFixed(2) }} {{ row.featureAmplitude.toFixed(2) }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="duration" title="持续时间(s)"></vxe-column> <vxe-column field="duration" title="持续时间(s)" sortable width="120"></vxe-column>
<vxe-column field="lineName" title="监测点" width="120"></vxe-column>
</vxe-table> </vxe-table>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader date-picker area > <TableHeader date-picker area>
<template v-slot:select> <template v-slot:select>
<el-form-item label="统计类型"> <el-form-item label="统计类型">
<el-radio-group v-model="tableStore.table.params.comFlag"> <el-radio-group v-model="tableStore.table.params.comFlag">
@@ -48,10 +48,12 @@
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent" :loading="loading">导出</el-button> <el-button icon="el-icon-Download" type="primary" @click="exportEvent" :loading="loading">
报告生成
</el-button>
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" :checkboxConfig="checkboxConfig" />
</div> </div>
</template> </template>
<script setup lang="tsx"> <script setup lang="tsx">
@@ -64,7 +66,7 @@ import { getEventReport } from '@/api/event-boot/report'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
defineOptions({ defineOptions({
name: 'Operationmanagement/terminalmanagement' name: 'TransientReport/eventreports'
}) })
const dictData = useDictData() const dictData = useDictData()
const triggerType = dictData.getBasicData('Event_Statis') const triggerType = dictData.getBasicData('Event_Statis')
@@ -82,6 +84,7 @@ const tableStore = new TableStore({
url: '/event-boot/report/getEventReport', url: '/event-boot/report/getEventReport',
method: 'POST', method: 'POST',
column: [ column: [
{ width: '60', type: 'checkbox' },
{ {
title: '序号', title: '序号',
@@ -93,42 +96,18 @@ const tableStore = new TableStore({
}, },
{ {
field: 'startTime', field: 'startTime',
title: '发生时刻', title: '暂降发生时刻',
width: '180', width: '180',
sortable: true,
formatter: (row: any) => { formatter: (row: any) => {
return row.cellValue ? row.cellValue.replace('T', ' ') : '/' return row.cellValue ? row.cellValue.replace('T', ' ') : '/'
} }
}, },
{ field: 'gdName', title: '供电公司', minWidth: '120' },
{ field: 'subName', title: '变电站', minWidth: '120' },
{ field: 'ip', title: '网络参数', width: '120px' },
{ field: 'lineName', title: '监测点', minWidth: '120' },
{
field: 'eventType',
title: '触发类型',minWidth: '100' ,
formatter: (row: any) => {
return triggerType.filter(item => item.id === row.cellValue)[0].name
}
},
{
field: 'advanceType',
title: '暂态类型',
minWidth: '100'
},
{
field: 'advanceReason',
title: '暂态原因',
minWidth: '100'
},
{
field: 'voltageScale',
title: '电压等级',
minWidth: '100'
},
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)', title: '暂降(骤升)幅值(%)',
width: '140', width: '160',
sortable: true,
formatter: (row: any) => { formatter: (row: any) => {
// return (row.cellValue * 100).toFixed(0) // return (row.cellValue * 100).toFixed(0)
@@ -138,8 +117,44 @@ const tableStore = new TableStore({
{ {
field: 'duration', field: 'duration',
title: '持续时间(s)', title: '持续时间(s)',
width: '100' width: '120',
sortable: true
},
{
field: 'eventType',
title: '触发类型',
minWidth: '100',
formatter: (row: any) => {
return triggerType.filter(item => item.id === row.cellValue)[0].name
}
},
{
field: 'advanceType',
title: '暂态类型',
minWidth: '100',
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{
field: 'advanceReason',
title: '暂态原因',
minWidth: '100',
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{ field: 'gdName', title: '供电公司', minWidth: '120' },
{ field: 'subName', title: '变电站', minWidth: '120' },
{ field: 'lineName', title: '监测点', minWidth: '120' },
{ field: 'ip', title: '网络参数', width: '120px' },
{
field: 'voltageScale',
title: '电压等级',
minWidth: '100'
} }
// { field: 'severity', title: '严重度' } // { field: 'severity', title: '严重度' }
] ]
}) })
@@ -156,7 +171,11 @@ tableStore.table.params.statisticalType = dictData.getBasicData('Statistical_Typ
'Voltage_Level', 'Voltage_Level',
'Load_Type' 'Load_Type'
])[0] ])[0]
const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({
checkMethod: ({ row }) => {
return row.fileFlag === 1
}
})
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
@@ -178,15 +197,17 @@ const exportEvent = () => {
// } // }
// }) // })
// }) // })
if (!tableStore.table.selection.length) {
ElMessage.warning('请选择数据')
const ids = tableStore.table.data.map((item: any) => item.eventId); return
}
const ids = tableStore.table.selection.map((item: any) => item.eventId)
loading.value = true loading.value = true
ElMessage('生成报告中,请稍等!') ElMessage('生成报告中,请稍等!')
getEventReport(ids) getEventReport(ids)
.then((res: any) => { .then((res: any) => {
if (res == undefined) { if (res == undefined) {
loading.value = false loading.value = false
return return
} }
@@ -197,14 +218,14 @@ const exportEvent = () => {
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签 const link = document.createElement('a') // 创建a标签
link.href = url link.href = url
link.download = '事件报告' // 设置下载的文件名 link.download = '事件报告' // 设置下载的文件名
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) document.body.removeChild(link)
loading.value = false loading.value = false
}) .catch(() => { })
.catch(() => {
loading.value = false loading.value = false
}) })
} }
</script> </script>

View File

@@ -56,19 +56,20 @@ const list = ref([
) )
} }
}, },
{ field: 'startTime', title: '暂态事件发生时刻', width: '200' }, { field: 'startTime', title: '暂态发生时刻', width: '200',sortable: true, },
{ field: 'gdName', title: '供电公司' },
{ field: 'subName', title: '变电站' },
{ field: 'lineName', title: '监测点' },
{ field: 'voltageScale', title: '监测点电压等级' },
{ field: 'loadType', title: '干扰源类型' },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)', title: '暂降(骤升)幅值(%)',sortable: true,width: '160',
formatter: ({ row }: any) => (row.featureAmplitude * 100).toFixed(2) formatter: ({ row }: any) => (row.featureAmplitude * 100).toFixed(2)
}, },
{ field: 'duration', title: '持续时间(s)' }, { field: 'duration', title: '持续时间(s)',sortable: true,width: '120', },
{ field: 'severity', title: '暂态事件严重度' } { field: 'gdName', title: '供电公司' ,minWidth: '120'},
{ field: 'subName', title: '变电站' ,minWidth: '120'},
{ field: 'lineName', title: '监测点' ,minWidth: '120'},
{ field: 'voltageScale', title: '监测点电压等级' ,minWidth: '120'},
{ field: 'loadType', title: '干扰源类型' ,minWidth: '120'},
{ field: 'severity', title: '暂态事件严重度' ,minWidth: '120'}
] ]
} }
] ]
@@ -86,7 +87,16 @@ const list = ref([
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'startTime', title: '暂降事件发生时刻', width: '200' }, { field: 'startTime', title: '暂降发生时刻', width: '200',sortable: true, },
{
field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)',
width: '160',sortable: true,
formatter: (row: any) => {
return Math.floor(row.cellValue * 10000) / 100
}
},
{ field: 'duration', title: '持续时间(s)', width: '120',sortable: true, },
{ field: 'gdName', title: '供电公司', width: '150' }, { field: 'gdName', title: '供电公司', width: '150' },
{ field: 'subName', title: '变电站', minWidth: '150' }, { field: 'subName', title: '变电站', minWidth: '150' },
{ field: 'lineName', title: '监测点', minWidth: '150' }, { field: 'lineName', title: '监测点', minWidth: '150' },
@@ -99,15 +109,7 @@ const list = ref([
{ field: 'voltageScale', title: '电压等级', width: '80' }, { field: 'voltageScale', title: '电压等级', width: '80' },
{ field: 'loadType', title: '干扰源类型', width: '150' }, { field: 'loadType', title: '干扰源类型', width: '150' },
{
field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)',
width: '150',
formatter: (row: any) => {
return Math.floor(row.cellValue * 10000) / 100
}
},
{ field: 'duration', title: '持续时间(s)', width: '120' },
{ field: 'advanceType', title: '暂降类型(机器判断)', width: '150' } { field: 'advanceType', title: '暂降类型(机器判断)', width: '150' }
] ]
}, },