|
|
|
@ -30,20 +30,21 @@
|
|
|
|
|
</span>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
|
|
|
|
<!-- WebSocket连接状态指示器 -->
|
|
|
|
|
<!-- WebSocket连接状态指示器 - 已注释,改用全局管理 -->
|
|
|
|
|
<!--
|
|
|
|
|
<el-tooltip :content="websocketStatusText" effect="dark" placement="bottom">
|
|
|
|
|
<span class="websocket-status right-menu-item">
|
|
|
|
|
<i :class="websocketStatusIcon" :style="{ color: websocketStatusColor }"></i>
|
|
|
|
|
</span>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
|
|
|
|
<!-- 告警队列状态指示器 -->
|
|
|
|
|
<el-tooltip :content="alarmQueueStatusText" effect="dark" placement="bottom">
|
|
|
|
|
<span class="alarm-queue-status right-menu-item" @click="showQueueStatus">
|
|
|
|
|
<i class="el-icon-collection" :style="{ color: queueStatusColor }"></i>
|
|
|
|
|
<span v-if="alarmQueueLength > 0" class="queue-count">{{ alarmQueueLength }}</span>
|
|
|
|
|
</span>
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
<screenfull id="screenfull" class="right-menu-item hover-effect"/>
|
|
|
|
|
|
|
|
|
@ -209,7 +210,8 @@
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
<!-- 实时告警弹窗 -->
|
|
|
|
|
<!-- 实时告警弹窗 - 已注释,使用全局弹窗代替 -->
|
|
|
|
|
<!--
|
|
|
|
|
<el-dialog
|
|
|
|
|
title="⚠️ 实时告警通知"
|
|
|
|
|
:visible.sync="realtimeAlarmDialog"
|
|
|
|
@ -220,10 +222,8 @@
|
|
|
|
|
class="realtime-alarm-dialog"
|
|
|
|
|
>
|
|
|
|
|
<el-tabs v-model="realtimeActiveTab" type="card">
|
|
|
|
|
<!-- 告警详情标签页 -->
|
|
|
|
|
<el-tab-pane label="告警详情" name="alarmDetail">
|
|
|
|
|
<div v-if="currentRealtimeAlarm" class="alarm-content">
|
|
|
|
|
<!-- 设备信息 -->
|
|
|
|
|
<div class="alarm-section">
|
|
|
|
|
<h3 class="section-title">📟 设备信息</h3>
|
|
|
|
|
<el-row :gutter="16">
|
|
|
|
@ -242,7 +242,6 @@
|
|
|
|
|
</el-row>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 设备当前数据 -->
|
|
|
|
|
<div class="alarm-section" v-if="currentRealtimeAlarm.deviceParam">
|
|
|
|
|
<h3 class="section-title">📊 设备当前数据</h3>
|
|
|
|
|
<el-row :gutter="16">
|
|
|
|
@ -314,7 +313,6 @@
|
|
|
|
|
</el-row>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 触发的告警规则 -->
|
|
|
|
|
<div class="alarm-section"
|
|
|
|
|
v-if="currentRealtimeAlarm.alarmRules && currentRealtimeAlarm.alarmRules.length > 0">
|
|
|
|
|
<h3 class="section-title">🚨 触发的告警规则</h3>
|
|
|
|
@ -339,7 +337,6 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 告警内容详情 -->
|
|
|
|
|
<div class="alarm-section"
|
|
|
|
|
v-if="currentRealtimeAlarm.alarmContents && currentRealtimeAlarm.alarmContents.length > 0">
|
|
|
|
|
<h3 class="section-title">📋 告警内容详情</h3>
|
|
|
|
@ -361,7 +358,6 @@
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
|
|
<!-- 处置措施标签页 -->
|
|
|
|
|
<el-tab-pane label="处置措施" name="realtimeActionSteps">
|
|
|
|
|
<div v-if="currentRealtimeAlarm">
|
|
|
|
|
<el-alert
|
|
|
|
@ -391,12 +387,10 @@
|
|
|
|
|
<span class="step-title">第{{ step.stepSequence }}步</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤描述 -->
|
|
|
|
|
<div class="step-description">
|
|
|
|
|
<p>{{ step.description }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤图片 -->
|
|
|
|
|
<div v-if="step.stepImages && step.stepImages.length > 0" class="step-images">
|
|
|
|
|
<div class="images-title">参考图片:</div>
|
|
|
|
|
<div class="image-gallery">
|
|
|
|
@ -412,7 +406,6 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤备注 -->
|
|
|
|
|
<div v-if="step.remark" class="step-remark">
|
|
|
|
|
<el-tag type="info" size="small">备注:{{ step.remark }}</el-tag>
|
|
|
|
|
</div>
|
|
|
|
@ -441,6 +434,7 @@
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
@ -458,7 +452,7 @@ import RuoYiDoc from '@/components/RuoYi/Doc'
|
|
|
|
|
import settings from '@/settings'
|
|
|
|
|
import {handleExceptions, listRecordAlarmData} from '@/api/ems/record/recordAlarmData'
|
|
|
|
|
import {getEmsAlarmActionStepsByRuleId, getEmsAlarmActionStepsByAlarmInfo} from '@/api/ems/base/emsAlarmActionStep'
|
|
|
|
|
import {saveWebSocketAlarmData} from '@/api/ems/record/recordAlarmData'
|
|
|
|
|
// import {saveWebSocketAlarmData} from '@/api/ems/record/recordAlarmData' // 已注释,改用全局处理
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
dicts: ['alarm_type', 'alarm_status'],
|
|
|
|
@ -492,61 +486,61 @@ export default {
|
|
|
|
|
imagePreviewVisible: false,
|
|
|
|
|
previewImageUrl: '',
|
|
|
|
|
|
|
|
|
|
// WebSocket告警相关
|
|
|
|
|
realtimeAlarmDialog: false,
|
|
|
|
|
currentRealtimeAlarm: null,
|
|
|
|
|
alarmProcessing: false,
|
|
|
|
|
currentAlarmId: null,
|
|
|
|
|
alarmProcessedCallback: null,
|
|
|
|
|
alarmTimeoutCallback: null,
|
|
|
|
|
websocketStatusText: '',
|
|
|
|
|
websocketStatusIcon: '',
|
|
|
|
|
websocketStatusColor: '',
|
|
|
|
|
alarmQueueStatusText: '',
|
|
|
|
|
queueStatusColor: '',
|
|
|
|
|
alarmQueueLength: 0,
|
|
|
|
|
queueStatusTimer: null,
|
|
|
|
|
// WebSocket告警相关 - 实时告警弹窗已注释,改用全局弹窗
|
|
|
|
|
// realtimeAlarmDialog: false,
|
|
|
|
|
// currentRealtimeAlarm: null,
|
|
|
|
|
// alarmProcessing: false,
|
|
|
|
|
// currentAlarmId: null,
|
|
|
|
|
// alarmProcessedCallback: null,
|
|
|
|
|
// alarmTimeoutCallback: null,
|
|
|
|
|
// websocketStatusText: '',
|
|
|
|
|
// websocketStatusIcon: '',
|
|
|
|
|
// websocketStatusColor: '',
|
|
|
|
|
// alarmQueueStatusText: '',
|
|
|
|
|
// queueStatusColor: '',
|
|
|
|
|
// alarmQueueLength: 0,
|
|
|
|
|
// queueStatusTimer: null // 已注释,改用全局管理
|
|
|
|
|
|
|
|
|
|
// 实时告警处置措施相关
|
|
|
|
|
realtimeActiveTab: 'alarmDetail',
|
|
|
|
|
realtimeActionSteps: [],
|
|
|
|
|
realtimeActionStepsLoading: false
|
|
|
|
|
// 实时告警处置措施相关 - 已注释
|
|
|
|
|
// realtimeActiveTab: 'alarmDetail',
|
|
|
|
|
// realtimeActionSteps: [],
|
|
|
|
|
// realtimeActionStepsLoading: false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
created() {
|
|
|
|
|
localStorage.setItem('this.alarmDataTotal', 0)
|
|
|
|
|
|
|
|
|
|
// 监听新的队列化WebSocket告警事件
|
|
|
|
|
this.$bus.$on('websocket-alarm-with-callback', this.handleQueuedRealtimeAlarm)
|
|
|
|
|
// 监听自动超时保存事件
|
|
|
|
|
this.$bus.$on('websocket-alarm-auto-save', this.handleAutoSaveAlarm)
|
|
|
|
|
// 监听WebSocket连接状态变化
|
|
|
|
|
this.$bus.$on('websocket-connected', this.onWebSocketConnected)
|
|
|
|
|
this.$bus.$on('websocket-disconnected', this.onWebSocketDisconnected)
|
|
|
|
|
this.$bus.$on('websocket-max-retries-reached', this.onWebSocketMaxRetriesReached)
|
|
|
|
|
// 监听新的队列化WebSocket告警事件 - 已注释,改用全局弹窗
|
|
|
|
|
// this.$bus.$on('websocket-alarm-with-callback', this.handleQueuedRealtimeAlarm)
|
|
|
|
|
// 监听自动超时保存事件 - 已注释,改用全局弹窗
|
|
|
|
|
// this.$bus.$on('websocket-alarm-auto-save', this.handleAutoSaveAlarm)
|
|
|
|
|
// 监听WebSocket连接状态变化 - 已注释,改用全局管理
|
|
|
|
|
// this.$bus.$on('websocket-connected', this.onWebSocketConnected)
|
|
|
|
|
// this.$bus.$on('websocket-disconnected', this.onWebSocketDisconnected)
|
|
|
|
|
// this.$bus.$on('websocket-max-retries-reached', this.onWebSocketMaxRetriesReached)
|
|
|
|
|
},
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
// 移除所有事件监听
|
|
|
|
|
this.$bus.$off('websocket-alarm-with-callback', this.handleQueuedRealtimeAlarm)
|
|
|
|
|
this.$bus.$off('websocket-alarm-auto-save', this.handleAutoSaveAlarm)
|
|
|
|
|
this.$bus.$off('websocket-connected', this.onWebSocketConnected)
|
|
|
|
|
this.$bus.$off('websocket-disconnected', this.onWebSocketDisconnected)
|
|
|
|
|
this.$bus.$off('websocket-max-retries-reached', this.onWebSocketMaxRetriesReached)
|
|
|
|
|
// 移除所有事件监听 - 实时告警相关已注释
|
|
|
|
|
// this.$bus.$off('websocket-alarm-with-callback', this.handleQueuedRealtimeAlarm)
|
|
|
|
|
// this.$bus.$off('websocket-alarm-auto-save', this.handleAutoSaveAlarm)
|
|
|
|
|
// this.$bus.$off('websocket-connected', this.onWebSocketConnected)
|
|
|
|
|
// this.$bus.$off('websocket-disconnected', this.onWebSocketDisconnected)
|
|
|
|
|
// this.$bus.$off('websocket-max-retries-reached', this.onWebSocketMaxRetriesReached)
|
|
|
|
|
|
|
|
|
|
// 清理定时器
|
|
|
|
|
if (this.queueStatusTimer) {
|
|
|
|
|
clearInterval(this.queueStatusTimer)
|
|
|
|
|
this.queueStatusTimer = null
|
|
|
|
|
}
|
|
|
|
|
// 清理定时器 - 已注释,改用全局管理
|
|
|
|
|
// if (this.queueStatusTimer) {
|
|
|
|
|
// clearInterval(this.queueStatusTimer)
|
|
|
|
|
// this.queueStatusTimer = null
|
|
|
|
|
// }
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
// 初始获取告警数据,后续完全依赖WebSocket推送
|
|
|
|
|
this.getAlarmData()
|
|
|
|
|
|
|
|
|
|
// 定期更新告警队列状态
|
|
|
|
|
this.queueStatusTimer = setInterval(() => {
|
|
|
|
|
this.updateQueueStatus()
|
|
|
|
|
}, 2000) // 每2秒更新一次状态
|
|
|
|
|
// 定期更新告警队列状态 - 已注释,改用全局管理
|
|
|
|
|
// this.queueStatusTimer = setInterval(() => {
|
|
|
|
|
// this.updateQueueStatus()
|
|
|
|
|
// }, 2000) // 每2秒更新一次状态
|
|
|
|
|
},
|
|
|
|
|
components: {
|
|
|
|
|
Breadcrumb,
|
|
|
|
@ -692,7 +686,8 @@ export default {
|
|
|
|
|
const baseURL = process.env.VUE_APP_BASE_API || '';
|
|
|
|
|
return baseURL + relativePath;
|
|
|
|
|
},
|
|
|
|
|
// 处理队列化的WebSocket实时告警
|
|
|
|
|
// 处理队列化的WebSocket实时告警 - 已注释,改用全局弹窗
|
|
|
|
|
/*
|
|
|
|
|
handleQueuedRealtimeAlarm(data) {
|
|
|
|
|
console.log('收到队列化实时告警:', data)
|
|
|
|
|
|
|
|
|
@ -729,7 +724,9 @@ export default {
|
|
|
|
|
console.error('播放提示音失败:', error)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 保存WebSocket告警数据到数据库
|
|
|
|
|
*/
|
|
|
|
|
// 保存WebSocket告警数据到数据库 - 已注释,改用全局处理
|
|
|
|
|
/*
|
|
|
|
|
async saveRealtimeAlarmData(alarmData, alarmStatus = 1) {
|
|
|
|
|
try {
|
|
|
|
|
// 构建符合EmsRecordAlarmData实体的数据列表
|
|
|
|
@ -848,7 +845,9 @@ export default {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 稍后处理实时告警(保存为未处理状态)
|
|
|
|
|
*/
|
|
|
|
|
// 稍后处理实时告警(保存为未处理状态) - 已注释,改用全局弹窗
|
|
|
|
|
/*
|
|
|
|
|
async closeRealtimeAlarmDialog() {
|
|
|
|
|
if (this.currentRealtimeAlarm) {
|
|
|
|
|
this.alarmProcessing = true
|
|
|
|
@ -911,7 +910,9 @@ export default {
|
|
|
|
|
this.realtimeActionSteps = []
|
|
|
|
|
this.realtimeActionStepsLoading = false
|
|
|
|
|
},
|
|
|
|
|
// 格式化告警时间
|
|
|
|
|
*/
|
|
|
|
|
// 格式化告警时间 - 已注释,主要用于实时告警弹窗
|
|
|
|
|
/*
|
|
|
|
|
formatAlarmTime(time) {
|
|
|
|
|
if (!time) return '--'
|
|
|
|
|
try {
|
|
|
|
@ -921,6 +922,7 @@ export default {
|
|
|
|
|
return time
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
*/
|
|
|
|
|
// 获取监测字段名称
|
|
|
|
|
getFieldName(fieldCode) {
|
|
|
|
|
const fieldMap = {
|
|
|
|
@ -936,7 +938,8 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
return fieldMap[fieldCode] || '未知字段'
|
|
|
|
|
},
|
|
|
|
|
// 处理WebSocket连接状态变化
|
|
|
|
|
// 处理WebSocket连接状态变化 - 已注释,改用全局管理
|
|
|
|
|
/*
|
|
|
|
|
onWebSocketConnected() {
|
|
|
|
|
console.log('WebSocket连接成功')
|
|
|
|
|
this.websocketStatusText = 'WebSocket连接成功'
|
|
|
|
@ -971,6 +974,9 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
*/
|
|
|
|
|
// 显示队列状态 - 已注释,改用全局管理
|
|
|
|
|
/*
|
|
|
|
|
showQueueStatus() {
|
|
|
|
|
// 获取告警队列状态并显示
|
|
|
|
|
if (this.$root.getAlarmQueueStatus) {
|
|
|
|
@ -992,6 +998,9 @@ export default {
|
|
|
|
|
this.$message.info('无法获取队列状态信息')
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
*/
|
|
|
|
|
// 队列状态更新 - 已注释,改用全局管理
|
|
|
|
|
/*
|
|
|
|
|
updateQueueStatus() {
|
|
|
|
|
// 从App.vue获取告警队列状态
|
|
|
|
|
if (this.$root.getAlarmQueueStatus) {
|
|
|
|
@ -1048,6 +1057,7 @@ export default {
|
|
|
|
|
this.realtimeActionStepsLoading = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
@ -1236,7 +1246,8 @@ export default {
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 实时告警弹窗样式
|
|
|
|
|
// 实时告警弹窗样式 - 已注释,改用全局弹窗
|
|
|
|
|
/*
|
|
|
|
|
.realtime-alarm-dialog {
|
|
|
|
|
.el-dialog__header {
|
|
|
|
|
background: linear-gradient(135deg, #ff4757, #ff6b7a);
|
|
|
|
@ -1358,7 +1369,7 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WebSocket状态和队列状态指示器样式
|
|
|
|
|
// WebSocket状态和队列状态指示器样式 - 已注释,改用全局管理
|
|
|
|
|
.websocket-status {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
@ -1403,6 +1414,7 @@ export default {
|
|
|
|
|
animation: pulse 2s infinite;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@keyframes pulse {
|
|
|
|
|
0% {
|
|
|
|
|