From 9e825bb9263ed29897bfaf467bfd0f86da8d3e5f Mon Sep 17 00:00:00 2001
From: chenhaozhe <cgz@hz-kingdee.com>
Date: 星期四, 15 一月 2026 16:08:30 +0800
Subject: [PATCH] 消息推送 优化

---
 utils/WebSocketServices.js |  278 ++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 204 insertions(+), 74 deletions(-)

diff --git a/utils/WebSocketServices.js b/utils/WebSocketServices.js
index 850b8d8..b7838a9 100644
--- a/utils/WebSocketServices.js
+++ b/utils/WebSocketServices.js
@@ -3,84 +3,214 @@
 } from "@/utils/common.js";
 
 class WebSocketServices {
-    constructor() {
-        this.wsInstance = null; // WebSocket 瀹炰緥
-        this.isConnecting = false; // 閬垮厤骞跺彂閲嶈繛
-        this.isConnected = false; // 閬垮厤骞跺彂閲嶈繛
-        this.wsUrl = CommonUtils.httpFormatWs()
-    }
+   constructor() {
+       this.wsInstance = null; // WebSocket 瀹炰緥
+       this.isConnecting = false; // 杩炴帴涓姸鎬侊紙閬垮厤骞跺彂閲嶈繛锛�
+       this.isConnected = false; // 宸茶繛鎺ョ姸鎬�
+       this.isReconnectStopped = false; // 鍋滄閲嶈繛鏍囪
+       this.wsUrl = CommonUtils.httpFormatWs(); // WebSocket 鍩虹鍦板潃
+   
+       // 瓒呮椂鏍¢獙閰嶇疆
+       this.noMessageTimeout = 45000; // 45绉掑唴娌℃敹鍒颁换浣曚笟鍔℃秷鎭� 鈫� 鍒ゅ畾杩炴帴澶辨晥锛堟湇鍔$30绉掑彂涓�娆ing锛岀暀15绉掑閿欙級
+       this.noMessageTimer = null; // 鏃犳秷鎭秴鏃跺畾鏃跺櫒
+   
+       // 鐩戝惉鍑芥暟寮曠敤
+       this.openListener = null;
+       this.messageListener = null;
+       this.closeListener = null;
+       this.errorListener = null;
+   
+       // 缂撳瓨鐢ㄦ埛淇℃伅
+       this.currentUserId = "";
+       this.currentUserName = "";
+     }
+   
+     /**
+      * 寤虹珛 WebSocket 杩炴帴
+      * @param {string/number} userId - 鐢ㄦ埛ID锛堝繀濉級
+      * @param {string} userName - 鐢ㄦ埛鍚嶏紙蹇呭~锛�
+      * @param {number} count - 褰撳墠閲嶈繛娆℃暟
+      * @param {number} limit - 鏈�澶ч噸杩炴鏁帮紙榛樿3娆★級
+      */
+     createConnect(userId, userName, count = 0, limit = 3) {
+       // 缂撳瓨鐢ㄦ埛淇℃伅锛堢敤浜庨噸杩烇級
+       this.currentUserId = userId;
+       this.currentUserName = userName;
+   
+       // 鍓嶇疆鏍¢獙锛氶伩鍏嶆棤鏁堣繛鎺ュ拰骞跺彂閲嶈繛
+       if (this.isConnecting || this.isConnected) return;
+       if (!userId && userId !== 0) { // 鍏煎 userId 涓� 0 鐨勫悎娉曞満鏅�
+         CommonUtils.showTips({ message: "鐢ㄦ埛鏍囪瘑涓嶈兘涓虹┖锛屾棤娉曞缓绔媁ebSocket杩炴帴" });
+         return;
+       }
+       if (count > limit) {
+         CommonUtils.showTips({
+           message: `WebSocket 閲嶈繛娆℃暟瓒呭嚭鏈�澶ч檺鍒讹紙${limit}娆★級锛屽凡鍋滄閲嶈繛`,
+         });
+         this.isReconnectStopped = true;
+         return;
+       }
+   
+       console.log(`[WebSocket] 寮�濮嬪缓绔嬭繛鎺ワ紙绗� ${count || 0} 娆★級`, {
+         wsUrl: this.wsUrl,
+         userId,
+         userName,
+       });
+   
+       // 娓呴櫎鍘嗗彶娈嬬暀锛氱洃鍚�+瀹氭椂鍣�
+       this.clearAllListeners();
+       this.clearNoMessageTimer();
+   
+       // 鍙戣捣杩炴帴
+       this.isConnecting = true;
+       this.wsInstance = uni.connectSocket({
+         url: `${this.wsUrl}?userId=${encodeURIComponent(userId)}&userName=${encodeURIComponent(userName)}`,
+         fail: (error) => {
+           console.error("[WebSocket] 杩炴帴鍙戣捣澶辫触", error);
+           this.isConnecting = false;
+           this.triggerReconnect(count);
+         },
+       });
+   
+       // 鐩戝惉杩炴帴鎴愬姛锛氬惎鍔ㄦ棤娑堟伅瓒呮椂鏍¢獙
+       this.openListener = uni.onSocketOpen((res) => {
+         console.log("[WebSocket] 杩炴帴寤虹珛鎴愬姛", res);
+         this.isConnecting = false;
+         this.isConnected = true;
+         this.isReconnectStopped = false;
+         this.startNoMessageCheck(); 
+         count = 0; 
+       });
+   
+       this.messageListener = uni.onSocketMessage((res) => {
+         try {
+           const message = JSON.parse(res.data);
+           console.log("[WebSocket] 鏀跺埌涓氬姟娑堟伅", message);
+   
+           // 閲嶇疆鏃犳秷鎭畾鏃跺櫒锛堟湁涓氬姟娑堟伅=杩炴帴姝e父锛�
+           this.resetNoMessageTimer();
+   
+           // 澶勭悊涓氬姟娑堟伅
+           if (message.Type === "Message") {
+             const content = JSON.parse(message.Content);
+             this.showTaskTip(`鎮ㄦ湁${content.length}鏉℃秷鎭渶瑕佸鐞�!`);
+             // this.emit("message", content); // 鏀寔澶栭儴鐩戝惉
+           }
+         } catch (error) {
+           console.error("[WebSocket] 娑堟伅瑙f瀽澶辫触", error, res.data);
+         }
+       });
+   
+       // 鐩戝惉杩炴帴鍏抽棴锛氫粎寮傚父鍏抽棴瑙﹀彂閲嶈繛
+       this.closeListener = uni.onSocketClose((res) => {
+         console.log("[WebSocket] 杩炴帴鍏抽棴", res);
+         this.isConnecting = false;
+         this.isConnected = false;
+         this.clearNoMessageTimer();
+   
+         // 姝e父鍏抽棴锛坈ode=1000锛夋垨涓诲姩鍋滄閲嶈繛鏃讹紝涓嶉噸杩�
+         if (!this.isReconnectStopped && res.code !== 1000) {
+           this.triggerReconnect(count);
+         }
+       });
+   
+       // 鐩戝惉杩炴帴閿欒锛氳Е鍙戦噸杩�
+       this.errorListener = uni.onSocketError((error) => {
+         console.error("[WebSocket] 杩炴帴閿欒", error);
+         this.isConnecting = false;
+         this.clearNoMessageTimer();
+         if (!this.isReconnectStopped) {
+           this.triggerReconnect(count);
+         }
+       });
+     }
+   
+     /**
+      * 缁熶竴瑙﹀彂閲嶈繛锛堝欢杩�3绉掞級
+      * @param {number} count - 褰撳墠閲嶈繛娆℃暟
+      */
+     triggerReconnect(count) {
+       console.log(`[WebSocket] 鍑嗗绗� ${count + 1} 娆¢噸杩瀈);
+       setTimeout(() => {
+         this.createConnect(this.currentUserId, this.currentUserName, count + 1);
+       }, 3000);
+     }
+   
+     /**
+      * 鍚姩鈥滄棤涓氬姟娑堟伅鈥濊秴鏃舵牎楠�
+      * 閫昏緫锛�45绉掑唴娌℃敹鍒颁换浣曚笟鍔℃秷鎭� 鈫� 鍒ゅ畾杩炴帴澶辨晥锛堟湇鍔$30绉掑彂Ping锛屽簳灞傚凡澶勭悊锛屾澶勪粎鏍¢獙涓氬姟閫氶亾锛�
+      */
+     startNoMessageCheck() {
+       this.clearNoMessageTimer();
+       this.noMessageTimer = setTimeout(() => {
+         console.warn("[WebSocket] 45绉掓湭鏀跺埌涓氬姟娑堟伅锛屽垽瀹氳繛鎺ュけ鏁堬紝涓诲姩閲嶈繛");
+         this.closeSocket();
+         this.createConnect(this.currentUserId, this.currentUserName);
+       }, this.noMessageTimeout);
+     }
+   
+     /**
+      * 鏀跺埌涓氬姟娑堟伅鍚庯紝閲嶇疆鏃犳秷鎭畾鏃跺櫒
+      */
+     resetNoMessageTimer() {
+       this.startNoMessageCheck();
+     }
+   
+     /**
+      * 娓呴櫎鏃犳秷鎭畾鏃跺櫒
+      */
+     clearNoMessageTimer() {
+       if (this.noMessageTimer) {
+         clearTimeout(this.noMessageTimer);
+         this.noMessageTimer = null;
+       }
+     }
+   
+     /**
+      * 娓呴櫎鎵�鏈� Socket 鐩戝惉 
+      */
+     clearAllListeners() {
+       if (this.openListener) {
+         uni.offSocketOpen(this.openListener);
+         this.openListener = null;
+       }
+       if (this.messageListener) {
+         uni.offSocketMessage(this.messageListener);
+         this.messageListener = null;
+       }
+       if (this.closeListener) {
+         uni.offSocketClose(this.closeListener);
+         this.closeListener = null;
+       }
+       if (this.errorListener) {
+         uni.offSocketError(this.errorListener);
+         this.errorListener = null;
+       }
+     }
+   
+     /**
+      * 涓诲姩鍏抽棴 WebSocket 杩炴帴 (鐧诲嚭鏃跺叧闂璚ebSocket杩炴帴)
+      */
+     closeSocket() {
+       this.isReconnectStopped = true;
+       this.clearAllListeners();
+       this.clearNoMessageTimer();
+   
+       if (this.wsInstance) {
+         uni.closeSocket({
+           success: () => console.log("[WebSocket] 涓诲姩鍏抽棴杩炴帴鎴愬姛"),
+           fail: (error) => console.error("[WebSocket] 涓诲姩鍏抽棴杩炴帴澶辫触", error),
+         });
+         this.wsInstance = null;
+       }
+   
+       this.isConnected = false;
+       this.isConnecting = false;
+     }
 
-    // 寤虹珛WebSocket杩炴帴
-    createConnect(userId, userName) { // 浣跨敤鐢ㄦ埛鏍囪瘑 浣滀负鍚庣杩炴帴鐨勫嚟鎹�
-        console.log('wsUrl: ', this.wsUrl);
-        console.log('userId: ', userId);
-        console.log('userName: ', userName);
-        if (this.isConnecting || !userId || this.isConnected) {
-            return
-        }
-        this.wsInstance = uni.connectSocket({
-            url: this.wsUrl + `?userId=${encodeURIComponent(userId)}&userName=${encodeURIComponent(userName)}`,
-            success() {
-                this.isConnecting = true
-            }
-        })
-
-        // 鐩戝惉濂楁帴瀛楄繛鎺ュ缓绔�
-        uni.onSocketOpen((res) => {
-            console.log('[webSocket]: 濂楁帴瀛楄繛鎺ュ缓绔嬫垚鍔�');
-            this.isConnecting = false
-            this.isConnected = true
-            console.log('res: ', res);
-            this.wsInstance = res.socketTask
-        })
-
-        uni.onSocketMessage((res) => {
-            let message = JSON.parse(res.data)
-            console.log('message: ', message);
-            if (message.Type == 'Message') {
-                // 娑堟伅淇″彿
-                let content = JSON.parse(message.Content)
-                console.log('content: ', content);
-
-                this.showTaskTip(`鎮ㄦ湁${content.length}鏉℃秷鎭渶瑕佸鐞�!`)
-            } else if (message.Type == 'ping') {
-                // 蹇冭烦淇″彿
-                uni.sendSocketMessage({
-                    data: "pong"
-                })
-            }
-        })
-    }
-
-    // 閲嶈繛
-    reConnect(reCount = 1, limit = 3) {
-        if (reCount > limit) {
-            uni.showToast({
-                icon: 'none',
-                title: `瓒呭嚭鏈�澶ч噸杩炴鏁般�傚凡閫�鍑鸿繛鎺
-            })
-            this.isConnecting = false
-            return
-        }
-        uni.showToast({
-            icon: 'none',
-            title: `姝e湪灏濊瘯閲嶈繛锛岄噸杩炴鏁� ${reCount}`
-        })
-
-        reConnect(reCount + 1, limit)
-
-        uni.hideToast()
-    }
-
-    // 杩炴帴娉ㄩ攢
-    disConnect() {
-
-    }
 
     showTaskTip(Content) {
-        console.log('Content: ', Content);
         // #ifdef APP-PLUS || APP
-        console.log('Content2: ', Content);
         let content = Content;
         let options = {
             title: "閲嶈閫氱煡",

--
Gitblit v1.9.1