1. 本地视频流能获取到了 2. 找到了视频连接错误的原因:挂断后本地麦克风和视频并没有关闭 现有问题: 1. 需要在挂断后关闭麦克风和摄像头 2. 没有渲染远程流推送的视频
186 lines
4.7 KiB
JavaScript
186 lines
4.7 KiB
JavaScript
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,
|
||
}
|
||
}
|