修改测试问题

This commit is contained in:
guanj
2026-06-16 08:34:45 +08:00
parent 1c01fe5ae1
commit d9dfd804c5
63 changed files with 5289 additions and 3842 deletions

View File

@@ -14,17 +14,13 @@
></el-cascader>
</el-form-item> -->
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="请输入监测点名称" />
</el-form-item>
<el-input maxlength="32" show-word-limit style="width: 240px"
v-model.trim="tableStore.table.params.searchValue" clearable placeholder="请输入设备名称" />
</el-form-item>
<el-form-item label="级别">
<el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable>
<el-option
v-for="item in rankOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
<el-option v-for="item in rankOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</template>
@@ -103,12 +99,17 @@ const tableStore = new TableStore({
}
},
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 120 },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120 },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120 },
{
title: '监测点名称', field: 'lineName', minWidth: 130, align: 'center', formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 130 },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 130 },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 130 },
// { title: '监测点名称', field: 'lineName', align: 'center', minWidth: 120 },
{
title: '事件描述',
minWidth: 300,
@@ -123,7 +124,7 @@ const tableStore = new TableStore({
return row.cellValue ? row.cellValue : '/'
}
},
{
title: '告警代码',
field: 'code',
@@ -168,23 +169,23 @@ const tableStore = new TableStore({
// }
// }
],
beforeSearchFun: () => {},
beforeSearchFun: () => { },
exportProcessingData: () => {
tableStore.table.allData = tableStore.table.allData.filter(item => {
item.level =
item.level == 1
? '1级'
: item.level == 2
? '2级'
: item.level == 3
? '3级'
: item.level == 4
? 'DEBUG'
: item.level == 5
? 'NORMAL'
: item.level == 6
? 'WARN'
: 'ERROR'
? '2级'
: item.level == 3
? '3级'
: item.level == 4
? 'DEBUG'
: item.level == 5
? 'NORMAL'
: item.level == 6
? 'WARN'
: 'ERROR'
return item
})
}
@@ -241,6 +242,6 @@ onMounted(() => {
setTimeout(() => {
// tableStore.table.height = mainHeight(200).height as any
}, 0)
const addMenu = () => {}
const addMenu = () => { }
</script>
<style></style>

View File

@@ -18,6 +18,7 @@
</template>
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Operation" @click="openFilterDialog">事件筛选</el-button>
<el-button type="primary" icon="el-icon-Histogram" @click="statistics">暂降原因分析</el-button>
</template>
</TableHeader>
@@ -43,10 +44,12 @@ import { analyseWave, getFileByEventId } from '@/api/common'
import { mainHeight } from '@/utils/layout'
import { ElMessage } from 'element-plus'
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
import { buildWaveExportFileName, getExportSubjectFromRow } from '@/utils/echartMethod'
import { useDictData } from '@/stores/dictData'
import { queryByCode, queryByid, queryCsDictTree } from '@/api/system-boot/dictTree'
import analysisList from '@/views/govern/device/control/analysisList/index.vue'
const props = defineProps(['deviceTree'])
const emit = defineEmits(['statistics'])
const refheader = ref()
const waveFormAnalysisRef = ref()
@@ -91,12 +94,12 @@ const tableStore = new TableStore({
{ title: '触发类型', field: 'showName', minWidth: 100, align: 'center' },
{
title: '暂降原因', field: 'advanceReason', minWidth: 100, align: 'center', formatter: (row: any) => {
return ReasonList.find((item: any) => item.id == row.cellValue)?.name || '未知'
return ReasonList.find((item: any) => item.id == row.cellValue)?.name || '其他'
}
},
{
title: '暂降类型', field: 'advanceType', minWidth: 100, align: 'center', formatter: (row: any) => {
return EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '未知'
return EventTypeList.find((item: any) => item.id == row.cellValue)?.name || '其他'
}
},
{ title: '监测点名称', field: 'lineName', minWidth: 130, align: 'center' },
@@ -158,7 +161,7 @@ const tableStore = new TableStore({
waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
// waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(200, 190)
})
}
},
{
@@ -179,7 +182,7 @@ const tableStore = new TableStore({
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
link.download = row.wavePath.split('/')[2] || '波形文件' // 设置下载的文件名
link.download = buildWaveExportFileName(getExportSubjectFromRow(row))
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
@@ -224,7 +227,7 @@ const tableStore = new TableStore({
deviceId: row.deviceId
})
} else if (code == 'DEV_CLD') {
} else if (code == 'DEV_CLD') {
row.loading2 = true
// 监测设备
getFileByEventId(row.id).then(res => {
@@ -361,6 +364,10 @@ onMounted(() => {
})
tableStore.index()
})
const statistics = () => {
emit('statistics')
}
const bxecharts = mainHeight(175).height as any
setTimeout(() => {
tableStore.table.height = mainHeight(200).height as any

View File

@@ -0,0 +1,39 @@
<template>
<div>
<el-tabs type="border-card" v-model.trim="activeName" tab-position="left">
<el-tab-pane label="暂降分布统计" name="1">
<Distribution v-if="activeName == '1'" />
</el-tab-pane>
<el-tab-pane label="ITIC曲线" name="2">
<ITIC v-if="activeName == '2'" />
</el-tab-pane>
<el-tab-pane label="F47曲线" name="3">
<F47 v-if="activeName == '3'" />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, provide } from 'vue'
import Distribution from './eventStatistics/distribution.vue'
import ITIC from './eventStatistics/ITIC.vue'
import F47 from './eventStatistics/F47.vue'
import { mainHeight } from '@/utils/layout'
const emit = defineEmits(['back'])
const activeName = ref('1')
const layout = mainHeight(80)
provide('eventStatisticsBack', () => emit('back'))
</script>
<style lang="scss" scoped>
:deep(.el-tabs--border-card>.el-tabs__content) {
padding: 10px 10px 10px 0;
}
:deep(.el-tabs--left.el-tabs--border-card .el-tabs__header.is-left) {
height: calc(100vh - 193px);
}
</style>

View File

@@ -0,0 +1,346 @@
<template>
<div v-show="!isWaveCharts" class="event-statistics-curve" :style="pageHeight">
<TableHeader ref="TableHeaderRef" :showReset="false" :timeKeyList="timeKeyList" datePicker
@selectChange="selectChange"> <template v-slot:operation>
<el-button icon="el-icon-Back" @click="handleBack">返回</el-button>
</template>
</TableHeader>
<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 v-loading="tableStore.table.loading" ref="chartRef" class="tall" :options="echartList"
:style="chartStyle" @chart-click="handleChartClick" />
</div>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, computed, nextTick, inject } from 'vue'
import TableStore from '@/utils/tableStore'
import MyEchart from '@/components/echarts/MyEchart.vue'
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
import TableHeader from '@/components/table/header/index.vue'
import { analyseWave } from '@/api/common'
import { getTime } from '@/utils/formatTime'
import { mainHeight } from '@/utils/layout'
import { ElMessage } from 'element-plus'
const pageHeight = mainHeight(105)
const eventStatisticsBack = inject<() => void>('eventStatisticsBack', () => {})
const handleBack = () => eventStatisticsBack()
const timeKeyList = ['1', '2', '3', '4', '5']
const defaultInterval = 3
const TableHeaderRef = ref()
const headerHeight = ref(57)
const echartList = ref()
const chartRef = ref()
const isWaveCharts = ref(false)
const loading = ref(false)
const wp = ref({})
const boxoList: any = ref({})
const waveFormAnalysisRef: any = ref(null)
const chartStyle = computed(() => ({
width: '100%',
height: `calc(${pageHeight.height} - 80px - ${headerHeight.value}px)`
}))
const data = reactive({
name: '事件个数',
gs: 0,
krr: 0,
bkrr: 0
})
const tableStore: any = new TableStore({
url: '/cs-harmonic-boot/csevent/f47Curve',
method: 'POST',
showPage: false,
column: [],
beforeSearchFun: () => {
setTime()
},
loadCallback: () => {
const gongData = gongfunction(tableStore.table.data)
data.gs = tableStore.table.data.length
data.krr = gongData.pointF.length
data.bkrr = gongData.pointFun.length
echartList.value = {
title: {
text: 'F47曲线'
},
legend: {
data: ['分割线', '可容忍事件', '不可容忍事件'],
itemGap: 15
},
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) {
let relVal = `<strong>${a.seriesName}</strong><br/>`
relVal += "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
relVal += "<font style='color:" + "'>特征幅值:" + Math.floor(a.value[1] * 100) / 100 + '%</font><br/>'
relVal += "<font style='color:" + "'>持续时间:" + a.value[0] + 's</font><br/>'
relVal += "<font style='color:" + "'>监测点名称:" + (a.value[4] || '/') + '</font><br/>'
relVal += "<font style='color:" + "'>设备名称:" + (a.value[5] || '/') + '</font><br/>'
relVal += "<font style='color:" + "'>项目名称:" + (a.value[6] || '/') + '</font><br/>'
relVal += "<font style='color:" + "'>工程名称:" + (a.value[7] || '/') + '</font>'
return relVal
}
},
xAxis: [
{
type: 'log',
min: 0.001,
max: 1000,
splitLine: {
show: false
},
name: 's'
}
],
yAxis: [
{
type: 'value',
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',
symbolSize: 8,
data: gongData.pointF,
legendSymbol: 'circle'
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
symbolSize: 8,
data: gongData.pointFun,
legendSymbol: 'rect'
}
]
}
}
}
})
const tableRef = ref()
provide('tableRef', tableRef)
provide('tableStore', tableStore)
const selectChange = (_showSelect: any, height: any, datePickerValue?: any) => {
headerHeight.value = height
if (datePickerValue && datePickerValue.timeValue) {
tableStore.table.params.searchBeginTime = datePickerValue.timeValue[0]
tableStore.table.params.searchEndTime = datePickerValue.timeValue[1]
}
}
const setTime = () => {
const time = getTime(
(TableHeaderRef.value?.datePickerRef.interval || defaultInterval) ?? 0,
timeKeyList,
[tableStore.table.params.searchBeginTime, tableStore.table.params.searchEndTime]
)
if (Array.isArray(time)) {
tableStore.table.params.searchBeginTime = time[0]
tableStore.table.params.searchEndTime = time[1]
TableHeaderRef.value?.setInterval(time[2] - 0)
TableHeaderRef.value?.setTimeInterval([time[0], time[1]])
} else {
console.warn('获取时间失败time 不是一个有效数组')
}
}
function gongfunction(arr: any) {
let standI = 0
let unstandI = 0
let standF = 0
let unstandF = 0
let pointIun: any[] = []
let pointI: any[] = []
let pointF: any[] = []
let pointFun: any[] = []
const total = arr.length
if (total > 0) {
for (let i = 0; i < arr.length; i++) {
const xx = arr[i].persistTime
const yy = arr[i].eventValue
const time = arr[i].time
const eventId = arr[i].eventId
const lineName = arr[i].lineName
const equipmentName = arr[i].equipmentName
const projectName = arr[i].projectName
const engineeringName = arr[i].engineeringName
const point = [xx, yy, time, eventId, lineName, equipmentName, projectName, engineeringName]
if (xx <= 0.003) {
const 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)
})
const handleChartClick = (params: any) => {
if (params.seriesName === '可容忍事件' || params.seriesName === '不可容忍事件') {
handleTolerableEventClick(params)
}
}
const handleTolerableEventClick = async (row: any) => {
loading.value = true
ElMessage.info(`正在加载,请稍等...`)
await analyseWave(row.value[3])
.then(res => {
if (res != undefined) {
loading.value = true
isWaveCharts.value = true
boxoList.value = {
persistTime: row.value[0],
featureAmplitude: row.value[1] / 100,
startTime: row.value[2],
lineName: row.value[4],
engineeringName: row.value[5],
systemType: 'YPT'
}
wp.value = res.data
}
loading.value = false
})
.catch(() => {
loading.value = false
})
nextTick(() => {
waveFormAnalysisRef.value?.getWpData(wp.value, boxoList.value, true)
})
}
</script>
<style scoped>
.event-statistics-curve {
width: 100%;
}
</style>

View File

@@ -0,0 +1,332 @@
<template>
<div v-show="!isWaveCharts" class="event-statistics-curve" :style="pageHeight">
<TableHeader ref="TableHeaderRef" :showReset="false" :timeKeyList="timeKeyList" datePicker
@selectChange="selectChange"> <template v-slot:operation>
<el-button icon="el-icon-Back" @click="handleBack">返回</el-button>
</template>
</TableHeader>
<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 v-loading="tableStore.table.loading" ref="chartRef" class="tall" :options="echartList"
:style="chartStyle" @chart-click="handleChartClick" />
</div>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, computed, nextTick, inject } from 'vue'
import TableStore from '@/utils/tableStore'
import MyEchart from '@/components/echarts/MyEchart.vue'
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
import TableHeader from '@/components/table/header/index.vue'
import { analyseWave } from '@/api/common'
import { getTime } from '@/utils/formatTime'
import { mainHeight } from '@/utils/layout'
import { ElMessage } from 'element-plus'
const pageHeight = mainHeight(105)
const eventStatisticsBack = inject<() => void>('eventStatisticsBack', () => {})
const handleBack = () => eventStatisticsBack()
const timeKeyList = ['1', '2', '3', '4', '5']
const defaultInterval = 3
const TableHeaderRef = ref()
const headerHeight = ref(57)
const echartList = ref()
const chartRef = ref()
const isWaveCharts = ref(false)
const loading = ref(false)
const wp = ref({})
const boxoList: any = ref({})
const waveFormAnalysisRef: any = ref(null)
const chartStyle = computed(() => ({
width: '100%',
height: `calc(${pageHeight.height} - 80px - ${headerHeight.value}px)`
}))
const data = reactive({
name: '事件个数',
gs: 0,
krr: 0,
bkrr: 0
})
const tableStore: any = new TableStore({
url: '/cs-harmonic-boot/csevent/f47Curve',
method: 'POST',
showPage: false,
column: [],
beforeSearchFun: () => {
setTime()
},
loadCallback: () => {
const gongData = gongfunction(tableStore.table.data)
data.gs = tableStore.table.data.length
data.krr = gongData.pointI.length
data.bkrr = gongData.pointIun.length
echartList.value = {
title: {
text: 'ITIC曲线'
},
legend: {
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
itemGap: 15
},
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) {
let relVal = `<strong>${a.seriesName}</strong><br/>`
relVal += "<font style='color:" + "'>发生时间:" + a.value[2] + '</font><br/>'
relVal += "<font style='color:" + "'>特征幅值:" + Math.floor(a.value[1] * 100) / 100 + '%</font><br/>'
relVal += "<font style='color:" + "'>持续时间:" + a.value[0] + 's</font><br/>'
relVal += "<font style='color:" + "'>监测点名称:" + (a.value[4] || '/') + '</font><br/>'
relVal += "<font style='color:" + "'>设备名称:" + (a.value[5] || '/') + '</font><br/>'
relVal += "<font style='color:" + "'>项目名称:" + (a.value[6] || '/') + '</font><br/>'
relVal += "<font style='color:" + "'>工程名称:" + (a.value[7] || '/') + '</font>'
return relVal
}
},
xAxis: [
{
type: 'log',
min: 0.001,
max: 1000,
splitLine: {
show: false
},
name: 's'
}
],
yAxis: [
{
type: 'value',
splitNumber: 10,
minInterval: 3,
name: '%'
}
],
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
options: {
dataZoom: null,
series: [
{
name: '上限',
type: 'line',
data: [
[0.001, 200],
[0.003, 140],
[0.003, 120],
[0.5, 120],
[0.5, 110],
[10, 110],
[1000, 110]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '下限',
type: 'line',
data: [
[0.02, 0],
[0.02, 70],
[0.5, 70],
[0.5, 80],
[10, 80],
[10, 90],
[1000, 90]
],
showSymbol: false,
tooltips: {
show: false
}
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
symbolSize: 8,
data: gongData.pointI,
legendSymbol: 'circle'
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
symbolSize: 8,
data: gongData.pointIun,
legendSymbol: 'rect'
}
]
}
}
}
})
const tableRef = ref()
provide('tableRef', tableRef)
provide('tableStore', tableStore)
const selectChange = (_showSelect: any, height: any, datePickerValue?: any) => {
headerHeight.value = height
if (datePickerValue && datePickerValue.timeValue) {
tableStore.table.params.searchBeginTime = datePickerValue.timeValue[0]
tableStore.table.params.searchEndTime = datePickerValue.timeValue[1]
}
}
const setTime = () => {
const time = getTime(
(TableHeaderRef.value?.datePickerRef.interval || defaultInterval) ?? 0,
timeKeyList,
[tableStore.table.params.searchBeginTime, tableStore.table.params.searchEndTime]
)
if (Array.isArray(time)) {
tableStore.table.params.searchBeginTime = time[0]
tableStore.table.params.searchEndTime = time[1]
TableHeaderRef.value?.setInterval(time[2] - 0)
TableHeaderRef.value?.setTimeInterval([time[0], time[1]])
} else {
console.warn('获取时间失败time 不是一个有效数组')
}
}
function gongfunction(arr: any) {
let standI = 0
let unstandI = 0
let pointIun: any[] = []
let pointI: any[] = []
const total = arr.length
if (total > 0) {
for (let i = 0; i < arr.length; i++) {
const xx = arr[i].persistTime
const yy = arr[i].eventValue
const time = arr[i].time
const eventId = arr[i].eventId
const lineName = arr[i].lineName
const equipmentName = arr[i].equipmentName
const projectName = arr[i].projectName
const engineeringName = arr[i].engineeringName
const point = [xx, yy, time, eventId, lineName, equipmentName, projectName, engineeringName]
if (xx <= 0.003) {
const line = 230 - 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' } } })
}
}
}
}
return { standI, unstandI, pointI, pointIun }
}
onMounted(() => {
setTimeout(() => {
tableStore.index()
}, 100)
})
const handleChartClick = (params: any) => {
if (params.seriesName === '可容忍事件' || params.seriesName === '不可容忍事件') {
handleTolerableEventClick(params)
}
}
const handleTolerableEventClick = async (row: any) => {
loading.value = true
ElMessage.info(`正在加载,请稍等...`)
await analyseWave(row.value[3])
.then(res => {
if (res != undefined) {
loading.value = true
isWaveCharts.value = true
boxoList.value = {
persistTime: row.value[0],
featureAmplitude: row.value[1] / 100,
startTime: row.value[2],
lineName: row.value[4],
engineeringName: row.value[5],
systemType: 'YPT'
}
wp.value = res.data
}
loading.value = false
})
.catch(() => {
loading.value = false
})
nextTick(() => {
waveFormAnalysisRef.value?.getWpData(wp.value, boxoList.value, true)
})
}
</script>
<style scoped>
.event-statistics-curve {
width: 100%;
}
</style>

View File

@@ -0,0 +1,248 @@
<template>
<div class="distribution-page" :style="pageHeight" v-loading="tableStore.table.loading">
<TableHeader ref="TableHeaderRef" :showReset="false" :timeKeyList="timeKeyList" datePicker
@selectChange="selectChange">
<template v-slot:operation>
<el-button icon="el-icon-Back" @click="handleBack">返回</el-button>
</template>
</TableHeader>
<p class="note">暂降类型仅统计暂降原因为短路故障事件</p>
<div class="statistics-main" v-if="renderFlag">
<div class="chart-cell">
<my-echart :options="reasonChart" class="chart-box" />
</div>
<div class="table-cell">
<vxe-table height="auto" auto-resize :data="reasonData" v-bind="defaultAttribute">
<vxe-column field="name" title="暂降原因" />
<vxe-column field="value" title="暂降次数" sortable />
</vxe-table>
</div>
<div class="chart-cell">
<my-echart :options="typeChart" class="chart-box" />
</div>
<div class="table-cell">
<vxe-table height="auto" auto-resize :data="typeData" v-bind="defaultAttribute">
<vxe-column field="name" title="暂降类型" />
<vxe-column field="value" title="暂降次数" sortable />
</vxe-table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, inject } from 'vue'
import TableStore from '@/utils/tableStore'
import MyEchart from '@/components/echarts/MyEchart.vue'
import TableHeader from '@/components/table/header/index.vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getTime } from '@/utils/formatTime'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { color1 } from '@/components/echarts/color'
const dictData = useDictData()
const ReasonList: any = dictData.getBasicData('Event_Reason')
const EventTypeList: any = dictData.getBasicData('Event_Type')
const pageHeight = mainHeight(106)
const eventStatisticsBack = inject<() => void>('eventStatisticsBack', () => {})
const handleBack = () => eventStatisticsBack()
const timeKeyList = ['1', '2', '3', '4', '5']
const defaultInterval = 3
const TableHeaderRef = ref()
const renderFlag = ref(true)
const reasonChart = ref({})
const typeChart = ref({})
const reasonData = ref<any[]>([])
const typeData = ref<any[]>([])
const sortDistributionList = (list: any[]) => {
const totalRow = list.find((item: any) => item.name === '总计')
const total = totalRow?.value ?? list.reduce((sum, item) => sum + (item.value ?? 0), 0)
const sorted = list
.filter((item: any) => item.name !== '总计')
.sort((a, b) => (b.value ?? 0) - (a.value ?? 0))
return [{ name: '总计', value: total }, ...sorted]
}
const transformReasonData = (eventReason: any[] = []) => {
const list = ReasonList.map((item: any) => {
const matched = eventReason.find((row: any) => row.eventReasonId === item.id)
return {
name: item.name,
value: matched?.eventReasonCount ?? 0
}
})
return sortDistributionList(list)
}
const transformTypeData = (eventType: any[] = []) => {
const list = EventTypeList.map((item: any) => {
const matched = eventType.find((row: any) => row.eventTypeId === item.id)
return {
name: item.name,
value: matched?.eventTypeCount ?? 0
}
})
return sortDistributionList(list)
}
const parseDistributionData = (raw: any) => {
if (raw?.eventReason || raw?.eventType) {
return {
reason: transformReasonData(raw.eventReason || []),
type: transformTypeData(raw.eventType || [])
}
}
if (raw?.reason?.length || raw?.type?.length) {
return {
reason: sortDistributionList(raw.reason || []),
type: sortDistributionList(raw.type || [])
}
}
return {
reason: transformReasonData([]),
type: transformTypeData([])
}
}
const buildPieOptions = (title: string, seriesName: string, data: any[], exportFileName: string) => ({
title: { text: title },
exportFileName,
legend: {
type: 'scroll',
orient: 'vertical',
left: 10,
top: '5%',
tooltip: { show: true }
},
color: color1,
xAxis: { show: false },
yAxis: { show: false },
dataZoom: { show: false },
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} (次)',
confine: true
},
options: {
series: [
{
name: seriesName,
type: 'pie',
center: ['50%', '50%'],
selectedOffset: 30,
clockwise: true,
label: { show: false, position: 'outside' },
data: data.filter((item: any) => item.name !== '总计')
}
]
}
})
const updateCharts = (res: any) => {
renderFlag.value = false
reasonData.value = res?.reason || []
typeData.value = res?.type || []
reasonChart.value = buildPieOptions('暂降原因', '暂降原因', reasonData.value, '暂降原因')
typeChart.value = buildPieOptions('暂降类型', '暂降类型', typeData.value, '暂降类型')
renderFlag.value = true
}
const tableStore: any = new TableStore({
url: '/cs-harmonic-boot/event/eventReasonAndTypeStatistics',
method: 'POST',
showPage: false,
column: [],
beforeSearchFun: () => {
setTime()
},
loadCallback: () => {
updateCharts(parseDistributionData(tableStore.table.data))
}
})
const tableRef = ref()
provide('tableRef', tableRef)
provide('tableStore', tableStore)
const selectChange = (_showSelect: any, _height: any, datePickerValue?: any) => {
if (datePickerValue?.timeValue) {
tableStore.table.params.searchBeginTime = datePickerValue.timeValue[0]
tableStore.table.params.searchEndTime = datePickerValue.timeValue[1]
}
}
const setTime = () => {
const time = getTime(
(TableHeaderRef.value?.datePickerRef.interval || defaultInterval) ?? 0,
timeKeyList,
[tableStore.table.params.searchBeginTime, tableStore.table.params.searchEndTime]
)
if (Array.isArray(time)) {
tableStore.table.params.searchBeginTime = time[0]
tableStore.table.params.searchEndTime = time[1]
TableHeaderRef.value?.setInterval(time[2] - 0)
TableHeaderRef.value?.setTimeInterval([time[0], time[1]])
} else {
console.warn('获取时间失败time 不是一个有效数组')
}
}
onMounted(() => {
updateCharts(parseDistributionData(null))
setTimeout(() => {
tableStore.index()
}, 100)
})
</script>
<style scoped>
.distribution-page {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
box-sizing: border-box;
}
.note {
margin: 8px 0 0;
flex-shrink: 0;
color: #f56c6c;
font-size: 12px;
}
.statistics-main {
flex: 1;
min-height: 0;
display: grid;
grid-template-columns: 1fr 420px;
grid-template-rows: 1fr 1fr;
gap: 20px;
margin-top: 8px;
}
.chart-cell,
.table-cell {
min-height: 0;
overflow: hidden;
}
.chart-cell {
display: flex;
}
.chart-box {
flex: 1;
min-height: 0;
width: 100%;
}
.chart-box :deep(.chart),
.chart-box :deep(.my-chart) {
height: 100%;
}
</style>

