Files
nl-im-pc/src/composables/useWebSocket.js
liqi 355a26051d 修复:
1. 本地视频流能获取到了
2. 找到了视频连接错误的原因:挂断后本地麦克风和视频并没有关闭

现有问题:
1. 需要在挂断后关闭麦克风和摄像头
2. 没有渲染远程流推送的视频
2025-07-11 08:15:38 +08:00

186 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ref, onMounted, onUnmounted } from "vue"
import { useUserStore } from "@/stores/user"
import { useChatStore } from "@/stores/chat"
export function useWebSocket() {
const userStore = useUserStore()
const chatStore = useChatStore()
const socket = ref(null)
const isConnected = ref(false)
const isConnecting = ref(false)
const reconnectAttempts = ref(0)
const maxReconnectAttempts = 5
const reconnectDelay = ref(1000)
const connectWebSocket = () => {
if (isConnecting.value || isConnected.value) return
isConnecting.value = true
chatStore.connectionStatus = "connecting"
try {
// const wsUrl = import.meta.env.VITE_WS_URL || "wss://g-ws.nailaoyun.cn/ws"
const wsUrl = import.meta.env.VITE_WS_URL || "ws://localhost:12080/ws"
socket.value = new WebSocket(wsUrl)
socket.value.onopen = handleOpen
socket.value.onmessage = handleMessage
socket.value.onclose = handleClose
socket.value.onerror = handleError
} catch (error) {
console.error("WebSocket连接失败:", error)
isConnecting.value = false
chatStore.connectionStatus = "disconnected"
}
}
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
// 绑定当前用户
if (userStore.currentUser?.id) {
bindUser(userStore.currentUser.id)
}
}
const handleMessage = (event) => {
try {
const data = JSON.parse(event.data)
console.log("收到WebSocket消息:", data)
// 优先处理通话信令(无论是否在当前聊天窗口)
if (data.call_id && data.call_status) {
handleCallSignal(data)
return
}
// 处理普通消息 - 添加来源判断防止循环
if (data.sender_user_id && data.receiver_user_id) {
chatStore.handleIncomingMessage(data, userStore.currentUser?.id)
}
} catch (error) {
console.error("解析WebSocket消息失败:", error)
}
}
const handleClose = (event) => {
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})`)
connectWebSocket()
}, reconnectDelay.value)
}
}
const handleError = (error) => {
console.error("WebSocket错误:", error)
isConnecting.value = false
chatStore.connectionStatus = "disconnected"
}
const handleCallSignal = (data) => {
console.log("收到通话信令:", data)
chatStore.handleCallSignal(data)
}
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))
console.log("发送消息:", message)
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) => {
return send({
request_type: "call_signal",
...signal,
sender_user_id: userStore.currentUser?.id,
})
}
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(() => {
disconnect()
})
return {
socket,
isConnected,
isConnecting,
connectWebSocket,
disconnect,
send,
sendMessage,
sendCallSignal,
bindUser,
generateCallId,
}
}