修改冀北问题

This commit is contained in:
guanj
2025-12-09 20:04:55 +08:00
parent 8c41a8fc77
commit 0fe2d2b911
49 changed files with 6357 additions and 5917 deletions

View File

@@ -1,32 +1,47 @@
import request from '@/utils/request' import request from '@/utils/request'
import { DEVICE_BOOT } from '@/utils/constantRequest' import { DEVICE_BOOT } from '@/utils/constantRequest'
const MAPPING_PATH = DEVICE_BOOT + '/line' const MAPPING_PATH = DEVICE_BOOT + '/line'
/** /**
* 查询终端详细信息 * 查询终端详细信息
*/ */
export const getDeviceDetailData = (id: string) => { export const getDeviceDetailData = (id: string) => {
return request({ return request({
url: MAPPING_PATH + '/getDeviceDetailData?id=' + id, url: MAPPING_PATH + '/getDeviceDetailData?id=' + id,
method: 'POST' method: 'POST'
}) })
} }
/** /**
* 查询监测点详细信息 * 查询监测点详细信息
*/ */
export const getLineDetailData = (id: string) => { export const getLineDetailData = (id: string) => {
return request({ return request({
url: MAPPING_PATH + '/getLineDetailData?id=' + id, url: MAPPING_PATH + '/getLineDetailData?id=' + id,
method: 'POST' method: 'POST'
}) })
} }
export const getSubstationSelect = () => { export const getSubstationSelect = () => {
return request({ return request({
url: 'device-boot/substation/getSubstationSelect', url: 'device-boot/substation/getSubstationSelect',
method: 'get' method: 'get'
}) })
} }
// 查询变电站详情
export const getSubstationSelectLine = (id: string) => {
return request({
url: '/device-boot/line/getSubstationData',
method: 'post',
data: [id]
})
}
// 查询监测点
export const getLineOverLimitData = (id: string) => {
return request({
url: '/device-boot/line/getLineOverLimitData?id=' + id,
method: 'post'
})
}

View File

@@ -31,7 +31,7 @@
<div class="divBox mt10"> <div class="divBox mt10">
<span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span> <span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span>
<span class="divBox_title">低于90%监测点数</span> <span class="divBox_title">低于90%监测点数</span>
<span class="divBox_num" style="color: #ff6600"> <span class="divBox_num" style="color: #57bc6e">
{{ monitoringPoints.abnormalNum }} {{ monitoringPoints.abnormalNum }}
</span> </span>
</div> </div>
@@ -90,7 +90,7 @@
{{ o.citTotalNum }} {{ o.citTotalNum }}
</span> </span>
<!-- 低于90%监测点数 --> <!-- 低于90%监测点数 -->
<span style="flex: 1; color: #ff9100" class="text"> <span style="flex: 1; color: #388e3c" class="text">
{{ o.citBelowNum }} {{ o.citBelowNum }}
</span> </span>
<span <span
@@ -179,10 +179,17 @@ const tableStore: any = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0 monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList abnormal.value = tableStore.table.data.citDetailList.filter((k: any) => {
if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0
} else {
return k.citName != '上送国网' && k.citName != '非上送国网'
}
})
} }
}) })
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = 0
const echart = () => { const echart = () => {
percentage.value = { percentage.value = {
color: ['#FF9100'], color: ['#FF9100'],

View File

@@ -31,7 +31,7 @@
<div class="divBox mt10"> <div class="divBox mt10">
<span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span> <span class="iconfont icon-igw-f-warning-data" style="color: #ff6600"></span>
<span class="divBox_title">低于90%终端数</span> <span class="divBox_title">低于90%终端数</span>
<span class="divBox_num" style="color: #ff6600"> <span class="divBox_num" style="color: #57bc6e">
{{ monitoringPoints.abnormalNum }} {{ monitoringPoints.abnormalNum }}
</span> </span>
</div> </div>
@@ -88,7 +88,7 @@
{{ o.citTotalNum }} {{ o.citTotalNum }}
</span> </span>
<!-- 低于90%终端数 --> <!-- 低于90%终端数 -->
<span style="flex: 1; color: #ff9100" class="text"> <span style="flex: 1; color: #388e3c" class="text">
{{ o.citBelowNum }} {{ o.citBelowNum }}
</span> </span>
<span <span
@@ -177,12 +177,18 @@ const tableStore: any = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0 monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList.filter( abnormal.value = tableStore.table.data.citDetailList.filter((k: any) => {
(k: any) => k.citName != '上送国网' && k.citName != '非上送国网' if (tableStore.table.params.statisticalType.name == '终端厂家') {
) return k.citTotalNum != 0
} else {
return k.citName != '上送国网' && k.citName != '非上送国网'
}
})
} }
}) })
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = 0
const echart = () => { const echart = () => {
percentage.value = { percentage.value = {
color: ['#FF9100'], color: ['#FF9100'],

View File

@@ -108,7 +108,7 @@
</span> </span>
<!-- --> <!-- -->
<sp <sp
style="flex: 1; color: #ff9100" style="flex: 1; color: #388e3c"
class="text" class="text"
:class="` ${o.integrity < 90 ? 'text-red' : ''}`" :class="` ${o.integrity < 90 ? 'text-red' : ''}`"
> >
@@ -123,7 +123,7 @@
</span> </span>
<span <span
style="flex: 1; color: #388e3c" style="flex: 1; color: #388e3c"
:class="` ${o.qualified < 90 ? 'text-red' : ''}`" :class="` ${o.qualified > 10 ? 'text-red' : ''}`"
class="text" class="text"
> >
{{ o.qualified }} {{ o.qualified }}
@@ -229,11 +229,17 @@ const tableStore: any = new TableStore({
statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length
statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length
abnormal.value = tableStore.table.data.filter((k: any) => k.name != '上送国网' && k.name != '非上送国网') abnormal.value = tableStore.table.data.filter((k: any) => {
if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.count != 0
} else {
return k.name != '上送国网' && k.name != '非上送国网'
}
})
} }
}) })
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = 0
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {

View File

@@ -1,14 +1,17 @@
export let color = [ export const color = [
'#07CCCA', '#07CCCA',
'#00BFF5', '#00BFF5',
'#FFBF00', '#FFBF00',
'#77DA63', '#77DA63',
'#D5FF6B', '#D5FF6B',
'#Ff6600', '#Ff6600',
'#FF9100', '#FF9100',
'#5B6E96', '#5B6E96',
'#66FFCC', '#66FFCC',
'#B3B' '#B266FF',
] '#FF6680',
export const gradeColor3 = ['#339966', '#FFCC33', '#A52a2a'] '#40A0FF',
export const gradeColor5 = ['#00CC00', '#99CC99', '#FF9900', '#996600', '#A52a2a'] '#33CC99'
]
export const gradeColor3 = ['#339966', '#FFCC33', '#A52a2a']
export const gradeColor5 = ['#00CC00', '#99CC99', '#FF9900', '#996600', '#A52a2a']

View File

@@ -0,0 +1,205 @@
<template>
<el-dialog draggable v-model="dialogVisible" :title="title" width="1200px">
<el-tabs type="border-card" v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="监测点详情" name="tab1">
<el-descriptions :column="3" border label-width="150px">
<el-descriptions-item label="项目工程">
{{ details.areaName }}
</el-descriptions-item>
<el-descriptions-item label="项目单位">
{{ details.gdName }}
</el-descriptions-item>
<el-descriptions-item label="所属变电站">
{{ details.bdName }}
</el-descriptions-item>
<el-descriptions-item label="电压等级">
{{ details.scale }}
</el-descriptions-item>
<el-descriptions-item label="终端厂家">
{{ details.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="终端名称">
{{ details.devName }}
</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ details.ip }}
</el-descriptions-item>
<el-descriptions-item label="监测点名称">
{{ details.lineName }}
</el-descriptions-item>
<el-descriptions-item label="监测点序号">
{{ details.id }}
</el-descriptions-item>
<el-descriptions-item label="通讯状态">
{{ details.comFlag }}
</el-descriptions-item>
<el-descriptions-item label="干扰源类型">
{{ details.loadType }}
</el-descriptions-item>
<el-descriptions-item label="监测点对象名称">
{{ details.objName }}
</el-descriptions-item>
<el-descriptions-item label="接线方式">
{{ details.ptType }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ details.pt }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
{{ details.ct }}
</el-descriptions-item>
<el-descriptions-item label="基准容量(MVA)">
{{ details.standardCapacity }}
</el-descriptions-item>
<el-descriptions-item label="最小短路容量(MVA)">
{{ details.shortCapacity }}
</el-descriptions-item>
<el-descriptions-item label="供电设备容量(MVA)">
{{ details.devCapacity }}
</el-descriptions-item>
<el-descriptions-item label="用户协议容量(MVA)">
{{ details.dealCapacity }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="监测点限值" name="tab2">
<el-descriptions :column="3" border label-width="250px">
<el-descriptions-item label="电压偏差上限值(%)">
{{ limitValue.voltageDev }}
</el-descriptions-item>
<el-descriptions-item label="电压偏差下限值(%)">
{{ limitValue.uvoltageDev }}
</el-descriptions-item>
<el-descriptions-item label="频率偏差限值(Hz)">
{{ limitValue.freqDev }}
</el-descriptions-item>
<el-descriptions-item label="三相电压不平衡度限值(%)">
{{ limitValue.ubalance }}
</el-descriptions-item>
<el-descriptions-item label="负序电流限值(A)">
{{ limitValue.ineg }}
</el-descriptions-item>
<el-descriptions-item label="长时闪变限值(%)">
{{ limitValue.flicker }}
</el-descriptions-item>
<el-descriptions-item label="电压总畸变率限值(%)">
{{ limitValue.uaberrance }}
</el-descriptions-item>
<el-descriptions-item label="奇次谐波电压含有率限值(%)">
{{ limitValue.oddHarm }}
</el-descriptions-item>
<el-descriptions-item label="偶次谐波电压含有率限值(%)">
{{ limitValue.evenHarm }}
</el-descriptions-item>
<el-descriptions-item label="3次谐波电流幅值限值(A)">
{{ limitValue.iharm3 }}
</el-descriptions-item>
<el-descriptions-item label="4次谐波电流幅值限值(A)">
{{ limitValue.iharm4 }}
</el-descriptions-item>
<el-descriptions-item label="5次谐波电流幅值限值(A)">
{{ limitValue.iharm5 }}
</el-descriptions-item>
<el-descriptions-item label="6次谐波电流幅值限值(A)">
{{ limitValue.iharm6 }}
</el-descriptions-item>
<el-descriptions-item label="7次谐波电流幅值限值(A)">
{{ limitValue.iharm7 }}
</el-descriptions-item>
<el-descriptions-item label="8次谐波电流幅值限值(A)">
{{ limitValue.iharm8 }}
</el-descriptions-item>
<el-descriptions-item label="9次谐波电流幅值限值(A)">
{{ limitValue.iharm9 }}
</el-descriptions-item>
<el-descriptions-item label="10次谐波电流幅值限值(A)">
{{ limitValue.iharm10 }}
</el-descriptions-item>
<el-descriptions-item label="11次谐波电流幅值限值(A)">
{{ limitValue.iharm11 }}
</el-descriptions-item>
<el-descriptions-item label="12次谐波电流幅值限值(A)">
{{ limitValue.iharm12 }}
</el-descriptions-item>
<el-descriptions-item label="13次谐波电流幅值限值(A)">
{{ limitValue.iharm13 }}
</el-descriptions-item>
<el-descriptions-item label="14次谐波电流幅值限值(A)">
{{ limitValue.iharm14 }}
</el-descriptions-item>
<el-descriptions-item label="15次谐波电流幅值限值(A)">
{{ limitValue.iharm15 }}
</el-descriptions-item>
<el-descriptions-item label="16次谐波电流幅值限值(A)">
{{ limitValue.iharm16 }}
</el-descriptions-item>
<el-descriptions-item label="17次谐波电流幅值限值(A)">
{{ limitValue.iharm17 }}
</el-descriptions-item>
<el-descriptions-item label="18次谐波电流幅值限值(A)">
{{ limitValue.iharm18 }}
</el-descriptions-item>
<el-descriptions-item label="19次谐波电流幅值限值(A)">
{{ limitValue.iharm19 }}
</el-descriptions-item>
<el-descriptions-item label="20次谐波电流幅值限值(A)">
{{ limitValue.iharm20 }}
</el-descriptions-item>
<el-descriptions-item label="21次谐波电流幅值限值(A)">
{{ limitValue.iharm21 }}
</el-descriptions-item>
<el-descriptions-item label="22次谐波电流幅值限值(A)">
{{ limitValue.iharm22 }}
</el-descriptions-item>
<el-descriptions-item label="23次谐波电流幅值限值(A)">
{{ limitValue.iharm23 }}
</el-descriptions-item>
<el-descriptions-item label="24次谐波电流幅值限值(A)">
{{ limitValue.iharm24 }}
</el-descriptions-item>
<el-descriptions-item label="25次谐波电流幅值限值(A)">
{{ limitValue.iharm25 }}
</el-descriptions-item>
<el-descriptions-item label="0.5-1.5次间谐波电压含有率限值(%)">
{{ limitValue.inUharm }}
</el-descriptions-item>
<el-descriptions-item label="2.5-15.5次谐波电压含有率限值(%)">
{{ limitValue.inUharm16 }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { getLineOverLimitData, getLineDetailData } from '@/api/device-boot/line'
const dialogVisible = ref(false)
const title = ref('')
const activeName = ref('tab1')
const details: any = ref([])
const limitValue: any = ref([])
const open = (data: any) => {
details.value = []
limitValue.value = []
activeName.value = 'tab1'
title.value = data.name.replace(/[^]*/g, '') + '_详情'
getLineDetailData(data.id).then(res => {
details.value = res.data
})
getLineOverLimitData(data.id).then(res => {
limitValue.value = res.data
})
dialogVisible.value = true
}
const handleClick = (tab: any, event: Event) => {}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-upload-list__item) {
width: 400px;
}
</style>

View File

@@ -0,0 +1,34 @@
<template>
<el-dialog draggable v-model="dialogVisible" :title="title" width="500px">
<el-descriptions class="margin-top" :column="1" border label-width="150px">
<el-descriptions-item label="变电站名称">{{ list[0]?.srbName }}</el-descriptions-item>
<el-descriptions-item label="电压等级">{{ list[0]?.scale }}</el-descriptions-item>
<el-descriptions-item label="经度">{{ list[0]?.coordY }}</el-descriptions-item>
<el-descriptions-item label="纬度">{{ list[0]?.coordX }}</el-descriptions-item>
</el-descriptions>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { getSubstationSelectLine } from '@/api/device-boot/line'
const dialogVisible = ref(false)
const title = ref('')
const list: any = ref([])
const open = (data: any) => {
list.value = []
title.value = data.name.replace(/[^]*/g, '') + '_详情'
getSubstationSelectLine(data.id).then(res => {
list.value = res.data
})
dialogVisible.value = true
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-upload-list__item) {
width: 400px;
}
</style>

View File

@@ -1,162 +1,245 @@
<template> <template>
<div :style="{ width: menuCollapse ? '40px' : props.width }" style="transition: all 0.3s; overflow: hidden"> <div :style="{ width: menuCollapse ? '40px' : props.width }" style="transition: all 0.3s; overflow: hidden">
<Icon v-show="menuCollapse" @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <Icon
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 mt20 menu-collapse" v-show="menuCollapse"
style="cursor: pointer" /> @click="onMenuCollapse"
<div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }"> :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
<div style="display: flex; align-items: center" class="mb10"> :class="menuCollapse ? 'unfold' : ''"
<el-input v-model="filterText" placeholder="请输入内容" clearable maxlength="10" show-word-limit @input="change"> size="18"
<template #prefix> class="fold ml10 mt20 menu-collapse"
<Icon name="el-icon-Search" style="font-size: 16px" /> style="cursor: pointer"
</template> />
</el-input> <div class="cn-tree" :style="{ opacity: menuCollapse ? 0 : 1 }">
<Icon @click="onMenuCollapse" :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'" <div style="display: flex; align-items: center" class="mb10">
:class="menuCollapse ? 'unfold' : ''" size="18" class="fold ml10 menu-collapse" <el-input
style="cursor: pointer" v-if="props.canExpand" /> v-model="filterText"
<el-button icon="el-icon-Plus" v-if="props.addTree" type="primary" class="ml10" placeholder="请输入内容"
@click="onAddTree">新增</el-button> clearable
</div> maxlength="10"
<el-tree style="flex: 1; overflow: auto" ref="treeRef" :props="defaultProps" highlight-current show-word-limit
:filter-node-method="filterNode" node-key="id" v-bind="$attrs"> @input="change"
<template #default="{ node, data }"> >
<span class="custom-tree-node"> <template #prefix>
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }" <Icon name="el-icon-Search" style="font-size: 16px" />
v-if="data.icon" /> </template>
<span style="margin-left: 4px">{{ node.label }}</span> </el-input>
</span> <Icon
</template> @click="onMenuCollapse"
</el-tree> :name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
</div> :class="menuCollapse ? 'unfold' : ''"
</div> size="18"
</template> class="fold ml10 menu-collapse"
style="cursor: pointer"
<script lang="ts" setup> v-if="props.canExpand"
import useCurrentInstance from '@/utils/useCurrentInstance' />
import { ElTree } from 'element-plus' <el-button icon="el-icon-Plus" v-if="props.addTree" type="primary" class="ml10" @click="onAddTree">
import { ref, watch } from 'vue' 新增
import { ElMessage } from 'element-plus' </el-button>
defineOptions({ </div>
name: 'govern/tree' <el-tree
}) style="flex: 1; overflow: auto"
const emit = defineEmits(['onAddTree']) ref="treeRef"
interface Props { :props="defaultProps"
width?: string highlight-current
canExpand?: boolean :filter-node-method="filterNode"
addTree?: boolean node-key="id"
} v-bind="$attrs"
>
const props = withDefaults(defineProps<Props>(), { <template #default="{ node, data }">
width: '280px', <span class="custom-tree-node">
canExpand: true, <Icon
addTree: false :name="data.icon"
}) style="font-size: 16px"
const { proxy } = useCurrentInstance() :style="{ color: data.color }"
const menuCollapse = ref(false) v-if="data.icon"
const filterText = ref('') />
const defaultProps = {
label: 'name', <el-tooltip
value: 'id' class="box-item"
} effect="customized"
const specialCharsPattern = /[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g; placement="bottom-start"
const change=(val) => { :offset="0"
v-if=" data.level == 6"
>
if (specialCharsPattern.test(val)) { <template #content>
ElMessage.warning('禁止输入特殊字符!') <el-button type="primary" plain @click="viewDetails(data)">
filterText.value = val.replace(/[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g, "") {{ data.level == 3 ? '变电站详情' : '监测点详情' }}
console.log("🚀 ~ change ~ filterText.value:", filterText.value) </el-button>
</template>
treeRef.value!.filter(filterText.value) <span style="margin-left: 4px">{{ node.label }}</span>
}else{ </el-tooltip>
treeRef.value!.filter(filterText.value) <span v-else style="margin-left: 4px">{{ node.label }}</span>
} </span>
} </template>
// watch(filterText, val => { </el-tree>
</div>
// console.log("🚀 ~ val:", specialCharsPattern.test(val)) <!-- 变电站详情 -->
// if (specialCharsPattern.test(val)) { <SubstationDetails ref="SubstationRef"/>
// ElMessage.warning('禁止输入特殊字符!') <!-- 监测点详情 -->
// filterText.value = val.replace(/[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g, "") <MonitoringPointDetails ref="MonitoringPointRef"/>
// console.log("🚀 ~ filterText.value:", filterText.value)
// treeRef.value!.filter(filterText.value)
// }else{ </div>
// treeRef.value!.filter(filterText.value) </template>
// }
<script lang="ts" setup>
// }) import useCurrentInstance from '@/utils/useCurrentInstance'
const onMenuCollapse = () => { import { ElTree } from 'element-plus'
menuCollapse.value = !menuCollapse.value import { ref, watch } from 'vue'
proxy.eventBus.emit('cnTreeCollapse', menuCollapse) import { ElMessage } from 'element-plus'
} import MonitoringPointDetails from './details/monitoringPointDetails.vue'
const filterNode = (value: string, data: any, node: any) => { import SubstationDetails from './details/substationDetails.vue'
if (!value) return true
// return data.name.includes(value) defineOptions({
if (data.name) { name: 'govern/tree'
})
return chooseNode(value, data, node) const emit = defineEmits(['onAddTree'])
} interface Props {
} width?: string
canExpand?: boolean
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符. addTree?: boolean
const chooseNode = (value: string, data: any, node: any) => { }
if (data.name.indexOf(value) !== -1) { const props = withDefaults(defineProps<Props>(), {
return true width: '280px',
} canExpand: true,
const level = node.level addTree: false
// 如果传入的节点本身就是一级节点就不用校验了 })
if (level === 1) { const { proxy } = useCurrentInstance()
return false const menuCollapse = ref(false)
} const MonitoringPointRef = ref()
// 先取当前节点的父节点 const SubstationRef = ref()
let parentData = node.parent const filterText = ref('')
// 遍历当前节点的父节点 const defaultProps = {
let index = 0 label: 'name',
while (index < level - 1) { value: 'id'
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤 }
if (parentData.data.name.indexOf(value) !== -1) { const specialCharsPattern = /[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g
return true const change = val => {
} if (specialCharsPattern.test(val)) {
// 否则的话再往上一层做匹配 ElMessage.warning('禁止输入特殊字符!')
parentData = parentData.parent filterText.value = val.replace(
index++ /[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g,
} ''
// 没匹配到返回false )
return false console.log('🚀 ~ change ~ filterText.value:', filterText.value)
}
// 添加树 treeRef.value!.filter(filterText.value)
const onAddTree = () => { } else {
emit('onAddTree') treeRef.value!.filter(filterText.value)
} }
const treeRef = ref<InstanceType<typeof ElTree>>() }
defineExpose({ treeRef }) // watch(filterText, val => {
</script>
// console.log("🚀 ~ val:", specialCharsPattern.test(val))
<style lang="scss" scoped> // if (specialCharsPattern.test(val)) {
.cn-tree { // ElMessage.warning('禁止输入特殊字符!')
flex-shrink: 0; // filterText.value = val.replace(/[`~!@$%^&*\-+=<>?:"{}|,.\/;'\\[\]·~@¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、~]/g, "")
display: flex; // console.log("🚀 ~ filterText.value:", filterText.value)
flex-direction: column; // treeRef.value!.filter(filterText.value)
box-sizing: border-box; // }else{
padding: 10px; // treeRef.value!.filter(filterText.value)
height: 100%; // }
width: 100%;
// })
:deep(.el-tree) { const onMenuCollapse = () => {
border: 1px solid var(--el-border-color); menuCollapse.value = !menuCollapse.value
} proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
}
:deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) { // 查看详情
background-color: var(--el-color-primary-light-7); const viewDetails = (data: any) => {
} console.log("🚀 ~ viewDetails ~ data:", data)
if (data.level == 3) {
.menu-collapse { // 变电站详情
color: var(--el-color-primary); // substationDetails
} SubstationRef.value.open(data)
} } else {
// 监测点详情
.custom-tree-node { MonitoringPointRef.value.open(data)
display: flex; }
align-items: center;
} // proxy.eventBus.emit('viewDetails', data)
</style> }
const filterNode = (value: string, data: any, node: any) => {
if (!value) return true
// return data.name.includes(value)
if (data.name) {
return chooseNode(value, data, node)
}
}
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
const chooseNode = (value: string, data: any, node: any) => {
if (data.name.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤
if (parentData.data.name.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
}
// 添加树
const onAddTree = () => {
emit('onAddTree')
}
const treeRef = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef })
</script>
<style lang="scss" scoped>
.cn-tree {
flex-shrink: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
height: 100%;
width: 100%;
:deep(.el-tree) {
border: 1px solid var(--el-border-color);
}
:deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content) {
background-color: var(--el-color-primary-light-7);
}
.menu-collapse {
color: var(--el-color-primary);
}
}
.custom-tree-node {
display: flex;
align-items: center;
}
</style>
<style>
.el-popper.is-customized {
/* Set padding to ensure the height is 32px */
padding: 0;
background: var(--el-color-primary-light-3);
}
.el-popper.is-customized .el-popper__arrow::before {
background: var(--el-color-primary-light-3);
right: 0;
display: none;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,355 +1,355 @@
<template> <template>
<div class="default-main" style="position: relative"> <div class="default-main" style="position: relative">
<TableHeader> <TableHeader>
<template #select> <template #select>
<el-form-item label="终端型号"> <el-form-item label="终端型号">
<el-select v-model="tableStore.table.params.teriminal" clearable placeholder="请选择终端型号"> <el-select v-model="tableStore.table.params.teriminal" clearable placeholder="请选择终端型号">
<el-option <el-option
v-for="item in teriminaloption" v-for="item in teriminaloption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端状态"> <el-form-item label="终端状态">
<el-select v-model="tableStore.table.params.teriminalstatus" clearable placeholder="请选择终端状态"> <el-select v-model="tableStore.table.params.teriminalstatus" clearable placeholder="请选择终端状态">
<el-option <el-option
v-for="item in teriminalstatusoption" v-for="item in teriminalstatusoption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="通讯状态"> <el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.state" clearable placeholder="请选择通讯状态"> <el-select v-model="tableStore.table.params.state" clearable placeholder="请选择通讯状态">
<el-option <el-option
v-for="item in stateoption" v-for="item in stateoption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="程序版本"> <el-form-item label="程序版本">
<el-select v-model="tableStore.table.params.program" clearable placeholder="请选择程序版本"> <el-select v-model="tableStore.table.params.program" clearable placeholder="请选择程序版本">
<el-option <el-option
v-for="item in programoption" v-for="item in programoption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input <el-input
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"
placeholder="输入关键字筛选" placeholder="输入关键字筛选"
/> />
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Download" @click="add">导出</el-button> <el-button icon="el-icon-Download" @click="add">导出</el-button>
<el-button icon="el-icon-Check" @click="add">批量升级</el-button> <el-button icon="el-icon-Check" @click="add">批量升级</el-button>
</template> </template>
</TableHeader> </TableHeader>
<div :style="`height: calc(${tableStore.table.height} + 58px)`"> <div :style="`height: calc(${tableStore.table.height} + 58px)`">
<vxe-table <vxe-table
v-loading="tableStore.table.loading" v-loading="tableStore.table.loading"
height="auto" height="auto"
auto-resize auto-resize
ref="tableRef" ref="tableRef"
v-bind="defaultAttribute" v-bind="defaultAttribute"
:data="treeData" :data="treeData"
show-overflow show-overflow
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }" :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
:scroll-y="{ enabled: true }" :scroll-y="{ enabled: true }"
> >
<vxe-column field="name" align="left" title="电网拓扑" min-width="200" tree-node></vxe-column> <vxe-column field="name" align="left" title="电网拓扑" min-width="200" tree-node></vxe-column>
<vxe-column field="devType" title="终端型号" :formatter="formFilter"></vxe-column> <vxe-column field="devType" title="终端型号" :formatter="formFilter"></vxe-column>
<vxe-column field="versionName" title="版本号"></vxe-column> <vxe-column field="versionName" title="版本号"></vxe-column>
<vxe-column field="protocol" title="协议版本"></vxe-column> <vxe-column field="protocol" title="协议版本"></vxe-column>
<vxe-column field="versionDate" title="版本日期"></vxe-column> <vxe-column field="versionDate" title="版本日期"></vxe-column>
<vxe-column field="runFlag" title="终端状态"> <vxe-column field="runFlag" title="终端状态">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.runFlag === 0" style="color: #fff; background: #0099cc" size="small"> <el-tag v-if="row.runFlag === 0" style="color: #fff; background: #0099cc" size="small">
投运 投运
</el-tag> </el-tag>
<el-tag v-if="row.runFlag === 1" style="color: #fff; background: #996600" size="small"> <el-tag v-if="row.runFlag === 1" style="color: #fff; background: #996600" size="small">
检修 检修
</el-tag> </el-tag>
<el-tag v-if="row.runFlag === 2" style="color: #fff; background: #A52a2a" size="small"> <el-tag v-if="row.runFlag === 2" style="color: #fff; background: #A52a2a" size="small">
停运 停运
</el-tag> </el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="comFlag" title="通讯状态"> <vxe-column field="comFlag" title="通讯状态">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.comFlag === 0" style="color: #fff; background: #A52a2a" size="small"> <el-tag v-if="row.comFlag === 0" style="color: #fff; background: #A52a2a" size="small">
中断 中断
</el-tag> </el-tag>
<el-tag v-if="row.comFlag === 1" style="color: #fff; background: #2e8b57" size="small"> <el-tag v-if="row.comFlag === 1" style="color: #fff; background: #2e8b57" size="small">
正常 正常
</el-tag> </el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="updateBy" title="升级人员"> <vxe-column field="updateBy" title="升级人员">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row.updateBy == null || row.updateBy == '/'">--</span> <span v-if="row.updateBy == null || row.updateBy == '/'">--</span>
<span v-else>{{ row.updateBy }}</span> <span v-else>{{ row.updateBy }}</span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="updateTime" title="最新升级时间"></vxe-column> <vxe-column field="updateTime" title="最新升级时间"></vxe-column>
<vxe-column title="操作" min-width="100"> <vxe-column title="操作" min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-button v-if="row.level == 4" size="small" link @click="updateprogram(row)">升级</el-button> <el-button v-if="row.level == 4" size="small" link @click="updateprogram(row)">升级</el-button>
<el-button <el-button
v-if="row.level == 4" v-if="row.level == 4"
:disabled="row.state == 1 ? true : false" :disabled="row.state == 1 ? true : false"
size="small" size="small"
link link
@click="queryview(row)" @click="queryview(row)"
> >
日志查看 日志查看
</el-button> </el-button>
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
</div> </div>
<el-dialog <el-dialog
draggable draggable
v-model="dialogVisible" v-model="dialogVisible"
:close-on-click-modal="false" :close-on-click-modal="false"
:title="protitle + '#终端升级日志查看'" :title="protitle + '#终端升级日志查看'"
width="70%" width="70%"
> >
<div :style="{ height: dialogHeight.height }"> <div :style="{ height: dialogHeight.height }">
<vxe-table height="auto" auto-resize :data="logtableData" v-bind="defaultAttribute"> <vxe-table height="auto" auto-resize :data="logtableData" v-bind="defaultAttribute">
<vxe-column field="devTypeName" align="center" title="终端序号"></vxe-column> <vxe-column field="devTypeName" align="center" title="终端序号"></vxe-column>
<vxe-column field="versionId" align="center" title="版本序号"></vxe-column> <vxe-column field="versionId" align="center" title="版本序号"></vxe-column>
<vxe-column field="flag" align="center" title="版本状态" width="100"> <vxe-column field="flag" align="center" title="版本状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.flag == true" style="color: #fff; background: #fc0">前期版本</el-tag> <el-tag v-if="row.flag == true" style="color: #fff; background: #fc0">前期版本</el-tag>
<el-tag v-if="row.flag == false" style="color: #fff; background: #0c0">当前版本</el-tag> <el-tag v-if="row.flag == false" style="color: #fff; background: #0c0">当前版本</el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="result" align="center" title="升级结果" width="100"> <vxe-column field="result" align="center" title="升级结果" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.result == false" style="color: #fff; background: #f30">升级失败</el-tag> <el-tag v-if="row.result == false" style="color: #fff; background: #f30">升级失败</el-tag>
<el-tag v-if="row.result == true" style="color: #fff; background: #093">升级成功</el-tag> <el-tag v-if="row.result == true" style="color: #fff; background: #093">升级成功</el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="state" align="center" title="状态" width="100"> <vxe-column field="state" align="center" title="状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.state == false" style="color: #fff; background: #f30">删除</el-tag> <el-tag v-if="row.state == false" style="color: #fff; background: #f30">删除</el-tag>
<el-tag v-if="row.state == true" style="color: #fff; background: #093">正常</el-tag> <el-tag v-if="row.state == true" style="color: #fff; background: #093">正常</el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="createBy" align="center" title="创建用户"></vxe-column> <vxe-column field="createBy" align="center" title="创建用户"></vxe-column>
<vxe-column field="createTime" align="center" title="创建时间"></vxe-column> <vxe-column field="createTime" align="center" title="创建时间"></vxe-column>
<vxe-column field="updateTime" align="center" title="升级时间"></vxe-column> <vxe-column field="updateTime" align="center" title="升级时间"></vxe-column>
<vxe-column field="updateBy" align="center" title="升级人员"></vxe-column> <vxe-column field="updateBy" align="center" title="升级人员"></vxe-column>
</vxe-table> </vxe-table>
</div> </div>
</el-dialog> </el-dialog>
<!-- 升级 --> <!-- 升级 -->
<el-dialog <el-dialog
draggable draggable
v-model="prodialogVisible" v-model="prodialogVisible"
:close-on-click-modal="false" :close-on-click-modal="false"
:title="protitle + '#终端程序升级'" :title="protitle + '#终端程序升级'"
width="40%" width="40%"
> >
<el-col v-for="(item, index) in percentageoption" :key="index"> <el-col v-for="(item, index) in percentageoption" :key="index">
<span style="font-size: 14px; font-weight: bold">{{ item.name }}</span> <span style="font-size: 14px; font-weight: bold">{{ item.name }}</span>
: :
<el-progress <el-progress
:text-inside="true" :text-inside="true"
:stroke-width="24" :stroke-width="24"
:percentage="item.percentage" :percentage="item.percentage"
:status="item.status" :status="item.status"
:format="format" :format="format"
></el-progress> ></el-progress>
</el-col> </el-col>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue' import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { getTerminalUpLog } from '@/api/device-boot/Business' import { getTerminalUpLog } from '@/api/device-boot/Business'
import XEUtils from 'xe-utils' import XEUtils from 'xe-utils'
import { getDevTypeList } from '@/api/device-boot/modelManage' import { getDevTypeList } from '@/api/device-boot/modelManage'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
defineOptions({ defineOptions({
name: 'BusinessAdministrator/TerminalManagement/ProgramManagement' name: 'BusinessAdministrator/TerminalManagement/ProgramManagement'
}) })
const pageHeight = mainHeight(83) const pageHeight = mainHeight(83)
const dialogHeight = mainHeight(300) const dialogHeight = mainHeight(300)
const dictData = useDictData() const dictData = useDictData()
const teriminaloption: any = ref([]) const teriminaloption: any = ref([])
const teriminalstatusoption = ref([ const teriminalstatusoption = ref([
{ name: '全部', id: '' }, { name: '全部', id: '' },
{ name: '投运', id: 0 }, { name: '投运', id: 0 },
{ name: '检修', id: 1 }, { name: '检修', id: 1 },
{ name: '停运', id: 2 } { name: '停运', id: 2 }
]) ])
const stateoption = ref([ const stateoption = ref([
{ name: '全部', id: '' }, { name: '全部', id: '' },
{ name: '正常', id: 1 }, { name: '正常', id: 1 },
{ name: '中断', id: 0 } { name: '中断', id: 0 }
]) ])
const prodialogVisible = ref(false) const prodialogVisible = ref(false)
const dialogVisible = ref(false) const dialogVisible = ref(false)
const protitle = ref('') const protitle = ref('')
const treeData: any = ref([]) const treeData: any = ref([])
const treeDataCopy: any = ref([]) const treeDataCopy: any = ref([])
//进度条对象 //进度条对象
const percentageoption = ref([ const percentageoption = ref([
{ {
name: '1号测试终端', name: '1号测试终端',
status: 'exception', status: 'exception',
percentage: 20 percentage: 20
}, },
{ {
name: '2号测试终端', name: '2号测试终端',
status: 'warning', status: 'warning',
percentage: 50 percentage: 50
}, },
{ {
name: '3号测试终端', name: '3号测试终端',
status: 'success', status: 'success',
percentage: 90 percentage: 90
} }
]) ])
const programoption: any = ref([]) const programoption: any = ref([])
const logtableData: any = ref([]) const logtableData: any = ref([])
const tableRef = ref() const tableRef = ref()
const status = ref('') const status = ref('')
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/device-boot/version/getTerminalVersionList', url: '/device-boot/version/getTerminalVersionList',
method: 'POST', method: 'POST',
column: [], column: [],
loadCallback: () => { loadCallback: () => {
// tableStore.table.data.forEach((item: any) => { // tableStore.table.data.forEach((item: any) => {
// if (item.children.length > 0) { // if (item.children.length > 0) {
// item.id = item.children[0].pid // item.id = item.children[0].pid
// } // }
// }) // })
treeData.value = tree2List(tableStore.table.data, Math.random() * 1000) treeData.value = tree2List(tableStore.table.data, Math.random() * 1000)
treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value)) treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value))
setTimeout(() => { setTimeout(() => {
tableRef.value.setAllTreeExpand(true) tableRef.value.setAllTreeExpand(true)
}, 0) }, 0)
} }
}) })
tableStore.table.params.teriminal = '' tableStore.table.params.teriminal = ''
tableStore.table.params.state = '' tableStore.table.params.state = ''
tableStore.table.params.program = '' tableStore.table.params.program = ''
tableStore.table.params.searchEvent = '' tableStore.table.params.searchEvent = ''
tableStore.table.params.filterName = '' tableStore.table.params.filterName = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
const tree2List = (list: any, id: any) => { const tree2List = (list: any, id: any) => {
//存储结果的数组 //存储结果的数组
let arr: any = [] let arr: any = []
// 遍历 tree 数组 // 遍历 tree 数组
list.forEach((item: any) => { list.forEach((item: any) => {
item.uPid = id item.uPid = id
item.uId = Math.random() * 1000 item.uId = Math.random() * 1000
// 判断item是否存在children // 判断item是否存在children
if (!item.children) return arr.push(item) if (!item.children) return arr.push(item)
// 函数递归对children数组进行tree2List的转换 // 函数递归对children数组进行tree2List的转换
const children = tree2List(item.children, item.uId) const children = tree2List(item.children, item.uId)
// 删除item的children属性 // 删除item的children属性
delete item.children delete item.children
// 把item和children数组添加至结果数组 // 把item和children数组添加至结果数组
//..children: 意思是把children数组展开 //..children: 意思是把children数组展开
arr.push(item, ...children) arr.push(item, ...children)
}) })
// 返回结果数组 // 返回结果数组
return arr return arr
} }
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
tableStore.table.params.searchState = 0 tableStore.table.params.searchState = 0
onMounted(() => { onMounted(() => {
getDevTypeList().then(res => { getDevTypeList().then(res => {
teriminaloption.value = res.data teriminaloption.value = res.data
}) })
tableStore.index() tableStore.index()
}) })
const add = () => {} const add = () => {}
const updateprogram = (row: any) => { const updateprogram = (row: any) => {
protitle.value = row.name protitle.value = row.name
prodialogVisible.value = true prodialogVisible.value = true
} }
const queryview = (row: any) => { const queryview = (row: any) => {
dialogVisible.value = true dialogVisible.value = true
protitle.value = row.name protitle.value = row.name
let data = { let data = {
id: row.id id: row.id
} }
getTerminalUpLog(data).then((res: any) => { getTerminalUpLog(data).then((res: any) => {
logtableData.value = res.data logtableData.value = res.data
}) })
} }
const format = (percentage: any) => { const format = (percentage: any) => {
if (percentage <= 100 && percentage >= 90) { if (percentage <= 100 && percentage >= 90) {
status.value = 'success' status.value = 'success'
return percentage === 100 ? '升级成功' : `${percentage}%` return percentage === 100 ? '升级成功' : `${percentage}%`
} else if (percentage > 0 && percentage < 50) { } else if (percentage > 0 && percentage < 50) {
status.value = 'exception' status.value = 'exception'
return percentage <= 20 ? '升级失败' + percentage + '%' : `${percentage}%` return percentage <= 20 ? '升级失败' + percentage + '%' : `${percentage}%`
} else if (percentage > 0 && percentage <= 50) { } else if (percentage > 0 && percentage <= 50) {
status.value = 'warning' status.value = 'warning'
return percentage <= 50 ? '升级中断' : `${percentage}%` return percentage <= 50 ? '升级中断' : `${percentage}%`
} }
} }
const formFilter = (row: any) => { const formFilter = (row: any) => {
let title = '/' let title = '/'
if (row.cellValue != null) { if (row.cellValue != null) {
teriminaloption.value.forEach((item: any) => { teriminaloption.value.forEach((item: any) => {
if (item.id == row.cellValue) { if (item.id == row.cellValue) {
title = item.name title = item.name
} }
}) })
} }
return title return title
} }
// 表格过滤 // 表格过滤
const searchEvent = debounce(e => { const searchEvent = debounce(e => {
const filterVal = XEUtils.toValueString(tableStore.table.params.filterName).trim().toLowerCase() const filterVal = XEUtils.toValueString(tableStore.table.params.filterName).trim().toLowerCase()
if (filterVal) { if (filterVal) {
const options = { children: 'children' } const options = { children: 'children' }
const searchProps = ['name'] const searchProps = ['name']
const rest = XEUtils.searchTree( const rest = XEUtils.searchTree(
treeDataCopy, treeDataCopy,
(item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1), (item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1),
options options
) )
treeData.value = rest treeData.value = rest
// 搜索之后默认展开所有子节点 // 搜索之后默认展开所有子节点
} else { } else {
treeData.value = treeDataCopy treeData.value = treeDataCopy
} }
nextTick(() => { nextTick(() => {
const $table = tableRef.value const $table = tableRef.value
if ($table) { if ($table) {
$table.setAllTreeExpand(true) $table.setAllTreeExpand(true)
} }
}) })
}, 300) }, 300)
</script> </script>

