// composables/useSignalR.js import { ref, onMounted, onUnmounted } from 'vue'; import { HubConnection, HubConnectionBuilder, HttpTransportType, LogLevel } from '@microsoft/signalr'; export function useSignalR() { const connection = ref(null) // 存储连接实例 const connectionId = ref('') // 存储 connectionId const isConnected = ref(false) // 连接状态 const sigMsg = ref(''); const error = ref(null); const authStore = useAuthStore(); const config = useRuntimeConfig(); // 消息处理器集合(支持多个监听器) const messageHandlers = ref({}); const hubUrl = config.public.signalRUrl; console.log("SignalR地址:", hubUrl); // 连接配置 const connect = async () => { try { connection.value = new HubConnectionBuilder() .withUrl(hubUrl, { accessTokenFactory: () => { const token = authStore.token; // 使用 Nuxt 的 useCookie 获取 Token return token.value; }, skipNegotiation: true, // 仅当使用 CORS 时需要 transport: HttpTransportType.WebSockets, // 优先 WebSocket // httpClient: { // fetch: async (url, options) => { // // 添加 Token 到请求头 // options.headers = { // ...options.headers, // Authorization: `Bearer ${useCookie('token')?.value}` // } // return fetch(url, options) // } // } }) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: (retryContext) => { // 自定义重连间隔(例如:首次 2s,之后 5s、10s...) return retryContext.retryCount === 0 ? 2000 : 5000 * retryContext.retryCount; } }) .configureLogging(LogLevel.Information) .build(); // 监听连接成功事件(关键!) // connection.value.on('ConnectionOpened', () => { // connectionId.value = connection.value?.connectionId as string // isConnected.value = true // console.log('SignalR 连接成功,connectionId:', connectionId.value) // }) // 注册消息处理 connection.value.on('ReceiveProgress', (progress, msg) => { // console.log("ReceiveProgress", progress, msg); sigMsg.value = JSON.stringify({ progress, msg }); // messages.value.push({ progress, msg, time: new Date() }); // 触发自定义事件(可选) if (messageHandlers.value['ReceiveProgress']) { messageHandlers.value['ReceiveProgress'](progress, msg); } }); connection.value.on("ReceiveConnectionId", (conId) => { connectionId.value = conId; console.log('SignalR 连接成功,connectionId:', conId) }); // 连接状态变更 connection.value.onclose((err) => { isConnected.value = false; error.value = err?.message || '连接意外断开'; console.error('SignalR 连接关闭:', err); }); // 启动连接 await connection.value.start(); console.log('SignalR 连接成功,connectionId:', connection.value.connectionId) isConnected.value = true; error.value = null; } catch (err) { isConnected.value = false; connectionId.value = ''; error.value = err.message || '连接失败'; console.error('SignalR 连接启动失败:', err); } }; // 断开连接 const disconnect = async () => { if (connection.value) { await connection.value.stop(); isConnected.value = false; connectionId.value = ''; } }; // 发送消息 const sendMessage = async (method, ...args) => { if (!isConnected.value) { throw new Error('未连接到 SignalR 服务'); } try { await connection.value.invoke(method, ...args); } catch (err) { error.value = `发送失败: ${err.message}`; throw err; } }; // 注册消息监听器(支持自定义事件) const on = (eventName, callback) => { if (!messageHandlers.value[eventName]) { messageHandlers.value[eventName] = []; } messageHandlers.value[eventName].push(callback); }; // 移除监听器 const off = (eventName, callback) => { if (messageHandlers.value[eventName]) { messageHandlers.value[eventName] = messageHandlers.value[eventName].filter(cb => cb !== callback); } }; // 生命周期钩子:自动连接 onMounted(() => { connect(); }); // 生命周期钩子:组件卸载时断开 onUnmounted(() => { disconnect(); messageHandlers.value = {}; // 清理监听器 }); return { isConnected, sigMsg, error, connectionId, connect, disconnect, sendMessage, on, off }; }