View File

@@ -2,8 +2,17 @@
<div class="default-main">
<el-tabs v-model.trim="activeName" type="border-card" class="demo-tabs">
<el-tab-pane label="暂态事件" name="4">
<Transient v-if="activeName == '4'" :deviceTree="deviceTree" :key="key" />
<Transient
v-if="!showEventStatistics"
:deviceTree="deviceTree"
:key="key"
@statistics="showEventStatistics = true"
/>
<eventStatistics v-else @back="showEventStatistics = false" />
</el-tab-pane>
<!-- <el-tab-pane label="事件统计" name="5">
</el-tab-pane> -->
<el-tab-pane label="稳态越限告警" name="3">
<Steady v-if="activeName == '3'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
@@ -15,16 +24,17 @@
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import { ref, onMounted, watch } from 'vue'
import Steady from './Steady.vue'
import Transient from './Transient.vue'
import Device from './Device.vue'
import Front from './Front.vue'
import eventStatistics from './eventStatistics.vue'
import { getDeviceTree } from '@/api/cs-device-boot/csLedger'
defineOptions({
name: 'govern/alarm/index'
@@ -32,25 +42,32 @@ defineOptions({
const deviceTree = ref([])
const activeName = ref('4')
const showEventStatistics = ref(false)
const key = ref(0)
getDeviceTree().then(res => {
// res.data.forEach((item: any) => {
// item.value = item.id
// item.label = item.name
// item.children.forEach((child: any) => {
// child.value = child.id
// child.label = child.name
// child.children.forEach((grand: any) => {
// grand.value = grand.id
// grand.label = grand.name
// delete grand.children
// })
// })
// })
deviceTree.value = res.data
key.value += 1
activeName.value = '4'
watch(activeName, val => {
if (val !== '4') {
showEventStatistics.value = false
}
})
// getDeviceTree().then(res => {
// res.data.forEach((item: any) => {
// item.value = item.id
// item.label = item.name
// item.children.forEach((child: any) => {
// child.value = child.id
// child.label = child.name
// child.children.forEach((grand: any) => {
// grand.value = grand.id
// grand.label = grand.name
// delete grand.children
// })
// })
// })
// deviceTree.value = res.data
// key.value += 1
// activeName.value = '4'
// })
onMounted(() => { })
const addMenu = () => { }