View File

@@ -1,282 +1,282 @@
<template> <template>
<div class="default-main" style="position: relative"> <div class="default-main" style="position: relative">
<TableHeader> <TableHeader>
<template #select> <template #select>
<el-form-item label="终端型号"> <el-form-item label="终端型号">
<el-select <el-select
v-model="tableStore.table.params.devType" v-model="tableStore.table.params.devType"
filterable filterable
clearable clearable
placeholder="请选择终端型号" placeholder="请选择终端型号"
> >
<el-option <el-option
v-for="item in teriminaloption" v-for="item in teriminaloption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端状态"> <el-form-item label="终端状态">
<el-select v-model="tableStore.table.params.runFlag" clearable placeholder="请选择终端状态"> <el-select v-model="tableStore.table.params.runFlag" clearable placeholder="请选择终端状态">
<el-option <el-option
v-for="item in teriminalstatusoption" v-for="item in teriminalstatusoption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="通讯状态"> <el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.comFlag" clearable placeholder="请选择通讯状态"> <el-select v-model="tableStore.table.params.comFlag" clearable placeholder="请选择通讯状态">
<el-option <el-option
v-for="item in stateoption" v-for="item in stateoption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input <el-input
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"
clearable clearable
placeholder="输入关键字筛选" placeholder="输入关键字筛选"
/> />
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button type="primary" icon="el-icon-DataLine" @click="manage('终端状态管理', 0)"> <el-button type="primary" icon="el-icon-DataLine" @click="manage('终端状态管理', 0)">
终端状态管理 终端状态管理
</el-button> </el-button>
<!-- <el-button type="primary" icon="el-icon-Operation" @click="manage('流量套餐配置', 1)"> <!-- <el-button type="primary" icon="el-icon-Operation" @click="manage('流量套餐配置', 1)">
流量套餐配置 流量套餐配置
</el-button> --> </el-button> -->
<!-- <el-button type="primary" icon="el-icon-Menu" @click="manage('流量策略配置', 2)"> <!-- <el-button type="primary" icon="el-icon-Menu" @click="manage('流量策略配置', 2)">
流量策略配置 流量策略配置
</el-button> </el-button>
<el-button type="primary" icon="el-icon-Histogram" @click="liultjData">流量统计</el-button> --> <el-button type="primary" icon="el-icon-Histogram" @click="liultjData">流量统计</el-button> -->
<!-- <el-button type="primary" icon="el-icon-Setting" @click="resect">重启前置程序</el-button> --> <!-- <el-button type="primary" icon="el-icon-Setting" @click="resect">重启前置程序</el-button> -->
</template> </template>
</TableHeader> </TableHeader>
<div :style="`height: calc(${tableStore.table.height} + 58px)`"> <div :style="`height: calc(${tableStore.table.height} + 58px)`">
<vxe-table <vxe-table
v-loading="tableStore.table.loading" v-loading="tableStore.table.loading"
height="auto" height="auto"
auto-resize auto-resize
ref="tableRef" ref="tableRef"
v-bind="defaultAttribute" v-bind="defaultAttribute"
:data="treeData" :data="treeData"
show-overflow show-overflow
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }" :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
:scroll-y="{ enabled: true }" :scroll-y="{ enabled: true }"
:checkbox-config="{ labelField: 'name' }" :checkbox-config="{ labelField: 'name' }"
> >
<vxe-column <vxe-column
field="name" field="name"
align="left" align="left"
type="checkbox" type="checkbox"
title="电网拓扑" title="电网拓扑"
min-width="200" min-width="200"
tree-node tree-node
></vxe-column> ></vxe-column>
<vxe-column field="devType" title="终端型号"> <vxe-column field="devType" title="终端型号">
<template #default="{ row }"> <template #default="{ row }">
{{ teriminaloption.find((item: any) => item.id === row.devType)?.name }} {{ teriminaloption.find((item: any) => item.id === row.devType)?.name }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="version" title="版本信息"></vxe-column> <vxe-column field="version" title="版本信息"></vxe-column>
<vxe-column field="ip" title="网络参数"></vxe-column> <vxe-column field="ip" title="网络参数"></vxe-column>
<vxe-column field="runFlag" title="终端状态"> <vxe-column field="runFlag" title="终端状态">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.runFlag === 0" type="success" :disable-transitions="true" size="small">投运</el-tag> <el-tag v-if="row.runFlag === 0" type="success" :disable-transitions="true" size="small">投运</el-tag>
<el-tag v-if="row.runFlag === 1" type="warning" :disable-transitions="true" size="small">检修</el-tag> <el-tag v-if="row.runFlag === 1" type="warning" :disable-transitions="true" size="small">检修</el-tag>
<el-tag v-if="row.runFlag === 2" type="danger" :disable-transitions="true" size="small">停运</el-tag> <el-tag v-if="row.runFlag === 2" type="danger" :disable-transitions="true" size="small">停运</el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="comFlag" title="通讯状态"> <vxe-column field="comFlag" title="通讯状态">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.comFlag === 0" type="danger" :disable-transitions="true" size="small">中断</el-tag> <el-tag v-if="row.comFlag === 0" type="danger" :disable-transitions="true" size="small">中断</el-tag>
<el-tag v-if="row.comFlag === 1" type="success" :disable-transitions="true" size="small">正常</el-tag> <el-tag v-if="row.comFlag === 1" type="success" :disable-transitions="true" size="small">正常</el-tag>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column title="操作" width="160"> <vxe-column title="操作" width="160">
<template #default="{ row }"> <template #default="{ row }">
<!-- <el-button v-if="row.level === 4" type="primary" size="small" link @click="uesdealia(row)"> <!-- <el-button v-if="row.level === 4" type="primary" size="small" link @click="uesdealia(row)">
终端详情 终端详情
</el-button> --> </el-button> -->
<el-button v-if="row.level === 4" type="primary" size="small" link @click="log(row)"> <el-button v-if="row.level === 4" type="primary" size="small" link @click="log(row)">
查看日志 查看日志
</el-button> </el-button>
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
</div> </div>
<!-- 终端详情 --> <!-- 终端详情 -->
<detail ref="detailRef" /> <detail ref="detailRef" />
<!-- 配置 --> <!-- 配置 -->
<disposition ref="dispositionRef" @onSubmit="tableStore.index()" /> <disposition ref="dispositionRef" @onSubmit="tableStore.index()" />
<!-- 日志 --> <!-- 日志 -->
<Log ref="logRef" v-if="logFlag" @close="logFlag = false" /> <Log ref="logRef" v-if="logFlag" @close="logFlag = false" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick, reactive } from 'vue' import { ref, onMounted, provide, nextTick, reactive } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { getDevTypeList } from '@/api/device-boot/modelManage' import { getDevTypeList } from '@/api/device-boot/modelManage'
import XEUtils from 'xe-utils' import XEUtils from 'xe-utils'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import disposition from './components/disposition.vue' import disposition from './components/disposition.vue'
import detail from './components/detail.vue' import detail from './components/detail.vue'
import Log from './components/log.vue' import Log from './components/log.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
defineOptions({ defineOptions({
name: 'BusinessAdministrator/TerminalManagement/TerminalManagement' name: 'BusinessAdministrator/TerminalManagement/TerminalManagement'
}) })
const dispositionRef = ref() const dispositionRef = ref()
const detailRef = ref() const detailRef = ref()
const logRef = ref() const logRef = ref()
const dictData = useDictData() const dictData = useDictData()
const logFlag = ref(false) const logFlag = ref(false)
const teriminaloption: any = ref([]) const teriminaloption: any = ref([])
const teriminalstatusoption = ref([ const teriminalstatusoption = ref([
{ name: '全部', id: '' }, { name: '全部', id: '' },
{ name: '投运', id: 0 }, { name: '投运', id: 0 },
{ name: '检修', id: 1 }, { name: '检修', id: 1 },
{ name: '停运', id: 2 } { name: '停运', id: 2 }
]) ])
const stateoption = ref([ const stateoption = ref([
{ name: '全部', id: '' }, { name: '全部', id: '' },
{ name: '正常', id: 1 }, { name: '正常', id: 1 },
{ name: '中断', id: 0 } { name: '中断', id: 0 }
]) ])
const treeData: any = ref([]) const treeData: any = ref([])
const treeDataCopy: any = ref([]) const treeDataCopy: any = ref([])
const tableRef = ref() const tableRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/device-boot/maintain/getTerminalMainList', url: '/device-boot/maintain/getTerminalMainList',
method: 'POST', method: 'POST',
column: [], column: [],
loadCallback: () => { loadCallback: () => {
treeData.value = tree2List(tableStore.table.data, Math.random() * 1000) treeData.value = tree2List(tableStore.table.data, Math.random() * 1000)
treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value)) treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value))
setTimeout(() => { setTimeout(() => {
tableRef.value.setAllTreeExpand(true) tableRef.value.setAllTreeExpand(true)
}, 0) }, 0)
searchEvent() searchEvent()
} }
}) })
tableStore.table.params.devType = '' tableStore.table.params.devType = ''
tableStore.table.params.runFlag = '' tableStore.table.params.runFlag = ''
tableStore.table.params.comFlag = '' tableStore.table.params.comFlag = ''
tableStore.table.params.filterName = '' tableStore.table.params.filterName = ''
// 处理大数据卡顿 // 处理大数据卡顿
const tree2List = (list: any, id: any) => { const tree2List = (list: any, id: any) => {
//存储结果的数组 //存储结果的数组
let arr: any = [] let arr: any = []
// 遍历 tree 数组 // 遍历 tree 数组
list.forEach((item: any) => { list.forEach((item: any) => {
item.uPid = id item.uPid = id
item.uId = Math.random() * 1000 item.uId = Math.random() * 1000
// 判断item是否存在children // 判断item是否存在children
if (!item.children) return arr.push(item) if (!item.children) return arr.push(item)
// 函数递归对children数组进行tree2List的转换 // 函数递归对children数组进行tree2List的转换
const children = tree2List(item.children, item.uId) const children = tree2List(item.children, item.uId)
// 删除item的children属性 // 删除item的children属性
delete item.children delete item.children
// 把item和children数组添加至结果数组 // 把item和children数组添加至结果数组
//..children: 意思是把children数组展开 //..children: 意思是把children数组展开
arr.push(item, ...children) arr.push(item, ...children)
}) })
// 返回结果数组 // 返回结果数组
return arr return arr
} }
provide('tableStore', tableStore) provide('tableStore', tableStore)
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
tableStore.table.params.searchState = 0 tableStore.table.params.searchState = 0
onMounted(() => { onMounted(() => {
getDevTypeList().then(res => { getDevTypeList().then(res => {
teriminaloption.value = res.data teriminaloption.value = res.data
}) })
tableStore.index() tableStore.index()
}) })
// 终端状态管理 // 终端状态管理
const manage = (name: string, key: number) => { const manage = (name: string, key: number) => {
const $table = tableRef.value const $table = tableRef.value
if ($table) { if ($table) {
const selectRecords = $table const selectRecords = $table
.getCheckboxRecords() .getCheckboxRecords()
.filter((item: any) => item.level == 4) .filter((item: any) => item.level == 4)
.map(item => item.id) .map(item => item.id)
console.log('🚀 ~ deviceData ~ selectRecords:', selectRecords) console.log('🚀 ~ deviceData ~ selectRecords:', selectRecords)
if (selectRecords.length == 0) { if (selectRecords.length == 0) {
return ElMessage({ return ElMessage({
message: '请至少选择一台装置', message: '请至少选择一台装置',
type: 'warning' type: 'warning'
}) })
} }
dispositionRef.value.open({ dispositionRef.value.open({
title: name, title: name,
id: selectRecords, id: selectRecords,
key: key key: key
}) })
} }
} }
// 流量统计 // 流量统计
const liultjData = () => {} const liultjData = () => {}
// 重启前置程序 // 重启前置程序
const resect = () => {} const resect = () => {}
// 终端详情 // 终端详情
const uesdealia = (row: any) => { const uesdealia = (row: any) => {
detailRef.value.open(row) detailRef.value.open(row)
} }
// 流量详情 // 流量详情
const log = (row: any) => { const log = (row: any) => {
logFlag.value = true logFlag.value = true
setTimeout(() => { setTimeout(() => {
logRef.value.open(row) logRef.value.open(row)
}, 100) }, 100)
} }
// 表格过滤 // 表格过滤
const searchEvent = debounce(() => { const searchEvent = debounce(() => {
const filterVal = XEUtils.toValueString(tableStore.table.params.filterName).trim().toLowerCase() const filterVal = XEUtils.toValueString(tableStore.table.params.filterName).trim().toLowerCase()
if (filterVal) { if (filterVal) {
const options = { children: 'children' } const options = { children: 'children' }
const searchProps = ['name'] const searchProps = ['name']
const rest = XEUtils.searchTree( const rest = XEUtils.searchTree(
treeDataCopy.value, treeDataCopy.value,
(item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1), (item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1),
options options
) )
treeData.value = rest treeData.value = rest
// 搜索之后默认展开所有子节点 // 搜索之后默认展开所有子节点
} else { } else {
treeData.value = treeDataCopy.value treeData.value = treeDataCopy.value
} }
nextTick(() => { nextTick(() => {
const $table = tableRef.value const $table = tableRef.value
if ($table) { if ($table) {
$table.setAllTreeExpand(true) $table.setAllTreeExpand(true)
} }
}) })
}, 500) }, 500)
</script> </script>

View File

