| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- // WebSocketService.js
- class WebSocketService {
- constructor() {
- this.websocket = null;
- this.heartbeatTimer = null;
- this.reconnectTimer = null;
- this.token = null;
- }
- initWebSocket(token) {
- if (!token) {
- console.warn('❌ WebSocket token 为空');
- // 全局提示用户登录过期
- if (typeof window !== 'undefined' && window.Vue && Vue.prototype.$message) {
- Vue.prototype.$message.error('登录状态已过期,请重新登录!');
- } else {
- alert('登录状态已过期,请重新登录!');
- }
- // 退出并跳转登录页
- if (this.store) {
- this.store.dispatch("LogOut").then(() => {
- location.href = "/index";
- });
- } else {
- // 如果没有 store 引用,直接跳转
- location.href = "/index";
- }
- return;
- }
- // 如果已连接或连接中,跳过
- if (this.websocket &&
- (this.websocket.readyState === WebSocket.OPEN || this.websocket.readyState === WebSocket.CONNECTING)) {
- console.log('ℹ️ WebSocket 已连接或连接中,跳过重复连接');
- return;
- }
- this.token = token;
- const wsUrl = `${process.env.VUE_APP_WS_URL}/${token}`;
- console.log("🔌 WebSocket连接中:", wsUrl);
- this.websocket = new WebSocket(wsUrl);
- this.websocket.onopen = this.websocketonopen.bind(this);
- this.websocket.onerror = this.websocketonerror.bind(this);
- this.websocket.onmessage = this.setOnmessageMessage.bind(this);
- this.websocket.onclose = this.websocketclose.bind(this);
- // 初始化状态为 connecting
- window.dispatchEvent(new CustomEvent('ws-status', { detail: 'connecting' }));
- }
- websocketonopen() {
- console.log('✅ WebSocket连接成功');
- this.startHeartbeat();
- window.dispatchEvent(new CustomEvent('ws-status', { detail: 'open' }));
- }
- websocketonerror(e) {
- console.error('❌ WebSocket连接错误:', e);
- window.dispatchEvent(new CustomEvent('ws-status', { detail: 'error' }));
- this.reconnect();
- }
- websocketclose(e) {
- console.warn('⚠️ WebSocket连接关闭:', e);
- this.stopHeartbeat();
- window.dispatchEvent(new CustomEvent('ws-status', { detail: 'closed' }));
- this.reconnect();
- }
- reconnect() {
- if (this.reconnectTimer) return;
- if (this.websocket &&
- (this.websocket.readyState === WebSocket.OPEN || this.websocket.readyState === WebSocket.CONNECTING)) {
- console.log('ℹ️ WebSocket 已连接,无需重连');
- return;
- }
- this.reconnectTimer = setTimeout(() => {
- console.warn('🔁 尝试重新连接 WebSocket...');
- this.initWebSocket(this.token);
- this.reconnectTimer = null;
- }, 5000);
- }
- setOnmessageMessage(event) {
- try {
- const msg = JSON.parse(event.data);
- console.log("📩 收到消息:", msg);
- if (msg.type) {
- window.dispatchEvent(new CustomEvent(msg.type, { detail: msg }));
- }
- } catch (err) {
- console.error("WebSocket消息解析失败:", err);
- }
- }
- startHeartbeat() {
- this.stopHeartbeat();
- this.heartbeatTimer = setInterval(() => {
- if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
- this.websocket.send(JSON.stringify({ type: 'heartbeat', time: new Date().toISOString() }));
- }
- }, 30000);
- }
- stopHeartbeat() {
- if (this.heartbeatTimer) {
- clearInterval(this.heartbeatTimer);
- this.heartbeatTimer = null;
- }
- }
- destroy() {
- this.stopHeartbeat();
- if (this.websocket) {
- this.websocket.close();
- this.websocket = null;
- }
- console.log("🧹 WebSocket 已销毁");
- window.dispatchEvent(new CustomEvent('ws-status', { detail: 'closed' }));
- }
- }
- export default new WebSocketService();
|