# 公共站内通知前端联调与验收契约 ## 交付边界 本文是后台管理端、代理端和 C 端的框架无关契约。当前仓库不包含前端源码,因此页面组件、状态管理和浏览器联调必须在对应前端仓库实施;本文不把契约完成表述为前端实现或人工验收完成。 第一版固定使用 HTTP 轮询,不使用 WebSocket/SSE,也不维护 Redis 未读计数。 ## 未读轮询与徽标 后台布局和 C 端消息入口挂载后立即请求各自的 `unread-count`,之后每 30 秒刷新: 1. 页面变为不可见时暂停计时器。 2. 页面恢复可见时立即刷新一次,再恢复 30 秒周期。 3. 请求失败时保留上一次成功值,不改写为 0;后续周期静默重试。 4. 组件卸载时必须清理计时器,避免重复轮询。 徽标固定宽度,验收矩阵如下: | `count` | `display_count` | 展示 | |---:|---|---| | 0 | `0` | 隐藏徽标 | | 1 | `1` | 显示 1 | | 99 | `99` | 显示 99 | | 100 | `99+` | 显示 99+ | 前端直接使用后端 `display_count`,不自行重复计算上限。 ## 后台铃铛、抽屉和通知中心 铃铛点击后使用 `GET /api/admin/notifications?page=1&page_size=10` 加载最近 10 条。抽屉提供“全部、审批、临期、同步、系统”入口,对应 `category` 为空或 `approval/expiry/sync/system`。 完整通知中心使用服务端参数: - `category`:`approval/expiry/sync/system` - `type`:稳定通知类型 - `severity`:`info/warning/error/critical` - `is_read`:已读状态 - `page/page_size`:服务端分页,默认 20、最大 50 “全部已读”调用 `PUT /api/admin/notifications/read-all`。当前分类为空时提交空对象;在分类视图中提交对应 `category`,成功后使用 `updated_count` 更新提示并重新拉取列表、汇总和未读数。 加载时保留已有内容并展示局部加载状态;首次空结果展示空态;请求失败展示重试入口,不把上一页数据伪装成新筛选结果。 ## 点击、已读和受控目标 点击顺序固定为: 1. 立即进入已读视觉状态。 2. 调用 `PUT /api/admin/notifications/:id/read`。 3. 调用 `GET /api/admin/notifications/:id/target`。 4. 只有 `available=true` 且 `target_type` 在前端白名单内时,使用结构化 `target_id/target_key` 构造站内路由。 已读请求失败时以下一次服务端刷新为准;目标解析失败或不可用不恢复未读。响应不包含 URL,前端禁止把 `target_id`、`target_key` 当作路径或完整地址直接跳转。 目标白名单: | `target_type` | 结构化标识 | 页面语义 | |---|---|---| | `refund_detail` | `target_id` | 退款详情 | | `agent_recharge_detail` | `target_id` | 代理充值详情 | | `wecom_approval_detail` | `target_id` | 企微审批详情 | | `iot_card_detail` | `target_id` | 物联网卡详情 | | `device_detail` | `target_id` | 设备详情 | | `expiring_asset_list` | `target_id` | 指定店铺的临期资产列表 | | `shop_fund_summary` | `target_id` | 店铺资金概况 | | `integration_log` | `target_key` | 外部集成记录 | | `system_config` | `target_key` | 受控系统配置 | 未知类型、空 `target_type` 或 `available=false` 只展示正文,不跳转、不回退到自由 URL。 示例: ```json { "code": 0, "msg": "success", "data": { "target_type": "shop_fund_summary", "target_id": 42, "available": true }, "timestamp": "2026-07-24T11:00:00+08:00" } ``` ## C 端简化通知中心 C 端只调用: - `GET /api/c/v1/notifications/unread-count` - `GET /api/c/v1/notifications?page=&page_size=` - `PUT /api/c/v1/notifications/read-all` - `PUT /api/c/v1/notifications/:id/read` C 端不展示后台筛选、分类汇总、同步或系统运维消息。列表只呈现当前个人客户可见的已开放审批、套餐、订单和资产业务通知。无通知时展示空态;网络失败保留上一成功结果并允许重试。 ## 联调验收矩阵 - 后台账号只能读取和修改自己的通知,构造其他通知 ID 不泄露事实。 - 个人客户之间完全隔离,C 端不能通过 ID 已读其他客户通知。 - 过期通知不进入列表、未读数、分类汇总或受控目标解析。 - 静态 `/read-all`、`/unread-count`、`/unread-summary` 不被 `/:id` 路由吞掉。 - 筛选、翻页、全部已读后,列表、汇总和徽标最终一致。 - 权限变化、目标删除和未知引用均显示正文但不跳转。 - 0、1、99、100 四个徽标边界无布局抖动。 - 页面隐藏时无轮询,恢复后立即刷新;失败期间未读数不闪回零。