13 Commits

Author SHA1 Message Date
6a84d28101 添加辽宁周期检测功能 2026-07-09 11:41:01 +08:00
guanj
1a69be62a0 修改监测点信息 2026-07-09 11:08:56 +08:00
guanj
02caca969e 修改用户性质 2026-07-09 10:33:22 +08:00
guanj
3f1af5e4cc 监测点信息添加终端型号 2026-07-08 16:08:02 +08:00
guanj
88e9812d5f 联调周期监测 2026-07-08 14:37:19 +08:00
guanj
83a827ba5b 修改文件上传问题 2026-07-08 11:14:32 +08:00
40b1092718 添加周期 2026-07-08 09:21:59 +08:00
guanj
83a1128884 用户管理添加监测报告,评估报告 2026-07-07 13:52:53 +08:00
1a44a2f9e0 添加周期 2026-07-07 10:18:22 +08:00
guanj
5044c88946 优化全景展示页面 2026-07-07 10:15:33 +08:00
guanj
51a862ed00 修改进程显示 2026-07-06 10:58:02 +08:00
guanj
1ca8e536dd 修改限值显示问题 2026-07-06 10:41:33 +08:00
guanj
2445cfbff3 修改辽宁全景展示问题 2026-07-06 10:12:51 +08:00
37 changed files with 3140 additions and 2243 deletions

View File