@@ -3073,7 +3073,7 @@ const setDown = () => {
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
if (VITE_FLAG) { if (VITE_FLAG) {
getYwZtSubstation({ orgId: '' }).then(res => { getYwZtSubstation({ orgId: '' }).then(res => {

View File

@@ -1,341 +1,341 @@
<template> <template>
<div class="default-main" :style="height"> <div class="default-main" :style="height">
<!-- 算法库 --> <!-- 算法库 -->
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes"> <splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size"> <pane :size="size">
<algorithmTree ref="treeRef" :default-expand-all="false" <algorithmTree ref="treeRef" :default-expand-all="false"
:default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []" :default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []"
:current-node-key="monitoringPoint.state.lineId" @node-click="handleNodeClick" :current-node-key="monitoringPoint.state.lineId" @node-click="handleNodeClick"
@init="handleNodeClick" @onAddTree="onAddTree"></algorithmTree> @init="handleNodeClick" @onAddTree="onAddTree"></algorithmTree>
</pane> </pane>
<pane style="background: #fff" :style="height"> <pane style="background: #fff" :style="height">
<div class="boxTop"> <div class="boxTop">
<div> <div>
<el-radio-group v-model="radio"> <el-radio-group v-model="radio">
<el-radio-button v-for="(item, i) in dotList?.childrens" :label="item.name" :value="i" /> <el-radio-button v-for="(item, i) in dotList?.childrens" :label="item.name" :value="i" />
</el-radio-group> </el-radio-group>
</div> </div>
<div v-if="information"> <div v-if="information">
<el-button icon="el-icon-Plus" type="primary" @click="addUser"> <el-button icon="el-icon-Plus" type="primary" @click="addUser">
新增 新增
</el-button> </el-button>
<el-button icon="el-icon-Edit" type="primary" @click="revise">修改</el-button> <el-button icon="el-icon-Edit" type="primary" @click="revise">修改</el-button>
<el-button icon="el-icon-Delete" type="primary" @click="deletes">删除</el-button> <el-button icon="el-icon-Delete" type="primary" @click="deletes">删除</el-button>
</div> </div>
</div> </div>
<div :style="heightTab"> <div :style="heightTab">
<vxe-table height="auto" v-bind="defaultAttribute" :data="dotList?.childrens[radio]?.children"> <vxe-table height="auto" v-bind="defaultAttribute" :data="dotList?.childrens[radio]?.children">
<vxe-column field="name" title="算法名称"></vxe-column> <vxe-column field="name" title="算法名称"></vxe-column>
<vxe-column field="createTime" title="创建时间"></vxe-column> <vxe-column field="createTime" title="创建时间"></vxe-column>
<vxe-column field="period" title="计算周期"> <vxe-column field="period" title="计算周期">
<template #default="{ row }"> <template #default="{ row }">
{{ {{
row.period == 0 row.period == 0
? '日' ? '日'
: row.period == 1 : row.period == 1
? '月' ? '月'
: row.period == 2 : row.period == 2
? '季' ? '季'
: row.period == 3 : row.period == 3
? '年' ? '年'
: '' : ''
}} }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="source" title="数据来源"></vxe-column> <vxe-column field="source" title="数据来源"></vxe-column>
<!-- <vxe-column field="useFLag" title="是否启用"> <!-- <vxe-column field="useFLag" title="是否启用">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.useFLag === 1 ? 'success' : 'info'" effect="dark" <el-tag :type="row.useFLag === 1 ? 'success' : 'info'" effect="dark"
style="cursor: pointer" @click="change(row)"> style="cursor: pointer" @click="change(row)">
{{ row.useFLag === 1 ? '' : '' }} {{ row.useFLag === 1 ? '' : '' }}
</el-tag> </el-tag>
</template> </template>
</vxe-column> --> </vxe-column> -->
<vxe-column field="definition" title="定义"> <vxe-column field="definition" title="定义">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link @click="view(row)">查看</el-button> <el-button type="primary" link @click="view(row)">查看</el-button>
</template> </template>
</vxe-column> </vxe-column>
<!-- <vxe-column title="操作" width="150px"> <!-- <vxe-column title="操作" width="150px">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link @click="edit(row)">修改</el-button> <el-button type="primary" link @click="edit(row)">修改</el-button>
<el-button type="danger" link @click="del(row)">删除</el-button> <el-button type="danger" link @click="del(row)">删除</el-button>
<el-popconfirm title="确定删除吗?" confirm-button-type='danger' @confirm="del(row)"> <el-popconfirm title="确定删除吗?" confirm-button-type='danger' @confirm="del(row)">
<template #reference> <template #reference>
<el-button type="danger" link>删除</el-button> <el-button type="danger" link>删除</el-button>
</template> </template>
</el-popconfirm> </el-popconfirm>
</template> </template>
</vxe-column> --> </vxe-column> -->
</vxe-table> </vxe-table>
</div> </div>
</pane> </pane>
</splitpanes> </splitpanes>
<!-- 树弹框 --> <!-- 树弹框 -->
<addTree ref="addTreeRef" @getTree="treeRef.loadData(dotList.id)" /> <addTree ref="addTreeRef" @getTree="treeRef.loadData(dotList.id)" />
<!-- 弹框 --> <!-- 弹框 -->
<PopupEdit ref="popupEditRef" v-if="popupEditFlag" <PopupEdit ref="popupEditRef" v-if="popupEditFlag"
@getTree="treeRef.loadData(dotList.id), (popupEditFlag = false)" /> @getTree="treeRef.loadData(dotList.id), (popupEditFlag = false)" />
<!-- 定义 --> <!-- 定义 -->
<el-dialog draggable v-model="viewFlag" title="定义" width="60%"> <el-dialog draggable v-model="viewFlag" title="定义" width="60%">
<div style="min-height: 300px; max-height: 55vh;"> <div style="min-height: 300px; max-height: 55vh;">
<div class="editor" ref="editorRef" v-html="summary" /> <div class="editor" ref="editorRef" v-html="summary" />
</div> </div>
</el-dialog> </el-dialog>
<!-- 删除 --> <!-- 删除 -->
<el-dialog draggable v-model="dialogVisible" title="请选择需要删除的数据" width="400"> <el-dialog draggable v-model="dialogVisible" title="请选择需要删除的数据" width="400">
<el-tree-select v-model="TreeValue" :data="TreeData" filterable check-strictly :props="defaultProps" <el-tree-select v-model="TreeValue" :data="TreeData" filterable check-strictly :props="defaultProps"
default-expand-all :render-after-expand="false" /> default-expand-all :render-after-expand="false" />
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button> <el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="del">删除</el-button> <el-button type="primary" @click="del">删除</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, provide } from 'vue' import { onMounted, ref, provide } from 'vue'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes' import { Splitpanes, Pane } from 'splitpanes'
import algorithmTree from '@/components/tree/pqs/algorithmTree.vue' import algorithmTree from '@/components/tree/pqs/algorithmTree.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getLineExport, getList, selectReleation } from '@/api/event-boot/report' import { getLineExport, getList, selectReleation } from '@/api/event-boot/report'
import addTree from './components/addTree.vue' import addTree from './components/addTree.vue'
import PopupEdit from './components/form.vue' import PopupEdit from './components/form.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint' import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { deleteyById } from '@/api/supervision-boot/database/index' import { deleteyById } from '@/api/supervision-boot/database/index'
import { queryAllAlgorithmLibrary, updateAlgorithmLibrary } from '@/api/supervision-boot/database/index' import { queryAllAlgorithmLibrary, updateAlgorithmLibrary } from '@/api/supervision-boot/database/index'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import katex from "katex"; import katex from "katex";
import "katex/dist/katex.css"; import "katex/dist/katex.css";
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
defineOptions({ defineOptions({
name: 'database/algorithm' name: 'database/algorithm'
}) })
const monitoringPoint = useMonitoringPoint() const monitoringPoint = useMonitoringPoint()
const height = mainHeight(20) const height = mainHeight(20)
const heightTab = mainHeight(82) const heightTab = mainHeight(82)
const size = ref(0) const size = ref(0)
const addTreeRef = ref() const addTreeRef = ref()
const editorRef = ref() const editorRef = ref()
const dialogVisible = ref(false) const dialogVisible = ref(false)
const viewFlag = ref(false) const viewFlag = ref(false)
const popupEditFlag = ref(false) const popupEditFlag = ref(false)
const treeRef = ref() const treeRef = ref()
const summary = ref('') const summary = ref('')
const popupEditRef = ref() const popupEditRef = ref()
const TreeData = ref([]) const TreeData = ref([])
const TreeValue = ref([]) const TreeValue = ref([])
const information = adminInfo.roleCode.includes('information_info') const information = adminInfo.roleCode.includes('information_info')
const defaultProps = { const defaultProps = {
label: 'name', label: 'name',
value: 'id' value: 'id'
} }
const dotList: any = ref() const dotList: any = ref()
const templatePolicy: any = ref([]) const templatePolicy: any = ref([])
// const tableStore = new TableStore({ // const tableStore = new TableStore({
// url: '/supervision-boot/libalgorithm/queryAllAlgorithmLibrary', // url: '/supervision-boot/libalgorithm/queryAllAlgorithmLibrary',
// method: 'GET', // method: 'GET',
// column: [ // column: [
// { title: '算法名称', field: 'name' }, // { title: '算法名称', field: 'name' },
// { // {
// title: '定义', // title: '定义',
// field: 'name1' // field: 'name1'
// }, // },
// { // {
// title: '计算公式', // title: '计算公式',
// field: 'name2' // field: 'name2'
// }, // },
// { // {
// title: '计算周期', // title: '计算周期',
// field: 'name3' // field: 'name3'
// }, // },
// { // {
// title: '数据来源', // title: '数据来源',
// field: 'name4' // field: 'name4'
// }, // },
// { // {
// title: '是否启用', // title: '是否启用',
// field: 'name5', // field: 'name5',
// render: 'tag', // render: 'tag',
// effect: 'dark', // effect: 'dark',
// custom: { // custom: {
// 0: 'info', // 0: 'info',
// 1: 'success' // 1: 'success'
// }, // },
// replaceValue: { // replaceValue: {
// 0: '否', // 0: '否',
// 1: '是' // 1: '是'
// } // }
// } // }
// ], // ],
// loadCallback: () => {} // loadCallback: () => {}
// }) // })
const radio = ref(0) const radio = ref(0)
// 新增弹框 // 新增弹框
const addUser = () => { const addUser = () => {
popupEditFlag.value = true popupEditFlag.value = true
setTimeout(() => { setTimeout(() => {
popupEditRef.value.open({ popupEditRef.value.open({
title: '新增算法' title: '新增算法'
}) })
}, 100) }, 100)
} }
// 修改弹框 // 修改弹框
const revise = () => { const revise = () => {
popupEditFlag.value = true popupEditFlag.value = true
setTimeout(() => { setTimeout(() => {
popupEditRef.value.open({ popupEditRef.value.open({
title: '修改算法', title: '修改算法',
row: dotList.value row: dotList.value
}) })
}, 100) }, 100)
} }
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
// tableStore.index() // tableStore.index()
}) })
const view = (row: any) => { const view = (row: any) => {
viewFlag.value = true viewFlag.value = true
summary.value = row.definition summary.value = row.definition
setTimeout(() => { setTimeout(() => {
const spans = document.querySelectorAll('span[data-value]'); const spans = document.querySelectorAll('span[data-value]');
// 遍历每个 span 标签 // 遍历每个 span 标签
spans.forEach(function (span) { spans.forEach(function (span) {
let val = katex.renderToString(span.getAttribute('data-value'), { let val = katex.renderToString(span.getAttribute('data-value'), {
throwOnError: false, throwOnError: false,
}) })
// var newDiv = document.createElement('div'); // var newDiv = document.createElement('div');
var newDiv = span var newDiv = span
newDiv.innerHTML = val; newDiv.innerHTML = val;
span.parentNode.replaceChild(newDiv, span); span.parentNode.replaceChild(newDiv, span);
}); });
}, 100) }, 100)
// //
} }
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
if (data.pid != '0') { if (data.pid != '0') {
dotList.value = data dotList.value = data
radio.value = 0 radio.value = 0
} }
} }
const onAddTree = () => { const onAddTree = () => {
addTreeRef.value.open('新增') addTreeRef.value.open('新增')
} }
const deletes = () => { const deletes = () => {
TreeValue.value = [] TreeValue.value = []
queryAllAlgorithmLibrary().then(res => { queryAllAlgorithmLibrary().then(res => {
TreeData.value = res.data TreeData.value = res.data
}) })
dialogVisible.value = true dialogVisible.value = true
} }
// 删除 // 删除
const del = () => { const del = () => {
if (TreeValue.value.length == 0) { if (TreeValue.value.length == 0) {
return ElMessage.warning('请选择数据') return ElMessage.warning('请选择数据')
} }
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', { ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
deleteyById({ id: TreeValue.value }).then(res => { deleteyById({ id: TreeValue.value }).then(res => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
dialogVisible.value = false dialogVisible.value = false
treeRef.value.loadData() treeRef.value.loadData()
}) })
}) })
// if (TreeValue.value.length > 0) { // if (TreeValue.value.length > 0) {
// ElMessage.warning('请选择数据') // ElMessage.warning('请选择数据')
// return // return
// } // }
} }
// 启用 // 启用
const change = (row: any) => { const change = (row: any) => {
console.log('🚀 ~ change ~ row:', row) console.log('🚀 ~ change ~ row:', row)
ElMessageBox.confirm(`请确认是否${row.useFLag == 0 ? '启用' : '关闭'}算法?`, '提示', { ElMessageBox.confirm(`请确认是否${row.useFLag == 0 ? '启用' : '关闭'}算法?`, '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
updateAlgorithmLibrary({ ...row, useFLag: row.useFLag == 0 ? 1 : 0 }).then(res => { updateAlgorithmLibrary({ ...row, useFLag: row.useFLag == 0 ? 1 : 0 }).then(res => {
ElMessage.success(row.useFLag == 0 ? '启用' : '关闭' + '成功') ElMessage.success(row.useFLag == 0 ? '启用' : '关闭' + '成功')
treeRef.value.loadData(dotList.value.id) treeRef.value.loadData(dotList.value.id)
}) })
}) })
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.splitpanes.default-theme .splitpanes__pane { .splitpanes.default-theme .splitpanes__pane {
background: #eaeef1; background: #eaeef1;
} }
.grid-content { .grid-content {
text-align: center; text-align: center;
} }
.el-divider--horizontal { .el-divider--horizontal {
margin: 10px 0; margin: 10px 0;
} }
.mTop { .mTop {
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
} }
.boxTop { .boxTop {
height: 52px; height: 52px;
padding: 10px 10px 10px 0; padding: 10px 10px 10px 0;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.editor { .editor {
table { table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
} }
th, th,
td { td {
border: 1px solid black; border: 1px solid black;
padding: 8px; padding: 8px;
text-align: center; text-align: center;
} }
th { th {
background-color: #f2f2f2; background-color: #f2f2f2;
font-weight: bold; font-weight: bold;
} }
td { td {
background-color: #ffffff; background-color: #ffffff;
} }
} }
</style> </style>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="default-main"> <div >
<TableHeader ref="TableHeaderRef"> <TableHeader ref="TableHeaderRef">
<template v-slot:select> <template v-slot:select>
<el-form-item label="名称"> <el-form-item label="名称">
@@ -26,6 +26,7 @@ const tableStore = new TableStore({
url: '/supervision-boot/libModel/pageLibModelQuery', url: '/supervision-boot/libModel/pageLibModelQuery',
method: 'POST', method: 'POST',
showPage: true, // 确保启用分页 showPage: true, // 确保启用分页
publicHeight: 60,
column: [ column: [
{ {
title: '典型设备', title: '典型设备',

View File

@@ -1,15 +1,19 @@
<template> <template>
<div class="default-main"> <div>
<TableHeader> <TableHeader>
<template v-slot:select> <template v-slot:select>
<el-form-item label="名称"> <el-form-item label="名称">
<el-input v-model="tableStore.table.params.searchValue" clearable <el-input
placeholder="请输入搜索名称" maxlength="32" show-word-limit/> v-model="tableStore.table.params.searchValue"
clearable
placeholder="请输入搜索名称"
maxlength="32"
show-word-limit
/>
</el-form-item> </el-form-item>
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" isGroup/> <Table ref="tableRef" isGroup />
</div> </div>
</template> </template>
<script setup lang="tsx"> <script setup lang="tsx">
@@ -23,7 +27,8 @@ const tableRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/supervision-boot/libModel/pageLibModelQuery', url: '/supervision-boot/libModel/pageLibModelQuery',
method: 'POST', method: 'POST',
column: [ publicHeight: 60,
column: [
{ {
title: '谐波源', title: '谐波源',
children: [ children: [
@@ -32,12 +37,14 @@ const tableStore = new TableStore({
title: '序号', title: '序号',
width: '80', width: '80',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (
(tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
)
} }
}, },
{ field: 'name', title: '名称',minWidth: 200 }, { field: 'name', title: '名称', minWidth: 200 },
{ field: 'voltage', title: '电压等级',minWidth: 200 }, { field: 'voltage', title: '电压等级', minWidth: 200 },
{ field: 'capacity', title: '容量',minWidth: 200 } { field: 'capacity', title: '容量', minWidth: 200 }
] ]
}, },
{ {
@@ -50,13 +57,13 @@ const tableStore = new TableStore({
})) }))
} }
], ],
// 在请求发送前处理参数 // 在请求发送前处理参数
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.table.params.pageSize = 100 tableStore.table.params.pageSize = 100
}, },
resetCallback: () => { resetCallback: () => {
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
}, }
}) })
tableStore.table.params.type = 1 tableStore.table.params.type = 1
@@ -70,5 +77,4 @@ const queryData = () => {
defineExpose({ defineExpose({
queryData queryData
}) })
</script> </script>

View File

@@ -1,212 +1,212 @@
<template> <template>
<div class="default-main" :style="height"> <div class="default-main" :style="height">
<!-- 标准库 --> <!-- 标准库 -->
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes"> <splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size"> <pane :size="size">
<standardTree ref="treeRef" <standardTree ref="treeRef"
:default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []" :default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []"
:current-node-key="monitoringPoint.state.lineId" @node-click="handleNodeClick" :current-node-key="monitoringPoint.state.lineId" @node-click="handleNodeClick"
@init="handleNodeClick"></standardTree> @init="handleNodeClick"></standardTree>
</pane> </pane>
<pane style="background: #fff" :style="height"> <pane style="background: #fff" :style="height">
<div class="pd10" style="display: flex; justify-content: end"> <div class="pd10" style="display: flex; justify-content: end">
<el-button icon="el-icon-Plus" type="primary" @click="addUser" v-if="information">新增</el-button> <el-button icon="el-icon-Plus" type="primary" @click="addUser" v-if="information">新增</el-button>
<el-button icon="el-icon-Edit" type="primary" @click="editUser" v-if="information">修改</el-button> <el-button icon="el-icon-Edit" type="primary" @click="editUser" v-if="information">修改</el-button>
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven" <el-button icon="el-icon-Delete" type="primary" @click="deleteEven"
v-if="information">删除</el-button> v-if="information">删除</el-button>
<el-button icon="el-icon-Download" type="primary" @click="download" v-if="flag">下载</el-button> <el-button icon="el-icon-Download" type="primary" @click="download" v-if="flag">下载</el-button>
</div> </div>
<el-empty v-if="url.length == 0" description="暂无数据" class="custom-empty" <el-empty v-if="url.length == 0" description="暂无数据" class="custom-empty"
:style="`height: calc(${height.height} - 60px);`" /> :style="`height: calc(${height.height} - 60px);`" />
<div :style="`height: calc(${height.height} - 60px);overflow: auto;`" v-else> <div :style="`height: calc(${height.height} - 60px);overflow: auto;`" v-else>
<vue-office-docx v-if="url.includes('.doc') || url.includes('.docx')" :src="url" /> <vue-office-docx v-if="url.includes('.doc') || url.includes('.docx')" :src="url" />
<vue-office-excel v-if="url.includes('.xls') || url.includes('.xlsx')" :src="url" <vue-office-excel v-if="url.includes('.xls') || url.includes('.xlsx')" :src="url"
:options="excelOptions" /> :options="excelOptions" />
<!-- <vue-office-pdf v-if="url.includes('.pdf')" :src="url"/> --> <!-- <vue-office-pdf v-if="url.includes('.pdf')" :src="url"/> -->
<iframe v-if="url.includes('.pdf')" :src="url" style="width: 100%; height: 99%"></iframe> <iframe v-if="url.includes('.pdf')" :src="url" style="width: 100%; height: 99%"></iframe>
<img v-if=" <img v-if="
url.includes('.png') || url.includes('.jpg') || url.includes('.gif') || url.includes('.bmp') url.includes('.png') || url.includes('.jpg') || url.includes('.gif') || url.includes('.bmp')
" :src="url" /> " :src="url" />
</div> </div>
</pane> </pane>
</splitpanes> </splitpanes>
<!-- 新增 --> <!-- 新增 -->
<addTree ref="addTreeRef" @onSubmit="treeRef.loadData(dotList.id)"></addTree> <addTree ref="addTreeRef" @onSubmit="treeRef.loadData(dotList.id)"></addTree>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, provide } from 'vue' import { onMounted, ref, provide } from 'vue'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes' import { Splitpanes, Pane } from 'splitpanes'
import standardTree from '@/components/tree/pqs/standardTree.vue' import standardTree from '@/components/tree/pqs/standardTree.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import addTree from './components/addTree.vue' import addTree from './components/addTree.vue'
import { useMonitoringPoint } from '@/stores/monitoringPoint' import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getFileNameAndFilePath, downloadFile } from '@/api/system-boot/file' import { getFileNameAndFilePath, downloadFile } from '@/api/system-boot/file'
//引入相关样式 //引入相关样式
import '@vue-office/excel/lib/index.css' import '@vue-office/excel/lib/index.css'
//引入VueOfficeDocx组件 //引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx' import VueOfficeDocx from '@vue-office/docx'
import VueOfficeExcel from '@vue-office/excel' import VueOfficeExcel from '@vue-office/excel'
//引入VueOfficePdf组件 //引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf' import VueOfficePdf from '@vue-office/pdf'
import { deleteyLibstandard } from '@/api/supervision-boot/database/index' import { deleteyLibstandard } from '@/api/supervision-boot/database/index'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
defineOptions({ defineOptions({
name: 'database/standard' name: 'database/standard'
}) })
const excelOptions = ref({}) const excelOptions = ref({})
const monitoringPoint = useMonitoringPoint() const monitoringPoint = useMonitoringPoint()
const height = mainHeight(20) const height = mainHeight(20)
const size = ref(0) const size = ref(0)
const treeRef = ref() const treeRef = ref()
const addTreeRef = ref() const addTreeRef = ref()
const url = ref('') const url = ref('')
const dotList: any = ref({}) const dotList: any = ref({})
const flag: any = ref(false) const flag: any = ref(false)
const information = adminInfo.roleCode.includes('information_info') const information = adminInfo.roleCode.includes('information_info')
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
console.log("🚀 ~ handleNodeClick ~ data:", data) console.log("🚀 ~ handleNodeClick ~ data:", data)
dotList.value = data dotList.value = data
url.value = '' url.value = ''
flag.value = false flag.value = false
if (data?.url != null && data?.url != '') { if (data?.url != null && data?.url != '') {
flag.value = true flag.value = true
setTimeout(() => { setTimeout(() => {
url.value = `/api-docx/excelreport` + data.url url.value = `/api-docx/excelreport` + data.url
excelOptions.value = { xls: data.url.split('.')[1] == 'xls' ? true : false } excelOptions.value = { xls: data.url.split('.')[1] == 'xls' ? true : false }
// getFileNameAndFilePath({ filePath: data.url }).then(res => { // getFileNameAndFilePath({ filePath: data.url }).then(res => {
// url.value = res.data.url // url.value = res.data.url
// }) // })
}, 100) }, 100)
} }
} }
// 删除 // 删除
const deleteEven = () => { const deleteEven = () => {
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', { ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
deleteyLibstandard({ id: dotList.value.id }).then(() => { deleteyLibstandard({ id: dotList.value.id }).then(() => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: '删除成功!' message: '删除成功!'
}) })
setTimeout(() => { setTimeout(() => {
treeRef.value.loadData() treeRef.value.loadData()
}, 100) }, 100)
}) })
}) })
} }
const addUser = () => { const addUser = () => {
addTreeRef.value.open('新增') addTreeRef.value.open('新增')
} }
const editUser = () => { const editUser = () => {
addTreeRef.value.open('修改', dotList.value) addTreeRef.value.open('修改', dotList.value)
} }
// 下载 // 下载
const download = () => { const download = () => {
let url = dotList.value.url let url = dotList.value.url
let urls = url let urls = url
let name = url.match(/\/([^/]+)\.(\w+)$/)[1] let name = url.match(/\/([^/]+)\.(\w+)$/)[1]
downloadFile({ filePath: url }).then((res: any) => { downloadFile({ filePath: url }).then((res: any) => {
let blob = new Blob([res], { let blob = new Blob([res], {
type: urls.includes('.pdf') type: urls.includes('.pdf')
? 'application/pdf' ? 'application/pdf'
: urls.includes('.docx') : urls.includes('.docx')
? 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
: urls.includes('.xls') : urls.includes('.xls')
? 'application/vnd.ms-excel' ? 'application/vnd.ms-excel'
: urls.includes('.xlsx') : urls.includes('.xlsx')
? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
: urls.includes('.png') : urls.includes('.png')
? 'image/png' ? 'image/png'
: urls.includes('.jpeg') : urls.includes('.jpeg')
? 'image/jpeg' ? 'image/jpeg'
: urls.includes('.jpg') : urls.includes('.jpg')
? 'image/jpg' ? 'image/jpg'
: '' : ''
}) })
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') const link = document.createElement('a')
link.href = url link.href = url
link.download = name link.download = name
document.body.appendChild(link) document.body.appendChild(link)
link.click() link.click()
link.remove() link.remove()
}) })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.splitpanes.default-theme .splitpanes__pane { .splitpanes.default-theme .splitpanes__pane {
background: #eaeef1; background: #eaeef1;
} }
.grid-content { .grid-content {
text-align: center; text-align: center;
} }
.divBox { .divBox {
width: 250px; width: 250px;
height: 31px; height: 31px;
margin: auto; margin: auto;
line-height: 32px; line-height: 32px;
border: 1px solid #c9c9c9; border: 1px solid #c9c9c9;
&:hover { &:hover {
border: 1px solid #002255; border: 1px solid #002255;
} }
} }
.box { .box {
padding: 10px; padding: 10px;
// margin-top: 10px; // margin-top: 10px;
overflow-y: auto; overflow-y: auto;
font-size: 15px; font-size: 15px;
} }
.el-divider--horizontal { .el-divider--horizontal {
margin: 10px 0; margin: 10px 0;
} }
.mTop { .mTop {
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
} }
/* 自定义 el-empty 的样式 */ /* 自定义 el-empty 的样式 */
:deep(.custom-empty) { :deep(.custom-empty) {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100%; height: 100%;
/* 调整高度 */ /* 调整高度 */
padding: 20px; padding: 20px;
/* 调整内边距 */ /* 调整内边距 */
.el-empty__image { .el-empty__image {
display: none; display: none;
/* 隐藏默认图片 */ /* 隐藏默认图片 */
} }
.el-empty__description { .el-empty__description {
font-size: 14px; font-size: 14px;
/* 调整字体大小 */ /* 调整字体大小 */
color: var(--vxe-font-color); color: var(--vxe-font-color);
} }
} }
</style> </style>

View File

@@ -1,282 +1,282 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<div v-show="view"> <div v-show="view">
<TableHeader datePicker area showExport> <TableHeader datePicker area showExport>
<template #select> <template #select>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.searchValue" placeholder="输入关键字筛选" />
</el-form-item> </el-form-item>
<el-form-item label="统计类型:"> <el-form-item label="统计类型:">
<el-select <el-select
v-model="tableStore.table.params.statisticalType" v-model="tableStore.table.params.statisticalType"
value-key="id" value-key="id"
placeholder="请选择统计类型" placeholder="请选择统计类型"
> >
<el-option <el-option
v-for="item in classificationData" v-for="item in classificationData"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级:">
<el-select <el-select
v-model="tableStore.table.params.scale" v-model="tableStore.table.params.scale"
multiple multiple
collapse-tags collapse-tags
clearable clearable
value-key="id" value-key="id"
placeholder="请选择电压等级" placeholder="请选择电压等级"
> >
<el-option <el-option
v-for="item in voltageleveloption" v-for="item in voltageleveloption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家:">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
multiple multiple
collapse-tags collapse-tags
clearable clearable
value-key="id" value-key="id"
placeholder="请选择终端厂家" placeholder="请选择终端厂家"
> >
<el-option <el-option
v-for="item in terminaloption" v-for="item in terminaloption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型:">
<el-select <el-select
v-model="tableStore.table.params.loadType" v-model="tableStore.table.params.loadType"
multiple multiple
collapse-tags collapse-tags
clearable clearable
value-key="id" value-key="id"
placeholder="请选择干扰源类型" placeholder="请选择干扰源类型"
> >
<el-option <el-option
v-for="item in interfereoption" v-for="item in interfereoption"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item" :value="item"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
<template v-slot:operation> <template v-slot:operation>
<el-button :icon="Download" type="primary" @click="download">下载波形</el-button> <el-button :icon="Download" type="primary" @click="download">下载波形</el-button>
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" :checkboxConfig="checkboxConfig" /> <Table ref="tableRef" :checkboxConfig="checkboxConfig" />
</div> </div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view"> <div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
<waveForm ref="waveFormRef" senior :boxoList="boxoList" :wp="wp" @backbxlb="backbxlb" /> <waveForm ref="waveFormRef" senior :boxoList="boxoList" :wp="wp" @backbxlb="backbxlb" />
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide } from 'vue' import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import { Download } from '@element-plus/icons-vue' import { Download } from '@element-plus/icons-vue'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import waveForm from '@/components/echarts/waveForm.vue' import waveForm from '@/components/echarts/waveForm.vue'
import { getMonitorEventAnalyseWave } from '@/api/event-boot/transient' import { getMonitorEventAnalyseWave } from '@/api/event-boot/transient'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import { VxeTablePropTypes } from 'vxe-table' import { VxeTablePropTypes } from 'vxe-table'
import { downloadWaveFile } from '@/api/event-boot/transient' import { downloadWaveFile } from '@/api/event-boot/transient'
const dictData = useDictData() const dictData = useDictData()
defineOptions({ defineOptions({
name: 'harmonic-boot/area/TransientEventList' name: 'harmonic-boot/area/TransientEventList'
}) })
const pageHeight = mainHeight(20) const pageHeight = mainHeight(20)
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type']) const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand') const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const terminaloption = dictData.getBasicData('Dev_Manufacturers') const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const interfereoption = dictData.getBasicData('Interference_Source') const interfereoption = dictData.getBasicData('Interference_Source')
const eventList = dictData.getBasicData('Event_Statis') const eventList = dictData.getBasicData('Event_Statis')
const view = ref(true) const view = ref(true)
const view2 = ref(false) const view2 = ref(false)
const waveFormRef = ref() const waveFormRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/event-boot/transient/getTransientValue', url: '/event-boot/transient/getTransientValue',
method: 'POST', method: 'POST',
column: [ column: [
{ width: '60', type: 'checkbox' }, { width: '60', type: 'checkbox' },
{ {
field: 'index', field: 'index',
title: '序号', title: '序号',
width: '60', width: '60',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'startTime', title: '暂降发生时刻', minWidth: '180' }, { field: 'startTime', title: '暂降发生时刻', minWidth: '180' },
{ field: 'lineName', title: '监测点名称', minWidth: '180' }, { field: 'lineName', title: '监测点名称', minWidth: '180' },
{ field: 'gdName', title: '供电公司', minWidth: '120' }, { field: 'gdName', title: '供电公司', minWidth: '120' },
{ field: 'subName', title: '变电站', minWidth: '150' }, { field: 'subName', title: '变电站', minWidth: '150' },
{ field: 'ip', title: '网络参数', minWidth: '110' }, { field: 'ip', title: '网络参数', minWidth: '110' },
{ field: 'scale', title: '电压等级', minWidth: '110' }, { field: 'scale', title: '电压等级', minWidth: '110' },
// { // {
// field: 'advanceType', // field: 'advanceType',
// title: '暂降类型', // title: '暂降类型',
// minWidth: '90', // minWidth: '90',
// formatter: (row: any) => { // formatter: (row: any) => {
// return row.cellValue || '其他' // return row.cellValue || '其他'
// } // }
// }, // },
{ {
field: 'advanceReason', field: 'advanceReason',
title: '暂降原因', title: '暂降原因',
minWidth: '90', minWidth: '90',
formatter: (row: any) => { formatter: (row: any) => {
return row.cellValue || '其他' return row.cellValue || '其他'
} }
}, },
{ {
field: 'eventType', field: 'eventType',
title: '暂态统计类型', title: '暂态统计类型',
minWidth: '120', minWidth: '120',
formatter: (row: any) => { formatter: (row: any) => {
return eventList.filter(item => item.id === row.cellValue)[0]?.name return eventList.filter(item => item.id === row.cellValue)[0]?.name
} }
}, },
// { // {
// field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => { // field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => {
// return row.cellValue.toFixed(2) // return row.cellValue.toFixed(2)
// } // }
// }, // },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
title: '暂降幅值(%)', title: '暂降幅值(%)',
minWidth: '110', minWidth: '110',
formatter: (row: any) => { formatter: (row: any) => {
return (row.cellValue * 100).toFixed(2) return (row.cellValue * 100).toFixed(2)
} }
}, },
{ {
field: 'eventDescribe', field: 'eventDescribe',
title: '暂降深度(%)', title: '暂降深度(%)',
minWidth: '110', minWidth: '110',
formatter: (row: any) => { formatter: (row: any) => {
let data: any = (100 - row.row.featureAmplitude * 100).toFixed(2) let data: any = (100 - row.row.featureAmplitude * 100).toFixed(2)
return data >= 0 ? data : '/' return data >= 0 ? data : '/'
} }
}, },
{ field: 'duration', title: '持续时间(s)', minWidth: '100' }, { field: 'duration', title: '持续时间(s)', minWidth: '100' },
{ {
title: '操作', title: '操作',
width: '120', width: '120',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
{ {
name: 'edit', name: 'edit',
title: '波形分析', title: '波形分析',
type: 'primary', type: 'primary',
disabled: row => { disabled: row => {
return row.fileFlag == 0 return row.fileFlag == 0
}, },
icon: 'el-icon-Plus', icon: 'el-icon-Plus',
render: 'basicButton', render: 'basicButton',
click: async row => { click: async row => {
view.value = false view.value = false
setTimeout(() => { setTimeout(() => {
waveFormRef.value.open(row) waveFormRef.value.open(row)
}, 100) }, 100)
// row.loading = true // row.loading = true
// boxoList.value = row // boxoList.value = row
// await getMonitorEventAnalyseWave({ id: row.eventId, systemType: 0 }) // await getMonitorEventAnalyseWave({ id: row.eventId, systemType: 0 })
// .then(res => { // .then(res => {
// row.loading = false // row.loading = false
// if (res != undefined) { // if (res != undefined) {
// wp.value = res.data // wp.value = res.data
// view.value = false // view.value = false
// view2.value = true // view2.value = true
// } // }
// }) // })
// .catch(() => { // .catch(() => {
// row.loading = false // row.loading = false
// }) // })
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '暂无波形', title: '暂无波形',
type: '', type: '',
disabled: row => { disabled: row => {
return row.fileFlag != 0 return row.fileFlag != 0
}, },
icon: 'el-icon-Plus', icon: 'el-icon-Plus',
render: 'basicButton' render: 'basicButton'
} }
] ]
} }
], ],
loadCallback: () => {} loadCallback: () => {}
}) })
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
tableStore.table.params.statisticalType = classificationData.filter(item => item.name == '电网拓扑')[0] tableStore.table.params.statisticalType = classificationData.filter(item => item.name == '电网拓扑')[0]
tableStore.table.params.scale = [] tableStore.table.params.scale = []
tableStore.table.params.manufacturer = [] tableStore.table.params.manufacturer = []
tableStore.table.params.loadType = [] tableStore.table.params.loadType = []
tableStore.table.params.monitorFlag = 2 tableStore.table.params.monitorFlag = 2
tableStore.table.params.powerFlag = 2 tableStore.table.params.powerFlag = 2
tableStore.table.params.statFlag = true tableStore.table.params.statFlag = true
tableStore.table.params.isType = 0 tableStore.table.params.isType = 0
const boxoList = ref({}) const boxoList = ref({})
const wp = ref({}) const wp = ref({})
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
tableStore.index() tableStore.index()
}) })
const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({ const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({
checkMethod: ({ row }) => { checkMethod: ({ row }) => {
return row.fileFlag === 1 return row.fileFlag === 1
} }
}) })
const backbxlb = () => { const backbxlb = () => {
view.value = true view.value = true
view2.value = false view2.value = false
} }
// 下载波形 // 下载波形
const download = () => { const download = () => {
if (!tableStore.table.selection.length) { if (!tableStore.table.selection.length) {
ElMessage.warning('请选择数据') ElMessage.warning('请选择数据')
return return
} }
downloadWaveFile({ downloadWaveFile({
lineId: tableStore.table.selection.map((item: any) => item.eventId) lineId: tableStore.table.selection.map((item: any) => item.eventId)
}).then((res: any) => { }).then((res: any) => {
if (res.type == 'application/json') { if (res.type == 'application/json') {
ElMessage.warning('暂无可下载的波形文件!') ElMessage.warning('暂无可下载的波形文件!')
return return
} }
ElMessage.info('下载中......') ElMessage.info('下载中......')
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接 let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签 const link = document.createElement('a') // 创建a标签
link.href = url link.href = url
link.download = '波形分析下载' // 设置下载的文件名 link.download = '波形分析下载' // 设置下载的文件名
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) //释放标签 document.body.removeChild(link) //释放标签
}) })
} }
</script> </script>

