修改测试bug

This commit is contained in:
guanj
2026-06-08 18:34:49 +08:00
parent 4f907a80c4
commit 03d302ded8
133 changed files with 3991 additions and 3442 deletions

View File

@@ -24,11 +24,11 @@
</el-form-item>
</template> -->
<template #select>
<el-form-item label="设备名称">
<el-input
maxlength="32"
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit
clearable
show-word-limit
v-model.trim="tableStore.table.params.searchValue"
placeholder="请输入设备名称"
/>

View File

@@ -1,7 +1,7 @@
<template>
<TableHeader datePicker ref="refheader" showExport>
<template v-slot:select>
<el-form-item label="数据来源">
<!-- <el-form-item label="数据来源">
<el-cascader
v-model.trim="tableStore.table.params.cascader"
filterable
@@ -12,8 +12,11 @@
:props="{ checkStrictly: true, value: 'id', label: 'name' }"
clearable
></el-cascader>
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
</el-form-item>
</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-form-item label="级别">
<el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable>
<el-option
@@ -100,10 +103,10 @@ const tableStore = new TableStore({
}
},
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120 },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120 },
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 120 },
{ title: '监测点名称', field: 'lineName', align: 'center', minWidth: 120 },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120 },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120 },
// { title: '监测点名称', field: 'lineName', align: 'center', minWidth: 120 },
{
title: '模块信息',
@@ -189,6 +192,7 @@ provide('tableStore', tableStore)
// "target": [],
// "type": "",
// "userId": ""
tableStore.table.params.searchValue = ''
tableStore.table.params.cascader = ''
tableStore.table.params.level = ''
tableStore.table.params.engineeringid = ''

View File

@@ -2,9 +2,9 @@
<TableHeader datePicker ref="refheader" showExport>
<template v-slot:select>
<el-form-item label="关键字筛选">
<el-input
maxlength="32"
show-word-limit
<el-input maxlength="32" show-word-limit
v-model.trim="tableStore.table.params.searchValue"
placeholder="请输入前置服务器名称ip"
/>

View File

@@ -1,12 +1,15 @@
<template>
<TableHeader datePicker ref="refheader" showExport>
<template v-slot:select>
<el-form-item label="数据来源">
<!-- <el-form-item label="数据来源">
<el-cascader v-model.trim="tableStore.table.params.cascader" filterable placeholder="请选择数据来源"
@change="sourceChange" :options="deviceTreeOptions" :show-all-levels="false"
:props="{ checkStrictly: true, value: 'id', label: 'name' }" clearable></el-cascader>
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
</el-form-item>
</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-form-item label="级别">
<el-select v-model.trim="tableStore.table.params.level" placeholder="请选择级别" clearable>
<el-option
@@ -77,9 +80,12 @@ const tableStore = new TableStore({
}
},
{ title: '发生时刻', field: 'startTime', align: 'center', sortable: true, minWidth: 180, },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120, },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120, },
{ title: '监测点名称', field: 'lineName', align: 'center', minWidth: 120,formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
} },
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 120, },
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120, },
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120, },
{ title: '事件描述', field: 'showName', align: 'center', minWidth: 250, }
@@ -91,6 +97,7 @@ provide('tableStore', tableStore)
// "target": [],
// "type": "",
// "userId": ""
tableStore.table.params.searchValue = ''
tableStore.table.params.engineeringid = ''
tableStore.table.params.deviceTypeId = ''
tableStore.table.params.projectId = ''

View File