@@ -1,7 +1,7 @@
import request from '@/utils/request'
// 获取区域中断终端
export function getAreaOffDev(data) {
export function getAreaOffDev(data:any) {
return request({
url: '/device-boot/device/getAreaOffDev',
method: 'post',
@@ -9,10 +9,28 @@ export function getAreaOffDev(data) {
})
}
// 获取区域中断终端
export function getYwZtSubstation(data) {
export function getYwZtSubstation(data:any) {
return request({
url: '/device-boot/ywZt/getYwZtSubstation',
method: 'GET',
params: data
})
}
//终端周期检测
export function terminalCheckPage(data:any) {
return request({
url: '/device-boot/alarm/terminalCheckPage',
method: 'post',
data
})
}
export function userCheckUpload(data:any) {
return request({
url: '/device-boot/userReport/userCheckUpload',
method: 'post',
data
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,8 @@ import { calcShuYAxisRange, formatAxisLabel } from '@/utils/chartAxisHelper'
import url from '@/assets/img/point.png'
import { buildWaveCacheKey, getWaveCache, setWaveCache } from '@/utils/waveCache'
import { getShuWorker, buildWorkerPayload } from '@/utils/waveWorkerPool'
import { compactShuWaveResult } from '@/utils/waveDisplayHelper'
import { getWaveRawList } from '@/utils/waveRawStore'
let waveRequestId = 0
const pendingCacheKeys = new Map<number, string>()
@@ -75,7 +77,6 @@ const eventValue = ref('')
const persistTime = ref('')
const lineName = ref('')
const subName = ref('')
const waveDatas = ref<WaveData[]>([])
const ptpass = ref('')
const waveHeight = ref<number>()
const rmsHeight = ref<number>()
@@ -156,12 +157,13 @@ watch(
)
const applyWorkerResult = (data: any) => {
titles.value = data.titles
iphasic.value = data.iphasic
time.value = data.time
type.value = data.type
severity.value = data.severity
initWave(data.waveDatas, data.time, data.type, data.severity, isOpen.value)
const compacted = compactShuWaveResult(data, props.value)
titles.value = compacted.titles
iphasic.value = compacted.iphasic
time.value = compacted.time
type.value = compacted.type
severity.value = compacted.severity
initWave(compacted.waveDatas, compacted.time, compacted.type, compacted.severity, isOpen.value)
loading.value = false
}
@@ -179,7 +181,7 @@ onMounted(() => {
}
const cacheKey = pendingCacheKeys.get(data.requestId)
if (cacheKey) {
setWaveCache(cacheKey, data)
setWaveCache(cacheKey, compactShuWaveResult(data, props.value))
pendingCacheKeys.delete(data.requestId)
}
applyWorkerResult(data)
@@ -240,7 +242,10 @@ const waveData = (instantF: any, instantS: any, shunshiF: any, shunshiS: any, ti
// 在组件中修改initWaves函数
const initWaves = () => {
if (!props.wp?.listWaveData?.length) {
const hasData =
props.wp?.listWaveData?.length ||
getWaveRawList('shu', props.wp?.waveStoreKey)?.length
if (!hasData) {
initWave(null, null, null, null, null)
loading.value = false
return
@@ -480,8 +485,8 @@ const initWave = (
type: 'value',
name: '时间\n(ms)',
boundaryGap: false,
min: props.wp?.listWaveData[0][0] || 0,
max: props.wp?.listWaveData[props.wp?.listWaveData.length - 1][0] + 1 || 1,
min: props.wp?.waveTimeRange?.min ?? props.wp?.listWaveData?.[0]?.[0] ?? 0,
max: props.wp?.waveTimeRange?.max ?? ((props.wp?.listWaveData?.[props.wp?.listWaveData?.length - 1]?.[0] ?? 0) + 1),
title: {
text: 'ms',
textStyle: {
@@ -789,8 +794,8 @@ const drawPics = (
type: 'value',
name: '时间\n(ms)',
boundaryGap: false,
min: props.wp.listWaveData[0][0],
max: props.wp.listWaveData[props.wp.listWaveData.length - 1][0] + 1,
min: props.wp?.waveTimeRange?.min ?? props.wp?.listWaveData?.[0]?.[0] ?? 0,
max: props.wp?.waveTimeRange?.max ?? ((props.wp?.listWaveData?.[props.wp?.listWaveData?.length - 1]?.[0] ?? 0) + 1),
title: {
text: 'ms',
textStyle: {
@@ -944,7 +949,6 @@ const drawPics = (
}
const backbxlb = () => {
waveDatas.value = []
const charts = [
myChartess.value,
myChartess1.value,
@@ -996,4 +1000,6 @@ const getMinOpen = (temp: number, tempA: number, tempB: number): number => {
temp = temp < tempB ? temp : tempB
return temp
}
defineExpose({ backbxlb })
</script>

View File

@@ -55,10 +55,12 @@
import shushiboxi from '@/components/echarts/shushiboxi.vue'
import rmsboxi from '@/components/echarts/rmsboxi.vue'
import analytics from '@/components/echarts/analytics.vue'
import { ref, reactive } from 'vue'
import { ref, shallowRef } from 'vue'
import { analysis } from '@/api/advance-boot/analyse'
import { mainHeight } from '@/utils/layout'
import { getMonitorEventAnalyseWave, downloadWaveFile } from '@/api/event-boot/transient'
import { buildWaveStoreKey, registerWaveRaw, buildSlimWp, releaseWaveRaw } from '@/utils/waveRawStore'
import { clearWaveCache } from '@/utils/waveCache'
const emit = defineEmits(['backbxlb'])
interface Props {
// boxoList: any
@@ -88,7 +90,7 @@ const shushiboxiRef = ref()
const bxecharts = ref(mainHeight(145).height as any)
const view2 = ref(true)
const boxoList: any = ref(null)
const wp = ref(null)
const wp = shallowRef<any>(null)
const showBoxi = ref(true)
const view3 = ref(false)
const view4 = ref(false)
@@ -102,7 +104,9 @@ const open = async (row: any) => {
if (res != undefined) {
boxoList.value = row
boxoList.value.pt = res.data.pt
wp.value = res.data
const storeKey = buildWaveStoreKey(row)
registerWaveRaw(storeKey, res.data)
wp.value = buildSlimWp(res.data, storeKey)
loading.value = false
view4.value = true
}
@@ -125,6 +129,9 @@ const bxhandleClick = (tab: any) => {
// console.log(tab, event);
}
const backbxlb = () => {
const storeKey = wp.value?.waveStoreKey
releaseWaveRaw(storeKey, 'all')
clearWaveCache()
boxoList.value = null
wp.value = null
@@ -154,8 +161,8 @@ const AdvancedAnalytics = () => {
view2.value = false
}
const changeView = () => {
if (shushiboxiRef.value) shushiboxiRef.value.backbxlb()
if (rmsboxiRef.value) rmsboxiRef.value.backbxlb()
shushiboxiRef.value?.backbxlb?.()
rmsboxiRef.value?.backbxlb?.()
showBoxi.value = false
setTimeout(() => {
showBoxi.value = true

View File

@@ -37,10 +37,10 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
nextFlag: false,
theCurrentTime: false,
isStatisticData: 1
isStatisticData: 0
})
const isMinuteData = computed(() => Number(props.isStatisticData) === 0)
const isMinuteData = computed(() => Number(props.isStatisticData) === 1)
const pickerType = computed(() => (isMinuteData.value ? 'datetimerange' : 'daterange'))
const pickerValueFormat = computed(() => (isMinuteData.value ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'))

View File

@@ -4,7 +4,7 @@
<el-form style="flex: 1; height: 32px; display: flex; flex-wrap: wrap" ref="headerForm" @submit.prevent=""
@keyup.enter="onComSearch" label-position="left" :inline="true">
<el-form-item v-if="datePicker" style="grid-column: span 2; "
:style="{ maxWidth: isStatisticData == 0 ? '750px' : '610px' }">
:style="{ maxWidth: isStatisticData == 1 ? '750px' : '610px' }">
<template #label>
<el-checkbox v-if="showTimeAll" v-model="timeAll" label="统计时间" />
<span v-else>{{ dateLabel }}</span>
@@ -73,7 +73,7 @@ interface Props {
showExport?: boolean //导出控制
showTimeAll?: boolean //控制时间是否显示
dateLabel?: string //设置时间名称
isStatisticData?: number | string // 0分钟数据 1统计数据
isStatisticData?: number | string // 0统计数据 1分钟数据
}
const props = withDefaults(defineProps<Props>(), {
@@ -86,7 +86,7 @@ const props = withDefaults(defineProps<Props>(), {
showExport: false,
showTimeAll: false,
dateLabel: '统计日期',
isStatisticData: 1
isStatisticData: 0
})
// 动态计算table高度
const resizeObserver = new ResizeObserver(entries => {

View File

@@ -10,7 +10,7 @@
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
>
<!-- @sort-change="handleSortChange" -->
<!-- Column 组件内部是 el-table-column -->

View File

@@ -3,167 +3,177 @@
<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="项目工程">
<el-descriptions-item label="项目工程">
{{ details.areaName }}
</el-descriptions-item>
<el-descriptions-item label="项目单位">
<el-descriptions-item label="项目单位">
{{ details.gdName }}
</el-descriptions-item>
<el-descriptions-item label="所属变电站">
<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="监测点名称">
<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="监测点对象名称">
<el-descriptions-item label="监测点对象名称">
{{ details.objName }}
</el-descriptions-item>
<el-descriptions-item label="接线方式">
<el-descriptions-item label="监测点序号">
{{ details.id }}
</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="终端型号">
{{ typeArr.find(item => item.id == details.devType)?.name }}
</el-descriptions-item>
<el-descriptions-item label="电压等级">
{{ details.scale }}
</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ details.ip }}
</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.ptType }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
<el-descriptions-item label="统计间隔(分钟)">
{{ details.timeInterval }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ details.pt }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
<el-descriptions-item label="CT变比">
{{ details.ct }}
</el-descriptions-item>
<el-descriptions-item label="基准容量(MVA)">
<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)">
<el-descriptions-item label="供电设备容量(MVA)">
{{ details.devCapacity }}
</el-descriptions-item>
<el-descriptions-item label="用户协议容量(MVA)">
<el-descriptions-item label="最小短路容量(MW)">
{{ details.shortCapacity }}
</el-descriptions-item>
<el-descriptions-item label="用户协议容量(MW)">
{{ 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="电压偏差上限值(%)">
<el-descriptions :column="3" border label-width="250px">
<el-descriptions-item label="电压偏差上限值(%)">
{{ limitValue.voltageDev }}
</el-descriptions-item>
<el-descriptions-item label="电压偏差下限值(%)">
<el-descriptions-item label="电压偏差下限值(%)">
{{ limitValue.uvoltageDev }}
</el-descriptions-item>
<el-descriptions-item label="频率偏差限值(Hz)">
<el-descriptions-item label="频率偏差限值(Hz)">
{{ limitValue.freqDev }}
</el-descriptions-item>
<el-descriptions-item label="三相电压不平衡度限值(%)">
<el-descriptions-item label="三相电压不平衡度限值(%)">
{{ limitValue.ubalance }}
</el-descriptions-item>
<el-descriptions-item label="负序电流限值(A)">
<el-descriptions-item label="负序电流限值(A)">
{{ limitValue.ineg }}
</el-descriptions-item>
<el-descriptions-item label="长时闪变限值(%)">
<el-descriptions-item label="长时闪变限值(%)">
{{ limitValue.flicker }}
</el-descriptions-item>
<el-descriptions-item label="电压总畸变率限值(%)">
<el-descriptions-item label="电压总畸变率限值(%)">
{{ limitValue.uaberrance }}
</el-descriptions-item>
<el-descriptions-item label="奇次谐波电压含有率限值(%)">
<el-descriptions-item label="奇次谐波电压含有率限值(%)">
{{ limitValue.oddHarm }}
</el-descriptions-item>
<el-descriptions-item label="偶次谐波电压含有率限值(%)">
<el-descriptions-item label="偶次谐波电压含有率限值(%)">
{{ limitValue.evenHarm }}
</el-descriptions-item>
<el-descriptions-item label="3次谐波电流幅值限值(A)">
<el-descriptions-item label="3次谐波电流幅值限值(A)">
{{ limitValue.iharm3 }}
</el-descriptions-item>
<el-descriptions-item label="4次谐波电流幅值限值(A)">
<el-descriptions-item label="4次谐波电流幅值限值(A)">
{{ limitValue.iharm4 }}
</el-descriptions-item>
<el-descriptions-item label="5次谐波电流幅值限值(A)">
<el-descriptions-item label="5次谐波电流幅值限值(A)">
{{ limitValue.iharm5 }}
</el-descriptions-item>
<el-descriptions-item label="6次谐波电流幅值限值(A)">
<el-descriptions-item label="6次谐波电流幅值限值(A)">
{{ limitValue.iharm6 }}
</el-descriptions-item>
<el-descriptions-item label="7次谐波电流幅值限值(A)">
<el-descriptions-item label="7次谐波电流幅值限值(A)">
{{ limitValue.iharm7 }}
</el-descriptions-item>
<el-descriptions-item label="8次谐波电流幅值限值(A)">
<el-descriptions-item label="8次谐波电流幅值限值(A)">
{{ limitValue.iharm8 }}
</el-descriptions-item>
<el-descriptions-item label="9次谐波电流幅值限值(A)">
<el-descriptions-item label="9次谐波电流幅值限值(A)">
{{ limitValue.iharm9 }}
</el-descriptions-item>
<el-descriptions-item label="10次谐波电流幅值限值(A)">
<el-descriptions-item label="10次谐波电流幅值限值(A)">
{{ limitValue.iharm10 }}
</el-descriptions-item>
<el-descriptions-item label="11次谐波电流幅值限值(A)">
<el-descriptions-item label="11次谐波电流幅值限值(A)">
{{ limitValue.iharm11 }}
</el-descriptions-item>
<el-descriptions-item label="12次谐波电流幅值限值(A)">
<el-descriptions-item label="12次谐波电流幅值限值(A)">
{{ limitValue.iharm12 }}
</el-descriptions-item>
<el-descriptions-item label="13次谐波电流幅值限值(A)">
<el-descriptions-item label="13次谐波电流幅值限值(A)">
{{ limitValue.iharm13 }}
</el-descriptions-item>
<el-descriptions-item label="14次谐波电流幅值限值(A)">
<el-descriptions-item label="14次谐波电流幅值限值(A)">
{{ limitValue.iharm14 }}
</el-descriptions-item>
<el-descriptions-item label="15次谐波电流幅值限值(A)">
<el-descriptions-item label="15次谐波电流幅值限值(A)">
{{ limitValue.iharm15 }}
</el-descriptions-item>
<el-descriptions-item label="16次谐波电流幅值限值(A)">
<el-descriptions-item label="16次谐波电流幅值限值(A)">
{{ limitValue.iharm16 }}
</el-descriptions-item>
<el-descriptions-item label="17次谐波电流幅值限值(A)">
<el-descriptions-item label="17次谐波电流幅值限值(A)">
{{ limitValue.iharm17 }}
</el-descriptions-item>
<el-descriptions-item label="18次谐波电流幅值限值(A)">
<el-descriptions-item label="18次谐波电流幅值限值(A)">
{{ limitValue.iharm18 }}
</el-descriptions-item>
<el-descriptions-item label="19次谐波电流幅值限值(A)">
<el-descriptions-item label="19次谐波电流幅值限值(A)">
{{ limitValue.iharm19 }}
</el-descriptions-item>
<el-descriptions-item label="20次谐波电流幅值限值(A)">
<el-descriptions-item label="20次谐波电流幅值限值(A)">
{{ limitValue.iharm20 }}
</el-descriptions-item>
<el-descriptions-item label="21次谐波电流幅值限值(A)">
<el-descriptions-item label="21次谐波电流幅值限值(A)">
{{ limitValue.iharm21 }}
</el-descriptions-item>
<el-descriptions-item label="22次谐波电流幅值限值(A)">
<el-descriptions-item label="22次谐波电流幅值限值(A)">
{{ limitValue.iharm22 }}
</el-descriptions-item>
<el-descriptions-item label="23次谐波电流幅值限值(A)">
<el-descriptions-item label="23次谐波电流幅值限值(A)">
{{ limitValue.iharm23 }}
</el-descriptions-item>
<el-descriptions-item label="24次谐波电流幅值限值(A)">
<el-descriptions-item label="24次谐波电流幅值限值(A)">
{{ limitValue.iharm24 }}
</el-descriptions-item>
<el-descriptions-item label="25次谐波电流幅值限值(A)">
<el-descriptions-item label="25次谐波电流幅值限值(A)">
{{ limitValue.iharm25 }}
</el-descriptions-item>
<el-descriptions-item label="0.5-1.5次间谐波电压含有率限值(%)">
<el-descriptions-item label="0.5-1.5次间谐波电压含有率限值(%)">
{{ limitValue.inUharm }}
</el-descriptions-item>
<el-descriptions-item label="2.5-15.5次谐波电压含有率限值(%)">
<el-descriptions-item label="2.5-15.5次谐波电压含有率限值(%)">
{{ limitValue.inUharm16 }}
</el-descriptions-item>
</el-descriptions>
@@ -174,11 +184,14 @@
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { getLineOverLimitData, getLineDetailData } from '@/api/device-boot/line'
import { useDictData } from '@/stores/dictData'
const dialogVisible = ref(false)
const title = ref('')
const activeName = ref('tab1')
const details: any = ref([])
const dictData = useDictData()
const limitValue: any = ref([])
const typeArr = dictData.getBasicData('Dev_Type')
const open = (data: any) => {
details.value = []
limitValue.value = []
@@ -187,7 +200,7 @@ const open = (data: any) => {
getLineDetailData(data.id).then(res => {
details.value = res.data
res.data.objName ? (title.value = res.data.objName + '_' + title.value) : ''
})
getLineOverLimitData(data.id).then(res => {
limitValue.value = res.data

View File

@@ -1,4 +1,5 @@
import { downloadFile } from '@/api/system-boot/file'
import { ElMessage } from 'element-plus'
const sanitizeUrl = (url: string): string => {
return url.replace(/\[/g, '(').replace(/\]/g, ')')
@@ -7,7 +8,7 @@ const sanitizeUrl = (url: string): string => {
// 下载文件
export const download = (urls: string) => {
//console.log('下载', urls)
ElMessage.info('下载中...')
downloadFile({ filePath: urls })
.then((res: any) => {
// 1. 确定文件MIME类型优化用更简洁的方式
@@ -26,9 +27,9 @@ export const download = (urls: string) => {
}
return mimeMap[ext] || ''
}
const blob = new Blob([res], { type: getFileType(urls) })
// 2. 提取文件名并保留原生后缀(核心修复点)
const fileName = urls.split('/').at(-1) || '下载文件' // 先提取URL最后一段文件名
@@ -43,8 +44,12 @@ export const download = (urls: string) => {
// 4. 清理资源(优化)
link.remove()
window.URL.revokeObjectURL(url) // 释放blob URL
setTimeout(() => {
ElMessage.success('下载成功')
}, 1000)
})
.catch(err => {
ElMessage.warning('下载失败:', err)
console.error('下载失败:', err)
// 可添加错误提示如Toast
})
@@ -61,7 +66,7 @@ export const previewFile = async (urls: any) => {
//console.log('预览', urls)
let url = ''
await downloadFile({ filePath: decodeURI(urls) })
.then((res: any) => {
.then((res: any) => {
// 1. 确定文件MIME类型优化用更简洁的方式
const getFileType = (url: string) => {
const ext = url.split('.').pop()?.toLowerCase() || ''
@@ -77,7 +82,7 @@ export const previewFile = async (urls: any) => {
jpg: 'image/jpg'
}
return mimeMap[ext] || ''
}
}
const blob = new Blob([res], { type: getFileType(decodeURI(urls)) })
// 3. 创建下载链接
url = window.URL.createObjectURL(blob)

View File

@@ -161,7 +161,7 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
})
.catch(err => {
// refresh_token + CAS 都过期 → 重新走CAS登录
window.location.href = '/api/pqs-auth/oauth/lnCheck'
//window.location.href = '/api/pqs-auth/oauth/lnCheck'
return Promise.reject(err)
})
.finally(() => {
@@ -215,10 +215,14 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
return Promise.reject(response.data)
} else if (response.data.code == 'A0121') {
//统一认证过期
const casLogoutUrl =
'http://privilege-epri.dcloud.ln.dc.sgcc.com.cn/cas/login?service=http://PQMonitoring.dcloud.ln.dc.sgcc.com.cn'
window.location.href = casLogoutUrl
//const casLogoutUrl = 'http://privilege-epri.dcloud.ln.dc.sgcc.com.cn/cas/login?service=http://PQMonitoring.dcloud.ln.dc.sgcc.com.cn'
// 1. 清空本地失效token、用户信息
adminInfo.removeToken()
adminInfo.reset()
// 2. 跳转统一鉴权中转接口
const authCheckUrl = '/api/pqs-auth/oauth/lnCheck'
window.location.href = authCheckUrl
// 中断请求
return Promise.reject(response.data)
} else {
if (options.showCodeMessage) {

View File

@@ -1,4 +1,6 @@
const MAX_CACHE_SIZE = 30
import { getWaveRawList } from './waveRawStore'
const MAX_CACHE_SIZE = 6
const cache = new Map<string, unknown>()
@@ -17,8 +19,10 @@ export function buildWaveCacheKey(
boxoList: Record<string, any>
): string {
if (!wp) return ''
const waveFp =
type === 'shu' ? dataFingerprint(wp.listWaveData) : dataFingerprint(wp.listRmsData)
const rawList = wp.waveStoreKey
? getWaveRawList(type, wp.waveStoreKey)
: ((type === 'shu' ? wp.listWaveData : wp.listRmsData) as unknown[][] | undefined)
const waveFp = dataFingerprint(rawList)
const boxoFp = boxoList?.startTime ?? boxoList?.lineName ?? boxoList?.equipmentName ?? ''
return `${type}|${wp.time}|${wp.waveType}|${wp.iphasic}|${value}|${isOpen}|${waveFp}|${boxoFp}`
}
@@ -40,3 +44,7 @@ export function setWaveCache(key: string, value: unknown): void {
if (oldest !== undefined) cache.delete(oldest)
}
}
export function clearWaveCache(): void {
cache.clear()
}

View File

@@ -0,0 +1,59 @@
const EMPTY_SERIES: number[][] = []
function ds(data: number[][] | undefined): number[][] {
if (!data?.length) return EMPTY_SERIES
return data
}
/** Worker 完整计算后,剔除当前未使用的值类型,降低内存占用 */
export function compactShuWaveResult(data: any, value: number) {
const waveDatas = data.waveDatas.map((wd: any) => {
if (value === 1) {
return {
...wd,
shunshiF: {
shunshiFA: ds(wd.shunshiF.shunshiFA),
shunshiFB: ds(wd.shunshiF.shunshiFB),
shunshiFC: ds(wd.shunshiF.shunshiFC)
},
shunshiS: { shunshiSA: EMPTY_SERIES, shunshiSB: EMPTY_SERIES, shunshiSC: EMPTY_SERIES }
}
}
return {
...wd,
shunshiF: { shunshiFA: EMPTY_SERIES, shunshiFB: EMPTY_SERIES, shunshiFC: EMPTY_SERIES },
shunshiS: {
shunshiSA: ds(wd.shunshiS.shunshiSA),
shunshiSB: ds(wd.shunshiS.shunshiSB),
shunshiSC: ds(wd.shunshiS.shunshiSC)
}
}
})
return { ...data, waveDatas }
}
export function compactRmsWaveResult(data: any, value: number) {
const waveDatas = data.waveDatas.map((wd: any) => {
if (value === 1) {
return {
...wd,
RMSFWave: {
rmsFA: ds(wd.RMSFWave.rmsFA),
rmsFB: ds(wd.RMSFWave.rmsFB),
rmsFC: ds(wd.RMSFWave.rmsFC)
},
RMSSWave: { rmsSA: EMPTY_SERIES, rmsSB: EMPTY_SERIES, rmsSC: EMPTY_SERIES }
}
}
return {
...wd,
RMSFWave: { rmsFA: EMPTY_SERIES, rmsFB: EMPTY_SERIES, rmsFC: EMPTY_SERIES },
RMSSWave: {
rmsSA: ds(wd.RMSSWave.rmsSA),
rmsSB: ds(wd.RMSSWave.rmsSB),
rmsSC: ds(wd.RMSSWave.rmsSC)
}
}
})
return { ...data, waveDatas }
}

75
src/utils/waveRawStore.ts Normal file
View File

@@ -0,0 +1,75 @@
/** 原始波形数据存放于 Vue 响应式体系之外,避免大数组触发深度代理与重复持有 */
interface WaveRawEntry {
listWaveData?: unknown[][]
listRmsData?: unknown[][]
waveTimeRange?: { min: number; max: number }
}
const rawStore = new Map<string, WaveRawEntry>()
function calcTimeRange(data: unknown[][] | undefined): { min: number; max: number } | undefined {
if (!data?.length) return undefined
const first = data[0] as number[]
const last = data[data.length - 1] as number[]
return { min: first[0], max: last[0] + 1 }
}
export function buildWaveStoreKey(boxoList: Record<string, any>): string {
const id = boxoList?.eventId ?? boxoList?.id ?? ''
return `${id}|${boxoList?.startTime ?? ''}`
}
export function registerWaveRaw(storeKey: string, wp: Record<string, any>): void {
if (!storeKey || !wp) return
const entry: WaveRawEntry = rawStore.get(storeKey) ?? {}
if (wp.listWaveData?.length) {
entry.listWaveData = wp.listWaveData
entry.waveTimeRange = calcTimeRange(wp.listWaveData) ?? entry.waveTimeRange
}
if (wp.listRmsData?.length) {
entry.listRmsData = wp.listRmsData
entry.waveTimeRange = calcTimeRange(wp.listRmsData) ?? entry.waveTimeRange
}
rawStore.set(storeKey, entry)
}
export function getWaveRawList(type: 'shu' | 'rms', storeKey: string | undefined): unknown[][] | undefined {
if (!storeKey) return undefined
const entry = rawStore.get(storeKey)
return type === 'shu' ? entry?.listWaveData : entry?.listRmsData
}
export function getWaveTimeRange(storeKey: string | undefined): { min: number; max: number } | undefined {
if (!storeKey) return undefined
return rawStore.get(storeKey)?.waveTimeRange
}
export function releaseWaveRaw(storeKey: string | undefined, type: 'shu' | 'rms' | 'all' = 'all'): void {
if (!storeKey) return
if (type === 'all') {
rawStore.delete(storeKey)
return
}
const entry = rawStore.get(storeKey)
if (!entry) return
if (type === 'shu') delete entry.listWaveData
if (type === 'rms') delete entry.listRmsData
if (!entry.listWaveData && !entry.listRmsData) {
rawStore.delete(storeKey)
} else {
rawStore.set(storeKey, entry)
}
}
/** 构建不含大数组的 wp 对象,供子组件 props 使用 */
export function buildSlimWp(wp: Record<string, any>, storeKey: string): Record<string, any> {
const { listWaveData: _w, listRmsData: _r, ...rest } = wp
return {
...rest,
waveStoreKey: storeKey,
waveTimeRange: getWaveTimeRange(storeKey) ?? calcTimeRange(_w) ?? calcTimeRange(_r)
}
}

View File

@@ -1,4 +1,5 @@
import { toRaw } from 'vue'
import { getWaveRawList } from './waveRawStore'
type WorkerMessageHandler = (data: any) => void
@@ -53,10 +54,11 @@ export function buildWorkerPayload(
waveType: plainWp.waveType,
yzd: plainWp.yzd
}
const storeKey = plainWp.waveStoreKey as string | undefined
if (type === 'shu') {
wpPayload.listWaveData = plainWp.listWaveData
wpPayload.listWaveData = getWaveRawList('shu', storeKey) ?? plainWp.listWaveData
} else {
wpPayload.listRmsData = plainWp.listRmsData
wpPayload.listRmsData = getWaveRawList('rms', storeKey) ?? plainWp.listRmsData
}
const plainBoxo: Record<string, unknown> = {}

View File

@@ -779,6 +779,7 @@ const analyseList = (e: string) => {
provide('tableStore', tableStore)
onMounted(() => {
TableHeaderRef.value.setTheDate(4)
const dom = document.getElementById('navigation-splitpanes')
if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 120)

View File

@@ -462,7 +462,7 @@ const currentChangeEvent = () => {
hasDevices.value = hasAnyDevices
dataSource.value = res.data.processDeviceList.filter(item => {
item.name = item.processNo + ''
item.name = item.processNo + '号进程'
return true // 保持原有的过滤逻辑
})
} else {

View File

@@ -0,0 +1,174 @@
<template>
<el-dialog
:title="dialogMode === 'detail' ? '定检详情' : '上传周期检测报告'"
:width="dialogMode === 'detail' ? '1000px' : '600px'"
v-model="dialogShow"
v-if="dialogShow"
>
<!-- 详情区域 -->
<div v-if="dialogMode === 'detail'">
</div>
<!-- 上传报告表单区域 -->
<div v-if="dialogMode === 'upload'">
<el-form ref="uploadFormRef" :model="uploadForm" :rules="uploadRules" label-width="120px">
<el-form-item label="定检日期" prop="thisCheckTime">
<el-date-picker
v-model="uploadForm.thisCheckTime"
type="date"
placeholder="请选择定检日期"
@change="calcNextCheckTime"
style="width:100%"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="下次定检日期" prop="nextCheckTime">
<el-date-picker
v-model="uploadForm.nextCheckTime"
type="date"
placeholder="请选择下次定检日期"
style="width:100%"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item class="uploadFile" for="-" label="设备检测报告:" prop="checkUrl">
<el-upload
v-model:file-list="uploadForm.checkUrl"
ref="uploadRef"
action=""
:accept="acceptType"
:limit="1"
:on-change="(file) => choose(file, 'checkUrl')"
:auto-upload="false"
:on-remove="removeFile('checkUrl')"
>
<template #trigger>
<el-button type="primary">上传文件</el-button>
</template>
</el-upload>
</el-form-item>
</el-form>
</div>
<template #footer>
<el-button v-if="dialogMode === 'upload'" @click="dialogShow = false">取消</el-button>
<el-button
v-if="dialogMode === 'upload'"
type="primary"
:loading="submitLoading"
@click="submitUploadReport"
>
提交
</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import type { UploadFile } from 'element-plus'
import { ElMessage } from 'element-plus'
import { uploadFile } from '@/api/system-boot/file'
import { userCheckUpload } from '@/api/device-boot/device'
const emit = defineEmits(['onSubmit'])
const acceptType = '.pdf,.docx'
const detailId = ref('')
const dialogShow = ref(false)
const dialogMode = ref<'detail' | 'upload'>('detail')
const submitLoading = ref(false)
const uploadFormRef = ref()
const uploadForm = reactive({
thisCheckTime: '',
nextCheckTime: '',
checkUrl: [] as any[],
devId: '',
objId: ''
})
const checkUrlFile = ref('')
const calcNextCheckTime = (dateVal: string) => {
if (!dateVal) {
uploadForm.nextCheckTime = ''
return
}
const date = new Date(dateVal)
date.setFullYear(date.getFullYear() + 3)
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
uploadForm.nextCheckTime = `${y}-${m}-${d}`
}
const uploadRules = reactive({
thisCheckTime: [{ required: true, message: '请选择定检日期', trigger: 'change' }],
checkUrl: [{ required: true, message: '请上传设备检测报告', trigger: 'change' }]
})
const submitUploadReport = async () => {
await uploadFormRef.value?.validate(async (valid: boolean) => {
if (!valid) return
if (!uploadForm.checkUrl.length) return ElMessage.warning('请先上传检测报告文件')
submitLoading.value = true
try {
const params = {
devId: uploadForm.devId,
objId: uploadForm.objId,
thisCheckTime: uploadForm.thisCheckTime,
nextCheckTime: uploadForm.nextCheckTime,
checkUrl: checkUrlFile.value
}
const res = await userCheckUpload(params)
if (res.code === 'A0000') {
ElMessage.success('提交成功')
dialogShow.value = false
emit('onSubmit')
}
} catch (err: any) {
ElMessage.error(err.msg || '提交失败')
} finally {
submitLoading.value = false
}
})
}
const openUpload = (row: any) => {
console.log("🚀 ~ openUpload ~ row:", row)
uploadForm.thisCheckTime = ''
uploadForm.nextCheckTime = ''
uploadForm.checkUrl = []
uploadForm.devId = row.devId
uploadForm.objId = row.objId
checkUrlFile.value = ''
uploadFormRef.value?.clearValidate()
dialogMode.value = 'upload'
dialogShow.value = true
}
const openDetail = (id: string) => {
detailId.value = id
dialogMode.value = 'detail'
dialogShow.value = true
}
const removeFile = (val: string) => {
return (_file: UploadFile, fileList: UploadFile[]) => {
if (val === 'checkUrl') {
checkUrlFile.value = ''
}
uploadForm[val] = fileList
}
}
const choose = (e: any, field: string) => {
uploadFile(e.raw, '/supervision/').then(res => {
if (field === 'checkUrl') {
checkUrlFile.value = res.data.name
}
})
}
defineExpose({ openUpload, openDetail })
</script>

View File

@@ -0,0 +1,205 @@
<template>
<div class="default-main">
<TableHeader ref="TableHeaderRef" showExport>
<template #select>
<el-form-item label="地市">
<el-select v-model="tableStore.table.params.city" clearable placeholder="请选择地市">
<el-option
v-for="item in areaOptionList"
:key="item.id"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="监测对象">
<el-input
style="width: 200px"
placeholder="请输入监测对象名称"
v-model="tableStore.table.params.searchValue"
clearable
maxlength="32"
show-word-limit
></el-input>
</el-form-item>
</template>
<template #operation>
<!-- <el-button icon="el-icon-Plus" type="primary" @click="addFormModel">新增定检记录</el-button>-->
</template>
</TableHeader>
<Table ref="tableRef" @cell-click="cellClickEvent" />
<checkForm ref="checkFormRef" @onSubmit="tableStore.index()" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, watch } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import checkForm from './components/form.vue'
import { useDictData } from '@/stores/dictData'
import { useAdminInfo } from '@/stores/adminInfo'
import { download } from '@/utils/fileDownLoad'
defineOptions({
name: 'terminal/terminaCkeck'
})
// 公共依赖
const TableHeaderRef = ref()
const checkFormRef = ref()
const dictData = useDictData()
const adminInfo = useAdminInfo()
// 地区字典(和你原有地市下拉同源)
const areaOptionList = dictData.getBasicData('jibei_area')
// TableStore 表格配置(仅修改字段映射,其余不动)
const tableStore = new TableStore({
url: '/device-boot/alarm/terminalCheckPage',
method: 'POST',
column: [
// 多选框
{
width: '60',
type: 'checkbox'
},
// 序号(分页自增,和你现有逻辑一致)
{
title: '序号',
width: 70,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'areaName', title: '所在地市', minWidth: 100 },
{ field: 'bdName', title: '变电站', minWidth: 150 },
{ field: 'objName', title: '监测对象', minWidth: 180 },
{ field: 'devName', title: '终端名称', minWidth: 180 },
{ field: 'loginDate', title: '投运时间', minWidth: 120 },
{ field: 'thisCheckTime', title: '本次定检时间', minWidth: 120 },
{ field: 'nextCheckTime', title: '下次定检时间', minWidth: 120 },
{
title: '是否逾期',
field: 'checkStatus',
align: 'center',
width: 80,
render: 'customRender',
customRender: props => {
const val = props.renderValue
let text = ''
let color = ''
if (val === 1) {
text = '是'
color = '#f56c6c'
} else if (val === 0) {
text = '否'
color = '#67c23a'
}
return h('span', { style: { color, fontWeight: 'bold' } }, text)
}
},
{
field: 'overdueDay',
title: '逾期天数',
minWidth: 80,
render: 'customRender',
customRender: props => {
const val = props.renderValue
let text = ''
let color = ''
if (val > 0) {
text = val
color = '#f56c6c'
} else if (val > -30) {
text = Math.abs(val).toString() + '天后将逾期'
color = '#e6a23c'
} else {
text = '/'
}
return h('span', { style: { color, fontWeight: 'bold' } }, text)
}
},
{
field: 'checkUrl',
title: '周期检测报告',
minWidth: 160,
render: 'customRender',
customRender: props => {
const val = props.renderValue?.replace(/^.*?\/(.*?)\//, '') || ''
return val ? h('span', { style: { color: 'var(--el-color-primary)', cursor: 'pointer' } }, val) : '/'
}
},
// 操作列固定右侧
{
title: '操作',
fixed: 'right',
minWidth: 160,
render: 'buttons',
buttons: [
// {
// name: 'detail',
// title: '详情',
// type: 'primary',
// icon: 'el-icon-EditPen',
// render: 'basicButton',
// click: row => {
// checkFormRef.value.openDetail(row.devId)
// }
// },
{
name: 'edit',
title: '上传周期检测报告',
type: 'primary',
icon: 'el-icon-Open',
render: 'basicButton',
click: row => {
checkFormRef.value.openUpload(row)
}
}
]
}
],
beforeSearchFun: () => {
// 携带当前登录人部门ID
tableStore.table.params.orgId = adminInfo.$state.deptId
}
})
// 初始化查询参数
tableStore.table.params.city = ''
tableStore.table.params.substation = ''
tableStore.table.params.terminalName = ''
tableStore.table.params.orgId = adminInfo.$state.deptId
// 路由跳转带ID回显编辑复用你原有路由传参逻辑
const props = defineProps({
id: { type: String, default: 'null' }
})
watch(
() => props.id,
async newVal => {
if (newVal === 'null') return
const fullId = newVal.split('@')[0]
const routeTime = Number(newVal.split('@')[1])
if (isNaN(routeTime) || Date.now() - routeTime > import.meta.env.VITE_ROUTE_TIME_OUT) return
const res = await getPqCheckById(fullId)
if (res.code === 'A0000') {
}
},
{ immediate: true }
)
// 点击行
const cellClickEvent = ({ row, column }: any) => {
if (column.field == 'checkUrl') {
row.checkUrl ? download(row.checkUrl) : ''
}
}
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
</script>
<style scoped></style>

View File

@@ -212,7 +212,7 @@
<el-form-item for="-" v-if="form.userType != '0' && form.userType != '1'" label="PCC点">
<el-input v-model.trim="form.pccPoint" autocomplete="off" placeholder="请输入PCC点" />
</el-form-item>
<el-form-item
<!-- <el-form-item
for="-"
v-if="form.userType == '2' || form.userType == '3' || form.userType == '4' || form.userType == '5'"
label="基准短路容量:"
@@ -273,7 +273,7 @@
>
<template #append>MVA</template>
</el-input>
</el-form-item>
</el-form-item>-->
<el-form-item for="-" v-if="form.userType == '6'" label="行业:">
<el-select v-model="form.industry" placeholder="请选择行业">
<el-option v-for="(item, index) in industryList" :label="item.name" :value="item.id" :key="index" />
@@ -368,6 +368,48 @@
show-word-limit
/>
</el-form-item>
<el-form-item
class="uploadFile"
for="-"
label="设备检测报告:"
prop="checkUrl"
>
<el-upload
v-model:file-list="form.checkUrl"
ref="uploadRef"
action=""
:accept="acceptType"
:limit="1"
:on-change="(file) => choose(file, 'checkUrl')"
:auto-upload="false"
:on-remove="removeFile('checkUrl')"
>
<template #trigger>
<el-button type="primary" >上传文件</el-button>
</template>
</el-upload>
</el-form-item>
<el-form-item
class="uploadFile"
for="-"
label="电能质量评估报告"
prop="evaluation"
>
<el-upload
v-model:file-list="form.assessUrl"
ref="uploadRef"
action=""
:accept="acceptType"
:limit="1"
:on-change="(file) => choose(file, 'assessUrl')"
:auto-upload="false"
:on-remove="removeFile('assessUrl')"
>
<template #trigger>
<el-button type="primary">上传文件</el-button>
</template>
</el-upload>
</el-form-item>
<el-form-item for="-" label="预测评估结论" style="width: 100%">
<el-input
type="textarea"
@@ -390,7 +432,7 @@
<script lang="ts" setup>
import { ref, onMounted, reactive, defineExpose, defineProps, defineEmits, watch, onUnmounted } from 'vue'
// import { upload, insertTerminal, updateTerminal } from '@/api/process-boot/terminal'
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
import type { UploadFile, UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
import { genFileId, ElMessage } from 'element-plus'
import { useDictData } from '@/stores/dictData'
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
@@ -435,10 +477,11 @@ const props = defineProps({
}
})
const emits = defineEmits(['onSubmit'])
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
const dictData = useDictData()
const dialogFormVisible = ref(false)
// .doc,.docx,.xlsx,.xls,.pdf
const acceptType = ''
const acceptType = '.pdf,.docx'
const form: any = ref({})
const loading = ref(false)
const control: any = ref(true)
@@ -532,6 +575,10 @@ const defaultProps = {
const nonlinearDeviceTypeList: any = ref('')
//获取登陆用户姓名和部门
const adminInfo = useAdminInfo()
// 电能质量检测报告
const checkUrlFile = ref('')
// 电能质量评估报告
const evaluationFile = ref('')
const resetForm = () => {
form.value = {
reporter: '', //填报人 1
@@ -558,6 +605,8 @@ const resetForm = () => {
pccPoint: '', //PCC点 1
evaluationType: evaluationTypeList[0].id, //评估类型 1
evaluationChekDept: '', //预测评估审单位 1
checkUrl: [], //电能质量检测报告
assessUrl: [], //电能质量评估报告
minShortCircuitCapacity: '', //系统最小短路容量MVA 1
userAgreementCapacity: '', //用户用电协议容量MVA 1
needGovernance: 0, //是否需要治理 1
@@ -581,6 +630,8 @@ const resetForm = () => {
delete form.value.loadLevel
delete form.value.powerSupplyInfo
}
checkUrlFile.value = ''
evaluationFile.value = ''
}
//初始化数据
resetForm()
@@ -900,6 +951,10 @@ const open = async (row: any) => {
} else {
resendId.value = ''
form.value.userType = userTypeList.value[0].value
checkUrlFile.value = ''
evaluationFile.value = ''
form.value.checkUrl = []
form.value.evaluation = []
}
await getSubstationSelect().then(res => {
stationList.value = res.data
@@ -917,18 +972,36 @@ async function handleResponse(data: any) {
// userType logic is commented out; if needed, implement accordingly
if (data.userReportProjectPO) {
form.value = { ...data, ...data.userReportProjectPO }
fileRaw(data, 'userReportProjectPO')
} else if (data.userReportSubstationPO) {
form.value = { ...data, ...data.userReportSubstationPO }
fileRaw(data, 'userReportSubstationPO')
} else if (data.userReportSensitivePO) {
form.value = {
...data,
...data.userReportSensitivePO,
energyQualityIndex: data.userReportSensitivePO.energyQualityIndex.split(', ')
}
fileRaw(data, 'userReportSensitivePO')
}
form.value.orgId = adminInfo.$state.deptName
}
// 处理上传文件回显
const fileRaw = (row: any, key: string) => {
const fileFields = ['checkUrl', 'assessUrl']
for (const field of fileFields) {
const filePath = row[key]?.[field] ?? row[field]
if (filePath != null && filePath.length > 0) {
form.value[field] = [{ name: filePath.split('/')[2] }]
} else {
form.value[field] = []
}
}
checkUrlFile.value = row[key]?.checkUrl ?? row.checkUrl ?? ''
evaluationFile.value = row[key]?.assessUrl ?? row.assessUrl ?? ''
}
const close = () => {
//重置表单内容
//取消表单校验状态
@@ -947,14 +1020,25 @@ const handleExceed: UploadProps['onExceed'] = files => {
file.uid = genFileId()
uploadRef.value!.handleStart(file)
}
let uploadName = ref('')
//上传报告字段名称
const uploadFileName = (val: any) => {
uploadName.value = val
}
//移除文件上传
const removeFile = (file: any, uploadFiles: any) => {
console.log(file, uploadFiles)
const removeFile = (val: string) => {
return (_file: UploadFile, fileList: UploadFile[]) => {
if (val === 'checkUrl') {
checkUrlFile.value = ''
} else if (val === 'assessUrl') {
evaluationFile.value = ''
}
form.value[val] = fileList
}
}
const choose = (e: any, field: string) => {
uploadFile(e.raw, '/supervision/').then(res => {
if (field === 'checkUrl') {
checkUrlFile.value = res.data.name
} else if (field === 'assessUrl') {
evaluationFile.value = res.data.name
}
})
}
// 关联终端
@@ -981,12 +1065,16 @@ const confirmForm = async (flag: boolean) => {
subForm.value.reporter = adminInfo.$state.id
subForm.value.orgId = adminInfo.$state.deptId
let confirmFormData = JSON.parse(JSON.stringify(subForm.value))
confirmFormData.checkUrl = checkUrlFile.value
confirmFormData.assessUrl = evaluationFile.value
//1.判断是否上传
if (subForm.value.userType == '0' || subForm.value.userType == '1') {
{
//其他报告非必填
confirmFormData.userReportProjectPO = {
...confirmFormData.userReportProjectPO
...confirmFormData.userReportProjectPO,
checkUrl: checkUrlFile.value,
assessUrl: evaluationFile.value
}
}
}
@@ -999,7 +1087,9 @@ const confirmForm = async (flag: boolean) => {
) {
{
confirmFormData.userReportSubstationPO = {
...confirmFormData.userReportSubstationPO
...confirmFormData.userReportSubstationPO,
checkUrl: checkUrlFile.value,
assessUrl: evaluationFile.value
}
}
}
@@ -1008,7 +1098,9 @@ const confirmForm = async (flag: boolean) => {
{
confirmFormData.userReportSensitivePO = {
...confirmFormData.userReportSensitivePO,
energyQualityIndex: confirmFormData.userReportSensitivePO.energyQualityIndex.join(', ')
energyQualityIndex: confirmFormData.userReportSensitivePO.energyQualityIndex.join(', '),
checkUrl: checkUrlFile.value,
assessUrl: evaluationFile.value
}
}
}
@@ -1060,8 +1152,6 @@ const filterUsers = (arr: any) => {
userTypeList.value = userTypeList.value.filter(item => !arr.includes(item.value))
}
const setcontroFlag = () => {
controFlag.value = true
}
defineExpose({ open, filterUsers, setcontroFlag })

View File

@@ -212,12 +212,21 @@
})?.name
}}
</el-descriptions-item>
<el-descriptions-item label="敏感电能质量指标" v-if="detailData.userType == 6">
{{
energyQualityIndexList.find(item => {
return item.id == proviteData.energyQualityIndex
})?.name
}}
<el-descriptions-item :span="2" label="电能质量设备检测报告">
<el-icon class="elView" v-if="detailData?.checkUrl">
<View @click="openFile(detailData?.checkUrl)" />
</el-icon>
<span class="aLoad" @click="download(detailData.checkUrl)" target="_blank">
{{ detailData.checkUrl?.replace(/^.*?\/(.*?)\//, '') || '' }}
</span>
</el-descriptions-item>
<el-descriptions-item :span="2" label="电能质量评估报告">
<el-icon class="elView" v-if="detailData?.assessUrl">
<View @click="openFile(detailData?.assessUrl)" />
</el-icon>
<span class="aLoad" @click="download(detailData.assessUrl)" target="_blank">
{{ detailData.assessUrl?.replace(/^.*?\/(.*?)\//, '') || '' }}
</span>
</el-descriptions-item>
</el-descriptions>
</div>
@@ -233,7 +242,7 @@ import { getDictTreeById } from '@/api/system-boot/dictTree'
import { useDictData } from '@/stores/dictData'
import { getFileNameAndFilePath } from '@/api/system-boot/file'
import { Link, View } from '@element-plus/icons-vue'
import PreviewFile from '@/components/PreviewFile/index.vue'
import { download } from '@/utils/fileDownLoad'
// import { addOrUpdateFile, getFileById } from '@/api/supervision-boot/interfere/index'
defineOptions({ name: 'BpmUserReportDetail' })

View File

@@ -1,6 +1,6 @@
<template>
<div class="default-main">
<TableHeader ref="TableHeaderRef">
<TableHeader ref="TableHeaderRef" showExport>
<template #select>
<el-form-item label="项目名称">
<el-input
@@ -32,7 +32,7 @@
<el-button icon="el-icon-Upload" type="primary" @click="importUserData">批量导入</el-button> -->
</template>
</TableHeader>
<Table ref="tableRef" />
<Table ref="tableRef" @cell-click="cellClickEvent" />
<el-dialog title="详情" width="1000px" v-model="dialogShow" v-if="dialogShow">
<DetailInfo :id="userId" :openType="'sourcesOfInterference'"></DetailInfo>
@@ -45,7 +45,7 @@
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick, watch } from 'vue'
import { ref, onMounted, reactive, provide, nextTick, watch, onUnmounted } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
@@ -58,6 +58,7 @@ import { downloadSensitiveReportTemplate } from '@/api/supervision-boot/userRepo
import DetailInfo from './components/detail.vue'
import { cancelFormData, getUserReportById } from '@/api/supervision-boot/interfere/index'
import { deleteUserReport } from '@/api/device-boot/sensitiveLoadMange'
import { download } from '@/utils/fileDownLoad'
const addForms = ref()
const dictData = useDictData()
const sensitiveUserPopup = ref()
@@ -88,13 +89,13 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'city', title: '所在地市', minWidth: 80 },
/* { field: 'substation', title: '厂站名称', minWidth: 100 },*/
{ field: 'projectName', title: '项目名称', minWidth: 170 },
{ field: 'city', title: '所在地市', minWidth: 100 },
/* { field: 'substation', title: '厂站名称', minWidth: 100 },*/
{ field: 'projectName', title: '监测对象名称', minWidth: 150 },
{
field: 'userType',
title: '用户性质',
minWidth: 150,
minWidth: 180,
formatter: (obj: any) => {
const userType = obj.row.userType
return getUserTypeName(userType)
@@ -102,20 +103,42 @@ const tableStore = new TableStore({
},
// { field: 'responsibleDepartment', title: '归口管理部门', minWidth: 130 },
{ field: 'ratePower', title: '装机容量(MW)', minWidth: 130 },
{ field: 'stationId', title: '所属电站', minWidth: 130 },
{ field: 'ratePower', title: '装机容量(MW)', minWidth: 80 },
{ field: 'stationId', title: '并网电站', minWidth: 150 },
{
field: 'checkUrl',
title: '电能质量设备检测报告',
minWidth: 160,
render: 'customRender',
customRender: props => {
const val = props.renderValue?.replace(/^.*?\/(.*?)\//, '') || ''
return val ? h('span', { style: { color: 'var(--el-color-primary)', cursor: 'pointer' } }, val) : '/'
}
},
{
field: 'assessUrl',
title: '电能质量评估报告',
minWidth: 160,
render: 'customRender',
customRender: props => {
const val = props.renderValue?.replace(/^.*?\/(.*?)\//, '') || ''
return val ? h('span', { style: { color: 'var(--el-color-primary)', cursor: 'pointer' } }, val) : '/'
}
},
/* {
field: 'createBy',
title: '创建人',
minWidth: 80,
formatter: (row: any) => {
return dictData.state.userList.filter(item => item.id == row.cellValue)[0]?.name
}
},
},*/
{
title: '操作',fixed: 'right',
title: '操作',
fixed: 'right',
minWidth: 150,
render: 'buttons',
buttons: [
{
@@ -138,7 +161,6 @@ const tableStore = new TableStore({
disabled: row => {
return !(row.status == 0)
},
click: row => {
addForms.value.filterUsers([6])
@@ -148,9 +170,7 @@ const tableStore = new TableStore({
row: row
})
}
},
}
]
}
],
@@ -209,27 +229,13 @@ const deleteEven = () => {
})
}
}
/**取消流程操作*/
const cancelLeave = async (row: any) => {
// 二次确认
const { value } = await ElMessageBox.prompt('请输入取消原因', '取消流程', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputType: 'textarea',
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
inputErrorMessage: '取消原因不能为空'
})
// 发起取消
let data = {
id: row.id,
processInstanceId: row.processInstanceId,
dataType: 1,
reason: value
// 点击行
const cellClickEvent = ({ row, column }: any) => {
if (column.field == 'checkUrl') {
row.checkUrl ? download(row.checkUrl) : ''
} else if (column.field == 'assessUrl') {
row.assessUrl ? download(row.assessUrl) : ''
}
await cancelFormData(data)
ElMessage.success('取消成功')
// 加载数据
tableStore.index()
}
// 新增
@@ -238,7 +244,7 @@ const addFormModel = () => {
setTimeout(() => {
addForms.value.open({
title: '用户档案录入'
title: '新能源场站档案录入'
})
})
}

View File

@@ -67,13 +67,13 @@ const tableStore = new TableStore({
column: [
{ field: 'index', title: '序号', width: '80', formatter: (row: any) => { return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1 } },
{ field: 'provinceCompany', title: '地级', minWidth: "150px", },
{ field: 'cityCompany', title: '供电公司', minWidth: "150px", },
{ field: 'provinceCompany', title: '地级', minWidth: "150px", },
/* { field: 'cityCompany', title: '供电公司', minWidth: "150px", },*/
{ field: 'subName', title: '变电站', minWidth: "150px", },
{ field: 'lineScale', title: '电压等级', minWidth: "120px", },
{ field: 'lineName', title: '监测点名称', minWidth: "150px", },
{ field: 'loadType', title: '干扰源类型', minWidth: "150px", },
{ field: 'lineObjectName', title: '监测点对象名称', minWidth: "180px", formatter: (row: any) => { return row.cellValue == null ? '/' : row.cellValue } },
{ field: 'lineName', title: '监测点名称', minWidth: "150px", },
{ field: 'lineScale', title: '电压等级', minWidth: "120px", },
{ field: 'loadType', title: '干扰源类型', minWidth: "150px", },
{ field: 'overDay', title: '超标天数', minWidth: "80px", },
{ field: 'freqOverDay', title: '频率偏差', minWidth: "100px", },
{ field: 'volDevOverDay', title: '电压偏差', minWidth: "100px", },

View File

@@ -159,18 +159,19 @@
</template>
</vxe-column>
<vxe-column field="cit" title="所在地市" minWidth="110px"></vxe-column>
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column v-if="!IS_LN" field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
<vxe-column v-if="VITE_FLAG" field="objName" title="监测对象" minWidth="130px"></vxe-column>
<vxe-column
field="lineName"
title="监测点名称"
:formatter="formatter"
minWidth="130px"
></vxe-column>
<vxe-column v-if="VITE_FLAG" field="objName" title="监测对象" minWidth="130px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }">
<el-tag
@@ -211,14 +212,14 @@
<script setup lang="ts">
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref, watch } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getMonitorVerifyDay } from '@/api/device-boot/dataVerify'
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
defineOptions({
name: 'harmonic-boot/harmonic/getIntegrityData'
})

View File

@@ -157,12 +157,12 @@
</template>
</vxe-column>
<vxe-column field="cit" title="所在地市" width="110px"></vxe-column>
<vxe-column field="company" title="供电公司" minWidth="110px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="110px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="110px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="130px"></vxe-column>
<vxe-column v-if="!IS_LN" field="company" title="供电公司" minWidth="100px"></vxe-column>
<vxe-column field="subStation" title="变电站" minWidth="100px"></vxe-column>
<vxe-column field="manufacturer" title="终端厂家" minWidth="90px"></vxe-column>
<vxe-column field="deviceName" title="终端名称" minWidth="100px"></vxe-column>
<vxe-column field="ip" title="终端IP" :formatter="formatter" width="120px"></vxe-column>
<vxe-column field="timeID" title="最新数据时间" :formatter="formatter" width="160px"></vxe-column>
<vxe-column field="runFlag" title="运行状态" width="90px">
<template #default="{ row }">
<el-tag
@@ -182,6 +182,19 @@
</el-tag>
</template>
</vxe-column>
<vxe-column field="comFlag" title="通讯状态" width="90px">
<template #default="{ row }">
<el-tag
:type="
row.comFlag == '正常'
? 'success'
: 'danger'
"
>
{{ row.comFlag }}
</el-tag>
</template>
</vxe-column>
<vxe-column field="onlineRate" title="在线率(%)" width="90px"></vxe-column>
</vxe-table>
</div>
@@ -201,16 +214,14 @@
</template>
<script setup lang="ts">
// import '@/assets/font/iconfont.css'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { onMounted, provide, ref } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import MyEchart from '@/components/echarts/MyEchart.vue'
import { getMonitorVerifyDay } from '@/api/device-boot/dataVerify'
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
defineOptions({
name: 'harmonic-boot/harmonic/getIntegrityData'
})

View File

@@ -38,7 +38,7 @@
<el-tab-pane label="告警数据统计" name="5" lazy v-if="!isReload && VITE_FLAG">
<Gaojingshujutongji v-if="activeName == '5'" />
</el-tab-pane>
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload">
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload && !VITE_FLAG1 && !IS_LNQR">
<Yunxingzhuangtai v-if="activeName == '6'" />
</el-tab-pane>
<el-tab-pane label="实时数据" name="7" lazy v-if="!isReload && !VITE_FLAG1 && !IS_LNQR">

View File

@@ -10,30 +10,53 @@
<DatePicker ref="datePickerRef" :theCurrentTime="true"></DatePicker>
</el-form-item>
<el-form-item label="指标类型:">
<el-select v-model="formData.condition" multiple collapse-tags :multiple-limit="checked ? 1 : 3"
filterable placeholder="请选择指标" @change="conditionChange">
<el-select
v-model="formData.condition"
multiple
collapse-tags
:multiple-limit="checked ? 1 : 3"
filterable
placeholder="请选择指标"
@change="conditionChange"
>
<el-option-group v-for="group in indexOptions" :key="group.label" :label="group.label">
<el-option v-for="item in group.options" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-option
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item label="数值类型:">
<el-select style="width: 100%" v-model="formData.valueType" placeholder="请选择类型">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-option
v-for="item in typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="谐波次数:" v-show="showXieBoCiShu">
<el-select style="width: 100%" v-model="formData.harmonic" placeholder="请选择谐波">
<el-option v-for="item in harmonicOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-option
v-for="item in harmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item v-show="showJianXieBoCiShu" label="间谐波次数:">
<el-select style="width: 100%" v-model="formData.inHarmonic" placeholder="请选择间谐波">
<el-option v-for="item in inharmonicOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-option
v-for="item in inharmonicOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</template>
@@ -44,10 +67,21 @@
<!-- <el-form :inline="true">
</el-form> -->
<div id="canvas" class="mt10" :style="height1" style="overflow-y: auto; overflow-x: hidden"
v-loading="loading">
<my-echart :options="item.option" v-for="item in list" style="min-height: 190px" :style="height"
@triggerPoint="triggerPoint" @group="group" />
<div
id="canvas"
class="mt10"
:style="height1"
style="overflow-y: auto; overflow-x: hidden"
v-loading="loading"
>
<my-echart
:options="item.option"
v-for="item in list"
style="min-height: 190px"
:style="height"
@triggerPoint="triggerPoint"
@group="group"
/>
</div>
</div>
<div :style="{ height: pageHeight.height }" style="padding: 10px; overflow: hidden" v-if="!view">
@@ -72,7 +106,7 @@ import html2canvas from 'html2canvas'
import { ElMessage } from 'element-plus'
import { yMethod, completeTimeSeries } from '@/utils/echartMethod'
import * as echarts from 'echarts' // 全引入
import { min } from 'xe-utils'
const datePickerRef = ref()
const monitoringPoint = useMonitoringPoint()
const checked = ref(monitoringPoint.state.showCheckBox)
@@ -198,8 +232,8 @@ const shujuchuli = (res: any) => {
let cvalue = []
let topLimit = []
let lowerLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -234,12 +268,7 @@ const shujuchuli = (res: any) => {
//不存在一个暂降点或1个 //处理暂降点
if (item.eventDetail.length > 0) {
for (let k = 0; k < item.eventDetail.length; k++) {
chufa.push([
item.eventDetail[k].time,
(0).toFixed(3),
item.eventDetail[k].id,
99
])
chufa.push([item.eventDetail[k].time, (0).toFixed(3), item.eventDetail[k].id, 99])
}
}
let shuju = {
@@ -267,8 +296,8 @@ const shujuchuli = (res: any) => {
let gvalue = []
let topLimit = []
let lowerLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -289,12 +318,7 @@ const shujuchuli = (res: any) => {
//不存在一个暂降点或1个 //处理暂降点
if (item.eventDetail.length > 0) {
for (let k = 0; k < item.eventDetail.length; k++) {
chufa.push([
item.eventDetail[k].time,
(0).toFixed(3),
item.eventDetail[k].id,
99
])
chufa.push([item.eventDetail[k].time, (0).toFixed(3), item.eventDetail[k].id, 99])
}
}
let shuju = {
@@ -345,7 +369,7 @@ const shujuchuli = (res: any) => {
let bvalue = []
let cvalue = []
let topLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -379,12 +403,7 @@ const shujuchuli = (res: any) => {
//不存在一个暂降点或1个 //处理暂降点
if (item.eventDetail.length > 0) {
for (let k = 0; k < item.eventDetail.length; k++) {
chufa.push([
item.eventDetail[k].time,
(0).toFixed(3),
item.eventDetail[k].id,
99
])
chufa.push([item.eventDetail[k].time, (0).toFixed(3), item.eventDetail[k].id, 99])
}
}
let shuju = {
@@ -409,7 +428,7 @@ const shujuchuli = (res: any) => {
if (item.phaiscType.length == 3) {
let gvalue = []
let topLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -479,7 +498,7 @@ const shujuchuli = (res: any) => {
let bvalue = []
let cvalue = []
let lowerLimit = []
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -538,7 +557,7 @@ const shujuchuli = (res: any) => {
if (item.phaiscType.length == 3) {
let gvalue = []
let lowerLimit = []
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -599,7 +618,6 @@ const shujuchuli = (res: any) => {
}
//无限值
if (item.topLimit == 0 && item.lowerLimit == 0) {
if (item.minValue !== null && item.maxValue !== null) {
//最小值等于下限值
//图列为A,B,C,暂降
@@ -638,12 +656,7 @@ const shujuchuli = (res: any) => {
//不存在一个暂降点或1个 //处理暂降点
if (item.eventDetail.length > 0) {
for (let k = 0; k < item.eventDetail.length; k++) {
chufa.push([
item.eventDetail[k].time,
(0).toFixed(3),
item.eventDetail[k].id,
99
])
chufa.push([item.eventDetail[k].time, (0).toFixed(3), item.eventDetail[k].id, 99])
}
}
let shuju = {
@@ -683,12 +696,7 @@ const shujuchuli = (res: any) => {
//不存在一个暂降点或1个 //处理暂降点
if (item.eventDetail.length > 0) {
for (let k = 0; k < item.eventDetail.length; k++) {
chufa.push([
item.eventDetail[k].time,
(0).toFixed(3),
item.eventDetail[k].id,
99
])
chufa.push([item.eventDetail[k].time, (0).toFixed(3), item.eventDetail[k].id, 99])
}
}
let shuju = {
@@ -740,8 +748,8 @@ const shujuchuli = (res: any) => {
let cvalue = []
let topLimit = []
let lowerLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -796,8 +804,8 @@ const shujuchuli = (res: any) => {
let gvalue = []
let topLimit = []
let lowerLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -863,7 +871,7 @@ const shujuchuli = (res: any) => {
let bvalue = []
let cvalue = []
let topLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
// item.minValue=item.lowerLimit
//判断数据是否存在
if (item.value !== null) {
@@ -916,7 +924,7 @@ const shujuchuli = (res: any) => {
if (item.phaiscType.length == 2) {
let gvalue = []
let topLimit = []
item.maxValue = (item.topLimit > item.maxValue ? item.topLimit : item.maxValue)
item.maxValue = item.topLimit > item.maxValue ? item.topLimit : item.maxValue
// item.minValue=item.lowerLimit
//判断数据是否存在
if (item.value !== null) {
@@ -981,7 +989,7 @@ const shujuchuli = (res: any) => {
let cvalue = []
let lowerLimit = []
// item.maxValue=item.topLimit
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -1034,7 +1042,7 @@ const shujuchuli = (res: any) => {
let gvalue = []
let lowerLimit = []
// item.maxValue=item.topLimit
item.minValue = (item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue)
item.minValue = item.lowerLimit < item.minValue ? item.lowerLimit : item.minValue
//判断数据是否存在
if (item.value !== null) {
for (let j = 0; j < item.value.length; j++) {
@@ -1202,6 +1210,7 @@ const getSeriesDataValues = (data: any[]) => {
.filter((v): v is number => v != null && !Number.isNaN(v))
}
const buildItemYAxis = (item: any) => {
console.log('🚀 ~ buildItemYAxis ~ item:', item)
if (item.useDualAxis && item.serise?.length) {
const uniqueUnits = [...new Set(item.units.filter((u: string) => u != null && u !== ''))] as string[]
const valuesByUnit: Record<string, number[]> = {}
@@ -1214,8 +1223,8 @@ const buildItemYAxis = (item: any) => {
if (unit) valuesByUnit[unit].push(...getSeriesDataValues(s.data))
})
return uniqueUnits.map((unit, index) => {
const [min, max] = yMethod(valuesByUnit[unit].length ? valuesByUnit[unit] : [0])
return {
type: 'value',
min,
@@ -1232,7 +1241,14 @@ const buildItemYAxis = (item: any) => {
})
}
const values = item.value?.length ? item.value.map((k: any) => k[1]) : [0]
const [min, max] = yMethod([item.maxValue, item.minValue, ...values])
const [min, max] = yMethod([
item.maxValue,
item.minValue,
...values,
item.topLimit?.[0]?.[1] || null,
item.lowerLimit?.[0]?.[1] || null
])
return [
{
type: 'value',
@@ -1281,10 +1297,7 @@ const rendering = () => {
let opitonserise: any[] = []
item.legend.forEach((item2: any) => {
if (
item.avalue !== undefined &&
(item2 == 'A相' || item2 == 'AB相' || item2.startsWith('零序电压'))
) {
if (item.avalue !== undefined && (item2 == 'A相' || item2 == 'AB相' || item2.startsWith('零序电压'))) {
let data = {
name: item2,
symbol: 'none',
@@ -1592,10 +1605,7 @@ const getEcharts = () => {
let tips = ''
tips += '时刻:' + params[0].data[0] + '</br/>'
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName == '暂态触发点') {
tips += ''
return tips
@@ -1605,29 +1615,29 @@ const getEcharts = () => {
params[i].marker + params[i].value[1] > 0
? 'A相谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? 'A相谐波电流方向:无<br/>'
: 'A相谐波电流方向:流出<br/>'
? 'A相谐波电流方向:无<br/>'
: 'A相谐波电流方向:流出<br/>'
} else if (params[i].seriesName == 'B相谐波电流方向') {
tips +=
params[i].marker + params[i].value[1] > 0
? 'B相谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? 'B相谐波电流方向:无<br/>'
: 'B相谐波电流方向:流出<br/>'
? 'B相谐波电流方向:无<br/>'
: 'B相谐波电流方向:流出<br/>'
} else if (params[i].seriesName == 'C相谐波电流方向') {
tips +=
params[i].marker + params[i].value[1] > 0
? 'C相谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? 'C相谐波电流方向:无<br/>'
: 'C相谐波电流方向:流出<br/>'
? 'C相谐波电流方向:无<br/>'
: 'C相谐波电流方向:流出<br/>'
} else if (params[i].seriesName == '总谐波电流方向') {
tips +=
params[i].marker + params[i].value[1] > 0
? '总谐波电流方向:流入<br/>'
: params[i].value[1] == 0
? '总谐波电流方向:无<br/>'
: '总谐波电流方向:流出<br/>'
? '总谐波电流方向:无<br/>'
: '总谐波电流方向:流出<br/>'
} else if (params[i].seriesName.includes('正序电压')) {
let str = (params[i].value[1] * 1).toString()
let reg = str.indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
@@ -1699,8 +1709,6 @@ const getEcharts = () => {
':' +
(Number.isNaN(Number(str2)) ? '/' : str2) +
'<br/>'
}
}
@@ -1908,7 +1916,6 @@ const getEcharts = () => {
echarts.connect('group')
}
const conditionChange = () => {
//判断一个指标时
if (formData.condition.length == 1) {
if (
@@ -2045,7 +2052,6 @@ const conditionChange = () => {
}
setTimeout(() => {
//console.log('🚀 ~ setTimeout ~ tableHeaderRef.value:', tableHeaderRef.value)
//tableHeaderRef.value && tableHeaderRef.value?.computedSearchRow()
}, 100)
}

View File

@@ -14,8 +14,8 @@
<template v-slot:select>
<el-form-item >
<el-radio-group v-model="isStatisticData" @change="onStatisticDataChange">
<el-radio-button value="1">统计数据</el-radio-button>
<el-radio-button value="0">分钟数据</el-radio-button>
<el-radio-button value="0">统计数据</el-radio-button>
<el-radio-button value="1">分钟数据</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="模板策略">
@@ -79,7 +79,7 @@ const dotList: any = ref({})
const Template: any = ref({})
const reportForm: any = ref('')
const name = ref('')
const isStatisticData = ref('1')
const isStatisticData = ref('0')
const templatePolicy: any = ref([])
const reportFormList: any = ref([
{
@@ -103,8 +103,8 @@ const tableStore = new TableStore({
tableStore.table.params.tempId = Template.value.id
tableStore.table.params.lineId = dotList.value.id
name.value = dotList.value.name
if (Number(isStatisticData.value) === 0) {
tableStore.table.params.isStatisticData = 0
if (Number(isStatisticData.value) === 1) {
tableStore.table.params.isStatisticData = 1
} else {
delete tableStore.table.params.isStatisticData
}
@@ -163,7 +163,7 @@ const changetype = (val: any) => {
const onStatisticDataChange = () => {
TableHeaderRef.value?.setTheDate(3)
if (dotList.value?.id) {
// tableStore.index()
}
}
const selectChange = () => {

View File

@@ -4,45 +4,46 @@
<template #select>
<el-form-item label="运行状态">
<el-select filterable multiple collapse-tags v-model="tableStore.table.params.runFlag" clearable
placeholder="请选择运行状态">
placeholder="请选择运行状态">
<el-option v-for="item in runFlagList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="通讯状态">
<el-select v-model="tableStore.table.params.comFlag" filterable multiple collapse-tags clearable
placeholder="请选择通讯状态">
placeholder="请选择通讯状态">
<el-option v-for="item in communicationstatus" :key="item.value" :label="item.label"
:value="item.value"></el-option>
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="电压等级">
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
placeholder="请选择电压等级" value-key="id">
placeholder="请选择电压等级" value-key="id">
<el-option v-for="item in voltageleveloption" :key="item.id" :label="item.name"
:value="item"></el-option>
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="终端厂家">
<el-select v-model="tableStore.table.params.manufacturer" filterable multiple collapse-tags
clearable placeholder="请选择终端厂家" value-key="id">
clearable placeholder="请选择终端厂家" value-key="id">
<el-option v-for="item in terminaloption" :key="item.id" :label="item.name"
:value="item"></el-option>
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="干扰源类型">
<el-select v-model="tableStore.table.params.loadType" filterable multiple collapse-tags clearable
placeholder="请选择干扰源类型" value-key="id">
placeholder="请选择干扰源类型" value-key="id">
<el-option v-for="item in interfereoption" :key="item.id" :label="item.name"
:value="item"></el-option>
:value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据筛选">
<el-input style="width: 240px" placeholder="电站名称,终端编号,监测点名称、电压等级、终端厂家、干扰源类型"
v-model="tableStore.table.params.searchValue" clearable maxlength="32"
show-word-limit></el-input>
<el-input style="width: 240px"
placeholder="电站名称,终端编号,监测点名称、电压等级、终端厂家、干扰源类型"
v-model="tableStore.table.params.searchValue" clearable maxlength="32"
show-word-limit></el-input>
</el-form-item>
</template>
@@ -51,6 +52,9 @@
</template>
</TableHeader>
<Table ref="tableRef" />
<!-- 限值查看弹框 -->
<LimitDialog ref="limitDialogRef" />
</div>
</template>
<script setup lang="ts">
@@ -58,14 +62,16 @@ import { ref, onMounted, provide, nextTick, watch } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import LimitDialog from './monitorLimit.vue'
import { useDictData } from '@/stores/dictData'
const dictData = useDictData()
const TableHeaderRef = ref()
const areaOptionList = dictData.getBasicData('jibei_area')
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
const interfereoption = dictData.getBasicData('Interference_Source')
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const limitDialogRef = ref()
const tableStore = new TableStore({
url: '/device-boot/runManage/getLineLedgerComm',
method: 'POST',
@@ -79,13 +85,22 @@ const tableStore = new TableStore({
}
},
{
field: 'areaName',
title: '省公司',
minWidth: 100
},
{
visible: !IS_LN,
field: 'areaName',
title: '省公司',
minWidth: 100
},
{ field: 'gdName', title: '市公司', minWidth: 150 },
{ visible: IS_LN,
field: 'gdName', title: '市公司', minWidth: 150, formatter: (row: any) => {
if (IS_LN) {
return row.cellValue.replace('国网', '').replace('供电公司', '')
} else {
return row.cellValue
}
}
},
{
field: 'bdName',
title: '所属变电站',
@@ -100,7 +115,7 @@ const tableStore = new TableStore({
}
},
{ field: 'lineName', title: '监测点名称', minWidth: 130 },
{ field: 'scale', title: '监测点电压等级', minWidth: 120 },
{ field: 'scale', title: '监测点电压等级', minWidth: 80 },
{ field: 'loadType', title: '干扰源类型', minWidth: 120 },
@@ -139,52 +154,53 @@ const tableStore = new TableStore({
{
field: 'shortCapacity',
title: '最小短路容量(MVA)',
minWidth: 150
minWidth: 100
},
{
field: 'devCapacity',
title: '供电设备容量(MVA )',
minWidth: 160
minWidth: 100
},
{
field: 'dealCapacity',
title: '用户协议容量(MVA)',
minWidth: 150
minWidth: 100
},
{ field: 'id', title: '监测点序号', minWidth: 90 },
{ field: 'id', title: '监测点序号', minWidth: 70 },
{ field: 'devName', title: '监测终端编号 ', minWidth: 140 },
{ field: 'ptType', title: '监测终端接线方式', minWidth: 140 },
{
field: 'voltageDev',
title: '电压偏差上限(%)',
minWidth: 140
minWidth: 80
},
{
field: 'uvoltageDev',
title: '电压偏差下限(%)',
minWidth: 140
}
minWidth: 80
},
/* {
title: '操作',fixed: 'right',
minWidth: 150,
{
title: '操作',
minWidth: 80,
fixed: 'right',
render: 'buttons',
buttons: [
{
name: 'productSetting',
title: '流程详情',
title: '查看限值',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
// 打开限值查看弹框
limitDialogRef.value?.open(row)
}
}
]
}*/
}
],
beforeSearchFun: () => {
@@ -209,7 +225,7 @@ tableStore.table.params.loadType = []
const runFlagList = [
{ id: 0, name: '投运' },
{ id: 1, name: '检修' },
{ id: 2, name: '停运' },
{ id: 2, name: '停运' }
]
@@ -224,5 +240,4 @@ onMounted(() => {
})
</script>

View File

@@ -0,0 +1,163 @@
<template>
<el-dialog
v-model="dialogVisible"
title="限值查看"
width="800px"
:close-on-click-modal="false"
destroy-on-close
>
<!-- 基本信息 -->
<div class="basic-info" style="margin-bottom: 20px; padding: 16px; background: #f5f7fa; border-radius: 4px;">
<el-row :gutter="20">
<el-col :span="8">
<div><strong>监测点名称</strong>{{ currentRow?.lineName || '-' }}</div>
</el-col>
<el-col :span="8">
<div><strong>监测对象名称</strong>{{ currentRow?.objName || '-' }}</div>
</el-col>
<el-col :span="8">
<div><strong>所属变电站</strong>{{ currentRow?.bdName || '-' }}</div>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 10px;">
<el-col :span="8">
<div><strong>电压等级</strong>{{ currentRow?.scale || '-' }}</div>
</el-col>
<el-col :span="8">
<div><strong>干扰源类型</strong>{{ currentRow?.loadType || '-' }}</div>
</el-col>
<el-col :span="8">
<div><strong>终端厂家</strong>{{ currentRow?.manufacturer || '-' }}</div>
</el-col>
</el-row>
</div>
<el-tabs v-model="activeTab">
<el-tab-pane label="电能质量限值" name="powerQuality">
<el-table :data="limitData" border style="width: 100%" max-height="400">
<el-table-column prop="name" label="参数名称" width="300" fixed />
<el-table-column prop="value" label="限值" width="300">
<template #default="{ row }">
<span>{{ row.value !== null && row.value !== undefined ? row.value + '%' : '-' }}</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="谐波电压限值" name="harmonicVoltage">
<el-table :data="harmonicVoltageData" border style="width: 100%" max-height="400">
<el-table-column prop="harmonic" label="谐波次数" width="300" />
<el-table-column prop="limit" label="限值(%)" width="300">
<template #default="{ row }">
<span>{{ row.limit || '-' }}</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="谐波电流限值" name="harmonicCurrent">
<el-table :data="harmonicCurrentData" border style="width: 100%" max-height="400">
<el-table-column prop="harmonic" label="谐波次数" width="300" />
<el-table-column prop="limit" label="限值(%)" width="300">
<template #default="{ row }">
<span>{{ row.limit || '-' }}</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const dialogVisible = ref(false)
const activeTab = ref('powerQuality')
const currentRow = ref<any>(null)
// 电能质量限值数据
const limitData = ref([
{ name: '频率偏差', value: 0.2 },
{ name: '电压偏差上限', value: null },
{ name: '电压偏差下限', value: null },
{ name: '电压不平衡度', value: 2 },
{ name: '闪变', value: 1 },
{ name: '电压波变', value: 3 },
{ name: '间谐波电压', value: 0.16 },
{ name: '负序电流', value: null },
])
// 谐波电压数据2-25次
const harmonicVoltageData = ref(
Array.from({ length: 24 }, (_, i) => {
const harmonicNumber = i + 2
let limit = 0
if (harmonicNumber <= 3) limit = 2.4
else if (harmonicNumber <= 5) limit = 1.2
else if (harmonicNumber <= 7) limit = 0.8
else if (harmonicNumber <= 9) limit = 0.6
else if (harmonicNumber <= 11) limit = 0.5
else if (harmonicNumber <= 13) limit = 0.4
else if (harmonicNumber <= 15) limit = 0.3
else if (harmonicNumber <= 17) limit = 0.2
else if (harmonicNumber <= 19) limit = 0.18
else limit = 0.15
return {
harmonic: `${harmonicNumber}`,
limit: limit
}
})
)
// 谐波电流数据2-25次
const harmonicCurrentData = ref(
Array.from({ length: 24 }, (_, i) => {
const harmonicNumber = i + 2
const limits = {
2: 16, 3: 13, 4: 8.1, 5: 13, 6: 5.4, 7: 9.3, 8: 4.1, 9: 4.3,
10: 3.3, 11: 5.9, 12: 2.7, 13: 5, 14: 2.3, 15: 2.6, 16: 2, 17: 3.8,
18: 1.8, 19: 3.4, 20: 1.6, 21: 1.9, 22: 1.5, 23: 2.8, 24: 1.4, 25: 2.6
}
return {
harmonic: `${harmonicNumber}`,
limit: limits[harmonicNumber as keyof typeof limits] || 0
}
})
)
// 打开弹框
const open = (row: any) => {
currentRow.value = row
// 更新电能质量限值数据
limitData.value.forEach(item => {
if (item.name === '电压偏差上限') {
item.value = row.voltageDev !== undefined ? row.voltageDev : null
} else if (item.name === '电压偏差下限') {
item.value = row.uvoltageDev !== undefined ? row.uvoltageDev : null
} else if (item.name === '负序电流') {
item.value = row.ineg !== undefined ? row.ineg : null
}
})
dialogVisible.value = true
}
defineExpose({
open
})
</script>
<style scoped lang="scss">
.dialog-footer {
display: flex;
justify-content: flex-end;
}
</style>

View File

@@ -128,6 +128,7 @@ const classificationData = dictData.getBasicData('Statistical_Type', ['Report_Ty
const voltageleveloption = dictData.getBasicData('Dev_Voltage_Stand')
const terminaloption = dictData.getBasicData('Dev_Manufacturers')
const interfereoption = dictData.getBasicData('Interference_Source')
const IS_LN = import.meta.env.VITE_NAME == 'LN' || import.meta.env.VITE_NAME == 'LNqr'
const communicationstatus = [
{ value: 0, label: '中断' },
@@ -150,8 +151,21 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'areaName', title: '区域', minWidth: 90 },
{ field: 'gdName', title: '市公司', minWidth: 110 },
{
visible: !IS_LN,
field: 'areaName',
title: '省公司',
minWidth: 100
},
{ visible: IS_LN,
field: 'gdName', title: '市公司', minWidth: 120, formatter: (row: any) => {
if (IS_LN) {
return row.cellValue.replace('国网', '').replace('供电公司', '')
} else {
return row.cellValue
}
}
},
{
field: 'bdName',
title: '变电站',

View File

@@ -90,6 +90,7 @@
</div>
<div
class="card-Box"
style="max-height: 100px;"
:style="`height:calc((${boxHeight.height} - 50px )/ 3);`"
v-for="val in item.children"
>
@@ -302,13 +303,14 @@ const countList: any = ref([
{
title: '网公司',
children: [
{ title: '非电网侧监测点', num: 0, onLineNum: 0, integrityRate: 0 },
{
title: '电网侧监测点',
num: 0,
onLineNum: 0,
integrityRate: 0
},
{ title: '非电网侧监测点', num: 0, onLineNum: 0, integrityRate: 0 }
]
},
{
@@ -395,8 +397,8 @@ const info = async (row: any) => {
})
// 监测点指标统计
getGridDiagramStatistics(form).then(res => {
countList.value[0].children[0] = { title: '电网侧监测点', ...res.data.data[0] }
countList.value[0].children[1] = { title: '电网侧监测点', ...res.data.data[1] }
countList.value[0].children[0] = { title: '电网侧监测点', ...res.data.data[1] }
countList.value[0].children[1] = { title: '电网侧监测点', ...res.data.data[0] }
countList.value[1].children[0] = { title: '电网侧监测点', ...res.data.gwData[0] }
})
// 监测运行统计

File diff suppressed because it is too large Load Diff

View File

@@ -85,11 +85,7 @@ const active: any = ref(1)
const evaluationData: any = ref([])
const dictData = useDictData()
const Voltage: any = dictData.getBasicData('Dev_Voltage_Stand').filter(item => {
if (item.code == '35kV' || item.code == '500kV' || item.code == '220kV' || item.code == '110kV') {
return item
}
})
const Voltage: any = dictData.getBasicData('Panoramic_voltage')
const chartRef = ref<HTMLDivElement>()
const url: any = [

View File

@@ -83,6 +83,7 @@
</div>
<div
class="card-Box"
style="max-height: 100px;"
:style="`height:calc((${boxHeight.height} - 50px )/ 3);`"
v-for="val in item.children"
>
@@ -339,13 +340,14 @@ const countList: any = ref([
{
title: '网公司',
children: [
{ title: '非电网侧监测点', num: 0, onLineNum: 0, integrityRate: 0 },
{
title: '电网侧监测点',
num: 0,
onLineNum: 0,
integrityRate: 0
},
{ title: '非电网侧监测点', num: 0, onLineNum: 0, integrityRate: 0 }
]
},
{
@@ -464,8 +466,8 @@ const info = async (row: any) => {
})
// 监测点指标统计
getGridDiagramStatistics(form).then(res => {
countList.value[0].children[0] = { title: '电网侧监测点', ...res.data.data[0] }
countList.value[0].children[1] = { title: '电网侧监测点', ...res.data.data[1] }
countList.value[0].children[0] = { title: '电网侧监测点', ...res.data.data[1] }
countList.value[0].children[1] = { title: '电网侧监测点', ...res.data.data[0] }
countList.value[1].children[0] = { title: '电网侧监测点', ...res.data.gwData[0] }
})
// 监测运行统计

View File

@@ -12,15 +12,15 @@
</template>
<div class="text">
<span style="color: #00B07D">无污染0</span>
<span style="color: #00B07D">优秀:(4.5,5]</span>
<br />
<span style="color: #3399ff">轻微污染(0 , 100]</span>
<span style="color: #3399ff">良好:(4,4.5]</span>
<br />
<span style="color: #ffcc33">轻度污染(100 , 1000]</span>
<span style="color: #ffcc33">合格:(3,4]</span>
<br />
<span style="color: #ff9900">中度污染(1000 , 10000]</span>
<span style="color: #ff9900">较差:(2,3]</span>
<br />
<span style="color: #A52a2a">重度污染(10000</span>
<span style="color: #A52a2a">极差:[1,2]</span>
</div>
</el-popover>
</span>
@@ -169,7 +169,7 @@
</div>
</div>
<!-- 技术监督管理 -->
<div>
<!-- <div>
<div class="title">
<span>技术监督统计</span>
<span class="info" @click="open(3)">
@@ -221,7 +221,7 @@
</el-col>
</el-row>
</div>
</div>
</div> -->
</div>
<img
class="imgR"
@@ -266,8 +266,8 @@ import {
const dictData = useDictData()
const show = ref(false)
const height = mainHeight(30)
const boxHeight: any = mainHeight(420, 2)
const EchHeight: any = mainHeight(510, 2)
const boxHeight: any = mainHeight(230, 2)
const EchHeight: any = mainHeight(320, 2)
const evaluateRef = ref()
const steadyStateRef = ref()
const formRow: any = ref({})

View File

@@ -90,6 +90,7 @@ const tableStore = new TableStore({
{ field: 'devType', title: '终端型号', minWidth: 100 },
{ field: 'ip', title: '终端网络参数', width: '120px' },
{ field: 'powerFlag', title: '用户性质', width: '120px' },
{ field: 'port', title: '端口号', minWidth: 70 },
{
field: 'comFlag',

View File

@@ -150,21 +150,8 @@ const tableStore = new TableStore({
return row.cellValue ? row.cellValue : '/'
}
},
{
field: 'shortCapacity',
title: '最小短路容量(MVA)',
minWidth: 150
},
{
field: 'devCapacity',
title: '供电设备容量(MVA )',
minWidth: 160
},
{
field: 'dealCapacity',
title: '用户协议容量(MVA)',
minWidth: 150
},
{ field: 'powerFlag', title: '用户性质', width: '120px' },
/* { field: 'comFlag', title: '通讯状态 ', minWidth: 120 },*/
{ field: 'id', title: '监测点序号', minWidth: 90 },
{
@@ -182,6 +169,21 @@ const tableStore = new TableStore({
},
{ field: 'devName', title: '监测终端编号 ', minWidth: 140 },
{ field: 'ptType', title: '监测终端接线方式', minWidth: 140 },
{
field: 'shortCapacity',
title: '最小短路容量(MVA)',
minWidth: 150
},
{
field: 'devCapacity',
title: '供电设备容量(MVA )',
minWidth: 160
},
{
field: 'dealCapacity',
title: '用户协议容量(MVA)',
minWidth: 150
},
{
field: 'voltageDev',
title: '电压偏差上限(%)',