Files
hms/apps/web/src/stores/message.ts
iven 59a22e762d
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
fix: 审计修复 — SSE事件监听 + 软删除列表 + 页面配置
- [HIGH] 前端 SSE store 补充 alert/vital_update 事件监听
- [LOW] seed.rs 软删除列表补充 device_readings
- [LOW] 小程序 device-sync 补充 index.config.ts 页面配置
2026-04-27 09:27:30 +08:00

103 lines
2.8 KiB
TypeScript

import { create } from 'zustand';
import { getUnreadCount, listMessages, markRead, type MessageInfo } from '../api/messages';
interface MessageState {
unreadCount: number;
recentMessages: MessageInfo[];
fetchUnreadCount: () => Promise<void>;
fetchRecentMessages: () => Promise<void>;
markAsRead: (id: string) => Promise<void>;
connectSSE: () => () => void;
}
// 请求去重:记录正在进行的请求,防止并发重复调用
let unreadCountPromise: Promise<void> | null = null;
let recentMessagesPromise: Promise<void> | null = null;
export const useMessageStore = create<MessageState>((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();
};
},
}));