2026-07-16 18:08:54 +08:00
|
|
|
|
import emitter from '@/utils/mitt';
|
|
|
|
|
|
|
|
|
|
|
|
type WebSocketInternalOptions = {
|
2025-11-20 18:17:09 +08:00
|
|
|
|
fullUrl: string;
|
|
|
|
|
|
reconnectInterval?: number;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let websocket: WebSocket | null = null;
|
|
|
|
|
|
let reconnectTimer: any = null;
|
|
|
|
|
|
let isManualClose = false;
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
/** 初始化WebSocket */
|
|
|
|
|
|
export function initWebSocket(options: WebSocketInternalOptions) {
|
|
|
|
|
|
const { fullUrl, reconnectInterval = 3000 } = options;
|
2025-11-20 18:17:09 +08:00
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
// 关闭已有连接
|
2025-11-20 18:17:09 +08:00
|
|
|
|
if (websocket) {
|
|
|
|
|
|
websocket.close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!('WebSocket' in window)) {
|
|
|
|
|
|
console.error('当前浏览器不支持WebSocket');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
websocket = new WebSocket(fullUrl);
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
// 连接成功
|
2025-11-20 18:17:09 +08:00
|
|
|
|
websocket.onopen = () => {
|
|
|
|
|
|
clearTimeout(reconnectTimer!);
|
|
|
|
|
|
isManualClose = false;
|
2026-07-16 18:08:54 +08:00
|
|
|
|
console.log('WebSocket 连接成功');
|
2025-11-20 18:17:09 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
// 接收消息,自动解析按 msgType 分发事件
|
2025-11-20 18:17:09 +08:00
|
|
|
|
websocket.onmessage = (event) => {
|
2026-07-16 18:08:54 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const rawMsg = JSON.parse(event.data);
|
|
|
|
|
|
const msgType = rawMsg.msgType;
|
|
|
|
|
|
emitter.emit(msgType, rawMsg);
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('WebSocket消息解析失败:', err);
|
|
|
|
|
|
}
|
2025-11-20 18:17:09 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
// 连接异常
|
2025-11-20 18:17:09 +08:00
|
|
|
|
websocket.onerror = (error) => {
|
2026-07-16 18:08:54 +08:00
|
|
|
|
console.error('WebSocket 连接异常:', error);
|
2025-11-20 18:17:09 +08:00
|
|
|
|
startReconnect(() => initWebSocket(options), reconnectInterval);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
// 连接关闭
|
2025-11-20 18:17:09 +08:00
|
|
|
|
websocket.onclose = () => {
|
2026-07-16 18:08:54 +08:00
|
|
|
|
console.log('WebSocket 连接关闭');
|
2025-11-20 18:17:09 +08:00
|
|
|
|
if (!isManualClose) {
|
|
|
|
|
|
startReconnect(() => initWebSocket(options), reconnectInterval);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
} catch (error) {
|
2026-07-16 18:08:54 +08:00
|
|
|
|
console.error('WebSocket 创建失败:', error);
|
2025-11-20 18:17:09 +08:00
|
|
|
|
startReconnect(() => initWebSocket(options), reconnectInterval);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
/** 发送ws消息 */
|
2025-11-20 18:17:09 +08:00
|
|
|
|
export function sendWebSocketMessage(message: any): boolean {
|
|
|
|
|
|
if (websocket && websocket.readyState === WebSocket.OPEN) {
|
|
|
|
|
|
websocket.send(JSON.stringify(message));
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2026-07-16 18:08:54 +08:00
|
|
|
|
console.error('WebSocket未连接,发送失败');
|
2025-11-20 18:17:09 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
/** 手动关闭ws(登出时调用) */
|
2025-11-20 18:17:09 +08:00
|
|
|
|
export function closeWebSocket(): void {
|
|
|
|
|
|
isManualClose = true;
|
|
|
|
|
|
if (reconnectTimer) {
|
|
|
|
|
|
clearTimeout(reconnectTimer);
|
|
|
|
|
|
}
|
|
|
|
|
|
websocket?.close();
|
|
|
|
|
|
websocket = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:08:54 +08:00
|
|
|
|
/** 获取当前连接状态 */
|
|
|
|
|
|
export function getWebSocketState(): number | null {
|
|
|
|
|
|
return websocket?.readyState || null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 内部重连私有方法
|
2025-11-20 18:17:09 +08:00
|
|
|
|
function startReconnect(connectCallback: () => void, interval: number): void {
|
|
|
|
|
|
if (reconnectTimer) {
|
|
|
|
|
|
clearTimeout(reconnectTimer);
|
|
|
|
|
|
}
|
|
|
|
|
|
reconnectTimer = setTimeout(connectCallback, interval);
|
|
|
|
|
|
}
|