添加工程信息管理 页面

This commit is contained in:
guanj
2026-02-02 13:56:50 +08:00
parent cf4291ed9a
commit dd0dab7643
20 changed files with 1152 additions and 470 deletions

View File

@@ -1,41 +1,82 @@
import request from '@/utils/request'
// 新增程序版本
export const addEdData = (data) => {
export const addEdData = data => {
return request({
url: '/cs-device-boot/edData/addEdData',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
'Content-Type': 'multipart/form-data'
},
data: data,
data: data
})
}
export const auditEdData = (data) => {
export const auditEdData = data => {
return request({
url: '/cs-device-boot/edData/auditEdData',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
'Content-Type': 'multipart/form-data'
},
data: data,
data: data
})
}
// 修改-删除工程
export const auditEngineering = (data:any)=> {
export const auditEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineering/auditEngineering',
method: 'post',
data: data,
data: data
})
}
// 修改项目
export const updateProject = (data:any) => {
export const updateProject = (data: any) => {
return request({
url: '/cs-device-boot/project/updateProject',
method: 'post',
data: data,
data: data
})
}
}
// 新增工程
export const addEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/addEngineering',
method: 'post',
data: data
})
}
// 修改工程
export const updateEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/updateEngineering',
method: 'post',
data: data
})
}
// 刪除工程
export const deleteEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/deleteEngineering',
method: 'post',
params: data
})
}
// 刪除項目
export const deleteProject = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/deleteProject',
method: 'post',
params: data
})
}
// 新增项目
export const addProject = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/addProject',
method: 'post',
data: data
})
}

View File

