Browse Source

常规上传

Koishi 2 weeks ago
parent
commit
e89d968428
2 changed files with 215 additions and 1 deletions
  1. 3 1
      .env.development
  2. 212 0
      src/tools/ws.js

+ 3 - 1
.env.development

@@ -5,4 +5,6 @@ VITE_APP_API=https://api.openweathermap.org
 VITE_APP_BD_API=http://127.0.0.1:3007
 
 # 获取外网天气数据
-VITE_APP_WW_API=http://192.168.2.180:3007
+VITE_APP_WW_API=http://192.168.2.180:3007
+
+VITE_APP_WS_URL=ws://10.121.128.117:8431/

+ 212 - 0
src/tools/ws.js

@@ -0,0 +1,212 @@
+class WebSocketService {
+    constructor() {
+        this.socket = null;
+        this.reconnectAttempts = 0;
+        this.maxReconnectAttempts = 5;
+        this.reconnectInterval = 3000; // 3秒
+        this.messageHandlers = new Map();
+        this.isConnected = false;
+        this.url = null;
+        this.reconnectTimer = null;
+    }
+
+    /**
+     * 连接 WebSocket
+     * @param {Object} options 连接选项
+     */
+    connect(options = {}) {
+        if (this.socket && this.isConnected) {
+            console.warn('WebSocket 已经连接');
+            return;
+        }
+
+        const {
+            protocols = [],
+            onOpen = null,
+            onClose = null,
+            onError = null,
+            autoReconnect = true,
+            maxReconnectAttempts = 5,
+            reconnectInterval = 3000,
+            baseURL = "",
+            url = "",
+        } = options;
+
+        this.url = `${baseURL || process.env.VITE_APP_WS_URL}${url}`;
+
+        this.autoReconnect = autoReconnect;
+        this.maxReconnectAttempts = maxReconnectAttempts;
+        this.reconnectInterval = reconnectInterval;
+
+        try {
+            this.socket = new WebSocket(url, protocols);
+
+            this.socket.onopen = (event) => {
+                console.log('WebSocket 连接成功');
+                this.isConnected = true;
+                this.reconnectAttempts = 0;
+
+                if (onOpen) onOpen(event);
+                this.trigger('open', event);
+            };
+
+            this.socket.onmessage = (event) => {
+                try {
+                    const data = JSON.parse(event.data);
+                    this.trigger('message', data);
+                } catch (error) {
+                    // 如果不是 JSON 数据,直接传递原始数据
+                    this.trigger('message', event.data);
+                }
+            };
+
+            this.socket.onclose = (event) => {
+                console.log('WebSocket 连接关闭', event.code, event.reason);
+                this.isConnected = false;
+
+                if (onClose) onClose(event);
+                this.trigger('close', event);
+
+                // 自动重连
+                if (this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
+                    this.scheduleReconnect();
+                }
+            };
+
+            this.socket.onerror = (error) => {
+                console.error('WebSocket 错误:', error);
+
+                if (onError) onError(error);
+                this.trigger('error', error);
+            };
+
+        } catch (error) {
+            console.error('创建 WebSocket 连接失败:', error);
+            this.trigger('error', error);
+        }
+    }
+
+    /**
+     * 发送消息
+     * @param {*} data 要发送的数据
+     */
+    send(data) {
+        if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
+            console.error('WebSocket 未连接,无法发送消息');
+            return false;
+        }
+
+        try {
+            const message = typeof data === 'string' ? data : JSON.stringify(data);
+            this.socket.send(message);
+            return true;
+        } catch (error) {
+            console.error('发送消息失败:', error);
+            this.trigger('error', error);
+            return false;
+        }
+    }
+
+    /**
+     * 关闭连接
+     * @param {number} code 关闭代码
+     * @param {string} reason 关闭原因
+     */
+    close(code = 1000, reason = '正常关闭') {
+        this.autoReconnect = false;
+
+        if (this.reconnectTimer) {
+            clearTimeout(this.reconnectTimer);
+            this.reconnectTimer = null;
+        }
+
+        if (this.socket) {
+            this.socket.close(code, reason);
+            this.socket = null;
+        }
+    }
+
+    /**
+     * 重新连接
+     */
+    reconnect() {
+        if (this.url) {
+            this.close();
+            this.connect(this.url, {
+                autoReconnect: this.autoReconnect,
+                maxReconnectAttempts: this.maxReconnectAttempts,
+                reconnectInterval: this.reconnectInterval
+            });
+        }
+    }
+
+    /**
+     * 安排重连
+     */
+    scheduleReconnect() {
+        if (this.reconnectTimer) {
+            clearTimeout(this.reconnectTimer);
+        }
+
+        this.reconnectAttempts++;
+        const delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1); // 指数退避
+
+        console.log(`将在 ${delay}ms 后尝试重连 (尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
+
+        this.reconnectTimer = setTimeout(() => {
+            this.reconnect();
+        }, delay);
+    }
+
+    /**
+     * 注册事件处理器
+     * @param {string} event 事件名称
+     * @param {Function} handler 处理函数
+     */
+    on(event, handler) {
+        if (!this.messageHandlers.has(event)) {
+            this.messageHandlers.set(event, new Set());
+        }
+        this.messageHandlers.get(event).add(handler);
+    }
+
+    /**
+     * 取消事件处理器
+     * @param {string} event 事件名称
+     * @param {Function} handler 处理函数
+     */
+    off(event, handler) {
+        if (this.messageHandlers.has(event)) {
+            this.messageHandlers.get(event).delete(handler);
+        }
+    }
+
+    /**
+     * 触发事件
+     * @param {string} event 事件名称
+     * @param {*} data 事件数据
+     */
+    trigger(event, data) {
+        if (this.messageHandlers.has(event)) {
+            this.messageHandlers.get(event).forEach(handler => {
+                try {
+                    handler(data);
+                } catch (error) {
+                    console.error(`事件 ${event} 的处理函数执行错误:`, error);
+                }
+            });
+        }
+    }
+
+    /**
+     * 获取连接状态
+     */
+    getReadyState() {
+        return this.socket ? this.socket.readyState : WebSocket.CLOSED;
+    }
+}
+
+// 创建单例实例
+const webSocketService = new WebSocketService();
+
+export default webSocketService;