View File

@@ -571,7 +571,7 @@ const group = (chart: any, myChartDom: any) => {
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
userDataList({ userDataList({
pageNum: 1, pageNum: 1,

View File

@@ -32,7 +32,7 @@
<el-option label="非电网侧" value="2"></el-option> <el-option label="非电网侧" value="2"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input <el-input
v-model="searchKeyword" v-model="searchKeyword"
placeholder="请输入变电站/终端/监测点" placeholder="请输入变电站/终端/监测点"
@@ -63,21 +63,21 @@
<vxe-column field="gdName" title="供电公司" align="center" min-width="120" ></vxe-column> <vxe-column field="gdName" title="供电公司" align="center" min-width="120" ></vxe-column>
<vxe-column field="subStationName" :show-overflow="true" title="变电站" align="center" min-width="150"></vxe-column> <vxe-column field="subStationName" :show-overflow="true" title="变电站" align="center" min-width="150"></vxe-column>
<vxe-column field="devName" title="终端名称" align="center" min-width="120"></vxe-column> <vxe-column field="devName" title="终端名称" align="center" min-width="120"></vxe-column>
<vxe-column field="devType" title="终端型号" align="center" min-width="150"></vxe-column> <!-- <vxe-column field="devType" title="终端型号" align="center" min-width="150"></vxe-column> -->
<vxe-column field="loginTime" title="投运时间" align="center" min-width="120"></vxe-column> <!-- <vxe-column field="loginTime" title="投运时间" align="center" min-width="120"></vxe-column> -->
<vxe-column field="lineName" title="监测点名称" align="center" min-width="150" :formatter="formatMonitorId"></vxe-column> <vxe-column field="lineName" title="监测点名称" align="center" min-width="150" :formatter="formatMonitorId"></vxe-column>
<vxe-column field="powerFlag" title="监测位置" align="center" min-width="100"></vxe-column> <!-- <vxe-column field="powerFlag" title="监测位置" align="center" min-width="100"></vxe-column> -->
<vxe-column field="lineVoltage" title="监测点电压等级" align="center" min-width="120"></vxe-column> <!-- <vxe-column field="lineVoltage" title="监测点电压等级" align="center" min-width="120"></vxe-column> -->
<vxe-column field="loadType" title="干扰源类型" align="center" min-width="120"></vxe-column> <!-- <vxe-column field="loadType" title="干扰源类型" align="center" min-width="120"></vxe-column> -->
<vxe-column field="objName" title="监测对象名称" align="center" min-width="150" :formatter="formatMonitorId"></vxe-column> <!-- <vxe-column field="objName" title="监测对象名称" align="center" min-width="150" :formatter="formatMonitorId"></vxe-column> -->
<vxe-column field="interval" title="统计间隔" align="center" min-width="100" :formatter="formatMonitorId"></vxe-column> <!-- <vxe-column field="interval" title="统计间隔" align="center" min-width="100" :formatter="formatMonitorId"></vxe-column> -->
<vxe-column field="onlineRate" title="在线率(%)" align="center" min-width="100"></vxe-column> <!-- <vxe-column field="onlineRate" title="在线率(%)" align="center" min-width="100"></vxe-column> -->
<vxe-column field="integrity" title="完整率(%)" align="center" min-width="100"></vxe-column> <!-- <vxe-column field="integrity" title="完整率(%)" align="center" min-width="100"></vxe-column> -->
<vxe-column field="harmonicValue" :title="harmonicValueTitle" align="center" min-width="120"></vxe-column> <vxe-column field="harmonicValue" :title="harmonicValueTitle" align="center" min-width="120"></vxe-column>
<vxe-column field="upCounts" title="暂升次数(次)" align="center" min-width="100"></vxe-column> <!-- <vxe-column field="upCounts" title="暂升次数(次)" align="center" min-width="100"></vxe-column> -->
<vxe-column field="downCounts" title="电压暂降(次)" align="center" min-width="100"></vxe-column> <!-- <vxe-column field="downCounts" title="电压暂降(次)" align="center" min-width="100"></vxe-column> -->
<vxe-column field="breakCounts" title="短时中断(次)" align="center" min-width="100"></vxe-column> <!-- <vxe-column field="breakCounts" title="短时中断(次)" align="center" min-width="100"></vxe-column> -->
<vxe-column field="monitorId" title="一类监测点" align="center" min-width="120" :formatter="formatMonitorId"></vxe-column> <!-- <vxe-column field="monitorId" title="一类监测点" align="center" min-width="120" :formatter="formatMonitorId"></vxe-column> -->
</vxe-table> </vxe-table>
</div> </div>

View File

@@ -32,7 +32,7 @@
<el-option label="非电网侧" value="2"></el-option> <el-option label="非电网侧" value="2"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input <el-input
v-model="searchKeyword" v-model="searchKeyword"
placeholder="请输入变电站" placeholder="请输入变电站"
@@ -86,9 +86,10 @@
</div> </div>
<!-- 添加弹窗 --> <!-- 添加弹窗 -->
<el-dialog <el-dialog draggable
v-model="detailDialogVisible" v-model="detailDialogVisible"
:title="detailDialogTitle" :title="detailDialogTitle"
width="1000px"
> >
<div v-loading="detailLoading"> <div v-loading="detailLoading">
@@ -99,6 +100,7 @@
ref="detailTableRef" ref="detailTableRef"
:data="detailData" :data="detailData"
auto-resize auto-resize
v-bind="defaultAttribute"
resizable resizable
show-overflow show-overflow
height="400px" height="400px"
@@ -123,6 +125,7 @@
import { ref, onMounted, provide, onBeforeUnmount, computed, watch } from 'vue' import { ref, onMounted, provide, onBeforeUnmount, computed, watch } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'

View File

@@ -109,7 +109,7 @@ const tableStore = new TableStore({
{ field: 'name', title: '电网拓扑', minWidth: '150' }, { field: 'name', title: '电网拓扑', minWidth: '150' },
{ {
field: 'onlineMonitorNumber', field: 'onlineMonitorNumber',
title: '在线监测点数(个)', title: '在监测点数(个)',
minWidth: '100px', minWidth: '100px',
formatter: (row: any) => { formatter: (row: any) => {
return row.cellValue == -1 ? '/' : row.cellValue return row.cellValue == -1 ? '/' : row.cellValue

View File

@@ -1,7 +1,7 @@
<template> <template>
<TableHeader area datePicker ref="TableHeaderRef"> <TableHeader area datePicker ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input <el-input
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"

View File

@@ -1,7 +1,7 @@
<template> <template>
<TableHeader area datePicker ref="TableHeaderRef"> <TableHeader area datePicker ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input <el-input
v-model="tableStore.table.params.filterName" v-model="tableStore.table.params.filterName"
@keyup="searchEvent" @keyup="searchEvent"

View File

@@ -12,8 +12,8 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.filterName" placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入监测点名称" />
</el-form-item> </el-form-item>
</template> </template>
@@ -47,7 +47,7 @@
<span class="divBox_title">低于90%监测点数</span> <span class="divBox_title">低于90%监测点数</span>
<span <span
class="divBox_num text-style" class="divBox_num text-style"
style="color: #ff6600" style="color: #57bc6e"
@click="totalTable(90, '低于90%监测点_')" @click="totalTable(90, '低于90%监测点_')"
> >
{{ monitoringPoints.abnormalNum }} {{ monitoringPoints.abnormalNum }}
@@ -115,7 +115,7 @@
</span> </span>
<!-- 低于90%监测点数 --> <!-- 低于90%监测点数 -->
<span <span
style="flex: 1; color: #ff9100" style="flex: 1; color: #388e3c"
class="text text-style" class="text text-style"
@click="renderTable(o.detailList, 90, o.citName + '_低于90%监测点_')" @click="renderTable(o.detailList, 90, o.citName + '_低于90%监测点_')"
> >
@@ -160,13 +160,13 @@
</span> </span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="cit" title="所在地市" width="110px"></vxe-column> <vxe-column field="cit" title="所在地市" minWidth="110px"></vxe-column>
<vxe-column field="company" title="供电公司"></vxe-column> <vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站"></vxe-column> <vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家"></vxe-column> <vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称"></vxe-column> <vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="130px"></vxe-column> <vxe-column field="ip" title="终端IP" :formatter="formatter" width="130px" ></vxe-column>
<vxe-column field="lineName" title="监测点名称" :formatter="formatter"></vxe-column> <vxe-column field="lineName" title="监测点名称" :formatter="formatter" minWidth="110px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px"> <vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }"> <template #default="{ row }">
<el-tag <el-tag
@@ -267,7 +267,13 @@ const tableStore = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0 monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList abnormal.value = tableStore.table.data.citDetailList.filter((k: any) => {
if (tableStore.table.params.statisticalType.name == '终端厂家') {
return k.citTotalNum != 0
} else {
return k.citName != '上送国网' && k.citName != '非上送国网'
}
})
// 合并子集数据 并去重 // 合并子集数据 并去重
totalData.value = Array.from( totalData.value = Array.from(
tableStore.table.data.citDetailList tableStore.table.data.citDetailList
@@ -413,7 +419,8 @@ const echart = () => {
} }
} }
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = '' tableStore.table.params.lineRunFlag = 0
tableStore.table.params.searchValue = ''
const formatter = (row: any) => { const formatter = (row: any) => {
return row.cellValue || '/' return row.cellValue || '/'

View File

@@ -1,216 +1,216 @@
<template> <template>
<TableHeader area datePicker ref="TableHeaderRef"> <TableHeader area datePicker ref="TableHeaderRef">
<template #select> <template #select>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.filterName" @keyup="searchEvent" placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.filterName" @keyup="searchEvent" placeholder="输入关键字筛选" />
</el-form-item> </el-form-item>
<el-form-item label="统计类型:"> <el-form-item label="统计类型:">
<el-select v-model="tableStore.table.params.statisticalType" value-key="id" placeholder="请选择统计类型"> <el-select v-model="tableStore.table.params.statisticalType" value-key="id" placeholder="请选择统计类型">
<el-option v-for="item in classificationData" :key="item.id" :label="item.name" <el-option v-for="item in classificationData" :key="item.id" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="电压等级:"> <el-form-item label="电压等级:">
<el-select v-model="tableStore.table.params.scale" multiple collapse-tags clearable value-key="id" <el-select v-model="tableStore.table.params.scale" multiple collapse-tags clearable value-key="id"
placeholder="请选择电压等级"> placeholder="请选择电压等级">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name" <el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家:">
<el-select v-model="tableStore.table.params.manufacturer" multiple collapse-tags clearable <el-select v-model="tableStore.table.params.manufacturer" multiple collapse-tags clearable
value-key="id" placeholder="请选择终端厂家"> value-key="id" placeholder="请选择终端厂家">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name" <el-option v-for="item in terminaloption" :key="item.id" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="干扰源类型:"> <el-form-item label="干扰源类型:">
<el-select v-model="tableStore.table.params.loadType" multiple collapse-tags clearable value-key="id" <el-select v-model="tableStore.table.params.loadType" multiple collapse-tags clearable value-key="id"
placeholder="请选择干扰源类型"> placeholder="请选择干扰源类型">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name" <el-option v-for="item in interfereoption" :key="item.id" :label="item.name"
:value="item"></el-option> :value="item"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }" <Table ref="tableRef" :tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
:scroll-y="{ enabled: true }" :key="num" /> :scroll-y="{ enabled: true }" :key="num" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue' import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import XEUtils from 'xe-utils' import XEUtils from 'xe-utils'
const dictData = useDictData() const dictData = useDictData()
const tableRef = ref() const tableRef = ref()
const num = ref(0) const num = ref(0)
const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type']) const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Type'])
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand') const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const terminaloption = dictData.getBasicData('Dev_Manufacturers') const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const interfereoption = dictData.getBasicData('Interference_Source') const interfereoption = dictData.getBasicData('Interference_Source')
const treeDataCopy: any = ref([]) const treeDataCopy: any = ref([])
const treeData: any = ref([]) const treeData: any = ref([])
const TableHeaderRef = ref() const TableHeaderRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/device-boot/terminalOnlineRateData/getOnlineRateData', url: '/device-boot/terminalOnlineRateData/getOnlineRateData',
publicHeight: 65, publicHeight: 65,
showPage: false, showPage: false,
method: 'POST', method: 'POST',
column: [ column: [
{ field: 'name', title: '电网拓扑', width: 350, align: 'left', treeNode: true }, { field: 'name', title: '电网拓扑', width: 350, align: 'left', treeNode: true },
{ {
field: 'ip', field: 'ip',
title: '网络参数', title: '网络参数',
formatter: ({ row }: any) => { formatter: ({ row }: any) => {
return row.ip || '/' return row.ip || '/'
} }
}, },
{ {
field: 'dataName', field: 'dataName',
title: '终端名称', title: '终端名称',
formatter: ({ row }: any) => { formatter: ({ row }: any) => {
return row.dataName || '/' return row.dataName || '/'
} }
}, },
{ {
field: 'manufacturer', field: 'manufacturer',
title: '厂家', title: '厂家',
formatter: ({ row }: any) => { formatter: ({ row }: any) => {
return row.manufacturer || '/' return row.manufacturer || '/'
} }
}, },
{ {
field: 'comFlag', field: 'comFlag',
title: '通讯状态', title: '通讯状态',
render: 'tag', render: 'tag',
custom: { custom: {
0: 'danger', 0: 'danger',
1: 'success', 1: 'success',
3: 'info' 3: 'info'
}, },
replaceValue: { replaceValue: {
0: '中断', 0: '中断',
1: '正常', 1: '正常',
3: '/' 3: '/'
} }
// formatter: ({ row }: any) => { // formatter: ({ row }: any) => {
// return row.comFlag || '/' // return row.comFlag || '/'
// } // }
}, },
{ {
field: 'updateTime', field: 'updateTime',
title: '最新数据时间', title: '最新数据时间',
formatter: ({ row }: any) => { formatter: ({ row }: any) => {
return row.updateTime || '/' return row.updateTime || '/'
} }
}, },
{ {
field: 'onlineRate', field: 'onlineRate',
title: '在线率(%)', title: '在线率(%)',
formatter: ({ row }: any) => { formatter: ({ row }: any) => {
return row.onlineRate == 3.14159 ? '暂无数据' : row.onlineRate.toFixed(2) return row.onlineRate == 3.14159 ? '暂无数据' : row.onlineRate.toFixed(2)
} }
}, },
{ {
field: 'assess', field: 'assess',
title: '评估', title: '评估',
render: 'tag', render: 'tag',
custom: { custom: {
0: 'info', 0: 'info',
1: 'danger', 1: 'danger',
2: 'warning', 2: 'warning',
3: 'success' 3: 'success'
}, },
replaceValue: { replaceValue: {
0: '暂无数据', 0: '暂无数据',
1: '不合格', 1: '不合格',
2: '合格', 2: '合格',
3: '优秀' 3: '优秀'
} }
} }
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
tableStore.options.column[0].title = tableStore.table.params.statisticalType.name tableStore.options.column[0].title = tableStore.table.params.statisticalType.name
}, },
loadCallback: () => { loadCallback: () => {
setTimeout(() => { setTimeout(() => {
tableRef.value.getRef().setAllTreeExpand(true) tableRef.value.getRef().setAllTreeExpand(true)
}, 1000) }, 1000)
treeData.value = tree2List(tableStore.table.data, Math.random() * 1000) treeData.value = tree2List(tableStore.table.data, Math.random() * 1000)
treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value)) treeDataCopy.value = JSON.parse(JSON.stringify(treeData.value))
tableStore.table.data = treeData.value tableStore.table.data = treeData.value
tableStore.table.params.filterName='' tableStore.table.params.filterName=''
searchEvent() searchEvent()
} }
}) })
tableStore.table.params.statisticalType = classificationData.filter(item => item.name == '电网拓扑')[0] tableStore.table.params.statisticalType = classificationData.filter(item => item.name == '电网拓扑')[0]
tableStore.table.params.monitorFlag = 2 tableStore.table.params.monitorFlag = 2
tableStore.table.params.powerFlag = 2 tableStore.table.params.powerFlag = 2
tableStore.table.params.serverName = 'harmonicBoot' tableStore.table.params.serverName = 'harmonicBoot'
provide('tableStore', tableStore) provide('tableStore', tableStore)
const tree2List = (list: any, id: any) => { const tree2List = (list: any, id: any) => {
//存储结果的数组 //存储结果的数组
let arr: any = [] let arr: any = []
// 遍历 tree 数组 // 遍历 tree 数组
list.forEach((item: any) => { list.forEach((item: any) => {
item.uPid = id item.uPid = id
item.uId = (Math.random() * 1000) item.uId = (Math.random() * 1000)
item.comFlag = item.comFlag == null ? 3 : item.comFlag item.comFlag = item.comFlag == null ? 3 : item.comFlag
item.assess = item.onlineRate == 3.14159 ? 0 : item.onlineRate < 60 ? 1 : item.onlineRate < 90 ? 2 : 3 item.assess = item.onlineRate == 3.14159 ? 0 : item.onlineRate < 60 ? 1 : item.onlineRate < 90 ? 2 : 3
// 判断item是否存在children // 判断item是否存在children
if (!item.children) return arr.push(item) if (!item.children) return arr.push(item)
// 函数递归对children数组进行tree2List的转换 // 函数递归对children数组进行tree2List的转换
const children = tree2List(item.children, item.uId) const children = tree2List(item.children, item.uId)
// 删除item的children属性 // 删除item的children属性
delete item.children delete item.children
// 把item和children数组添加至结果数组 // 把item和children数组添加至结果数组
//..children: 意思是把children数组展开 //..children: 意思是把children数组展开
arr.push(item, ...children) arr.push(item, ...children)
}) })
// 返回结果数组 // 返回结果数组
return arr return arr
} }
// 表格过滤 // 表格过滤
const searchEvent = debounce(() => { const searchEvent = debounce(() => {
const filterVal = XEUtils.toValueString(tableStore.table.params.filterName).trim().toLowerCase() const filterVal = XEUtils.toValueString(tableStore.table.params.filterName).trim().toLowerCase()
if (filterVal) { if (filterVal) {
const options = { children: 'children' } const options = { children: 'children' }
const searchProps = ['name'] const searchProps = ['name']
const rest = XEUtils.searchTree( const rest = XEUtils.searchTree(
treeDataCopy.value, treeDataCopy.value,
(item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1), (item: any) => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1),
options options
) )
console.log("🚀 ~ searchEvent ~ rest:", rest) console.log("🚀 ~ searchEvent ~ rest:", rest)
tableStore.table.data = rest tableStore.table.data = rest
// 搜索之后默认展开所有子节点 // 搜索之后默认展开所有子节点
} else { } else {
tableStore.table.data = treeDataCopy.value tableStore.table.data = treeDataCopy.value
} }
nextTick(() => { nextTick(() => {
const $table = tableRef.value.getRef() const $table = tableRef.value.getRef()
if ($table) { if ($table) {
$table.setAllTreeExpand(true) $table.setAllTreeExpand(true)
} }
}) })
}, 500) }, 500)
onMounted(() => { onMounted(() => {
tableStore.index() tableStore.index()
}) })
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -12,8 +12,8 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.filterName" placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.searchValue" placeholder="输入终端名称" />
</el-form-item> </el-form-item>
</template> </template>
@@ -47,7 +47,7 @@
<span class="divBox_title">低于90%终端数</span> <span class="divBox_title">低于90%终端数</span>
<span <span
class="divBox_num text-style" class="divBox_num text-style"
style="color: #ff6600" style="color: #57bc6e"
@click="totalTable(90, '低于90%终端_')" @click="totalTable(90, '低于90%终端_')"
> >
{{ monitoringPoints.abnormalNum }} {{ monitoringPoints.abnormalNum }}
@@ -115,7 +115,7 @@
</span> </span>
<!-- 低于90%终端数 --> <!-- 低于90%终端数 -->
<span <span
style="flex: 1; color: #ff9100" style="flex: 1; color: #388e3c"
class="text text-style" class="text text-style"
@click="renderTable(o.detailList, 90, o.citName + '_低于90%终端_')" @click="renderTable(o.detailList, 90, o.citName + '_低于90%终端_')"
> >
@@ -161,10 +161,10 @@
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="cit" title="所在地市" width="110px"></vxe-column> <vxe-column field="cit" title="所在地市" width="110px"></vxe-column>
<vxe-column field="company" title="供电公司"></vxe-column> <vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站"></vxe-column> <vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家"></vxe-column> <vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称"></vxe-column> <vxe-column field="deviceName" title="终端名称" minWidth="110px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="130px"></vxe-column> <vxe-column field="ip" title="终端IP" :formatter="formatter" width="130px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px"> <vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }"> <template #default="{ row }">
@@ -267,9 +267,15 @@ const tableStore = new TableStore({
monitoringPoints.value.runNum = tableStore.table.data.totalNum monitoringPoints.value.runNum = tableStore.table.data.totalNum
monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum monitoringPoints.value.abnormalNum = tableStore.table.data.belowNum
monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0 monitoringPoints.value.totalOnlineRate = tableStore.table.data.totalOnlineRate - 0
abnormal.value = tableStore.table.data.citDetailList.filter( abnormal.value = tableStore.table.data.citDetailList.filter((k: any) => {
(k: any) => k.citName != '上送国网' && k.citName != '非上送国网' if (tableStore.table.params.statisticalType.name == '终端厂家') {
) return k.citTotalNum != 0
} else {
return k.citName != '上送国网' && k.citName != '非上送国网'
}
})
console.log(123, tableStore.table.params.statisticalType.name)
// 合并子集数据 并去重 // 合并子集数据 并去重
totalData.value = Array.from( totalData.value = Array.from(
tableStore.table.data.citDetailList tableStore.table.data.citDetailList
@@ -417,7 +423,8 @@ const echart = () => {
} }
} }
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = '' tableStore.table.params.lineRunFlag = 0
tableStore.table.params.searchValue = ''
const formatter = (row: any) => { const formatter = (row: any) => {
return row.cellValue || '/' return row.cellValue || '/'
@@ -478,7 +485,7 @@ tableStore.table.params.name = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/font/iconfont.css'; @import '@/assets/font/iconfont.css';
.card-list { .card-list {
display: flex; display: flex;
.monitoringPoints { .monitoringPoints {

View File

@@ -90,7 +90,7 @@ const activeName = ref('2')
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {

View File

@@ -109,7 +109,7 @@ provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
getTemplateByDept({ id: dictData.state.area[0].id }) getTemplateByDept({ id: dictData.state.area[0].id })

View File

@@ -129,7 +129,7 @@ provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
getTemplateByDept({ id: dictData.state.area[0].id }) getTemplateByDept({ id: dictData.state.area[0].id })

View File

@@ -1,152 +1,152 @@
<template> <template>
<div class='default-main' :style='height'> <div class='default-main' :style='height'>
<splitpanes style='height: 100%' class='default-theme' id='navigation-splitpanes'> <splitpanes style='height: 100%' class='default-theme' id='navigation-splitpanes'>
<pane :size='size'> <pane :size='size'>
<PointTree :default-expand-all='false' @node-click='handleNodeClick' @init='handleNodeClick'> <PointTree :default-expand-all='false' @node-click='handleNodeClick' @init='handleNodeClick'>
</PointTree> </PointTree>
</pane> </pane>
<pane style='background: #fff' :style='height'> <pane style='background: #fff' :style='height'>
<TableHeader ref='TableHeaderRef' datePicker :show-search='false'> <TableHeader ref='TableHeaderRef' datePicker :show-search='false'>
<template v-slot:select> <template v-slot:select>
<el-form-item label='客户名称'> <el-form-item label='客户名称'>
<el-input v-model='tableStore.table.params.crmName' maxlength='32' show-word-limit clearable <el-input v-model='tableStore.table.params.crmName' maxlength='32' show-word-limit clearable
placeholder='请输入客户名称' /> placeholder='请输入客户名称' />
</el-form-item> </el-form-item>
<el-form-item label='报表编号'> <el-form-item label='报表编号'>
<el-input v-model='tableStore.table.params.reportNumber' clearable <el-input v-model='tableStore.table.params.reportNumber' clearable
placeholder='请输入报表编号' maxlength='12' show-word-limit /> placeholder='请输入报表编号' maxlength='12' show-word-limit />
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-upload :show-file-list='false' ref='uploadRef' action='' accept='.png,.jpg' <el-upload :show-file-list='false' ref='uploadRef' action='' accept='.png,.jpg'
:on-change='choose' :auto-upload='false'> :on-change='choose' :auto-upload='false'>
<template #trigger> <template #trigger>
<el-button icon='el-icon-Upload' type='primary' class='mr10 ml10'>上传接线图</el-button> <el-button icon='el-icon-Upload' type='primary' class='mr10 ml10'>上传接线图</el-button>
</template> </template>
</el-upload> </el-upload>
<el-button icon='el-icon-Download' type='primary' @click='exportEvent'>生成</el-button> <el-button icon='el-icon-Download' type='primary' @click='exportEvent'>生成</el-button>
</template> </template>
</TableHeader> </TableHeader>
<div class='box'> <div class='box'>
<div id='luckysheet'> <div id='luckysheet'>
<img width='100%' :style='`height: calc(${tableStore.table.height} + 40px)`' <img width='100%' :style='`height: calc(${tableStore.table.height} + 40px)`'
src='@/assets/img/jss.png' /> src='@/assets/img/jss.png' />
</div> </div>
</div> </div>
</pane> </pane>
</splitpanes> </splitpanes>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { onMounted, ref, provide } from 'vue' import { onMounted, ref, provide } from 'vue'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes' import { Splitpanes, Pane } from 'splitpanes'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import PointTree from '@/components/tree/pqs/pointTree.vue' import PointTree from '@/components/tree/pqs/pointTree.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { exportModel } from '@/api/process-boot/reportForms' import { exportModel } from '@/api/process-boot/reportForms'
import { genFileId, ElMessage, ElNotification } from 'element-plus' import { genFileId, ElMessage, ElNotification } from 'element-plus'
import type { UploadProps, UploadUserFile } from 'element-plus' import type { UploadProps, UploadUserFile } from 'element-plus'
defineOptions({ defineOptions({
// name: 'harmonic-boot/report/word' // name: 'harmonic-boot/report/word'
}) })
const height = mainHeight(20) const height = mainHeight(20)
const size = ref(0) const size = ref(0)
const dictData = useDictData() const dictData = useDictData()
const TableHeaderRef = ref() const TableHeaderRef = ref()
const dotList: any = ref({}) const dotList: any = ref({})
const Template: any = ref({}) const Template: any = ref({})
const uploadList: any = ref([]) const uploadList: any = ref([])
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '', url: '',
method: 'POST', method: 'POST',
column: [], column: [],
beforeSearchFun: () => { beforeSearchFun: () => {
}, },
loadCallback: () => { loadCallback: () => {
} }
}) })
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
dotList.value = data dotList.value = data
} }
// 上传 // 上传
const choose = (files: any) => { const choose = (files: any) => {
const isJPG = files.raw.type === 'image/jpg' const isJPG = files.raw.type === 'image/jpg'
const isPNG = files.raw.type === 'image/png' const isPNG = files.raw.type === 'image/png'
if (!isJPG && !isPNG) { if (!isJPG && !isPNG) {
ElMessage.warning('上传文件只能是 JPG/PNG 格式!') ElMessage.warning('上传文件只能是 JPG/PNG 格式!')
return false return false
} }
uploadList.value = files uploadList.value = files
ElMessage.success('上传成功') ElMessage.success('上传成功')
} }
// 生成 // 生成
const exportEvent = () => { const exportEvent = () => {
if (dotList.value.level != 6) { if (dotList.value.level != 6) {
return ElMessage.warning('请选择监测点进行报告生成!') return ElMessage.warning('请选择监测点进行报告生成!')
} }
let form = new FormData() let form = new FormData()
form.append('lineIndex', dotList.value.id) form.append('lineIndex', dotList.value.id)
form.append('name', dotList.value.name) form.append('name', dotList.value.name)
form.append('crmName', tableStore.table.params.crmName || '') form.append('crmName', tableStore.table.params.crmName || '')
form.append('reportNumber', tableStore.table.params.reportNumber || '') form.append('reportNumber', tableStore.table.params.reportNumber || '')
form.append('type', '0') form.append('type', '0')
form.append('startTime', TableHeaderRef.value.datePickerRef.timeValue[0]) form.append('startTime', TableHeaderRef.value.datePickerRef.timeValue[0])
form.append('endTime', TableHeaderRef.value.datePickerRef.timeValue[1]) form.append('endTime', TableHeaderRef.value.datePickerRef.timeValue[1])
console.log('🚀 ~ exportEvent ~ uploadList.value:', uploadList.value?.raw) console.log('🚀 ~ exportEvent ~ uploadList.value:', uploadList.value?.raw)
form.append('file', uploadList.value?.raw || '') form.append('file', uploadList.value?.raw || '')
// 特殊字符正则表达式 // 特殊字符正则表达式
const specialCharRegex = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/ const specialCharRegex = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/
if (specialCharRegex.test(tableStore.table.params.crmName) || specialCharRegex.test(tableStore.table.params.reportNumber)) { if (specialCharRegex.test(tableStore.table.params.crmName) || specialCharRegex.test(tableStore.table.params.reportNumber)) {
ElNotification({ ElNotification({
type: 'error', type: 'error',
message: '包含特殊字符,请注意修改!' message: '包含特殊字符,请注意修改!'
}) })
}else{ }else{
ElMessage('生成报告中...') ElMessage('生成报告中...')
exportModel(form).then((res: any) => { exportModel(form).then((res: any) => {
let blob = new Blob([res], { let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8' type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8'
}) })
// createObjectURL(blob); //创建下载的链接 // createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签 const link = document.createElement('a') // 创建a标签
link.href = url link.href = url
link.download = dotList.value.name // 设置下载的文件名 link.download = dotList.value.name // 设置下载的文件名
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) document.body.removeChild(link)
}) })
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.splitpanes.default-theme .splitpanes__pane { .splitpanes.default-theme .splitpanes__pane {
background: #eaeef1; background: #eaeef1;
} }
.box { .box {
padding: 10px; padding: 10px;
} }
</style> </style>

View File

@@ -1,343 +1,343 @@
<!-- 稳态 --> <!-- 稳态 -->
<template> <template>
<!-- 终端 --> <!-- 终端 -->
<el-dialog draggable title="稳态电能质量水平评估统计" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="稳态电能质量水平评估统计" v-model="dialogVisible" width="1400px">
<el-row style="height: 300px" :gutter="20"> <el-row style="height: 300px" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
<span>稳态电能质量水平评估</span> <span>稳态电能质量水平评估</span>
</div> </div>
<div class="boxSteps"> <div class="boxSteps">
<el-steps> <el-steps>
<template v-for="(item, i) in Voltage"> <template v-for="(item, i) in Voltage">
<el-step <el-step
:class="active == i ? 'highlight' : ''" :class="active == i ? 'highlight' : ''"
:title="item.name" :title="item.name"
@click="handleClick(i)" @click="handleClick(i)"
></el-step> ></el-step>
</template> </template>
</el-steps> </el-steps>
</div> </div>
<div v-for="(item, i) in evaluationData" class="evaluationData"> <div v-for="(item, i) in evaluationData" class="evaluationData">
<el-row style="width: 100%"> <el-row style="width: 100%">
<el-col :span="12" style="display: flex"> <el-col :span="12" style="display: flex">
<img :src="url[i]" /> <img :src="url[i]" />
<span>{{ item.targetName }}</span> <span>{{ item.targetName }}</span>
</el-col> </el-col>
<el-col :span="12" style="display: flex"> <el-col :span="12" style="display: flex">
<div style="width: 150px"> <div style="width: 150px">
均值 均值
<span style="color: #339966">{{ item.avg == 3.14159 ? '--' : item.avg }}</span> <span style="color: #339966">{{ item.avg == 3.14159 ? '--' : item.avg }}</span>
</div> </div>
<div> <div>
标准差 标准差
<span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.sd }}</span> <span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.sd }}</span>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
<span>稳态电能质量超标占比环比变化</span> <span>稳态电能质量超标占比环比变化</span>
</div> </div>
<div class="pie"> <div class="pie">
<div style="height: 250px; width: 100%" ref="chartRef"></div> <div style="height: 250px; width: 100%" ref="chartRef"></div>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div> <div>
<div class="title"> <div class="title">
<span>区域稳态电能质量水平评估</span> <span>区域稳态电能质量水平评估</span>
</div> </div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="365px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="365px" :data="tableData">
<vxe-column field="deptName" title="区域" /> <vxe-column field="deptName" title="区域" />
<vxe-column sortable field="onlineNum" title="在线监测点数(个)" /> <vxe-column sortable field="onlineNum" title="在监测点数(个)" />
<vxe-column sortable field="overNum" title="超标监测点数量(个)" /> <vxe-column sortable field="overNum" title="超标监测点数量(个)" />
<vxe-column sortable field="overRatio" title="超标监测点占比(%)" /> <vxe-column sortable field="overRatio" title="超标监测点占比(%)" />
<vxe-colgroup :title="item" v-for="(item, i) in title"> <vxe-colgroup :title="item" v-for="(item, i) in title">
<vxe-column title="监测点数 " field="overNum"> <vxe-column title="监测点数 " field="overNum">
<template #default="scope"> <template #default="scope">
<span>{{ scope.row.list == null ? '' : scope.row.list[i].overNum }}</span> <span>{{ scope.row.list == null ? '' : scope.row.list[i].overNum }}</span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column title="天数" field="overDay"> <vxe-column title="天数" field="overDay">
<template #default="scope"> <template #default="scope">
<span>{{ scope.row.list == null ? '' : scope.row.list[i].overDay }}</span> <span>{{ scope.row.list == null ? '' : scope.row.list[i].overDay }}</span>
</template> </template>
</vxe-column> </vxe-column>
</vxe-colgroup> </vxe-colgroup>
</vxe-table> </vxe-table>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick } from 'vue' import { ref, nextTick } from 'vue'
import echarts from '@/components/echarts/echarts' import echarts from '@/components/echarts/echarts'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { color } from '@/components/echarts/color' import { color } from '@/components/echarts/color'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getEvaluationData, evaluationDetail, evaluationRatio } from '@/api/device-boot/panorama' import { getEvaluationData, evaluationDetail, evaluationRatio } from '@/api/device-boot/panorama'
const dialogVisible: any = ref(false) const dialogVisible: any = ref(false)
const rowList = ref({}) const rowList = ref({})
const active: any = ref(1) const active: any = ref(1)
const evaluationData: any = ref([]) const evaluationData: any = ref([])
const dictData = useDictData() const dictData = useDictData()
const Voltage: any = dictData.getBasicData('Dev_Voltage_Stand').filter(item => { const Voltage: any = dictData.getBasicData('Dev_Voltage_Stand').filter(item => {
if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') { if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') {
return item return item
} }
}) })
const chartRef = ref<HTMLDivElement>() const chartRef = ref<HTMLDivElement>()
const url: any = [ const url: any = [
new URL(`@/assets/img/PLPC.png`, import.meta.url), new URL(`@/assets/img/PLPC.png`, import.meta.url),
new URL(`@/assets/img/DYPC.png`, import.meta.url), new URL(`@/assets/img/DYPC.png`, import.meta.url),
new URL(`@/assets/img/JBL.png`, import.meta.url), new URL(`@/assets/img/JBL.png`, import.meta.url),
new URL(`@/assets/img/SXDY.png`, import.meta.url), new URL(`@/assets/img/SXDY.png`, import.meta.url),
new URL(`@/assets/img/SB.png`, import.meta.url) new URL(`@/assets/img/SB.png`, import.meta.url)
] ]
const tableData: any = ref([]) const tableData: any = ref([])
const title = ['电压偏差(超标)', '频率偏差(超标)', '电压总谐波畸变率(超标)', '闪变(超标)', '三相电压不平衡度(超标)'] const title = ['电压偏差(超标)', '频率偏差(超标)', '电压总谐波畸变率(超标)', '闪变(超标)', '三相电压不平衡度(超标)']
const echart = (row: any) => { const echart = (row: any) => {
let maxList: any = [] let maxList: any = []
row.forEach((item: any) => { row.forEach((item: any) => {
maxList.push(...(item.ratioList || [0])) maxList.push(...(item.ratioList || [0]))
}) })
let max = Math.max(...maxList) > 50 ? 100 : 50 let max = Math.max(...maxList) > 50 ? 100 : 50
let chart = echarts.init(chartRef.value as HTMLDivElement) let chart = echarts.init(chartRef.value as HTMLDivElement)
let dataname = [ let dataname = [
'频率偏差(Hz)', '频率偏差(Hz)',
'电压偏差(%)', '电压偏差(%)',
'电压总谐波畸变率(%)', '电压总谐波畸变率(%)',
'三相电压不平衡度(%)', '三相电压不平衡度(%)',
'闪变', '闪变',
'谐波电压(%)', '谐波电压(%)',
'谐波电流(%)', '谐波电流(%)',
'间谐波电压(%)', '间谐波电压(%)',
'负序电流(A)' '负序电流(A)'
] ]
// let datamax = [100, 100, 100, 100, 100, 100] // let datamax = [100, 100, 100, 100, 100, 100]
let indicator = [] let indicator = []
for (let i = 0; i < dataname.length; i++) { for (let i = 0; i < dataname.length; i++) {
indicator.push({ indicator.push({
name: dataname[i], name: dataname[i],
max: max max: max
}) })
} }
let option: any = { let option: any = {
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
axisPointer: { axisPointer: {
type: 'shadow', type: 'shadow',
label: { label: {
color: '#fff', color: '#fff',
fontSize: 16 fontSize: 16
} }
}, },
textStyle: { textStyle: {
color: '#fff', color: '#fff',
fontStyle: 'normal', fontStyle: 'normal',
opacity: 0.35, opacity: 0.35,
fontSize: 14 fontSize: 14
}, },
backgroundColor: 'rgba(0,0,0,0.55)', backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0, borderWidth: 0,
position: 'bottom' position: 'bottom'
}, },
legend: { legend: {
data: row.map((item: any) => item.time), data: row.map((item: any) => item.time),
type: 'scroll', type: 'scroll',
orient: 'vertical', orient: 'vertical',
icon: 'roundRect', icon: 'roundRect',
right: '20', right: '20',
itemGap: 10, itemGap: 10,
itemWidth: 16, itemWidth: 16,
itemHeight: 16, itemHeight: 16,
textStyle: { textStyle: {
fontSize: '15', fontSize: '15',
color: '#656565' color: '#656565'
} }
}, },
radar: { radar: {
center: ['50%', '60%'], center: ['50%', '60%'],
radius: '60%', radius: '60%',
startAngle: 90, startAngle: 90,
splitNumber: 5, splitNumber: 5,
splitArea: { splitArea: {
areaStyle: { areaStyle: {
color: ['#FFFFFF', '#F5F9FF'].reverse() color: ['#FFFFFF', '#F5F9FF'].reverse()
} }
}, },
axisLabel: { axisLabel: {
show: false show: false
}, },
axisLine: { axisLine: {
show: true, show: true,
lineStyle: { lineStyle: {
color: '#D2E4F8' color: '#D2E4F8'
} }
}, },
splitLine: { splitLine: {
show: true, show: true,
lineStyle: { lineStyle: {
color: '#D2E4F8' color: '#D2E4F8'
} }
}, },
name: { name: {
formatter: '{value}', formatter: '{value}',
textStyle: { textStyle: {
color: '#656565', color: '#656565',
fontSize: 15 fontSize: 15
} }
}, },
indicator: indicator indicator: indicator
}, },
series: [] series: []
} }
row.forEach((item: any, i: any) => { row.forEach((item: any, i: any) => {
option.series.push({ option.series.push({
name: item.time, name: item.time,
type: 'radar', type: 'radar',
symbol: 'none', symbol: 'none',
areaStyle: { areaStyle: {
normal: { normal: {
color: color[i + 1] color: color[i + 1]
} }
}, },
itemStyle: { itemStyle: {
color: color[i + 1] color: color[i + 1]
}, },
data: [item.ratioList] data: [item.ratioList]
}) })
}) })
chart.setOption(option) chart.setOption(option)
} }
const open = async (row: any) => { const open = async (row: any) => {
rowList.value = row rowList.value = row
dialogVisible.value = true dialogVisible.value = true
// 稳态电能质量水平评估 // 稳态电能质量水平评估
handleClick(0) handleClick(0)
//环比 //环比
evaluationRatio(row).then(res => { evaluationRatio(row).then(res => {
echart(res.data) echart(res.data)
}) })
// 稳态电能质量水平评估详细列表 // 稳态电能质量水平评估详细列表
evaluationDetail(row).then(res => { evaluationDetail(row).then(res => {
tableData.value = res.data tableData.value = res.data
}) })
} }
// 点击电压等级 // 点击电压等级
const handleClick = (i: any) => { const handleClick = (i: any) => {
active.value = i active.value = i
getEvaluationData({ getEvaluationData({
...rowList.value, ...rowList.value,
voltageLevel: Voltage[i].id voltageLevel: Voltage[i].id
}).then(res => { }).then(res => {
evaluationData.value = res.data evaluationData.value = res.data
}) })
} }
defineExpose({ open }) defineExpose({ open })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-select) { :deep(.el-select) {
min-width: 80px; min-width: 80px;
} }
.title { .title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin: 10px; margin: 10px;
span { span {
font-weight: 550; font-weight: 550;
font-size: 18px; font-size: 18px;
} }
} }
.pie { .pie {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
} }
.evaluationData { .evaluationData {
height: 33px; height: 33px;
margin: 8px 30px; margin: 8px 30px;
width: 100%; width: 100%;
box-shadow: 1px 1px 1px 1px #e8e3e3; box-shadow: 1px 1px 1px 1px #e8e3e3;
display: flex; display: flex;
font-size: 18px; font-size: 18px;
line-height: 35px; line-height: 35px;
img { img {
height: 25px; height: 25px;
width: 25px; width: 25px;
margin: 4px 20px 0px 30px; margin: 4px 20px 0px 30px;
} }
} }
.el-steps { .el-steps {
margin-top: 5px; margin-top: 5px;
} }
:deep(.el-step__icon) { :deep(.el-step__icon) {
border: none; border: none;
background: #ccc; background: #ccc;
margin-top: 5px; margin-top: 5px;
width: 15px; width: 15px;
height: 15px; height: 15px;
} }
:deep(.el-step__icon-inner) { :deep(.el-step__icon-inner) {
display: none; display: none;
} }
:deep(.boxSteps) { :deep(.boxSteps) {
border-radius: 50px; border-radius: 50px;
width: 60%; width: 60%;
height: 25px; height: 25px;
margin: auto; margin: auto;
margin-top: 30px; margin-top: 30px;
.el-step__title { .el-step__title {
line-height: 18px; line-height: 18px;
font-size: 16px; font-size: 16px;
margin-left: -10px; margin-left: -10px;
font-weight: 500; font-weight: 500;
color: #000 !important; color: #000 !important;
position: relative; position: relative;
top: -50px; top: -50px;
} }
} }
:deep(.highlight) { :deep(.highlight) {
.el-step__icon { .el-step__icon {
background: var(--el-color-primary); background: var(--el-color-primary);
} }
.el-step__title { .el-step__title {
font-weight: 700 !important; font-weight: 700 !important;
color: var(--el-color-primary) !important; color: var(--el-color-primary) !important;
} }
// .is-wait { // .is-wait {
// color: var(--el-color-primary) !important; // color: var(--el-color-primary) !important;
// } // }
} }
:deep(.el-dialog__body) { :deep(.el-dialog__body) {
max-height: none !important; max-height: none !important;
} }
</style> </style>

