## Context 系统已经存在 `ArtNotification` 顶部通知组件,但组件中的通知、消息和待办列表都是静态数据,顶部通知按钮处于注释状态。新的通知能力需要同时服务顶部快速查看和完整通知中心,并确保用户在任一入口执行已读操作后未读数与列表状态一致。 ## Goals / Non-Goals - Goals: 提供余额预警、临期提醒、审批结果和系统告警统一的站内通知入口。 - Goals: 在顶部快速查看最近 10 条通知,并提供进入通知中心的入口。 - Goals: 支持通知分类、类型、严重级别和已读状态筛选。 - Goals: 将通知点击导航限制在前端认可的业务目标内,禁止任意 URL 跳转。 - Goals: 单条已读、全部已读、抽屉和通知中心共享同一份未读状态。 - Non-Goals: 不实现 C 端通知页面。 - Non-Goals: 不实现推送通道或服务端通知生成规则。 - Non-Goals: 不让前端根据通知正文推断跳转地址。 ## Decisions - Decision: 通知铃铛放在顶部全局导航的设置按钮和用户头像菜单附近。 - Rationale: 该区域已承载全局设置和用户级入口,适合放置跨页面可访问的通知入口,也符合产品指定位置。 - Decision: 顶部抽屉只加载最近 10 条,完整通知中心使用独立路由 `/notifications`。 - Rationale: 顶部入口保持轻量,筛选和完整历史查询放在独立页面,避免挤占全局导航空间。 - Decision: 未读数使用独立接口获取,单条通知和全部已读成功后立即更新本地共享状态,并以接口返回值为最终结果。 - Rationale: 未读数是全局状态,不能依赖当前抽屉或列表的局部数量推导。 - Decision: 点击通知先调用单条已读接口,再调用目标接口,根据返回的受控 route name/route params 跳转。 - Rationale: 已读状态必须在导航前落库,目标由后端业务引用解析,前端不执行通知携带的任意 URL。 - Decision: 未知 `ref_type` 或目标接口无可用目标时只展示通知正文和状态,不跳转。 - Rationale: 保证安全,同时让无法关联页面的系统通知仍然可读。 - Decision: `unread-summary` 为顶部抽屉分类提供数据,`notifications` 为通知中心筛选列表提供数据。 - Rationale: 顶部快速查看与完整列表的数据量和筛选职责不同,避免顶部加载完整历史数据。 ## Data Contract - Notification item: id, title, content, category, type, severity, read status, created time and optional `ref_type`/reference ID. - Unread count: non-negative integer; frontend formats it as `0`, `1`-`99` or `99+`. - Unread summary: category counts and recent notification items, limited to the latest 10 items for the drawer. - Notification list: paginated items plus total count, with category, type, severity and read-state filters. - Target response: controlled internal route information, such as route name/path and route params; no arbitrary executable URL. ## Risks / Trade-offs - Risk: 后端通知字段或枚举名称与文档不一致。 - Mitigation: 在任务阶段先确认字段契约,类型层保留稳定的可选字段和未知值占位展示。 - Risk: 用户在多个标签页同时读通知,单页本地未读数短暂不一致。 - Mitigation: 操作成功后刷新未读数和当前列表;跨标签实时同步不作为本期强制目标。 - Risk: 目标记录已删除或用户权限发生变化。 - Mitigation: 目标接口返回不可跳转时只展示正文,并处理权限/不存在状态,不回退到任意 URL。 ## Migration Plan 1. 确认通知列表、摘要、未读数和目标接口字段及枚举。 2. 新增通知 API service、类型和共享状态。 3. 将顶部通知按钮放入设置/头像区域,接入未读数和最近通知抽屉。 4. 新增 `/notifications` 路由及通知中心页面。 5. 实现筛选、单条已读、全部已读和受控目标跳转。 6. 删除或替换 `ArtNotification` 中的静态 mock 数据,并验证四类通知展示一致。 ## Open Questions - 通知中心是否需要分页参数名称 `page/page_size`,以及默认每页数量需要后端确认。 - `category`、`type`、`severity` 和 `read_status` 的枚举值及展示名称需要后端确认。 - 目标接口返回 route name、path 还是 route key + params,需要与路由菜单契约确认。 - 未读数是否需要页面进入时定时刷新或仅在打开抽屉/完成操作时刷新,本期默认按接口调用时机刷新。 - 通知中心菜单权限和按钮权限编码需要后端权限表确认。