@@ -143,7 +143,7 @@ const tableStore: any = new TableStore({
},
loadCallback: () => {
// 定义 x 轴标签顺序
const xAxisLabels = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
const xAxisLabels = ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
// 根据指标名称顺序提取对应的 extent 数据
const chartData = xAxisLabels.map(label => {

View File

@@ -85,7 +85,7 @@ const tableStore: any = new TableStore({
width: '150'
},
{
title: '闪变越限(%)',
title: '长时闪变越限(%)',
field: 'flickerOvertime',
width: '90',
render: 'customTemplate',

View File

@@ -88,7 +88,7 @@ const initEcharts = () => {
xAxis: {
// name: '(区域)',
data: ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
data: ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
},
yAxis: {
@@ -149,7 +149,7 @@ const tableStore: any = new TableStore({
title: '越限占比(%)',
children: [
{
title: '闪变',
title: '长时闪变',
field: 'flicker',
minWidth: '70',
render: 'customTemplate',

View File

@@ -136,7 +136,7 @@ const initProbabilityData = () => {
// 处理接口返回的数据,转换为图表所需格式
if (res.data && Array.isArray(res.data)) {
// 定义指标类型顺序
const indicatorOrder = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
const indicatorOrder = ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
// 按照指定顺序排序数据
const sortedData = [...res.data].sort((a, b) => {
return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName)

View File

@@ -135,7 +135,7 @@ const initProbabilityData = () => {
// 处理接口返回的数据,转换为图表所需格式
if (res.data && Array.isArray(res.data)) {
// 定义指标类型顺序
const indicatorOrder = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
const indicatorOrder = ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
// 按照指定顺序排序数据
const sortedData = [...res.data].sort((a, b) => {
return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName)

View File

@@ -12,7 +12,7 @@
multiple
:multiple-limit="2"
collapse-tags
collapse-tags-tooltip
collapse-tags-tooltip
v-model="searchForm.index"
placeholder="请选择统计指标"
@change="onIndexChange($event)"
@@ -66,7 +66,7 @@
<el-option
v-for="vv in item.countOptions"
:key="vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:value="vv"
></el-option>
</el-select>
@@ -81,12 +81,8 @@
</template>
</TableHeader>
</div>
<div class="history_chart" :style="pageHeight" v-loading="loading">
<MyEchart
ref="historyChart"
:options="echartsData"
v-if="showEchart"
/>
<div class="history_chart" :style="pageHeight" v-loading="loading">
<MyEchart ref="historyChart" :options="echartsData" v-if="showEchart" />
<el-empty :style="pageHeight" v-else description="暂无数据" />
</div>
</el-dialog>
@@ -160,28 +156,40 @@ const countOptions: any = ref([])
const legendDictList: any = ref([])
const initCode = (field: string, title: string) => {
queryByCode('steady_state_limit_trend').then(res => {
queryByCode('gridSide_exceedTheLimit').then(res => {
queryCsDictTree(res.data.id).then(item => {
//排序
indexOptions.value = item.data.sort((a: any, b: any) => {
return a.sort - b.sort
})
const titleMap: Record<string, number> = {
flickerOvertime: 0,
uaberranceOvertime: 3,
ubalanceOvertime: 4,
freqDevOvertime: 5
}
// const titleMap: Record<string, number> = {
// flickerOvertime: 0,
// uaberranceOvertime: 3,
// ubalanceOvertime: 4,
// freqDevOvertime: 5
// }
let defaultIndex = 0 // 默认值
// let defaultIndex = 0 // 默认值
if (field in titleMap) {
defaultIndex = titleMap[field]
} else if (field.includes('uharm')) {
defaultIndex = 1
} else if (field.includes('iharm')) {
defaultIndex = 2
}
// if (field in titleMap) {
// defaultIndex = titleMap[field]
// } else if (field.includes('uharm')) {
// defaultIndex = 1
// } else if (field.includes('iharm')) {
// defaultIndex = 2
// }
let codeKey = field.includes('flickerOvertime')
? '闪变'
: field.includes('uharm')
? '谐波电压'
: field.includes('iharm')
? '谐波电流'
: field.includes('voltageDevOvertime')
? '电压偏差'
: field.includes('ubalanceOvertime')
? '不平衡'
: ''
let defaultIndex = indexOptions.value.findIndex((item: any) => item.name.includes(codeKey)) || 0
searchForm.value.index[0] = indexOptions.value[defaultIndex].id
})
@@ -294,7 +302,7 @@ const init = async () => {
}
lists[index] = {
statisticalId: item.index,
frequency: frequencys !== null && frequencys !== undefined ? String(frequencys) : ''
frequency: frequencys !== null && frequencys !== undefined ? String(frequencys) : ''
}
})
let obj = {
@@ -579,7 +587,6 @@ const setTimeControl = () => {
}
const selectChange = (flag: boolean, height: any) => {
pageHeight.value = mainHeight(height * 1.6, 1.6)
}
//导出

View File

@@ -86,7 +86,7 @@ const tableStore: any = new TableStore({
width: '150'
},
{
title: '闪变越限(分钟)',
title: '越限(分钟)',
field: 'flickerOvertime',
width: '90',
render: 'customTemplate',
@@ -101,6 +101,14 @@ const tableStore: any = new TableStore({
{
title: '谐波电流越限(分钟)',
children: loop50('iharm')
}, {
title: '电压偏差越限(分钟)',
field: 'uaberranceOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
}
},
{
title: '三相不平衡度越限(分钟)',
@@ -111,24 +119,16 @@ const tableStore: any = new TableStore({
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`
}
},
{
title: '电压偏差越限(分钟)',
field: 'uaberranceOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
}
},
{
title: '频率偏差越限(分钟)',
field: 'freqDevOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
}
}
// {
// title: '频率偏差越限(分钟)',
// field: 'freqDevOvertime',
// width: '100',
// render: 'customTemplate',
// customTemplate: (row: any) => {
// return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
// }
// }
],
beforeSearchFun: () => {
},

View File

@@ -69,7 +69,7 @@ const tableStore: any = new TableStore({
width: '150'
},
{
title: '闪变越限(分钟)',
title: '长时闪变越限(分钟)',
field: 'flicker',
width: '80'
},
@@ -99,26 +99,7 @@ const tableStore: any = new TableStore({
],
beforeSearchFun: () => {},
loadCallback: () => {
tableStore.table.data = [
{
time: '2024-01-01 00:00:00',
name: '35kV进线',
flicker: '0',
},
{
time: '2024-01-01 00:00:00',
name: '35kV进线',
flicker: '0',
},
{
time: '2024-01-01 00:00:00',
name: '35kV进线',
flicker: '0',
},
]
}
})

View File

@@ -84,7 +84,7 @@ const tableStore: any = new TableStore({
width: '150'
},
{
title: '闪变越限(分钟)',
title: '长时闪变越限(分钟)',
field: 'flicker',
width: '80',
render: 'customTemplate',

View File

@@ -85,7 +85,7 @@ const tableStore: any = new TableStore({
width: '150'
},
{
title: '闪变越限(%)',
title: '长时闪变越限(%)',
field: 'flickerOvertime',
width: '90',
render: 'customTemplate',
@@ -101,16 +101,7 @@ const tableStore: any = new TableStore({
title: '谐波电流越限(%)',
children: loop50('iharm')
},
{
title: '三相不平衡度越限(%)',
field: 'ubalanceOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`
}
},
{
{
title: '电压偏差越限(%)',
field: 'voltageDevOvertime',
width: '100',
@@ -120,14 +111,24 @@ const tableStore: any = new TableStore({
}
},
{
title: '频率偏差越限(%)',
field: 'freqDevOvertime',
title: '三相不平衡度越限(%)',
field: 'ubalanceOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`
}
}
},
// {
// title: '频率偏差越限(%)',
// field: 'freqDevOvertime',
// width: '100',
// render: 'customTemplate',
// customTemplate: (row: any) => {
// return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
// }
// }
],
beforeSearchFun: () => {
},

View File

@@ -85,7 +85,7 @@ const tableStore: any = new TableStore({
width: '150'
},
{
title: '闪变越限(%)',
title: '长时闪变越限(%)',
field: 'flickerOvertime',
width: '90',
render: 'customTemplate',

View File

@@ -89,7 +89,7 @@ const initEcharts = () => {
xAxis: {
// name: '(区域)',
data: ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
data: ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
},
yAxis: {
@@ -150,7 +150,7 @@ const tableStore: any = new TableStore({
title: '越限占比(%)',
children: [
{
title: '闪变',
title: '长时闪变',
field: 'flicker',
minWidth: '70',
render: 'customTemplate',

View File

@@ -481,7 +481,33 @@
:disabled="true"
></el-input>
</el-form-item>
<el-form-item
class="form-item"
label="日志等级:"
:prop="'deviceInfoList[' + bIndex + '].devLogLevel'"
>
<el-select
clearable
filterable
v-model="busItem.devLogLevel"
placeholder="请选择日志等级"
style="width: 100%"
:disabled="
!(
(nodeLevel == 3 && pageStatus == 3) ||
((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) &&
pageStatus == 2)
)
"
>
<el-option
v-for="value in logList"
:key="value.value"
:label="value.label"
:value="value.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
class="form-item"
label="排序:"
@@ -939,7 +965,7 @@
class="form-item"
label="是否治理:"
:prop="'lineInfoList[' + lIndex + '].govern'"
:rules="{ required: true, message: '请选择是否治理', trigger: 'blur' }"
:rules="{ required: true, message: '请选择是否治理', trigger: 'change' }"
>
<el-select
clearable
@@ -985,6 +1011,35 @@
<el-option label="退运" :value="4" />
</el-select>
</el-form-item>
<el-form-item
class="form-item"
label="日志等级:"
:prop="'lineInfoList[' + lIndex + '].lineLogLevel'"
:rules="{ required: true, message: '请选择日志等级', trigger: 'change' }"
>
<!-- 0运行1检修2停运3调试4退运 -->
<el-select
clearable
filterable
v-model="lineItem.lineLogLevel"
placeholder="请选择日志等级"
:disabled="
!(
(nodeLevel == 4 && pageStatus == 3) ||
((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) &&
pageStatus == 2)
)
"
>
<el-option
v-for="value in logList"
:key="value.value"
:label="value.label"
:value="value.value"
></el-option>
</el-select>
</el-form-item>
</div>
</el-tab-pane>
</el-tabs>
@@ -1159,6 +1214,24 @@ const lineSpaceArr = ref([
{ name: '5分钟', value: 5 },
{ name: '10分钟', value: 10 }
])
const logList = ref([
{
value: 'DEBUG',
label: 'DEBUG'
},
{
value: 'NORMAL',
label: 'NORMAL'
},
{
value: 'WARN',
label: 'WARN'
},
{
value: 'ERROR',
label: 'ERROR'
}
])
//工程
// const engineeringParam = ref({
// city: '',
@@ -1179,6 +1252,7 @@ interface DeviceInfo {
devModel: string
devType: string
devAccessMethod: string
devLogLevel: string
mac: string
ndid: string
nodeId: string
@@ -1203,6 +1277,7 @@ interface LineInfo {
monitorObj: string
position: string
govern: string | number
lineLogLevel: string
runStatus: string | number
basicCapacity: number
shortCircuitCapacity: number
@@ -1555,6 +1630,7 @@ const add = () => {
devModel: '',
devType: '',
devAccessMethod: 'CLD',
devLogLevel: 'WARN',
mac: '',
ndid: '',
nodeId: '',
@@ -1583,6 +1659,7 @@ const add = () => {
monitorObj: '',
position: '',
govern: 0,
lineLogLevel: 'WARN',
runStatus: 0,
basicCapacity: 0,
shortCircuitCapacity: 0,
@@ -1695,8 +1772,9 @@ const updateEquipmentFunc = (id: any) => {
id: id, // 设备ID用于修改
name: currentDevice.name,
devModel: currentDevice.devModel,
devType: currentDevice.devType,
devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod,
devLogLevel: currentDevice.devLogLevel,
mac: currentDevice.mac,
nodeId: currentDevice.nodeId,
cntractNo: currentDevice.cntractNo,
@@ -1760,6 +1838,7 @@ const updateLineFunc = (id: any) => {
monitorObj: currentLine.monitorObj || '',
position: currentLine.position || '',
govern: currentLine.govern,
lineLogLevel: currentLine.lineLogLevel,
runStatus: currentLine.runStatus,
basicCapacity: currentLine.basicCapacity || 0,
shortCircuitCapacity: currentLine.shortCircuitCapacity || 0,
@@ -1925,6 +2004,7 @@ const next = async () => {
devModel: '',
devType: '',
devAccessMethod: 'CLD',
devLogLevel: 'WARN',
mac: '',
ndid: '',
nodeId: '',
@@ -1957,6 +2037,7 @@ const next = async () => {
monitorObj: '',
position: '',
govern: 0,
lineLogLevel:'WARN',
runStatus: 0,
basicCapacity: 0,
shortCircuitCapacity: 0,
@@ -2361,6 +2442,8 @@ const resetAllForms = () => {
device.devModel = ''
device.devType = ''
device.devAccessMethod = 'CLD'
device.devLogLevel = 'WARN'
device.mac = ''
device.nodeId = ''
device.cntractNo = ''
@@ -2382,6 +2465,7 @@ const resetAllForms = () => {
line.monitorObj = ''
line.position = ''
line.govern = 0
line.lineLogLevel = 'WARN'
line.runStatus = 0
line.basicCapacity = 0
line.shortCircuitCapacity = 0
@@ -2480,6 +2564,7 @@ const submitData = () => {
devModel: currentDevice.devModel,
devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod,
devLogLevel: currentDevice.devLogLevel,
mac: currentDevice.mac,
nodeId: currentDevice.nodeId,
cntractNo: currentDevice.cntractNo,
@@ -2550,6 +2635,7 @@ const submitData = () => {
monitorObj: currentLine.monitorObj,
position: currentLine.position,
govern: currentLine.govern,
lineLogLevel: currentLine.lineLogLevel,
runStatus: currentLine.runStatus,
basicCapacity: currentLine.basicCapacity,
shortCircuitCapacity: currentLine.shortCircuitCapacity,
@@ -2664,6 +2750,7 @@ const handleBusBarTabsEdit = (targetName: any, action: any) => {
devModel: '',
devType: '',
devAccessMethod: 'CLD',
devLogLevel: 'WARN',
mac: '',
ndid: '',
nodeId: '',
@@ -2740,6 +2827,7 @@ const handleLineTabsEdit = (targetName: any, action: any) => {
monitorObj: '',
position: '',
govern: 0,
lineLogLevel: 'WARN',
runStatus: 0,
basicCapacity: 0,
shortCircuitCapacity: 0,

View File

@@ -1,213 +1,211 @@
<template>
<div class="default-main" :style="{ height: pageHeight.height }">
<vxe-table
v-loading="tableStore.table.loading"
height="auto"
auto-resize
ref="tableRef"
v-bind="defaultAttribute"
:data="tableStore.table.data"
:column-config="{ resizable: true }"
:tree-config="{ expandAll: true }"
>
<vxe-column field="name" align="left" title="名称" tree-node></vxe-column>
<vxe-column field="area" title="区域">
<template #default="{ row }">
{{ row.area || '/' }}
</template>
</vxe-column>
<vxe-column field="remark" title="备注">
<template #default="{ row }">
{{ row.remark || '/' }}
</template>
</vxe-column>
<vxe-column field="remark" title="操作" width="150px">
<template #default="{ row }">
<el-button type="primary" link @click="edit(row)" v-if="!row.path">编辑</el-button>
<el-popconfirm
title="确定删除吗?"
confirm-button-type="danger"
@confirm="deletes(row)"
v-if="!row.path"
>
<template #reference>
<el-button type="danger" link>删除</el-button>
</template>
</el-popconfirm>
</template>
</vxe-column>
</vxe-table>
<el-dialog v-model="dialogVisible" title="编辑" width="500">
<el-form :model="form" ref="ruleFormRef" label-width="80px" :rules="rules">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" clearable placeholder="请输入名称" />
</el-form-item>
<el-form-item label="区域" :prop="form.pid == '0' ? 'city' : 'area'">
<!-- <el-input v-model="form.city" clearable placeholder="请输入区域" /> -->
<el-cascader
v-model="form.city"
v-if="form.pid == '0'"
style="width: 100%"
:options="areaTree"
:props="props"
clearable
filterable
placeholder="请输入区域"
/>
<el-input v-else v-model="form.area" clearable placeholder="请输入区域" />
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import { useDictData } from '@/stores/dictData'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
import { ElMessageBox, ElMessage } from 'element-plus'
import { auditEngineering, updateProject } from '@/api/cs-device-boot/edData'
import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user'
import tree from '@/assets/map/area.json'
defineOptions({
name: 'govern/manage/engineering'
})
const dictData = useDictData()
const tableRef = ref()
const dialogVisible = ref(false)
const pageHeight = mainHeight(20)
const tableStore = new TableStore({
url: '/cs-device-boot/csLedger/getProjectTree',
method: 'POST',
column: [],
loadCallback: () => {
setTimeout(() => {
tableRef.value.setAllTreeExpand(true)
}, 500)
}
})
const ruleFormRef = ref()
const rules = ref({
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
city: [{ required: true, message: '请输入区域', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }]
})
console.log("🚀 ~ dictData.state.areaTree:", dictData.state)
const areaTree: any = tree
const props = {
label: 'text',
value: 'value',
children: 'children',
checkStrictly: true
}
const form = ref({
id: '',
pid: '',
area: '',
name: '',
city: '',
description: ''
})
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
// setTimeout(() => {
// tableRef.value.setAllTreeExpand(true)
// }, 500)
})
const deletes = (row: any) => {
ElMessageBox.prompt('二次校验密码确认', '·', {
confirmButtonText: '确认',
cancelButtonText: '取消',
customClass: 'customInput',
inputType: 'text',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
if (instance.inputValue == null) {
return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else {
done()
}
} else {
done()
}
}
}).then(({ value }) => {
passwordConfirm(value).then(res => {
auditEngineering({
id: row.id,
status: 0
}).then((res: any) => {
ElMessage.success('删除成功')
tableStore.index()
})
})
})
}
// 编辑
const edit = (row: any) => {
form.value = {
id: row.id,
pid: row.pid,
name: row.name,
city: row.cityId,
area: row.area,
description: row.remark
}
dialogVisible.value = true
}
const save = () => {
ruleFormRef.value.validate((valid: any) => {
if (valid) {
if (form.value.pid == '0') {
auditEngineering({ ...form.value, city: form.value.city[form.value.city.length - 1] }).then(
(res: any) => {
ElMessage.success('保存成功')
dialogVisible.value = false
tableStore.index()
}
)
} else {
let params = new FormData()
params.append('id', form.value.id)
params.append('area', form.value.area)
params.append('description', form.value.description)
params.append('name', form.value.name)
updateProject(form.value).then((res: any) => {
ElMessage.success('保存成功')
dialogVisible.value = false
tableStore.index()
})
}
}
})
}
</script>
<style lang="scss">
.customInput {
.el-input__inner {
-webkit-text-security: disc !important;
}
}
</style>
<template>
<div class="default-main" :style="{ height: pageHeight.height }">
<vxe-table
v-loading="tableStore.table.loading"
height="auto"
auto-resize
ref="tableRef"
v-bind="defaultAttribute"
:data="tableStore.table.data"
:column-config="{ resizable: true }"
:tree-config="{ expandAll: true }"
>
<vxe-column field="name" align="left" title="名称" tree-node></vxe-column>
<vxe-column field="area" title="区域">
<template #default="{ row }">
{{ row.area || '/' }}
</template>
</vxe-column>
<vxe-column field="remark" title="备注">
<template #default="{ row }">
{{ row.remark || '/' }}
</template>
</vxe-column>
<vxe-column field="remark" title="操作" width="150px">
<template #default="{ row }">
<el-button type="primary" link @click="edit(row)" v-if="!row.path">编辑</el-button>
<el-popconfirm
title="确定删除吗?"
confirm-button-type="danger"
@confirm="deletes(row)"
v-if="!row.path"
>
<template #reference>
<el-button type="danger" link>删除</el-button>
</template>
</el-popconfirm>
</template>
</vxe-column>
</vxe-table>
<el-dialog v-model="dialogVisible" title="编辑" width="500">
<el-form :model="form" ref="ruleFormRef" label-width="80px" :rules="rules">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" clearable placeholder="请输入名称" />
</el-form-item>
<el-form-item label="区域" :prop="form.pid == '0' ? 'city' : 'area'">
<!-- <el-input v-model="form.city" clearable placeholder="请输入区域" /> -->
<el-cascader
v-model="form.city"
v-if="form.pid == '0'"
style="width: 100%"
:options="areaTree"
:props="props"
clearable
filterable
placeholder="请输入区域"
/>
<el-input v-else v-model="form.area" clearable placeholder="请输入区域" />
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import { useDictData } from '@/stores/dictData'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
import { ElMessageBox, ElMessage } from 'element-plus'
import { auditEngineering, updateProject } from '@/api/cs-device-boot/edData'
import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user'
import tree from '@/assets/map/area.json'
defineOptions({
name: 'govern/manage/engineering'
})
const dictData = useDictData()
const tableRef = ref()
const dialogVisible = ref(false)
const pageHeight = mainHeight(20)
const tableStore = new TableStore({
url: '/cs-device-boot/csLedger/getProjectTree',
method: 'POST',
column: [],
loadCallback: () => {
setTimeout(() => {
tableRef.value.setAllTreeExpand(true)
}, 500)
}
})
const ruleFormRef = ref()
const rules = ref({
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
city: [{ required: true, message: '请输入区域', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }]
})
const areaTree: any = tree
const props = {
label: 'text',
value: 'value',
children: 'children',
checkStrictly: true
}
const form = ref({
id: '',
pid: '',
area: '',
name: '',
city: '',
description: ''
})
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
// setTimeout(() => {
// tableRef.value.setAllTreeExpand(true)
// }, 500)
})
const deletes = (row: any) => {
ElMessageBox.prompt('二次校验密码确认', '·', {
confirmButtonText: '确认',
cancelButtonText: '取消',
customClass: 'customInput',
inputType: 'text',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
if (instance.inputValue == null) {
return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else {
done()
}
} else {
done()
}
}
}).then(({ value }) => {
passwordConfirm(value).then(res => {
auditEngineering({
id: row.id,
status: 0
}).then((res: any) => {
ElMessage.success('删除成功')
tableStore.index()
})
})
})
}
// 编辑
const edit = (row: any) => {
form.value = {
id: row.id,
pid: row.pid,
name: row.name,
city: row.cityId,
area: row.area,
description: row.remark
}
dialogVisible.value = true
}
const save = () => {
ruleFormRef.value.validate((valid: any) => {
if (valid) {
if (form.value.pid == '0') {
auditEngineering({ ...form.value, city: form.value.city[form.value.city.length - 1] }).then(
(res: any) => {
ElMessage.success('保存成功')
dialogVisible.value = false
tableStore.index()
}
)
} else {
let params = new FormData()
params.append('id', form.value.id)
params.append('area', form.value.area)
params.append('description', form.value.description)
params.append('name', form.value.name)
updateProject(form.value).then((res: any) => {
ElMessage.success('保存成功')
dialogVisible.value = false
tableStore.index()
})
}
}
})
}
</script>
<style lang="scss">
.customInput {
.el-input__inner {
-webkit-text-security: disc !important;
}
}
</style>

View File

@@ -0,0 +1,221 @@
<template>
<el-dialog draggable class="cn-operate-dialog" width="520px" v-model.trim="dialogVisible" :title="title">
<el-form :inline="false" ref="formRef" :model="form" label-width="auto" class="form-one" :rules="rules">
<el-form-item label="项目名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="所属工程" prop="engineeringId">
<el-select v-model="form.engineeringId" filterable placeholder="请选择工程" clearable>
<el-option
v-for="item in engineeringList"
:key="item.engineeringId"
:label="item.engineeringName"
:value="item.engineeringId"
/>
</el-select>
</el-form-item>
<el-form-item label="区域" prop="area">
<el-input v-model="form.area" clearable placeholder="请输入区域" />
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input maxlength="32" show-word-limit-number v-model.number="form.sort" :min="0" />
</el-form-item>
<el-form-item label="拓扑图" prop="sort">
<div class="image-radio-group">
<div
class="image-radio-item"
v-for="item in images"
:key="item.id"
@click="handleSelect(item.id)"
>
<el-radio :label="item.id" v-model="form.topoIds" class="hidden-radio">
{{ item.name }}
</el-radio>
<div class="image-container" :class="{ selected: form.topoIds === item.id }">
<img :src="item.url" v-if="item.url" class="image-preview" />
<div v-else style="width: 120px; height: 90px; text-align: center; line-height: 90px">
暂无图片
</div>
<div class="image-overlay" v-if="form.topoIds === item.id">
<el-icon class="check-icon"><Check /></el-icon>
</div>
</div>
<div class="image-name">{{ item.name }}</div>
</div>
</div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { ElMessage } from 'element-plus'
import { add, update } from '@/api/user-boot/role'
import { useAdminInfo } from '@/stores/adminInfo'
import { addProject, updateProject } from '@/api/cs-device-boot/edData'
import { getTopoTemplate } from '@/api/cs-device-boot/topologyTemplate'
import { getFileUrl } from '@/api/system-boot/file'
const adminInfo = useAdminInfo()
const tableStore = inject('tableStore') as TableStore
// do not use same name with ref
const form = reactive({
name: '',
id: '',
engineeringId: '',
area: '',
sort: 100,
description: '',
topoIds: ''
})
const engineeringList: any = ref([])
const rules = {
name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
engineeringId: [{ required: true, message: '请输入工程', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const dialogVisible = ref(false)
const title = ref('新增菜单')
const formRef = ref()
const props = {
label: 'text',
value: 'value',
children: 'children'
// checkStrictly: true
}
const open = (text: string, List: any, data?: anyObj, id?: string) => {
getImageList().catch(() => {})
formRef.value?.resetFields()
title.value = text
dialogVisible.value = true
engineeringList.value = List
if (data) {
form.id = data.projectId
form.name = data.projectName
form.area = data.projectArea
form.description = data.projectRemark
form.sort = data.projectSort
form.engineeringId = id || ''
form.topoIds = data.topologyInfoId || ''
} else {
form.id = ''
form.name = ''
form.area = ''
form.description = ''
form.engineeringId = ''
form.topoIds = ''
form.sort = 100
}
}
const submit = async () => {
formRef.value.validate(async valid => {
console.log("🚀 ~ submit ~ form.topoIds:", form.topoIds)
if (valid) {
if (form.id) {
await updateProject({ ...form ,topoIds:[form.topoIds]})
} else {
await addProject({ ...form,topoIds:[form.topoIds] })
}
ElMessage.success('保存成功')
tableStore.index()
dialogVisible.value = false
}
})
}
const images: any = ref([])
const getImageList = async () => {
getTopoTemplate().then(res => {
images.value = res.data
images.value.forEach(async item => {
let row = await getFileUrl({ filePath: item.filePath })
item.url = row.data
})
})
}
const handleSelect = (filePath: any) => {
form.topoIds = filePath
}
defineExpose({ open })
</script>
<style scoped>
.image-radio-group {
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.image-radio-item {
cursor: pointer;
text-align: center;
}
.hidden-radio {
display: none;
}
.image-container {
position: relative;
border: 2px solid #dcdfe6;
border-radius: 8px;
overflow: hidden;
transition: all 0.3s;
}
.image-container:hover {
border-color: var(--el-color-primary);
}
.image-container.selected {
border-color: var(--el-color-primary);
/* box-shadow: 0 0 8px rgba(64, 158, 255, 0.3); */
}
.image-preview {
width: 120px;
height: 90px;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* background-color: rgba(64, 158, 255, 0.1); */
display: flex;
align-items: center;
justify-content: center;
}
.check-icon {
color: var(--el-color-primary);
font-size: 24px;
}
.image-name {
margin-top: 8px;
font-size: 14px;
width: 120px;
white-space: nowrap; /* 强制文字单行显示,不换行 */
overflow: hidden; /* 隐藏超出容器的文字 */
text-overflow: ellipsis; /* 超出部分显示省略号(点点点) */
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<el-dialog draggable class="cn-operate-dialog" width="500px" v-model.trim="dialogVisible" :title="title">
<el-form :inline="false" ref="formRef" :model="form" label-width="auto" class="form-one" :rules="rules">
<el-form-item label="工程名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入工程名称" />
</el-form-item>
<el-form-item label="区域" prop="city">
<el-cascader
v-model="form.city"
style="width: 100%"
:options="areaTree"
:props="props"
clearable
filterable
placeholder="请选择区域"
/>
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input maxlength="32" show-word-limit-number v-model.number="form.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="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { ElMessage } from 'element-plus'
import { add, update } from '@/api/user-boot/role'
import { useAdminInfo } from '@/stores/adminInfo'
import { addEngineering, updateEngineering } from '@/api/cs-device-boot/edData'
const adminInfo = useAdminInfo()
const tableStore = inject('tableStore') as TableStore
import tree from '@/assets/map/area.json'
// do not use same name with ref
const form = reactive({
name: '',
id: '',
pid: 0,
city: '',
sort: 100,
description: ''
})
const areaTree: any = tree
const rules = {
name: [{ required: true, message: '请输入工程名称', trigger: 'blur' }],
city: [{ required: true, message: '请输入区域', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const dialogVisible = ref(false)
const title = ref('新增菜单')
const formRef = ref()
const props = {
label: 'text',
value: 'value',
children: 'children',
// checkStrictly: true
}
const open = (text: string, data?: anyObj) => {
formRef.value?.resetFields()
title.value = text
dialogVisible.value = true
if (data) {
form.id = data.engineeringId
form.name = data.engineeringName
form.city = [data.provinceId,data.cityId]
form.description = data.engineeringRemark
form.sort = data.engineeringSort
} else {
form.id = ''
form.name = ''
form.city = ''
form.description = ''
form.sort = 100
}
}
const submit = async () => {
formRef.value.validate(async valid => {
if (valid) {
if (form.id) {
await updateEngineering({ ...form, province: form.city[0], city: form.city[1] || '' })
} else {
await addEngineering({ ...form, province: form.city[0], city: form.city[1]||'' })
}
ElMessage.success('保存成功')
tableStore.index()
dialogVisible.value = false
}
})
}
defineExpose({ open })
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="default-main">
<div style="display: flex">
<div style="width: 800px">
<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" @currentChange="currentChange" />
</div>
<div style="flex: 1">
<div class="custom-table-header">
<div class="title">項目列表</div>
<el-button type="primary" icon="el-icon-Plus" @click="add">新增項目</el-button>
</div>
<div :style="height">
<vxe-table
ref="tableRef1"
v-bind="defaultAttribute"
:data="itemList"
height="auto"
style="width: 100%"
>
<vxe-column field="projectName" title="项目名称"></vxe-column>
<vxe-column field="projectArea" title="地址"></vxe-column>
<vxe-column title="拓扑图">
<template #default="{ row }">
<el-image
:hide-on-click-modal="true"
:preview-teleported="true"
:preview-src-list="[row.topologyImageUrl]"
:src="getUrl(row) ? row.topologyImageUrl : ''"
></el-image>
</template>
</vxe-column>
<vxe-column field="projectRemark" title="备注"></vxe-column>
<vxe-column field="projectSort" title="排序" width="80px"></vxe-column>
<vxe-column title="操作" width="180px">
<template #default="{ row }">
<el-button
style="margin-left: 4px"
type="primary"
link
size="small"
@click="itemModification(row)"
class="ml10 mr10"
>
编辑
</el-button>
<el-popconfirm
@confirm="itemeRemove(row)"
title="确定删除吗?"
confirm-button-type="danger"
>
<template #reference>
<el-button style="margin-left: 4px" type="danger" size="small" link>
刪除
</el-button>
</template>
</el-popconfirm>
</template>
</vxe-column>
</vxe-table>
</div>
</div>
</div>
<!-- 新增工程 -->
<popup ref="popupRef" @save="save" />
<!-- 新增項目 -->
<itemAdd ref="itemAddRef" @save="save" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import { delTemplate, deleteSysExcel, bandRelation, queryList } from '@/api/harmonic-boot/luckyexcel'
import { deleteProject ,deleteEngineering} from '@/api/cs-device-boot/edData'
import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
import popup from './components/popup.vue'
import itemAdd from './components/itemAdd.vue'
const dictData = useDictData()
defineOptions({
name: 'govern/manage/engineering'
})
const height = mainHeight(80)
const volConTypeList: any = dictData.getBasicData('Dev_Connect')
import { getFileUrl } from '@/api/system-boot/file'
const popupRef = ref()
const tableRef = ref()
const tableRef1 = ref()
const itemList = ref([])
const menuListId = ref([])
const itemAddRef = ref()
const engineeringId = ref('')
const tableStore: any = new TableStore({
url: '/cs-device-boot/engineeringProjectRelation/list',
method: 'POST',
publicHeight: 60,
showPage: false,
column: [
{ field: 'engineeringName', title: '工程名称' },
{
field: 'engineeringAreaName',
title: '区域'
},
{
field: 'engineeringRemark',
title: '备注'
},
{
field: 'engineeringSort',
title: '排序',
width: '80px'
},
{
title: '操作',
fixed: 'right',
width: '150',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
popupRef.value.open('编辑工程', row)
}
},
{
name: 'del',
text: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除?'
},
click: row => {
deleteEngineering({ id: row.engineeringId }).then(res => {
engineeringId.value = ''
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {
if (engineeringId.value == '') {
engineeringId.value = tableStore.table.data[0].engineeringId
}
let list = tableStore.table.data.filter((item: any) => item.engineeringId == engineeringId.value)
tableRef.value.getRef().setCurrentRow(list[0])
itemList.value = list[0].projectInfoList
}
})
provide('tableStore', tableStore)
// 修改模版
const itemModification = (row: any) => {
itemAddRef.value.open('新增项目', tableStore.table.data, row, engineeringId.value)
}
// 删除模版
const itemeRemove = (row: any) => {
deleteProject({ id: row.projectId }).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
const addRole = () => {
// add()
popupRef.value.open('新增工程')
}
const add = () => {
itemAddRef.value.open('新增项目', tableStore.table.data)
}
// 查询绑定模版
const currentChange = (data: any) => {
engineeringId.value = data.row.engineeringId
itemList.value = data.row.projectInfoList
}
// 保存模版
const save = () => {
bandRelation({
modelIds: tableRef1.value.getCheckboxRecords().map(item => item.id),
id: menuListId.value
})
.then(() => {
ElMessage.success('操作成功!')
})
.catch(() => {})
}
const imgList = ref([])
// 获取拓扑图
const getUrl = async (row: any) => {
if (!row.topologyInfo || row.topologyInfo === '/') return false
try {
const res = await getFileUrl({ filePath: row.topologyInfo })
row.topologyImageUrl = res.data
return true
} catch (error) {
return false
}
}
onMounted(() => {
tableStore.index()
})
</script>
<style scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-image {
height: 36px;
}
</style>

View File

@@ -6,7 +6,7 @@
maxlength="32"
show-word-limit
v-model.trim="form.modelTypeName"
placeholder="请输入菜单名称"
placeholder="请输入报表名称"
/>
</el-form-item>
<el-form-item label="报表类型" prop="modelType">

View File

@@ -1,152 +1,152 @@
<template>
<div class="default-main">
<TableHeader date-picker area>
<template v-slot:select>
<el-form-item label="干扰源类型">
<el-select multiple clearable collapse-tags v-model.trim="interferenceSourceForm" placeholder="请选择"
@change="onLoadTypeChange">
<el-option v-for="item in interferenceSource" :key="item.id" :label="item.name"
:value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="电压等级">
<el-select multiple clearable collapse-tags v-model.trim="scaleForm" placeholder="请选择"
@change="onScaleChange">
<el-option v-for="item in level" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="通讯状态">
<el-select multiple clearable collapse-tags v-model.trim="tableStore.table.params.comFlag"
placeholder="请选择">
<el-option label="正常" value="1" />
<el-option label="中断" value="0" />
</el-select>
</el-form-item>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"
placeholder="根据变电站,终端编号,型号或网络参数查询" />
</el-form-item>
</template>
</TableHeader>
<Table isGroup ref="tableRef" />
</div>
</template>
<script setup lang="tsx">
import { ref, onMounted, provide, reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import Area from '@/components/form/area/index.vue'
defineOptions({
name: 'voltage/sags/operationsManagement/point'
})
const dictData = useDictData()
const interferenceSource = dictData.getBasicData('Interference_Source')
const level = dictData.getBasicData('Dev_Voltage_Stand')
const interferenceSourceForm = ref<string[]>([])
const scaleForm = ref<string[]>([])
const tableStore = new TableStore({
isWebPaging: true,
url: '/device-boot/runManage/getLineLedger',
method: 'POST',
column: [
{ field: 'areaName', title: '省公司', width: 120 },
{ field: 'gdName', title: '市公司', width: 120 },
{ field: 'scale', title: '监测点电压等级', width: 150 },
{ field: 'lineName', title: '监测点名称', width: 120 },
{ field: 'bdName', title: '所属变电站', width: 120 },
{ field: 'loadType', title: '干扰源类型', width: 120 },
{ field: 'objName', title: '监测对象名称', width: 180 },
{ field: 'shortCapacity', title: '最小短路容量(MVA)', width: 190 },
{ field: 'devCapacity', title: '供电设备容量(MVA )', width: 190 },
{ field: 'dealCapacity', title: '用户协议容量(MVA)', width: 190 },
{ field: 'comFlag', title: '通讯状态 ', width: 120 },
{ field: 'id', title: '监测点序号', width: 120 },
{ field: 'devName', title: '监测终端编号 ', width: 140 },
{ field: 'ptType', title: '监测终端接线方式', width: 160 },
{ field: 'voltageDev', title: '电压偏差上限(%)', width: 160 },
{ field: 'uvoltageDev', title: '电压偏差下限(%)', width: 160 },
{
field: 'limitValue',
title: '限值',
children: [
{ field: 'freqDev', title: '频率(Hz)', width: 120 },
{ field: 'ubalance', title: '三相电压不平衡度(%)', width: 190 },
{ field: 'ineg', title: '负序电流(A)', width: 120 },
{ field: 'flicker', title: '长时闪变', width: 120 },
{ field: 'uaberrance', title: '电压总谐波畸变率(%)', width: 190 },
{ field: 'oddHarm', title: '奇数次谐波电压(%)', width: 180 },
{ field: 'evenHarm', title: '偶数次谐波电压(%)', width: 180 }
]
},
{
field: 'evaluate',
title: '电流限值',
children: [
{ field: 'iharm2', title: '2次谐波(A)', width: 120 },
{ field: 'iharm3', title: '3次谐波(A)', width: 120 },
{ field: 'iharm4', title: '4次谐波(A)', width: 120 },
{ field: 'iharm5', title: '5次谐波(A)', width: 120 },
{ field: 'iharm6', title: '6次谐波(A)', width: 120 },
{ field: 'iharm7', title: '7次谐波(A)', width: 120 },
{ field: 'iharm8', title: '8次谐波(A)', width: 120 },
{ field: 'iharm9', title: '9次谐波(A)', width: 120 },
{ field: 'iharm10', title: '10次谐波(A)', width: 140 },
{ field: 'iharm11', title: '11次谐波(A)', width: 140 },
{ field: 'iharm12', title: '12次谐波(A)', width: 140 },
{ field: 'iharm13', title: '13次谐波(A)', width: 140 },
{ field: 'iharm14', title: '14次谐波(A)', width: 140 },
{ field: 'iharm15', title: '15次谐波(A)', width: 140 },
{ field: 'iharm16', title: '16次谐波(A)', width: 140 },
{ field: 'iharm17', title: '17次谐波(A)', width: 140 },
{ field: 'iharm18', title: '18次谐波(A)', width: 140 },
{ field: 'iharm19', title: '19次谐波(A)', width: 140 },
{ field: 'iharm10', title: '20次谐波(A)', width: 140 },
{ field: 'iharm21', title: '21次谐波(A)', width: 140 },
{ field: 'iharm22', title: '22次谐波(A)', width: 140 },
{ field: 'iharm23', title: '23次谐波(A)', width: 140 },
{ field: 'iharm24', title: '24次谐波(A)', width: 140 },
{ field: 'iharm25', title: '25次谐波(A)', width: 140 },
{ field: 'inUharm', title: '0.5-1.5次间谐波(A)', width: 180 },
{ field: 'inUharm16', title: '2.5-15.5次间谐波(A)', width: 190 }
]
}
],
resetCallback: () => {
interferenceSourceForm.value = []
scaleForm.value = []
}
})
tableStore.table.params.scale = []
tableStore.table.params.comFlag = []
tableStore.table.params.loadType = []
tableStore.table.params.statisticalType = {}
tableStore.table.params.serverName = 'event-boot'
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
const onLoadTypeChange = () => {
tableStore.table.params.loadType = interferenceSource
.filter(item => {
return interferenceSourceForm.value.includes(item.id)
})
.map(item => {
return { ...item, label: item.name, value: item.id }
})
}
const onScaleChange = () => {
tableStore.table.params.scale = level
.filter(item => {
return scaleForm.value.includes(item.id)
})
.map(item => {
return { ...item, label: item.name, value: item.id }
})
}
</script>
<template>
<div class="default-main">
<TableHeader date-picker area>
<template v-slot:select>
<el-form-item label="干扰源类型">
<el-select multiple clearable collapse-tags v-model.trim="interferenceSourceForm" placeholder="请选择"
@change="onLoadTypeChange">
<el-option v-for="item in interferenceSource" :key="item.id" :label="item.name"
:value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="电压等级">
<el-select multiple clearable collapse-tags v-model.trim="scaleForm" placeholder="请选择"
@change="onScaleChange">
<el-option v-for="item in level" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="通讯状态">
<el-select multiple clearable collapse-tags v-model.trim="tableStore.table.params.comFlag"
placeholder="请选择">
<el-option label="正常" value="1" />
<el-option label="中断" value="0" />
</el-select>
</el-form-item>
<el-form-item label="关键字筛选">
<el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue"
placeholder="根据变电站,终端编号,型号或网络参数查询" />
</el-form-item>
</template>
</TableHeader>
<Table isGroup ref="tableRef" />
</div>
</template>
<script setup lang="tsx">
import { ref, onMounted, provide, reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import Area from '@/components/form/area/index.vue'
defineOptions({
name: 'voltage/sags/operationsManagement/point'
})
const dictData = useDictData()
const interferenceSource = dictData.getBasicData('Interference_Source')
const level = dictData.getBasicData('Dev_Voltage_Stand')
const interferenceSourceForm = ref<string[]>([])
const scaleForm = ref<string[]>([])
const tableStore = new TableStore({
isWebPaging: true,
url: '/device-boot/runManage/getLineLedger',
method: 'POST',
column: [
{ field: 'areaName', title: '省公司', width: 120 },
{ field: 'gdName', title: '市公司', width: 120 },
{ field: 'scale', title: '监测点电压等级', width: 150 },
{ field: 'lineName', title: '监测点名称', width: 120 },
{ field: 'bdName', title: '所属变电站', width: 120 },
{ field: 'loadType', title: '干扰源类型', width: 120 },
{ field: 'objName', title: '监测对象名称', width: 180 },
{ field: 'shortCapacity', title: '最小短路容量(MVA)', width: 190 },
{ field: 'devCapacity', title: '供电设备容量(MVA )', width: 190 },
{ field: 'dealCapacity', title: '用户协议容量(MVA)', width: 190 },
{ field: 'comFlag', title: '通讯状态 ', width: 120 },
{ field: 'id', title: '监测点序号', width: 120 },
{ field: 'devName', title: '监测终端编号 ', width: 140 },
{ field: 'ptType', title: '监测终端接线方式', width: 160 },
{ field: 'voltageDev', title: '电压偏差上限(%)', width: 160 },
{ field: 'uvoltageDev', title: '电压偏差下限(%)', width: 160 },
{
field: 'limitValue',
title: '限值',
children: [
{ field: 'freqDev', title: '频率(Hz)', width: 120 },
{ field: 'ubalance', title: '三相电压不平衡度(%)', width: 190 },
{ field: 'ineg', title: '负序电流(A)', width: 120 },
{ field: 'flicker', title: '长时闪变', width: 120 },
{ field: 'uaberrance', title: '电压总谐波畸变率(%)', width: 190 },
{ field: 'oddHarm', title: '奇数次谐波电压(%)', width: 180 },
{ field: 'evenHarm', title: '偶数次谐波电压(%)', width: 180 }
]
},
{
field: 'evaluate',
title: '电流限值',
children: [
{ field: 'iharm2', title: '2次谐波(A)', width: 120 },
{ field: 'iharm3', title: '3次谐波(A)', width: 120 },
{ field: 'iharm4', title: '4次谐波(A)', width: 120 },
{ field: 'iharm5', title: '5次谐波(A)', width: 120 },
{ field: 'iharm6', title: '6次谐波(A)', width: 120 },
{ field: 'iharm7', title: '7次谐波(A)', width: 120 },
{ field: 'iharm8', title: '8次谐波(A)', width: 120 },
{ field: 'iharm9', title: '9次谐波(A)', width: 120 },
{ field: 'iharm10', title: '10次谐波(A)', width: 140 },
{ field: 'iharm11', title: '11次谐波(A)', width: 140 },
{ field: 'iharm12', title: '12次谐波(A)', width: 140 },
{ field: 'iharm13', title: '13次谐波(A)', width: 140 },
{ field: 'iharm14', title: '14次谐波(A)', width: 140 },
{ field: 'iharm15', title: '15次谐波(A)', width: 140 },
{ field: 'iharm16', title: '16次谐波(A)', width: 140 },
{ field: 'iharm17', title: '17次谐波(A)', width: 140 },
{ field: 'iharm18', title: '18次谐波(A)', width: 140 },
{ field: 'iharm19', title: '19次谐波(A)', width: 140 },
{ field: 'iharm10', title: '20次谐波(A)', width: 140 },
{ field: 'iharm21', title: '21次谐波(A)', width: 140 },
{ field: 'iharm22', title: '22次谐波(A)', width: 140 },
{ field: 'iharm23', title: '23次谐波(A)', width: 140 },
{ field: 'iharm24', title: '24次谐波(A)', width: 140 },
{ field: 'iharm25', title: '25次谐波(A)', width: 140 },
{ field: 'inUharm', title: '0.5-1.5次间谐波(A)', width: 180 },
{ field: 'inUharm16', title: '2.5-15.5次间谐波(A)', width: 190 }
]
}
],
resetCallback: () => {
interferenceSourceForm.value = []
scaleForm.value = []
}
})
tableStore.table.params.scale = []
tableStore.table.params.comFlag = []
tableStore.table.params.loadType = []
tableStore.table.params.statisticalType = {}
tableStore.table.params.serverName = 'event-boot'
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
const onLoadTypeChange = () => {
tableStore.table.params.loadType = interferenceSource
.filter(item => {
return interferenceSourceForm.value.includes(item.id)
})
.map(item => {
return { ...item, label: item.name, value: item.id }
})
}
const onScaleChange = () => {
tableStore.table.params.scale = level
.filter(item => {
return scaleForm.value.includes(item.id)
})
.map(item => {
return { ...item, label: item.name, value: item.id }
})
}
</script>