View File

@@ -1,338 +1,338 @@
<!-- 稳态 --> <!-- 稳态 -->
<template> <template>
<!-- 终端 --> <!-- 终端 -->
<el-dialog draggable title="稳态电能质量水平评估统计" v-model="dialogVisible" width="1400px"> <el-dialog draggable title="稳态电能质量水平评估统计" v-model="dialogVisible" width="1400px">
<el-row style="height: 300px" :gutter="20"> <el-row style="height: 300px" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
<span>稳态电能质量水平评估</span> <span>稳态电能质量水平评估</span>
</div> </div>
<div class="boxSteps"> <div class="boxSteps">
<el-steps> <el-steps>
<template v-for="(item, i) in Voltage"> <template v-for="(item, i) in Voltage">
<el-step :class="active == i ? 'highlight' : ''" :title="item.name" <el-step :class="active == i ? 'highlight' : ''" :title="item.name"
@click="handleClick(i)"></el-step> @click="handleClick(i)"></el-step>
</template> </template>
</el-steps> </el-steps>
</div> </div>
<div v-for="(item, i) in evaluationData" class="evaluationData"> <div v-for="(item, i) in evaluationData" class="evaluationData">
<el-row style="width: 100%"> <el-row style="width: 100%">
<el-col :span="12" style="display: flex"> <el-col :span="12" style="display: flex">
<img :src="url[i]" /> <img :src="url[i]" />
<span>{{ item.targetName }}</span> <span>{{ item.targetName }}</span>
</el-col> </el-col>
<el-col :span="12" style="display: flex"> <el-col :span="12" style="display: flex">
<div style="width: 150px"> <div style="width: 150px">
均值 均值
<span style="color: #339966">{{ item.avg == 3.14159 ? '--' : item.avg }}</span> <span style="color: #339966">{{ item.avg == 3.14159 ? '--' : item.avg }}</span>
</div> </div>
<div> <div>
标准差 标准差
<span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.sd }}</span> <span style="color: #ff9900">{{ item.avg == 3.14159 ? '--' : item.sd }}</span>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<div class="title"> <div class="title">
<span>稳态电能质量超标占比环比变化</span> <span>稳态电能质量超标占比环比变化</span>
</div> </div>
<div class="pie"> <div class="pie">
<div style="height: 250px; width: 100%" ref="chartRef"></div> <div style="height: 250px; width: 100%" ref="chartRef"></div>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div> <div>
<div class="title"> <div class="title">
<span>区域稳态电能质量水平评估</span> <span>区域稳态电能质量水平评估</span>
</div> </div>
<vxe-table v-bind="defaultAttribute" ref="vxeRef" height="365px" :data="tableData"> <vxe-table v-bind="defaultAttribute" ref="vxeRef" height="365px" :data="tableData">
<vxe-column field="deptName" title="区域" /> <vxe-column field="deptName" title="区域" />
<vxe-column sortable field="onlineNum" title="在线监测点数(个)" /> <vxe-column sortable field="onlineNum" title="在监测点数(个)" />
<vxe-column sortable field="overNum" title="超标监测点数量(个)" /> <vxe-column sortable field="overNum" title="超标监测点数量(个)" />
<vxe-column sortable field="overRatio" title="超标监测点占比(%)" /> <vxe-column sortable field="overRatio" title="超标监测点占比(%)" />
<vxe-colgroup :title="item" v-for="(item, i) in title"> <vxe-colgroup :title="item" v-for="(item, i) in title">
<vxe-column title="监测点数 " field="overNum"> <vxe-column title="监测点数 " field="overNum">
<template #default="scope"> <template #default="scope">
<span>{{ scope.row.list[i].overNum }}</span> <span>{{ scope.row.list[i].overNum }}</span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column title="天数" field="overDay"> <vxe-column title="天数" field="overDay">
<template #default="scope"> <template #default="scope">
<span>{{ scope.row.list[i].overDay }}</span> <span>{{ scope.row.list[i].overDay }}</span>
</template> </template>
</vxe-column> </vxe-column>
</vxe-colgroup> </vxe-colgroup>
</vxe-table> </vxe-table>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick } from 'vue' import { ref, nextTick } from 'vue'
import echarts from '@/components/echarts/echarts' import echarts from '@/components/echarts/echarts'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { color } from '@/components/echarts/color' import { color } from '@/components/echarts/color'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getEvaluationData, evaluationDetail, evaluationRatio } from '@/api/device-boot/panorama' import { getEvaluationData, evaluationDetail, evaluationRatio } from '@/api/device-boot/panorama'
const dialogVisible: any = ref(false) const dialogVisible: any = ref(false)
const rowList = ref({}) const rowList = ref({})
const active: any = ref(1) const active: any = ref(1)
const evaluationData: any = ref([]) const evaluationData: any = ref([])
const dictData = useDictData() const dictData = useDictData()
const Voltage: any = dictData.getBasicData('Dev_Voltage_Stand').filter(item => { const Voltage: any = dictData.getBasicData('Dev_Voltage_Stand').filter(item => {
if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') { if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') {
return item return item
} }
}) })
const chartRef = ref<HTMLDivElement>() const chartRef = ref<HTMLDivElement>()
const url: any = [ const url: any = [
new URL(`@/assets/img/PLPC.png`, import.meta.url), new URL(`@/assets/img/PLPC.png`, import.meta.url),
new URL(`@/assets/img/DYPC.png`, import.meta.url), new URL(`@/assets/img/DYPC.png`, import.meta.url),
new URL(`@/assets/img/JBL.png`, import.meta.url), new URL(`@/assets/img/JBL.png`, import.meta.url),
new URL(`@/assets/img/SXDY.png`, import.meta.url), new URL(`@/assets/img/SXDY.png`, import.meta.url),
new URL(`@/assets/img/SB.png`, import.meta.url) new URL(`@/assets/img/SB.png`, import.meta.url)
] ]
const tableData: any = ref([]) const tableData: any = ref([])
const title = ['电压偏差(超标)', '频率偏差(超标)', '电压总谐波畸变率(超标)', '闪变(超标)', '三相电压不平衡度(超标)'] const title = ['电压偏差(超标)', '频率偏差(超标)', '电压总谐波畸变率(超标)', '闪变(超标)', '三相电压不平衡度(超标)']
const echart = (row: any) => { const echart = (row: any) => {
let maxList: any = [] let maxList: any = []
row.forEach((item: any) => { row.forEach((item: any) => {
maxList.push(...(item.ratioList || [0])) maxList.push(...(item.ratioList || [0]))
}) })
let max = Math.max(...maxList) > 50 ? 100 : 50 let max = Math.max(...maxList) > 50 ? 100 : 50
let chart = echarts.init(chartRef.value as HTMLDivElement) let chart = echarts.init(chartRef.value as HTMLDivElement)
let dataname = ['频率偏差(Hz)', let dataname = ['频率偏差(Hz)',
'电压偏差(%)', '电压偏差(%)',
'电压总谐波畸变率(%)', '电压总谐波畸变率(%)',
'三相电压不平衡度(%)', '三相电压不平衡度(%)',
'闪变', '闪变',
'谐波电压(%)', '谐波电压(%)',
'谐波电流(%)', '谐波电流(%)',
'间谐波电压(%)', '间谐波电压(%)',
'负序电流(A)'] '负序电流(A)']
// let datamax = [100, 100, 100, 100, 100, 100] // let datamax = [100, 100, 100, 100, 100, 100]
let indicator = [] let indicator = []
for (let i = 0; i < dataname.length; i++) { for (let i = 0; i < dataname.length; i++) {
indicator.push({ indicator.push({
name: dataname[i], name: dataname[i],
max: max max: max
}) })
} }
let option: any = { let option: any = {
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
axisPointer: { axisPointer: {
type: 'shadow', type: 'shadow',
label: { label: {
color: '#fff', color: '#fff',
fontSize: 16 fontSize: 16
} }
}, },
textStyle: { textStyle: {
color: '#fff', color: '#fff',
fontStyle: 'normal', fontStyle: 'normal',
opacity: 0.35, opacity: 0.35,
fontSize: 14 fontSize: 14
}, },
backgroundColor: 'rgba(0,0,0,0.55)', backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0, borderWidth: 0,
position: 'bottom' position: 'bottom'
}, },
legend: { legend: {
data: row.map((item: any) => item.time), data: row.map((item: any) => item.time),
type: 'scroll', type: 'scroll',
orient: 'vertical', orient: 'vertical',
icon: 'roundRect', icon: 'roundRect',
right: '20', right: '20',
itemGap: 10, itemGap: 10,
itemWidth: 16, itemWidth: 16,
itemHeight: 16, itemHeight: 16,
textStyle: { textStyle: {
fontSize: '15', fontSize: '15',
color: '#656565' color: '#656565'
} }
}, },
radar: { radar: {
center: ['50%', '60%'], center: ['50%', '60%'],
radius: '60%', radius: '60%',
startAngle: 90, startAngle: 90,
splitNumber: 5, splitNumber: 5,
splitArea: { splitArea: {
areaStyle: { areaStyle: {
color: ['#FFFFFF', '#F5F9FF'].reverse() color: ['#FFFFFF', '#F5F9FF'].reverse()
} }
}, },
axisLabel: { axisLabel: {
show: false show: false
}, },
axisLine: { axisLine: {
show: true, show: true,
lineStyle: { lineStyle: {
color: '#D2E4F8' color: '#D2E4F8'
} }
}, },
splitLine: { splitLine: {
show: true, show: true,
lineStyle: { lineStyle: {
color: '#D2E4F8' color: '#D2E4F8'
} }
}, },
name: { name: {
formatter: '{value}', formatter: '{value}',
textStyle: { textStyle: {
color: '#656565', color: '#656565',
fontSize: 15 fontSize: 15
} }
}, },
indicator: indicator indicator: indicator
}, },
series: [] series: []
} }
row.forEach((item: any, i: any) => { row.forEach((item: any, i: any) => {
option.series.push({ option.series.push({
name: item.time, name: item.time,
type: 'radar', type: 'radar',
symbol: 'none', symbol: 'none',
areaStyle: { areaStyle: {
normal: { normal: {
color: color[i + 1] color: color[i + 1]
} }
}, },
itemStyle: { itemStyle: {
color: color[i + 1] color: color[i + 1]
}, },
data: [item.ratioList] data: [item.ratioList]
}) })
}) })
chart.setOption(option) chart.setOption(option)
} }
const open = async (row: any) => { const open = async (row: any) => {
rowList.value = row rowList.value = row
dialogVisible.value = true dialogVisible.value = true
// 稳态电能质量水平评估 // 稳态电能质量水平评估
handleClick(0) handleClick(0)
//环比 //环比
evaluationRatio(row).then(res => { evaluationRatio(row).then(res => {
echart(res.data) echart(res.data)
}) })
// 稳态电能质量水平评估详细列表 // 稳态电能质量水平评估详细列表
evaluationDetail(row).then(res => { evaluationDetail(row).then(res => {
tableData.value = res.data tableData.value = res.data
}) })
} }
// 点击电压等级 // 点击电压等级
const handleClick = (i: any) => { const handleClick = (i: any) => {
active.value = i active.value = i
getEvaluationData({ getEvaluationData({
...rowList.value, ...rowList.value,
voltageLevel: Voltage[i].id voltageLevel: Voltage[i].id
}).then(res => { }).then(res => {
evaluationData.value = res.data evaluationData.value = res.data
}) })
} }
defineExpose({ open }) defineExpose({ open })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-select) { :deep(.el-select) {
min-width: 80px; min-width: 80px;
} }
.title { .title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin: 10px; margin: 10px;
span { span {
font-weight: 550; font-weight: 550;
font-size: 18px; font-size: 18px;
} }
} }
.pie { .pie {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
} }
.evaluationData { .evaluationData {
height: 33px; height: 33px;
margin: 8px 30px; margin: 8px 30px;
width: 100%; width: 100%;
box-shadow: 1px 1px 1px 1px #e8e3e3; box-shadow: 1px 1px 1px 1px #e8e3e3;
display: flex; display: flex;
font-size: 18px; font-size: 18px;
line-height: 35px; line-height: 35px;
img { img {
height: 25px; height: 25px;
width: 25px; width: 25px;
margin: 4px 20px 0px 30px; margin: 4px 20px 0px 30px;
} }
} }
.el-steps { .el-steps {
margin-top: 5px; margin-top: 5px;
} }
:deep(.el-step__icon) { :deep(.el-step__icon) {
border: none; border: none;
background: #ccc; background: #ccc;
margin-top: 5px; margin-top: 5px;
width: 15px; width: 15px;
height: 15px; height: 15px;
} }
:deep(.el-step__icon-inner) { :deep(.el-step__icon-inner) {
display: none; display: none;
} }
:deep(.boxSteps) { :deep(.boxSteps) {
border-radius: 50px; border-radius: 50px;
width: 60%; width: 60%;
height: 25px; height: 25px;
margin: auto; margin: auto;
margin-top: 30px; margin-top: 30px;
.el-step__title { .el-step__title {
line-height: 18px; line-height: 18px;
font-size: 16px; font-size: 16px;
margin-left: -10px; margin-left: -10px;
font-weight: 500; font-weight: 500;
color: #000 !important; color: #000 !important;
position: relative; position: relative;
top: -50px; top: -50px;
} }
} }
:deep(.highlight) { :deep(.highlight) {
.el-step__icon { .el-step__icon {
background: var(--el-color-primary); background: var(--el-color-primary);
} }
.el-step__title { .el-step__title {
font-weight: 700 !important; font-weight: 700 !important;
color: var(--el-color-primary) !important; color: var(--el-color-primary) !important;
} }
// .is-wait { // .is-wait {
// color: var(--el-color-primary) !important; // color: var(--el-color-primary) !important;
// } // }
} }
:deep(.el-dialog__body) { :deep(.el-dialog__body) {
max-height: none !important; max-height: none !important;
} }
</style> </style>

