|
|
|
@ -212,12 +212,15 @@
|
|
|
|
|
<el-dialog
|
|
|
|
|
title="⚠️ 实时告警通知"
|
|
|
|
|
:visible.sync="realtimeAlarmDialog"
|
|
|
|
|
width="800px"
|
|
|
|
|
width="900px"
|
|
|
|
|
append-to-body
|
|
|
|
|
:close-on-click-modal="false"
|
|
|
|
|
:close-on-press-escape="false"
|
|
|
|
|
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">
|
|
|
|
@ -342,6 +345,71 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
|
|
<!-- 处置措施标签页 -->
|
|
|
|
|
<el-tab-pane label="处置措施" name="realtimeActionSteps">
|
|
|
|
|
<div v-if="currentRealtimeAlarm">
|
|
|
|
|
<el-alert
|
|
|
|
|
:title="`设备:${currentRealtimeAlarm.monitorId} | 告警时间:${formatAlarmTime(currentRealtimeAlarm.recordTime)}`"
|
|
|
|
|
type="warning"
|
|
|
|
|
:closable="false"
|
|
|
|
|
style="margin-bottom: 20px;"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div v-loading="realtimeActionStepsLoading">
|
|
|
|
|
<div v-if="realtimeActionSteps.length === 0" class="no-steps">
|
|
|
|
|
<el-empty description="该告警规则暂无配置处置措施"></el-empty>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-else>
|
|
|
|
|
<el-timeline>
|
|
|
|
|
<el-timeline-item
|
|
|
|
|
v-for="(step, index) in realtimeActionSteps"
|
|
|
|
|
:key="step.objId"
|
|
|
|
|
:timestamp="`步骤 ${step.stepSequence}`"
|
|
|
|
|
placement="top"
|
|
|
|
|
type="primary"
|
|
|
|
|
size="large"
|
|
|
|
|
>
|
|
|
|
|
<el-card class="step-card">
|
|
|
|
|
<div slot="header" class="clearfix">
|
|
|
|
|
<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">
|
|
|
|
|
<div
|
|
|
|
|
v-for="image in step.stepImages"
|
|
|
|
|
:key="image.objId"
|
|
|
|
|
class="image-item"
|
|
|
|
|
@click="previewImage(getFullImageUrl(image.imageUrl))"
|
|
|
|
|
>
|
|
|
|
|
<img :src="getFullImageUrl(image.imageUrl)" :alt="image.description" />
|
|
|
|
|
<div v-if="image.description" class="image-desc">{{ image.description }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤备注 -->
|
|
|
|
|
<div v-if="step.remark" class="step-remark">
|
|
|
|
|
<el-tag type="info" size="small">备注:{{ step.remark }}</el-tag>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
</el-timeline-item>
|
|
|
|
|
</el-timeline>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
</el-tabs>
|
|
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
|
<el-button
|
|
|
|
@ -423,7 +491,12 @@ export default {
|
|
|
|
|
alarmQueueStatusText: '',
|
|
|
|
|
queueStatusColor: '',
|
|
|
|
|
alarmQueueLength: 0,
|
|
|
|
|
queueStatusTimer: null
|
|
|
|
|
queueStatusTimer: null,
|
|
|
|
|
|
|
|
|
|
// 实时告警处置措施相关
|
|
|
|
|
realtimeActiveTab: 'alarmDetail',
|
|
|
|
|
realtimeActionSteps: [],
|
|
|
|
|
realtimeActionStepsLoading: false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
created() {
|
|
|
|
@ -617,12 +690,18 @@ export default {
|
|
|
|
|
this.alarmProcessedCallback = onProcessed
|
|
|
|
|
this.alarmTimeoutCallback = onTimeout
|
|
|
|
|
|
|
|
|
|
// 重置标签页到告警详情
|
|
|
|
|
this.realtimeActiveTab = 'alarmDetail'
|
|
|
|
|
|
|
|
|
|
// 显示告警弹窗
|
|
|
|
|
this.realtimeAlarmDialog = true
|
|
|
|
|
|
|
|
|
|
// 播放提示音
|
|
|
|
|
this.playAlarmSound()
|
|
|
|
|
|
|
|
|
|
// 自动加载第一个告警规则的处置措施
|
|
|
|
|
this.loadRealtimeActionSteps(alarm)
|
|
|
|
|
|
|
|
|
|
console.log('告警弹窗已显示,告警ID:', alarm.id, '优先级:', alarm.priority)
|
|
|
|
|
},
|
|
|
|
|
// 播放告警提示音
|
|
|
|
@ -812,6 +891,11 @@ export default {
|
|
|
|
|
this.currentAlarmId = null
|
|
|
|
|
this.alarmProcessedCallback = null
|
|
|
|
|
this.alarmTimeoutCallback = null
|
|
|
|
|
|
|
|
|
|
// 清理实时告警处置措施数据
|
|
|
|
|
this.realtimeActiveTab = 'alarmDetail'
|
|
|
|
|
this.realtimeActionSteps = []
|
|
|
|
|
this.realtimeActionStepsLoading = false
|
|
|
|
|
},
|
|
|
|
|
// 格式化告警时间
|
|
|
|
|
formatAlarmTime(time) {
|
|
|
|
@ -926,6 +1010,29 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 加载实时告警的处置措施
|
|
|
|
|
async loadRealtimeActionSteps(alarm) {
|
|
|
|
|
if (!alarm || !alarm.alarmRules || alarm.alarmRules.length === 0) {
|
|
|
|
|
this.realtimeActionSteps = []
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.realtimeActionStepsLoading = true
|
|
|
|
|
try {
|
|
|
|
|
// 使用第一个告警规则的字段信息来获取处置措施
|
|
|
|
|
const firstRule = alarm.alarmRules[0]
|
|
|
|
|
const fieldName = this.getFieldName(firstRule.monitorField)
|
|
|
|
|
|
|
|
|
|
const response = await getEmsAlarmActionStepsByAlarmInfo(alarm.monitorId, fieldName)
|
|
|
|
|
this.realtimeActionSteps = response.data || []
|
|
|
|
|
console.log('实时告警处置措施加载成功:', this.realtimeActionSteps.length, '个步骤')
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载实时告警处置措施失败:', error)
|
|
|
|
|
this.realtimeActionSteps = []
|
|
|
|
|
} finally {
|
|
|
|
|
this.realtimeActionStepsLoading = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|