优化项目

This commit is contained in:
guanj
2026-06-04 19:06:36 +08:00
parent 4f32f84132
commit 4f907a80c4
53 changed files with 987 additions and 3499 deletions

View File

@@ -484,7 +484,7 @@
<div style="height: calc(100vh - 340px)" v-if="dataSet.indexOf('_trenddata') != -1">
<Trend ref="trendRef" :TrendList="TrendList"></Trend>
</div>
<!-- 电数据 -->
<!-- 电数据 -->
<div style="height: calc(100vh - 340px)" v-if="dataSet.indexOf('_kilowattHour') != -1">
<electroplating ref="electroplatingRef" :TrendList="TrendList"></electroplating>
</div>
@@ -585,7 +585,7 @@ import { ElMessage } from 'element-plus'
import DatePicker from '@/components/form/datePicker/index.vue'
import Trend from './tabs/trend.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 operatingTrend from './tabs/operatingTrend.vue' //运行趋势
import harmonicSpectrum from './tabs/components/harmonicSpectrum.vue' //实时数据-谐波频谱子页面
@@ -705,6 +705,25 @@ const activeTrendName: any = ref(0)
const trendTimer: any = ref()
const trendDataTime: any = ref()
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 () => {
realTimeFlag.value = false
@@ -728,21 +747,7 @@ const handleTrend = async () => {
// console.log(res, '获取谐波频谱数据')
})
}, 30000)
mqttRef.value.on('message', (topic: any, message: any) => {
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
// }
})
bindMqttMessage(onMqttTrendMessage)
} else {
ElMessage.warning('设备应答失败')
}
@@ -885,8 +890,8 @@ const lineId: any = ref('')
const dataLevel: any = ref('')
const dataSource = ref([])
const engineeringName = ref('')
const nodeClick = async (e: anyObj, node: any) => {
if (e == undefined || e.level == 2) {
const nodeClick = async (e: anyObj, node?: any) => {
if (e == undefined) {
return (loading.value = false)
}
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
await queryDictType({
@@ -940,7 +945,7 @@ const nodeClick = async (e: anyObj, node: any) => {
if (item.type === 'trenddata') {
item.id = item.id + '_trenddata'
}
//电数据
//电数据
if (item.type === 'kilowattHour') {
item.id = item.id + '_kilowattHour'
}
@@ -995,6 +1000,14 @@ const trendRef: any = ref()
const eventRef: any = ref()
const mqttRef = ref()
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 = () => {
if (mqttRef.value) {
if (mqttRef.value.connected) {
@@ -1035,16 +1048,44 @@ const getRealDataMqttMsg = async () => {
// console.log(res, '获取基础实时数据')
})
}, 30000)
mqttRef.value.on('message', (topic: any, message: any) => {
// console.log(
// '实时数据&实时趋势---mqtt接收到消息',
// JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
// )
let obj = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
bindMqttMessage(onMqttRealDataMessage)
//2.建立mqtt通讯
//每隔30s调用一下接口通知后台推送mqtt消息
if (lineId.value != obj.lineId || adminInfo.userIndex != obj.userId) return
mqttRef.value.on('error', (error: any) => {
console.log('mqtt连接失败...', error)
mqttRef.value.end()
})
//处理mqtt数据 1转2除 2转1乘
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
//处理mqtt数据 1转2除 2转1乘
//如果消息返回值是二次值,下拉框是二次值只需要单位换算 除以1000
//如果消息返回值是一次值,下拉框是一次值只需要单位换算 除以1000
if (obj.dataLevel == formInline.dataLevel) {
@@ -1178,36 +1219,8 @@ const getRealDataMqttMsg = async () => {
// sonTab.value == 1 &&
// realTrendRef.value &&
// 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) => {
tableLoading.value = true
showButton.value = false
@@ -1272,7 +1285,7 @@ const handleClick = async (tab?: any) => {
tableLoading.value = false
}, 0)
}
//电数据
//电数据
if (dataSet.value.includes('_kilowattHour')) {
let obj = {
devId: deviceId.value, //e.id
@@ -1475,6 +1488,8 @@ const handleClick = async (tab?: any) => {
window.clearInterval(trendTimer.value)
}
if (mqttRef.value) {
mqttRef.value.off('message', onMqttTrendMessage)
mqttRef.value.off('message', onMqttRealDataMessage)
mqttRef.value.end()
}
}
@@ -1557,6 +1572,8 @@ onBeforeUnmount(() => {
realDataTimer.value = 0
trendTimer.value = 0
if (mqttRef.value) {
mqttRef.value.off('message', onMqttTrendMessage)
mqttRef.value.off('message', onMqttRealDataMessage)
mqttRef.value.end()
}
})

View File

@@ -293,31 +293,31 @@ const setRealTrendData = (val: any) => {
if (selectValue.value == '2') {
if (activeName.value == 2) {
if (numberPart % 2 !== 0 && numberPart < 17) {
tableData.value[key] = val[key]
tableData.value[key] = val[key].toFixed(2)
}
} else {
if (numberPart % 2 === 0) {
tableData.value[key] = val[key]
tableData.value[key] = val[key].toFixed(2)
}
}
} else {
if (activeName.value == 2) {
if (numberPart % 2 === 0 && numberPart < 17) {
tableData.value[key] = val[key]
tableData.value[key] = val[key].toFixed(2)
}
} else {
if (numberPart % 2 !== 0) {
tableData.value[key] = val[key]
tableData.value[key] = val[key].toFixed(2)
}
}
}
} else {
if (activeName.value == 2) {
if (numberPart < 17) {
tableData.value[key] = val[key]
tableData.value[key] = val[key].toFixed(2)
}
} else {
tableData.value[key] = val[key]
tableData.value[key] = val[key].toFixed(2)
}
}
}

View File

@@ -20,25 +20,15 @@
<el-button @click="handleBack" :icon="Back">返回</el-button>
</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;'">
<shushiboxi
v-if="isWp && wp && activeName == 'ssbx' && showBoxi"
:value="value"
:boxoList="boxoList"
:parentHeight="parentHeight"
:wp="wp"
></shushiboxi>
<shushiboxi v-if="isWp && wp && activeName == 'ssbx' && showBoxi" :value="value" :boxoList="boxoList"
:parentHeight="parentHeight" :wp="wp"></shushiboxi>
</el-tab-pane>
<el-tab-pane label="RMS波形" name="rmsbx" :style="'height:' + bxecharts + ';overflow-y: auto;'">
<rmsboxi
v-if="isWp && wp && activeName == 'rmsbx' && showBoxi"
:value="value"
:boxoList="boxoList"
:parentHeight="parentHeight"
:wp="wp"
></rmsboxi>
<rmsboxi v-if="isWp && wp && activeName == 'rmsbx' && showBoxi" :value="value" :boxoList="boxoList"
:parentHeight="parentHeight" :wp="wp"></rmsboxi>
</el-tab-pane>
</el-tabs>
</div>
@@ -117,11 +107,10 @@ const getWpData = (val: any, list: any) => {
const changeView = () => {
showBoxi.value = false
loading.value = true
setTimeout(() => {
value.value = theTypeOfValue.value
showBoxi.value = true
}, 500)
setTimeout(() => {
loading.value = false
}, 1000)
}
@@ -148,7 +137,7 @@ const setHeight = (h: any, vh: any, num = 1) => {
bxecharts.value = mainHeight(vh, num).height
}, 100)
}
onMounted(() => {})
onMounted(() => { })
defineExpose({ getWpData, setHeight })
</script>
<style lang="scss" scoped>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<!-- 数据数据 -->
<!-- 数据数据 -->
<div>
<TableHeader ref="tableHeaderRef" :showSearch="false" @selectChange="selectChange">
<template v-slot:select>
@@ -310,7 +310,7 @@ const setEchart = () => {
exportCSV(
echartsData.value.options.series.map((item: any) => item.name),
dataList,
'电数据.csv'
'电数据.csv'
)
}
}

View File

@@ -4,13 +4,8 @@
<TableHeader datePicker ref="headerRef" :showReset="false"></TableHeader>
<Table ref="tableRef" />
</div>
<waveFormAnalysis
v-loading="loading"
v-if="isWaveCharts"
ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false"
:wp="wp"
/>
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
</div>
</template>
<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
}
},
{ field: 'startTime', title: '发生时刻', minWidth: 170, sortable: true },
{ field: 'showName', title: '事件描述', minWidth: 120 },
{ field: 'startTime', title: '暂降发生时刻', minWidth: 180, sortable: true },
{
field: 'phaseType',
title: '相别',
minWidth: 80,
field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)',
minWidth: 160,
sortable: true,
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',
title: '持续时间(s)',
@@ -79,18 +81,17 @@ const tableStore: any = new TableStore({
sortable: true
},
{
field: 'featureAmplitude',
title: '暂降(聚升)幅值(%)',
minWidth: 130,
field: 'phaseType',
title: '相别',
minWidth: 80,
formatter: (row: any) => {
//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
return row.cellValue || '/'
}
},
{ field: 'showName', title: '触发类型', minWidth: 120 },
{
title: '操作',
fixed: 'right',
@@ -111,7 +112,7 @@ const tableStore: any = new TableStore({
},
click: async row => {
row.loading1 = true
await analyseWave(row.id)
.then(res => {
isWaveCharts.value = true
@@ -149,7 +150,7 @@ const tableStore: any = new TableStore({
icon: 'el-icon-DataLine',
render: 'basicButton',
disabled: row => {
return row.showName != '未知'
return row.wavePath
}
},
{
@@ -164,6 +165,7 @@ const tableStore: any = new TableStore({
return !row.wavePath
},
click: row => {
ElMessage.info('下载中......')
getFileZip({ eventId: row.id }).then(res => {
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob)
@@ -173,6 +175,7 @@ const tableStore: any = new TableStore({
document.body.appendChild(link)
link.click() //执行下载
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.type = 3
},
loadCallback: () => {}
loadCallback: () => { }
})
provide('tableStore', tableStore)
const isWaveCharts = ref(false)

View File

@@ -238,7 +238,7 @@ const deviceTypeChange = (val: any, obj: any) => {
nodeClick(obj)
}
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
nDid.value = e.ndid
devId.value = e.id

View File

@@ -137,12 +137,11 @@ const deviceTypeChange = (val: any, obj: any) => {
}
// 树节点点击
const nodeClick = (e: anyObj) => {
console.log('🚀 ~ nodeClick ~ e:', e)
if (!e) {
loading.value = false
return
}
if (e.level == 2) {
if (e.level == 2 || e.level == 3) {
pName.value = e.pName
nDid.value = e.ndid
loading.value = true

View File

@@ -44,30 +44,11 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'startTime', title: '发生时刻', minWidth: 170, sortable: true },
{ field: 'showName', title: '事件描述', minWidth: 170 },
{
field: 'phaseType',
title: '相别',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue : '/'
return row.cellValue
}
},
{
field: 'persistTime',
title: '持续时间(s)',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue
}, sortable: true
},
{ field: 'startTime', title: '暂降发生时刻', minWidth: 170, sortable: true },
{
field: 'featureAmplitude',
title: '暂降(升)幅值(%)',
minWidth: 100,
title: '暂降(升)幅值(%)',
minWidth: 160,
formatter: (row: any) => {
row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
if (String(row.cellValue).split('.')[1] == '00') {
@@ -76,11 +57,32 @@ const tableStore = new TableStore({
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',
title: '相别',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue : '/'
return row.cellValue
}
},
{ field: 'showName', title: '触发类型', minWidth: 170 },
{
title: '操作', fixed: 'right',
width: 180,
render: 'buttons',
buttons: [
{
name: 'edit',
@@ -95,7 +97,7 @@ const tableStore = new TableStore({
},
click: async row => {
row.loading1 = true
await analyseWave(row.id)
.then(res => {
loading.value = true
@@ -143,6 +145,7 @@ const tableStore = new TableStore({
return !row.wavePath
},
click: row => {
ElMessage.info('下载中......')
getFileZip({ eventId: row.id }).then(res => {
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob)
@@ -152,7 +155,7 @@ const tableStore = new TableStore({
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
ElMessage.success('波形下载成功')
})
}

View File

@@ -1,13 +1,7 @@
<template>
<div class="device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree
ref="treeRef"
:showCheckbox="true"
:default-checked-keys="defaultCheckedKeys"
@checkChange="checkChange"
:height="35"
:engineering="true"
></DeviceTree>
<DeviceTree ref="treeRef" :showCheckbox="true" :default-checked-keys="defaultCheckedKeys"
@checkChange="checkChange" :height="35" :engineering="true"></DeviceTree>
<div class="device-manage-right" :style="{ height: pageHeight.height }">
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" style="width: 100%">
<vxe-column field="enginerName" title="工程名称"></vxe-column>
@@ -36,6 +30,7 @@ const tableData = ref([])
const treeRef = ref(null)
const ignoreCheckChange = ref(false)
const checkChange = (data: any) => {
console.log("🚀 ~ checkChange ~ data:", data)
if (data == undefined) return (loading.value = false)
if (data.data.pName == '便携式设备') {
if (ignoreCheckChange.value) {
@@ -47,7 +42,7 @@ const checkChange = (data: any) => {
return treeRef.value?.treRef?.treeRef2?.setCheckedKeys([])
}
if (data.data.level === 2) {
if (data.data.level === 2 || data.data.level === 3) {
if (data.checked) {
defaultCheckedKeys.value.push(data.data.id)
} else {
@@ -100,6 +95,7 @@ onMounted(() => {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;