coze-middleschool/src/hooks/useMicrosoftSignal.ts

80 lines
2.2 KiB
TypeScript

import { useEffect, useRef } from "react";
import * as signalR from "@microsoft/signalr";
import { useRealtimeClient } from "@/components/Provider/RealtimeClientProvider";
import { useToast } from "@/hooks/use-toast";
export const useSignalRConnection = (params: {
access_token: string;
roomId: string;
}) => {
const connectionRef = useRef<signalR.HubConnection | null>(null);
const { handleDisconnect } = useRealtimeClient();
const { toast } = useToast();
const timerRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
if (!params.access_token || !params.roomId) {
return;
}
const connection = new signalR.HubConnectionBuilder()
.withServerTimeout(30000)
.withAutomaticReconnect()
.withUrl(
`https://api.v3.ycymedu.com/hubs/weminpro?access_token=${params.access_token}&roomId=${params.roomId}`
)
.configureLogging(signalR.LogLevel.Information)
.build();
connectionRef.current = connection;
connection.on("ForceOffline", function (msg) {
// 可加逻辑:注销用户、跳转登录页等
toast({
variant: "destructive",
title: "下线提醒",
description: msg,
});
handleDisconnect();
});
connection.on("SendWarn", function (msg) {
console.warn(`下线提醒:${msg}"`);
// 也可以弹窗提醒用户保存数据
toast({
variant: "destructive",
title: "下线提醒",
description: msg,
});
});
connection
.start()
.then(() => {
console.log("SignalR连接已建立");
timerRef.current = setInterval(() => {
connection.invoke("Ping");
}, 5000);
})
.catch((err) => {
console.error("SignalR连接失败:", err);
});
return () => {
if (connectionRef.current) {
connectionRef.current
.stop()
.then(() => {
clearInterval(timerRef.current as NodeJS.Timeout);
console.log("SignalR连接已关闭");
})
.catch((err) => {
console.error("关闭SignalR连接失败:", err);
});
}
};
}, [params.access_token, params.roomId]);
return connectionRef.current;
};