交互式开关和响应式弹窗总线数据监听和传递

This commit is contained in:
龚皓 2024-11-22 17:33:57 +08:00
parent 6c39f1aa5f
commit a8266b78eb
1 changed files with 77 additions and 42 deletions

View File

@ -1,34 +1,59 @@
import { ref } from 'vue'; import { ref } from 'vue';
import { ElMessage, ElNotification } from 'element-plus'; import { ElMessage, ElNotification } from 'element-plus';
import eventBus from '@/utils/eventBus'; import eventBus from '@/utils/eventBus';
import dayjs from 'dayjs';
import { BoxApi } from '@/utils/boxApi';
const apiInstance = new BoxApi();
const websocket = ref<WebSocket | null>(null); const algorithmMap = ref(new Map());
const isWebSocketConnected = ref(false);
let heartbeatInterval: number | null = null;
// 加载算法映射表
const loadAlgorithms = async () => {
const token = localStorage.getItem('alertToken');
if (token) {
const algorithms = await apiInstance.getAlgorithms(token);
algorithmMap.value = new Map(
algorithms.map((algo: { code_name: string; name: string }) => [algo.code_name, algo.name])
);
} else {
console.error('Token 未找到,请登录');
}
};
const websocket = ref<WebSocket | null>(null); // WebSocket 实例
const isWebSocketConnected = ref(false); // WebSocket 连接状态
let heartbeatInterval: number | null = null; // 心跳定时器
const formatDateTime = (isoString: string): string => dayjs(isoString).format('YYYY-MM-DD HH:mm:ss');
// 连接 WebSocket // 连接 WebSocket
const connectWebSocket = () => { const connectWebSocket = () => {
websocket.value = new WebSocket(`ws://192.168.28.33:8080/ws/event`); const rememberedAddress = localStorage.getItem('rememberedAddress'); // 获取存储的主机地址
if (rememberedAddress) {
websocket.value = new WebSocket(`ws://${rememberedAddress}:8080/ws/event`);
// websocket.value = new WebSocket(`ws://192.168.28.33:8080/ws/event`);
loadAlgorithms();
websocket.value.onopen = () => { websocket.value.onopen = () => {
ElMessage.success('全局 WebSocket 连接成功'); ElMessage.success('全局 WebSocket 连接成功');
isWebSocketConnected.value = true; isWebSocketConnected.value = true;
}; };
websocket.value.onmessage = (event) => { websocket.value.onmessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data); // 解析收到的数据
handlePopupNotification(data); // 根据模式处理弹窗通知
// 显示通知,并在点击时通过 eventBus 触发全局弹窗事件
showNotification(data);
}; };
websocket.value.onclose = handleClose; websocket.value.onclose = handleClose; // 处理连接关闭
websocket.value.onerror = handleError; websocket.value.onerror = handleError; // 处理连接错误
} else {
ElMessage.error('主机地址获取失败,请重新登录');
}
}; };
// 关闭 WebSocket // 关闭 WebSocket
const closeWebSocket = () => { const closeWebSocket = () => {
if (websocket.value) { if (websocket.value) {
websocket.value.close(); websocket.value.close();
websocket.value = null;
ElMessage.info('全局 WebSocket 已关闭'); ElMessage.info('全局 WebSocket 已关闭');
stopHeartbeat(); stopHeartbeat(); // 停止心跳
isWebSocketConnected.value = false; isWebSocketConnected.value = false;
} }
}; };
@ -38,7 +63,7 @@ const startHeartbeat = () => {
if (heartbeatInterval) return; if (heartbeatInterval) return;
heartbeatInterval = window.setInterval(() => { heartbeatInterval = window.setInterval(() => {
if (websocket.value && websocket.value.readyState === WebSocket.OPEN) { if (websocket.value && websocket.value.readyState === WebSocket.OPEN) {
websocket.value.send('ping'); websocket.value.send('ping'); // 发送心跳数据
} }
}, 5000); }, 5000);
}; };
@ -55,42 +80,52 @@ const stopHeartbeat = () => {
const handleClose = () => { const handleClose = () => {
ElMessage.warning('WebSocket 连接已关闭'); ElMessage.warning('WebSocket 连接已关闭');
isWebSocketConnected.value = false; isWebSocketConnected.value = false;
stopHeartbeat(); stopHeartbeat(); // 停止心跳
}; };
// 处理错误 // 处理连接错误
const handleError = () => { const handleError = () => {
ElMessage.error('WebSocket 连接出错'); ElMessage.error('WebSocket 连接出错');
isWebSocketConnected.value = false; isWebSocketConnected.value = false;
stopHeartbeat(); stopHeartbeat(); // 停止心跳
}; };
// 显示自定义通知 // 根据弹窗模式处理通知
const showNotification = (data: any) => { const handlePopupNotification = (data: any) => {
const isInteractive = localStorage.getItem('isInteractivePopupEnabled') === 'true'; // 是否为交互式弹窗
const isResponsive = localStorage.getItem('isResponsivePopupEnabled') === 'true'; // 是否为响应式弹窗
if (isResponsive) {
// 响应式模式:直接显示对话框
eventBus.emit('showDialog', data);
} else if (isInteractive) {
const formattedTime = formatDateTime(data.started_at);
ElNotification({ ElNotification({
title: '新告警', title: '新告警',
message: ` message: `
<div style="max-height: 200px; overflow-y: auto;"> <div style="max-height: 200px; overflow-y: auto;">
<p><strong></strong>${data.id || '未知'}</p> <p><strong></strong>${data.id || '未知'}</p>
<p><strong></strong>${data.camera_id || '未知'}</p> <p><strong></strong>${data.camera?.name|| '未知'}</p>
<p><strong></strong>${data.camera.name || '未知'}</p> <p><strong></strong>${algorithmMap.value.get(data.types) || '未知'}</p>
<p><strong></strong>${formattedTime || '未知'}</p>
</div> </div>
`, `,
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
duration: 5000, duration: 5000,
customClass: 'custom-notification', customClass: 'custom-notification',
onClick: () => { onClick: () => {
// 触发全局事件总线的 showDialog 事件 eventBus.emit('showDialog', data); // 点击通知触发对话框
eventBus.emit('showDialog', data);
} }
}); });
}
}; };
// 导出类型和方法 // 导出类型和方法
export interface GlobalWebSocket { export interface GlobalWebSocket {
connectWebSocket: () => void; connectWebSocket: () => void; // 连接 WebSocket
closeWebSocket: () => void; closeWebSocket: () => void; // 关闭 WebSocket
isWebSocketConnected: typeof isWebSocketConnected; isWebSocketConnected: typeof isWebSocketConnected; // WebSocket 连接状态
} }
export const useGlobalWebSocket = (): GlobalWebSocket => ({ export const useGlobalWebSocket = (): GlobalWebSocket => ({