View File

@@ -6,7 +6,7 @@
<span style="font-size: 16px">{{ dropList.lineName }}详情 </span> <span style="font-size: 16px">{{ dropList.lineName }}详情 </span>
<span style="font-weight: 500">最新数据时间</span> <span style="font-weight: 500">最新数据时间</span>
<span style="color: var(--color-primary-default)">{{ dropList.updateTime }}</span> <span style="color: var(--color-primary-default)">{{ dropList.updateTime }}</span>
<span style="font-weight: 500">统计日期</span> <span style="font-weight: 500" class="ml20">统计日期</span>
<span style="color: var(--color-primary-default)"> <span style="color: var(--color-primary-default)">
{{ getTimeOfTheMonth('3')[0] + '至' + getTimeOfTheMonth('3')[1] }} {{ getTimeOfTheMonth('3')[0] + '至' + getTimeOfTheMonth('3')[1] }}
</span> </span>
@@ -657,7 +657,7 @@ const echart = (row: any) => {
}, },
indicator: indicator indicator: indicator
}, },
color: color,
series: [] series: []
} }
@@ -666,13 +666,17 @@ const echart = (row: any) => {
name: item.time, name: item.time,
type: 'radar', type: 'radar',
symbol: 'none', symbol: 'none',
areaStyle: { areaStyle: {
normal: { opacity: 0.6, // 调整透明度,避免重叠遮挡
color: '#2a9fe069' color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
} { offset: 0, color: `${color[i]}50` },
{ offset: 1, color: `${color[i]}50` } // 渐变透明
])
}, },
itemStyle: { lineStyle: {
color: '#2a9fe0' color: color[i],
width: 2
}, },
data: [item.ratioList] data: [item.ratioList]
}) })

View File

@@ -2,7 +2,7 @@
<div> <div>
<TableHeader date-picker area ref="TableHeaderRef"> <TableHeader date-picker area ref="TableHeaderRef">
<template v-slot:select> <template v-slot:select>
<el-form-item label="对象类型"> <!-- <el-form-item label="对象类型">
<el-select <el-select
v-model="tableStore.table.params.objType" v-model="tableStore.table.params.objType"
clearable clearable
@@ -16,7 +16,7 @@
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item> -->
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家:">
<el-select <el-select
v-model="tableStore.table.params.manufacturer" v-model="tableStore.table.params.manufacturer"
@@ -136,7 +136,7 @@
/> />
</el-form-item> </el-form-item>
<el-form-item class="form_but"> <el-form-item class="form_but">
<el-button type="primary" @click="MonitorVerify" icon="el-icon-Refresh">更新</el-button> <el-button type="primary" @click="MonitorVerify" icon="el-icon-Search">查询</el-button>
<el-button type="primary" @click="onExport" icon="el-icon-Download">导出</el-button> <el-button type="primary" @click="onExport" icon="el-icon-Download">导出</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>

View File

@@ -1,143 +1,151 @@
<template> <template>
<el-dialog draggable width="1350px" class="cn-operate-dialog" v-model="dialogVisible" :title="title"> <el-dialog draggable width="1350px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<div style="display: flex"> <div style="display: flex" v-loading="loading">
<div :style="height1" class="mr10 box" style="width: 500px"> <div :style="height1" class="mr10 box" style="width: 500px">
<vxe-table <vxe-table
height="auto" height="auto"
:data="TableData" :data="TableData"
v-bind="defaultAttribute" v-bind="defaultAttribute"
ref="tableRef" ref="tableRef"
:row-config="{ isCurrent: true, isHover: true }" :row-config="{ isCurrent: true, isHover: true }"
@current-change="currentChangeEvent" @current-change="currentChangeEvent"
> >
<vxe-column type="seq" title="序号" width="60px"></vxe-column> <vxe-column type="seq" title="序号" width="60px"></vxe-column>
<vxe-column field="date" title="日期"></vxe-column> <vxe-column field="date" title="日期"></vxe-column>
<vxe-column field="bdName" title="所属电站(场站)" width="120px"></vxe-column> <vxe-column field="bdName" title="所属电站(场站)" width="120px"></vxe-column>
<vxe-column field="monitorName" title="监测点名称" width="120px"></vxe-column> <vxe-column field="monitorName" title="监测点名称" width="120px"></vxe-column>
<vxe-column field="timeSum" title="告警时间(分钟)" width="80px"></vxe-column> <vxe-column field="timeSum" title="告警时间(分钟)" width="80px"></vxe-column>
</vxe-table> </vxe-table>
</div> </div>
<div :style="height" style="width: 820px" v-loading="loading1"> <div :style="height" style="width: 820px" v-loading="loading1">
<vxe-table <vxe-table
height="auto" height="auto"
:data="TableData1.slice((pageNum - 1) * pageSize, pageNum * pageSize)" :data="TableData1.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
v-bind="defaultAttribute" v-bind="defaultAttribute"
> >
<vxe-column type="seq" title="序号" width="80px"> <vxe-column type="seq" title="序号" width="80px">
<template #default="{ rowIndex }"> <template #default="{ rowIndex }">
<span>{{ (pageNum - 1) * pageSize + rowIndex + 1 }}</span> <span>{{ (pageNum - 1) * pageSize + rowIndex + 1 }}</span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="time" title="时间" :formatter="formatter"></vxe-column> <vxe-column field="time" title="时间" :formatter="formatter"></vxe-column>
<vxe-column field="targetName" title="指标类型" min-width="100px"></vxe-column> <vxe-column field="targetName" title="指标类型" min-width="100px"></vxe-column>
<vxe-column field="phaseType" title="相别" width="80px"> <vxe-column field="phaseType" title="相别" width="80px">
<template v-slot="{ row }"> <template v-slot="{ row }">
{{ row.phaseType == 'T' ? '/' : row.phaseType }} {{ row.phaseType == 'T' ? '/' : row.phaseType }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="type" title="数据类型" width="105px" :formatter="formatter"></vxe-column> <vxe-column field="type" title="数据类型" width="105px" :formatter="formatter"></vxe-column>
<vxe-column field="val" title="值" width="85px" :formatter="formatter"></vxe-column> <vxe-column field="val" title="值" width="85px" :formatter="formatter"></vxe-column>
</vxe-table> <vxe-column field="overLimitValue" title="限值" width="85px" :formatter="formatter"></vxe-column>
<div class="table-pagination"> </vxe-table>
<el-pagination <div class="table-pagination">
v-model:currentPage="pageNum" <el-pagination
v-model:page-size="pageSize" v-model:currentPage="pageNum"
:page-sizes="[10, 20, 50, 100, 200]" v-model:page-size="pageSize"
background :page-sizes="[10, 20, 50, 100, 200]"
layout="sizes,total, ->, prev, pager, next, jumper" background
:total="TableData1.length" layout="sizes,total, ->, prev, pager, next, jumper"
></el-pagination> :total="TableData1.length"
</div> ></el-pagination>
</div> </div>
</div> </div>
</el-dialog> </div>
</template> </el-dialog>
<script lang="ts" setup> </template>
import { ref, inject } from 'vue' <script lang="ts" setup>
import { useDictData } from '@/stores/dictData' import { ref, inject } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { monitorLimitTable, monitorLimitTableDetail } from '@/api/device-boot/dataVerify' import { ElMessage } from 'element-plus'
import { mainHeight } from '@/utils/layout' import { monitorLimitTable, monitorLimitTableDetail } from '@/api/device-boot/dataVerify'
const dictData = useDictData() import { mainHeight } from '@/utils/layout'
const StatisList = dictData.getBasicData('Steady_Statis') const dictData = useDictData()
const dialogVisible = ref(false) const StatisList = dictData.getBasicData('Steady_Statis')
const height1 = mainHeight(-110, 2) const dialogVisible = ref(false)
const height = mainHeight(10, 2) const height1 = mainHeight(-110, 2)
const tableRef = ref() const height = mainHeight(10, 2)
const title = ref('') const tableRef = ref()
const loading1 = ref(false) const title = ref('')
const TableData = ref([]) const loading = ref(false)
const TableData1 = ref([]) const loading1 = ref(false)
const pageNum = ref(1) const TableData = ref([])
const pageSize = ref(20) const TableData1 = ref([])
const numKey = ref(0) const pageNum = ref(1)
const targetKey = ref('') const pageSize = ref(20)
const clickRow = ref({}) const numKey = ref(0)
const open = (data: anyObj, time: string[], num: number) => { const targetKey = ref('')
// title.value = (num == 0 ? data.targetName : data.monitorName) + '_告警详情展示' const clickRow = ref({})
title.value = '告警监测点详情' const open = (data: anyObj, time: string[], num: number) => {
numKey.value = num // title.value = (num == 0 ? data.targetName : data.monitorName) + '_告警详情展示'
targetKey.value = data.key loading.value = true
TableData.value = [] title.value = '告警监测点详情'
monitorLimitTable({ numKey.value = num
monitorIds: num == 0 ? data.ids : [data.monitorId], targetKey.value = data.key
targetKey: num == 0 ? data.key : '', TableData.value = []
searchBeginTime: time[0], monitorLimitTable({
searchEndTime: time[1] monitorIds: num == 0 ? data.ids : [data.monitorId],
}).then(res => { targetKey: num == 0 ? data.key : '',
TableData.value = res.data searchBeginTime: time[0],
tableRef.value.setCurrentRow(TableData.value[0]) searchEndTime: time[1]
currentChangeEvent() })
}) .then(res => {
dialogVisible.value = true TableData.value = res.data
} tableRef.value.setCurrentRow(TableData.value[0])
const currentChangeEvent = () => { currentChangeEvent()
loading1.value = true loading.value = false
clickRow.value = tableRef.value.getCurrentRecord() })
TableData1.value = [] .catch(() => {
monitorLimitTableDetail({ loading.value = false
monitorIds: [clickRow.value.monitorId], })
searchBeginTime: clickRow.value.date, dialogVisible.value = true
targetKey: numKey.value == 0 ? targetKey.value : '' }
}) const currentChangeEvent = () => {
.then(res => { loading1.value = true
TableData1.value = res.data clickRow.value = tableRef.value.getCurrentRecord()
loading1.value = false TableData1.value = []
pageNum.value = 1 monitorLimitTableDetail({
}) monitorIds: [clickRow.value.monitorId],
.catch(() => { searchBeginTime: clickRow.value.date,
loading1.value = false targetKey: numKey.value == 0 ? targetKey.value : ''
}) })
} .then(res => {
const formatter = (row: any) => { TableData1.value = res.data
if (row.column.field == 'time') { loading1.value = false
return clickRow.value.date + ' ' + row.cellValue pageNum.value = 1
} else if (row.column.field == 'type') { })
return row.cellValue === 'null' ? '/' : row.cellValue .catch(() => {
} else { loading1.value = false
return row.cellValue == null ? '/' : (row.cellValue - 0).toFixed(2) })
} }
} const formatter = (row: any) => {
defineExpose({ open }) if (row.column.field == 'time') {
</script> return clickRow.value.date + ' ' + row.cellValue
<style lang="scss" scoped> } else if (row.column.field == 'type') {
.table-pagination { return row.cellValue === 'null' ? '/' : row.cellValue
height: 58px; } else {
box-sizing: border-box; return row.cellValue == null ? '/' : (row.cellValue - 0).toFixed(2)
width: 100%; }
max-width: 100%; }
background-color: var(--ba-bg-color-overlay); defineExpose({ open })
padding: 13px 15px; </script>
border-left: 1px solid #e4e7e9; <style lang="scss" scoped>
border-right: 1px solid #e4e7e9; .table-pagination {
border-bottom: 1px solid #e4e7e9; height: 58px;
} box-sizing: border-box;
:deep(.box) { width: 100%;
.row--current { max-width: 100%;
background-color: var(--el-color-primary-light-8) !important; background-color: var(--ba-bg-color-overlay);
} padding: 13px 15px;
} border-left: 1px solid #e4e7e9;
</style> border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
:deep(.box) {
.row--current {
background-color: var(--el-color-primary-light-8) !important;
}
}
</style>

View File

@@ -254,7 +254,7 @@ onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
setTimeout(() => { setTimeout(() => {
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}, 100) }, 100)
}) })

View File

