Files
one-pipe-system/openspec/changes/add-notification-center/design.md
luo d1ff4d5f6c
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m7s
feat: 顶部通知铃铛与站内通知中心
2026-07-24 17:12:29 +08:00

4.5 KiB
Raw Blame History

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,以及默认每页数量需要后端确认。
  • categorytypeseverityread_status 的枚举值及展示名称需要后端确认。
  • 目标接口返回 route name、path 还是 route key + params需要与路由菜单契约确认。
  • 未读数是否需要页面进入时定时刷新或仅在打开抽屉/完成操作时刷新,本期默认按接口调用时机刷新。
  • 通知中心菜单权限和按钮权限编码需要后端权限表确认。