liming 3 zile în urmă
părinte
comite
00f04bbb79

+ 100 - 49
src/stores/modules/webSocketStore.js

@@ -6,7 +6,6 @@ import { useWalletStore } from "@/stores/modules/walletStore";
 import { getMessageApi } from "@/api/path/im.api";
 import { MSG_TYPE, MSG_TYPE_MAP } from "@/common/constant/msgType";
 
-
 import {
   setMessageHook,
   handleMessageHook,
@@ -20,9 +19,7 @@ export const useWebSocketStore = defineStore("webSocketStore", {
     socket: null, // socket实例
     peer: null, // peer实例
     lockConnection: false, // 锁定连接
-    reconnectAttempts: 0, // 重连次数
-    maxReconnectAttempts: 80, // 最大重连次数
-    reconnectInterval: 2000, // 重连间隔
+    reconnectAttempts: 0, // 重连次数 
     messages: [], // 消息列表
     toUserInfo: {},
     unreadMessages: [], // 未读消息列表
@@ -31,10 +28,12 @@ export const useWebSocketStore = defineStore("webSocketStore", {
 
     // 心跳检测配置
     heartCheck: {
-      timeout: 10000, // 连接丢失后,多长时间内没有收到服务端的消息,则认为连接已断开
-      timeoutObj: null, // 定时器对象
-      serverTimeoutObj: null, // 服务器定时器对象
-      num: 3, // 重连次数
+      interval: 30000, // 心跳发送间隔(30秒)
+      timeout: 10000, // 响应超时时间(10秒)
+      timeoutObj: null,
+      serverTimeoutObj: null,
+      retryLimit: 3, // 重试次数
+      retryCount: 0, // 当前重试计数
     },
   }),
   persist: {
@@ -73,16 +72,16 @@ export const useWebSocketStore = defineStore("webSocketStore", {
         console.error("WebSocket未连接");
         return false;
       }
- 
-      // 获取url上uuid参数 
+
+      // 获取url上uuid参数
       const walletStore = useWalletStore();
       let data = {
         ...messageData,
         fromUsername: walletStore.username,
         from: walletStore.account,
         to: this.toUserInfo.uuid,
-      }; 
-      console.log("发送消息=", data)
+      };
+      console.log("发送消息=", data);
       try {
         const MessageType = protobuf.lookupType("protocol.Message");
         const messagePB = MessageType.create(data);
@@ -98,34 +97,73 @@ export const useWebSocketStore = defineStore("webSocketStore", {
       }
     },
     // 初始化socket
-    startHeartbeat() {
-      const self = this;
-      const _num = this.heartCheck.num;
+    // startHeartbeat() {
+    //   const self = this;
+    //   const _num = this.heartCheck.num;
 
-      this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj);
-      this.heartCheck.serverTimeoutObj &&
-        clearTimeout(this.heartCheck.serverTimeoutObj);
+    //   this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj);
+    //   this.heartCheck.serverTimeoutObj &&
+    //     clearTimeout(this.heartCheck.serverTimeoutObj);
+
+    //   this.heartCheck.timeoutObj = setTimeout(() => {
+    //     if (this.socket?.readyState === WebSocket.OPEN) {
+    //       const data = {
+    //         type: "heatbeat",
+    //         content: "ping",
+    //       };
+    //       const MessageType = protobuf.lookupType("protocol.Message");
+    //       const messagePB = MessageType.create(data);
+    //       const buffer = MessageType.encode(messagePB).finish();
+    //       this.socket.send(buffer);
+    //     }
+
+    //     self.heartCheck.serverTimeoutObj = setTimeout(() => {
+    //       _num--;
+    //       if (_num <= 0) {
+    //         console.log("the ping num is more then 3, close socket!");
+    //         this.socket?.close();
+    //       }
+    //     }, self.heartCheck.timeout);
+    //   }, this.heartCheck.timeout);
+    // },
+
+    startHeartbeat() {
+      this.resetHeartbeat();
 
       this.heartCheck.timeoutObj = setTimeout(() => {
-        if (this.socket?.readyState === WebSocket.OPEN) {
-          const data = {
-            type: "heatbeat",
-            content: "ping",
-          };
-          const MessageType = protobuf.lookupType("protocol.Message");
-          const messagePB = MessageType.create(data);
-          const buffer = MessageType.encode(messagePB).finish();
-          this.socket.send(buffer);
-        }
+        if (this.isConnected) {
+          try {
+            const pingMsg = {
+              type: "heatbeat",
+              content: "ping",
+              timestamp: Date.now(),
+            };
 
-        self.heartCheck.serverTimeoutObj = setTimeout(() => {
-          _num--;
-          if (_num <= 0) {
-            console.log("the ping num is more then 3, close socket!");
-            this.socket?.close();
+            const MessageType = protobuf.lookupType("protocol.Message");
+            const messagePB = MessageType.create(pingMsg);
+            const buffer = MessageType.encode(messagePB).finish();
+            this.socket.send(buffer);
+
+            // 设置响应超时检测
+            this.heartCheck.serverTimeoutObj = setTimeout(() => {
+              this.heartCheck.retryCount++;
+
+              if (this.heartCheck.retryCount >= this.heartCheck.retryLimit) {
+                console.error("心跳响应超时,关闭连接");
+                this.socket?.close();
+              } else {
+                console.warn(
+                  `心跳无响应,第${this.heartCheck.retryCount}次重试`
+                );
+                this.startHeartbeat(); // 重新发送心跳
+              }
+            }, this.heartCheck.timeout);
+          } catch (error) {
+            console.error("心跳发送失败:", error);
+            this.reconnect();
           }
-        }, self.heartCheck.timeout);
-      }, this.heartCheck.timeout);
+        }
+      }, this.heartCheck.interval);
     },
 
     resetHeartbeat() {
@@ -203,25 +241,34 @@ export const useWebSocketStore = defineStore("webSocketStore", {
       reader.readAsArrayBuffer(data);
     },
     // 断线重连
+
+    // 替换现有的reconnect方法
     reconnect() {
-      if (
-        this.lockConnection ||
-        this.reconnectAttempts >= this.maxReconnectAttempts
-      ) {
-        return;
-      }
+      if (this.lockConnection) return;
 
       this.lockConnection = true;
-      this.reconnectAttempts++;
+      this.reconnectConfig.currentAttempt++;
+
+      // 指数退避算法计算重连间隔
+      const delay = Math.min(
+        this.reconnectConfig.baseInterval *
+          Math.pow(
+            this.reconnectConfig.multiplier,
+            this.reconnectConfig.currentAttempt - 1
+          ),
+        this.reconnectConfig.maxInterval
+      );
 
       console.log(
-        `重新连接中... (尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts})`
+        `将在 ${delay}ms 后尝试第 ${this.reconnectConfig.currentAttempt} 次重连`
       );
 
       setTimeout(() => {
-        this.connect(this.uuid);
+        if (!this.isConnected) {
+          this.connect(this.uuid);
+        }
         this.lockConnection = false;
-      }, this.reconnectInterval);
+      }, delay);
     },
     // 重连
     disconnect() {
@@ -234,7 +281,7 @@ export const useWebSocketStore = defineStore("webSocketStore", {
         this.peer.close();
         this.peer = null;
       }
-      this.reconnectAttempts = 0;
+      this.heartCheck.retryCount = 0;
     },
 
     // 发送WebRTC消息
@@ -247,7 +294,9 @@ export const useWebSocketStore = defineStore("webSocketStore", {
 
       reader.onload = (event) => {
         try {
-          const messagePB = MessageType.decode(new Uint8Array(event.target?.result));
+          const messagePB = MessageType.decode(
+            new Uint8Array(event.target?.result)
+          );
           const message = MessageType.toObject(messagePB, {
             longs: String,
             enums: String,
@@ -258,7 +307,7 @@ export const useWebSocketStore = defineStore("webSocketStore", {
           handleMessageHook(message, this);
 
           // 调用所有回调函数
-          this.onMessageCallbacks.forEach(cb => {
+          this.onMessageCallbacks.forEach((cb) => {
             try {
               cb(message);
             } catch (e) {
@@ -288,7 +337,9 @@ export const useWebSocketStore = defineStore("webSocketStore", {
     },
 
     removeOnMessageCallback(cb) {
-      this.onMessageCallbacks = this.onMessageCallbacks.filter(item => item !== cb);
+      this.onMessageCallbacks = this.onMessageCallbacks.filter(
+        (item) => item !== cb
+      );
     },
   },
 });

+ 3 - 3
src/updater/update.json

@@ -1,7 +1,7 @@
 {
-  "version": "1.0.54",
-  "releaseDate": "2025-08-11 11:15:30",
-  "checksum": "6e113d8daf10836fccb51cdae7631218dcbe90b0476b0ffc75d8f01ff48992c7",
+  "version": "1.0.56",
+  "releaseDate": "2025-08-12 02:29:05",
+  "checksum": "c5da4cd027d82dfc77a570f213a3ba30df48f21f625596c60d17fda7c545852f",
   "minBinaryVersion": "1.0.0",
   "mandatory": true,
   "upDataDescription": "✨修正一些錯誤。。。。!!!"

+ 5 - 1
src/views/im/components/CallController/index.vue

@@ -55,7 +55,7 @@
 import { useWebSocketStore } from "@/stores/modules/webSocketStore";
 import { useWebRTCStore } from "@/stores/modules/webrtcStore";
 import * as Constant from "@/common/constant/Constant";
-
+import { soundVoice } from "@/utils/notifications.js";
 const wsStore = useWebSocketStore();
 const rtcStore = useWebRTCStore();
 
@@ -100,6 +100,7 @@ function onMessage(message) {
 }
 
 async function acceptCall() {
+  soundVoice.stop()
   try {
     inCall.value = true;
     wsStore.sendMessage({
@@ -114,6 +115,7 @@ async function acceptCall() {
 }
 
 function rejectCall() {
+  soundVoice.stop()
   wsStore.sendMessage({
     messageType: Constant.MESSAGE_TYPE_USER,
     contentType: Constant.REJECT_AUDIO_ONLINE,
@@ -124,6 +126,7 @@ function rejectCall() {
 }
 
 function hangupCall() {
+  soundVoice.stop()
   rtcStore.cleanup();
   wsStore.sendMessage({
     messageType: Constant.MESSAGE_TYPE_USER,
@@ -132,6 +135,7 @@ function hangupCall() {
   });
   rtcStore.imSate.videoCallModal = false;
   inCall.value = false;
+ 
 }
 
 watch(