Files
nl-im-pc/src/composables/useWebSocket.js

186 lines
4.7 KiB
JavaScript
Raw Normal View History

2025-07-04 12:56:18 +08:00
import { ref, onMounted, onUnmounted } from "vue"
2025-07-02 16:54:52 +08:00
import { useUserStore } from "@/stores/user"
import { useChatStore } from "@/stores/chat"
export function useWebSocket() {
const userStore = useUserStore()
const chatStore = useChatStore()
2025-07-04 12:56:18 +08:00
const socket = ref(null)
const isConnected = ref(false)
const isConnecting = ref(false)
const reconnectAttempts = ref(0)
const maxReconnectAttempts = 5
const reconnectDelay = ref(1000)
2025-07-02 16:54:52 +08:00
const connectWebSocket = () => {
2025-07-04 12:56:18 +08:00
if (isConnecting.value || isConnected.value) return
isConnecting.value = true
chatStore.connectionStatus = "connecting"
2025-07-02 16:54:52 +08:00
try {
// const wsUrl = import.meta.env.VITE_WS_URL || "wss://g-ws.nailaoyun.cn/ws"
2025-07-04 12:56:18 +08:00
const wsUrl = import.meta.env.VITE_WS_URL || "ws://localhost:12080/ws"
socket.value = new WebSocket(wsUrl)
2025-07-02 16:54:52 +08:00
2025-07-04 12:56:18 +08:00
socket.value.onopen = handleOpen
socket.value.onmessage = handleMessage
2025-07-05 16:09:14 +08:00
socket.value.onclose = handleClose
2025-07-04 12:56:18 +08:00
socket.value.onerror = handleError
} catch (error) {
console.error("WebSocket连接失败:", error)
isConnecting.value = false
chatStore.connectionStatus = "disconnected"
}
}
2025-07-02 16:54:52 +08:00
2025-07-04 12:56:18 +08:00
const handleOpen = (event) => {
console.log("WebSocket连接已建立")
isConnected.value = true
isConnecting.value = false
reconnectAttempts.value = 0
reconnectDelay.value = 1000
chatStore.connectionStatus = "connected"
chatStore.socket = socket.value
2025-07-05 16:09:14 +08:00
// 绑定当前用户
if (userStore.currentUser?.id) {
bindUser(userStore.currentUser.id)
}
2025-07-04 12:56:18 +08:00
}
const handleMessage = (event) => {
try {
const data = JSON.parse(event.data)
2025-07-05 16:09:14 +08:00
console.log("收到WebSocket消息:", data)
2025-07-02 16:54:52 +08:00
// 优先处理通话信令(无论是否在当前聊天窗口)
2025-07-04 12:56:18 +08:00
if (data.call_id && data.call_status) {
handleCallSignal(data)
return
2025-07-02 16:54:52 +08:00
}
// 处理普通消息 - 添加来源判断防止循环
2025-07-04 12:56:18 +08:00
if (data.sender_user_id && data.receiver_user_id) {
chatStore.handleIncomingMessage(data, userStore.currentUser?.id)
2025-07-02 16:54:52 +08:00
}
} catch (error) {
2025-07-04 12:56:18 +08:00
console.error("解析WebSocket消息失败:", error)
2025-07-02 16:54:52 +08:00
}
}
2025-07-05 16:09:14 +08:00
const handleClose = (event) => {
2025-07-04 12:56:18 +08:00
console.log("WebSocket连接已关闭:", event.code, event.reason)
isConnected.value = false
isConnecting.value = false
chatStore.connectionStatus = "disconnected"
chatStore.socket = null
// 自动重连
if (reconnectAttempts.value < maxReconnectAttempts) {
setTimeout(() => {
reconnectAttempts.value++
reconnectDelay.value = Math.min(reconnectDelay.value * 2, 30000)
console.log(`尝试重连 (${reconnectAttempts.value}/${maxReconnectAttempts})`)
2025-07-05 16:09:14 +08:00
connectWebSocket()
2025-07-04 12:56:18 +08:00
}, reconnectDelay.value)
2025-07-02 16:54:52 +08:00
}
}
2025-07-04 12:56:18 +08:00
const handleError = (error) => {
console.error("WebSocket错误:", error)
isConnecting.value = false
chatStore.connectionStatus = "disconnected"
}
const handleCallSignal = (data) => {
console.log("收到通话信令:", data)
2025-07-05 16:09:14 +08:00
chatStore.handleCallSignal(data)
2025-07-04 12:56:18 +08:00
}
const bindUser = (userId) => {
if (!isConnected.value || !userId) return
const bindMessage = {
request_type: "bind",
sender_user_id: userId,
}
send(bindMessage)
}
const send = (message) => {
if (!isConnected.value || !socket.value) {
console.error("WebSocket未连接无法发送消息")
return false
}
try {
socket.value.send(JSON.stringify(message))
2025-07-05 16:09:14 +08:00
console.log("发送消息:", message)
2025-07-04 12:56:18 +08:00
return true
} catch (error) {
console.error("发送消息失败:", error)
return false
}
}
const sendMessage = (receiverUserId, messageType, content) => {
const message = {
request_type: "send_message",
sender_user_id: userStore.currentUser?.id,
receiver_user_id: receiverUserId,
message_type: messageType,
message_content: content,
}
return send(message)
}
const sendCallSignal = (signal) => {
2025-07-05 16:09:14 +08:00
return send({
request_type: "call_signal",
...signal,
2025-07-09 08:18:59 +08:00
sender_user_id: userStore.currentUser?.id,
2025-07-05 16:09:14 +08:00
})
2025-07-04 12:56:18 +08:00
}
const disconnect = () => {
if (socket.value) {
socket.value.close()
socket.value = null
}
isConnected.value = false
isConnecting.value = false
chatStore.connectionStatus = "disconnected"
chatStore.socket = null
}
// 生成唯一ID
const generateCallId = () => {
return Date.now().toString() + Math.random().toString(36).substr(2, 9)
}
onMounted(() => {
connectWebSocket()
})
onUnmounted(() => {
2025-07-05 16:09:14 +08:00
disconnect()
2025-07-04 12:56:18 +08:00
})
2025-07-02 16:54:52 +08:00
return {
2025-07-04 12:56:18 +08:00
socket,
isConnected,
isConnecting,
2025-07-02 16:54:52 +08:00
connectWebSocket,
2025-07-05 16:09:14 +08:00
disconnect,
2025-07-04 12:56:18 +08:00
send,
sendMessage,
sendCallSignal,
bindUser,
generateCallId,
2025-07-02 16:54:52 +08:00
}
2025-07-09 08:18:59 +08:00
}