Files
junhong_cmp_fiber/docs/tech-inapp-notifications/前端联调与验收契约.md
2026-07-24 16:07:18 +08:00

108 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 公共站内通知前端联调与验收契约
## 交付边界
本文是后台管理端、代理端和 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 四个徽标边界无布局抖动。
- 页面隐藏时无轮询,恢复后立即刷新;失败期间未读数不闪回零。