import { create } from 'zustand'; import { getUnreadCount, listMessages, markRead, type MessageInfo } from '../api/messages'; interface MessageState { unreadCount: number; recentMessages: MessageInfo[]; fetchUnreadCount: () => Promise; fetchRecentMessages: () => Promise; markAsRead: (id: string) => Promise; connectSSE: () => () => void; } // 请求去重:记录正在进行的请求,防止并发重复调用 let unreadCountPromise: Promise | null = null; let recentMessagesPromise: Promise | null = null; export const useMessageStore = create((set, get) => ({ unreadCount: 0, recentMessages: [], fetchUnreadCount: async () => { // 如果已有进行中的请求,复用该 Promise if (unreadCountPromise) { await unreadCountPromise; return; } unreadCountPromise = (async () => { try { const result = await getUnreadCount(); set({ unreadCount: result.count }); } catch { // 静默失败,不影响用户体验 } finally { unreadCountPromise = null; } })(); await unreadCountPromise; }, fetchRecentMessages: async () => { if (recentMessagesPromise) { await recentMessagesPromise; return; } recentMessagesPromise = (async () => { try { const result = await listMessages({ page: 1, page_size: 5 }); set({ recentMessages: result.data }); } catch { // 静默失败 } finally { recentMessagesPromise = null; } })(); await recentMessagesPromise; }, markAsRead: async (id: string) => { const prev = { unreadCount: get().unreadCount, recentMessages: get().recentMessages }; set((state) => ({ unreadCount: Math.max(0, state.unreadCount - 1), recentMessages: state.recentMessages.map((m) => m.id === id ? { ...m, is_read: true } : m, ), })); try { await markRead(id); } catch { set({ unreadCount: prev.unreadCount, recentMessages: prev.recentMessages }); } }, connectSSE: () => { const baseUrl = import.meta.env.VITE_API_BASE_URL || '/api/v1'; const token = localStorage.getItem('token'); if (!token) return () => {}; const url = `${baseUrl}/messages/stream?token=${encodeURIComponent(token)}`; const es = new EventSource(url); es.addEventListener('message', () => { get().fetchUnreadCount(); get().fetchRecentMessages(); }); es.addEventListener('alert', () => { get().fetchUnreadCount(); }); es.addEventListener('vital_update', () => { // 体征数据更新事件 — 预留:未来可触发趋势图刷新 }); es.onerror = () => { // SSE 连接断开时 EventSource 会自动重连 }; return () => { es.close(); }; }, }));