From 64015d814e3c3d2cf5c76ab4b1b9bac049ddb023 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Wed, 20 May 2026 23:23:19 +0800 Subject: [PATCH] auto-sync: 2026-05-20 23:23:19 --- .../src/components/NotificationCenter.tsx | 71 ++++--------------- 1 file changed, 14 insertions(+), 57 deletions(-) diff --git a/src/frontend/src/components/NotificationCenter.tsx b/src/frontend/src/components/NotificationCenter.tsx index 1350668..2f62b38 100644 --- a/src/frontend/src/components/NotificationCenter.tsx +++ b/src/frontend/src/components/NotificationCenter.tsx @@ -1,7 +1,8 @@ /** * 通知中心 — 烽火台 - * 数据来源:未读邮件(store.mails)+ SSE 事件(store.sseEvents) - * 单一 SSE 连接由 store.ts 管理,这里只读数据 + * 数据来源:SSE 实时事件(store.sseEvents) + * 按 topic7-9 设计:按级别分组、操作按钮、任务链接、全部已读 + * 邮件数据不在此展示(飞鸽传书 Tab 独立展示) */ import { useEffect } from 'react'; @@ -27,66 +28,25 @@ const TYPE_STYLES: Record = { - inform: 'info', task: 'info', alert: 'warning', error: 'error', done: 'success', - }; - return { - id: m.id, - type: typeMap[m.type] || 'info', - title: m.title || '(无标题)', - message: `${m.from || '?'} → ${m.to || '?'}`, - time: m.created_at || '', - read: !!m.is_read, - source: 'mail', - }; -} - export default function NotificationCenter({ onClose }: { onClose: () => void }) { - const mails = useStore(s => s.mails); - const sseEvents = useStore(s => s.sseEvents) as NotifItem[]; - const loadMails = useStore(s => s.loadMails); - - useEffect(() => { loadMails(); }, []); - - // 合并 + 分组 - const mailNotifs = (mails || []).slice(0, 20).map(mailToNotif); - const allNotifs: NotifItem[] = [...(sseEvents || []), ...mailNotifs]; - const unread = allNotifs.filter(n => !n.read).length; + const sseEvents = (useStore(s => s.sseEvents) || []) as NotifItem[]; + const unread = sseEvents.filter(n => !n.read).length; const grouped = LEVEL_ORDER.map(type => ({ type, label: TYPE_STYLES[type].label, - items: allNotifs.filter(n => n.type === type), + items: sseEvents.filter(n => n.type === type), })).filter(g => g.items.length > 0); - const handleMarkRead = async (notif: NotifItem) => { - if (notif.source === 'mail' && !notif.read) { - await fetch(`/api/mail/${notif.id}`, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ is_read: true }), - }); - loadMails(); - } - if (notif.source === 'event') { - useStore.setState({ - sseEvents: (useStore.getState().sseEvents as NotifItem[]).map( - n => n.id === notif.id ? { ...n, read: true } : n - ), - }); - } + const handleMarkRead = (notif: NotifItem) => { + useStore.setState({ + sseEvents: (useStore.getState().sseEvents as NotifItem[]).map( + n => n.id === notif.id ? { ...n, read: true } : n + ), + }); }; - const handleMarkAllRead = async () => { - for (const n of allNotifs.filter(n => !n.read && n.source === 'mail')) { - await fetch(`/api/mail/${n.id}`, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ is_read: true }), - }); - } - loadMails(); + const handleMarkAllRead = () => { useStore.setState({ sseEvents: (useStore.getState().sseEvents as NotifItem[]).map(n => ({ ...n, read: true })), }); @@ -116,7 +76,7 @@ export default function NotificationCenter({ onClose }: { onClose: () => void }) - {allNotifs.length === 0 ? ( + {sseEvents.length === 0 ? (
🔕
暂无烽火
@@ -141,9 +101,6 @@ export default function NotificationCenter({ onClose }: { onClose: () => void })
{s.icon} {n.title} - - {n.source === 'mail' ? '✉️' : '📡'} - {!n.read && }
{n.message}