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

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'); // 获取存储的主机地址
websocket.value.onopen = () => { if (rememberedAddress) {
ElMessage.success('全局 WebSocket 连接成功'); websocket.value = new WebSocket(`ws://${rememberedAddress}:8080/ws/event`);
isWebSocketConnected.value = true; // websocket.value = new WebSocket(`ws://192.168.28.33:8080/ws/event`);
}; loadAlgorithms();
websocket.value.onmessage = (event) => { websocket.value.onopen = () => {
const data = JSON.parse(event.data); ElMessage.success('全局 WebSocket 连接成功');
isWebSocketConnected.value = true;
// 显示通知,并在点击时通过 eventBus 触发全局弹窗事件 };
showNotification(data); websocket.value.onmessage = (event) => {
}; const data = JSON.parse(event.data); // 解析收到的数据
websocket.value.onclose = handleClose; handlePopupNotification(data); // 根据模式处理弹窗通知
websocket.value.onerror = handleError; };
websocket.value.onclose = handleClose; // 处理连接关闭
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) => {
ElNotification({ const isInteractive = localStorage.getItem('isInteractivePopupEnabled') === 'true'; // 是否为交互式弹窗
title: '新告警', const isResponsive = localStorage.getItem('isResponsivePopupEnabled') === 'true'; // 是否为响应式弹窗
message: `
<div style="max-height: 200px; overflow-y: auto;"> if (isResponsive) {
<p><strong></strong>${data.id || '未知'}</p> // 响应式模式:直接显示对话框
<p><strong></strong>${data.camera_id || '未知'}</p> eventBus.emit('showDialog', data);
<p><strong></strong>${data.camera.name || '未知'}</p> } else if (isInteractive) {
</div>
`, const formattedTime = formatDateTime(data.started_at);
dangerouslyUseHTMLString: true, ElNotification({
duration: 5000, title: '新告警',
customClass: 'custom-notification', message: `
onClick: () => { <div style="max-height: 200px; overflow-y: auto;">
// 触发全局事件总线的 showDialog 事件 <p><strong></strong>${data.id || '未知'}</p>
eventBus.emit('showDialog', data); <p><strong></strong>${data.camera?.name|| '未知'}</p>
} <p><strong></strong>${algorithmMap.value.get(data.types) || '未知'}</p>
}); <p><strong></strong>${formattedTime || '未知'}</p>
</div>
`,
dangerouslyUseHTMLString: true,
duration: 5000,
customClass: 'custom-notification',
onClick: () => {
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 => ({