83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
/**
|
|
* SSE Toast通知Hook
|
|
* 通过Server-Sent Events接收实时Toast推送
|
|
*/
|
|
|
|
import { useEffect } from 'react';
|
|
|
|
export interface ToastData {
|
|
id: number;
|
|
type: 'success' | 'info' | 'calling';
|
|
message: string;
|
|
duration: number;
|
|
}
|
|
|
|
interface UseToastSSEOptions {
|
|
familyId: string;
|
|
onToast: (toast: ToastData) => void;
|
|
}
|
|
|
|
export function useToastSSE({ familyId, onToast }: UseToastSSEOptions) {
|
|
useEffect(() => {
|
|
const sseUrl = `http://localhost:8000/api/elderly/toast/stream?family_id=${familyId}`;
|
|
let eventSource: EventSource | null = null;
|
|
let reconnectTimeout: NodeJS.Timeout | null = null;
|
|
|
|
const connect = () => {
|
|
try {
|
|
console.log('[SSE Toast] 连接中...');
|
|
eventSource = new EventSource(sseUrl);
|
|
|
|
eventSource.onopen = () => {
|
|
console.log('[SSE Toast] 连接已建立');
|
|
};
|
|
|
|
eventSource.onmessage = (event) => {
|
|
try {
|
|
const data = JSON.parse(event.data);
|
|
|
|
// 忽略连接确认消息
|
|
if (data.type === 'connected') {
|
|
console.log('[SSE Toast] 连接已确认');
|
|
return;
|
|
}
|
|
|
|
// 收到Toast通知
|
|
console.log('[SSE Toast] 收到通知:', data);
|
|
onToast(data as ToastData);
|
|
} catch (err) {
|
|
console.error('[SSE Toast] 解析数据失败:', err);
|
|
}
|
|
};
|
|
|
|
eventSource.onerror = (error) => {
|
|
console.error('[SSE Toast] 连接错误:', error);
|
|
eventSource?.close();
|
|
|
|
// 5秒后重连
|
|
reconnectTimeout = setTimeout(() => {
|
|
console.log('[SSE Toast] 尝试重新连接...');
|
|
connect();
|
|
}, 5000);
|
|
};
|
|
} catch (error) {
|
|
console.error('[SSE Toast] 连接失败:', error);
|
|
}
|
|
};
|
|
|
|
// 建立连接
|
|
connect();
|
|
|
|
// 清理
|
|
return () => {
|
|
console.log('[SSE Toast] 清理连接');
|
|
if (eventSource) {
|
|
eventSource.close();
|
|
}
|
|
if (reconnectTimeout) {
|
|
clearTimeout(reconnectTimeout);
|
|
}
|
|
};
|
|
}, [familyId, onToast]);
|
|
}
|