@@ -1,74 +1,46 @@
<template>
<div ref="refheader" v-show="!isWaveCharts" style="width: 100%">
<TableHeader datePicker showExport>
<TableHeader datePicker showExport @onResetForm="onResetForm">
<template v-slot:select>
<el-form-item label="数据来源">
<!-- <el-form-item label="数据来源">
<el-cascader placeholder="请选择数据来源" @change="sourceChange" filterable
v-model.trim="tableStore.table.params.cascader" :options="deviceTreeOptions"
:show-all-levels="false" :props="{ checkStrictly: true, value: 'id', label: 'name' }"
clearable></el-cascader>
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" 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-select>
</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-form-item>
<el-button type="primary" plain @click="openFilterDialog">多条件筛选</el-button>
</el-form-item>
</template>
</TableHeader>
<MultiCondition v-model:visible="filterVisible" :params="tableStore.table.params"
ref="multiConditionRef" @confirm="onFilterConfirm" />
<Table></Table>
</div>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
<!-- <div style="height: 300px;"> -->
<!-- <div style="padding: 10px" v-if="!view" v-loading="loading">
<el-row>
<el-col :span="12">
<div v-if="view2" style="display: flex">
<el-radio-group v-model.trim="value" @change="changeView">
<el-radio-button label="一次值" :value="1" />
<el-radio-button label="二次值" :value="2" />
</el-radio-group>
</div>
</el-col>
<el-col :span="12">
<el-button v-if="view2" @click="backbxlb" class="el-icon-refresh-right" icon="el-icon-Back"
style="float: right">
返回
</el-button>
</el-col>
</el-row>
<el-tabs v-if="view2" v-model.trim="bxactiveName" @tab-click="bxhandleClick">
<el-tab-pane label="瞬时波形" name="ssbx" class="boxbx pt10 pb10"
:style="'height:' + bxecharts + ';overflow-y: scroll;'">
<shushiboxi v-if="bxactiveName == 'ssbx' && showBoxi" :value="value" :boxoList="boxoList" :wp="wp">
</shushiboxi>
</el-tab-pane>
<el-tab-pane label="RMS波形" class="boxbx pt10 pb10" name="rmsbx"
:style="'height:' + bxecharts + ';overflow-y: scroll;'">
<rmsboxi v-if="bxactiveName == 'rmsbx' && showBoxi" :value="value" :boxoList="boxoList" :wp="wp">
</rmsboxi>
</el-tab-pane>
</el-tabs>
</div> -->
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import shushiboxi from '@/components/echarts/shushiboxi.vue'
import MultiCondition from './multiCondition.vue'
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue'
import rmsboxi from '@/components/echarts/rmsboxi.vue'
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 { useDictData } from '@/stores/dictData'
const props = defineProps(['deviceTree'])
const refheader = ref()
const waveFormAnalysisRef = ref()
const view = ref(true)
@@ -78,32 +50,18 @@ const showBoxi = ref(true)
const loading = ref(false)
const bxactiveName = ref('ssbx')
const boxoList: any = ref({})
const wp = ref({})
const value = ref(1)
const options = ref([
{
value: 1,
label: '一次值'
},
{
value: 2,
label: '二次值'
}
])
const rankOptions = ref([
{
value: '1',
label: '1级'
},
{
value: '2',
label: '2级'
},
{
value: '3',
label: '3级'
}
])
const dictData = useDictData()
const ReasonList: any = dictData.getBasicData('Event_Reason')
const EventTypeList = [
{ label: '电压暂降', value: '电压暂降' },
{ label: '电压暂升', value: '电压暂升' },
{ label: '电压中断', value: '电压中断' }
]
const filterVisible = ref(false)
const multiConditionRef = ref<InstanceType<typeof MultiCondition>>()
const tableStore = new TableStore({
url: '/cs-harmonic-boot/eventUser/queryEventpageWeb',
@@ -118,20 +76,38 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '暂降发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{ title: '暂降(骤升)幅值(%)', minWidth: 160, field: 'evtParamVVaDepth', align: 'center', sortable: true },
{ title: '暂降幅值(%)', minWidth: 120, field: 'evtParamVVaDepth', align: 'center', sortable: true, },
{ title: '持续时间(s)', field: 'evtParamTm', minWidth: 110, align: 'center', sortable: true },
{ title: '相别', field: 'evtParamPhase', minWidth: 80, align: 'center' },
{ title: '触发类型', field: 'showName', minWidth: 120, align: 'center' },
{ title: '工程名称', field: 'engineeringName', minWidth: 120, align: 'center' },
{ title: '项目名称', field: 'projectName', minWidth: 120, align: 'center' },
{ title: '设备名称', field: 'equipmentName', minWidth: 120, align: 'center' },
{ title: '监测点名称', field: 'lineName', minWidth: 120, align: 'center' },
{ title: '发生位置', field: 'evtParamPosition', minWidth: 150, align: 'center' },
{
title: '暂降原因', field: 'advanceReason', minWidth: 100, align: 'center', formatter: (row: any) => {
return ReasonList.find((item: any) => item.value == row.cellValue)?.label || '未知'
}
},
{
title: '暂降类型', field: 'advanceType', minWidth: 100, align: 'center', formatter: (row: any) => {
return EventTypeList.find((item: any) => item.value == row.cellValue)?.label || '未知'
}
},
{ title: '监测点名称', field: 'lineName', minWidth: 130, align: 'center' },
{ title: '电压等级(kV)', field: 'lineVoltage', minWidth: 120, align: 'center', sortable: true, },
{ title: '设备名称', field: 'equipmentName', minWidth: 130, align: 'center' },
{ title: '项目名称', field: 'projectName', minWidth: 130, align: 'center' },
{ title: '工程名称', field: 'engineeringName', minWidth: 130, align: 'center' },
{
title: '发生位置', field: 'sagSource', minWidth: 120, align: 'center', formatter: (row: any) => {
return row.cellValue == 1 ? '上游' : row.cellValue == 2 ? '下游' : '未知'
}
},
{
title: '操作',
@@ -160,6 +136,7 @@ const tableStore = new TableStore({
loading.value = true
isWaveCharts.value = true
boxoList.value = row
boxoList.value.engineeringName = row.projectName
boxoList.value.persistTime = row.evtParamTm
boxoList.value.featureAmplitude =
row.evtParamVVaDepth != '-' ? (row.evtParamVVaDepth - 0) / 100 : null
@@ -212,6 +189,7 @@ const tableStore = new TableStore({
return !row.wavePath
},
click: row => {
row.loading2 = true
ElMessage.info('下载中......')
getFileZip({ eventId: row.id }).then(res => {
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
@@ -223,6 +201,9 @@ const tableStore = new TableStore({
link.click() //执行下载
document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
row.loading2 = false
}).catch(() => {
row.loading2 = false
})
}
},
@@ -233,25 +214,25 @@ const tableStore = new TableStore({
icon: 'el-icon-DataLine',
render: 'basicButton',
disabled: row => {
return row.wavePath
return row.wavePath
}
},
{
name: 'edit',
title: '波形补召',
type: 'primary',
icon: 'el-icon-Check',
render: 'basicButton',
disabled: row => {
return row.wavePath || row.showName === '未知'
},
click: row => {
getFileByEventId(row.id).then(res => {
ElMessage.success(res.message)
tableStore.index()
})
}
}
// {
// name: 'edit',
// title: '波形补召',
// type: 'primary',
// icon: 'el-icon-Check',
// render: 'basicButton',
// disabled: row => {
// return row.wavePath || row.showName === '未知'
// },
// click: row => {
// getFileByEventId(row.id).then(res => {
// ElMessage.success(res.message)
// tableStore.index()
// })
// }
// }
]
}
],
@@ -275,6 +256,7 @@ provide('tableStore', tableStore)
// "target": [],
// "type": "",
// "userId": ""
tableStore.table.params.searchValue = ''
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceTypeId = ''
@@ -286,8 +268,18 @@ tableStore.table.params.target = []
tableStore.table.params.userId = ''
tableStore.table.params.cascader = ''
tableStore.table.params.deviceTypeName = ''
Object.assign(tableStore.table.params, {
featureAmplitude: '',
evtParamTm: '',
showName: '',
fileFlag: ''
})
// tableStore.table.params.level=''
const openFilterDialog = () => {
filterVisible.value = true
}
const deviceTreeOptions: any = ref<any>(props.deviceTree)
deviceTreeOptions.value.map((item: any, index: any) => {
if (item?.children.length == 0) {
@@ -335,38 +327,23 @@ const sourceChange = (e: any) => {
// tableStore.table.params.deviceId = e[2] || ''
// }
}
const getboxin = async (row: any) => {
console.log('🚀 ~ getboxin ~ row:', row)
// boxoList.value = row
// await analyseWave(row.id).then(res => {
// if (res != undefined) {
// wp.value = res.data
// view.value = false
// view2.value = true
// }
// })
const onFilterConfirm = () => {
tableStore.onTableAction('search', {})
}
const changeView = () => {
showBoxi.value = false
setTimeout(() => {
showBoxi.value = true
}, 0)
}
const bxhandleClick = (tab: any) => {
if (tab.name == 'ssbx') {
bxactiveName.value = 'ssbx'
} else if (tab.name == 'rmsbx') {
bxactiveName.value = 'rmsbx'
}
// console.log(tab, event);
}
const backbxlb = () => {
view.value = true
view2.value = false
setTimeout(() => {
tableStore.table.height = mainHeight(180).height as any
}, 0)
// 重置
const onResetForm = () => {
filterVisible.value = false
tableStore.table.params.cascader = ''
tableStore.table.params.deviceTypeId = ''
tableStore.table.params.engineeringid = ''
tableStore.table.params.projectId = ''
tableStore.table.params.deviceId = ''
tableStore.table.params.deviceTypeName = ''
multiConditionRef.value?.reset()
}
onMounted(() => {
tableStore.index()
})

View File

@@ -3,7 +3,7 @@
@closed="handleClosed">
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto" class="form-one">
<el-form-item label="方案名称" prop="name">
<el-input v-model.trim="form.name" maxlength="64" show-word-limit placeholder="请输入方案名称" clearable />
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入方案名称" clearable />
</el-form-item>
<el-form-item label="在线率阈值" prop="onlineRateLimit">
<el-input-number v-model="form.onlineRateLimit" :min="0" :max="100" :precision="0" style="width: 100%"

View File

@@ -1,18 +1,20 @@
<template>
<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" />
</el-tab-pane>
<el-tab-pane label="稳态越限告警" name="3">
<Steady v-if="activeName == '3'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="设备告警" name="1">
<Device v-if="activeName == '1'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="前置告警" name="2">
<Front v-if="activeName == '2'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="稳态越限告警" name="3">
<Steady v-if="activeName == '3'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="暂态事件" name="4">
<Transient v-if="activeName == '4'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
<el-tab-pane label="异常事件" name="5">
<Abnormal v-if="activeName == '5'" :deviceTree="deviceTree" :key="key" />
</el-tab-pane>
@@ -32,7 +34,7 @@ defineOptions({
})
const deviceTree = ref([])
const activeName = ref('1')
const activeName = ref('4')
const key = ref(0)
getDeviceTree().then(res => {
// res.data.forEach((item: any) => {
@@ -50,7 +52,7 @@ getDeviceTree().then(res => {
// })
deviceTree.value = res.data
key.value += 1
activeName.value = '1'
activeName.value = '4'
})
onMounted(() => { })

View File

@@ -0,0 +1,217 @@
<template>
<el-dialog v-model="visible" title="多条件筛选" width="450px" append-to-body draggable
class="transient-filter-dialog">
<el-form label-width="auto" class="filter-form">
<el-form-item label="暂态幅值(%)">
<div class="range-inputs">
<el-input-number v-model="filterForm.featureAmplitudeMin" class="range-input-item" :min="0"
:max="200" :precision="3" :step="0.01" :controls="false" placeholder="0"
@change="onRangeMinChange($event, 'featureAmplitudeMax')" />
<span class="range-sep">&lt;  幅值  &lt;</span>
<el-input-number v-model="filterForm.featureAmplitudeMax" class="range-input-item" :min="0"
:max="200" :precision="3" :step="0.01" :controls="false" placeholder="200"
@change="onRangeMaxChange($event, filterForm.featureAmplitudeMin, 'featureAmplitudeMax', '暂态幅值')" />
</div>
</el-form-item>
<el-form-item label="暂态持续时间">
<div class="range-inputs">
<el-input-number v-model="filterForm.evtParamTmMin" class="range-input-item" :min="0"
:precision="3" :step="0.01" :controls="false" placeholder="X毫秒"
@change="onRangeMinChange($event, 'evtParamTmMax')" />
<span class="range-sep">&lt; 持续时间 &lt;</span>
<el-input-number v-model="filterForm.evtParamTmMax" class="range-input-item" :min="0"
:precision="3" :step="0.01" :controls="false" placeholder="X毫秒"
@change="onRangeMaxChange($event, filterForm.evtParamTmMin, 'evtParamTmMax', '暂态持续时间')" />
</div>
</el-form-item>
<el-form-item label="触发类型">
<el-select v-model="params.showName" clearable placeholder="请选择触发类型" style="width: 100%">
<el-option v-for="item in eventTypeList" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="是否存在波形">
<el-select v-model="params.fileFlag" clearable placeholder="请选择是否存在波形" style="width: 100%">
<el-option v-for="item in fileFlagOptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div>
<el-button type="primary" @click="onConfirm">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
const getDefaultFilterParams = () => ({
featureAmplitude: '',
evtParamTm: '',
showName: '',
fileFlag: '' as string | number
})
const visible = defineModel<boolean>('visible', { default: false })
const props = defineProps<{
params: Record<string, any>
}>()
const emit = defineEmits<{
confirm: []
}>()
const eventTypeList = [
{ label: '电压暂降', value: '电压暂降' },
{ label: '电压暂升', value: '电压暂升' },
{ label: '电压中断', value: '电压中断' }
]
const fileFlagOptions = [
{ label: '存在', value: 1 },
{ label: '不存在', value: 0 }
]
type RangeMaxField = 'featureAmplitudeMax' | 'evtParamTmMax'
const filterForm = ref<{
featureAmplitudeMin?: number
featureAmplitudeMax?: number
evtParamTmMin?: number
evtParamTmMax?: number
}>({})
const parseRangeParam = (val: string): [number | undefined, number | undefined] => {
if (!val) return [undefined, undefined]
const [min = '', max = ''] = String(val).split(',')
const minNum = min !== '' ? Number(min) : undefined
const maxNum = max !== '' ? Number(max) : undefined
return [
minNum != null && !Number.isNaN(minNum) ? minNum : undefined,
maxNum != null && !Number.isNaN(maxNum) ? maxNum : undefined
]
}
const joinRangeParam = (min?: number, max?: number) => {
if (min == null && max == null) return ''
return `${min ?? ''},${max ?? ''}`
}
const onRangeMinChange = (min: number | undefined, maxField: RangeMaxField) => {
const max = filterForm.value[maxField]
if (min != null && max != null && max <= min) {
filterForm.value[maxField] = undefined
}
}
const onRangeMaxChange = (
max: number | undefined,
min: number | undefined,
maxField: RangeMaxField,
label: string
) => {
if (min != null && max != null && max <= min) {
ElMessage.warning(`${label}最大值必须大于最小值`)
filterForm.value[maxField] = undefined
}
}
const validateRange = (
min: number | undefined,
max: number | undefined,
label: string,
options?: { maxLimit?: number }
) => {
const hasMin = min != null && !Number.isNaN(min)
const hasMax = max != null && !Number.isNaN(max)
if (!hasMin && !hasMax) return true
if (hasMin !== hasMax) {
ElMessage.warning(`${label}请同时填写最小值和最大值`)
return false
}
if (min! <= 0 || max! <= 0) {
ElMessage.warning(`${label}必须大于0`)
return false
}
if (max! <= min!) {
ElMessage.warning(`${label}最大值必须大于最小值`)
return false
}
if (options?.maxLimit !== undefined && max! > options.maxLimit) {
ElMessage.warning(`${label}最大值不能大于${options.maxLimit}`)
return false
}
return true
}
const syncFromParams = () => {
const [faMin, faMax] = parseRangeParam(props.params.featureAmplitude)
const [tmMin, tmMax] = parseRangeParam(props.params.evtParamTm)
filterForm.value.featureAmplitudeMin = faMin
filterForm.value.featureAmplitudeMax = faMax
filterForm.value.evtParamTmMin = tmMin
filterForm.value.evtParamTmMax = tmMax
}
const reset = () => {
filterForm.value = {}
Object.assign(props.params, getDefaultFilterParams())
}
const onConfirm = () => {
const { featureAmplitudeMin, featureAmplitudeMax, evtParamTmMin, evtParamTmMax } = filterForm.value
if (!validateRange(featureAmplitudeMin, featureAmplitudeMax, '暂态幅值', { maxLimit: 200 })) {
return
}
if (!validateRange(evtParamTmMin, evtParamTmMax, '暂态持续时间')) {
return
}
props.params.featureAmplitude = joinRangeParam(featureAmplitudeMin, featureAmplitudeMax)
props.params.evtParamTm = joinRangeParam(evtParamTmMin, evtParamTmMax)
visible.value = false
emit('confirm')
}
watch(visible, val => {
if (val) syncFromParams()
})
defineExpose({ reset, syncFromParams })
</script>
<style scoped lang="scss">
.range-inputs {
display: flex;
align-items: center;
width: 100%;
gap: 8px;
.range-input-item {
width: 120px;
:deep(.el-input__wrapper) {
width: 100%;
}
}
.range-sep {
flex-shrink: 0;
color: var(--el-text-color-regular);
font-size: 14px;
white-space: nowrap;
}
}
</style>

View File

@@ -4,19 +4,19 @@
<el-scrollbar max-height="60vh">
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto" class="form-two">
<el-form-item label="指标名称" prop="indexName">
<el-input v-model.trim="form.indexName" placeholder="请输入指标名称" clearable maxlength="128" />
<el-input maxlength="32" show-word-limit v-model.trim="form.indexName" placeholder="请输入指标名称" clearable/>
</el-form-item>
<el-form-item label="指标code" prop="indexCode">
<el-input v-model.trim="form.indexCode" placeholder="请输入指标code" clearable maxlength="64" />
<el-form-item label="指标Code" prop="indexCode">
<el-input maxlength="32" show-word-limit v-model.trim="form.indexCode" placeholder="请输入指标Code" clearable />
</el-form-item>
<el-form-item label="表名" prop="influxdbTableName">
<el-input v-model.trim="form.influxdbTableName" placeholder="请输入表名" clearable />
<el-input maxlength="32" show-word-limit v-model.trim="form.influxdbTableName" placeholder="请输入表名" clearable />
</el-form-item>
<el-form-item label="列属性" prop="influxdbColumnName">
<el-input v-model.trim="form.influxdbColumnName" placeholder="实体类属性名" clearable maxlength="128" />
<el-input maxlength="32" show-word-limit v-model.trim="form.influxdbColumnName" placeholder="实体类属性名" clearable />
</el-form-item>
<el-form-item label="谐波次数">
<el-slider v-model.trim="form.harmSlider" range :max="50" style="width: 90%" />
@@ -40,7 +40,7 @@
<el-radio :value="1">参与</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Ct变比参与" prop="ctAttendFlag">
<el-form-item label="CT变比参与" prop="ctAttendFlag">
<el-radio-group v-model="form.ctAttendFlag">
<el-radio :value="0">不参与</el-radio>
<el-radio :value="1">参与</el-radio>
@@ -60,10 +60,10 @@
</el-select>
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model.trim="form.unit" placeholder="请输入单位" clearable maxlength="32" />
<el-input maxlength="32" show-word-limit v-model.trim="form.unit" placeholder="请输入单位" clearable />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="form.sort" :min="0" :precision="0" style="width: 100%" />
<el-input-number v-model="form.sort" :min="0" style="width: 100%;" :precision="0" />
</el-form-item>
<!-- <el-form-item label="状态" prop="state">
<el-select v-model="form.state" placeholder="请选择" style="width: 100%">
@@ -72,12 +72,12 @@
</el-select>
</el-form-item> -->
<el-form-item label="条件描述" prop="otherAlgorithm" class="form-item-full">
<el-input v-model.trim="form.otherAlgorithm" type="textarea" :rows="2" placeholder="无具体范围时的判断条件描述"
maxlength="500" show-word-limit />
<el-input show-word-limit v-model.trim="form.otherAlgorithm" type="textarea" :rows="2" placeholder="无具体范围时的判断条件描述"
maxlength="300" />
</el-form-item>
<el-form-item label="备注" prop="remark" class="form-item-full">
<el-input v-model.trim="form.remark" type="textarea" :rows="2" placeholder="备注" maxlength="500"
show-word-limit />
<el-input show-word-limit v-model.trim="form.remark" type="textarea" :rows="2" placeholder="备注" maxlength="300"
/>
</el-form-item>
</el-form>
</el-scrollbar>
@@ -172,7 +172,7 @@ const validateMinMax = (_rule: any, _value: any, callback: (e?: Error) => void)
}
const rules: any = {
indexCode: [{ required: true, message: '请输入指标code', trigger: 'blur' }],
indexCode: [{ required: true, message: '请输入指标Code', trigger: 'blur' }],
indexName: [{ required: true, message: '请输入指标名称', trigger: 'blur' }],
phaseList: [{ required: true, message: '请输入指标名称', trigger: 'change' }],

View File

@@ -15,8 +15,8 @@
</el-select>
</el-form-item>
<el-form-item label="表名">
<el-input v-model.trim="tableStore.table.params.tableName" placeholder="请输入表名" clearable
maxlength="64" />
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.tableName" placeholder="请输入表名" clearable
/>
</el-form-item>
</template>
<template #operation>
@@ -64,7 +64,7 @@ const tableStore: any = new TableStore({
}
},
{ field: 'indexName', title: '指标名称', minWidth: 200 },
{ field: 'indexCode', title: '指标code', minWidth: 150 },
{ field: 'indexCode', title: '指标Code', minWidth: 150 },
{ field: 'influxdbTableName', title: '表名', minWidth: 150 },
{ field: 'influxdbColumnName', title: '列属性', minWidth: 150 },
@@ -91,7 +91,7 @@ const tableStore: any = new TableStore({
},
{
field: 'ctAttendFlag',
title: 'Ct变比参与',
title: 'CT变比参与',
width: 100,
formatter: (row: any) => yesNo(row.cellValue)
},

View File

@@ -1,440 +1,489 @@
<template>
<div class="default-main" style="display: flex" :style="height">
<div style="width: 400px; overflow: hidden">
<div class="custom-table-header">
<div class="title">方案列表</div>
<el-button :icon="Plus" type="primary" @click="addRole" class="ml10">新增</el-button>
</div>
<Table ref="tableRef" :row-config="{ isCurrent: true, isHover: true }" @currentChange="currentChange" />
</div>
<div style="flex: 1; overflow: hidden">
<div class="custom-table-header">
<div class="title">指标配置</div>
<!-- <el-button :icon="Select" type="primary" @click="saveIndicator" class="ml10">保存</el-button> -->
</div>
<div class="pd10 borderBox" :style="height1" style="overflow-y: auto">
<H4 class="mt10">基础指标</H4>
<el-checkbox-group v-model="indicator">
<el-checkbox label="频率偏差" value="频率偏差" />
<el-checkbox label="电压偏差" value="电压偏差" />
<el-checkbox label="三相电压不平衡度" value="三相电压不平衡度" />
<el-checkbox label="闪变" value="闪变" />
<el-checkbox label="电压总谐波畸变率" value="电压总谐波畸变率" />
<el-checkbox label="负序电流" value="负序电流" />
</el-checkbox-group>
<H4 class="mt10">谐波电压</H4>
<div class="df">
<div class="title">谐波电压含有率:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll1" @change="handleCheckAllChange1">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleHarmonicVoltageChange">
<el-checkbox
v-for="num in 24"
:key="`harmonicVoltage_${num + 1}`"
:label="`${num + 1}次`"
:value="`${num + 1}次谐波电压含有率`"
/>
</el-checkbox-group>
</div>
</div>
<H4 class="mt10">谐波电流</H4>
<div class="df">
<div class="title">谐波电流有效值:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll2" @change="handleCheckAllChange2">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleHarmonicCurrentChange">
<el-checkbox
v-for="num in 24"
:key="`harmonicCurrent_${num + 1}`"
:label="`${num + 1}次`"
:value="`${num + 1}次谐波电流有效值`"
/>
</el-checkbox-group>
</div>
</div>
<H4 class="mt10">谐波电压</H4>
<div class="df">
<div class="title">间谐波电压含有率:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll3" @change="handleCheckAllChange3">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleInterharmonicVoltageChange">
<el-checkbox
v-for="num in 16"
:key="`interharmonicVoltage_${num}`"
:label="`${num - 0.5}次`"
:value="`${num - 0.5}次间谐波电压含有率`"
/>
</el-checkbox-group>
</div>
</div>
</div>
</div>
<div style="width: 370px">
<div class="custom-table-header">
<div class="title">监测点绑定</div>
<el-button :icon="Select" type="primary" @click="saveIndicator" class="ml10" :loading="loading">
保存
</el-button>
</div>
<!-- <steadyStateTree /> -->
<Tree
class="borderBox"
ref="treeRef"
show-checkbox
:showBut="false"
width="370px"
:height="260"
:data="menuTree"
:checkStrictly="checkStrictly"
></Tree>
</div>
<!-- 新增/编辑弹框 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="400px" :before-close="handleClose">
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px">
<el-form-item label="方案名称" prop="name">
<el-input v-model.trim="formData.name" placeholder="请输入方案名称" clearable />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input maxlength="32" show-word-limit-number v-model.number="formData.sort" :min="0" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { Plus, Select } from '@element-plus/icons-vue'
import { ref, onMounted, provide, computed } from 'vue'
import TableStore from '@/utils/tableStore'
import { getLineTree, getCldTree } from '@/api/cs-device-boot/csLedger'
import Table from '@/components/table/index.vue'
import { save, deletePlan, update, getById } from '@/api/cs-harmonic-boot/mxgraph'
import { mainHeight } from '@/utils/layout'
import { ElMessage } from 'element-plus'
import steadyStateTree from '@/components/tree/govern/steadyStateTree.vue'
import { useConfig } from '@/stores/config'
import Tree from '@/components/tree/allocation.vue'
import { id } from 'element-plus/es/locale'
defineOptions({
name: 'govern/steadyStateEvent'
})
const height = mainHeight(20)
const height1 = mainHeight(90)
const config = useConfig()
const tableRef = ref()
const checkAll1 = ref(false)
const checkAll2 = ref(false)
const checkAll3 = ref(false)
const menuTree: any = ref([])
const checkStrictly = ref(false)
const indicator: any = ref([])
const lineList: any = ref([])
const copyRow: any = ref({})
const treeRef = ref()
const loading = ref(false)
// 弹框相关
const dialogVisible = ref(false)
const dialogTitle = ref('新增方案')
const formRef = ref()
const formData = ref({
id: '',
sort: 0,
lineList: [],
harmonicTarget: '',
name: ''
})
const formRules = {
name: [{ required: true, message: '请输入方案名称', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
// 生成各分组的指标值数组
const harmonicVoltageValues = computed(() => Array.from({ length: 24 }, (_, i) => `${i + 2}次谐波电压含有率`))
const harmonicCurrentValues = computed(() => Array.from({ length: 24 }, (_, i) => `${i + 2}次谐波电流有效值`))
const interharmonicVoltageValues = computed(() => Array.from({ length: 16 }, (_, i) => `${i + 0.5}次间谐波电压含有率`))
// 谐波电压全选/取消全选
const handleCheckAllChange1 = (val: any) => {
if (val) {
const newValues = harmonicVoltageValues.value.filter(v => !indicator.value.includes(v))
indicator.value = [...indicator.value, ...newValues]
} else {
indicator.value = indicator.value.filter(v => !harmonicVoltageValues.value.includes(v))
}
}
// 谐波电流全选/取消全选
const handleCheckAllChange2 = (val: any) => {
if (val) {
const newValues = harmonicCurrentValues.value.filter(v => !indicator.value.includes(v))
indicator.value = [...indicator.value, ...newValues]
} else {
indicator.value = indicator.value.filter(v => !harmonicCurrentValues.value.includes(v))
}
}
// 间谐波电压全选/取消全选
const handleCheckAllChange3 = (val: any) => {
if (val) {
const newValues = interharmonicVoltageValues.value.filter(v => !indicator.value.includes(v))
indicator.value = [...indicator.value, ...newValues]
} else {
indicator.value = indicator.value.filter(v => !interharmonicVoltageValues.value.includes(v))
}
}
// 谐波电压分组内值变化时,更新全选状态
const handleHarmonicVoltageChange = () => {
const selectedInGroup = harmonicVoltageValues.value.filter(v => indicator.value.includes(v))
checkAll1.value =
selectedInGroup.length == harmonicVoltageValues.value.length && harmonicVoltageValues.value.length > 0
}
// 谐波电流分组内值变化时,更新全选状态
const handleHarmonicCurrentChange = () => {
const selectedInGroup = harmonicCurrentValues.value.filter(v => indicator.value.includes(v))
checkAll2.value =
selectedInGroup.length == harmonicCurrentValues.value.length && harmonicCurrentValues.value.length > 0
}
// 谐波电压分组内值变化时,更新全选状态
const handleInterharmonicVoltageChange = () => {
const selectedInGroup = interharmonicVoltageValues.value.filter(v => indicator.value.includes(v))
checkAll3.value =
selectedInGroup.length == interharmonicVoltageValues.value.length && interharmonicVoltageValues.value.length > 0
}
const tableStore = new TableStore({
showPage: false,
url: '/cs-harmonic-boot/csHarmonicPlan/list',
method: 'GET',
publicHeight: 70,
column: [
{ title: '方案名称', field: 'name', align: 'center' },
{
title: '操作',
fixed: 'right',
align: 'center',
width: '100',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
openDialog('edit', row)
}
},
{
name: 'del',
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除该角色吗?'
},
click: row => {
deletePlan([row.id]).then(() => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
beforeSearchFun: () => {},
loadCallback: () => {
tableRef.value.getRef().setCurrentRow(tableStore.table.data[0])
currentChange({
row: tableStore.table.data[0]
})
}
})
tableStore.table.params.searchValue = ''
getCldTree().then(res => {
res.data?.children.map((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item: any) => {
item.icon = 'el-icon-List'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
item2.color = item2.comFlag == 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.color = item3.comFlag == 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
})
})
})
})
menuTree.value = filterTreeKeepPath(res.data.children)
})
provide('tableStore', tableStore)
const filterTreeKeepPath = (treeData: any) => {
const result = []
for (const node of treeData) {
// 递归处理子节点
const filteredChildren: any = node.children?.length ? filterTreeKeepPath(node.children) : []
// 如果当前节点 level == 3或者子节点中有符合条件的数据
if (node.level == 3 || filteredChildren.length > 0) {
result.push({
...node,
children: filteredChildren
})
}
}
return result
}
// 打开弹框
const openDialog = (type: string, row?: any) => {
if (type == 'add') {
dialogTitle.value = '新增方案'
formData.value = {
id: '',
name: '',
lineList: [],
harmonicTarget: '',
sort: 0
}
} else if (type == 'edit') {
dialogTitle.value = '编辑方案'
formData.value = {
id: row.id,
lineList: row.lineList,
harmonicTarget: row.harmonicTarget,
sort: row.sort,
name: row.name
}
}
dialogVisible.value = true
}
// 关闭弹框
const handleClose = () => {
dialogVisible.value = false
formRef.value?.resetFields()
}
// 提交表单
const submitForm = async () => {
await formRef.value?.validate()
if (dialogTitle.value == '新增方案') {
await save({
harmonicTarget: '',
id: '',
lineList: [],
name: formData.value.name,
sort: formData.value.sort
}).then((res: any) => {
ElMessage.success(`${dialogTitle.value}成功`)
dialogVisible.value = false
tableStore.index() // 刷新列表
})
} else {
await update({
harmonicTarget: formData.value.harmonicTarget,
id: formData.value.id,
lineList: formData.value.lineList,
name: formData.value.name,
sort: formData.value.sort
}).then((res: any) => {
ElMessage.success(`${dialogTitle.value}成功`)
dialogVisible.value = false
tableStore.index() // 刷新列表
})
}
// 模拟保存成功
}
// 保存指标
const saveIndicator = () => {
// TODO: 调用保存指标接口
loading.value = true
update({
harmonicTarget: indicator.value.join(','),
id: copyRow.value.id,
lineList: treeRef.value.treeRef
.getCheckedNodes(false, true)
.filter(item => item.level == 3)
.map((node: any) => node.id),
name: copyRow.value.name,
sort: copyRow.value.sort
})
.then((res: any) => {
ElMessage.success(`保存成功`)
loading.value = false
tableStore.index()
})
.catch(() => {
loading.value = false
})
}
const currentChange = (data: any) => {
getById({ id: data.row.id }).then((res: any) => {
checkStrictly.value = true
indicator.value = res.data.harmonicTarget.split(',')
lineList.value = res.data.lineList || []
copyRow.value = res.data
treeRef.value.treeRef.setCheckedKeys(lineList.value)
setTimeout(() => {
handleInterharmonicVoltageChange()
handleHarmonicCurrentChange()
handleHarmonicVoltageChange()
checkStrictly.value = false
}, 100)
})
}
onMounted(() => {
tableStore.index()
})
const addRole = () => {
openDialog('add')
}
</script>
<style lang="scss" scoped>
:deep(.el-tabs--border-card > .el-tabs__content) {
padding: 0px !important;
}
.df {
display: flex;
.title {
width: 125px;
}
:deep(.el-checkbox) {
width: 70px;
}
}
.custom-table-header {
height: 60px;
}
.borderBox {
border: 1px solid var(--el-border-color);
}
</style>
<template>
<div class="default-main" style="display: flex" :style="height">
<div style="width: 400px; overflow: hidden">
<div class="custom-table-header">
<div class="title">方案列表</div>
<el-button :icon="Plus" type="primary" @click="addRole" class="ml10">新增</el-button>
</div>
<Table ref="tableRef" :row-config="{ isCurrent: true, isHover: true }" @currentChange="currentChange" />
</div>
<div style="flex: 1; overflow: hidden">
<div class="custom-table-header">
<div class="title">指标配置</div>
<!-- <el-button :icon="Select" type="primary" @click="saveIndicator" class="ml10">保存</el-button> -->
</div>
<div class="pd10 borderBox" :style="height1" style="overflow-y: auto">
<!-- <H4 class="mt10">基础指标</H4>
<el-checkbox-group v-model="indicator">
<el-checkbox label="频率偏差" value="频率偏差" />
<el-checkbox label="电压偏差" value="电压偏差" />
<el-checkbox label="三相电压不平衡度" value="三相电压不平衡度" />
<el-checkbox label="闪变" value="闪变" />
<el-checkbox label="电压总谐波畸变率" value="电压总谐波畸变率" />
<el-checkbox label="负序电流" value="负序电流" />
</el-checkbox-group> -->
<el-tabs type="border-card">
<el-tab-pane label="基础指标" class="pd10">
<el-checkbox-group v-model="indicator"
class="indicator-checkbox-grid indicator-checkbox-grid--wide">
<el-checkbox label="频率偏差" value="频率偏差" />
<el-checkbox label="电压偏差" value="电压偏差" />
<el-checkbox label="三相电压不平衡度" value="三相电压不平衡度" />
<el-checkbox label="闪变" value="闪变" />
<el-checkbox label="电压总谐波畸变率" value="电压总谐波畸变率" />
<el-checkbox label="负序电流" value="负序电流" />
</el-checkbox-group>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" class="mt10">
<el-tab-pane label="谐波电压" class="pd10">
<div class="df">
<div class="title">谐波电压含有率:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll1" @change="handleCheckAllChange1">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleHarmonicVoltageChange">
<el-checkbox v-for="num in 24" :key="`harmonicVoltage_${num + 1}`"
:label="`${num + 1}次`" :value="`${num + 1}次谐波电压含有率`" />
</el-checkbox-group>
</div>
</div>
</el-tab-pane>
</el-tabs>
<!-- <H4 class="mt10">谐波电压</H4>
<div class="df">
<div class="title">谐波电压含有率:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll1" @change="handleCheckAllChange1">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleHarmonicVoltageChange">
<el-checkbox
v-for="num in 24"
:key="`harmonicVoltage_${num + 1}`"
:label="`${num + 1}次`"
:value="`${num + 1}次谐波电压含有率`"
/>
</el-checkbox-group>
</div>
</div> -->
<!-- <H4 class="mt10">谐波电流</H4>
<div class="df">
<div class="title">谐波电流有效值:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll2" @change="handleCheckAllChange2">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleHarmonicCurrentChange">
<el-checkbox v-for="num in 24" :key="`harmonicCurrent_${num + 1}`" :label="`${num + 1}次`"
:value="`${num + 1}次谐波电流有效值`" />
</el-checkbox-group>
</div>
</div> -->
<el-tabs type="border-card" class="mt10">
<el-tab-pane label="谐波电流" class="pd10">
<div class="df">
<div class="title">谐波电流有效值:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll2" @change="handleCheckAllChange2">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleHarmonicCurrentChange">
<el-checkbox v-for="num in 24" :key="`harmonicCurrent_${num + 1}`"
:label="`${num + 1}次`" :value="`${num + 1}次谐波电流有效值`" />
</el-checkbox-group>
</div>
</div>
</el-tab-pane>
</el-tabs>
<el-tabs type="border-card" class="mt10">
<el-tab-pane label="间谐波电压" class="pd10">
<div class="df">
<div class="title">间谐波电压含有率:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll3" @change="handleCheckAllChange3">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleInterharmonicVoltageChange">
<el-checkbox v-for="num in 16" :key="`interharmonicVoltage_${num}`"
:label="`${num - 0.5}次`" :value="`${num - 0.5}次间谐波电压含有率`" />
</el-checkbox-group>
</div>
</div>
</el-tab-pane>
</el-tabs>
<!-- <H4 class="mt10">间谐波电压</H4>
<div class="df">
<div class="title">间谐波电压含有率:</div>
<div style="flex: 1">
<el-checkbox v-model="checkAll3" @change="handleCheckAllChange3">全选</el-checkbox>
<el-checkbox-group v-model="indicator" @change="handleInterharmonicVoltageChange">
<el-checkbox v-for="num in 16" :key="`interharmonicVoltage_${num}`" :label="`${num - 0.5}次`"
:value="`${num - 0.5}次间谐波电压含有率`" />
</el-checkbox-group>
</div>
</div> -->
</div>
</div>
<div style="width: 370px">
<div class="custom-table-header">
<div class="title">监测点绑定</div>
<el-button :icon="Select" type="primary" @click="saveIndicator" class="ml10" :loading="loading">
保存
</el-button>
</div>
<!-- <steadyStateTree /> -->
<Tree class="borderBox" ref="treeRef" show-checkbox :showBut="false" width="370px" :height="260"
:data="menuTree" :checkStrictly="checkStrictly"></Tree>
</div>
<!-- 新增/编辑弹框 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="400px" :before-close="handleClose">
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px">
<el-form-item label="方案名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="formData.name" placeholder="请输入方案名称" clearable />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model.number="formData.sort" :min="0" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { Plus, Select } from '@element-plus/icons-vue'
import { ref, onMounted, provide, computed } from 'vue'
import TableStore from '@/utils/tableStore'
import { getLineTree, getCldTree } from '@/api/cs-device-boot/csLedger'
import Table from '@/components/table/index.vue'
import { save, deletePlan, update, getById } from '@/api/cs-harmonic-boot/mxgraph'
import { mainHeight } from '@/utils/layout'
import { ElMessage } from 'element-plus'
import steadyStateTree from '@/components/tree/govern/steadyStateTree.vue'
import { useConfig } from '@/stores/config'
import Tree from '@/components/tree/allocation.vue'
import { id } from 'element-plus/es/locale'
defineOptions({
name: 'govern/steadyStateEvent'
})
const height = mainHeight(20)
const height1 = mainHeight(90)
const config = useConfig()
const tableRef = ref()
const checkAll1 = ref(false)
const checkAll2 = ref(false)
const checkAll3 = ref(false)
const menuTree: any = ref([])
const checkStrictly = ref(false)
const indicator: any = ref([])
const lineList: any = ref([])
const copyRow: any = ref({})
const treeRef = ref()
const loading = ref(false)
// 弹框相关
const dialogVisible = ref(false)
const dialogTitle = ref('新增方案')
const formRef = ref()
const formData = ref({
id: '',
sort: 0,
lineList: [],
harmonicTarget: '',
name: ''
})
const formRules = {
name: [{ required: true, message: '请输入方案名称', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
// 生成各分组的指标值数组
const harmonicVoltageValues = computed(() => Array.from({ length: 24 }, (_, i) => `${i + 2}次谐波电压含有率`))
const harmonicCurrentValues = computed(() => Array.from({ length: 24 }, (_, i) => `${i + 2}次谐波电流有效值`))
const interharmonicVoltageValues = computed(() => Array.from({ length: 16 }, (_, i) => `${i + 0.5}次间谐波电压含有率`))
// 谐波电压全选/取消全选
const handleCheckAllChange1 = (val: any) => {
if (val) {
const newValues = harmonicVoltageValues.value.filter(v => !indicator.value.includes(v))
indicator.value = [...indicator.value, ...newValues]
} else {
indicator.value = indicator.value.filter(v => !harmonicVoltageValues.value.includes(v))
}
}
// 谐波电流全选/取消全选
const handleCheckAllChange2 = (val: any) => {
if (val) {
const newValues = harmonicCurrentValues.value.filter(v => !indicator.value.includes(v))
indicator.value = [...indicator.value, ...newValues]
} else {
indicator.value = indicator.value.filter(v => !harmonicCurrentValues.value.includes(v))
}
}
// 间谐波电压全选/取消全选
const handleCheckAllChange3 = (val: any) => {
if (val) {
const newValues = interharmonicVoltageValues.value.filter(v => !indicator.value.includes(v))
indicator.value = [...indicator.value, ...newValues]
} else {
indicator.value = indicator.value.filter(v => !interharmonicVoltageValues.value.includes(v))
}
}
// 谐波电压分组内值变化时,更新全选状态
const handleHarmonicVoltageChange = () => {
const selectedInGroup = harmonicVoltageValues.value.filter(v => indicator.value.includes(v))
checkAll1.value =
selectedInGroup.length == harmonicVoltageValues.value.length && harmonicVoltageValues.value.length > 0
}
// 谐波电流分组内值变化时,更新全选状态
const handleHarmonicCurrentChange = () => {
const selectedInGroup = harmonicCurrentValues.value.filter(v => indicator.value.includes(v))
checkAll2.value =
selectedInGroup.length == harmonicCurrentValues.value.length && harmonicCurrentValues.value.length > 0
}
// 间谐波电压分组内值变化时,更新全选状态
const handleInterharmonicVoltageChange = () => {
const selectedInGroup = interharmonicVoltageValues.value.filter(v => indicator.value.includes(v))
checkAll3.value =
selectedInGroup.length == interharmonicVoltageValues.value.length && interharmonicVoltageValues.value.length > 0
}
const tableStore = new TableStore({
showPage: false,
url: '/cs-harmonic-boot/csHarmonicPlan/list',
method: 'GET',
publicHeight: 70,
column: [
{ title: '方案名称', field: 'name', align: 'center' },
{
title: '操作',
fixed: 'right',
align: 'center',
width: '100',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
openDialog('edit', row)
}
},
{
name: 'del',
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除该角色吗?'
},
click: row => {
deletePlan([row.id]).then(() => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
beforeSearchFun: () => { },
loadCallback: () => {
tableRef.value.getRef().setCurrentRow(tableStore.table.data[0])
currentChange({
row: tableStore.table.data[0]
})
}
})
tableStore.table.params.searchValue = ''
getCldTree().then(res => {
res.data?.children.map((item: any) => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item: any) => {
item.icon = 'el-icon-List'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
item2.color = item2.comFlag == 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.color = item3.comFlag == 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
})
})
})
})
menuTree.value = filterTreeKeepPath(res.data.children)
})
provide('tableStore', tableStore)
const filterTreeKeepPath = (treeData: any) => {
const result = []
for (const node of treeData) {
// 递归处理子节点
const filteredChildren: any = node.children?.length ? filterTreeKeepPath(node.children) : []
// 如果当前节点 level == 3或者子节点中有符合条件的数据
if (node.level == 3 || filteredChildren.length > 0) {
result.push({
...node,
children: filteredChildren
})
}
}
return result
}
// 打开弹框
const openDialog = (type: string, row?: any) => {
if (type == 'add') {
dialogTitle.value = '新增方案'
formData.value = {
id: '',
name: '',
lineList: [],
harmonicTarget: '',
sort: 0
}
} else if (type == 'edit') {
dialogTitle.value = '编辑方案'
formData.value = {
id: row.id,
lineList: row.lineList,
harmonicTarget: row.harmonicTarget,
sort: row.sort,
name: row.name
}
}
dialogVisible.value = true
}
// 关闭弹框
const handleClose = () => {
dialogVisible.value = false
formRef.value?.resetFields()
}
// 提交表单
const submitForm = async () => {
await formRef.value?.validate()
if (dialogTitle.value == '新增方案') {
await save({
harmonicTarget: '',
id: '',
lineList: [],
name: formData.value.name,
sort: formData.value.sort
}).then((res: any) => {
ElMessage.success(`${dialogTitle.value}成功`)
dialogVisible.value = false
tableStore.index() // 刷新列表
})
} else {
await update({
harmonicTarget: formData.value.harmonicTarget,
id: formData.value.id,
lineList: formData.value.lineList,
name: formData.value.name,
sort: formData.value.sort
}).then((res: any) => {
ElMessage.success(`${dialogTitle.value}成功`)
dialogVisible.value = false
tableStore.index() // 刷新列表
})
}
// 模拟保存成功
}
// 保存指标
const saveIndicator = () => {
// TODO: 调用保存指标接口
loading.value = true
update({
harmonicTarget: indicator.value.join(','),
id: copyRow.value.id,
lineList: treeRef.value.treeRef
.getCheckedNodes(false, true)
.filter(item => item.level == 3)
.map((node: any) => node.id),
name: copyRow.value.name,
sort: copyRow.value.sort
})
.then((res: any) => {
ElMessage.success(`保存成功`)
loading.value = false
tableStore.index()
})
.catch(() => {
loading.value = false
})
}
const currentChange = (data: any) => {
getById({ id: data.row.id }).then((res: any) => {
checkStrictly.value = true
indicator.value = res.data.harmonicTarget.split(',')
lineList.value = res.data.lineList || []
copyRow.value = res.data
treeRef.value.treeRef.setCheckedKeys(lineList.value)
setTimeout(() => {
handleInterharmonicVoltageChange()
handleHarmonicCurrentChange()
handleHarmonicVoltageChange()
checkStrictly.value = false
}, 100)
})
}
onMounted(() => {
tableStore.index()
})
const addRole = () => {
openDialog('add')
}
</script>
<style lang="scss" scoped>
:deep(.el-tabs--border-card > .el-tabs__content) {
padding: 0px !important;
}
.df {
display: flex;
.title {
width: 125px;
}
:deep(.el-checkbox) {
width: 70px;
}
}
.custom-table-header {
height: 60px;
}
.borderBox {
border: 1px solid var(--el-border-color);
}
</style>