import { ref, onMounted, onUnmounted } from 'vue'; let heartbeatTimer: NodeJS.Timeout; export default function () { const socket = ref(null); const message = ref(); const status = ref<'connecting' | 'open' | 'error' | 'closed'>('closed'); const pendingMessages = ref([]); const reconnectAttempts = ref(0); const maxReconnectAttempts = 5; const isConnected = computed(() => { return status.value === 'open' }); const isConnecting = computed(() => { return status.value === 'connecting' }); const config = useRuntimeConfig(); const connectionTimeout = config.public.apiTimeout || 5000; // 5秒连接超时 // 初始化连接 const connect = () => { if (isConnected.value || isConnecting.value) return; status.value = 'connecting'; socket.value = new WebSocket(config.public.wsUrl, "json"); socket.value.onopen = () => { status.value = 'open'; reconnectAttempts.value = 0; console.log('WebSocket连接成功'); retryPendingMessages(); }; socket.value.onmessage = (event) => { message.value = event.data; // console.log('收到消息:', event.data); // try { // const json = JSON.parse(event.data); // // console.info(json); // const evtType = json.type; // console.log(evtType) // } // finally{ // } }; socket.value.onerror = (error) => { status.value = 'error'; console.error('WebSocket发生错误:', error); // 重试逻辑 if (reconnectAttempts.value < maxReconnectAttempts) { setTimeout(connect, 1000 * reconnectAttempts.value); reconnectAttempts.value++; } }; socket.value.onclose = (event) => { status.value = 'closed'; console.log('WebSocket连接关闭'); if (!event.wasClean) { // 非正常关闭时尝试重连 connect(); } }; } // 等待连接就绪 const waitForConnection = () => { return new Promise((resolve, reject) => { if (isConnected.value) { resolve(true); return; } // 设置连接超时 const timeout = setTimeout(() => { reject(new Error('连接超时')); }, connectionTimeout); // 监听连接状态变化 const watchHandle = watch(isConnected, (newVal) => { if (newVal) { clearTimeout(timeout); watchHandle(); // 取消监听 resolve(true); } }, { immediate: true }); }); }; // 发送消息 const send = async (name: string, json: object, token: string = '') => { const msg = { type: name, drawerToken: token || localStorage.getItem('drawerToken') || '', data: json } try { // 等待连接就绪 await waitForConnection(); socket.value.send(JSON.stringify(msg)); if (name != 'ping' && name != 'MouseMove') { console.log('发送消息:', msg); } } catch (error) { console.error('消息发送失败:', error); // 添加到待发队列 pendingMessages.value.push(JSON.stringify({ type: name, data: json })); throw error; } } // 重发待处理消息 const retryPendingMessages = () => { while (pendingMessages.value.length > 0) { const message = pendingMessages.value.shift(); let jsonData = JSON.parse(message); send(jsonData.type, jsonData.data); } }; const startHeartbeat = () => { heartbeatTimer = setInterval(() => { if (socket.value?.readyState === WebSocket.OPEN) { send("ping", {}); // console.log('发送心跳'); } }, 5000) } // const reconnect = ()=>{ // setTimeout(()=>{ // console.log('尝试重新连接WebSocket'); // connect(); // },50000) // } onMounted(() => { connect(); startHeartbeat(); }); onUnmounted(() => { if (heartbeatTimer) { clearInterval(heartbeatTimer); }; socket.value?.close(); }); return { message, status, send, connect, waitForConnection } }