@@ -2,7 +2,7 @@
<div> <div>
<TableHeader date-picker area ref="TableHeaderRef"> <TableHeader date-picker area ref="TableHeaderRef">
<template v-slot:select> <template v-slot:select>
<el-form-item label="对象类型"> <!-- <el-form-item label="对象类型">
<el-select <el-select
v-model="tableStore.table.params.objType" v-model="tableStore.table.params.objType"
clearable clearable
@@ -16,7 +16,7 @@
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item> -->
<el-form-item label="终端厂家:"> <el-form-item label="终端厂家:">
<el-select v-model="tableStore.table.params.manufacturer" clearable placeholder="请选择终端厂家"> <el-select v-model="tableStore.table.params.manufacturer" clearable placeholder="请选择终端厂家">
<el-option <el-option
@@ -60,8 +60,8 @@
{{ {{
isNaN((monitoringPoints.abnormalNum / monitoringPoints.runNum) * 100) isNaN((monitoringPoints.abnormalNum / monitoringPoints.runNum) * 100)
? 0 ? 0
: Math.floor((monitoringPoints.abnormalNum / monitoringPoints.runNum) * 10000) / : Math.floor((monitoringPoints.abnormalNum / monitoringPoints.runNum) * 10000) /
100 100
}}% }}%
</div> </div>
</div> </div>
@@ -99,13 +99,13 @@
</el-segmented> </el-segmented>
</div> </div>
<div class="header"> <div class="header">
<span style="width: 170px; text-align: left">指标名称</span> <span style="width: 165px; text-align: left">指标名称</span>
<span style="flex: 1">合理范围</span> <span style="flex: 1">合理范围</span>
<span style="width: 90px">异常测点数</span> <span style="width: 80px">异常测点数</span>
</div> </div>
<div :style="indicatorHeight" style="overflow-y: auto"> <div :style="indicatorHeight" style="overflow-y: auto">
<div v-for="o in abnormal.filter(item => item.remark == segmented)" class="abnormal mb10"> <div v-for="o in abnormal.filter(item => item.remark == segmented)" class="abnormal mb10">
<span style="width: 170px; height: 24px" class="iconDiv"> <span style="width: 165px; height: 24px" class="iconDiv">
<div :style="{ backgroundColor: o.ids.length > 0 ? '#FF9100' : '' }"></div> <div :style="{ backgroundColor: o.ids.length > 0 ? '#FF9100' : '' }"></div>
{{ o.targetName }} {{ o.targetName }}
</span> </span>
@@ -113,7 +113,7 @@
<!-- 合理范围 --> <!-- 合理范围 -->
<span style="color: #388e3c" class="text">{{ o.rangeDesc }}</span> <span style="color: #388e3c" class="text">{{ o.rangeDesc }}</span>
</span> </span>
<span style="width: 90px; text-align: center"> <span style="width: 80px; text-align: center">
<span <span
style="color: #388e3c" style="color: #388e3c"
:class="` ${o.ids.length > 0 ? 'text-red' : ''}`" :class="` ${o.ids.length > 0 ? 'text-red' : ''}`"
@@ -173,26 +173,26 @@
</span> </span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="monitorName" title="监测点名称"></vxe-column> <vxe-column field="monitorName" title="监测点名称" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家"></vxe-column> <vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="devName" title="所属终端名称"></vxe-column> <vxe-column field="devName" title="所属终端名称" minWidth="110px"></vxe-column>
<vxe-column field="ip" title="IP"> <vxe-column field="ip" title="IP">
<template #default="{ row }"> <template #default="{ row }">
{{ decryptFromBase64(row.ip) }} {{ decryptFromBase64(row.ip) }}
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="stationName" title="所属电站"></vxe-column> <vxe-column field="stationName" title="所属电站" minWidth="110px"></vxe-column>
<vxe-column field="objType" title="监测对象类型" :formatter="formatter"></vxe-column> <vxe-column field="objType" title="监测对象类型" :formatter="formatter" minWidth="110px"></vxe-column>
<vxe-column field="objName" title="监测对象名称" :formatter="formatter"></vxe-column> <vxe-column field="objName" title="监测对象名称" :formatter="formatter" minWidth="110px"></vxe-column>
<vxe-column field="voltageLevel" title="电压等级"></vxe-column> <vxe-column field="voltageLevel" title="电压等级" minWidth="80px"></vxe-column>
<vxe-column field="abnormalDay" title="异常天数"> <vxe-column field="abnormalDay" title="异常天数" width="80px">
<template #default="{ row }"> <template #default="{ row }">
<span class="table_name" @click="quantityClick(row, 1)"> <span class="table_name" @click="quantityClick(row, 1)">
{{ row.abnormalDay }} {{ row.abnormalDay }}
</span> </span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="abnormalDay" title="严重度"> <vxe-column field="abnormalDay" title="严重度" width="80px">
<template #default="{ row }"> <template #default="{ row }">
<el-tag type="warning" v-if="row.severity == 0">预警</el-tag> <el-tag type="warning" v-if="row.severity == 0">预警</el-tag>
<el-tag type="danger" v-if="row.severity == 1">告警</el-tag> <el-tag type="danger" v-if="row.severity == 1">告警</el-tag>
@@ -518,7 +518,7 @@ tableStore.table.params.name = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/font/iconfont.css'; @import '@/assets/font/iconfont.css';
.card-list { .card-list {
display: flex; display: flex;
.monitoringPoints { .monitoringPoints {

View File

@@ -1,6 +1,6 @@
<template> <template>
<el-dialog draggable width="1550px" class="cn-operate-dialog" v-model="dialogVisible" :title="title"> <el-dialog draggable width="1550px" class="cn-operate-dialog" v-model="dialogVisible" :title="title">
<div style="display: flex"> <div style="display: flex" v-loading="loading">
<div :style="height1" class="mr10 box" style="width: 600px"> <div :style="height1" class="mr10 box" style="width: 600px">
<vxe-table <vxe-table
height="auto" height="auto"
@@ -100,6 +100,7 @@ const height1 = mainHeight(-110, 2)
const height = mainHeight(10, 2) const height = mainHeight(10, 2)
const tableRef = ref() const tableRef = ref()
const title = ref('') const title = ref('')
const loading = ref(false)
const loading1 = ref(false) const loading1 = ref(false)
const TableData = ref([]) const TableData = ref([])
const TableData1 = ref([]) const TableData1 = ref([])
@@ -110,6 +111,7 @@ const targetKey = ref('')
const showColumn = ref(true) const showColumn = ref(true)
const open = (data: anyObj, time: string[], num: number) => { const open = (data: anyObj, time: string[], num: number) => {
// title.value = (num == 0 ? data.targetName : data.monitorName) + '_异常监测点详情' // title.value = (num == 0 ? data.targetName : data.monitorName) + '_异常监测点详情'
loading.value = true
title.value = '异常监测点详情' title.value = '异常监测点详情'
TableData.value = [] TableData.value = []
numKey.value = num numKey.value = num
@@ -123,6 +125,9 @@ const open = (data: anyObj, time: string[], num: number) => {
TableData.value = res.data TableData.value = res.data
tableRef.value.setCurrentRow(TableData.value[0]) tableRef.value.setCurrentRow(TableData.value[0])
currentChangeEvent() currentChangeEvent()
loading.value = false
}).catch(() => {
loading.value = false
}) })
dialogVisible.value = true dialogVisible.value = true
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<TableHeader date-picker ref="TableHeaderRef" > <TableHeader date-picker ref="TableHeaderRef">
<template v-slot:select> <template v-slot:select>
<el-form-item label="运行状态"> <el-form-item label="运行状态">
<el-select v-model="tableStore.table.params.lineRunFlag" clearable placeholder="请选择运行状态"> <el-select v-model="tableStore.table.params.lineRunFlag" clearable placeholder="请选择运行状态">
@@ -12,8 +12,8 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.filterName" placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入终端名称" />
</el-form-item> </el-form-item>
</template> </template>
@@ -86,22 +86,22 @@
</span> </span>
<!-- --> <!-- -->
<span <span
style="flex: 1; color: #ff9100" style="flex: 1; color: #388e3c"
class="text" class="text"
:class="` ${o.integrity < 90 ? 'text-red' : ''}`" :class="` ${o.integrity < 90 ? 'text-red' : ''}`"
> >
{{ o.integrity }} {{ o.integrity }}
</span> </span>
<span <span
style="width: 80px; color: #388e3c" style="width: 80px; color: #388e3c"
:class="` ${o.online < 90 ? 'text-red' : ''}`" :class="` ${o.online < 90 ? 'text-red' : ''}`"
class="text" class="text"
> >
{{ o.online }} {{ o.online }}
</span> </span>
<span <span
style="width: 80px; color: #388e3c" style="width: 80px; color: #388e3c"
:class="` ${o.qualified < 90 ? 'text-red' : ''}`" :class="` ${o.qualified > 10 ? 'text-red' : ''}`"
class="text" class="text"
> >
{{ o.qualified }} {{ o.qualified }}
@@ -138,12 +138,12 @@
</span> </span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="cit" title="所在地市" width="110px"></vxe-column> <vxe-column field="cit" title="所在地市" minWidth="110px"></vxe-column>
<vxe-column field="company" title="供电公司"></vxe-column> <vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subName" title="变电站"></vxe-column> <vxe-column field="subName" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家"></vxe-column> <vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="name" title="终端名称"></vxe-column> <vxe-column field="name" title="终端名称" minWidth="110px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="130px"></vxe-column> <vxe-column field="ip" title="终端IP" :formatter="formatter" width="130px" ></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="100px"> <vxe-column field="runFlag" title="运行状态" width="100px">
<template #default="{ row }"> <template #default="{ row }">
<el-tag <el-tag
@@ -269,9 +269,13 @@ const tableStore = new TableStore({
statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length statisticsList.value.checkNum = totalData.value.filter(item => item.runFlag === '调试').length
statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length statisticsList.value.stopRunNum = totalData.value.filter(item => item.runFlag === '停运').length
abnormal.value = tableStore.table.data.filter( abnormal.value = tableStore.table.data.filter((k: any) => {
(k: any) => k.name != '上送国网' && k.name != '非上送国网' if (tableStore.table.params.statisticalType.name == '终端厂家') {
) return k.count != 0
} else {
return k.name != '上送国网' && k.name != '非上送国网'
}
})
// 合并子集数据 并去重 // 合并子集数据 并去重
totalTable(101, '') totalTable(101, '')
@@ -406,7 +410,8 @@ const echart = () => {
} }
} }
tableStore.table.params.deptIndex = dictData.state.area[0].id tableStore.table.params.deptIndex = dictData.state.area[0].id
tableStore.table.params.lineRunFlag = '' tableStore.table.params.lineRunFlag = 0
tableStore.table.params.searchValue = ''
const formatter = (row: any) => { const formatter = (row: any) => {
return row.cellValue || '/' return row.cellValue || '/'
@@ -425,7 +430,7 @@ const totalTable = (num: number, t: string) => {
} }
const change = (e: string) => { const change = (e: string) => {
title.value = e==''?'' : e+'_' title.value = e == '' ? '' : e + '_'
loading.value = true loading.value = true
pageNum.value = 1 pageNum.value = 1
dataList.value = [] dataList.value = []

View File

@@ -1,331 +1,331 @@
<!--待办事项列表--> <!--待办事项列表-->
<template> <template>
<div> <div>
<TableHeader date-picker nextFlag theCurrentTime> <TableHeader date-picker nextFlag theCurrentTime>
<template #select> <template #select>
<el-form-item label="流程状态"> <el-form-item label="流程状态">
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择流程状态"> <el-select v-model="tableStore.table.params.status" clearable placeholder="请选择流程状态">
<el-option v-for="item in statusSelect" :key="item.id" :label="item.name" <el-option v-for="item in statusSelect" :key="item.id" :label="item.name"
:value="item.id"></el-option> :value="item.id"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入关键字" <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入关键字"
clearable maxlength="32" show-word-limit></el-input> clearable maxlength="32" show-word-limit></el-input>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button> <el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button> <el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button>
</template> </template>
</TableHeader> </TableHeader>
<!--表格--> <!--表格-->
<Table ref="tableRef" :checkbox-config="checkboxConfig"></Table> <Table ref="tableRef" :checkbox-config="checkboxConfig"></Table>
<!--弹框--> <!--弹框-->
<monitor-quit-popup ref="deviceQuitPopup" /> <monitor-quit-popup ref="deviceQuitPopup" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref, watch } from 'vue' import { onMounted, provide, ref, watch } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import MonitorQuitPopup from '@/views/pqs/supervise/retire/monitorQuitPopup.vue' import MonitorQuitPopup from '@/views/pqs/supervise/retire/monitorQuitPopup.vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { ElMessageBox } from 'element-plus/es' import { ElMessageBox } from 'element-plus/es'
import { cancelQuitRunningDevice, getRunningDeviceById } from '@/api/supervision-boot/device/quitRunningDev' import { cancelQuitRunningDevice, getRunningDeviceById } from '@/api/supervision-boot/device/quitRunningDev'
import { deleteQuitRunningDevice } from '@/api/supervision-boot/delete/index' import { deleteQuitRunningDevice } from '@/api/supervision-boot/delete/index'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
const dictData = useDictData() const dictData = useDictData()
const statusSelect = dictData.statusSelect() const statusSelect = dictData.statusSelect()
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
//获取登陆用户姓名和部门 //获取登陆用户姓名和部门
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
defineOptions({ defineOptions({
name: 'supervision/retire' name: 'supervision/retire'
}) })
const { push, options, currentRoute } = useRouter() const { push, options, currentRoute } = useRouter()
const flag = ref(false) const flag = ref(false)
const deviceQuitPopup = ref() const deviceQuitPopup = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/supervision-boot/quitRunningDevice/list', url: '/supervision-boot/quitRunningDevice/list',
method: 'POST', method: 'POST',
publicHeight: 65, publicHeight: 65,
column: [ column: [
{ {
width: '60', width: '60',
type: 'checkbox' type: 'checkbox'
}, },
{ {
title: '序号', title: '序号',
width: '80', width: '80',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ title: '供电公司', field: 'gdName', minWidth: 130 }, { title: '供电公司', field: 'gdName', minWidth: 130 },
{ title: '变电站', field: 'subName', minWidth: 160 }, { title: '变电站', field: 'subName', minWidth: 160 },
{ title: '监测点', field: 'deviceName', minWidth: 200 }, { title: '监测点', field: 'deviceName', minWidth: 200 },
{ title: '退运原因', field: 'propertyNo', minWidth: 160 }, { title: '退运原因', field: 'propertyNo', minWidth: 160 },
{ {
title: '变更前状态', title: '变更前状态',
field: 'devOriginalStatus', field: 'devOriginalStatus',
minWidth: 130, minWidth: 130,
render: 'tag', render: 'tag',
custom: { custom: {
0: 'success', 0: 'success',
1: 'warning', 1: 'warning',
2: 'danger', 2: 'danger',
3: 'warning', 3: 'warning',
4: 'info', 4: 'info',
null: 'primary' null: 'primary'
}, },
replaceValue: { replaceValue: {
0: '投运', 0: '投运',
1: '检修', 1: '检修',
2: '停运', 2: '停运',
3: '调试', 3: '调试',
4: '退运', 4: '退运',
null: '/' null: '/'
} }
}, },
{ {
title: '目标状态', title: '目标状态',
field: 'devStatus', field: 'devStatus',
minWidth: 130, minWidth: 130,
render: 'tag', render: 'tag',
custom: { custom: {
0: 'success', 0: 'success',
1: 'warning', 1: 'warning',
2: 'danger', 2: 'danger',
3: 'warning', 3: 'warning',
4: 'info', 4: 'info',
null: 'primary' null: 'primary'
}, },
replaceValue: { replaceValue: {
0: '投运', 0: '投运',
1: '检修', 1: '检修',
2: '停运', 2: '停运',
3: '调试', 3: '调试',
4: '退运', 4: '退运',
null: '/' null: '/'
} }
}, },
{ {
field: 'status', field: 'status',
title: '流程状态', title: '流程状态',
minWidth: 100, minWidth: 100,
render: 'tag', render: 'tag',
custom: { custom: {
0: 'warning', 0: 'warning',
1: 'primary', 1: 'primary',
2: 'success', 2: 'success',
3: 'danger', 3: 'danger',
4: 'warning', 4: 'warning',
null: 'primary' null: 'primary'
}, },
replaceValue: { replaceValue: {
0: '待提交审批', 0: '待提交审批',
1: '审批中', 1: '审批中',
2: '审批通过', 2: '审批通过',
3: '审批不通过', 3: '审批不通过',
4: '已取消', 4: '已取消',
null: '/' null: '/'
} }
}, },
{ field: 'createTime', title: '开始时间', minWidth: 170 }, { field: 'createTime', title: '开始时间', minWidth: 170 },
{ {
field: 'createBy', field: 'createBy',
title: '填报人', title: '填报人',
minWidth: 80, minWidth: 80,
formatter: (row: any) => { formatter: (row: any) => {
return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name
} }
}, },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
minWidth: '150', minWidth: '150',
fixed: 'right', fixed: 'right',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
{ {
name: 'productSetting', name: 'productSetting',
title: '流程详情', title: '流程详情',
type: 'primary', type: 'primary',
icon: 'el-icon-EditPen', icon: 'el-icon-EditPen',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return !row.processInstanceId return !row.processInstanceId
}, },
click: row => { click: row => {
handleAudit(row.processInstanceId, row.historyInstanceId) handleAudit(row.processInstanceId, row.historyInstanceId)
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '编辑', title: '编辑',
type: 'primary', type: 'primary',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
showDisabled: row => { showDisabled: row => {
return row.createBy != adminInfo.$state.id || !(row.status == 0) return row.createBy != adminInfo.$state.id || !(row.status == 0)
}, },
disabled: row => { disabled: row => {
return !(row.status == 0) return !(row.status == 0)
}, },
click: row => { click: row => {
deviceQuitPopup.value.open('编辑', row) deviceQuitPopup.value.open('编辑', row)
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '重新发起', title: '重新发起',
type: 'warning', type: 'warning',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.createBy != adminInfo.$state.id || !(row.status == 3 || row.status == 4) return row.createBy != adminInfo.$state.id || !(row.status == 3 || row.status == 4)
}, },
click: row => { click: row => {
deviceQuitPopup.value.open('重新发起', row) deviceQuitPopup.value.open('重新发起', row)
} }
}, },
{ {
name: 'cancel', name: 'cancel',
title: '取消', title: '取消',
type: 'danger', type: 'danger',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.createBy != adminInfo.$state.id || row.status !== 1 return row.createBy != adminInfo.$state.id || row.status !== 1
}, },
click: row => { click: row => {
cancelLeave(row) cancelLeave(row)
} }
} }
] ]
} }
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
// for (let key in tableStore.table.params) { // for (let key in tableStore.table.params) {
// if (tableStore.table.params[key] === '') { // if (tableStore.table.params[key] === '') {
// delete tableStore.table.params[key] // delete tableStore.table.params[key]
// } // }
// } // }
tableStore.table.params.deviceType = 2 tableStore.table.params.deviceType = 2
} }
}) })
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
tableStore.table.params.status = '' tableStore.table.params.status = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
//新增退运终端信息 //新增退运终端信息
const add = () => { const add = () => {
deviceQuitPopup.value.open('新增监测点状态变更') deviceQuitPopup.value.open('新增监测点状态变更')
} }
// 禁止点击 // 禁止点击
const checkboxConfig = reactive({ const checkboxConfig = reactive({
checkMethod: ({ row }) => { checkMethod: ({ row }) => {
return adminInfo.roleCode.includes('delete_info') return adminInfo.roleCode.includes('delete_info')
? true ? true
: row.createBy == adminInfo.$state.id && row.status == 0 : row.createBy == adminInfo.$state.id && row.status == 0
} }
}) })
const deleteEven = () => { const deleteEven = () => {
if (tableStore.table.selection.length == 0) { if (tableStore.table.selection.length == 0) {
ElMessage({ ElMessage({
type: 'warning', type: 'warning',
message: '请选择要删除的数据' message: '请选择要删除的数据'
}) })
} else { } else {
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', { ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}) })
.then(() => { .then(() => {
deleteQuitRunningDevice(tableStore.table.selection.map(item => item.id)).then(res => { deleteQuitRunningDevice(tableStore.table.selection.map(item => item.id)).then(res => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: '删除成功!' message: '删除成功!'
}) })
tableStore.index() tableStore.index()
}) })
}) })
} }
} }
/** 流程实例详情 */ /** 流程实例详情 */
const handleAudit = (instanceId: string, historyInstanceId: string) => { const handleAudit = (instanceId: string, historyInstanceId: string) => {
push({ push({
name: 'BpmProcessInstanceDetail', name: 'BpmProcessInstanceDetail',
state: { state: {
id: instanceId, id: instanceId,
historyInstanceId historyInstanceId
} }
}) })
} }
/**取消流程操作*/ /**取消流程操作*/
const cancelLeave = async (row: any) => { const cancelLeave = async (row: any) => {
// 二次确认 // 二次确认
const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', { const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
inputType: 'textarea', inputType: 'textarea',
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格 inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
inputErrorMessage: '取消原因不能为空' inputErrorMessage: '取消原因不能为空'
}) })
// 发起取消 // 发起取消
let data = { let data = {
id: row.id, id: row.id,
processInstanceId: row.processInstanceId, processInstanceId: row.processInstanceId,
reason: value reason: value
} }
await cancelQuitRunningDevice(data) await cancelQuitRunningDevice(data)
ElMessage.success('取消成功') ElMessage.success('取消成功')
// 加载数据 // 加载数据
tableStore.index() tableStore.index()
} }
onMounted(() => { onMounted(() => {
// 加载数据 // 加载数据
tableStore.index() tableStore.index()
}) })
watch( watch(
() => currentRoute.value.path, () => currentRoute.value.path,
() => { () => {
if (flag.value && options.history.state.forward?.split('/')[1] == 'bpm') { if (flag.value && options.history.state.forward?.split('/')[1] == 'bpm') {
tableStore.index() tableStore.index()
flag.value = false flag.value = false
} }
}, },
{ {
deep: true deep: true
} }
) )
const props = defineProps({ id: { type: String, default: 'null' } }) const props = defineProps({ id: { type: String, default: 'null' } })
watch(() => props.id, async (newValue, oldValue) => { watch(() => props.id, async (newValue, oldValue) => {
if (newValue === 'null') return // 直接返回,避免后续逻辑执行 if (newValue === 'null') return // 直接返回,避免后续逻辑执行
const fullId = newValue.split('@')[0] const fullId = newValue.split('@')[0]
let nowTime = Date.now() let nowTime = Date.now()
const routeTime = Number(newValue.split('@')[1]) const routeTime = Number(newValue.split('@')[1])
if (isNaN(routeTime) || nowTime - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return // 路由时间超过500ms则不执行 if (isNaN(routeTime) || nowTime - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return // 路由时间超过500ms则不执行
await getRunningDeviceById(fullId).then(res => { await getRunningDeviceById(fullId).then(res => {
if (res && res.code == 'A0000') { if (res && res.code == 'A0000') {
deviceQuitPopup.value.open('重新发起', res.data) deviceQuitPopup.value.open('重新发起', res.data)
} }
}) })
}, { immediate: true }) }, { immediate: true })
</script> </script>

View File

@@ -1,324 +1,324 @@
<!--待办事项列表--> <!--待办事项列表-->
<template> <template>
<div> <div>
<TableHeader date-picker nextFlag theCurrentTime> <TableHeader date-picker nextFlag theCurrentTime>
<template v-slot:select> <template v-slot:select>
<el-form-item label="流程状态"> <el-form-item label="流程状态">
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择流程状态"> <el-select v-model="tableStore.table.params.status" clearable placeholder="请选择流程状态">
<el-option v-for="item in statusSelect" :key="item.id" :label="item.name" <el-option v-for="item in statusSelect" :key="item.id" :label="item.name"
:value="item.id"></el-option> :value="item.id"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入关键字" clearable maxlength="32" show-word-limit></el-input> <el-input v-model="tableStore.table.params.searchValue" placeholder="请输入关键字" clearable maxlength="32" show-word-limit></el-input>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button> <el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button> <el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button>
</template> </template>
</TableHeader> </TableHeader>
<!--表格--> <!--表格-->
<Table ref="tableRef" :checkbox-config="checkboxConfig"></Table> <Table ref="tableRef" :checkbox-config="checkboxConfig"></Table>
<!--弹框--> <!--弹框-->
<device-quit-popup ref="deviceQuitPopup" /> <device-quit-popup ref="deviceQuitPopup" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref, watch } from 'vue' import { onMounted, provide, ref, watch } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import DeviceQuitPopup from '@/views/pqs/supervise/retire/deviceQuitPopup.vue' import DeviceQuitPopup from '@/views/pqs/supervise/retire/deviceQuitPopup.vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { ElMessageBox } from 'element-plus/es' import { ElMessageBox } from 'element-plus/es'
import { cancelQuitRunningDevice, getRunningDeviceById } from '@/api/supervision-boot/device/quitRunningDev' import { cancelQuitRunningDevice, getRunningDeviceById } from '@/api/supervision-boot/device/quitRunningDev'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { deleteQuitRunningDevice } from '@/api/supervision-boot/delete/index' import { deleteQuitRunningDevice } from '@/api/supervision-boot/delete/index'
const dictData = useDictData() const dictData = useDictData()
const statusSelect = dictData.statusSelect() const statusSelect = dictData.statusSelect()
//获取登陆用户姓名和部门 //获取登陆用户姓名和部门
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
defineOptions({ defineOptions({
name: 'supervision/retire' name: 'supervision/retire'
}) })
const { push, options, currentRoute } = useRouter() const { push, options, currentRoute } = useRouter()
const flag = ref(false) const flag = ref(false)
const deviceQuitPopup = ref() const deviceQuitPopup = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/supervision-boot/quitRunningDevice/list', url: '/supervision-boot/quitRunningDevice/list',
method: 'POST', method: 'POST',
publicHeight: 65, publicHeight: 65,
column: [ column: [
{ {
width: '60', width: '60',
type: 'checkbox' type: 'checkbox'
}, },
{ {
field: 'index', field: 'index',
title: '序号', title: '序号',
width: '80', width: '80',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ title: '供电公司', field: 'gdName', minWidth: 130 }, { title: '供电公司', field: 'gdName', minWidth: 130 },
{ title: '变电站', field: 'subName', minWidth: 160 }, { title: '变电站', field: 'subName', minWidth: 160 },
{ title: '终端名称', field: 'deviceName', minWidth: 130 }, { title: '终端名称', field: 'deviceName', minWidth: 130 },
{ title: '变更原因', field: 'propertyNo', minWidth: 160 }, { title: '变更原因', field: 'propertyNo', minWidth: 160 },
{ {
title: '变更前状态', title: '变更前状态',
field: 'devOriginalStatus', field: 'devOriginalStatus',
minWidth: 130, minWidth: 130,
render: 'tag', render: 'tag',
custom: { custom: {
0: 'success', 0: 'success',
1: 'warning', 1: 'warning',
2: 'danger', 2: 'danger',
3: 'warning', 3: 'warning',
4: 'info', 4: 'info',
null: 'primary' null: 'primary'
}, },
replaceValue: { replaceValue: {
0: '运行', 0: '运行',
1: '检修', 1: '检修',
2: '停运', 2: '停运',
3: '调试', 3: '调试',
4: '退运', 4: '退运',
null: '/' null: '/'
} }
}, },
{ {
title: '目标状态', title: '目标状态',
field: 'devStatus', field: 'devStatus',
minWidth: 130, minWidth: 130,
render: 'tag', render: 'tag',
custom: { custom: {
0: 'success', 0: 'success',
1: 'warning', 1: 'warning',
2: 'danger', 2: 'danger',
3: 'warning', 3: 'warning',
4: 'info', 4: 'info',
null: 'primary' null: 'primary'
}, },
replaceValue: { replaceValue: {
0: '运行', 0: '运行',
1: '检修', 1: '检修',
2: '停运', 2: '停运',
3: '调试', 3: '调试',
4: '退运', 4: '退运',
null: '/' null: '/'
} }
}, },
{ {
field: 'status', field: 'status',
title: '流程状态', title: '流程状态',
minWidth: 100, minWidth: 100,
render: 'tag', render: 'tag',
custom: { custom: {
0: 'warning', 0: 'warning',
1: 'primary', 1: 'primary',
2: 'success', 2: 'success',
3: 'danger', 3: 'danger',
4: 'warning' 4: 'warning'
}, },
replaceValue: { replaceValue: {
0: '待提交审批', 0: '待提交审批',
1: '审批中', 1: '审批中',
2: '审批通过', 2: '审批通过',
3: '审批不通过', 3: '审批不通过',
4: '已取消' 4: '已取消'
} }
}, },
{ field: 'createTime', title: '开始时间', minWidth: 170 }, { field: 'createTime', title: '开始时间', minWidth: 170 },
{ {
field: 'createBy', field: 'createBy',
title: '填报人', title: '填报人',
minWidth: 80, minWidth: 80,
formatter: (row: any) => { formatter: (row: any) => {
return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name
} }
}, },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
minWidth: '150', minWidth: '150',
fixed: 'right', fixed: 'right',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
{ {
name: 'productSetting', name: 'productSetting',
title: '流程详情', title: '流程详情',
type: 'primary', type: 'primary',
icon: 'el-icon-EditPen', icon: 'el-icon-EditPen',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return !row.processInstanceId return !row.processInstanceId
}, },
click: row => { click: row => {
flag.value = true flag.value = true
handleAudit(row.processInstanceId, row.historyInstanceId) handleAudit(row.processInstanceId, row.historyInstanceId)
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '编辑', title: '编辑',
type: 'primary', type: 'primary',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
showDisabled: row => { showDisabled: row => {
return row.createBy != adminInfo.$state.id || !(row.status == 0) return row.createBy != adminInfo.$state.id || !(row.status == 0)
}, },
disabled: row => { disabled: row => {
return !(row.status == 0) return !(row.status == 0)
}, },
click: row => { click: row => {
deviceQuitPopup.value.open('编辑', row) deviceQuitPopup.value.open('编辑', row)
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '重新发起', title: '重新发起',
type: 'warning', type: 'warning',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.createBy != adminInfo.$state.id || !(row.status == 3 || row.status == 4) return row.createBy != adminInfo.$state.id || !(row.status == 3 || row.status == 4)
}, },
click: row => { click: row => {
deviceQuitPopup.value.open('重新发起', row) deviceQuitPopup.value.open('重新发起', row)
} }
}, },
{ {
name: 'cancel', name: 'cancel',
title: '取消', title: '取消',
type: 'danger', type: 'danger',
icon: 'el-icon-Open', icon: 'el-icon-Open',
render: 'basicButton', render: 'basicButton',
disabled: row => { disabled: row => {
return row.createBy != adminInfo.$state.id || row.status != 1 return row.createBy != adminInfo.$state.id || row.status != 1
}, },
click: row => { click: row => {
cancelLeave(row) cancelLeave(row)
} }
} }
] ]
} }
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
// for (let key in tableStore.table.params) { // for (let key in tableStore.table.params) {
// if (tableStore.table.params[key] === '') { // if (tableStore.table.params[key] === '') {
// delete tableStore.table.params[key] // delete tableStore.table.params[key]
// } // }
// } // }
tableStore.table.params.deviceType = 1 tableStore.table.params.deviceType = 1
} }
}) })
tableStore.table.params.status = '' tableStore.table.params.status = ''
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
provide('tableStore', tableStore) provide('tableStore', tableStore)
//新增退运终端信息 //新增退运终端信息
const add = () => { const add = () => {
deviceQuitPopup.value.open('新增终端状态变更') deviceQuitPopup.value.open('新增终端状态变更')
} }
// 禁止点击 // 禁止点击
const checkboxConfig = reactive({ const checkboxConfig = reactive({
checkMethod: ({ row }) => { checkMethod: ({ row }) => {
return adminInfo.roleCode.includes('delete_info') return adminInfo.roleCode.includes('delete_info')
? true ? true
: row.createBy == adminInfo.$state.id && row.status == 0 : row.createBy == adminInfo.$state.id && row.status == 0
} }
}) })
const deleteEven = () => { const deleteEven = () => {
if (tableStore.table.selection.length == 0) { if (tableStore.table.selection.length == 0) {
ElMessage({ ElMessage({
type: 'warning', type: 'warning',
message: '请选择要删除的数据' message: '请选择要删除的数据'
}) })
} else { } else {
ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', { ElMessageBox.confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}) })
.then(() => { .then(() => {
deleteQuitRunningDevice(tableStore.table.selection.map(item => item.id)).then(res => { deleteQuitRunningDevice(tableStore.table.selection.map(item => item.id)).then(res => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: '删除成功!' message: '删除成功!'
}) })
tableStore.index() tableStore.index()
}) })
}) })
} }
} }
/** 流程实例详情 */ /** 流程实例详情 */
const handleAudit = (instanceId: string, historyInstanceId: string) => { const handleAudit = (instanceId: string, historyInstanceId: string) => {
push({ push({
name: 'BpmProcessInstanceDetail', name: 'BpmProcessInstanceDetail',
state: { state: {
id: instanceId, id: instanceId,
historyInstanceId historyInstanceId
} }
}) })
} }
/**取消流程操作*/ /**取消流程操作*/
const cancelLeave = async (row: any) => { const cancelLeave = async (row: any) => {
// 二次确认 // 二次确认
const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', { const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
inputType: 'textarea', inputType: 'textarea',
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格 inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
inputErrorMessage: '取消原因不能为空' inputErrorMessage: '取消原因不能为空'
}) })
// 发起取消 // 发起取消
let data = { let data = {
id: row.id, id: row.id,
processInstanceId: row.processInstanceId, processInstanceId: row.processInstanceId,
reason: value reason: value
} }
await cancelQuitRunningDevice(data) await cancelQuitRunningDevice(data)
ElMessage.success('取消成功') ElMessage.success('取消成功')
// 加载数据 // 加载数据
tableStore.index() tableStore.index()
} }
onMounted(() => { onMounted(() => {
// 加载数据 // 加载数据
tableStore.index() tableStore.index()
}) })
watch( watch(
() => currentRoute.value.path, () => currentRoute.value.path,
() => { () => {
if (flag.value && options.history.state.forward?.split('/')[1] == 'bpm') { if (flag.value && options.history.state.forward?.split('/')[1] == 'bpm') {
tableStore.index() tableStore.index()
flag.value = false flag.value = false
} }
}, },
{ {
deep: true deep: true
} }
) )
const props = defineProps({ id: { type: String, default: 'null' } }) const props = defineProps({ id: { type: String, default: 'null' } })
watch(() => props.id, async (newValue, oldValue) => { watch(() => props.id, async (newValue, oldValue) => {
if (newValue === 'null') return // 直接返回,避免后续逻辑执行 if (newValue === 'null') return // 直接返回,避免后续逻辑执行
const fullId = newValue.split('@')[0] const fullId = newValue.split('@')[0]
let nowTime = Date.now() let nowTime = Date.now()
const routeTime = Number(newValue.split('@')[1]) const routeTime = Number(newValue.split('@')[1])
if (isNaN(routeTime) || nowTime - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return // 路由时间超过500ms则不执行 if (isNaN(routeTime) || nowTime - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return // 路由时间超过500ms则不执行
await getRunningDeviceById(fullId).then(res => { await getRunningDeviceById(fullId).then(res => {
if (res && res.code == 'A0000') { if (res && res.code == 'A0000') {
deviceQuitPopup.value.open('重新发起', res.data) deviceQuitPopup.value.open('重新发起', res.data)
} }
}) })
}, { immediate: true }) }, { immediate: true })
</script> </script>

View File

@@ -9,7 +9,7 @@
<el-radio-button :label="1">离线</el-radio-button> <el-radio-button :label="1">离线</el-radio-button>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="筛选"> <el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" /> <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />
</el-form-item> </el-form-item>
<el-form-item label="触发类型:"> <el-form-item label="触发类型:">

View File

@@ -1,218 +1,218 @@
<template> <template>
<div class="default-main"> <div class="default-main">
<div v-show="view"> <div v-show="view">
<TableHeader datePicker :showReset="false" showExport ref="TableHeaderRef"> <TableHeader datePicker :showReset="false" showExport ref="TableHeaderRef">
<template #select> <template #select>
<!-- <el-form-item label="筛选">--> <!-- <el-form-item label="筛选数据">-->
<!-- <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />--> <!-- <el-input v-model="tableStore.table.params.searchValue" clearable placeholder="输入关键字筛选" />-->
<!-- </el-form-item>--> <!-- </el-form-item>-->
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Tickets" type="primary" @click="analysis1">分析记录管理</el-button> <el-button icon="el-icon-Tickets" type="primary" @click="analysis1">分析记录管理</el-button>
<el-button icon="el-icon-SuccessFilled" type="primary" @click="firing">启动关联分析</el-button> <el-button icon="el-icon-SuccessFilled" type="primary" @click="firing">启动关联分析</el-button>
</template> </template>
</TableHeader> </TableHeader>
<Table ref="tableRef" /> <Table ref="tableRef" />
<!-- 分析记录管理 --> <!-- 分析记录管理 -->
<el-dialog draggable v-model="dialogAnalysis" title="分析记录管理" width="60%"> <el-dialog draggable v-model="dialogAnalysis" title="分析记录管理" width="60%">
<vxe-table height="500" auto-resize :data="AnalysisData" v-bind="defaultAttribute"> <vxe-table height="500" auto-resize :data="AnalysisData" v-bind="defaultAttribute">
<vxe-column field="timeId" title="策略名称"></vxe-column> <vxe-column field="timeId" title="策略名称"></vxe-column>
<vxe-column field="timeId" title="操作时间"></vxe-column> <vxe-column field="timeId" title="操作时间"></vxe-column>
<vxe-column field="createName" title="操作人"></vxe-column> <vxe-column field="createName" title="操作人"></vxe-column>
<vxe-column title="操作" width="100"> <vxe-column title="操作" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-popconfirm title="是否确认删除策略!" @confirm="details(row)"> <el-popconfirm title="是否确认删除策略!" @confirm="details(row)">
<template #reference> <template #reference>
<el-button type="danger" link>删除</el-button> <el-button type="danger" link>删除</el-button>
</template> </template>
</el-popconfirm> </el-popconfirm>
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
</el-dialog> </el-dialog>
</div> </div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view"> <div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
<waveForm ref="waveFormRef" senior :boxoList="boxoList" :wp="wp" @backbxlb="backbxlb" /> <waveForm ref="waveFormRef" senior :boxoList="boxoList" :wp="wp" @backbxlb="backbxlb" />
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue' import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue' import Table from '@/components/table/index.vue'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { queryRelevantLogPage, delRelevantLog, processEvents, analysis } from '@/api/advance-boot/analyse' import { queryRelevantLogPage, delRelevantLog, processEvents, analysis } from '@/api/advance-boot/analyse'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import waveForm from '@/components/echarts/waveForm.vue' import waveForm from '@/components/echarts/waveForm.vue'
import { getMonitorEventAnalyseWave } from '@/api/event-boot/transient' import { getMonitorEventAnalyseWave } from '@/api/event-boot/transient'
defineOptions({ defineOptions({
name: 'Advancedanalysis/eventcorrelation' name: 'Advancedanalysis/eventcorrelation'
}) })
const dialogAnalysis = ref(false) const dialogAnalysis = ref(false)
const AnalysisData = ref([]) const AnalysisData = ref([])
const pageHeight = mainHeight(20) const pageHeight = mainHeight(20)
const bxecharts = mainHeight(95).height as any const bxecharts = mainHeight(95).height as any
const loading = ref(false) const loading = ref(false)
const view = ref(true) const view = ref(true)
const view2 = ref(false) const view2 = ref(false)
const TableHeaderRef = ref() const TableHeaderRef = ref()
const waveFormRef = ref() const waveFormRef = ref()
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '/advance-boot/process/querySagEventsPage', url: '/advance-boot/process/querySagEventsPage',
method: 'POST', method: 'POST',
column: [ column: [
{ {
field: 'index', field: 'index',
title: '序号', title: '序号',
width: '80', width: '80',
formatter: (row: any) => { formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
} }
}, },
{ field: 'startTime', title: '发生时间' }, { field: 'startTime', title: '发生时间' },
{ field: 'duration', title: '持续时间(s)' }, { field: 'duration', title: '持续时间(s)' },
{ {
field: 'featureAmplitude', field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)' title: '暂降(骤升)幅值(%)'
}, },
{ field: 'gdName', title: '供电公司' }, { field: 'gdName', title: '供电公司' },
{ field: 'subName', title: '变电站' }, { field: 'subName', title: '变电站' },
{ field: 'lineName', title: '监测点' }, { field: 'lineName', title: '监测点' },
{ {
field: 'dealFlag', field: 'dealFlag',
title: '暂降特征幅值计算', title: '暂降特征幅值计算',
render: 'tag', render: 'tag',
custom: { custom: {
0: 'warning', 0: 'warning',
1: 'success', 1: 'success',
2: 'success', 2: 'success',
3: 'warning' 3: 'warning'
}, },
replaceValue: { replaceValue: {
0: '未处理', 0: '未处理',
1: '已处理', 1: '已处理',
2: '已处理,无结果', 2: '已处理,无结果',
3: '计算失败' 3: '计算失败'
} }
}, },
{ {
field: 'fileFlag', field: 'fileFlag',
title: '录波文件', title: '录波文件',
render: 'tag', render: 'tag',
custom: { custom: {
0: 'warning', 0: 'warning',
1: 'success' 1: 'success'
}, },
replaceValue: { replaceValue: {
0: '不存在', 0: '不存在',
1: '存在' 1: '存在'
} }
}, },
{ {
title: '操作', title: '操作',
width: '120', width: '120',
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
{ {
name: 'edit', name: 'edit',
title: '波形分析', title: '波形分析',
type: 'primary', type: 'primary',
disabled: row => { disabled: row => {
return row.fileFlag == 0 return row.fileFlag == 0
}, },
icon: 'el-icon-Plus', icon: 'el-icon-Plus',
render: 'basicButton', render: 'basicButton',
click: async row => { click: async row => {
view.value = false view.value = false
setTimeout(() => { setTimeout(() => {
waveFormRef.value.open(row) waveFormRef.value.open(row)
},100) },100)
// row.loading = true // row.loading = true
// boxoList.value = row // boxoList.value = row
// await getMonitorEventAnalyseWave({ id: row.eventId, systemType: 0 }) // await getMonitorEventAnalyseWave({ id: row.eventId, systemType: 0 })
// .then(res => { // .then(res => {
// row.loading = false // row.loading = false
// if (res != undefined) { // if (res != undefined) {
// wp.value = res.data // wp.value = res.data
// view.value = false // view.value = false
// view2.value = true // view2.value = true
// } // }
// }) // })
// .catch(() => { // .catch(() => {
// row.loading = false // row.loading = false
// }) // })
} }
}, },
{ {
name: 'edit', name: 'edit',
title: '暂无波形', title: '暂无波形',
type: '', type: '',
disabled: row => { disabled: row => {
return row.fileFlag != 0 return row.fileFlag != 0
}, },
icon: 'el-icon-Plus', icon: 'el-icon-Plus',
render: 'basicButton' render: 'basicButton'
} }
] ]
} }
], ],
loadCallback: () => { } loadCallback: () => { }
}) })
tableStore.table.params.searchValue = '' tableStore.table.params.searchValue = ''
const bxactiveName = ref('ssbx') const bxactiveName = ref('ssbx')
const boxoList = ref({}) const boxoList = ref({})
const wp = ref({}) const wp = ref({})
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
TableHeaderRef.value.setTheDate(1) TableHeaderRef.value.setTheDate(1)
nextTick(() => { nextTick(() => {
// tableStore.index() // tableStore.index()
TableHeaderRef.value.onComSearch() TableHeaderRef.value.onComSearch()
}) })
}) })
//分析记录管理 //分析记录管理
const analysis1 = () => { const analysis1 = () => {
queryRelevantLogPage({}).then((res: any) => { queryRelevantLogPage({}).then((res: any) => {
AnalysisData.value = res.data.records AnalysisData.value = res.data.records
}) })
dialogAnalysis.value = true dialogAnalysis.value = true
} }
// 启动关联分析 // 启动关联分析
const firing = () => { const firing = () => {
processEvents({ processEvents({
startTime: tableStore.table.params.searchBeginTime, startTime: tableStore.table.params.searchBeginTime,
endTime: tableStore.table.params.searchEndTime endTime: tableStore.table.params.searchEndTime
}).then(res => { }).then(res => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: res.message message: res.message
}) })
tableStore.index() tableStore.index()
}) })
} }
// 删除策略 // 删除策略
const details = (row: any) => { const details = (row: any) => {
delRelevantLog({ id: row.id }).then((res: any) => { delRelevantLog({ id: row.id }).then((res: any) => {
ElMessage({ ElMessage({
type: 'success', type: 'success',
message: res.message message: res.message
}) })
queryRelevantLogPage({}).then((res: any) => { queryRelevantLogPage({}).then((res: any) => {
AnalysisData.value = res.data.records AnalysisData.value = res.data.records
}) })
}) })
} }
const backbxlb = () => { const backbxlb = () => {
view.value = true view.value = true
view2.value = false view2.value = false
} }
</script> </script>

