193 lines
5.1 KiB
TypeScript
193 lines
5.1 KiB
TypeScript
import { onMounted, onUnmounted, ref } from 'vue';
|
||
|
||
import { useChatStore } from '../stores/chat';
|
||
import { useUserStore } from '../stores/user';
|
||
// useVbenUserStore
|
||
export function useWebSocket() {
|
||
const userStore = useUserStore();
|
||
const chatStore = useChatStore();
|
||
|
||
const socket = ref();
|
||
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';
|
||
const wsUrl = 'wss://api.ws.g.xiaokang88.com/ws';
|
||
// const wsUrl = import.meta.env.VITE_WS_URL || "wss://g-ws.nailaoyun.cn/ws"
|
||
socket.value = new WebSocket(wsUrl);
|
||
|
||
socket.value.addEventListener('open', handleOpen);
|
||
socket.value.onmessage = handleMessage;
|
||
socket.value.addEventListener('close', 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;
|
||
console.log(userStore.currentUser, 'ssssssssss')
|
||
|
||
// 绑定当前用户
|
||
if (userStore.currentUser?.doctor_id) {
|
||
bindUser(userStore.currentUser.doctor_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?.doctor_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, 30_000);
|
||
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',
|
||
user_type: 'doctor',
|
||
sender_user_id: `doctor-${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?.doctor_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?.doctor_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).slice(2, 11);
|
||
};
|
||
|
||
// onMounted(() => {
|
||
// connectWebSocket();
|
||
// });
|
||
|
||
onUnmounted(() => {
|
||
disconnect();
|
||
});
|
||
|
||
return {
|
||
socket,
|
||
isConnected,
|
||
isConnecting,
|
||
connectWebSocket,
|
||
disconnect,
|
||
send,
|
||
sendMessage,
|
||
sendCallSignal,
|
||
bindUser,
|
||
generateCallId,
|
||
};
|
||
}
|