Files
admin-govern/src/views/govern/cloudDeviceEntry/index.vue

2365 lines
91 KiB
Vue
Raw Normal View History

2025-10-11 10:35:25 +08:00
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size">
2025-10-17 14:37:31 +08:00
<CloudDeviceEntryTree ref="TerminalRef" @node-click="nodeClick" @init="nodeClick" @onAdd="onAdd"></CloudDeviceEntryTree>
2025-10-11 10:35:25 +08:00
</pane>
<pane style="background: #fff">
<div class="device-manage-right">
<el-form :inline="true" class="demo-form-inline" style="height: 42px">
<el-form-item style="position: relative; z-index: 2" >
<el-button icon="el-icon-Plus" type="primary" @click="add" v-if="nodeLevel != 4">
{{
nodeLevel == 0
? '新增工程'
: nodeLevel == 1
? '新增项目'
: nodeLevel == 2
? '新增设备'
: nodeLevel == 3
? '新增监测点'
: '新增'
}}
</el-button>
<el-button icon="el-icon-Edit" type="primary" @click="update" v-if="nodeLevel != 0">
修改
</el-button>
<el-button icon="el-icon-Close" type="danger" @click="remove" v-if="nodeLevel != 0">
删除
</el-button>
<el-button
icon="el-icon-Right"
:disabled="nextfalg"
type="primary"
@click="next"
v-if="nodeLevel != 4 && pageStatus == 2"
>
下一步
</el-button>
<el-button
type="info"
@click="black"
icon="el-icon-Back"
v-if="pageStatus == 2 || pageStatus == 3"
>
</el-button>
<el-button icon="el-icon-Check" type="primary" v-if="pageStatus == 2" @click="onsubmit">
确认提交
</el-button>
<el-button icon="el-icon-Check" type="primary" v-if="pageStatus == 3" @click="onsubmit">
修改提交
</el-button>
</el-form-item>
<el-form-item style="right: 500px; position: absolute; overflow: hidden">
<LocationInformation style="width: 16px; margin-right: 8px; color: var(--el-color-primary)" />
<span style="font-size: 16px; font-weight: bold; color: var(--el-color-primary)">当前操作节点</span>
</el-form-item>
<el-form-item style="right: 0; position: absolute; overflow: hidden">
<div class="title" :class="titleList.length > 5 ? 'titleScroll' : ''">
<span v-for="(item, index) in titleList" :key="index">{{ index == 0 ? '' : ' > ' }}{{ item }}</span>
</div>
</el-form-item>
</el-form>
<div id="scrollBox" :style="{ height: Height.height }" style="overflow-y: auto">
<el-form
class="main-form overview_scroll"
:label-position="'right'"
label-width="120px"
:inline="true"
ref="mainForm"
2025-10-17 09:55:43 +08:00
2025-10-11 10:35:25 +08:00
>
<el-form-item
id="id100"
class="form-item"
label="设备名称:"
:rules="{ required: true, message: '请输入设备名称', trigger: 'blur' }"
>
<el-select
filterable
v-model="project[2].name"
:disabled="true"
placeholder="请选择设备类型"
>
<el-option
v-for="item in project"
:key="item.name"
:label="item.name"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<!--工程-->
<!-- 省下拉框 -->
<el-form-item
id="id200"
class="form-item"
label="省:"
v-if="nodeLevel > 0 || pageStatus == 2"
2025-10-17 14:37:31 +08:00
2025-10-17 09:55:43 +08:00
:rules="{ required: true, message: '请选择省', trigger: 'change' }"
2025-10-11 10:35:25 +08:00
>
<el-select
2025-10-17 09:55:43 +08:00
filterable
v-model="engineeringParam.province"
:disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))"
placeholder="请选择省"
@change="provinceChange"
2025-10-11 10:35:25 +08:00
>
<el-option
v-for="item in provinceOptions"
:key="item.value"
:label="item.text"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<!-- 市下拉框 -->
<el-form-item
id="id200"
class="form-item"
label="市:"
v-if="(nodeLevel > 0 || pageStatus == 2)"
2025-10-17 14:37:31 +08:00
2025-10-17 09:55:43 +08:00
:rules="{ required: true, message: '请选择市', trigger: 'change' }"
2025-10-11 10:35:25 +08:00
>
<el-select
filterable
v-model="engineeringParam.city"
:disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))"
placeholder="请选择市"
>
<el-option
v-for="item in cityOptions"
:key="item.value"
:label="item.text"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
id="id300"
class="form-item"
label="工程名称:"
v-if="nodeLevel > 0 || pageStatus == 2"
2025-10-17 09:55:43 +08:00
:prop="'name'"
:rules="{ required: true, message: '请输入工程名称', trigger: 'blur' }"
2025-10-11 10:35:25 +08:00
>
<el-input
v-model="engineeringParam.name"
placeholder="请输入工程名称"
:disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))"
></el-input>
</el-form-item>
<el-form-item
id="id300"
class="form-item"
label="描述:"
v-if="nodeLevel > 0 || pageStatus == 2"
>
<el-input
v-model="engineeringParam.description"
placeholder="请输入描述"
:disabled="!((nodeLevel == 1 && pageStatus == 3) || (nodeLevel == 0 && pageStatus == 2))"
></el-input>
</el-form-item>
<!--项目-->
<div style="width: 100%" v-if="nodeLevel > 0 || pageStatus == 2">
<el-tabs
v-model="deviceIndex"
type="card"
2025-10-17 09:55:43 +08:00
:addable="false"
:closable="pageStatus != 1"
2025-10-11 10:35:25 +08:00
@edit="handleDeviceTabsEdit"
@tab-click="tabChange('deviceIndex')"
>
<el-tab-pane
v-for="(item, index) in projectInfoList"
:key="index"
:label="item.name ? item.name : '新建项目' + index"
:name="index + ''"
>
<div class="flex mt10">
<el-form-item
class="form-item"
label="项目名称:"
:rules="[{ required: true, message: '请输入项目名称', trigger: 'blur' }]"
>
<el-input
v-model="item.name"
placeholder="请输入项目名称"
:disabled="!((nodeLevel == 2 && pageStatus == 3) || ((nodeLevel == 1 || (nodeLevel == 0 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
<el-form-item
class="form-item"
label="地市:"
:rules="[{ required: true, message: '请输入地市', trigger: 'blur' }]"
>
<el-input
v-model="item.area"
placeholder="请输入地市"
:disabled="!((nodeLevel == 2 && pageStatus == 3) || ((nodeLevel == 1 || (nodeLevel == 0 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
<el-form-item
class="form-item"
label="描述:"
:rules="[{ required: true, message: '请输入描述', trigger: 'blur' }]"
>
<el-input
v-model="item.description"
placeholder="请输入描述"
:disabled="!((nodeLevel == 2 && pageStatus == 3) || ((nodeLevel == 1 || (nodeLevel == 0 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
</div>
</el-tab-pane>
</el-tabs>
</div>
<!--设备-->
2025-10-17 09:55:43 +08:00
<div style="width: 100%" v-if="(nodeLevel > 1 || pageStatus == 2) && (nodeLevel >= 2 || pageStatus == 2)">
2025-10-11 10:35:25 +08:00
<el-tabs
v-model="busBarIndex"
type="card"
2025-10-17 09:55:43 +08:00
:addable="false"
:closable="pageStatus != 1"
2025-10-11 10:35:25 +08:00
@edit="handleBusBarTabsEdit"
@tab-click="tabChange('busBarIndex')"
>
<el-tab-pane
v-for="(busItem, bIndex) in deviceInfoList"
:key="bIndex"
:label="busItem.name ? busItem.name : '新建装置' + bIndex"
:name="bIndex + ''"
>
<div class="flex mt10">
<el-form-item
class="form-item"
label="装置名称:"
:rules="[{ required: true, message: '请输入装置名称', trigger: 'blur' }]"
>
<el-input
v-model="busItem.name"
placeholder="请输入装置名称"
:disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
<el-form-item
id="id200"
class="form-item"
label="装置类型:"
:rules="[{ required: true, message: '请选择装置类型', trigger: 'change' }]"
>
<el-select
filterable
v-model="busItem.devType"
placeholder="请选择装置类型"
style="width: 100%"
:disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option
v-for="item in formDevTypeOptions"
:key="item.value"
:label="item.label || item.name"
:value="item.value || item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
id="id200"
class="form-item"
label="装置型号:"
:rules="[{ required: true, message: '请选择装置型号', trigger: 'change' }]"
>
<el-select
filterable
v-model="busItem.devModel"
placeholder="请选择装置型号"
style="width: 100%"
:disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option
v-for="option in devCLD"
:key="option.id"
:label="option.name"
:value="option.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
id="id200"
class="form-item"
label="装置接入方式:"
:rules="[{ required: true, message: '请选择装置接入方式', trigger: 'change' }]"
>
<el-select
filterable
v-model="busItem.devAccessMethod"
placeholder="请选择装置接入方式"
style="width: 100%"
:disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option label="CLD" value="CLD"></el-option>
</el-select>
</el-form-item>
<el-form-item
2025-10-20 09:42:01 +08:00
2025-10-11 10:35:25 +08:00
class="form-item"
label="装置mac地址:"
:rules="{ required: true, message: '请输入装置mac地址', trigger: 'blur' }"
>
<MacAddressInput v-model="busItem.mac" :disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"/>
</el-form-item>
<!-- <el-form-item
class="form-item"
label="网络设备ID:"
:rules="[{ required: true, message: '请输入网络设备ID', trigger: 'blur' }]"
>
<el-input
v-model="busItem.ndid"
disabled
placeholder="请输入网络设备ID"
></el-input>
</el-form-item> -->
2025-10-17 14:37:31 +08:00
<el-form-item class="form-item" label="合同号:">
<el-input
v-model="busItem.cntractNo"
placeholder="请输入合同号"
:disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
2025-10-11 10:35:25 +08:00
<el-form-item
class="form-item"
label="所属前置机:"
:rules="[
{ required: true, message: '请选择所属前置机', trigger: 'change' }
]"
>
<el-select
filterable
v-model="busItem.nodeId"
placeholder="请选择所属前置机"
2025-10-17 14:37:31 +08:00
:disabled="!(pageStatus == 2 && nodeLevel >= 2)"
2025-10-11 10:35:25 +08:00
>
<el-option
v-for="option in affiliatiedFrontArr"
:key="option.id"
:label="option.name"
:value="option.id"
></el-option>
</el-select>
</el-form-item>
2025-10-17 14:37:31 +08:00
<el-form-item class="form-item" label="进程号:">
2025-10-11 10:35:25 +08:00
<el-input
2025-10-17 14:37:31 +08:00
v-model="busItem.nodeProcess"
placeholder="自动分配"
:disabled="true"
2025-10-11 10:35:25 +08:00
></el-input>
</el-form-item>
2025-10-17 14:37:31 +08:00
2025-10-11 10:35:25 +08:00
<el-form-item
class="form-item"
label="排序:"
:rules="[{ required: true, message: '请输入排序', trigger: 'blur' }]"
>
<el-input
v-model="busItem.sort"
placeholder="请输入排序"
:disabled="!((nodeLevel == 3 && pageStatus == 3) || ((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
</div>
</el-tab-pane>
</el-tabs>
</div>
<!--监测点-->
2025-10-17 09:55:43 +08:00
<div style="width: 100%" v-if="(nodeLevel > 2 || pageStatus == 2) && (nodeLevel >= 3 || pageStatus == 2)">
2025-10-11 10:35:25 +08:00
<el-tabs
type="card"
v-model="lineIndex"
2025-10-17 09:55:43 +08:00
:addable="false"
:closable="pageStatus != 1"
2025-10-11 10:35:25 +08:00
@edit="handleLineTabsEdit"
@tab-click="tabChange('lineIndex')"
>
<el-tab-pane
v-for="(lineItem, lIndex) in lineInfoList"
:key="lIndex"
:label="lineItem.name ? lineItem.name : '新建监测点' + lIndex"
:name="lIndex + ''"
>
<div class="flex mt10">
<el-form-item
class="form-item"
label="监测点名称:"
:rules="{
required: true,
message: '请输入监测点名称',
trigger: 'blur'
}"
>
<el-input
v-model="lineItem.name"
placeholder="请输入监测点名称"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</el-form-item>
<el-form-item
class="form-item"
label="线路号:"
:rules="{
required: true,
message: '请选择线路号',
trigger: 'blur'
}"
>
<el-select
filterable
v-model="lineItem.lineNo"
placeholder="请选择线路号"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option
v-for="option in pointNumArr"
:key="option.name"
:label="option.name"
:value="option.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
class="form-item"
label="接线方式:"
:rules="{ required: true, message: '请选择接线方式', trigger: 'blur' }"
>
<el-select
filterable
v-model="lineItem.conType"
placeholder="请选择接线方式"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option
v-for="option in wiringTypeArr"
:key="option.name"
:label="option.name"
:value="option.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
class="form-item"
label="统计间隔:"
:rules="{ required: true, message: '请选择统计间隔', trigger: 'blur' }"
>
<el-select
filterable
v-model="lineItem.lineInterval"
placeholder="请选择统计间隔"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option
v-for="option in lineSpaceArr"
:key="option.name"
:label="option.name"
:value="option.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
class="form-item"
label="PT变比:"
:rules="{ required: true, message: '请输入pt', trigger: 'blur' }"
>
<div style="width: 100%; display: flex; justify-content: space-between">
<el-input
style="width: 48%"
v-model="lineItem.ptRatio"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
<span style="display: flex; align-items: center; justify-content: center;">:</span>
<el-input
style="width: 48%"
v-model="lineItem.pt2Ratio"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</div>
</el-form-item>
<el-form-item
class="form-item"
label="CT变比:"
:rules="{ required: true, message: '请输入ct', trigger: 'blur' }"
>
<div style="width: 100%; display: flex; justify-content: space-between">
<el-input
style="width: 48%"
v-model="lineItem.ctRatio"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
<span style="display: flex; align-items: center; justify-content: center;">:</span>
<el-input
style="width: 48%"
v-model="lineItem.ct2Ratio"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
></el-input>
</div>
</el-form-item>
<el-form-item
class="form-item"
label="电压等级:"
:rules="{ required: true, message: '请选择电压等级', trigger: 'blur' }"
>
<el-select
filterable
v-model="lineItem.volGrade"
placeholder="请选择电压等级"
:disabled="!((nodeLevel == 4 && pageStatus == 3) || ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && pageStatus == 2))"
>
<el-option
v-for="option in voltageLevelOptions"
:key="option.value"
:label="option.name"
:value="option.value"
>
</el-option>
</el-select>
</el-form-item>
</div>
</el-tab-pane>
</el-tabs>
</div>
</el-form>
</div>
</div>
</pane>
</splitpanes>
2025-10-17 14:37:31 +08:00
<el-dialog
v-model="resultDialogVisible"
title="台账推送结果"
width="50%"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="true"
@close="handleDialogClose"
>
<div v-if="pushResult" style="padding: 20px;">
<el-result
:icon="pushResult.success ? 'success' : 'error'"
:title="pushResult.success ? '推送成功' : '推送失败'"
:sub-title="pushResult.message"
>
</el-result>
<!-- 日志展示区域 -->
<div style="margin-top: 20px;">
<h3>推送日志:</h3>
<div style="max-height: 300px; overflow-y: auto; border: 1px solid #ebeef5; border-radius: 4px; padding: 10px;">
<div
v-for="(log, index) in pushResult.logs"
:key="index"
style="padding: 5px 0; border-bottom: 1px solid #f0f0f0;"
>
<span style="margin-left: 10px;">{{ log.message }}</span>
</div>
<div v-if="pushResult.logs.length === 0" style="text-align: center; color: #999; padding: 20px;">
暂无日志信息
</div>
</div>
</div>
</div>
<div v-else style="text-align: center; padding: 20px;">
2025-10-17 14:41:58 +08:00
<el-icon :size="40" class="is-loading" style="color: #409EFF;">
2025-10-17 14:37:31 +08:00
<Loading />
</el-icon>
<p style="margin-top: 15px; font-size: 16px;">正在推送台账信息请稍候...</p>
<p style="margin-top: 10px; color: #999;">预计需要30秒左右</p>
<p style="margin-top: 10px; color: #999;">已等待: {{ countdown }}</p>
</div>
</el-dialog>
2025-10-11 10:35:25 +08:00
</div>
</template>
<script setup lang="ts">
import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes'
import { LocationInformation } from '@element-plus/icons-vue'
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTree.vue'
import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
2025-10-17 14:37:31 +08:00
import {getById,getEngineerById,getProjectById,getEquipmentById,getInfoById,nodeAllList,addLedger,deleteProject,deleteLine,deleteEquipment,updateEquipment,updateLine,pushLog,queryPushResult} from '@/api/cs-device-boot/cloudDeviceEntry'
2025-10-11 10:35:25 +08:00
import tree from '@/assets/map/area.json'
import { queryByCode,queryCsDictTree } from '@/api/system-boot/dictTree'
import MacAddressInput from '@/components/form/mac/MacAddressInput.vue'
import { auditEngineering } from '@/api/cs-device-boot/edData'
import { convertToObject } from 'typescript'
2025-10-17 14:37:31 +08:00
import { Loading } from '@element-plus/icons-vue'
2025-10-11 10:35:25 +08:00
defineOptions({
name: '/cs-device-boot/cloudDeviceEntry'
})
const size = ref(0)
const TerminalRef = ref()
const pageHeight = mainHeight(20)
const Height = mainHeight(100)
const mainForm = ref()
const loading = ref(false)
const nextfalg = ref(false)
const dictData = useDictData()
const nodeLevel = ref(0)
const pageStatus = ref(1)
const titleList: any = ref([])
const nodeData: any = ref([])
const deviceIndex: any = ref('0')
const busBarIndex: any = ref('0')
const lineIndex: any = ref('0')
const projectId: any = ref('0')
const provinceId: any = ref('0')
const gdId: any = ref('0')
const subId: any = ref('0')
const devId: any = ref('0')
const busBarId: any = ref('0')
const lineId: any = ref('0')
const currentGdName: any = ref('')
const affiliatiedFrontArr: any = ref([])
const voltageLevelArr = dictData.getBasicData('Dev_Voltage_Stand')
const devCLD = ref<{ id: string; name: string }[] | null>(null)
const devTypeOptions = ref<{ id: string; name: string }[] | null>(null)
const devTypeOptions2: any = ref([])
const treeClickCount = ref(0)
const areaTree: any = tree
const project = ref([
{ name: '治理设备', value: '治理设备' },
{ name: '便携式设备', value: '便携式设备' },
2025-10-14 09:51:42 +08:00
{ name: '在线设备', value: '在线设备' }
2025-10-11 10:35:25 +08:00
])
const wiringTypeArr = ref([
{ name: '星型接线', value: 0 },
{ name: '三角型接线', value: 1 },
{ name: '开口三角型接线', value: 2 }
])
/**监测点序号 */
const pointNumArr = ref([
{ name: '1', value: 1 },
{ name: '2', value: 2 },
{ name: '3', value: 3 },
{ name: '4', value: 4 },
{ name: '5', value: 5 },
{ name: '6', value: 6 }
])
/**监测点间隔 */
const lineSpaceArr = ref([
{ name: '1分钟', value: 1 },
{ name: '3分钟', value: 3 },
{ name: '5分钟', value: 5 },
{ name: '10分钟', value: 10 }
])
//工程
const engineeringParam = ref({
city: '',
description: '',
name: '',
province: ''
})
interface ProjectInfo {
name: string
area: string
description: string
}
// 项目信息列表
const projectInfoList = ref<ProjectInfo[]>([])
interface DeviceInfo {
name: string
devModel: string
devType: string
devAccessMethod: string
mac: string
ndid: string
nodeId: string
cntractNo: string
sort: number
2025-10-20 09:42:01 +08:00
nodeProcess:string
2025-10-11 10:35:25 +08:00
}
// 设备信息列表
const deviceInfoList = ref<DeviceInfo[]>([])
interface LineInfo {
name: string
lineNo: number
conType: number
lineInterval: number
ptRatio: number
pt2Ratio: number
ctRatio: number
ct2Ratio: number
volGrade: number | string
devMac: string
2025-10-17 14:37:31 +08:00
2025-10-11 10:35:25 +08:00
}
// 监测点信息列表
const lineInfoList = ref<LineInfo[]>([])
const arrdess: any = ref((rule: any, value: any, callback: any) => {
let reg1 =
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
let reg2 =
/^[A-Fa-f0-9]{1,2}\-[A-Fa-f0-9]{1,2}\-[A-Fa-f0-9]{1,2}\-[A-Fa-f0-9]{1,2}\-[A-Fa-f0-9]{1,2}\-[A-Fa-f0-9]{1,2}$/
let reg3 =
/^[A-Fa-f0-9]{1,2}\:[A-Fa-f0-9]{1,2}\:[A-Fa-f0-9]{1,2}\:[A-Fa-f0-9]{1,2}\:[A-Fa-f0-9]{1,2}\:[A-Fa-f0-9]{1,2}$/
if (reg1.test(value)) {
return true
} else if (reg2.test(value)) {
return true
} else if (reg3.test(value)) {
return true
} else if (value == '') {
return callback(new Error('请输入IP/MAC地址'))
} else {
callback(new Error('请输入正确IP/MAC地址'))
}
})
// 省市选择相关数据
const provinceOptions = computed(() => areaTree)
const cityOptions = computed(() => {
if (engineeringParam.value.province) {
const province = areaTree.find((item: any) => item.value === engineeringParam.value.province)
return province ? province.children : []
}
return []
})
const formDevTypeOptions = computed(() => {
return [devTypeOptions2.value]
})
// 电压等级选项,用于显示带单位的名称
const voltageLevelOptions = computed(() => {
// 确保 voltageLevelArr.value 是数组
if (!Array.isArray(voltageLevelArr)) {
return []
}
return voltageLevelArr.map((item: any) => {
return {
...item,
name: `${item.value}kV` // 优先使用code字段如果没有则构造带单位的名称
}
})
})
// 省改变时清空市的选择
const provinceChange = () => {
engineeringParam.value.city = ''
}
// 临时存储所有层级的数据
const tempAllLevelData = ref<any>({
engineering: null,
projects: [],
devices: [],
lines: []
})
const nodeDataList=ref()
const nodeEventList=ref()
const nodeClick = (e: anyObj, data: any) => {
nodeDataList.value = data
nodeEventList.value = e
treeClickCount.value++
if (treeClickCount.value > 2) return
if (treeClickCount.value == 1) {
if (pageStatus.value == 2 || pageStatus.value == 3) {
if (pageStatus.value == 3 || pageStatus.value == 2) {
ElMessage({
type: 'warning',
message: '请先提交,再做操作'
})
}
return
}
}
titleList.value = []
getparentsNode(data)
pageStatus.value = 1
nodeData.value = e
if(nodeData.value.level == 0){
nodeLevel.value = 0
}else if(nodeData.value.level == 1){//工程节点
nodeLevel.value = 1
}else if(nodeData.value.level == 2){//项目
nodeLevel.value = 2
}else if(nodeData.value.level == 3){ //设备
nodeLevel.value = 3
}else if(nodeData.value.level == 4){ //监测点
nodeLevel.value = 4
}
2025-10-17 14:37:31 +08:00
// 更新 nextfalg 状态
nextfalg.value = nodeLevel.value >= 4;
2025-10-17 09:55:43 +08:00
// 根据节点层级清理不需要的数据
cleanUnnecessaryData()
2025-10-11 10:35:25 +08:00
/**不是根节点请求数据 */
queryNodeContent()
treeClickCount.value = 0
}
2025-10-17 09:55:43 +08:00
2025-10-17 14:37:31 +08:00
const countdown = ref(0)
const resultDialogVisible = ref(false)
const pushResult = ref<{
success: boolean;
message: string;
logs: Array<{message: string }>
} | null>(null)
const timer = ref<number | null>(null)
const handleDialogClose = () => {
pushResult.value = null
resultDialogVisible.value = false
if (timer.value) {
clearInterval(timer.value)
timer.value = null
}
countdown.value = 0
}
const onAdd = async () => {
resultDialogVisible.value = true
pushResult.value = null
countdown.value = 0
// 启动倒计时
if (timer.value) clearInterval(timer.value)
timer.value = window.setInterval(() => {
countdown.value++
if (countdown.value >= 30) {
clearInterval(timer.value!)
timer.value = null
}
}, 1000)
try {
// 调用推送日志接口
2025-10-20 09:42:01 +08:00
const pushLogResponse = await pushLog()
2025-10-17 14:37:31 +08:00
2025-10-20 09:42:01 +08:00
// 检查返回的data是否为"暂无需要推送的数据"
if (pushLogResponse.data != "成功") {
// 直接提示用户没有数据推送
pushResult.value = {
success: false,
message: '暂无需要推送的数据',
logs: [{
message: '暂无需要推送的数据'
}]
}
return;
2025-10-17 14:37:31 +08:00
}
2025-10-20 09:42:01 +08:00
// 如果data不是"暂无需要推送的数据",则继续执行
if (pushLogResponse.data === "成功") {
// 等待30秒
await new Promise(resolve => setTimeout(resolve, 30000))
// 30秒后调用查询推送结果接口
const result = await queryPushResult()
// 处理返回的日志数据
const logs = Array.isArray(result.data) ? result.data : []
// 根据结果进行处理
pushResult.value = {
success: true,
message: '台账推送成功',
logs: logs.map((item: any) => ({
message: item.message || JSON.stringify(item)
}))
}
}
2025-10-17 14:37:31 +08:00
} catch (error: any) {
pushResult.value = {
success: false,
message: error.message || '推送过程中发生错误',
logs: [{
message: error.message || '未知错误'
}]
}
} finally {
if (timer.value) {
clearInterval(timer.value)
timer.value = null
}
countdown.value = 0
}
}
2025-10-17 09:55:43 +08:00
/**
* 根据当前节点层级清理不需要的数据
*/
const cleanUnnecessaryData = () => {
// 根据当前节点层级清理不需要的数据
switch(nodeLevel.value) {
case 0: // 根节点
// 清理所有数据
projectInfoList.value = []
deviceInfoList.value = []
lineInfoList.value = []
break
case 1: // 工程节点
// 清理设备和监测点数据
deviceInfoList.value = []
lineInfoList.value = []
break
case 2: // 项目节点
// 清理监测点数据
lineInfoList.value = []
break
case 3: // 设备节点
// 不清理任何数据
break
case 4: // 监测点节点
// 不清理任何数据
break
}
// 重置tab索引
if (nodeLevel.value < 2) {
deviceIndex.value = '0'
}
if (nodeLevel.value < 3) {
busBarIndex.value = '0'
}
if (nodeLevel.value < 4) {
lineIndex.value = '0'
}
}
2025-10-11 10:35:25 +08:00
const getparentsNode = (node: any) => {
// 检查node是否存在以及是否有parent属性
if (!node || !node.parent) {
return
}
titleList.value.unshift(node.label)
getparentsNode(node.parent) //调用递归
}
/**查询节点内容 */
const queryNodeContent = () => {
if (nodeData.value.id == null) {
return
}
if(nodeLevel.value == 1){
getEngineerById(nodeData.value.id)
}else if(nodeLevel.value == 2){
getProjectById(nodeData.value.id)
}else if(nodeLevel.value == 3){
getEquipmentById(nodeData.value.id)
}else if(nodeLevel.value == 4){
getById(nodeData.value.id)
}
getInfoById(nodeData.value.id).then((res: any) => {
Object.assign(engineeringParam.value, res.data);
engineeringParam.value.name = res.data.engineeringName
engineeringParam.value.description = res.data.engineeringDescription
projectInfoList.value = res.data.projectInfoList || []
if (nodeLevel.value >= 2) {
deviceInfoList.value = res.data.deviceInfoList || []
}
if (nodeLevel.value >= 3) {
lineInfoList.value = res.data.lineInfoList || []
lineInfoList.value.map((item: any) => {
item.volGrade = item.volGrade + 'kV'
})
}
})
}
// 新增
const add = () => {
if (pageStatus.value == 2 || pageStatus.value == 3) {
ElMessage({
type: 'warning',
message: '请先提交修改,再新增'
})
return
}
pageStatus.value = 2
// 根据当前节点层级添加对应的tab页
switch (nodeLevel.value) {
case 0: // 新增工程不需要添加tab
// 初始化工程参数
engineeringParam.value.city = ''
engineeringParam.value.description = ''
engineeringParam.value.name = ''
engineeringParam.value.province = ''
2025-10-17 09:55:43 +08:00
// 清理其他层级数据
projectInfoList.value = []
deviceInfoList.value = []
lineInfoList.value = []
2025-10-11 10:35:25 +08:00
break
case 1: // 新增项目添加一个新的项目tab
// 添加一个新的空项目到projectInfoList
projectInfoList.value.push({
name: '',
area: '',
description: ''
})
deviceIndex.value = (projectInfoList.value.length - 1).toString()
2025-10-17 09:55:43 +08:00
// 清理设备和监测点数据
deviceInfoList.value = []
lineInfoList.value = []
2025-10-11 10:35:25 +08:00
break
case 2: // 新增设备添加一个新的设备tab
// 添加一个新的空设备到deviceInfoList
deviceInfoList.value.push({
name: '',
devModel: '',
devType: '',
devAccessMethod: 'CLD',
mac: '',
ndid: '',
nodeId: '',
cntractNo: '',
2025-10-17 14:37:31 +08:00
sort: 0,
2025-10-20 09:42:01 +08:00
nodeProcess: '自动分配',
2025-10-11 10:35:25 +08:00
})
busBarIndex.value = (deviceInfoList.value.length - 1).toString()
2025-10-17 09:55:43 +08:00
// 清理监测点数据
lineInfoList.value = []
2025-10-11 10:35:25 +08:00
break
case 3: // 新增监测点添加一个新的监测点tab
// 添加一个新的空监测点到lineInfoList
lineInfoList.value.push({
name: '',
lineNo: 1,
conType: 0,
lineInterval: 1,
ptRatio: 0,
pt2Ratio: 0,
ctRatio: 0,
ct2Ratio: 0,
volGrade: '',
devMac:'',
})
lineIndex.value = (lineInfoList.value.length - 1).toString()
break
}
}
// 修改
const update = () => {
if (Object.keys(nodeData.value).length == 0) {
ElMessage({
type: 'warning',
message: '没有选中节点'
})
return
}
if (nodeData.value.level == 0) {
ElMessage({
type: 'warning',
message: '不能修改根节点'
})
return
}
if (pageStatus.value == 2 || pageStatus.value == 3) {
if (pageStatus.value == 2) {
ElMessage({
type: 'warning',
message: '请先新增完成在修改'
})
}
return
}
pageStatus.value = 3
// 使用 scrollTo 方法,并启用平滑滚动
const scrollBox: any = document.getElementById('scrollBox')
scrollBox.scrollTo({
top: scrollBox.scrollHeight, // 滚动到内容的最底部
behavior: 'smooth' // 启用平滑滚动动画
})
}
/**
* 修改工程
*/
const updateEngineering = (id: any) => {
// 获取工程信息
const engData = engineeringParam.value;
// 构建工程修改数据结构
const engineeringData = {
id: id, // 工程ID用于修改
city: engData.city,
description: engData.description,
name: engData.name,
province: engData.province,
};
auditEngineering(engineeringData).then((res: any) => {
ElMessage({
type: 'success',
message: '修改工程成功'
})
pageStatus.value = 1
TerminalRef.value.info()
})
}
/**
* 修改项目
*/
const updateProjectFunc = (id: any) => {
// 获取当前选中的项目信息
const currentProject = projectInfoList.value[deviceIndex.value];
if (!currentProject) {
ElMessage({
type: 'error',
message: '未找到项目信息'
});
return;
}
deleteProject(id,currentProject.name,currentProject.area, currentProject.description,1).then((res: any) => {
ElMessage({
type: 'success',
message: '修改项目成功'
})
pageStatus.value = 1
2025-10-17 09:55:43 +08:00
treedata()
2025-10-11 10:35:25 +08:00
})
}
/**
* 修改设备
*/
const updateEquipmentFunc = (id: any) => {
// 获取当前选中的设备信息
const currentDevice = deviceInfoList.value[busBarIndex.value];
if (!currentDevice) {
ElMessage({
type: 'error',
message: '未找到设备信息'
});
return;
}
// 构建与新增设备相同的结构体
const deviceData = {
id: id, // 设备ID用于修改
name: currentDevice.name,
devModel: currentDevice.devModel,
devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod,
mac: currentDevice.mac,
nodeId: currentDevice.nodeId,
cntractNo: currentDevice.cntractNo,
ndid: currentDevice.mac.replace(/:/g, ''),
sort: currentDevice.sort,
};
updateEquipment(deviceData).then((res: any) => {
ElMessage({
type: 'success',
message: '修改设备成功'
})
pageStatus.value = 1
TerminalRef.value.info()
})
}
/**
* 修改监测点
*/
const updateLineFunc = (id: any) => {
// 获取当前选中的监测点信息
const currentLine = lineInfoList.value[lineIndex.value];
if (!currentLine) {
ElMessage({
type: 'error',
message: '未找到监测点信息'
});
return;
}
// 处理电压等级,去除"kV"后缀
let volGradeValue = currentLine.volGrade;
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2);
}
// 获取设备MAC地址和设备ID
let devMac = '';
let devId = '';
if (deviceInfoList.value && deviceInfoList.value[busBarIndex.value]) {
devMac = deviceInfoList.value[busBarIndex.value].mac || '';
// 如果有设备ID也获取它
if (deviceInfoList.value[busBarIndex.value].id) {
devId = deviceInfoList.value[busBarIndex.value].id || '';
}
}
// 构建与新增监测点相同的结构体
const lineData = {
lineId: id,
name: currentLine.name || '',
lineNo: currentLine.lineNo || 1,
conType: currentLine.conType || 0,
lineInterval: currentLine.lineInterval || 1,
ptRatio: currentLine.ptRatio || 0,
pt2Ratio: currentLine.pt2Ratio || 0,
ctRatio: currentLine.ctRatio || 0,
ct2Ratio: currentLine.ct2Ratio || 0,
volGrade: volGradeValue || 0,
devMac: devMac,
devId: devId,
};
updateLine(lineData).then((res: any) => {
ElMessage({
type: 'success',
message: '修改监测点成功'
})
pageStatus.value = 1
2025-10-17 09:55:43 +08:00
treedata()
2025-10-11 10:35:25 +08:00
})
}
// 删除
const remove = () => {
if (Object.keys(nodeData.value).length == 0) {
ElMessage({
type: 'warning',
message: '没有选中节点'
})
return
}
if (nodeData.value.level == 0) {
ElMessage({
type: 'error',
message: '无法删除根节点'
})
return
}
if (nodeData.value.id == null) {
ElMessage.warning('无法删除该节点')
return
}
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
switch (nodeLevel.value) {
case 1:
let data = {
id: nodeData.value.id,
status: "0",
};
auditEngineering(data).then((res: any) => {
ElMessage({
type: 'success',
message: res.message
})
reaseStatus()
// 删除工程后选中根节点
setTimeout(() => {
treedata()
}, 100)
})
break;
case 2: // 项目层级
// 删除项目后选中工程节点
const engineeringId = nodeData.value.pids ? nodeData.value.pids.split(',')[1] : null
deleteProject(nodeData.value.id,'','','', 0).then((res: any) => {
ElMessage({
type: 'success',
message: res.message
})
reaseStatus()
2025-10-17 09:55:43 +08:00
console.log('engineeringId',engineeringId)
2025-10-11 10:35:25 +08:00
if (engineeringId) {
setTimeout(() => {
treedata(engineeringId)
}, 100)
} else {
treedata()
}
})
break;
case 3: // 设备层级
// 删除设备后选中项目节点
const projectId = nodeData.value.pids ? nodeData.value.pids.split(',')[2] : null
deleteEquipment(nodeData.value.id).then((res: any) => {
ElMessage({
type: 'success',
message: res.message
})
reaseStatus()
if (projectId) {
setTimeout(() => {
treedata(projectId)
}, 100)
} else {
treedata()
}
})
break;
case 4: // 监测点层级
const deviceId = nodeData.value.pids ? nodeData.value.pids.split(',')[3] : null
console.log(deviceId)
deleteLine(nodeData.value.id).then((res: any) => {
ElMessage({
type: 'success',
message: res.message
})
reaseStatus()
// 删除监测点后选中设备节点
if (deviceId) {
setTimeout(() => {
treedata(deviceId)
}, 100)
} else {
treedata()
}
})
break;
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
// 下一步
const next = async () => {
2025-10-17 09:55:43 +08:00
// 在新增模式下pageStatus == 2保存当前数据并创建下一个层级的Tab
switch (nodeLevel.value) {
case 0: // 工程层级下一步创建项目Tab
// 保存当前工程信息到临时存储
tempAllLevelData.value.engineering = { ...engineeringParam.value }
// 创建新的项目Tab
projectInfoList.value.push({
name: '',
area: '',
description: '',
})
deviceIndex.value = (projectInfoList.value.length - 1).toString()
nextfalg.value = false
nodeLevel.value = 1
break
case 1: // 项目层级下一步创建设备Tab
// 保存当前项目信息到临时存储
const currentProject = { ...projectInfoList.value[deviceIndex.value] }
tempAllLevelData.value.projects[deviceIndex.value] = currentProject
// 创建新的设备Tab
deviceInfoList.value.push({
name: '',
devModel: '',
devType: '',
devAccessMethod: 'CLD',
mac: '',
ndid: '',
nodeId: '',
cntractNo: '',
2025-10-17 14:37:31 +08:00
sort: 0,
2025-10-20 09:42:01 +08:00
nodeProcess: '自动分配',
2025-10-17 09:55:43 +08:00
})
busBarIndex.value = (deviceInfoList.value.length - 1).toString()
nextfalg.value = false
nodeLevel.value = 2
break
case 2: // 设备层级下一步创建监测点Tab
// 保存当前设备信息到临时存储
const currentDevice = { ...deviceInfoList.value[busBarIndex.value] }
tempAllLevelData.value.devices[busBarIndex.value] = currentDevice
// 创建新的监测点Tab
lineInfoList.value.push({
name: '',
lineNo: 1,
conType: 0,
lineInterval: 1,
ptRatio: 0,
pt2Ratio: 0,
ctRatio: 0,
ct2Ratio: 0,
volGrade: '',
devMac: '',
})
lineIndex.value = (lineInfoList.value.length - 1).toString()
2025-10-17 14:37:31 +08:00
nextfalg.value = true
2025-10-17 09:55:43 +08:00
nodeLevel.value = 3
break
case 3: // 监测点层级
// 保存当前监测点信息到临时存储
const currentLine = { ...lineInfoList.value[lineIndex.value] }
tempAllLevelData.value.lines[lineIndex.value] = currentLine
nextfalg.value = true
nodeLevel.value = 4
break
}
2025-10-17 14:37:31 +08:00
2025-10-11 10:35:25 +08:00
}
2025-10-17 14:37:31 +08:00
2025-10-11 10:35:25 +08:00
// 撤销
const black = () => {
pageStatus.value = 1
busBarIndex.value = '0'
deviceIndex.value = '0'
lineIndex.value = '0'
// 清空临时数据
tempAllLevelData.value = {
engineering: null,
projects: [],
devices: [],
lines: []
}
nodeClick(nodeEventList.value,nodeDataList.value)
}
// 确认提交
const onsubmit = () => {
if (pageStatus.value == 2) {
// 新增
// 检查是否是多层级新增还是单层级新增
if (tempAllLevelData.value.engineering !== null ||
tempAllLevelData.value.projects.length > 0 ||
tempAllLevelData.value.devices.length > 0 ||
tempAllLevelData.value.lines.length > 0) {
// 多层级新增,一次性提交所有数据
submitAllLevelData()
} else {
// 单层级新增,使用原有的提交方式
submitData()
}
} else if (pageStatus.value == 3) {
// 修改
switch (nodeLevel.value) {
case 1: // 修改工程
updateEngineering(nodeData.value.id)
break
case 2: // 修改项目
updateProjectFunc(nodeData.value.id)
break
case 3: // 修改设备
updateEquipmentFunc(nodeData.value.id)
break
case 4: // 修改监测点
updateLineFunc(nodeData.value.id)
break
}
}
}
/**
* 一次性提交所有层级数据
*/
const submitAllLevelData = () => {
let submitData: any = {}
// 根据当前节点层级构建相应的数据结构
switch (nodeLevel.value) {
case 0: // 只有工程
submitData = {
engineering: tempAllLevelData.value.engineering || { ...engineeringParam.value }
}
break
case 1: // 工程 + 项目
// 工程信息
const engineeringData = tempAllLevelData.value.engineering || { ...engineeringParam.value }
// 项目信息
const projectData = tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects[0]
: (projectInfoList.value[0] || {})
// 如果是从根节点开始新增工程和项目
if (nodeData.value.level === 0) {
submitData = {
engineering: engineeringData,
project: projectData
}
} else {
// 如果是从工程节点开始新增项目
submitData = {
engineeringIndex: nodeData.value?.id || "",
project: projectData
}
}
break
case 2: // 工程 + 项目 + 设备
// 工程信息
const engineeringData2 = tempAllLevelData.value.engineering || { ...engineeringParam.value }
// 项目信息
const projectData2 = tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects[0]
: (projectInfoList.value[0] || {})
// 设备信息
let devices = []
if (tempAllLevelData.value.devices.length > 0) {
devices = tempAllLevelData.value.devices.filter((d: any) => d && d.name)
} else {
devices = deviceInfoList.value.filter((d: any) => d && d.name)
}
// 如果是从根节点开始新增
if (nodeData.value.level === 0) {
submitData = {
engineering: engineeringData2,
project: projectData2,
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
}
}
// 如果是从工程节点开始新增
else if (nodeData.value.level === 1) {
submitData = {
engineeringIndex: nodeData.value?.id || "",
project: projectData2,
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
}
}
// 如果是从项目节点开始新增
else if (nodeData.value.level === 2) {
const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : [];
const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : "";
submitData = {
projectIndex: nodeData.value?.id || "",
engineeringIndex: engineeringId,
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
}
}
break
case 3: // 工程 + 项目 + 设备 + 监测点
case 4:
// 工程信息
const engineeringData3 = tempAllLevelData.value.engineering || { ...engineeringParam.value }
// 项目信息
const projectData3 = tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects[0]
: (projectInfoList.value[0] || {})
// 设备信息
let devices2: any[] = []
if (tempAllLevelData.value.devices.length > 0) {
devices2 = tempAllLevelData.value.devices.filter((d: any) => d && d.name)
} else {
devices2 = deviceInfoList.value.filter((d: any) => d && d.name)
}
// 监测点信息
let lines = []
if (tempAllLevelData.value.lines.length > 0) {
lines = tempAllLevelData.value.lines.filter((l: any) => l && l.name)
} else {
lines = lineInfoList.value.filter((l: any) => l && l.name)
}
// 如果是从根节点开始新增
if (nodeData.value.level === 0) {
submitData = {
engineering: engineeringData3,
project: projectData3,
device: devices2.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
}
}
// 如果是从工程节点开始新增
else if (nodeData.value.level === 1) {
submitData = {
engineeringIndex: nodeData.value?.id || "",
project: projectData3,
device: devices2.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
}
}
// 如果是从项目节点开始新增
else if (nodeData.value.level === 2) {
const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : [];
const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : "";
submitData = {
device: devices2.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
projectIndex: nodeData.value?.id || "",
engineeringIndex: engineeringId,
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
}
}
// 如果是从设备节点开始新增
else if (nodeData.value.level === 3) {
const pidsArray2 = nodeData.value?.pids ? nodeData.value.pids.split(',') : [];
const engineeringId2 = pidsArray2.length >= 2 ? pidsArray2[1] : "";
const projectId = pidsArray2.length >= 3 ? pidsArray2[2] : "";
submitData = {
devIndex: nodeData.value?.id || "",
projectIndex: projectId,
engineeringIndex: engineeringId2,
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
}
}
break
}
// 发送请求
addLedger(submitData).then((res: any) => {
ElMessage({
type: 'success',
message: '数据提交成功'
})
pageStatus.value = 1
// 清空所有表单
resetAllForms()
// 刷新树并选中合适的节点
TerminalRef.value.info().then(() => {
// 等待树更新完成后,根据之前点击的节点层级选中合适的节点
setTimeout(() => {
let nodeIdToSelect: string|null|undefined = null;
// 根据新增的层级选择要选中的节点
switch (nodeLevel.value) {
case 0: // 新增了工程,选中根节点
nodeIdToSelect = null; // 根节点
break;
case 1: // 新增了项目,选中工程节点
nodeIdToSelect = nodeData.value.id; // 工程节点
break;
case 2: // 新增了设备,选中项目节点
nodeIdToSelect = nodeData.value.id; // 项目节点
break;
case 3: // 新增了监测点,选中设备节点
case 4:
nodeIdToSelect = nodeData.value.id; // 设备节点
break;
}
if (nodeIdToSelect) {
setTimeout(() => {
treedata(nodeIdToSelect !== null ? nodeIdToSelect : undefined);
// 重新加载节点内容以显示最新数据
setTimeout(() => {
queryNodeContent();
}, 200);
}, 100);
} else {
treedata(); // 选中根节点
}
}, 100);
})
})
}
/**
* 重置所有表单
*/
const resetAllForms = () => {
// 清空工程表单
engineeringParam.value.city = ''
engineeringParam.value.description = ''
engineeringParam.value.name = ''
engineeringParam.value.province = ''
// 清空项目表单
projectInfoList.value.forEach(project => {
project.name = ''
project.area = ''
project.description = ''
})
// 清空设备表单
deviceInfoList.value.forEach(device => {
device.name = ''
device.devModel = ''
device.devType = ''
device.devAccessMethod = 'CLD'
device.mac = ''
device.nodeId = ''
device.cntractNo = ''
device.sort = 0
})
// 清空监测点表单
lineInfoList.value.forEach(line => {
line.name = ''
line.lineNo = 1
line.conType = 0
line.lineInterval = 1
line.ptRatio = 0
line.pt2Ratio = 0
line.ctRatio = 0
line.ct2Ratio = 0
line.volGrade = ''
})
// 清空临时数据
tempAllLevelData.value = {
engineering: null,
projects: [],
devices: [],
lines: []
}
}
/**
* 提交数据
*/
const submitData = () => {
switch (nodeLevel.value) {
case 0: // 新增工程
const engineering = {
engineering: {
city: engineeringParam.value.city,
description: engineeringParam.value.description,
name: engineeringParam.value.name,
province: engineeringParam.value.province
},
};
addLedger(engineering).then((res: any) => {
ElMessage({
type: 'success',
message: '新增工程成功'
})
pageStatus.value = 1
// 刷新树并选中根节点
setTimeout(() => {
treedata(); // 选中根节点
}, 100);
})
break ;
case 1:// 新增项目
const project = {
engineeringIndex: nodeData.value?.id || "",
project: {
area: projectInfoList.value[deviceIndex.value]?.area || "",
description: projectInfoList.value[deviceIndex.value]?.description || "",
name: projectInfoList.value[deviceIndex.value]?.name || "",
engineeringId: nodeData.value?.id || "",
},
};
addLedger(project).then((res: any) => {
ElMessage({
type: 'success',
message: '新增项目成功'
})
pageStatus.value = 1
// 刷新树并选中工程节点(而不是新增的项目节点)
const engineeringId = nodeData.value?.id; // 工程ID
if (engineeringId) {
setTimeout(() => {
treedata(engineeringId); // 选中工程节点
// 重新加载节点内容以显示最新数据
setTimeout(() => {
queryNodeContent();
}, 200);
}, 100);
} else {
TerminalRef.value.info();
}
})
break;
case 2:// 新增设备
// 获取当前选中的设备信息
const currentDevice = deviceInfoList.value[busBarIndex.value];
if (!currentDevice) {
ElMessage({
type: 'error',
message: '未找到设备信息'
});
return;
}
const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : [];
const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : "";
const deviceData = {
projectIndex: nodeData.value?.id || "",
engineeringIndex: engineeringId,
device: [{
name: currentDevice.name,
devModel: currentDevice.devModel,
devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod,
mac: currentDevice.mac,
nodeId: currentDevice.nodeId,
cntractNo: currentDevice.cntractNo,
ndid: currentDevice.mac.replace(/:/g, ''),
sort: currentDevice.sort,
}],
};
addLedger(deviceData).then((res: any) => {
ElMessage({
type: 'success',
message: '新增设备成功'
})
pageStatus.value = 1
// 刷新树并选中项目节点(而不是新增的设备节点)
const projectId = nodeData.value?.id; // 项目ID
if (projectId) {
setTimeout(() => {
treedata(projectId); // 选中项目节点
// 重新加载节点内容以显示最新数据
setTimeout(() => {
queryNodeContent();
}, 200);
}, 100);
} else {
TerminalRef.value.info();
}
})
break;
case 3:// 新增监测点
// 获取当前选中的监测点信息
const currentLine = lineInfoList.value[lineIndex.value];
if (!currentLine) {
ElMessage({
type: 'error',
message: '未找到监测点信息'
});
return;
}
// 处理电压等级,去除"kV"后缀
let volGradeValue = currentLine.volGrade;
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2);
}
// 从pids中提取工程ID和项目ID
const pidsArray2 = nodeData.value?.pids ? nodeData.value.pids.split(',') : [];
const engineeringId2 = pidsArray2.length >= 2 ? pidsArray2[1] : "";
const projectId2 = pidsArray2.length >= 3 ? pidsArray2[2] : "";
const lineData = {
devIndex: nodeData.value?.id || "",
projectIndex: projectId2, // 从pids中提取的项目ID
engineeringIndex: engineeringId2, // 从pids中提取的工程ID
line: [{
name: currentLine.name,
lineNo: currentLine.lineNo,
conType: currentLine.conType,
lineInterval: currentLine.lineInterval,
ptRatio: currentLine.ptRatio,
pt2Ratio: currentLine.pt2Ratio,
ctRatio: currentLine.ctRatio,
ct2Ratio: currentLine.ct2Ratio,
volGrade: volGradeValue,
devMac: deviceInfoList.value[busBarIndex.value].mac,
}]
};
addLedger(lineData).then((res: any) => {
ElMessage({
type: 'success',
message: '新增监测点成功'
})
pageStatus.value = 1
// 刷新树并选中设备节点(而不是新增的监测点节点)
const deviceId = nodeData.value?.id; // 设备ID
if (deviceId) {
setTimeout(() => {
treedata(deviceId); // 选中设备节点
// 重新加载节点内容以显示最新数据
setTimeout(() => {
queryNodeContent();
}, 200);
}, 100);
} else {
TerminalRef.value.info();
}
})
break;
}
}
/**
* 项目tab编辑新增/删除
*/
const handleDeviceTabsEdit = (targetName: any, action: any) => {
if (action === 'add') {
// 新增项目
projectInfoList.value.push({
name: '',
area: '',
description: ''
})
deviceIndex.value = (projectInfoList.value.length - 1).toString()
} else if (action === 'remove') {
// 删除项目
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
2025-10-17 09:55:43 +08:00
// 删除项目
if (projectInfoList.value[deviceIndex.value]?.id) {
2025-10-11 10:35:25 +08:00
deleteProject(
projectInfoList.value[deviceIndex.value].id,
projectInfoList.value[deviceIndex.value].name,
projectInfoList.value[deviceIndex.value].area,
projectInfoList.value[deviceIndex.value].description,
0 // 0表示删除
).then((res: any) => {
ElMessage({
type: 'success',
message: res.message
})
// 从列表中移除
projectInfoList.value.splice(deviceIndex.value, 1)
// 重新设置当前选中的tab
deviceIndex.value = projectInfoList.value.length
? (projectInfoList.value.length - 1).toString()
: '0'
// 重置相关索引
busBarIndex.value = '0'
lineIndex.value = '0'
2025-10-17 09:55:43 +08:00
pageStatus.value = 1
treedata()
2025-10-11 10:35:25 +08:00
})
} else {
// 如果是新增模式下删除未保存的项目
projectInfoList.value.splice(deviceIndex.value, 1)
deviceIndex.value = projectInfoList.value.length
? (projectInfoList.value.length - 1).toString()
: '0'
busBarIndex.value = '0'
lineIndex.value = '0'
ElMessage({
type: 'success',
message: '删除成功'
})
}
}).catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
}
/**
* 设备tab编辑新增/删除
*/
const handleBusBarTabsEdit = (targetName: any, action: any) => {
if (action === 'add') {
// 新增设备
deviceInfoList.value.push({
name: '',
devModel: '',
devType: '',
devAccessMethod: 'CLD',
mac: '',
ndid: '',
nodeId: '',
cntractNo: '',
2025-10-17 14:37:31 +08:00
sort: 0,
2025-10-20 09:42:01 +08:00
nodeProcess: '自动分配',
2025-10-11 10:35:25 +08:00
})
busBarIndex.value = (deviceInfoList.value.length - 1).toString()
} else if (action === 'remove') {
// 删除设备
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 如果是编辑现有设备
2025-10-17 09:55:43 +08:00
if ( deviceInfoList.value[busBarIndex.value]?.id) {
2025-10-11 10:35:25 +08:00
deleteEquipment(deviceInfoList.value[busBarIndex.value].id).then((res: any) => {
ElMessage({
type: 'success',
message: res.message
})
// 从列表中移除
deviceInfoList.value.splice(busBarIndex.value, 1)
// 重新设置当前选中的tab
busBarIndex.value = deviceInfoList.value.length
? (deviceInfoList.value.length - 1).toString()
: '0'
lineIndex.value = '0'
2025-10-17 09:55:43 +08:00
pageStatus.value = 1
treedata()
2025-10-11 10:35:25 +08:00
})
} else {
// 如果是新增模式下删除未保存的设备
deviceInfoList.value.splice(busBarIndex.value, 1)
busBarIndex.value = deviceInfoList.value.length
? (deviceInfoList.value.length - 1).toString()
: '0'
lineIndex.value = '0'
ElMessage({
type: 'success',
message: '删除成功'
})
}
}).catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
}
/**
* 监测点tab编辑新增/删除
*/
const handleLineTabsEdit = (targetName: any, action: any) => {
if (action === 'add') {
// 新增监测点
lineInfoList.value.push({
name: '',
lineNo: 1,
conType: 0,
lineInterval: 1,
ptRatio: 0,
pt2Ratio: 0,
ctRatio: 0,
ct2Ratio: 0,
volGrade: '',
devMac: '',
})
lineIndex.value = (lineInfoList.value.length - 1).toString()
} else if (action === 'remove') {
// 删除监测点
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 如果是编辑现有监测点
2025-10-17 09:55:43 +08:00
if (lineInfoList.value[lineIndex.value]?.lineId) {
deleteLine(lineInfoList.value[lineIndex.value].lineId).then((res: any) => {
2025-10-11 10:35:25 +08:00
ElMessage({
type: 'success',
message: res.message
})
// 从列表中移除
lineInfoList.value.splice(lineIndex.value, 1)
// 重新设置当前选中的tab
lineIndex.value = lineInfoList.value.length
? (lineInfoList.value.length - 1).toString()
: '0'
2025-10-17 09:55:43 +08:00
pageStatus.value = 1
treedata()
2025-10-11 10:35:25 +08:00
})
} else {
// 如果是新增模式下删除未保存的监测点
lineInfoList.value.splice(lineIndex.value, 1)
lineIndex.value = lineInfoList.value.length
? (lineInfoList.value.length - 1).toString()
: '0'
ElMessage({
type: 'success',
message: '删除成功'
})
}
}).catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
})
})
}
}
2025-10-17 09:55:43 +08:00
2025-10-11 10:35:25 +08:00
const tabChange = (type: string) => {
if (type == 'deviceIndex') {
busBarIndex.value = '0'
lineIndex.value = '0'
} else if (type == 'busBarIndex') {
lineIndex.value = '0'
}
}
const treedata = (selectedNodeId?: string) => {
if (selectedNodeId) {
TerminalRef.value.info(selectedNodeId);
} else {
TerminalRef.value.info();
}
2025-10-17 09:55:43 +08:00
titleList.value = []
titleList.value.unshift('在线设备')
2025-10-11 10:35:25 +08:00
}
/**
* 重置初始状态
*/
const reaseStatus = () => {
nodeData.value = {}
nodeLevel.value = 0
pageStatus.value = 1
projectId.value = 0
provinceId.value = 0
gdId.value = 0
subId.value = 0
devId.value = 0
busBarId.value = 0
lineId.value = 0
deviceIndex.value = '0'
busBarIndex.value = '0'
lineIndex.value = '0'
currentGdName.value = ''
}
const area = () => {
nodeAllList().then(res => {
affiliatiedFrontArr.value = res.data
}).catch(error => {
console.error('获取前置机数据失败:', error)
})
queryByCode('DEV_CLD').then(res => {
devTypeOptions2.value = res.data
return queryCsDictTree(res.data.id).then(res => {
devCLD.value = res.data
})
}).then(() => {
return queryByCode('Device_Type').then(res => {
return queryCsDictTree(res.data.id).then(res => {
devTypeOptions.value = res.data
})
})
}).catch(error => {
console.error('查询过程中出现错误:', error)
})
}
onMounted(() => {
nodeData.value.level = 0
const dom = document.getElementById('navigation-splitpanes')
if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100)
}
})
area()
</script>
<style scoped>
</style>
<style lang="scss" scoped>
2025-10-17 14:41:58 +08:00
.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
2025-10-11 10:35:25 +08:00
.device-manage {
display: flex;
padding: 10px;
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;
display: flex;
align-items: center;
}
}
}
.main-form {
display: flex;
flex-wrap: wrap;
.form-top {
width: 100%;
}
.el-form-item {
width: 30%;
margin-bottom: 15px;
.el-select {
width: 100%;
min-width: 0px;
}
}
}
.el-tabs__content {
margin-top: 15px;
}
.splitpanes.default-theme .splitpanes__pane {
background: #fff !important;
}
.title {
width: 500px;
overflow: hidden;
// display: flex;
white-space: nowrap;
font-weight: bold;
}
.titleScroll {
animation: scroll 10s linear infinite; /* 滚动动画 */
}
@keyframes scroll {
0% {
transform: translateX(100%); /* 从右侧开始 */
}
100% {
transform: translateX(-160%); /* 滚动到左侧 */
}
}
</style>