View File

@@ -2,7 +2,7 @@
<div> <div>
<div v-show="view"> <div v-show="view">
<!-- 表头 --> <!-- 表头 -->
<TableHeader date-picker showExport> <TableHeader ref="TableHeaderRef" date-picker showExport>
<template v-slot:operation> <template v-slot:operation>
<el-button :icon="Download" type="primary" @click="download">下载波形</el-button> <el-button :icon="Download" type="primary" @click="download">下载波形</el-button>
</template> </template>
@@ -130,11 +130,16 @@ const tableStore = new TableStore({
}, },
loadCallback: () => {} loadCallback: () => {}
}) })
const TableHeaderRef = ref()
provide('tableStore', tableStore) provide('tableStore', tableStore)
tableStore.table.params.searchState = 0 tableStore.table.params.searchState = 0
onMounted(() => { onMounted(() => {
TableHeaderRef.value.setTheDate(1)
// 加载数据 // 加载数据
tableStore.index() nextTick(() => {
// tableStore.index()
TableHeaderRef.value.onComSearch()
})
}) })
const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({ const checkboxConfig = reactive<VxeTablePropTypes.CheckboxConfig<any>>({
checkMethod: ({ row }) => { checkMethod: ({ row }) => {

View File

@@ -30,9 +30,9 @@
<EventStatistics :externalHeight='20'/> <EventStatistics :externalHeight='20'/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="运行情况" name="4" lazy :style="height" v-if="!isReload"> <!-- <el-tab-pane label="运行情况" name="4" lazy :style="height" v-if="!isReload">
<RunningCondition :externalHeight='20'/> <RunningCondition :externalHeight='20'/>
</el-tab-pane> </el-tab-pane> -->
<el-tab-pane label="暂态报告" name="5" lazy v-if="!isReload"> <el-tab-pane label="暂态报告" name="5" lazy v-if="!isReload">
<TransientReport /> <TransientReport />
</el-tab-pane> </el-tab-pane>
@@ -70,7 +70,7 @@ const activeName = ref('3')
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {

View File

@@ -49,7 +49,7 @@ const showTree = ref(false)
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
params.value.deptIndex = adminInfo.$state.deptId params.value.deptIndex = adminInfo.$state.deptId
params.value.searchBeginTime = datePickerRef.value.timeValue[0] params.value.searchBeginTime = datePickerRef.value.timeValue[0]

View File

@@ -17,6 +17,7 @@
</el-form-item> --> </el-form-item> -->
</template> </template>
<template #operation> <template #operation>
<!-- <el-button icon="el-icon-Download" type="primary" @click="preview">预览报告</el-button> -->
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">生成报告</el-button> <el-button icon="el-icon-Download" type="primary" @click="exportEvent">生成报告</el-button>
</template> </template>
</TableHeader> </TableHeader>
@@ -175,7 +176,7 @@ provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
@@ -202,12 +203,41 @@ const exportEvent = () => {
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签 const link = document.createElement('a') // 创建a标签
link.href = url link.href = url
link.download = '监测点报告' // 设置下载的文件名 link.download = monitoringPoint.state.lineName.split('>').at(-1)+'_暂态报告' // 设置下载的文件名
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) document.body.removeChild(link)
}) })
} }
const preview = () => {
if (dotList.value.level != 6) {
return ElMessage({
message: '请选择监测点进行预览!',
type: 'warning'
})
}
let a = ''
formd.value.lineId = monitoringPoint.state.lineId
formd.value.lineName = monitoringPoint.state.lineName.split('>').at(-1)
formd.value.searchBeginTime = TableHeaderRef.value.datePickerRef.timeValue[0]
formd.value.searchEndTime = TableHeaderRef.value.datePickerRef.timeValue[1]
formd.value.flag = TableHeaderRef.value.datePickerRef.interval
ElMessage('生成报告中,请稍等!')
getLineExport(formd.value).then((res: any) => {
let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8'
})
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
link.download = monitoringPoint.state.lineName.split('>').at(-1)+'_暂态报告' // 设置下载的文件名
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link)
})
}
</script> </script>
<style lang="scss"> <style lang="scss">
.splitpanes.default-theme .splitpanes__pane { .splitpanes.default-theme .splitpanes__pane {

View File

@@ -1,297 +1,297 @@
<template> <template>
<div class="default-main" :style="height"> <div class="default-main" :style="height">
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes"> <splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size"> <pane :size="size">
<PointTree <PointTree
:default-expand-all="false" :default-expand-all="false"
:default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []" :default-expanded-keys="monitoringPoint.state.lineId ? [monitoringPoint.state.lineId] : []"
:current-node-key="monitoringPoint.state.lineId" :current-node-key="monitoringPoint.state.lineId"
@node-click="handleNodeClick" @node-click="handleNodeClick"
@init="handleNodeClick" @init="handleNodeClick"
></PointTree> ></PointTree>
</pane> </pane>
<pane style="background: #fff" :style="height"> <pane style="background: #fff" :style="height">
<!-- <div :style="height"></div> --> <!-- <div :style="height"></div> -->
<TableHeader ref="TableHeaderRef" date-picker :show-search="false"> <TableHeader ref="TableHeaderRef" date-picker :show-search="false">
<template v-slot:select> <template v-slot:select>
<el-form-item label=" 模板策略"> <el-form-item label=" 模板策略">
<el-select v-model="value" placeholder="请选择" @change="changeFn" clearable> <el-select v-model="value" placeholder="请选择" @change="changeFn" clearable>
<el-option <el-option
v-for="item in templatePolicy" v-for="item in templatePolicy"
:key="item.id" :key="item.id"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
<template #operation> <template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">生成报告</el-button> <el-button icon="el-icon-Download" type="primary" @click="exportEvent">生成报告</el-button>
</template> </template>
</TableHeader> </TableHeader>
<div class="box" :style="`height: calc(${tableStore.table.height} + 45px)`"> <div class="box" :style="`height: calc(${tableStore.table.height} + 45px)`">
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">监测点详情</div> <div class="divBox">监测点详情</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.xq">监测点详情</el-checkbox> <el-checkbox v-model="formd.xq">监测点详情</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">暂降事件列表</div> <div class="divBox">暂降事件列表</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.lb">表格</el-checkbox> <el-checkbox v-model="formd.lb">表格</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">暂降密度</div> <div class="divBox">暂降密度</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.mdbg">表格</el-checkbox> <el-checkbox v-model="formd.mdbg">表格</el-checkbox>
<el-checkbox v-model="formd.mdtx">图形</el-checkbox> <el-checkbox v-model="formd.mdtx">图形</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">暂降事件点</div> <div class="divBox">暂降事件点</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.sjdITIC">ITIC</el-checkbox> <el-checkbox v-model="formd.sjdITIC">ITIC</el-checkbox>
<el-checkbox v-model="formd.sjdF47">F47</el-checkbox> <el-checkbox v-model="formd.sjdF47">F47</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">概率分布</div> <div class="divBox">概率分布</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.glfbfz">暂降幅值</el-checkbox> <el-checkbox v-model="formd.glfbfz">暂降幅值</el-checkbox>
<el-checkbox v-model="formd.glfbsj">持续时间</el-checkbox> <el-checkbox v-model="formd.glfbsj">持续时间</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">月份统计</div> <div class="divBox">月份统计</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.tjbg">表格</el-checkbox> <el-checkbox v-model="formd.tjbg">表格</el-checkbox>
<el-checkbox v-model="formd.tjtx">图形</el-checkbox> <el-checkbox v-model="formd.tjtx">图形</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">暂降原因</div> <div class="divBox">暂降原因</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.yybg">表格</el-checkbox> <el-checkbox v-model="formd.yybg">表格</el-checkbox>
<el-checkbox v-model="formd.yytx">图形</el-checkbox> <el-checkbox v-model="formd.yytx">图形</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row> <el-row>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<div class="grid-content"> <div class="grid-content">
<div class="divBox">暂降类型</div> <div class="divBox">暂降类型</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12" class="mTop"> <el-col :span="12" class="mTop">
<el-checkbox v-model="formd.lxbg">表格</el-checkbox> <el-checkbox v-model="formd.lxbg">表格</el-checkbox>
<el-checkbox v-model="formd.lxtx">图形</el-checkbox> <el-checkbox v-model="formd.lxtx">图形</el-checkbox>
</el-col> </el-col>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
</div> </div>
</pane> </pane>
</splitpanes> </splitpanes>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, provide } from 'vue' import { onMounted, ref, provide } from 'vue'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes' import { Splitpanes, Pane } from 'splitpanes'
import TableStore from '@/utils/tableStore' import TableStore from '@/utils/tableStore'
import PointTree from '@/components/tree/pqs/pointTree.vue' import PointTree from '@/components/tree/pqs/pointTree.vue'
import TableHeader from '@/components/table/header/index.vue' import TableHeader from '@/components/table/header/index.vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { getLineExport, getList, selectReleation } from '@/api/event-boot/report' import { getLineExport, getList, selectReleation } from '@/api/event-boot/report'
import { useMonitoringPoint } from '@/stores/monitoringPoint' import { useMonitoringPoint } from '@/stores/monitoringPoint'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
defineOptions({ defineOptions({
name: 'TransientReport/monitoringpointReport' name: 'TransientReport/monitoringpointReport'
}) })
const monitoringPoint = useMonitoringPoint() const monitoringPoint = useMonitoringPoint()
const height = mainHeight(20) const height = mainHeight(20)
const size = ref(0) const size = ref(0)
const value = ref('') const value = ref('')
const TableHeaderRef = ref() const TableHeaderRef = ref()
const dotList: any = ref({ const dotList: any = ref({
name: monitoringPoint.state.lineName.split('>')[3], name: monitoringPoint.state.lineName.split('>')[3],
id: monitoringPoint.state.lineId, id: monitoringPoint.state.lineId,
level: 6 level: 6
}) })
const formd: any = ref({ const formd: any = ref({
xq: false, xq: false,
lb: false, lb: false,
mdbg: false, mdbg: false,
mdtx: false, mdtx: false,
sjdITIC: false, sjdITIC: false,
sjdF47: false, sjdF47: false,
glfbfz: false, glfbfz: false,
glfbsj: false, glfbsj: false,
tjbg: false, tjbg: false,
tjtx: false, tjtx: false,
yybg: false, yybg: false,
yytx: false, yytx: false,
lxbg: false, lxbg: false,
lxtx: false, lxtx: false,
type: 0 type: 0
}) })
const templatePolicy: any = ref([]) const templatePolicy: any = ref([])
const tableStore = new TableStore({ const tableStore = new TableStore({
url: '', url: '',
method: 'post', method: 'post',
column: [] column: []
}) })
provide('tableStore', tableStore) provide('tableStore', tableStore)
onMounted(() => { onMounted(() => {
const dom = document.getElementById('navigation-splitpanes') const dom = document.getElementById('navigation-splitpanes')
if (dom) { if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100) size.value = Math.round((180 / dom.offsetHeight) * 120)
} }
}) })
getList({ getList({
pageNum: 1, pageNum: 1,
pageSize: 100, pageSize: 100,
type: 0 type: 0
}).then(res => { }).then(res => {
templatePolicy.value = res.data.records templatePolicy.value = res.data.records
// 默认选中第一个 // 默认选中第一个
if (res.data.records && res.data.records.length > 0) { if (res.data.records && res.data.records.length > 0) {
value.value = res.data.records[0].id value.value = res.data.records[0].id
// 触发 change 事件,加载对应的配置 // 触发 change 事件,加载对应的配置
changeFn(res.data.records[0].id) changeFn(res.data.records[0].id)
} }
}) })
const handleNodeClick = (data: any, node: any) => { const handleNodeClick = (data: any, node: any) => {
dotList.value = data dotList.value = data
} }
const changeFn = (val: any) => { const changeFn = (val: any) => {
formd.value = { formd.value = {
xq: false, xq: false,
lb: false, lb: false,
mdbg: false, mdbg: false,
mdtx: false, mdtx: false,
sjdITIC: false, sjdITIC: false,
sjdF47: false, sjdF47: false,
glfbfz: false, glfbfz: false,
glfbsj: false, glfbsj: false,
tjbg: false, tjbg: false,
tjtx: false, tjtx: false,
yybg: false, yybg: false,
yytx: false, yytx: false,
lxbg: false, lxbg: false,
lxtx: false, lxtx: false,
type: 0 type: 0
} }
let data = { let data = {
id: val id: val
} }
selectReleation(data).then(res => { selectReleation(data).then(res => {
res.data.forEach((item: any) => { res.data.forEach((item: any) => {
for (let k in formd.value) { for (let k in formd.value) {
if (item.name == k) { if (item.name == k) {
formd.value[k] = true formd.value[k] = true
return return
} }
} }
}) })
}) })
} }
const exportEvent = () => { const exportEvent = () => {
if (dotList.value.level != 6) { if (dotList.value.level != 6) {
return ElMessage({ return ElMessage({
message: '请选择监测点进行报告生成!', message: '请选择监测点进行报告生成!',
type: 'warning' type: 'warning'
}) })
} }
let a = '' let a = ''
formd.value.lineId = dotList.value.id formd.value.lineId = dotList.value.id
formd.value.lineName = dotList.value.name formd.value.lineName = dotList.value.name
formd.value.searchBeginTime = TableHeaderRef.value.datePickerRef.timeValue[0] formd.value.searchBeginTime = TableHeaderRef.value.datePickerRef.timeValue[0]
formd.value.searchEndTime = TableHeaderRef.value.datePickerRef.timeValue[1] formd.value.searchEndTime = TableHeaderRef.value.datePickerRef.timeValue[1]
formd.value.flag = TableHeaderRef.value.datePickerRef.interval formd.value.flag = TableHeaderRef.value.datePickerRef.interval
ElMessage('生成报告中,请稍等!') ElMessage('生成报告中,请稍等!')
getLineExport(formd.value).then((res: any) => { getLineExport(formd.value).then((res: any) => {
let blob = new Blob([res], { let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8' type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8'
}) })
// createObjectURL(blob); //创建下载的链接 // createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签 const link = document.createElement('a') // 创建a标签
link.href = url link.href = url
link.download = '监测点报告' // 设置下载的文件名 link.download = '监测点报告' // 设置下载的文件名
document.body.appendChild(link) document.body.appendChild(link)
link.click() //执行下载 link.click() //执行下载
document.body.removeChild(link) document.body.removeChild(link)
}) })
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.splitpanes.default-theme .splitpanes__pane { .splitpanes.default-theme .splitpanes__pane {
background: #eaeef1; background: #eaeef1;
} }
.grid-content { .grid-content {
text-align: center; text-align: center;
} }
.divBox { .divBox {
width: 250px; width: 250px;
height: 31px; height: 31px;
margin: auto; margin: auto;
line-height: 32px; line-height: 32px;
border: 1px solid #c9c9c9; border: 1px solid #c9c9c9;
&:hover { &:hover {
border: 1px solid #002255; border: 1px solid #002255;
} }
} }
.box { .box {
padding: 10px; padding: 10px;
// margin-top: 10px; // margin-top: 10px;
overflow-y: auto; overflow-y: auto;
font-size: 15px; font-size: 15px;
} }
.el-divider--horizontal { .el-divider--horizontal {
margin: 10px 0; margin: 10px 0;
} }
.mTop { .mTop {
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
} }
</style> </style>