Ver código fonte

Merge branch 'master' of https://git.nanodreamtech.com/wkw/wallet_app

wkw 1 semana atrás
pai
commit
80a23fe310
1 arquivos alterados com 221 adições e 169 exclusões
  1. 221 169
      src/stores/modules/webSocketStore.js

+ 221 - 169
src/stores/modules/webSocketStore.js

@@ -1,184 +1,236 @@
 // src/stores/websocket.ts
-import { defineStore } from 'pinia'
-import { ref } from 'vue' 
-import { $root as protobuf } from '@/common/proto/proto'
-import * as Constant from '@/common/constant/Constant'
+import { defineStore } from "pinia";
+import { $root as protobuf } from "@/common/proto/proto";
+import * as Constant from "@/common/constant/Constant";
 import { useWalletStore } from "@/stores/modules/walletStore";
 
-//  MessageType = $root.lookupType("protocol.Message");
-
-
-
-export const useWebSocketStore = defineStore('webSocketStore', () => {
-  const socket = ref(null) // 创建WebSocket对象
-  const peer = ref(null) // 创建RTCPeerConnection对象
-  const lockConnection = ref(false)
-  const reconnectAttempts = ref(0)
-  const maxReconnectAttempts = 5
-  const reconnectInterval = 3000
-
-  // 心跳检测
-  const heartCheck = {
-    timeout: 10000,
-    timeoutObj: null,
-    serverTimeoutObj: null,
-    num: 3,
-    start: function () {
-      const self = this
-      const _num = this.num
-      
-      this.timeoutObj && clearTimeout(this.timeoutObj)
-      this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
-      
-      this.timeoutObj = setTimeout(() => {
-        if (socket.value?.readyState === 1) {
+export const useWebSocketStore = defineStore("webSocketStore", {
+  // 状态定义
+  state: () => ({
+    socket: null, // socket实例
+    peer: null, // peer实例
+    lockConnection: false, // 锁定连接
+    reconnectAttempts: 0, // 重连次数
+    maxReconnectAttempts: 5, // 最大重连次数
+    reconnectInterval: 3000, // 重连间隔
+    messages: [], // 消息列表
+    unreadMessages: [], // 未读消息列表
+    lastMessage: null, // 最后一条消息
+
+    // 心跳检测配置
+    heartCheck: {
+      timeout: 10000, // 连接丢失后,多长时间内没有收到服务端的消息,则认为连接已断开
+      timeoutObj: null, // 定时器对象
+      serverTimeoutObj: null, // 服务器定时器对象
+      num: 3, // 重连次数
+    },
+  }),
+
+  // 计算属性
+  getters: {
+    isConnected: (state) => state.socket?.readyState === WebSocket.OPEN,
+    hasUnreadMessages: (state) => state.unreadMessages.length > 0,
+  },
+
+  // 方法
+  actions: {
+    // 初始化socket
+    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 = setTimeout(() => {
+        if (this.socket?.readyState === WebSocket.OPEN) {
           const data = {
             type: "heatbeat",
             content: "ping",
-          }
-          const message = protobuf.lookup("protocol.Message")
-          const messagePB = message.create(data)
-          socket.value.send(message.encode(messagePB).finish())
+          };
+          const MessageType = protobuf.lookupType("protocol.Message");
+          const messagePB = MessageType.create(data);
+          const buffer = MessageType.encode(messagePB).finish();
+          this.socket.send(buffer);
         }
 
-        self.serverTimeoutObj = setTimeout(() => {
-          _num--
+        self.heartCheck.serverTimeoutObj = setTimeout(() => {
+          _num--;
           if (_num <= 0) {
-            console.log("the ping num is more then 3, close socket!")
-            socket.value?.close()
+            console.log("the ping num is more then 3, close socket!");
+            this.socket?.close();
           }
-        }, self.timeout)
-      }, this.timeout)
-    }
-  }
-
-  // 连接WebSocket
-  const connect = (userUuid) => {
-    console.log("开始连接...")
-    peer.value = new RTCPeerConnection()
-    socket.value = new WebSocket(`ws://192.168.0.59:8888/api/v1/socket.io?user=${userUuid}`)
-
-    socket.value.onopen = () => {
-      heartCheck.start()
-      console.log("链接")
-      webrtcConnection()
-    }
-
-    socket.value.onmessage = (event) => {
-      heartCheck.start()
-      handleMessage(event.data)
-    }
-
-    socket.value.onclose = () => {
-      console.log("关闭并重新连接-->--->")
-      reconnect()
-    }
-
-    socket.value.onerror = () => {
-      console.log("error----->>>>")
-      reconnect()
-    }
-  }
-
-  // 处理接收到的消息
-  const handleMessage = (data) => {
-    const messageProto = protobuf.lookupType("protocol.Message")
-    const reader = new FileReader()
-    
-    reader.readAsArrayBuffer(data)
-    reader.onload = (event) => {
-      const messagePB = messageProto.decode(new Uint8Array(event.target?.result))
-      // 单独解码 
-      console.log(messagePB)
-      
-      if (messagePB.type === "heatbeat") return
-      
-      if (messagePB.type === Constant.MESSAGE_TRANS_TYPE) {
-        dealWebRtcMessage(messagePB)
-        return
-      }
-      
-      // 其他消息处理...
-    }
-  }
-
-  // WebRTC 连接
-  const webrtcConnection = () => {
-    if (!peer.value) return
-    
-    peer.value.onicecandidate = (e) => {
-      if (e.candidate && socket.value) {
-        const candidate = {
-          type: 'answer_ice',
-          iceCandidate: e.candidate
+        }, self.heartCheck.timeout);
+      }, this.heartCheck.timeout);
+    },
+
+    resetHeartbeat() {
+      this.heartCheck.timeoutObj && clearTimeout(this.heartCheck.timeoutObj);
+      this.heartCheck.serverTimeoutObj &&
+        clearTimeout(this.heartCheck.serverTimeoutObj);
+      this.heartCheck.num = 3;
+    },
+    // 链接ws
+    connect(userUuid) {
+      console.log("开始连接...");
+      this.disconnect(); // 确保先断开现有连接
+
+      this.peer = new RTCPeerConnection();
+      this.socket = new WebSocket(
+        `ws://192.168.0.59:8888/api/v1/socket.io?user=${userUuid}`
+      );
+
+      this.socket.onopen = () => {
+        this.startHeartbeat();
+        console.log("WebSocket连接成功");
+        this.webrtcConnection();
+      };
+
+      this.socket.onmessage = (event) => {
+        this.startHeartbeat();
+        this.handleMessage(event.data);
+      };
+
+      this.socket.onclose = () => {
+        console.log("连接关闭,尝试重新连接...");
+        this.resetHeartbeat();
+        this.reconnect();
+      };
+
+      this.socket.onerror = (error) => {
+        console.error("WebSocket错误:", error);
+        this.resetHeartbeat();
+        this.reconnect();
+      };
+    },
+    // 处理消息
+    handleMessage(data) {
+      const MessageType = protobuf.lookupType("protocol.Message");
+      const reader = new FileReader();
+
+      reader.onload = (event) => {
+        try {
+          const messagePB = MessageType.decode(
+            new Uint8Array(event.target?.result)
+          );
+          const message = MessageType.toObject(messagePB, {
+            longs: String,
+            enums: String,
+            bytes: String,
+          });
+
+          console.log("收到消息:", message);
+
+          // 更新状态
+          this.messages.push(message);
+          this.lastMessage = message;
+
+          if (message.type === "heatbeat") return;
+
+          if (message.type === Constant.MESSAGE_TRANS_TYPE) {
+            this.dealWebRtcMessage(message);
+            return;
+          }
+
+          // 其他消息处理逻辑...
+        } catch (error) {
+          console.error("消息解码错误:", error);
         }
-        const message = {
-          content: JSON.stringify(candidate),
-          type: Constant.MESSAGE_TRANS_TYPE,
+      };
+
+      reader.readAsArrayBuffer(data);
+    },
+    // 处理WebRTC消息    
+    webrtcConnection() {
+      if (!this.peer) return;
+
+      this.peer.onicecandidate = (e) => {
+        if (e.candidate && this.socket) {
+          const candidate = {
+            type: "answer_ice",
+            iceCandidate: e.candidate,
+          };
+          const message = {
+            content: JSON.stringify(candidate),
+            type: Constant.MESSAGE_TRANS_TYPE,
+          };
+          this.sendMessage(message);
         }
-        sendMessage(message)
+      };
+
+      this.peer.ontrack = (e) => {
+        if (e && e.streams) {
+          const remoteVideo = document.getElementById("remoteVideoReceiver");
+          const remoteAudio = document.getElementById("audioPhone");
+
+          if (remoteVideo) remoteVideo.srcObject = e.streams[0];
+          if (remoteAudio) remoteAudio.srcObject = e.streams[0];
+        }
+      };
+    },
+    // 断线重连    
+    reconnect() {
+      if (
+        this.lockConnection ||
+        this.reconnectAttempts >= this.maxReconnectAttempts
+      ) {
+        return;
+      }
+
+      this.lockConnection = true;
+      this.reconnectAttempts++;
+
+      console.log(
+        `重新连接中... (尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts})`
+      );
+
+      setTimeout(() => {
+        this.connect(localStorage.uuid);
+        this.lockConnection = false;
+      }, this.reconnectInterval);
+    },
+    // 重连
+    disconnect() {
+      if (this.socket) {
+        this.resetHeartbeat();
+        this.socket.close();
+        this.socket = null;
       }
-    }
-
-    peer.value.ontrack = (e) => {
-      if (e && e.streams) {
-        const remoteVideo = document.getElementById("remoteVideoReceiver")
-        const remoteAudio = document.getElementById("audioPhone")
-        
-        if (remoteVideo) remoteVideo.srcObject = e.streams[0]
-        if (remoteAudio) remoteAudio.srcObject = e.streams[0]
+      if (this.peer) {
+        this.peer.close();
+        this.peer = null;
       }
-    }
-  }
-
-  // 处理WebRTC消息
-  const dealWebRtcMessage = (messagePB) => {
-    // 实现与React版本相同的逻辑
-  }
-
-  // 重新连接
-  const reconnect = () => {
-    if (lockConnection.value) return
-    lockConnection.value = true
-
-    setTimeout(() => {
-      if (socket.value?.readyState !== 1) {
-        connect(localStorage.uuid)
+      this.reconnectAttempts = 0;
+    },
+    // 发送消息    
+    sendMessage(messageData) {
+      if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
+        console.error("WebSocket未连接");
+        return false;
+      }
+
+      const walletStore = useWalletStore();
+      const data = {
+        ...messageData,
+        fromUsername: walletStore.username,
+        from: walletStore.account,
+      };
+
+      try {
+        const MessageType = protobuf.lookupType("protocol.Message");
+        const messagePB = MessageType.create(data);
+        const buffer = MessageType.encode(messagePB).finish();
+        this.socket.send(buffer);
+        return true;
+      } catch (error) {
+        console.error("消息编码错误:", error);
+        return false;
       }
-      lockConnection.value = false
-    }, 10000)
-  }
-
-  // 发送消息
-  const sendMessage = (messageData) => {
-    if (!socket.value) return
-    const walletStore = useWalletStore()
-    const data = {
-      ...messageData,
-      fromUsername: walletStore.username,
-      from: walletStore.account,
-    }
-    
-    const message = protobuf.lookup("protocol.Message")
-    const messagePB = message.create(data)
-    socket.value.send(message.encode(messagePB).finish())
-  }
-
-  // 关闭连接
-  const close = () => {
-    socket.value?.close()
-    peer.value?.close()
-    socket.value = null
-    peer.value = null
-  }
-
-  return {
-    socket,
-    peer,
-    connect,
-    sendMessage,
-    close,
-    dealWebRtcMessage,
-    webrtcConnection
-  }
-})
+    },
+    // 发送WebRTC消息
+    dealWebRtcMessage(message) {
+      // 实现WebRTC消息处理逻辑
+    },
+  },
+});