Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f907a80c4 |
@@ -154,7 +154,7 @@ const tableStore: any = new TableStore({
|
|||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
name: '越限占比',
|
name: '指标越限严重度',
|
||||||
data: tableStore.table.data.map((item: any) => Math.floor(item.extent * 100) / 100),
|
data: tableStore.table.data.map((item: any) => Math.floor(item.extent * 100) / 100),
|
||||||
barMaxWidth: 30
|
barMaxWidth: 30
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, provide, reactive, watch, h, computed, nextTick } from 'vue'
|
import { ref, onMounted, onUnmounted, provide, reactive, watch, h, computed, nextTick } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import { exportExcel } from '@/views/govern/reportForms/export.js'
|
import { exportExcel } from '@/views/govern/reportForms/export.js'
|
||||||
|
import { destroyLuckysheet, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||||
import TableHeader from '@/components/table/header/index.vue'
|
import TableHeader from '@/components/table/header/index.vue'
|
||||||
import { querySysExcel } from '@/api/harmonic-boot/luckyexcel'
|
import { querySysExcel } from '@/api/harmonic-boot/luckyexcel'
|
||||||
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||||
@@ -119,6 +120,9 @@ const downloadExcel = () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initListByIds()
|
initListByIds()
|
||||||
})
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroyLuckysheet()
|
||||||
|
})
|
||||||
|
|
||||||
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
|
const selectChange = (showSelect: any, height: any, datePickerValue?: any) => {
|
||||||
if (datePickerValue && datePickerValue.timeValue) {
|
if (datePickerValue && datePickerValue.timeValue) {
|
||||||
@@ -159,16 +163,7 @@ const tableStore: any = new TableStore({
|
|||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
loadCallback: () => {
|
loadCallback: () => {
|
||||||
luckysheet.create({
|
renderLuckysheetReport('luckysheet', tableStore.table.data, { allowEdit: false })
|
||||||
container: 'luckysheet',
|
|
||||||
title: '', // 表 头名
|
|
||||||
lang: 'zh', // 中文
|
|
||||||
showtoolbar: false, // 是否显示工具栏
|
|
||||||
showinfobar: false, // 是否显示顶部信息栏
|
|
||||||
showsheetbar: true, // 是否显示底部sheet按钮
|
|
||||||
allowEdit: false, // 禁止所有编辑操作(必填)
|
|
||||||
data: tableStore.table.data
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ const tableStore: any = new TableStore({
|
|||||||
icon: 'el-icon-DataLine',
|
icon: 'el-icon-DataLine',
|
||||||
render: 'basicButton',
|
render: 'basicButton',
|
||||||
disabled: row => {
|
disabled: row => {
|
||||||
return !!row.wavePath
|
return row.wavePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ const tableStore: any = new TableStore({
|
|||||||
icon: 'el-icon-DataLine',
|
icon: 'el-icon-DataLine',
|
||||||
render: 'basicButton',
|
render: 'basicButton',
|
||||||
disabled: row => {
|
disabled: row => {
|
||||||
return !!row.wavePath
|
return row.wavePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ const fliteWaveData = (wp, step, iphasicValue, isOpen) => {
|
|||||||
|
|
||||||
// 监听消息
|
// 监听消息
|
||||||
self.onmessage = function (e) {
|
self.onmessage = function (e) {
|
||||||
const { wp, isOpen, value, boxoList } = JSON.parse(e.data)
|
const { wp, isOpen, value, boxoList, requestId } = e.data
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const iphasicValue = wp.iphasic || 1
|
const iphasicValue = wp.iphasic || 1
|
||||||
@@ -303,6 +303,7 @@ self.onmessage = function (e) {
|
|||||||
}
|
}
|
||||||
// 发送处理结果回主线程
|
// 发送处理结果回主线程
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
|
requestId,
|
||||||
titles: titles,
|
titles: titles,
|
||||||
success: true,
|
success: true,
|
||||||
waveDatas,
|
waveDatas,
|
||||||
@@ -313,6 +314,7 @@ self.onmessage = function (e) {
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
|
requestId,
|
||||||
success: false,
|
success: false,
|
||||||
error: error.message
|
error: error.message
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,9 +14,15 @@ import html2canvas from 'html2canvas'
|
|||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { mainHeight } from '@/utils/layout'
|
import { mainHeight } from '@/utils/layout'
|
||||||
|
import { calcRmsYAxisRange, formatAxisLabel } from '@/utils/chartAxisHelper'
|
||||||
import url from '@/assets/img/point.png'
|
import url from '@/assets/img/point.png'
|
||||||
import url2 from '@/assets/img/dw.png'
|
import url2 from '@/assets/img/dw.png'
|
||||||
const worker = ref<Worker | null>(null)
|
import { buildWaveCacheKey, getWaveCache, setWaveCache } from '@/utils/waveCache'
|
||||||
|
import { getRmsWorker, buildWorkerPayload } from '@/utils/waveWorkerPool'
|
||||||
|
|
||||||
|
let waveRequestId = 0
|
||||||
|
const pendingCacheKeys = new Map<number, string>()
|
||||||
|
let rmsWorker: Worker | null = null
|
||||||
interface WaveData {
|
interface WaveData {
|
||||||
instantF: { max: number; min: number }
|
instantF: { max: number; min: number }
|
||||||
instantS: { max: number; min: number }
|
instantS: { max: number; min: number }
|
||||||
@@ -125,26 +131,19 @@ const vw = computed(() => '100%')
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
newVal => {
|
() => {
|
||||||
if (newVal == 2) {
|
query()
|
||||||
initWaves()
|
|
||||||
} else {
|
|
||||||
$('#wave1').remove()
|
|
||||||
initWaves()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
watch(
|
||||||
const zoomValue = document.body.style.getPropertyValue('zoom')
|
() => props.wp,
|
||||||
zoom.value = 1 / (zoomValue ? parseFloat(zoomValue) : 1)
|
() => {
|
||||||
window.addEventListener('resize', handleResize)
|
query()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// 初始化 Web Worker
|
const applyWorkerResult = (data: any) => {
|
||||||
worker.value = new Worker(new URL('./rmsWorker.js', import.meta.url))
|
|
||||||
worker.value.onmessage = e => {
|
|
||||||
if (e.data.success) {
|
|
||||||
const data = e.data
|
|
||||||
titles.value = data.titles
|
titles.value = data.titles
|
||||||
waveDatas.value = data.waveDatas
|
waveDatas.value = data.waveDatas
|
||||||
time.value = data.time
|
time.value = data.time
|
||||||
@@ -152,25 +151,41 @@ onMounted(() => {
|
|||||||
severity.value = data.severity
|
severity.value = data.severity
|
||||||
iphasic.value = data.iphasic
|
iphasic.value = data.iphasic
|
||||||
|
|
||||||
// 初始化波形图
|
if (Number(severity.value) < 0) {
|
||||||
initWave(waveDatas.value, time.value, type.value, severity.value, isOpen.value)
|
severity.value = '/'
|
||||||
} else {
|
type.value = '/'
|
||||||
console.error('Worker error:', e.data.error)
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initWave(waveDatas.value, time.value, type.value, severity.value, isOpen.value)
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const zoomValue = document.body.style.getPropertyValue('zoom')
|
||||||
|
zoom.value = 1 / (zoomValue ? parseFloat(zoomValue) : 1)
|
||||||
|
window.addEventListener('resize', handleResize)
|
||||||
|
|
||||||
|
rmsWorker = getRmsWorker(data => {
|
||||||
|
if (data.requestId !== waveRequestId) return
|
||||||
|
if (!data.success) {
|
||||||
|
console.error('Worker error:', data.error)
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const cacheKey = pendingCacheKeys.get(data.requestId)
|
||||||
|
if (cacheKey) {
|
||||||
|
setWaveCache(cacheKey, data)
|
||||||
|
pendingCacheKeys.delete(data.requestId)
|
||||||
|
}
|
||||||
|
applyWorkerResult(data)
|
||||||
|
})
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTimeout(() => {
|
|
||||||
query()
|
query()
|
||||||
}, 500)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
if (worker.value) {
|
|
||||||
worker.value.terminate()
|
|
||||||
}
|
|
||||||
backbxlb()
|
backbxlb()
|
||||||
window.removeEventListener('resize', handleResize)
|
window.removeEventListener('resize', handleResize)
|
||||||
})
|
})
|
||||||
@@ -195,23 +210,15 @@ const download = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EXTRA_PANEL_CLASS = 'wave-extra-panel'
|
||||||
|
|
||||||
|
const resetWaveDom = () => {
|
||||||
|
backbxlb()
|
||||||
|
$('#rmsp').nextAll(`.${EXTRA_PANEL_CLASS}`).remove()
|
||||||
|
}
|
||||||
|
|
||||||
const query = () => {
|
const query = () => {
|
||||||
loading.value = true
|
initWaves()
|
||||||
if (props.wp) {
|
|
||||||
// 使用 Worker 处理数据
|
|
||||||
if (worker.value) {
|
|
||||||
worker.value.postMessage(
|
|
||||||
JSON.stringify({
|
|
||||||
wp: props.wp,
|
|
||||||
isOpen: isOpen.value,
|
|
||||||
value: props.value,
|
|
||||||
boxoList: props.boxoList
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
initWave(null, null, null, null, null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const waveData = (
|
const waveData = (
|
||||||
@@ -245,29 +252,31 @@ const waveData = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initWaves = () => {
|
const initWaves = () => {
|
||||||
if (props.wp) {
|
if (!props.wp?.listRmsData?.length) {
|
||||||
iphasic.value = props.wp.iphasic || 1
|
|
||||||
const picCounts = (props.wp.waveTitle.length - 1) / iphasic.value
|
|
||||||
waveDatas.value = []
|
|
||||||
|
|
||||||
for (let i = 0; i < picCounts; i++) {
|
|
||||||
const data = fliteWaveData(props.wp, i)
|
|
||||||
waveDatas.value.push(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.value = props.wp.time
|
|
||||||
type.value = props.wp.waveType
|
|
||||||
severity.value = props.wp.yzd
|
|
||||||
|
|
||||||
if (Number(severity.value) < 0) {
|
|
||||||
severity.value = '/'
|
|
||||||
type.value = '/'
|
|
||||||
}
|
|
||||||
|
|
||||||
initWave(waveDatas.value, time.value, type.value, severity.value, isOpen.value)
|
|
||||||
} else {
|
|
||||||
initWave(null, null, null, null, null)
|
initWave(null, null, null, null, null)
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cacheKey = buildWaveCacheKey('rms', props.wp, props.value, isOpen.value, props.boxoList)
|
||||||
|
const cached = getWaveCache<any>(cacheKey)
|
||||||
|
if (cached) {
|
||||||
|
applyWorkerResult(cached)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
iphasic.value = props.wp.iphasic || 1
|
||||||
|
const currentRequestId = ++waveRequestId
|
||||||
|
pendingCacheKeys.set(currentRequestId, cacheKey)
|
||||||
|
|
||||||
|
rmsWorker?.postMessage(
|
||||||
|
buildWorkerPayload('rms', props.wp, props.boxoList, {
|
||||||
|
requestId: currentRequestId,
|
||||||
|
value: props.value,
|
||||||
|
isOpen: isOpen.value
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fliteWaveData = (wp: any, step: number): WaveData => {
|
const fliteWaveData = (wp: any, step: number): WaveData => {
|
||||||
@@ -482,7 +491,7 @@ const initWave = (
|
|||||||
severity: string | null,
|
severity: string | null,
|
||||||
isOpen: boolean | null
|
isOpen: boolean | null
|
||||||
) => {
|
) => {
|
||||||
$('div.bx').remove()
|
resetWaveDom()
|
||||||
|
|
||||||
let picHeight = vh.value
|
let picHeight = vh.value
|
||||||
const show = !isOpen
|
const show = !isOpen
|
||||||
@@ -594,7 +603,7 @@ const initWave = (
|
|||||||
for (let step = waveDatas.length - 1; step > 0 && step < waveDatas.length; step--) {
|
for (let step = waveDatas.length - 1; step > 0 && step < waveDatas.length; step--) {
|
||||||
const rmsId = 'rms' + step
|
const rmsId = 'rms' + step
|
||||||
const newDivRms = $(
|
const newDivRms = $(
|
||||||
`<div style="height:${vh.value};overflow: hidden;min-height: 200px;"><div class='bx' id='${rmsId}'></div></div>`
|
`<div class="${EXTRA_PANEL_CLASS}" style="height:${vh.value};overflow: hidden;min-height: 200px;"><div class='bx' id='${rmsId}'></div></div>`
|
||||||
)
|
)
|
||||||
newDivRms.insertAfter($('#rmsp'))
|
newDivRms.insertAfter($('#rmsp'))
|
||||||
$(`#${rmsId}`).css('height', picHeight).css('width', vw.value).css('min-height', '200px')
|
$(`#${rmsId}`).css('height', picHeight).css('width', vw.value).css('min-height', '200px')
|
||||||
@@ -607,6 +616,12 @@ const initWave = (
|
|||||||
const rms = document.getElementById('rmsp')
|
const rms = document.getElementById('rmsp')
|
||||||
|
|
||||||
if (!rms) return
|
if (!rms) return
|
||||||
|
|
||||||
|
const yRange = calcRmsYAxisRange(rmscu[0]?.[1] ?? 0, rmscm[0]?.[1] ?? 0)
|
||||||
|
|
||||||
|
const existingChart = echarts.getInstanceByDom(rms)
|
||||||
|
if (existingChart) existingChart.dispose()
|
||||||
|
|
||||||
const myChartes = echarts.init(rms)
|
const myChartes = echarts.init(rms)
|
||||||
const echartsColor = {
|
const echartsColor = {
|
||||||
WordColor: '#000',
|
WordColor: '#000',
|
||||||
@@ -750,8 +765,8 @@ const initWave = (
|
|||||||
},
|
},
|
||||||
// max: rmscm[0]?.[1] * 1.06 || 0,
|
// max: rmscm[0]?.[1] * 1.06 || 0,
|
||||||
// min: rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0,
|
// min: rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0,
|
||||||
max: Math.floor((rmscm[0]?.[1] * 1.06 || 0) * 1.1 * 10) / 10,
|
max: yRange.max,
|
||||||
min: Math.floor((rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0) * 10) / 10,
|
min: yRange.min,
|
||||||
boundaryGap: [0, '100%'],
|
boundaryGap: [0, '100%'],
|
||||||
showLastLabel: true,
|
showLastLabel: true,
|
||||||
opposite: false,
|
opposite: false,
|
||||||
@@ -770,7 +785,7 @@ const initWave = (
|
|||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
color: props.DColor ? '#000' : echartsColor.WordColor,
|
color: props.DColor ? '#000' : echartsColor.WordColor,
|
||||||
formatter: function (value: number) {
|
formatter: function (value: number) {
|
||||||
return Math.floor(value * 1000) / 1000
|
return formatAxisLabel(value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
@@ -955,6 +970,10 @@ const drawPics = (
|
|||||||
const rmsIds = document.getElementById(rmsId)
|
const rmsIds = document.getElementById(rmsId)
|
||||||
if (!rmsIds) return
|
if (!rmsIds) return
|
||||||
|
|
||||||
|
const subMin = props.value === 1 ? waveDataTemp.RMSF.min : waveDataTemp.RMSS.min
|
||||||
|
const subMax = props.value === 1 ? waveDataTemp.RMSF.max : waveDataTemp.RMSS.max
|
||||||
|
const yRange = calcRmsYAxisRange(subMin, subMax)
|
||||||
|
|
||||||
const myChartes = echarts.init(rmsIds)
|
const myChartes = echarts.init(rmsIds)
|
||||||
const echartsColor = {
|
const echartsColor = {
|
||||||
WordColor: '#000',
|
WordColor: '#000',
|
||||||
@@ -1078,6 +1097,8 @@ const drawPics = (
|
|||||||
},
|
},
|
||||||
boundaryGap: [0, '100%'],
|
boundaryGap: [0, '100%'],
|
||||||
showLastLabel: true,
|
showLastLabel: true,
|
||||||
|
max: yRange.max,
|
||||||
|
min: yRange.min,
|
||||||
opposite: false,
|
opposite: false,
|
||||||
// max: Math.floor((rmscm[0]?.[1] * 1.06 || 0) * 1.1 * 10) / 10,
|
// max: Math.floor((rmscm[0]?.[1] * 1.06 || 0) * 1.1 * 10) / 10,
|
||||||
// min: Math.floor((rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0) * 10) / 10,
|
// min: Math.floor((rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0) * 10) / 10,
|
||||||
@@ -1096,8 +1117,7 @@ const drawPics = (
|
|||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
color: props.DColor ? '#000' : echartsColor.WordColor,
|
color: props.DColor ? '#000' : echartsColor.WordColor,
|
||||||
formatter: function (value: number) {
|
formatter: function (value: number) {
|
||||||
// return (value - 0).toFixed(2)
|
return formatAxisLabel(value)
|
||||||
return Math.floor(value * 1000) / 1000
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
@@ -1213,12 +1233,7 @@ const backbxlb = () => {
|
|||||||
myChartess4.value = null
|
myChartess4.value = null
|
||||||
myChartess5.value = null
|
myChartess5.value = null
|
||||||
|
|
||||||
// echarts.disconnect(charts.filter(Boolean) as echarts.ECharts[])
|
$('#rmsp').nextAll(`.${EXTRA_PANEL_CLASS}`).remove()
|
||||||
charts.filter(Boolean).forEach(chart => {
|
|
||||||
if (chart && typeof chart.dispose === 'function') {
|
|
||||||
chart.dispose()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMax = (temp: number, tempA: number, tempB: number, tempC: number): number => {
|
const getMax = (temp: number, tempA: number, tempB: number, tempC: number): number => {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
// waveData.worker.js
|
// waveData.worker.js
|
||||||
self.addEventListener('message', function (e) {
|
self.addEventListener('message', function (e) {
|
||||||
const { wp, value, iphasic, isOpen, boxoList } = JSON.parse(e.data)
|
const { wp, value, iphasic, isOpen, boxoList, requestId } = e.data
|
||||||
|
|
||||||
// 处理波形数据的函数
|
// 处理波形数据的函数
|
||||||
const fliteWaveData = (wp, step) => {
|
const fliteWaveData = (wp, step) => {
|
||||||
@@ -195,6 +195,8 @@ self.addEventListener('message', function (e) {
|
|||||||
|
|
||||||
// 将处理结果发送回主线程
|
// 将处理结果发送回主线程
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
|
requestId,
|
||||||
|
success: true,
|
||||||
waveDatas,
|
waveDatas,
|
||||||
time,
|
time,
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading" class="boxbx" style="position: relative; height: 100%">
|
<div v-loading="loading" class="boxbx" style="position: relative; height: 100%">
|
||||||
<div id="boxsj">
|
<div id="boxsj">
|
||||||
<div id="shushi" :style="`height:${vh};overflow: hidden;min-height: 200px;`">
|
<div id="shushi" :style="containerStyle">
|
||||||
<div class="bx" id="wave" style="min-height: 200px"></div>
|
<div class="bx" id="wave" :style="waveStyle"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -14,9 +14,14 @@ import html2canvas from 'html2canvas'
|
|||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { mainHeight } from '@/utils/layout'
|
import { mainHeight } from '@/utils/layout'
|
||||||
|
import { calcShuYAxisRange, formatAxisLabel } from '@/utils/chartAxisHelper'
|
||||||
import url from '@/assets/img/point.png'
|
import url from '@/assets/img/point.png'
|
||||||
// 创建Worker
|
import { buildWaveCacheKey, getWaveCache, setWaveCache } from '@/utils/waveCache'
|
||||||
let waveDataWorker: Worker | null = null
|
import { getShuWorker, buildWorkerPayload } from '@/utils/waveWorkerPool'
|
||||||
|
|
||||||
|
let waveRequestId = 0
|
||||||
|
const pendingCacheKeys = new Map<number, string>()
|
||||||
|
let shuWorker: Worker | null = null
|
||||||
interface WaveData {
|
interface WaveData {
|
||||||
instantF: { max: number; min: number }
|
instantF: { max: number; min: number }
|
||||||
instantS: { max: number; min: number }
|
instantS: { max: number; min: number }
|
||||||
@@ -110,38 +115,82 @@ const vh = computed(() => {
|
|||||||
|
|
||||||
const vw = computed(() => '100%')
|
const vw = computed(() => '100%')
|
||||||
|
|
||||||
|
const containerStyle = computed(() => ({
|
||||||
|
height: vh.value,
|
||||||
|
overflow: 'hidden',
|
||||||
|
minHeight: '200px'
|
||||||
|
}))
|
||||||
|
|
||||||
|
const waveStyle = computed(() => ({
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
minHeight: '200px'
|
||||||
|
}))
|
||||||
|
|
||||||
|
const applyChartSize = (el: HTMLElement) => {
|
||||||
|
el.style.width = '100%'
|
||||||
|
el.style.height = vh.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const finishChartRender = (chart: echarts.ECharts, endLoading = false) => {
|
||||||
|
nextTick(() => {
|
||||||
|
chart.resize()
|
||||||
|
if (endLoading) {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
newVal => {
|
() => {
|
||||||
if (newVal == 2) {
|
query()
|
||||||
initWaves()
|
|
||||||
} else {
|
|
||||||
$('#wave1').remove()
|
|
||||||
initWaves()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.wp,
|
||||||
|
() => {
|
||||||
|
query()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const zoomValue = document.body.style.getPropertyValue('zoom')
|
const zoomValue = document.body.style.getPropertyValue('zoom')
|
||||||
zoom.value = 1 / (zoomValue ? parseFloat(zoomValue) : 1)
|
zoom.value = 1 / (zoomValue ? parseFloat(zoomValue) : 1)
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize)
|
window.addEventListener('resize', handleResize)
|
||||||
|
shuWorker = getShuWorker(data => {
|
||||||
|
if (data.requestId !== waveRequestId) return
|
||||||
|
if (!data.success) {
|
||||||
|
console.error('Worker error:', data.error)
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const cacheKey = pendingCacheKeys.get(data.requestId)
|
||||||
|
if (cacheKey) {
|
||||||
|
setWaveCache(cacheKey, data)
|
||||||
|
pendingCacheKeys.delete(data.requestId)
|
||||||
|
}
|
||||||
|
applyWorkerResult(data)
|
||||||
|
})
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTimeout(() => {
|
|
||||||
query()
|
query()
|
||||||
}, 500)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
console.log('组件卸载')
|
|
||||||
|
|
||||||
if (waveDataWorker) {
|
|
||||||
waveDataWorker.terminate()
|
|
||||||
waveDataWorker = null
|
|
||||||
}
|
|
||||||
|
|
||||||
backbxlb()
|
backbxlb()
|
||||||
window.removeEventListener('resize', handleResize)
|
window.removeEventListener('resize', handleResize)
|
||||||
})
|
})
|
||||||
@@ -166,6 +215,13 @@ const download = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EXTRA_PANEL_CLASS = 'wave-extra-panel'
|
||||||
|
|
||||||
|
const resetWaveDom = () => {
|
||||||
|
backbxlb()
|
||||||
|
$('#shushi').nextAll(`.${EXTRA_PANEL_CLASS}`).remove()
|
||||||
|
}
|
||||||
|
|
||||||
const query = () => {
|
const query = () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
initWaves()
|
initWaves()
|
||||||
@@ -184,48 +240,32 @@ const waveData = (instantF: any, instantS: any, shunshiF: any, shunshiS: any, ti
|
|||||||
|
|
||||||
// 在组件中修改initWaves函数
|
// 在组件中修改initWaves函数
|
||||||
const initWaves = () => {
|
const initWaves = () => {
|
||||||
if (props.wp) {
|
if (!props.wp?.listWaveData?.length) {
|
||||||
|
initWave(null, null, null, null, null)
|
||||||
|
loading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheKey = buildWaveCacheKey('shu', props.wp, props.value, isOpen.value, props.boxoList)
|
||||||
|
const cached = getWaveCache<any>(cacheKey)
|
||||||
|
if (cached) {
|
||||||
|
applyWorkerResult(cached)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
iphasic.value = props.wp.iphasic || 1
|
iphasic.value = props.wp.iphasic || 1
|
||||||
// 使用Web Worker处理数据
|
const currentRequestId = ++waveRequestId
|
||||||
if (!waveDataWorker) {
|
pendingCacheKeys.set(currentRequestId, cacheKey)
|
||||||
waveDataWorker = new Worker(new URL('./shuWorker.js', import.meta.url))
|
|
||||||
|
|
||||||
waveDataWorker.onmessage = function (e) {
|
shuWorker?.postMessage(
|
||||||
const data = e.data
|
buildWorkerPayload('shu', props.wp, props.boxoList, {
|
||||||
|
requestId: currentRequestId,
|
||||||
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)
|
|
||||||
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
waveDataWorker.onerror = function (error) {
|
|
||||||
console.error('Worker error:', error)
|
|
||||||
loading.value = false
|
|
||||||
// 备用方案:在主线程处理数据
|
|
||||||
// processDataInMainThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送数据到Worker
|
|
||||||
waveDataWorker.postMessage(
|
|
||||||
JSON.stringify({
|
|
||||||
wp: props.wp,
|
|
||||||
value: props.value,
|
value: props.value,
|
||||||
iphasic: iphasic.value,
|
|
||||||
isOpen: isOpen.value,
|
isOpen: isOpen.value,
|
||||||
boxoList: props.boxoList
|
iphasic: iphasic.value
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
initWave(null, null, null, null, null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const initWave = (
|
const initWave = (
|
||||||
@@ -235,6 +275,7 @@ const initWave = (
|
|||||||
severity: string | null,
|
severity: string | null,
|
||||||
isOpen: boolean | null
|
isOpen: boolean | null
|
||||||
) => {
|
) => {
|
||||||
|
resetWaveDom()
|
||||||
$('div.bx1').remove()
|
$('div.bx1').remove()
|
||||||
|
|
||||||
let picHeight = vh.value
|
let picHeight = vh.value
|
||||||
@@ -327,7 +368,7 @@ const initWave = (
|
|||||||
|
|
||||||
for (let step = waveDatas.length - 1; step > 0 && step < waveDatas.length; step--) {
|
for (let step = waveDatas.length - 1; step > 0 && step < waveDatas.length; step--) {
|
||||||
const waveId = 'wave' + step
|
const waveId = 'wave' + step
|
||||||
const newDivShunshi = $(`<div style="height:${vh.value};overflow: hidden;min-height: 200px;">
|
const newDivShunshi = $(`<div class="${EXTRA_PANEL_CLASS}" style="height:${vh.value};overflow: hidden;min-height: 200px;">
|
||||||
<div class='bx1' id='${waveId}'></div>
|
<div class='bx1' id='${waveId}'></div>
|
||||||
</div>`)
|
</div>`)
|
||||||
newDivShunshi.insertAfter($('#shushi'))
|
newDivShunshi.insertAfter($('#shushi'))
|
||||||
@@ -342,6 +383,13 @@ const initWave = (
|
|||||||
const wave = document.getElementById('wave')
|
const wave = document.getElementById('wave')
|
||||||
if (!wave) return
|
if (!wave) return
|
||||||
|
|
||||||
|
applyChartSize(wave)
|
||||||
|
|
||||||
|
const yRange = calcShuYAxisRange(Number(min), Number(max))
|
||||||
|
|
||||||
|
const existingChart = echarts.getInstanceByDom(wave)
|
||||||
|
if (existingChart) existingChart.dispose()
|
||||||
|
|
||||||
const myChartes = echarts.init(wave)
|
const myChartes = echarts.init(wave)
|
||||||
const echartsColor = {
|
const echartsColor = {
|
||||||
WordColor: '#000',
|
WordColor: '#000',
|
||||||
@@ -363,11 +411,6 @@ const initWave = (
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
wave.style.width = '100%'
|
|
||||||
wave.style.height = vh.value
|
|
||||||
}, 0)
|
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
top: '10px',
|
top: '10px',
|
||||||
@@ -481,10 +524,8 @@ const initWave = (
|
|||||||
},
|
},
|
||||||
boundaryGap: [0, '100%'],
|
boundaryGap: [0, '100%'],
|
||||||
showLastLabel: true,
|
showLastLabel: true,
|
||||||
// max: max.toFixed(2) * 1.1,
|
max: yRange.max,
|
||||||
// min: min.toFixed(2) > 0 ? min.toFixed(2) - min.toFixed(2) * 0.1 : min.toFixed(2) * 1.1,
|
min: yRange.min,
|
||||||
max: Math.floor(max.toFixed(2) * 1.1 * 10) / 10,
|
|
||||||
min: Math.floor(min.toFixed(2) > 0 ? min.toFixed(2) - min.toFixed(2) * 0.1 : min.toFixed(2) * 1.1 * 10) / 10 ,
|
|
||||||
opposite: false,
|
opposite: false,
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
@@ -501,8 +542,7 @@ const initWave = (
|
|||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
color: props.DColor ? '#000' : echartsColor.WordColor,
|
color: props.DColor ? '#000' : echartsColor.WordColor,
|
||||||
formatter: function (value: number) {
|
formatter: function (value: number) {
|
||||||
// return (value - 0).toFixed(2)
|
return formatAxisLabel(value)
|
||||||
return Math.floor(value * 1000) / 1000
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
@@ -518,7 +558,6 @@ const initWave = (
|
|||||||
right: '45px',
|
right: '45px',
|
||||||
bottom: '40px',
|
bottom: '40px',
|
||||||
top: '60px'
|
top: '60px'
|
||||||
// containLabel: true
|
|
||||||
},
|
},
|
||||||
dataZoom: [
|
dataZoom: [
|
||||||
{
|
{
|
||||||
@@ -578,11 +617,7 @@ const initWave = (
|
|||||||
|
|
||||||
myChartes.setOption(option)
|
myChartes.setOption(option)
|
||||||
myChartess.value = myChartes
|
myChartess.value = myChartes
|
||||||
|
finishChartRender(myChartes, true)
|
||||||
setTimeout(() => {
|
|
||||||
myChartes.resize()
|
|
||||||
loading.value = false
|
|
||||||
}, 400)
|
|
||||||
|
|
||||||
if (waveDatas && waveDatas.length > 1) {
|
if (waveDatas && waveDatas.length > 1) {
|
||||||
const waveDatasTemp = waveDatas.slice(1)
|
const waveDatasTemp = waveDatas.slice(1)
|
||||||
@@ -679,6 +714,13 @@ const drawPics = (
|
|||||||
const waveIds = document.getElementById(waveId)
|
const waveIds = document.getElementById(waveId)
|
||||||
if (!waveIds) return
|
if (!waveIds) return
|
||||||
|
|
||||||
|
applyChartSize(waveIds)
|
||||||
|
|
||||||
|
const yRange = calcShuYAxisRange(Number(min), Number(max))
|
||||||
|
|
||||||
|
const existingChart = echarts.getInstanceByDom(waveIds)
|
||||||
|
if (existingChart) existingChart.dispose()
|
||||||
|
|
||||||
const myChartes = echarts.init(waveIds)
|
const myChartes = echarts.init(waveIds)
|
||||||
const echartsColor = {
|
const echartsColor = {
|
||||||
WordColor: '#000',
|
WordColor: '#000',
|
||||||
@@ -791,8 +833,8 @@ const drawPics = (
|
|||||||
},
|
},
|
||||||
boundaryGap: [0, '100%'],
|
boundaryGap: [0, '100%'],
|
||||||
showLastLabel: true,
|
showLastLabel: true,
|
||||||
max: Math.floor(max.toFixed(2) * 1.1 * 10) / 10,
|
max: yRange.max,
|
||||||
min: Math.floor(min.toFixed(2) > 0 ? min.toFixed(2) - min.toFixed(2) * 0.1 : min.toFixed(2) * 1.1 * 10) / 10 ,
|
min: yRange.min,
|
||||||
opposite: false,
|
opposite: false,
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
@@ -809,8 +851,7 @@ const drawPics = (
|
|||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
color: props.DColor ? '#000' : echartsColor.WordColor,
|
color: props.DColor ? '#000' : echartsColor.WordColor,
|
||||||
formatter: function (value: number) {
|
formatter: function (value: number) {
|
||||||
// return (value - 0).toFixed(2)
|
return formatAxisLabel(value)
|
||||||
return Math.floor(value * 1000) / 1000
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
@@ -897,10 +938,7 @@ const drawPics = (
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
finishChartRender(myChartes)
|
||||||
myChartes.resize()
|
|
||||||
loading.value = false
|
|
||||||
}, 400)
|
|
||||||
|
|
||||||
echarts.connect([myChartes1, myChartes])
|
echarts.connect([myChartes1, myChartes])
|
||||||
}
|
}
|
||||||
@@ -929,12 +967,8 @@ const backbxlb = () => {
|
|||||||
myChartess4.value = null
|
myChartess4.value = null
|
||||||
myChartess5.value = null
|
myChartess5.value = null
|
||||||
|
|
||||||
// echarts.disconnect(charts.filter(Boolean) as echarts.ECharts[])
|
$('#shushi').nextAll(`.${EXTRA_PANEL_CLASS}`).remove()
|
||||||
charts.filter(Boolean).forEach(chart => {
|
$('div.bx1').remove()
|
||||||
if (chart && typeof chart.dispose === 'function') {
|
|
||||||
chart.dispose()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMax = (temp: number, tempA: number, tempB: number, tempC: number): number => {
|
const getMax = (temp: number, tempA: number, tempB: number, tempC: number): number => {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,11 @@
|
|||||||
@checkbox-all="selectChangeEvent"
|
@checkbox-all="selectChangeEvent"
|
||||||
@checkbox-change="selectChangeEvent"
|
@checkbox-change="selectChangeEvent"
|
||||||
:showOverflow="showOverflow"
|
:showOverflow="showOverflow"
|
||||||
:sort-config="{ remote: true }"
|
|
||||||
@sort-change="handleSortChange"
|
|
||||||
>
|
|
||||||
|
|
||||||
|
|
||||||
|
>
|
||||||
|
<!-- :sort-config="{ remote: true }" -->
|
||||||
|
<!-- @sort-change="handleSortChange" -->
|
||||||
<!-- Column 组件内部是 el-table-column -->
|
<!-- Column 组件内部是 el-table-column -->
|
||||||
<template v-if="isGroup">
|
<template v-if="isGroup">
|
||||||
<GroupColumn :column="tableStore.table.column" />
|
<GroupColumn :column="tableStore.table.column" />
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ async function selectInitialNode(
|
|||||||
|
|
||||||
treeInstance?.setCurrentKey(node.id)
|
treeInstance?.setCurrentKey(node.id)
|
||||||
|
|
||||||
emit('init', { level, ...node })
|
emit('init', { ...node })
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ async function loadTree() {
|
|||||||
await selectTreeNode(treRef.value, node, {
|
await selectTreeNode(treRef.value, node, {
|
||||||
level: 3,
|
level: 3,
|
||||||
onSelect: selected => {
|
onSelect: selected => {
|
||||||
emit('init', { level: 3, ...selected })
|
emit('init', { ...selected, level: 3 })
|
||||||
changePointType('4', selected)
|
changePointType('4', selected)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ async function initTree(list: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await selectTreeNode(treRef.value, node, {
|
await selectTreeNode(treRef.value, node, {
|
||||||
onSelect: selected => emit('init', { level: 2, ...selected })
|
onSelect: selected => emit('init', { ...selected, level: 2 })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<Tree
|
<Tree ref="treRef" @check-change="handleCheckChange" :default-checked-keys="defaultCheckedKeys"
|
||||||
ref="treRef"
|
:show-checkbox="props.showCheckbox" :data="tree" :height="props.height" @changeDeviceType="changeDeviceType"
|
||||||
@check-change="handleCheckChange"
|
@changeTreeType="loadTree" :engineering="props.engineering" leaf-mode="device" />
|
||||||
:default-checked-keys="defaultCheckedKeys"
|
|
||||||
:show-checkbox="props.showCheckbox"
|
|
||||||
:data="tree"
|
|
||||||
:height="props.height"
|
|
||||||
@changeDeviceType="changeDeviceType"
|
|
||||||
@changeTreeType="loadTree"
|
|
||||||
:engineering="props.engineering"
|
|
||||||
leaf-mode="device"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -65,7 +56,7 @@ async function selectInitialNode(type: string | undefined, leaves: LineTreeLeave
|
|||||||
if (!node) continue
|
if (!node) continue
|
||||||
const treeInstance = await waitForTreeRef(treRef.value, refKey)
|
const treeInstance = await waitForTreeRef(treRef.value, refKey)
|
||||||
treeInstance?.setCurrentKey(node.id)
|
treeInstance?.setCurrentKey(node.id)
|
||||||
emit('init', { level, ...node })
|
emit('init', { ...node })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
emit('init')
|
emit('init')
|
||||||
@@ -81,13 +72,10 @@ const loadTree = (type?: string) => {
|
|||||||
|
|
||||||
onMounted(() => loadTree(props.engineering ? '2' : '1'))
|
onMounted(() => loadTree(props.engineering ? '2' : '1'))
|
||||||
|
|
||||||
const handleCheckChange = throttle(
|
const handleCheckChange =
|
||||||
(data: any, checked: any, indeterminate: any) => {
|
(data: any, checked: any, indeterminate: any) => {
|
||||||
emit('checkChange', { data, checked, indeterminate })
|
emit('checkChange', { data, checked, indeterminate })
|
||||||
},
|
}
|
||||||
300,
|
|
||||||
{ leading: true, trailing: false }
|
|
||||||
)
|
|
||||||
|
|
||||||
defineExpose({ treRef })
|
defineExpose({ treRef })
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ export function decorateDeviceTree(
|
|||||||
child.children?.forEach((grand: any) => {
|
child.children?.forEach((grand: any) => {
|
||||||
applyMeta(grand, {
|
applyMeta(grand, {
|
||||||
icon: 'el-icon-Platform',
|
icon: 'el-icon-Platform',
|
||||||
color: statusColor(grand.comFlag)
|
color: statusColor(grand.comFlag),
|
||||||
|
level: 3
|
||||||
})
|
})
|
||||||
leaves.engineering.push(grand)
|
leaves.engineering.push(grand)
|
||||||
})
|
})
|
||||||
@@ -68,6 +69,7 @@ export function decorateDeviceTree(
|
|||||||
l3.pName = '监测设备'
|
l3.pName = '监测设备'
|
||||||
applyMeta(l3, {
|
applyMeta(l3, {
|
||||||
icon: 'el-icon-Platform',
|
icon: 'el-icon-Platform',
|
||||||
|
level: 3,
|
||||||
color: l3.comFlag === 1 ? '#e26257 !important' : primary()
|
color: l3.comFlag === 1 ? '#e26257 !important' : primary()
|
||||||
})
|
})
|
||||||
leaves.monitor.push(l3)
|
leaves.monitor.push(l3)
|
||||||
|
|||||||
@@ -39,6 +39,21 @@ export function createLineTreeDecorators(getPrimaryColor: () => string): LineTre
|
|||||||
|
|
||||||
export type TreeRefKey = 'treeRef1' | 'treeRef2' | 'treeRef3' | 'treeRef4'
|
export type TreeRefKey = 'treeRef1' | 'treeRef2' | 'treeRef3' | 'treeRef4'
|
||||||
|
|
||||||
|
/** 线路树可选叶子节点元数据 */
|
||||||
|
export const LINE_LEAF_META = { level: 3, type: 'line' as const }
|
||||||
|
|
||||||
|
/** 是否为线路树可选叶子(监测点/线路) */
|
||||||
|
export function isLineTreeLeaf(node: any): boolean {
|
||||||
|
if (!node?.id) return false
|
||||||
|
return node.type === 'line' || node.level === 3
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 是否为报告/导出可选监测点 */
|
||||||
|
export function isReportMonitorPoint(node: any): boolean {
|
||||||
|
if (!node?.id) return false
|
||||||
|
return isLineTreeLeaf(node) || node.level === 3 || (!node.children?.length && !!node.pid)
|
||||||
|
}
|
||||||
|
|
||||||
export interface DecorateLineTreeOptions {
|
export interface DecorateLineTreeOptions {
|
||||||
/** 是否禁用父级节点(分析树隐藏父节点,测点树不禁用) */
|
/** 是否禁用父级节点(分析树隐藏父节点,测点树不禁用) */
|
||||||
disableParents?: boolean
|
disableParents?: boolean
|
||||||
@@ -69,7 +84,11 @@ export function decorateLineTree(
|
|||||||
...parentDisabled
|
...parentDisabled
|
||||||
})
|
})
|
||||||
grand.children?.forEach((leaf: any) => {
|
grand.children?.forEach((leaf: any) => {
|
||||||
applyMeta(leaf, { icon: 'el-icon-Platform', color: statusColor(leaf.comFlag) })
|
applyMeta(leaf, {
|
||||||
|
icon: 'el-icon-Platform',
|
||||||
|
color: statusColor(leaf.comFlag),
|
||||||
|
...LINE_LEAF_META
|
||||||
|
})
|
||||||
leaves.engineering.push(leaf)
|
leaves.engineering.push(leaf)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -90,7 +109,11 @@ export function decorateLineTree(
|
|||||||
...parentDisabled
|
...parentDisabled
|
||||||
})
|
})
|
||||||
l3.children?.forEach((l4: any) => {
|
l3.children?.forEach((l4: any) => {
|
||||||
applyMeta(l4, { icon: 'el-icon-Platform', color: statusColor(l4.comFlag) })
|
applyMeta(l4, {
|
||||||
|
icon: 'el-icon-Platform',
|
||||||
|
color: statusColor(l4.comFlag),
|
||||||
|
...LINE_LEAF_META
|
||||||
|
})
|
||||||
leaves.govern.push(l4)
|
leaves.govern.push(l4)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -100,7 +123,11 @@ export function decorateLineTree(
|
|||||||
item.children?.forEach((l1: any) => {
|
item.children?.forEach((l1: any) => {
|
||||||
applyMeta(l1, { icon: 'el-icon-Platform', color: statusColor(l1.comFlag) })
|
applyMeta(l1, { icon: 'el-icon-Platform', color: statusColor(l1.comFlag) })
|
||||||
l1.children?.forEach((l2: any) => {
|
l1.children?.forEach((l2: any) => {
|
||||||
applyMeta(l2, { icon: 'el-icon-Platform', color: statusColor(l2.comFlag) })
|
applyMeta(l2, {
|
||||||
|
icon: 'el-icon-Platform',
|
||||||
|
color: statusColor(l2.comFlag),
|
||||||
|
...LINE_LEAF_META
|
||||||
|
})
|
||||||
leaves.portable.push(l2)
|
leaves.portable.push(l2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -117,7 +144,11 @@ export function decorateLineTree(
|
|||||||
...parentDisabled
|
...parentDisabled
|
||||||
})
|
})
|
||||||
l3.children?.forEach((l4: any) => {
|
l3.children?.forEach((l4: any) => {
|
||||||
applyMeta(l4, { icon: 'el-icon-Platform', color: statusColor(l4.comFlag) })
|
applyMeta(l4, {
|
||||||
|
icon: 'el-icon-Platform',
|
||||||
|
color: statusColor(l4.comFlag),
|
||||||
|
...LINE_LEAF_META
|
||||||
|
})
|
||||||
leaves.monitor.push(l4)
|
leaves.monitor.push(l4)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ async function selectInitialNode(type: string | undefined, leaves: LineTreeLeave
|
|||||||
|
|
||||||
const treeInstance = await waitForTreeRef(treRef.value, refKey)
|
const treeInstance = await waitForTreeRef(treRef.value, refKey)
|
||||||
treeInstance?.setCurrentKey(node.id)
|
treeInstance?.setCurrentKey(node.id)
|
||||||
emit('init', { level, ...node })
|
emit('init', { ...node })
|
||||||
|
|
||||||
if (type === '2') {
|
if (type === '2') {
|
||||||
changePointType('4', node)
|
changePointType('4', node)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ interface Props {
|
|||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), { template: false })
|
const props = withDefaults(defineProps<Props>(), { template: false })
|
||||||
|
|
||||||
const emit = defineEmits(['init', 'checkChange', 'nodeChange', 'editNode', 'getChart', 'Policy'])
|
const emit = defineEmits(['init', 'checkChange', 'nodeChange', 'node-click', 'editNode', 'getChart', 'Policy'])
|
||||||
|
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const tree = ref<any[]>([])
|
const tree = ref<any[]>([])
|
||||||
@@ -109,6 +109,7 @@ const clickNode = (e: any) => {
|
|||||||
planId.value = e?.children ? e.id : e.pid
|
planId.value = e?.children ? e.id : e.pid
|
||||||
id.value = e.id
|
id.value = e.id
|
||||||
emit('nodeChange', e)
|
emit('nodeChange', e)
|
||||||
|
emit('node-click', e)
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrapWithTemplate(
|
bootstrapWithTemplate(
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import useCurrentInstance from '@/utils/useCurrentInstance'
|
|||||||
import { ElMessage, ElTree } from 'element-plus'
|
import { ElMessage, ElTree } from 'element-plus'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { createTreeFilterNode } from './govern/treeFilterUtils'
|
import { createTreeFilterNode } from './govern/treeFilterUtils'
|
||||||
|
import { isLineTreeLeaf } from './govern/lineTreeUtils'
|
||||||
|
|
||||||
defineOptions({ name: 'govern/select', inheritAttrs: false })
|
defineOptions({ name: 'govern/select', inheritAttrs: false })
|
||||||
|
|
||||||
@@ -75,7 +76,8 @@ const filterNode = createTreeFilterNode()
|
|||||||
const checkedNodes = ref<any[]>([])
|
const checkedNodes = ref<any[]>([])
|
||||||
const defaultCheckedKeys = ref<string[]>([])
|
const defaultCheckedKeys = ref<string[]>([])
|
||||||
const MAX_CHECK = 5
|
const MAX_CHECK = 5
|
||||||
const MONITOR_LEVEL = 3
|
|
||||||
|
const isMonitorLeaf = (node: any) => isLineTreeLeaf(node)
|
||||||
|
|
||||||
watch(filterText, val => treeRef.value?.filter(val))
|
watch(filterText, val => treeRef.value?.filter(val))
|
||||||
|
|
||||||
@@ -85,7 +87,7 @@ const onMenuCollapse = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleCheckChange = (_data: any, checkInfo: any) => {
|
const handleCheckChange = (_data: any, checkInfo: any) => {
|
||||||
const monitoringPointNodes = (checkInfo.checkedNodes as any[]).filter(node => node.level === MONITOR_LEVEL)
|
const monitoringPointNodes = (checkInfo.checkedNodes as any[]).filter(isMonitorLeaf)
|
||||||
|
|
||||||
if (monitoringPointNodes.length > MAX_CHECK) {
|
if (monitoringPointNodes.length > MAX_CHECK) {
|
||||||
const previousCheckedNodes = checkedNodes.value
|
const previousCheckedNodes = checkedNodes.value
|
||||||
@@ -122,7 +124,7 @@ const updateNodeCheckStatus = (currentCount: number) => {
|
|||||||
if (!treeRef.value) return
|
if (!treeRef.value) return
|
||||||
const isMaxSelected = currentCount >= MAX_CHECK
|
const isMaxSelected = currentCount >= MAX_CHECK
|
||||||
treeRef.value.store._getAllNodes().forEach((node: any) => {
|
treeRef.value.store._getAllNodes().forEach((node: any) => {
|
||||||
if (node.level === MONITOR_LEVEL) {
|
if (isMonitorLeaf(node.data)) {
|
||||||
node.data.disabled = isMaxSelected && !node.checked
|
node.data.disabled = isMaxSelected && !node.checked
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-logo">
|
<div class="layout-logo">
|
||||||
<img v-if="!config.layout.menuCollapse" class="logo-img" :src="getTheme.logoUrl" />
|
<img v-if="!config.layout.menuCollapse && getTheme.logoUrl" class="logo-img" :src="getTheme.logoUrl" />
|
||||||
<!-- <div-->
|
<!-- <div-->
|
||||||
<!-- v-if="!config.layout.menuCollapse"-->
|
<!-- v-if="!config.layout.menuCollapse"-->
|
||||||
<!-- :style="{ color: config.getColorVal('menuActiveColor') }"-->
|
<!-- :style="{ color: config.getColorVal('menuActiveColor') }"-->
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<!-- >-->
|
<!-- >-->
|
||||||
<!-- 灿能-->
|
<!-- 灿能-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
<!-- <Icon
|
<Icon
|
||||||
v-if="config.layout.layoutMode != 'Streamline'"
|
v-if="config.layout.layoutMode != 'Streamline'"
|
||||||
@click="onMenuCollapse"
|
@click="onMenuCollapse"
|
||||||
:name="config.layout.menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
|
:name="config.layout.menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
|
||||||
@@ -17,18 +17,18 @@
|
|||||||
style="margin: 15px;"
|
style="margin: 15px;"
|
||||||
size="18"
|
size="18"
|
||||||
class="fold"
|
class="fold"
|
||||||
/> -->
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useConfig } from '@/stores/config'
|
import { useConfig } from '@/stores/config'
|
||||||
import { closeShade } from '@/utils/pageShade'
|
import { closeShade } from '@/utils/pageShade'
|
||||||
import { Session } from '@/utils/storage'
|
import { getStoredTheme } from '@/utils/storage'
|
||||||
import { setNavTabsWidth } from '@/utils/layout'
|
import { setNavTabsWidth } from '@/utils/layout'
|
||||||
|
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const getTheme = JSON.parse(window.localStorage.getItem('getTheme') as string)
|
const getTheme = getStoredTheme()
|
||||||
const onMenuCollapse = function () {
|
const onMenuCollapse = function () {
|
||||||
if (config.layout.shrink && !config.layout.menuCollapse) {
|
if (config.layout.shrink && !config.layout.menuCollapse) {
|
||||||
closeShade()
|
closeShade()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<!-- <Icon @click="onMenuCollapse" name="fa fa-indent" :color="config.getColorVal('menuActiveColor')"
|
<!-- <Icon @click="onMenuCollapse" name="fa fa-indent" :color="config.getColorVal('menuActiveColor')"
|
||||||
size="18" /> -->
|
size="18" /> -->
|
||||||
</div>
|
</div>
|
||||||
<span class="nav-bar-title">{{ getTheme.name }} <span style="font-size: 14px;" v-if="Version?.versionName">
|
<span class="nav-bar-title">{{ themeName }} <span style="font-size: 14px;" v-if="Version?.versionName">
|
||||||
({{ Version?.versionName }})
|
({{ Version?.versionName }})
|
||||||
</span></span>
|
</span></span>
|
||||||
<NavMenus />
|
<NavMenus />
|
||||||
@@ -19,8 +19,9 @@ import NavMenus from '../navMenus.vue'
|
|||||||
import { showShade } from '@/utils/pageShade'
|
import { showShade } from '@/utils/pageShade'
|
||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue'
|
||||||
import { getLastData } from '@/api/systerm'
|
import { getLastData } from '@/api/systerm'
|
||||||
|
import { getStoredThemeName } from '@/utils/storage'
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const getTheme = JSON.parse(window.localStorage.getItem('getTheme') as string)
|
const themeName = getStoredThemeName()
|
||||||
const Version: any = ref({})
|
const Version: any = ref({})
|
||||||
const onMenuCollapse = () => {
|
const onMenuCollapse = () => {
|
||||||
showShade('ba-aside-menu-shade', () => {
|
showShade('ba-aside-menu-shade', () => {
|
||||||
@@ -33,7 +34,7 @@ onMounted(() => {
|
|||||||
Version.value = res.data
|
Version.value = res.data
|
||||||
|
|
||||||
})
|
})
|
||||||
document.title = getTheme.name
|
document.title = themeName
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
59
src/utils/chartAxisHelper.ts
Normal file
59
src/utils/chartAxisHelper.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
const AXIS_DECIMALS = 2
|
||||||
|
|
||||||
|
export function roundAxisValue(val: number, decimals = AXIS_DECIMALS): number {
|
||||||
|
if (!Number.isFinite(val)) return 0
|
||||||
|
const factor = 10 ** decimals
|
||||||
|
return Math.round(val * factor) / factor
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Y 轴刻度:最多 2 位小数,末尾 0 去掉(如 1.00 → 1,0.10 → 0.1) */
|
||||||
|
export function formatAxisLabel(value: number): string {
|
||||||
|
if (!Number.isFinite(value)) return '0'
|
||||||
|
return String(Number(roundAxisValue(value).toFixed(AXIS_DECIMALS)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 瞬间波形 Y 轴范围 */
|
||||||
|
export function calcShuYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } {
|
||||||
|
const min = Number(dataMin)
|
||||||
|
const max = Number(dataMax)
|
||||||
|
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
||||||
|
return { min: 0, max: 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
let axisMax = max * 1.1
|
||||||
|
let axisMin = min > 0 ? min - min * 0.1 : min * 1.1
|
||||||
|
|
||||||
|
if (axisMax <= axisMin) {
|
||||||
|
const pad = Math.abs(max) * 0.1 || 0.01
|
||||||
|
axisMax = max + pad
|
||||||
|
axisMin = min - pad
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
min: roundAxisValue(axisMin),
|
||||||
|
max: roundAxisValue(axisMax)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RMS 波形 Y 轴范围 */
|
||||||
|
export function calcRmsYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } {
|
||||||
|
const min = Number(dataMin)
|
||||||
|
const max = Number(dataMax)
|
||||||
|
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
||||||
|
return { min: 0, max: 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
let axisMax = max * 1.06 * 1.1
|
||||||
|
let axisMin = min - min * 0.2
|
||||||
|
|
||||||
|
if (axisMax <= axisMin) {
|
||||||
|
const pad = Math.abs(max - min) * 0.1 || Math.abs(max) * 0.1 || 0.01
|
||||||
|
axisMax = max + pad
|
||||||
|
axisMin = min - pad
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
min: roundAxisValue(axisMin),
|
||||||
|
max: roundAxisValue(axisMax)
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/utils/luckysheetHelper.ts
Normal file
83
src/utils/luckysheetHelper.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { exportExcel } from '@/views/system/reportForms/export.js'
|
||||||
|
|
||||||
|
/** 解析 Luckysheet 接口返回的 sheet 数据 */
|
||||||
|
export function parseLuckysheetSheets(sheets: any[]) {
|
||||||
|
sheets.forEach((item: any) => {
|
||||||
|
if (item.data1) {
|
||||||
|
try {
|
||||||
|
item.data = JSON.parse(item.data1)
|
||||||
|
} catch {
|
||||||
|
/* ignore invalid json */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item.celldata?.forEach((cell: any) => {
|
||||||
|
if (item.data?.[cell.r]?.[cell.c]?.v != null) {
|
||||||
|
item.data[cell.r][cell.c] = cell.v
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const luckysheet: any
|
||||||
|
|
||||||
|
const DEFAULT_REPORT_OPTIONS = {
|
||||||
|
title: '',
|
||||||
|
lang: 'zh',
|
||||||
|
showtoolbar: false,
|
||||||
|
showinfobar: false,
|
||||||
|
showsheetbar: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 销毁已有 Luckysheet 实例,避免重复 create 导致 DOM 堆积 */
|
||||||
|
export function destroyLuckysheet() {
|
||||||
|
try {
|
||||||
|
if (typeof luckysheet !== 'undefined' && luckysheet.destroy) {
|
||||||
|
luckysheet.destroy()
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 解析 sheet 数据、销毁旧实例并渲染报表 */
|
||||||
|
export function renderLuckysheetReport(
|
||||||
|
container: string,
|
||||||
|
sheets: any[],
|
||||||
|
options: Record<string, any> = {}
|
||||||
|
) {
|
||||||
|
parseLuckysheetSheets(sheets)
|
||||||
|
destroyLuckysheet()
|
||||||
|
setTimeout(() => {
|
||||||
|
luckysheet.create({
|
||||||
|
container,
|
||||||
|
...DEFAULT_REPORT_OPTIONS,
|
||||||
|
...options,
|
||||||
|
data: sheets,
|
||||||
|
})
|
||||||
|
}, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 安全导出 Luckysheet,无数据时提示并返回 false */
|
||||||
|
export function exportLuckysheetFile(filename: string, hasData = true): boolean {
|
||||||
|
if (!hasData) {
|
||||||
|
ElMessage.warning('暂无数据')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (typeof luckysheet === 'undefined' || !luckysheet.getAllSheets) {
|
||||||
|
ElMessage.warning('暂无数据')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const sheets = luckysheet.getAllSheets()
|
||||||
|
if (!sheets?.length) {
|
||||||
|
ElMessage.warning('暂无数据')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
exportExcel(sheets, filename)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
ElMessage.warning('导出失败,请先加载报表数据')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,21 @@ export const Local = {
|
|||||||
* @method remove 移除会话缓存
|
* @method remove 移除会话缓存
|
||||||
* @method clear 移除全部会话缓存
|
* @method clear 移除全部会话缓存
|
||||||
*/
|
*/
|
||||||
|
const DEFAULT_THEME_NAME = '电能质量监测系统'
|
||||||
|
|
||||||
|
export function getStoredTheme(): { name?: string; logoUrl?: string; [key: string]: any } {
|
||||||
|
try {
|
||||||
|
const raw = window.localStorage.getItem('getTheme')
|
||||||
|
return raw ? JSON.parse(raw) : {}
|
||||||
|
} catch {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStoredThemeName(): string {
|
||||||
|
return getStoredTheme().name || DEFAULT_THEME_NAME
|
||||||
|
}
|
||||||
|
|
||||||
export const Session = {
|
export const Session = {
|
||||||
set(key: string, val: any) {
|
set(key: string, val: any) {
|
||||||
window.sessionStorage.setItem(key, JSON.stringify(val))
|
window.sessionStorage.setItem(key, JSON.stringify(val))
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ interface TableStoreParams {
|
|||||||
resetCallback?: () => void // 重置
|
resetCallback?: () => void // 重置
|
||||||
loadCallback?: () => void // 接口调用后的回调
|
loadCallback?: () => void // 接口调用后的回调
|
||||||
exportProcessingData?: () => void //导出处理数据
|
exportProcessingData?: () => void //导出处理数据
|
||||||
beforeSearchFun?: () => void // 接口调用前的回调
|
beforeSearchFun?: () => void | boolean // 接口调用前的回调,返回 false 中止请求
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TableStore {
|
export default class TableStore {
|
||||||
@@ -75,7 +75,13 @@ export default class TableStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
index() {
|
index() {
|
||||||
this.table.beforeSearchFun && this.table.beforeSearchFun()
|
if (this.table.beforeSearchFun) {
|
||||||
|
const canSearch = this.table.beforeSearchFun()
|
||||||
|
if (canSearch === false) {
|
||||||
|
this.table.loading = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
this.table.data = []
|
this.table.data = []
|
||||||
this.table.loading = true
|
this.table.loading = true
|
||||||
// 重置用的数据数据
|
// 重置用的数据数据
|
||||||
|
|||||||
42
src/utils/waveCache.ts
Normal file
42
src/utils/waveCache.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
const MAX_CACHE_SIZE = 30
|
||||||
|
|
||||||
|
const cache = new Map<string, unknown>()
|
||||||
|
|
||||||
|
function dataFingerprint(data: unknown[][] | undefined): string {
|
||||||
|
if (!data?.length) return '0'
|
||||||
|
const first = data[0]
|
||||||
|
const last = data[data.length - 1]
|
||||||
|
return `${data.length}:${first?.[0]}:${last?.[0]}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildWaveCacheKey(
|
||||||
|
type: 'shu' | 'rms',
|
||||||
|
wp: Record<string, any> | undefined,
|
||||||
|
value: number,
|
||||||
|
isOpen: boolean,
|
||||||
|
boxoList: Record<string, any>
|
||||||
|
): string {
|
||||||
|
if (!wp) return ''
|
||||||
|
const waveFp =
|
||||||
|
type === 'shu' ? dataFingerprint(wp.listWaveData) : dataFingerprint(wp.listRmsData)
|
||||||
|
const boxoFp = boxoList?.startTime ?? boxoList?.lineName ?? boxoList?.equipmentName ?? ''
|
||||||
|
return `${type}|${wp.time}|${wp.waveType}|${wp.iphasic}|${value}|${isOpen}|${waveFp}|${boxoFp}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getWaveCache<T>(key: string): T | null {
|
||||||
|
if (!key || !cache.has(key)) return null
|
||||||
|
const value = cache.get(key) as T
|
||||||
|
cache.delete(key)
|
||||||
|
cache.set(key, value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setWaveCache(key: string, value: unknown): void {
|
||||||
|
if (!key) return
|
||||||
|
if (cache.has(key)) cache.delete(key)
|
||||||
|
cache.set(key, value)
|
||||||
|
while (cache.size > MAX_CACHE_SIZE) {
|
||||||
|
const oldest = cache.keys().next().value
|
||||||
|
if (oldest !== undefined) cache.delete(oldest)
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/utils/waveWorkerPool.ts
Normal file
96
src/utils/waveWorkerPool.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { toRaw } from 'vue'
|
||||||
|
|
||||||
|
type WorkerMessageHandler = (data: any) => void
|
||||||
|
|
||||||
|
let shuWorker: Worker | null = null
|
||||||
|
let rmsWorker: Worker | null = null
|
||||||
|
|
||||||
|
/** 递归剥离 Vue 响应式代理,得到可 structuredClone 的纯对象 */
|
||||||
|
export function toPlainDeep<T>(value: T): T {
|
||||||
|
const raw = toRaw(value as object) as T
|
||||||
|
if (Array.isArray(raw)) {
|
||||||
|
return raw.map(item => toPlainDeep(item)) as T
|
||||||
|
}
|
||||||
|
if (raw !== null && typeof raw === 'object') {
|
||||||
|
const out: Record<string, unknown> = {}
|
||||||
|
for (const [key, val] of Object.entries(raw)) {
|
||||||
|
out[key] = toPlainDeep(val)
|
||||||
|
}
|
||||||
|
return out as T
|
||||||
|
}
|
||||||
|
return raw
|
||||||
|
}
|
||||||
|
|
||||||
|
const BOXO_LIST_KEYS = [
|
||||||
|
'systemType',
|
||||||
|
'powerStationName',
|
||||||
|
'measurementPointName',
|
||||||
|
'startTime',
|
||||||
|
'featureAmplitude',
|
||||||
|
'duration',
|
||||||
|
'engineeringName',
|
||||||
|
'equipmentName',
|
||||||
|
'evtParamVVaDepth',
|
||||||
|
'evtParamTm',
|
||||||
|
'lineName',
|
||||||
|
'persistTime',
|
||||||
|
'subName'
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function buildWorkerPayload(
|
||||||
|
type: 'shu' | 'rms',
|
||||||
|
wp: Record<string, any>,
|
||||||
|
boxoList: Record<string, any>,
|
||||||
|
extras: { requestId: number; value: number; isOpen: boolean; iphasic?: number }
|
||||||
|
) {
|
||||||
|
const plainWp = toPlainDeep(wp)
|
||||||
|
const wpPayload: Record<string, unknown> = {
|
||||||
|
pt: plainWp.pt,
|
||||||
|
ct: plainWp.ct,
|
||||||
|
waveTitle: plainWp.waveTitle,
|
||||||
|
iphasic: plainWp.iphasic,
|
||||||
|
time: plainWp.time,
|
||||||
|
waveType: plainWp.waveType,
|
||||||
|
yzd: plainWp.yzd
|
||||||
|
}
|
||||||
|
if (type === 'shu') {
|
||||||
|
wpPayload.listWaveData = plainWp.listWaveData
|
||||||
|
} else {
|
||||||
|
wpPayload.listRmsData = plainWp.listRmsData
|
||||||
|
}
|
||||||
|
|
||||||
|
const plainBoxo: Record<string, unknown> = {}
|
||||||
|
const rawBoxo = toPlainDeep(boxoList)
|
||||||
|
for (const key of BOXO_LIST_KEYS) {
|
||||||
|
if (rawBoxo[key] !== undefined) {
|
||||||
|
plainBoxo[key] = rawBoxo[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
requestId: extras.requestId,
|
||||||
|
value: extras.value,
|
||||||
|
isOpen: extras.isOpen,
|
||||||
|
iphasic: extras.iphasic,
|
||||||
|
wp: wpPayload,
|
||||||
|
boxoList: plainBoxo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getShuWorker(onMessage: WorkerMessageHandler): Worker {
|
||||||
|
if (!shuWorker) {
|
||||||
|
shuWorker = new Worker(new URL('../components/echarts/shuWorker.js', import.meta.url))
|
||||||
|
}
|
||||||
|
shuWorker.onmessage = e => onMessage(e.data)
|
||||||
|
shuWorker.onerror = error => console.error('Shu worker error:', error)
|
||||||
|
return shuWorker
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRmsWorker(onMessage: WorkerMessageHandler): Worker {
|
||||||
|
if (!rmsWorker) {
|
||||||
|
rmsWorker = new Worker(new URL('../components/echarts/rmsWorker.js', import.meta.url))
|
||||||
|
}
|
||||||
|
rmsWorker.onmessage = e => onMessage(e.data)
|
||||||
|
rmsWorker.onerror = error => console.error('Rms worker error:', error)
|
||||||
|
return rmsWorker
|
||||||
|
}
|
||||||
@@ -92,8 +92,8 @@ const tableStore = new TableStore({
|
|||||||
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: 'ndid', align: 'center' },
|
|
||||||
{ title: '异常时间', field: 'evtTime', align: 'center', sortable: true },
|
{ title: '异常时间', field: 'evtTime', align: 'center', sortable: true },
|
||||||
|
{ title: '设备名称', field: 'ndid', align: 'center' },
|
||||||
{
|
{
|
||||||
title: '告警代码',
|
title: '告警代码',
|
||||||
field: 'code',
|
field: 'code',
|
||||||
|
|||||||
@@ -99,16 +99,17 @@ const tableStore = new TableStore({
|
|||||||
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: 'equipmentName', align: 'center', width: 120 },
|
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
|
||||||
{ title: '监测点名称', field: 'lineName', align: 'center', width: 140 },
|
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120 },
|
||||||
{ title: '工程名称', field: 'engineeringName', align: 'center', width: 120 },
|
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120 },
|
||||||
{ title: '项目名称', field: 'projectName', align: 'center', width: 120 },
|
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 120 },
|
||||||
{ title: '发生时刻', field: 'startTime', align: 'center', width: 180, sortable: true },
|
{ title: '监测点名称', field: 'lineName', align: 'center', minWidth: 120 },
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '模块信息',
|
title: '模块信息',
|
||||||
field: 'moduleNo',
|
field: 'moduleNo',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 100,
|
minWidth: 100,
|
||||||
formatter: (row: any) => {
|
formatter: (row: any) => {
|
||||||
return row.cellValue ? row.cellValue : '/'
|
return row.cellValue ? row.cellValue : '/'
|
||||||
}
|
}
|
||||||
@@ -117,7 +118,7 @@ const tableStore = new TableStore({
|
|||||||
title: '告警代码',
|
title: '告警代码',
|
||||||
field: 'code',
|
field: 'code',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 100,
|
minWidth: 100,
|
||||||
formatter: (row: any) => {
|
formatter: (row: any) => {
|
||||||
return row.cellValue ? '\u200B' + row.cellValue : '/'
|
return row.cellValue ? '\u200B' + row.cellValue : '/'
|
||||||
},
|
},
|
||||||
@@ -125,13 +126,13 @@ const tableStore = new TableStore({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '事件描述',
|
title: '事件描述',
|
||||||
minWidth: 250,
|
minWidth: 300,
|
||||||
field: 'showName'
|
field: 'showName'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '级别',
|
title: '级别',
|
||||||
field: 'level',
|
field: 'level',
|
||||||
width: 100,
|
width: 110,
|
||||||
render: 'tag',
|
render: 'tag',
|
||||||
custom: {
|
custom: {
|
||||||
// 1:Ⅰ级 2:Ⅱ级 3:Ⅲ级 4:DEBUG 5:NORMAL 6:WARN 7:ERROR
|
// 1:Ⅰ级 2:Ⅱ级 3:Ⅲ级 4:DEBUG 5:NORMAL 6:WARN 7:ERROR
|
||||||
@@ -202,7 +203,7 @@ tableStore.table.params.deviceTypeId = ''
|
|||||||
tableStore.table.params.deviceTypeName = ''
|
tableStore.table.params.deviceTypeName = ''
|
||||||
const deviceTreeOptions = ref<any>(props.deviceTree)
|
const deviceTreeOptions = ref<any>(props.deviceTree)
|
||||||
deviceTreeOptions.value.map((item: any, index: any) => {
|
deviceTreeOptions.value.map((item: any, index: any) => {
|
||||||
if (item.children.length == 0) {
|
if (item?.children.length == 0) {
|
||||||
deviceTreeOptions.value.splice(index, 1)
|
deviceTreeOptions.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -78,10 +78,10 @@ const tableStore = new TableStore({
|
|||||||
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: 'lineId', align: 'center', width: 120 },
|
|
||||||
{ title: '前置服务器ip', field: 'wavePath', align: 'center', width: 120 },
|
|
||||||
{ title: '进程号', field: 'clDid', align: 'center', width: 60 },
|
|
||||||
{ title: '发生时刻', field: 'startTime', align: 'center', width: 180, sortable: true },
|
{ title: '发生时刻', field: 'startTime', align: 'center', width: 180, sortable: true },
|
||||||
|
{ title: '前置服务器名称', field: 'lineId', align: 'center', width: 150 },
|
||||||
|
{ title: '前置服务器ip', field: 'wavePath', align: 'center', width: 150 },
|
||||||
|
{ title: '进程号', field: 'clDid', align: 'center', width: 70 },
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '事件描述',
|
title: '事件描述',
|
||||||
@@ -102,7 +102,7 @@ const tableStore = new TableStore({
|
|||||||
{
|
{
|
||||||
title: '级别',
|
title: '级别',
|
||||||
field: 'level',
|
field: 'level',
|
||||||
width: 100,
|
width: 110,
|
||||||
render: 'tag',
|
render: 'tag',
|
||||||
custom: {
|
custom: {
|
||||||
// 1:Ⅰ级 2:Ⅱ级 3:Ⅲ级 4:DEBUG 5:NORMAL 6:WARN 7:ERROR
|
// 1:Ⅰ级 2:Ⅱ级 3:Ⅲ级 4:DEBUG 5:NORMAL 6:WARN 7:ERROR
|
||||||
@@ -153,7 +153,7 @@ tableStore.table.params.searchValue = ''
|
|||||||
tableStore.table.params.level = ''
|
tableStore.table.params.level = ''
|
||||||
const deviceTreeOptions = ref<any>(props.deviceTree)
|
const deviceTreeOptions = ref<any>(props.deviceTree)
|
||||||
deviceTreeOptions.value.map((item: any, index: any) => {
|
deviceTreeOptions.value.map((item: any, index: any) => {
|
||||||
if (item.children.length == 0) {
|
if (item?.children.length == 0) {
|
||||||
deviceTreeOptions.value.splice(index, 1)
|
deviceTreeOptions.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,16 +2,9 @@
|
|||||||
<TableHeader datePicker ref="refheader" showExport>
|
<TableHeader datePicker ref="refheader" showExport>
|
||||||
<template v-slot:select>
|
<template v-slot:select>
|
||||||
<el-form-item label="数据来源">
|
<el-form-item label="数据来源">
|
||||||
<el-cascader
|
<el-cascader v-model.trim="tableStore.table.params.cascader" filterable placeholder="请选择数据来源"
|
||||||
v-model.trim="tableStore.table.params.cascader"
|
@change="sourceChange" :options="deviceTreeOptions" :show-all-levels="false"
|
||||||
filterable
|
:props="{ checkStrictly: true, value: 'id', label: 'name' }" clearable></el-cascader>
|
||||||
placeholder="请选择数据来源"
|
|
||||||
@change="sourceChange"
|
|
||||||
:options="deviceTreeOptions"
|
|
||||||
:show-all-levels="false"
|
|
||||||
:props="{ checkStrictly: true, value: 'id', label: 'name' }"
|
|
||||||
clearable
|
|
||||||
></el-cascader>
|
|
||||||
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
|
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="级别">
|
<!-- <el-form-item label="级别">
|
||||||
@@ -83,14 +76,15 @@ const tableStore = new TableStore({
|
|||||||
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: 'equipmentName', align: 'center' },
|
{ title: '发生时刻', field: 'startTime', align: 'center', sortable: true, minWidth: 180, },
|
||||||
{ title: '工程名称', field: 'engineeringName', align: 'center' },
|
{ title: '工程名称', field: 'engineeringName', align: 'center', minWidth: 120, },
|
||||||
{ title: '项目名称', field: 'projectName', align: 'center' },
|
{ title: '项目名称', field: 'projectName', align: 'center', minWidth: 120, },
|
||||||
{ title: '发生时刻', field: 'startTime', align: 'center', sortable: true },
|
{ title: '设备名称', field: 'equipmentName', align: 'center', minWidth: 120, },
|
||||||
|
|
||||||
{ title: '事件描述', field: 'showName', align: 'center' }
|
|
||||||
|
{ title: '事件描述', field: 'showName', align: 'center', minWidth: 250, }
|
||||||
],
|
],
|
||||||
beforeSearchFun: () => {}
|
beforeSearchFun: () => { }
|
||||||
})
|
})
|
||||||
|
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
@@ -112,7 +106,7 @@ tableStore.table.params.deviceTypeName = ''
|
|||||||
|
|
||||||
const deviceTreeOptions = ref<any>(props.deviceTree)
|
const deviceTreeOptions = ref<any>(props.deviceTree)
|
||||||
deviceTreeOptions.value.map((item: any, index: any) => {
|
deviceTreeOptions.value.map((item: any, index: any) => {
|
||||||
if (item.children.length == 0) {
|
if (item?.children.length == 0) {
|
||||||
deviceTreeOptions.value.splice(index, 1)
|
deviceTreeOptions.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -143,6 +137,6 @@ onMounted(() => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tableStore.table.height = mainHeight(200).height as any
|
tableStore.table.height = mainHeight(200).height as any
|
||||||
}, 0)
|
}, 0)
|
||||||
const addMenu = () => {}
|
const addMenu = () => { }
|
||||||
</script>
|
</script>
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|||||||
@@ -3,16 +3,10 @@
|
|||||||
<TableHeader datePicker showExport>
|
<TableHeader datePicker showExport>
|
||||||
<template v-slot:select>
|
<template v-slot:select>
|
||||||
<el-form-item label="数据来源">
|
<el-form-item label="数据来源">
|
||||||
<el-cascader
|
<el-cascader placeholder="请选择数据来源" @change="sourceChange" filterable
|
||||||
placeholder="请选择数据来源"
|
v-model.trim="tableStore.table.params.cascader" :options="deviceTreeOptions"
|
||||||
@change="sourceChange"
|
:show-all-levels="false" :props="{ checkStrictly: true, value: 'id', label: 'name' }"
|
||||||
filterable
|
clearable></el-cascader>
|
||||||
v-model.trim="tableStore.table.params.cascader"
|
|
||||||
:options="deviceTreeOptions"
|
|
||||||
:show-all-levels="false"
|
|
||||||
:props="{ checkStrictly: true, value: 'id', label: 'name' }"
|
|
||||||
clearable
|
|
||||||
></el-cascader>
|
|
||||||
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
|
<!-- <el-input maxlength="32" show-word-limit v-model.trim="tableStore.table.params.searchValue" placeholder="请输入设备名称" /> -->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="级别">
|
<!-- <el-form-item label="级别">
|
||||||
@@ -26,13 +20,8 @@
|
|||||||
|
|
||||||
<Table></Table>
|
<Table></Table>
|
||||||
</div>
|
</div>
|
||||||
<waveFormAnalysis
|
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
|
||||||
v-loading="loading"
|
@handleHideCharts="isWaveCharts = false" :wp="wp" />
|
||||||
v-if="isWaveCharts"
|
|
||||||
ref="waveFormAnalysisRef"
|
|
||||||
@handleHideCharts="isWaveCharts = false"
|
|
||||||
:wp="wp"
|
|
||||||
/>
|
|
||||||
<!-- <div style="height: 300px;"> -->
|
<!-- <div style="height: 300px;"> -->
|
||||||
|
|
||||||
<!-- <div style="padding: 10px" v-if="!view" v-loading="loading">
|
<!-- <div style="padding: 10px" v-if="!view" v-loading="loading">
|
||||||
@@ -129,16 +118,20 @@ const tableStore = new TableStore({
|
|||||||
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: 'equipmentName', minWidth: 120, align: 'center' },
|
{ title: '暂降发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
|
||||||
|
|
||||||
|
|
||||||
|
{ title: '暂降(骤升)幅值(%)', minWidth: 160, field: 'evtParamVVaDepth', align: 'center', sortable: true },
|
||||||
|
|
||||||
|
{ title: '持续时间(s)', field: 'evtParamTm', minWidth: 110, align: 'center', sortable: true },
|
||||||
|
{ title: '相别', field: 'evtParamPhase', minWidth: 80, align: 'center' },
|
||||||
|
|
||||||
|
{ title: '触发类型', field: 'showName', minWidth: 120, align: 'center' },
|
||||||
{ title: '工程名称', field: 'engineeringName', minWidth: 120, align: 'center' },
|
{ title: '工程名称', field: 'engineeringName', minWidth: 120, align: 'center' },
|
||||||
{ title: '项目名称', field: 'projectName', minWidth: 120, align: 'center' },
|
{ title: '项目名称', field: 'projectName', minWidth: 120, align: 'center' },
|
||||||
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
|
{ title: '设备名称', field: 'equipmentName', minWidth: 120, align: 'center' },
|
||||||
{ title: '监测点名称', field: 'lineName', minWidth: 120, align: 'center' },
|
{ title: '监测点名称', field: 'lineName', minWidth: 120, align: 'center' },
|
||||||
{ title: '事件描述', field: 'showName', minWidth: 120, align: 'center' },
|
{ title: '发生位置', field: 'evtParamPosition', minWidth: 150, align: 'center' },
|
||||||
{ title: '事件发生位置', field: 'evtParamPosition', minWidth: 150, align: 'center' },
|
|
||||||
{ title: '相别', field: 'evtParamPhase', minWidth: 80, align: 'center' },
|
|
||||||
{ title: '持续时间(s)', field: 'evtParamTm', minWidth: 80, align: 'center', sortable: true },
|
|
||||||
{ title: '暂降(聚升)幅值(%)', minWidth: 100, field: 'evtParamVVaDepth', align: 'center', sortable: true },
|
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@@ -219,6 +212,7 @@ const tableStore = new TableStore({
|
|||||||
return !row.wavePath
|
return !row.wavePath
|
||||||
},
|
},
|
||||||
click: row => {
|
click: row => {
|
||||||
|
ElMessage.info('下载中......')
|
||||||
getFileZip({ eventId: row.id }).then(res => {
|
getFileZip({ eventId: row.id }).then(res => {
|
||||||
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)
|
||||||
@@ -228,6 +222,7 @@ const tableStore = new TableStore({
|
|||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
link.click() //执行下载
|
link.click() //执行下载
|
||||||
document.body.removeChild(link) //释放标签
|
document.body.removeChild(link) //释放标签
|
||||||
|
ElMessage.success('波形下载成功')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -238,7 +233,7 @@ const tableStore = new TableStore({
|
|||||||
icon: 'el-icon-DataLine',
|
icon: 'el-icon-DataLine',
|
||||||
render: 'basicButton',
|
render: 'basicButton',
|
||||||
disabled: row => {
|
disabled: row => {
|
||||||
return row.showName != '未知'
|
return row.wavePath
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -295,7 +290,7 @@ tableStore.table.params.deviceTypeName = ''
|
|||||||
|
|
||||||
const deviceTreeOptions: any = ref<any>(props.deviceTree)
|
const deviceTreeOptions: any = ref<any>(props.deviceTree)
|
||||||
deviceTreeOptions.value.map((item: any, index: any) => {
|
deviceTreeOptions.value.map((item: any, index: any) => {
|
||||||
if (item.children.length == 0) {
|
if (item?.children.length == 0) {
|
||||||
deviceTreeOptions.value.splice(index, 1)
|
deviceTreeOptions.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -380,6 +375,6 @@ setTimeout(() => {
|
|||||||
tableStore.table.height = mainHeight(200).height as any
|
tableStore.table.height = mainHeight(200).height as any
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
const addMenu = () => {}
|
const addMenu = () => { }
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
@@ -9,44 +9,23 @@
|
|||||||
<DatePicker ref="datePickerRef"></DatePicker>
|
<DatePicker ref="datePickerRef"></DatePicker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="统计指标:">
|
<el-form-item label="统计指标:">
|
||||||
<el-select
|
<el-select style="width: 200px" v-model.trim="formInline.statisticalId" filterable
|
||||||
style="width: 200px"
|
@change="frequencyFlag" placeholder="请选择">
|
||||||
v-model.trim="formInline.statisticalId"
|
<el-option v-for="item in zblist" :key="item.value" :label="item.label"
|
||||||
filterable
|
:value="item.value"></el-option>
|
||||||
@change="frequencyFlag"
|
|
||||||
placeholder="请选择"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in zblist"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="谐波次数:" v-show="frequencyShow">
|
<el-form-item label="谐波次数:" v-show="frequencyShow">
|
||||||
<el-select
|
<el-select v-model.trim="formInline.frequency" filterable placeholder="请选择"
|
||||||
v-model.trim="formInline.frequency"
|
style="width: 100px">
|
||||||
filterable
|
<el-option v-for="item in 49" :key="item + 1" :label="item + 1"
|
||||||
placeholder="请选择"
|
:value="item + 1"></el-option>
|
||||||
style="width: 100px"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in 49"
|
|
||||||
:key="item + 1"
|
|
||||||
:label="item + 1"
|
|
||||||
:value="item + 1"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="值类型:">
|
<el-form-item label="值类型:">
|
||||||
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择">
|
<el-select v-model.trim="formInline.valueType" filterable placeholder="请选择">
|
||||||
<el-option
|
<el-option v-for="item in typelist" :key="item.value" :label="item.label"
|
||||||
v-for="item in typelist"
|
:value="item.value"></el-option>
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
@@ -149,7 +128,7 @@ const deviceTypeChange = (val: any, obj: any) => {
|
|||||||
nodeClick(obj)
|
nodeClick(obj)
|
||||||
}
|
}
|
||||||
const nodeClick = async (e: anyObj) => {
|
const nodeClick = async (e: anyObj) => {
|
||||||
if (e.level == 2 && flag.value) {
|
if ((e.level == 2 || e.level == 3) && flag.value) {
|
||||||
formInline.devId = e.id
|
formInline.devId = e.id
|
||||||
loading.value = true
|
loading.value = true
|
||||||
if (zblist.value.length === 0) {
|
if (zblist.value.length === 0) {
|
||||||
@@ -315,8 +294,7 @@ const setEchart = () => {
|
|||||||
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
|
||||||
}
|
}
|
||||||
|
|
||||||
str += `${marker}${el.seriesName.split('(')[0]}:${
|
str += `${marker}${el.seriesName.split('(')[0]}:${el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == 'null' ? '' : el.value[2]) : '-'
|
||||||
el.value[1] != null ? el.value[1] + ' ' + (el.value[2] == 'null' ? '' : el.value[2]) : '-'
|
|
||||||
}<br>`
|
}<br>`
|
||||||
})
|
})
|
||||||
return str
|
return str
|
||||||
|
|||||||
@@ -122,15 +122,16 @@ const tableStore = new TableStore({
|
|||||||
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: 'showName', minWidth: 150 },
|
{ title: '暂降发生时刻', field: 'startTime', sortable: true, minWidth: 180 },
|
||||||
{
|
{
|
||||||
title: '发生位置', field: 'evtParamPosition', minWidth: 150,
|
title: '暂降(骤升)幅值(%)',
|
||||||
|
field: 'evtParamVVaDepth',
|
||||||
|
minWidth: 160,
|
||||||
formatter: (row: any) => {
|
formatter: (row: any) => {
|
||||||
const val = row.cellValue
|
let a = row.cellValue.split('%')[0] - 0
|
||||||
if (val === null || val === undefined || val === '' || val === '-') return '/'
|
return a ? a.toFixed(2) : '/'
|
||||||
|
},
|
||||||
return val
|
sortable: true
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '持续时间(s)',
|
title: '持续时间(s)',
|
||||||
@@ -145,17 +146,19 @@ const tableStore = new TableStore({
|
|||||||
return Math.floor(num * 10000) / 100
|
return Math.floor(num * 10000) / 100
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ title: '触发类型', field: 'showName', minWidth: 150 },
|
||||||
{
|
{
|
||||||
title: '暂降(聚升)幅值(%)',
|
title: '发生位置', field: 'evtParamPosition', minWidth: 150,
|
||||||
field: 'evtParamVVaDepth',
|
|
||||||
minWidth: 150,
|
|
||||||
formatter: (row: any) => {
|
formatter: (row: any) => {
|
||||||
let a = row.cellValue.split('%')[0] - 0
|
const val = row.cellValue
|
||||||
return a ? a.toFixed(2) : '/'
|
if (val === null || val === undefined || val === '' || val === '-') return '/'
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
},
|
},
|
||||||
sortable: true
|
|
||||||
},
|
|
||||||
{ title: '发生时刻', field: 'startTime', sortable: true, minWidth: 180 },
|
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
@@ -229,6 +232,7 @@ const tableStore = new TableStore({
|
|||||||
return !row.wavePath
|
return !row.wavePath
|
||||||
},
|
},
|
||||||
click: row => {
|
click: row => {
|
||||||
|
ElMessage.info('下载中......')
|
||||||
getFileZip({ eventId: row.id }).then(res => {
|
getFileZip({ eventId: row.id }).then(res => {
|
||||||
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)
|
||||||
@@ -238,6 +242,7 @@ const tableStore = new TableStore({
|
|||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
link.click() //执行下载
|
link.click() //执行下载
|
||||||
document.body.removeChild(link) //释放标签
|
document.body.removeChild(link) //释放标签
|
||||||
|
ElMessage.success('波形下载成功')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,7 +267,7 @@ const deviceTypeChange = (val: any, obj: any) => {
|
|||||||
}
|
}
|
||||||
const nodeClick = async (e: anyObj) => {
|
const nodeClick = async (e: anyObj) => {
|
||||||
// console.log("🚀 ~ nodeClick ~ e:", e)
|
// console.log("🚀 ~ nodeClick ~ e:", e)
|
||||||
if (e.level == 2 && flag.value) {
|
if ((e.level == 2 || e.level == 3) && flag.value) {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
tableStore.table.params.deviceId = e.id
|
tableStore.table.params.deviceId = e.id
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
</TableHeader>
|
</TableHeader>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-empty description="暂无数据" v-if="!echartsData" style="flex: 1"></el-empty>
|
<el-empty description="暂无数据" v-if="!echartsData" style="flex: 1;margin-top: 10%"></el-empty>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div :style="echartHeight">
|
<div :style="echartHeight">
|
||||||
<MyEchart :options="echartsData" />
|
<MyEchart :options="echartsData" />
|
||||||
|
|||||||
@@ -42,13 +42,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, provide } from 'vue'
|
import { onMounted, onUnmounted, ref, provide } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import pointTreeWx from '@/components/tree/govern/pointTreeWx.vue'
|
import pointTreeWx from '@/components/tree/govern/pointTreeWx.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 { exportExcel } from '@/views/system/reportForms/export.js'
|
import { destroyLuckysheet, exportLuckysheetFile, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||||
|
import { isLineTreeLeaf } from '@/components/tree/govern/lineTreeUtils'
|
||||||
import DatePicker from '@/components/form/datePicker/time.vue'
|
import DatePicker from '@/components/form/datePicker/time.vue'
|
||||||
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTreeZL.vue'
|
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTreeZL.vue'
|
||||||
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||||
@@ -77,35 +78,20 @@ const tableStore = new TableStore({
|
|||||||
// ;(tableStore.table.params.startTime = datePickerRef.value.timeValue[0]),
|
// ;(tableStore.table.params.startTime = datePickerRef.value.timeValue[0]),
|
||||||
// (tableStore.table.params.endTime = datePickerRef.value.timeValue[1]),
|
// (tableStore.table.params.endTime = datePickerRef.value.timeValue[1]),
|
||||||
if (!tableStore.table.params.tempId) {
|
if (!tableStore.table.params.tempId) {
|
||||||
return ElMessage.warning('请选择模板')
|
ElMessage.warning('请选择模板')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!dotList.value?.id) {
|
||||||
|
ElMessage.warning('请选择监测点')
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
delete tableStore.table.params.searchBeginTime
|
delete tableStore.table.params.searchBeginTime
|
||||||
delete tableStore.table.params.searchEndTime
|
delete tableStore.table.params.searchEndTime
|
||||||
delete tableStore.table.params.timeFlag
|
delete tableStore.table.params.timeFlag
|
||||||
},
|
},
|
||||||
loadCallback: () => {
|
loadCallback: () => {
|
||||||
console.log('🚀 ~ tableStore.table:', tableStore.table.data)
|
|
||||||
name.value = dotList.value.name
|
name.value = dotList.value.name
|
||||||
// tableStore.table.data.forEach((item: any) => {
|
renderLuckysheetReport('luckysheet', tableStore.table.data, { allowEdit: false })
|
||||||
// item.data1 ? (item.data = JSON.parse(item.data1)) : ''
|
|
||||||
// item.celldata.forEach((k: any) => {
|
|
||||||
// item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
luckysheet.create({
|
|
||||||
container: 'luckysheet',
|
|
||||||
title: '', // 表 头名
|
|
||||||
lang: 'zh', // 中文
|
|
||||||
showtoolbar: false, // 是否显示工具栏
|
|
||||||
showinfobar: false, // 是否显示顶部信息栏
|
|
||||||
showsheetbar: true, // 是否显示底部sheet按钮
|
|
||||||
allowEdit: false, // 禁止所有编辑操作(必填)
|
|
||||||
data: tableStore.table.data
|
|
||||||
// tableStore.table.data
|
|
||||||
})
|
|
||||||
}, 10)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
@@ -115,6 +101,9 @@ const flag = ref(true)
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initListByIds()
|
initListByIds()
|
||||||
})
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroyLuckysheet()
|
||||||
|
})
|
||||||
|
|
||||||
const idList = ref([])
|
const idList = ref([])
|
||||||
// 监测对象
|
// 监测对象
|
||||||
@@ -131,7 +120,6 @@ const initListByIds = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const stencil = (val: any) => {
|
const stencil = (val: any) => {
|
||||||
console.log('🚀 ~ stencil ~ val:', val)
|
|
||||||
templatePolicy.value = val.filter((item: any) => item.excelType == '4')
|
templatePolicy.value = val.filter((item: any) => item.excelType == '4')
|
||||||
Template.value = templatePolicy.value[0]
|
Template.value = templatePolicy.value[0]
|
||||||
reportForm.value = templatePolicy.value[0]?.excelType
|
reportForm.value = templatePolicy.value[0]?.excelType
|
||||||
@@ -142,7 +130,7 @@ const changetype = (val: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleNodeClick = (data: any, node: any) => {
|
const handleNodeClick = (data: any, node: any) => {
|
||||||
if (data?.level == 3) {
|
if (isLineTreeLeaf(data) || data?.level == 3) {
|
||||||
dotList.value = data
|
dotList.value = data
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tableStore.index()
|
tableStore.index()
|
||||||
@@ -160,7 +148,7 @@ const exportEvent = () => {
|
|||||||
|
|
||||||
// 格式化YYYY - MM - DD(补零)
|
// 格式化YYYY - MM - DD(补零)
|
||||||
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
||||||
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
|
exportLuckysheetFile(name.value + formattedDate, tableStore.table.data.length > 0)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -484,7 +484,7 @@
|
|||||||
<div style="height: calc(100vh - 340px)" v-if="dataSet.indexOf('_trenddata') != -1">
|
<div style="height: calc(100vh - 340px)" v-if="dataSet.indexOf('_trenddata') != -1">
|
||||||
<Trend ref="trendRef" :TrendList="TrendList"></Trend>
|
<Trend ref="trendRef" :TrendList="TrendList"></Trend>
|
||||||
</div>
|
</div>
|
||||||
<!-- 电镀数据 -->
|
<!-- 电度数据 -->
|
||||||
<div style="height: calc(100vh - 340px)" v-if="dataSet.indexOf('_kilowattHour') != -1">
|
<div style="height: calc(100vh - 340px)" v-if="dataSet.indexOf('_kilowattHour') != -1">
|
||||||
<electroplating ref="electroplatingRef" :TrendList="TrendList"></electroplating>
|
<electroplating ref="electroplatingRef" :TrendList="TrendList"></electroplating>
|
||||||
</div>
|
</div>
|
||||||
@@ -585,7 +585,7 @@ import { ElMessage } from 'element-plus'
|
|||||||
import DatePicker from '@/components/form/datePicker/index.vue'
|
import DatePicker from '@/components/form/datePicker/index.vue'
|
||||||
import Trend from './tabs/trend.vue' //趋势数据
|
import Trend from './tabs/trend.vue' //趋势数据
|
||||||
import realTime from './tabs/realtime.vue' //实时数据-主界面
|
import realTime from './tabs/realtime.vue' //实时数据-主界面
|
||||||
import electroplating from './tabs/electroplating.vue' //电镀数据-主界面
|
import electroplating from './tabs/electroplating.vue' //电度数据-主界面
|
||||||
import realTrend from './tabs/components/realtrend.vue' //实时数据-实时趋势
|
import realTrend from './tabs/components/realtrend.vue' //实时数据-实时趋势
|
||||||
import operatingTrend from './tabs/operatingTrend.vue' //运行趋势
|
import operatingTrend from './tabs/operatingTrend.vue' //运行趋势
|
||||||
import harmonicSpectrum from './tabs/components/harmonicSpectrum.vue' //实时数据-谐波频谱子页面
|
import harmonicSpectrum from './tabs/components/harmonicSpectrum.vue' //实时数据-谐波频谱子页面
|
||||||
@@ -705,6 +705,25 @@ const activeTrendName: any = ref(0)
|
|||||||
const trendTimer: any = ref()
|
const trendTimer: any = ref()
|
||||||
const trendDataTime: any = ref()
|
const trendDataTime: any = ref()
|
||||||
const showButton = ref(false)
|
const showButton = ref(false)
|
||||||
|
|
||||||
|
const decodeMqttPayload = (message: any) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
|
||||||
|
} catch {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 谐波频谱 MQTT 消息(命名函数,便于 off 避免重复注册) */
|
||||||
|
const onMqttTrendMessage = (topic: any, message: any) => {
|
||||||
|
const obj = decodeMqttPayload(message) || {}
|
||||||
|
if ((obj.hasOwnProperty('data1') || obj.hasOwnProperty('data2')) && obj.dataTime) {
|
||||||
|
trendDataTime.value = obj.dataTime
|
||||||
|
realTrendRef.value?.setRealTrendData(obj)
|
||||||
|
tableLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//谐波频谱方法
|
//谐波频谱方法
|
||||||
const handleTrend = async () => {
|
const handleTrend = async () => {
|
||||||
realTimeFlag.value = false
|
realTimeFlag.value = false
|
||||||
@@ -728,21 +747,7 @@ const handleTrend = async () => {
|
|||||||
// console.log(res, '获取谐波频谱数据')
|
// console.log(res, '获取谐波频谱数据')
|
||||||
})
|
})
|
||||||
}, 30000)
|
}, 30000)
|
||||||
mqttRef.value.on('message', (topic: any, message: any) => {
|
bindMqttMessage(onMqttTrendMessage)
|
||||||
let obj = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message)))) || {}
|
|
||||||
if ((obj.hasOwnProperty('data1') || obj.hasOwnProperty('data2')) && obj.dataTime) {
|
|
||||||
trendDataTime.value = obj.dataTime
|
|
||||||
realTrendRef.value && realTrendRef.value.setRealTrendData(obj)
|
|
||||||
tableLoading.value = false
|
|
||||||
// console.log(
|
|
||||||
// '谐波频谱---mqtt接收到消息',
|
|
||||||
// JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
// else {
|
|
||||||
// trendDataTime.value = obj.dataTime
|
|
||||||
// }
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
ElMessage.warning('设备应答失败')
|
ElMessage.warning('设备应答失败')
|
||||||
}
|
}
|
||||||
@@ -885,8 +890,8 @@ const lineId: any = ref('')
|
|||||||
const dataLevel: any = ref('')
|
const dataLevel: any = ref('')
|
||||||
const dataSource = ref([])
|
const dataSource = ref([])
|
||||||
const engineeringName = ref('')
|
const engineeringName = ref('')
|
||||||
const nodeClick = async (e: anyObj, node: any) => {
|
const nodeClick = async (e: anyObj, node?: any) => {
|
||||||
if (e == undefined || e.level == 2) {
|
if (e == undefined) {
|
||||||
return (loading.value = false)
|
return (loading.value = false)
|
||||||
}
|
}
|
||||||
searchValue.value = ''
|
searchValue.value = ''
|
||||||
@@ -900,7 +905,7 @@ const nodeClick = async (e: anyObj, node: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//选中设备名称后,点击标签页也能查询数据,要求点击设备名称后,点击标签页默认查询第一个监测点数据
|
//选中设备名称后,点击标签页也能查询数据,要求点击设备名称后,点击标签页默认查询第一个监测点数据
|
||||||
if (e.level == 3 || e.level == 2) {
|
if (e.level == 3 ) {
|
||||||
engineeringName.value = node?.parent.parent.data.name
|
engineeringName.value = node?.parent.parent.data.name
|
||||||
|
|
||||||
await queryDictType({
|
await queryDictType({
|
||||||
@@ -940,7 +945,7 @@ const nodeClick = async (e: anyObj, node: any) => {
|
|||||||
if (item.type === 'trenddata') {
|
if (item.type === 'trenddata') {
|
||||||
item.id = item.id + '_trenddata'
|
item.id = item.id + '_trenddata'
|
||||||
}
|
}
|
||||||
//电镀数据
|
//电度数据
|
||||||
if (item.type === 'kilowattHour') {
|
if (item.type === 'kilowattHour') {
|
||||||
item.id = item.id + '_kilowattHour'
|
item.id = item.id + '_kilowattHour'
|
||||||
}
|
}
|
||||||
@@ -995,6 +1000,14 @@ const trendRef: any = ref()
|
|||||||
const eventRef: any = ref()
|
const eventRef: any = ref()
|
||||||
const mqttRef = ref()
|
const mqttRef = ref()
|
||||||
const url: any = window.localStorage.getItem('MQTTURL')
|
const url: any = window.localStorage.getItem('MQTTURL')
|
||||||
|
|
||||||
|
/** 同一 handler 先 off 再 on,避免重复 message 监听 */
|
||||||
|
const bindMqttMessage = (handler: (topic: any, message: any) => void) => {
|
||||||
|
if (!mqttRef.value) return
|
||||||
|
mqttRef.value.off('message', handler)
|
||||||
|
mqttRef.value.on('message', handler)
|
||||||
|
}
|
||||||
|
|
||||||
const connectMqtt = () => {
|
const connectMqtt = () => {
|
||||||
if (mqttRef.value) {
|
if (mqttRef.value) {
|
||||||
if (mqttRef.value.connected) {
|
if (mqttRef.value.connected) {
|
||||||
@@ -1035,12 +1048,40 @@ const getRealDataMqttMsg = async () => {
|
|||||||
// console.log(res, '获取基础实时数据')
|
// console.log(res, '获取基础实时数据')
|
||||||
})
|
})
|
||||||
}, 30000)
|
}, 30000)
|
||||||
mqttRef.value.on('message', (topic: any, message: any) => {
|
bindMqttMessage(onMqttRealDataMessage)
|
||||||
// console.log(
|
//2.建立mqtt通讯
|
||||||
// '实时数据&实时趋势---mqtt接收到消息',
|
//每隔30s调用一下接口,通知后台推送mqtt消息
|
||||||
// JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
|
|
||||||
// )
|
mqttRef.value.on('error', (error: any) => {
|
||||||
let obj = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
|
console.log('mqtt连接失败...', error)
|
||||||
|
mqttRef.value.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
mqttRef.value.on('close', function () {
|
||||||
|
console.log('mqtt客户端已断开连接.....')
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
tableLoading.value = false
|
||||||
|
}, 6000)
|
||||||
|
} else {
|
||||||
|
ElMessage.success('设备应答失败')
|
||||||
|
tableLoading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
setTimeout(() => {
|
||||||
|
tableLoading.value = false
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//tab点击事件
|
||||||
|
|
||||||
|
const realDataTimer: any = ref()
|
||||||
|
const mqttMessage = ref<any>({})
|
||||||
|
|
||||||
|
/** 实时数据 / 实时趋势 MQTT 消息(命名函数,便于 off 避免重复注册) */
|
||||||
|
const onMqttRealDataMessage = (topic: any, message: any) => {
|
||||||
|
let obj = decodeMqttPayload(message)
|
||||||
|
|
||||||
if (lineId.value != obj.lineId || adminInfo.userIndex != obj.userId) return
|
if (lineId.value != obj.lineId || adminInfo.userIndex != obj.userId) return
|
||||||
|
|
||||||
@@ -1178,36 +1219,8 @@ const getRealDataMqttMsg = async () => {
|
|||||||
// sonTab.value == 1 &&
|
// sonTab.value == 1 &&
|
||||||
// realTrendRef.value &&
|
// realTrendRef.value &&
|
||||||
// realTrendRef.value.setRealTrendData(obj)
|
// realTrendRef.value.setRealTrendData(obj)
|
||||||
})
|
|
||||||
//2.建立mqtt通讯
|
|
||||||
//每隔30s调用一下接口,通知后台推送mqtt消息
|
|
||||||
|
|
||||||
mqttRef.value.on('error', (error: any) => {
|
|
||||||
console.log('mqtt连接失败...', error)
|
|
||||||
mqttRef.value.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
mqttRef.value.on('close', function () {
|
|
||||||
console.log('mqtt客户端已断开连接.....')
|
|
||||||
})
|
|
||||||
setTimeout(() => {
|
|
||||||
tableLoading.value = false
|
|
||||||
}, 6000)
|
|
||||||
} else {
|
|
||||||
ElMessage.success('设备应答失败')
|
|
||||||
tableLoading.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
setTimeout(() => {
|
|
||||||
tableLoading.value = false
|
|
||||||
}, 0)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
//tab点击事件
|
|
||||||
|
|
||||||
const realDataTimer: any = ref()
|
|
||||||
const mqttMessage = ref<any>({})
|
|
||||||
const handleClick = async (tab?: any) => {
|
const handleClick = async (tab?: any) => {
|
||||||
tableLoading.value = true
|
tableLoading.value = true
|
||||||
showButton.value = false
|
showButton.value = false
|
||||||
@@ -1272,7 +1285,7 @@ const handleClick = async (tab?: any) => {
|
|||||||
tableLoading.value = false
|
tableLoading.value = false
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
//电镀数据
|
//电度数据
|
||||||
if (dataSet.value.includes('_kilowattHour')) {
|
if (dataSet.value.includes('_kilowattHour')) {
|
||||||
let obj = {
|
let obj = {
|
||||||
devId: deviceId.value, //e.id
|
devId: deviceId.value, //e.id
|
||||||
@@ -1475,6 +1488,8 @@ const handleClick = async (tab?: any) => {
|
|||||||
window.clearInterval(trendTimer.value)
|
window.clearInterval(trendTimer.value)
|
||||||
}
|
}
|
||||||
if (mqttRef.value) {
|
if (mqttRef.value) {
|
||||||
|
mqttRef.value.off('message', onMqttTrendMessage)
|
||||||
|
mqttRef.value.off('message', onMqttRealDataMessage)
|
||||||
mqttRef.value.end()
|
mqttRef.value.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1557,6 +1572,8 @@ onBeforeUnmount(() => {
|
|||||||
realDataTimer.value = 0
|
realDataTimer.value = 0
|
||||||
trendTimer.value = 0
|
trendTimer.value = 0
|
||||||
if (mqttRef.value) {
|
if (mqttRef.value) {
|
||||||
|
mqttRef.value.off('message', onMqttTrendMessage)
|
||||||
|
mqttRef.value.off('message', onMqttRealDataMessage)
|
||||||
mqttRef.value.end()
|
mqttRef.value.end()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -293,31 +293,31 @@ const setRealTrendData = (val: any) => {
|
|||||||
if (selectValue.value == '2') {
|
if (selectValue.value == '2') {
|
||||||
if (activeName.value == 2) {
|
if (activeName.value == 2) {
|
||||||
if (numberPart % 2 !== 0 && numberPart < 17) {
|
if (numberPart % 2 !== 0 && numberPart < 17) {
|
||||||
tableData.value[key] = val[key]
|
tableData.value[key] = val[key].toFixed(2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (numberPart % 2 === 0) {
|
if (numberPart % 2 === 0) {
|
||||||
tableData.value[key] = val[key]
|
tableData.value[key] = val[key].toFixed(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (activeName.value == 2) {
|
if (activeName.value == 2) {
|
||||||
if (numberPart % 2 === 0 && numberPart < 17) {
|
if (numberPart % 2 === 0 && numberPart < 17) {
|
||||||
tableData.value[key] = val[key]
|
tableData.value[key] = val[key].toFixed(2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (numberPart % 2 !== 0) {
|
if (numberPart % 2 !== 0) {
|
||||||
tableData.value[key] = val[key]
|
tableData.value[key] = val[key].toFixed(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (activeName.value == 2) {
|
if (activeName.value == 2) {
|
||||||
if (numberPart < 17) {
|
if (numberPart < 17) {
|
||||||
tableData.value[key] = val[key]
|
tableData.value[key] = val[key].toFixed(2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tableData.value[key] = val[key]
|
tableData.value[key] = val[key].toFixed(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,25 +20,15 @@
|
|||||||
|
|
||||||
<el-button @click="handleBack" :icon="Back">返回</el-button>
|
<el-button @click="handleBack" :icon="Back">返回</el-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- v-loading="loading" -->
|
<!-- -->
|
||||||
<el-tabs class="home_body" type="border-card" v-model.trim="activeName1" @tab-click="handleClick">
|
<el-tabs class="home_body" v-loading="loading" type="border-card" v-model.trim="activeName1" @tab-click="handleClick">
|
||||||
<el-tab-pane label="瞬时波形" name="ssbx" :style="'height:' + bxecharts + ';overflow-y: auto;'">
|
<el-tab-pane label="瞬时波形" name="ssbx" :style="'height:' + bxecharts + ';overflow-y: auto;'">
|
||||||
<shushiboxi
|
<shushiboxi v-if="isWp && wp && activeName == 'ssbx' && showBoxi" :value="value" :boxoList="boxoList"
|
||||||
v-if="isWp && wp && activeName == 'ssbx' && showBoxi"
|
:parentHeight="parentHeight" :wp="wp"></shushiboxi>
|
||||||
:value="value"
|
|
||||||
:boxoList="boxoList"
|
|
||||||
:parentHeight="parentHeight"
|
|
||||||
:wp="wp"
|
|
||||||
></shushiboxi>
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="RMS波形" name="rmsbx" :style="'height:' + bxecharts + ';overflow-y: auto;'">
|
<el-tab-pane label="RMS波形" name="rmsbx" :style="'height:' + bxecharts + ';overflow-y: auto;'">
|
||||||
<rmsboxi
|
<rmsboxi v-if="isWp && wp && activeName == 'rmsbx' && showBoxi" :value="value" :boxoList="boxoList"
|
||||||
v-if="isWp && wp && activeName == 'rmsbx' && showBoxi"
|
:parentHeight="parentHeight" :wp="wp"></rmsboxi>
|
||||||
:value="value"
|
|
||||||
:boxoList="boxoList"
|
|
||||||
:parentHeight="parentHeight"
|
|
||||||
:wp="wp"
|
|
||||||
></rmsboxi>
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,11 +107,10 @@ const getWpData = (val: any, list: any) => {
|
|||||||
const changeView = () => {
|
const changeView = () => {
|
||||||
showBoxi.value = false
|
showBoxi.value = false
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
value.value = theTypeOfValue.value
|
value.value = theTypeOfValue.value
|
||||||
showBoxi.value = true
|
showBoxi.value = true
|
||||||
}, 500)
|
|
||||||
setTimeout(() => {
|
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
@@ -148,7 +137,7 @@ const setHeight = (h: any, vh: any, num = 1) => {
|
|||||||
bxecharts.value = mainHeight(vh, num).height
|
bxecharts.value = mainHeight(vh, num).height
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
onMounted(() => {})
|
onMounted(() => { })
|
||||||
defineExpose({ getWpData, setHeight })
|
defineExpose({ getWpData, setHeight })
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- 电镀数据数据 -->
|
<!-- 电度数据数据 -->
|
||||||
<div>
|
<div>
|
||||||
<TableHeader ref="tableHeaderRef" :showSearch="false" @selectChange="selectChange">
|
<TableHeader ref="tableHeaderRef" :showSearch="false" @selectChange="selectChange">
|
||||||
<template v-slot:select>
|
<template v-slot:select>
|
||||||
@@ -310,7 +310,7 @@ const setEchart = () => {
|
|||||||
exportCSV(
|
exportCSV(
|
||||||
echartsData.value.options.series.map((item: any) => item.name),
|
echartsData.value.options.series.map((item: any) => item.name),
|
||||||
dataList,
|
dataList,
|
||||||
'电镀数据.csv'
|
'电度数据.csv'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,8 @@
|
|||||||
<TableHeader datePicker ref="headerRef" :showReset="false"></TableHeader>
|
<TableHeader datePicker ref="headerRef" :showReset="false"></TableHeader>
|
||||||
<Table ref="tableRef" />
|
<Table ref="tableRef" />
|
||||||
</div>
|
</div>
|
||||||
<waveFormAnalysis
|
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
|
||||||
v-loading="loading"
|
@handleHideCharts="isWaveCharts = false" :wp="wp" />
|
||||||
v-if="isWaveCharts"
|
|
||||||
ref="waveFormAnalysisRef"
|
|
||||||
@handleHideCharts="isWaveCharts = false"
|
|
||||||
:wp="wp"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -57,16 +52,23 @@ const tableStore: any = new TableStore({
|
|||||||
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: 170, sortable: true },
|
{ field: 'startTime', title: '暂降发生时刻', minWidth: 180, sortable: true },
|
||||||
{ field: 'showName', title: '事件描述', minWidth: 120 },
|
|
||||||
{
|
{
|
||||||
field: 'phaseType',
|
field: 'featureAmplitude',
|
||||||
title: '相别',
|
title: '暂降(骤升)幅值(%)',
|
||||||
minWidth: 80,
|
minWidth: 160,
|
||||||
|
sortable: true,
|
||||||
formatter: (row: any) => {
|
formatter: (row: any) => {
|
||||||
return row.cellValue || '/'
|
//row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
|
||||||
|
row.cellValue = row.cellValue != null ? Number(row.cellValue).toFixed(2) : '/'
|
||||||
|
if (String(row.cellValue).split('.')[1] == '00') {
|
||||||
|
row.cellValue = String(row.cellValue).split('.')[0]
|
||||||
|
}
|
||||||
|
return row.cellValue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'persistTime',
|
field: 'persistTime',
|
||||||
title: '持续时间(s)',
|
title: '持续时间(s)',
|
||||||
@@ -79,18 +81,17 @@ const tableStore: any = new TableStore({
|
|||||||
sortable: true
|
sortable: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'featureAmplitude',
|
field: 'phaseType',
|
||||||
title: '暂降(聚升)幅值(%)',
|
title: '相别',
|
||||||
minWidth: 130,
|
minWidth: 80,
|
||||||
formatter: (row: any) => {
|
formatter: (row: any) => {
|
||||||
//row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
|
return row.cellValue || '/'
|
||||||
row.cellValue = row.cellValue != null ? Number(row.cellValue).toFixed(2) : '/'
|
|
||||||
if (String(row.cellValue).split('.')[1] == '00') {
|
|
||||||
row.cellValue = String(row.cellValue).split('.')[0]
|
|
||||||
}
|
|
||||||
return row.cellValue
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ field: 'showName', title: '触发类型', minWidth: 120 },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
@@ -149,7 +150,7 @@ const tableStore: any = new TableStore({
|
|||||||
icon: 'el-icon-DataLine',
|
icon: 'el-icon-DataLine',
|
||||||
render: 'basicButton',
|
render: 'basicButton',
|
||||||
disabled: row => {
|
disabled: row => {
|
||||||
return row.showName != '未知'
|
return row.wavePath
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -164,6 +165,7 @@ const tableStore: any = new TableStore({
|
|||||||
return !row.wavePath
|
return !row.wavePath
|
||||||
},
|
},
|
||||||
click: row => {
|
click: row => {
|
||||||
|
ElMessage.info('下载中......')
|
||||||
getFileZip({ eventId: row.id }).then(res => {
|
getFileZip({ eventId: row.id }).then(res => {
|
||||||
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)
|
||||||
@@ -173,6 +175,7 @@ const tableStore: any = new TableStore({
|
|||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
link.click() //执行下载
|
link.click() //执行下载
|
||||||
document.body.removeChild(link) //释放标签
|
document.body.removeChild(link) //释放标签
|
||||||
|
ElMessage.success('波形下载成功')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -202,7 +205,7 @@ const tableStore: any = new TableStore({
|
|||||||
tableStore.table.params.list = tableParams.value.list
|
tableStore.table.params.list = tableParams.value.list
|
||||||
tableStore.table.params.type = 3
|
tableStore.table.params.type = 3
|
||||||
},
|
},
|
||||||
loadCallback: () => {}
|
loadCallback: () => { }
|
||||||
})
|
})
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
const isWaveCharts = ref(false)
|
const isWaveCharts = ref(false)
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ const deviceTypeChange = (val: any, obj: any) => {
|
|||||||
nodeClick(obj)
|
nodeClick(obj)
|
||||||
}
|
}
|
||||||
const nodeClick = (e: any) => {
|
const nodeClick = (e: any) => {
|
||||||
if (e && (e.level == 2 || e.type == 'device')) {
|
if (e && (e.level == 2 || e.level == 3 || e.type == 'device')) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
nDid.value = e.ndid
|
nDid.value = e.ndid
|
||||||
devId.value = e.id
|
devId.value = e.id
|
||||||
|
|||||||
@@ -137,12 +137,11 @@ const deviceTypeChange = (val: any, obj: any) => {
|
|||||||
}
|
}
|
||||||
// 树节点点击
|
// 树节点点击
|
||||||
const nodeClick = (e: anyObj) => {
|
const nodeClick = (e: anyObj) => {
|
||||||
console.log('🚀 ~ nodeClick ~ e:', e)
|
|
||||||
if (!e) {
|
if (!e) {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (e.level == 2) {
|
if (e.level == 2 || e.level == 3) {
|
||||||
pName.value = e.pName
|
pName.value = e.pName
|
||||||
nDid.value = e.ndid
|
nDid.value = e.ndid
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|||||||
@@ -44,8 +44,28 @@ const tableStore = new TableStore({
|
|||||||
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: 170, sortable: true },
|
{ field: 'startTime', title: '暂降发生时刻', minWidth: 170, sortable: true },
|
||||||
{ field: 'showName', title: '事件描述', minWidth: 170 },
|
{
|
||||||
|
field: 'featureAmplitude',
|
||||||
|
title: '暂降(骤升)幅值(%)',
|
||||||
|
minWidth: 160,
|
||||||
|
formatter: (row: any) => {
|
||||||
|
row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
|
||||||
|
if (String(row.cellValue).split('.')[1] == '00') {
|
||||||
|
row.cellValue = String(row.cellValue).split('.')[0]
|
||||||
|
}
|
||||||
|
return row.cellValue
|
||||||
|
}, sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'persistTime',
|
||||||
|
title: '持续时间(s)',
|
||||||
|
minWidth: 110,
|
||||||
|
formatter: (row: any) => {
|
||||||
|
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
|
||||||
|
return row.cellValue
|
||||||
|
}, sortable: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'phaseType',
|
field: 'phaseType',
|
||||||
title: '相别',
|
title: '相别',
|
||||||
@@ -55,27 +75,9 @@ const tableStore = new TableStore({
|
|||||||
return row.cellValue
|
return row.cellValue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
field: 'persistTime',
|
|
||||||
title: '持续时间(s)',
|
{ field: 'showName', title: '触发类型', minWidth: 170 },
|
||||||
minWidth: 100,
|
|
||||||
formatter: (row: any) => {
|
|
||||||
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
|
|
||||||
return row.cellValue
|
|
||||||
}, sortable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'featureAmplitude',
|
|
||||||
title: '暂降(聚升)幅值(%)',
|
|
||||||
minWidth: 100,
|
|
||||||
formatter: (row: any) => {
|
|
||||||
row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
|
|
||||||
if (String(row.cellValue).split('.')[1] == '00') {
|
|
||||||
row.cellValue = String(row.cellValue).split('.')[0]
|
|
||||||
}
|
|
||||||
return row.cellValue
|
|
||||||
}, sortable: true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '操作', fixed: 'right',
|
title: '操作', fixed: 'right',
|
||||||
width: 180,
|
width: 180,
|
||||||
@@ -143,6 +145,7 @@ const tableStore = new TableStore({
|
|||||||
return !row.wavePath
|
return !row.wavePath
|
||||||
},
|
},
|
||||||
click: row => {
|
click: row => {
|
||||||
|
ElMessage.info('下载中......')
|
||||||
getFileZip({ eventId: row.id }).then(res => {
|
getFileZip({ eventId: row.id }).then(res => {
|
||||||
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)
|
||||||
@@ -152,7 +155,7 @@ const tableStore = new TableStore({
|
|||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
link.click() //执行下载
|
link.click() //执行下载
|
||||||
document.body.removeChild(link) //释放标签
|
document.body.removeChild(link) //释放标签
|
||||||
|
ElMessage.success('波形下载成功')
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
|
<div class="device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
|
||||||
<DeviceTree
|
<DeviceTree ref="treeRef" :showCheckbox="true" :default-checked-keys="defaultCheckedKeys"
|
||||||
ref="treeRef"
|
@checkChange="checkChange" :height="35" :engineering="true"></DeviceTree>
|
||||||
:showCheckbox="true"
|
|
||||||
:default-checked-keys="defaultCheckedKeys"
|
|
||||||
@checkChange="checkChange"
|
|
||||||
:height="35"
|
|
||||||
:engineering="true"
|
|
||||||
></DeviceTree>
|
|
||||||
<div class="device-manage-right" :style="{ height: pageHeight.height }">
|
<div class="device-manage-right" :style="{ height: pageHeight.height }">
|
||||||
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" style="width: 100%">
|
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" style="width: 100%">
|
||||||
<vxe-column field="enginerName" title="工程名称"></vxe-column>
|
<vxe-column field="enginerName" title="工程名称"></vxe-column>
|
||||||
@@ -36,6 +30,7 @@ const tableData = ref([])
|
|||||||
const treeRef = ref(null)
|
const treeRef = ref(null)
|
||||||
const ignoreCheckChange = ref(false)
|
const ignoreCheckChange = ref(false)
|
||||||
const checkChange = (data: any) => {
|
const checkChange = (data: any) => {
|
||||||
|
console.log("🚀 ~ checkChange ~ data:", data)
|
||||||
if (data == undefined) return (loading.value = false)
|
if (data == undefined) return (loading.value = false)
|
||||||
if (data.data.pName == '便携式设备') {
|
if (data.data.pName == '便携式设备') {
|
||||||
if (ignoreCheckChange.value) {
|
if (ignoreCheckChange.value) {
|
||||||
@@ -47,7 +42,7 @@ const checkChange = (data: any) => {
|
|||||||
return treeRef.value?.treRef?.treeRef2?.setCheckedKeys([])
|
return treeRef.value?.treRef?.treeRef2?.setCheckedKeys([])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.data.level === 2) {
|
if (data.data.level === 2 || data.data.level === 3) {
|
||||||
if (data.checked) {
|
if (data.checked) {
|
||||||
defaultCheckedKeys.value.push(data.data.id)
|
defaultCheckedKeys.value.push(data.data.id)
|
||||||
} else {
|
} else {
|
||||||
@@ -100,6 +95,7 @@ onMounted(() => {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 10px 10px 10px 0;
|
padding: 10px 10px 10px 0;
|
||||||
|
|
||||||
.el-descriptions__header {
|
.el-descriptions__header {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
margin-bottom: 7px;
|
margin-bottom: 7px;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
</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>
|
||||||
@@ -144,6 +144,7 @@ import { genFileId, ElMessage, ElNotification } from 'element-plus'
|
|||||||
import type { UploadProps, UploadUserFile } from 'element-plus'
|
import type { UploadProps, UploadUserFile } from 'element-plus'
|
||||||
import pointTree from '@/components/tree/govern/pointTree.vue'
|
import pointTree from '@/components/tree/govern/pointTree.vue'
|
||||||
import { getLineExport } from '@/api/harmonic-boot/cockpit/cockpit'
|
import { getLineExport } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||||
|
import { isReportMonitorPoint } from '@/components/tree/govern/lineTreeUtils'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'TransientReport/monitoringpointReport'
|
name: 'TransientReport/monitoringpointReport'
|
||||||
})
|
})
|
||||||
@@ -212,7 +213,7 @@ const choose = (files: any) => {
|
|||||||
|
|
||||||
//生成报告
|
//生成报告
|
||||||
const exportEvent = () => {
|
const exportEvent = () => {
|
||||||
if (dotList.value?.level != 3) {
|
if (!isReportMonitorPoint(dotList.value)) {
|
||||||
return ElMessage.warning('请选择监测点进行报告生成!')
|
return ElMessage.warning('请选择监测点进行报告生成!')
|
||||||
}
|
}
|
||||||
let a = ''
|
let a = ''
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="default-main" :style="height" style="display: flex; height: 100%; overflow: hidden">
|
<div class="default-main" :style="height" style="display: flex; overflow: hidden">
|
||||||
<div style="width: 280px; flex-shrink: 0; height: 100%; overflow: hidden">
|
<div style="width: 280px; flex-shrink: 0; height: 100%; overflow: hidden">
|
||||||
<pointTree
|
<pointTree
|
||||||
ref="TerminalRef"
|
ref="TerminalRef"
|
||||||
@@ -73,6 +73,7 @@ import { genFileId, ElMessage, ElNotification } from 'element-plus'
|
|||||||
import type { UploadProps, UploadUserFile } from 'element-plus'
|
import type { UploadProps, UploadUserFile } from 'element-plus'
|
||||||
import pointTree from '@/components/tree/govern/pointTree.vue'
|
import pointTree from '@/components/tree/govern/pointTree.vue'
|
||||||
import { exportModel } from '@/api/cs-harmonic-boot/datatrend'
|
import { exportModel } from '@/api/cs-harmonic-boot/datatrend'
|
||||||
|
import { isReportMonitorPoint } from '@/components/tree/govern/lineTreeUtils'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'harmonic-boot/report/word'
|
name: 'harmonic-boot/report/word'
|
||||||
})
|
})
|
||||||
@@ -97,7 +98,9 @@ const pointTypeChange = (val: any, obj: any) => {
|
|||||||
handleNodeClick(obj)
|
handleNodeClick(obj)
|
||||||
}
|
}
|
||||||
const handleNodeClick = (data: any) => {
|
const handleNodeClick = (data: any) => {
|
||||||
|
if (isReportMonitorPoint(data)) {
|
||||||
dotList.value = data
|
dotList.value = data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 上传
|
// 上传
|
||||||
const choose = (files: any) => {
|
const choose = (files: any) => {
|
||||||
@@ -115,7 +118,7 @@ const choose = (files: any) => {
|
|||||||
// 生成
|
// 生成
|
||||||
const exportEvent = () => {
|
const exportEvent = () => {
|
||||||
console.log('🚀 ~ exportEvent ~ dotList.value:', dotList.value)
|
console.log('🚀 ~ exportEvent ~ dotList.value:', dotList.value)
|
||||||
if (dotList.value?.level != 3) {
|
if (!isReportMonitorPoint(dotList.value)) {
|
||||||
return ElMessage.warning('请选择监测点进行报告生成!')
|
return ElMessage.warning('请选择监测点进行报告生成!')
|
||||||
}
|
}
|
||||||
let form = new FormData()
|
let form = new FormData()
|
||||||
|
|||||||
@@ -29,13 +29,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, provide } from 'vue'
|
import { onMounted, onUnmounted, ref, provide } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import PointTree from '@/components/tree/govern/pointTree.vue'
|
import PointTree from '@/components/tree/govern/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 { exportExcel } from '@/views/system/reportForms/export.js'
|
import { destroyLuckysheet, exportLuckysheetFile, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||||
|
import { isLineTreeLeaf } from '@/components/tree/govern/lineTreeUtils'
|
||||||
import 'splitpanes/dist/splitpanes.css'
|
import 'splitpanes/dist/splitpanes.css'
|
||||||
import { Splitpanes, Pane } from 'splitpanes'
|
import { Splitpanes, Pane } from 'splitpanes'
|
||||||
// import data from './123.json'
|
// import data from './123.json'
|
||||||
@@ -74,25 +75,7 @@ const tableStore = new TableStore({
|
|||||||
tableStore.table.params.lineId = dotList.value.id
|
tableStore.table.params.lineId = dotList.value.id
|
||||||
},
|
},
|
||||||
loadCallback: () => {
|
loadCallback: () => {
|
||||||
tableStore.table.data.forEach((item: any) => {
|
renderLuckysheetReport('luckysheet', tableStore.table.data)
|
||||||
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
|
|
||||||
item.celldata.forEach((k: any) => {
|
|
||||||
|
|
||||||
item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
|
|
||||||
})
|
|
||||||
})
|
|
||||||
setTimeout(() => {
|
|
||||||
luckysheet.create({
|
|
||||||
container: 'luckysheet',
|
|
||||||
title: '', // 表 头名
|
|
||||||
lang: 'zh', // 中文
|
|
||||||
showtoolbar: false, // 是否显示工具栏
|
|
||||||
showinfobar: false, // 是否显示顶部信息栏
|
|
||||||
showsheetbar: true, // 是否显示底部sheet按钮
|
|
||||||
data: tableStore.table.data
|
|
||||||
// tableStore.table.data
|
|
||||||
})
|
|
||||||
}, 10)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
@@ -104,6 +87,9 @@ onMounted(() => {
|
|||||||
size.value = ((280 / (dom.offsetWidth - 7)) * 100)
|
size.value = ((280 / (dom.offsetWidth - 7)) * 100)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroyLuckysheet()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const stencil = (val: any) => {
|
const stencil = (val: any) => {
|
||||||
@@ -118,7 +104,7 @@ const changetype = (val: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleNodeClick = (data: any, node: any) => {
|
const handleNodeClick = (data: any, node: any) => {
|
||||||
if (data?.type == "line") {
|
if (isLineTreeLeaf(data)) {
|
||||||
dotList.value = data
|
dotList.value = data
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tableStore.index()
|
tableStore.index()
|
||||||
@@ -127,7 +113,7 @@ const handleNodeClick = (data: any, node: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const exportEvent = () => {
|
const exportEvent = () => {
|
||||||
exportExcel(luckysheet.getAllSheets(), '统计报表下载')
|
exportLuckysheetFile('统计报表下载', tableStore.table.data.length > 0)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -31,14 +31,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, provide } from 'vue'
|
import { ref, provide, onUnmounted } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import pointTreeWx from '@/components/tree/govern/pointTreeWx.vue'
|
import pointTreeWx from '@/components/tree/govern/pointTreeWx.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 { exportExcel } from '@/views/system/reportForms/export.js'
|
import { destroyLuckysheet, exportLuckysheetFile, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||||
import DatePicker from '@/components/form/datePicker/time.vue'
|
import DatePicker from '@/components/form/datePicker/time.vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
const name = ref('')
|
const name = ref('')
|
||||||
// import data from './123.json'
|
// import data from './123.json'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -61,33 +62,19 @@ const tableStore = new TableStore({
|
|||||||
beforeSearchFun: () => {
|
beforeSearchFun: () => {
|
||||||
tableStore.table.params.tempId = Template.value.id
|
tableStore.table.params.tempId = Template.value.id
|
||||||
tableStore.table.params.lineId = dotList.value.id
|
tableStore.table.params.lineId = dotList.value.id
|
||||||
tableStore.table.params.startTime = datePickerRef.value.timeValue[0],
|
if (!datePickerRef.value?.timeValue?.[0] || !datePickerRef.value?.timeValue?.[1]) {
|
||||||
tableStore.table.params.endTime = datePickerRef.value.timeValue[1],
|
ElMessage.warning('请选择时间')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tableStore.table.params.startTime = datePickerRef.value.timeValue[0]
|
||||||
|
tableStore.table.params.endTime = datePickerRef.value.timeValue[1]
|
||||||
delete tableStore.table.params.searchBeginTime
|
delete tableStore.table.params.searchBeginTime
|
||||||
delete tableStore.table.params.searchEndTime
|
delete tableStore.table.params.searchEndTime
|
||||||
delete tableStore.table.params.timeFlag
|
delete tableStore.table.params.timeFlag
|
||||||
},
|
},
|
||||||
loadCallback: () => {
|
loadCallback: () => {
|
||||||
name.value = dotList.value.name
|
name.value = dotList.value.name
|
||||||
tableStore.table.data.forEach((item: any) => {
|
renderLuckysheetReport('luckysheet', tableStore.table.data, { allowEdit: false })
|
||||||
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
|
|
||||||
item.celldata.forEach((k: any) => {
|
|
||||||
|
|
||||||
item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
|
|
||||||
})
|
|
||||||
})
|
|
||||||
setTimeout(() => {
|
|
||||||
luckysheet.create({
|
|
||||||
container: 'luckysheet',
|
|
||||||
title: '', // 表 头名
|
|
||||||
lang: 'zh', // 中文
|
|
||||||
showtoolbar: false, // 是否显示工具栏
|
|
||||||
showinfobar: false, // 是否显示顶部信息栏
|
|
||||||
showsheetbar: true, // 是否显示底部sheet按钮
|
|
||||||
data: tableStore.table.data
|
|
||||||
// tableStore.table.data
|
|
||||||
})
|
|
||||||
}, 10)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
@@ -127,8 +114,11 @@ const exportEvent = () => {
|
|||||||
|
|
||||||
// 格式化YYYY - MM - DD(补零)
|
// 格式化YYYY - MM - DD(补零)
|
||||||
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
||||||
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
|
exportLuckysheetFile(name.value + formattedDate, tableStore.table.data.length > 0)
|
||||||
}
|
}
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroyLuckysheet()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.report-zl-page {
|
.report-zl-page {
|
||||||
|
|||||||
@@ -55,13 +55,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, provide } from 'vue'
|
import { ref, provide, onUnmounted } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import pointTreeWx from '@/components/tree/govern/pointTreeWx.vue'
|
import pointTreeWx from '@/components/tree/govern/pointTreeWx.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 { exportExcel } from '@/views/system/reportForms/export.js'
|
import { destroyLuckysheet, exportLuckysheetFile, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||||
|
import { isLineTreeLeaf } from '@/components/tree/govern/lineTreeUtils'
|
||||||
import DatePicker from '@/components/form/datePicker/time.vue'
|
import DatePicker from '@/components/form/datePicker/time.vue'
|
||||||
import pointTree from '@/components/tree/govern/pointTree.vue'
|
import pointTree from '@/components/tree/govern/pointTree.vue'
|
||||||
// import data from './123.json'
|
// import data from './123.json'
|
||||||
@@ -92,36 +93,8 @@ const tableStore = new TableStore({
|
|||||||
delete tableStore.table.params.timeFlag
|
delete tableStore.table.params.timeFlag
|
||||||
},
|
},
|
||||||
loadCallback: () => {
|
loadCallback: () => {
|
||||||
console.log('🚀 ~ tableStore.table:', tableStore.table)
|
|
||||||
name.value = dotList.value.name
|
name.value = dotList.value.name
|
||||||
// tableStore.table.data.forEach((item: any) => {
|
renderLuckysheetReport('luckysheet', tableStore.table.data, { allowEdit: false })
|
||||||
// item.data1 ? (item.data = JSON.parse(item.data1)) : ''
|
|
||||||
// item.celldata.forEach((k: any) => {
|
|
||||||
|
|
||||||
// item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
tableStore.table.data.forEach((item: any) => {
|
|
||||||
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
|
|
||||||
item.celldata.forEach((k: any) => {
|
|
||||||
item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
|
|
||||||
})
|
|
||||||
})
|
|
||||||
console.log('🚀 ~ tableStore.table:', tableStore.table)
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
luckysheet.create({
|
|
||||||
container: 'luckysheet',
|
|
||||||
title: '', // 表 头名
|
|
||||||
lang: 'zh', // 中文
|
|
||||||
showtoolbar: false, // 是否显示工具栏
|
|
||||||
showinfobar: false, // 是否显示顶部信息栏
|
|
||||||
showsheetbar: true, // 是否显示底部sheet按钮
|
|
||||||
allowEdit: false, // 禁止所有编辑操作(必填)
|
|
||||||
data: tableStore.table.data
|
|
||||||
// tableStore.table.data
|
|
||||||
})
|
|
||||||
}, 10)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
@@ -143,7 +116,7 @@ const pointTypeChange = (val: any, obj: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleNodeClick = (data: any) => {
|
const handleNodeClick = (data: any) => {
|
||||||
if (data?.level == 3) {
|
if (isLineTreeLeaf(data)) {
|
||||||
dotList.value = data
|
dotList.value = data
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tableStore.index()
|
tableStore.index()
|
||||||
@@ -155,14 +128,15 @@ const handleNodeClick = (data: any) => {
|
|||||||
|
|
||||||
const exportEvent = () => {
|
const exportEvent = () => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const year = now.getFullYear() // 4位年份
|
const year = now.getFullYear()
|
||||||
const month = now.getMonth() + 1 // 月份0-11,需+1
|
const month = now.getMonth() + 1
|
||||||
const day = now.getDate() // 日期1-31
|
const day = now.getDate()
|
||||||
|
|
||||||
// 格式化YYYY - MM - DD(补零)
|
|
||||||
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
||||||
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
|
exportLuckysheetFile(name.value + formattedDate, tableStore.table.data.length > 0)
|
||||||
}
|
}
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroyLuckysheet()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.report-zl-page {
|
.report-zl-page {
|
||||||
|
|||||||
@@ -43,13 +43,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, provide } from 'vue'
|
import { onMounted, onUnmounted, ref, provide } from 'vue'
|
||||||
import TableStore from '@/utils/tableStore'
|
import TableStore from '@/utils/tableStore'
|
||||||
import pointTreeWx from '@/components/tree/govern/pointTreeWx.vue'
|
import pointTreeWx from '@/components/tree/govern/pointTreeWx.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 { exportExcel } from '@/views/system/reportForms/export.js'
|
import { destroyLuckysheet, exportLuckysheetFile, renderLuckysheetReport } from '@/utils/luckysheetHelper'
|
||||||
|
import { isLineTreeLeaf } from '@/components/tree/govern/lineTreeUtils'
|
||||||
import DatePicker from '@/components/form/datePicker/time.vue'
|
import DatePicker from '@/components/form/datePicker/time.vue'
|
||||||
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTreeZL.vue'
|
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTreeZL.vue'
|
||||||
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
|
||||||
@@ -80,35 +81,20 @@ const tableStore = new TableStore({
|
|||||||
// ;(tableStore.table.params.startTime = datePickerRef.value.timeValue[0]),
|
// ;(tableStore.table.params.startTime = datePickerRef.value.timeValue[0]),
|
||||||
// (tableStore.table.params.endTime = datePickerRef.value.timeValue[1]),
|
// (tableStore.table.params.endTime = datePickerRef.value.timeValue[1]),
|
||||||
if (!tableStore.table.params.tempId) {
|
if (!tableStore.table.params.tempId) {
|
||||||
return ElMessage.warning('请选择模板')
|
ElMessage.warning('请选择模板')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!dotList.value?.id) {
|
||||||
|
ElMessage.warning('请选择监测点')
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
delete tableStore.table.params.searchBeginTime
|
delete tableStore.table.params.searchBeginTime
|
||||||
delete tableStore.table.params.searchEndTime
|
delete tableStore.table.params.searchEndTime
|
||||||
delete tableStore.table.params.timeFlag
|
delete tableStore.table.params.timeFlag
|
||||||
},
|
},
|
||||||
loadCallback: () => {
|
loadCallback: () => {
|
||||||
console.log('🚀 ~ tableStore.table:', tableStore.table.data)
|
|
||||||
name.value = dotList.value.name
|
name.value = dotList.value.name
|
||||||
// tableStore.table.data.forEach((item: any) => {
|
renderLuckysheetReport('luckysheet', tableStore.table.data, { allowEdit: false })
|
||||||
// item.data1 ? (item.data = JSON.parse(item.data1)) : ''
|
|
||||||
// item.celldata.forEach((k: any) => {
|
|
||||||
// item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
luckysheet.create({
|
|
||||||
container: 'luckysheet',
|
|
||||||
title: '', // 表 头名
|
|
||||||
lang: 'zh', // 中文
|
|
||||||
showtoolbar: false, // 是否显示工具栏
|
|
||||||
showinfobar: false, // 是否显示顶部信息栏
|
|
||||||
showsheetbar: true, // 是否显示底部sheet按钮
|
|
||||||
allowEdit: false, // 禁止所有编辑操作(必填)
|
|
||||||
data: tableStore.table.data
|
|
||||||
// tableStore.table.data
|
|
||||||
})
|
|
||||||
}, 10)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
provide('tableStore', tableStore)
|
provide('tableStore', tableStore)
|
||||||
@@ -118,6 +104,9 @@ const flag = ref(true)
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initListByIds()
|
initListByIds()
|
||||||
})
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
destroyLuckysheet()
|
||||||
|
})
|
||||||
|
|
||||||
const idList = ref([])
|
const idList = ref([])
|
||||||
// 监测对象
|
// 监测对象
|
||||||
@@ -134,7 +123,6 @@ const initListByIds = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const stencil = (val: any) => {
|
const stencil = (val: any) => {
|
||||||
console.log('🚀 ~ stencil ~ val:', val)
|
|
||||||
templatePolicy.value = val.filter((item: any) => item.excelType == '4')
|
templatePolicy.value = val.filter((item: any) => item.excelType == '4')
|
||||||
Template.value = templatePolicy.value[0]
|
Template.value = templatePolicy.value[0]
|
||||||
reportForm.value = templatePolicy.value[0]?.excelType
|
reportForm.value = templatePolicy.value[0]?.excelType
|
||||||
@@ -145,7 +133,7 @@ const changetype = (val: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleNodeClick = (data: any, node: any) => {
|
const handleNodeClick = (data: any, node: any) => {
|
||||||
if (data?.level == 3) {
|
if (isLineTreeLeaf(data) || data?.level == 3) {
|
||||||
dotList.value = data
|
dotList.value = data
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tableStore.index()
|
tableStore.index()
|
||||||
@@ -163,7 +151,7 @@ const exportEvent = () => {
|
|||||||
|
|
||||||
// 格式化YYYY - MM - DD(补零)
|
// 格式化YYYY - MM - DD(补零)
|
||||||
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
|
||||||
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
|
exportLuckysheetFile(name.value + formattedDate, tableStore.table.data.length > 0)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
2
types/table.d.ts
vendored
2
types/table.d.ts
vendored
@@ -30,7 +30,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
loadCallback: (() => void) | null
|
loadCallback: (() => void) | null
|
||||||
resetCallback: (() => void) | null
|
resetCallback: (() => void) | null
|
||||||
beforeSearchFun: (() => void) | null
|
beforeSearchFun: (() => void | boolean) | null
|
||||||
exportProcessingData: (() => void) | null
|
exportProcessingData: (() => void) | null
|
||||||
height: string
|
height: string
|
||||||
publicHeight: number
|
publicHeight: number
|
||||||
|
|||||||
Reference in New Issue
Block a user