跳转到主要内容

FSD M5 · 通知公告

← 总则 | 附录 → | 上游:PRD §4 M5 实现落点:backend/internal/domain/notification/(service.go 读侧 89 行+hub.go SSE 基座)+ cmd/server/notify_handlers.go + cmd/server/routes.go:96-102(挂载)。事实基准=Go 代码;冻结版 qmtv/server/index.js:474-485 仅差异对拍参照。 域内要点:通知零 SSE(hub.go 属本包但通知读面不走事件——写入方五源自持 INSERT);** announcements 公开面无 amw**;read 是 MySQL 保留字全 SQL 反引号(PRD ①);对账勿混:routes.go:288-290 /admin/announcements* 3 条属 M12 管理后台组。

M5 通知公告

4 端点全量(读 3+公开 1;写侧散布五域:auth/admin/recharge/seed/evaluation 自持 INSERT notifications——本域零写通知)。PRD §4 M5 已登记差异 ①~④(prd-qmtv-v1.md:168)引用不重立。

F5.01 通知读面与已读(notifications 三件)

对应 PRD:§4 M5 · GET /api/notifications、GET /api/notifications/unread-count、POST /api/notifications/read | 状态:实现 | 实现落点:notify_handlers.go:13-52、service.go:44-79 | UI:App.vue 顶栏铃铛(60s 轮询 unread-count)+下拉列表 | 场景挂钩:无专门 e2e(E2E-NAV-01 间接;集成锚 WorkbenchNotifyChain 第十二链覆盖 unread-count 联动+read 双分支)

1 功能定义

站内通知读面:最近 50 条列表、未读计数、已读标记(单条/全标)。

2 触发条件与前置状态

三端点登录态(amw);零前置(无通知返回空/0)。

3 输入与校验

list 无参数;read body {id?} 可选——有 id 单条/无 id 整用户全标(service.go:69-77);id 不属于自己也静默 0 行(无 404 面,quirk 照抄冻结 :480-483)。

4 处理流程

list:SELECT id,user_id,title,content,\read`,created_at … WHERE user_id=? ORDER BY created_at DESC LIMIT 50(:53-55——**无已读过滤、无分页**,quirk;read 反引号 PRD ①)。unread-count:COUNT(*) … AND `read`=0(:63-65)。read:单条 WHERE id=? AND user_id=?/ 全标WHERE user_id=?`(:69-77)。

5 输出与结果状态

list=NotificationRow 数组(read int64 0/1、Content *string 可空下发 null,service.go:20-27);unread-count=ok 裸数字(handler OK(c, n),非对象信封——quirk);read 恒 true。

6 状态流转

read 0→1 单向(无未读回置——通知一旦已读不可逆,照冻结)。

7 边界与异常
条件系统行为提示/码
超过 50 条旧通知不可见(LIMIT 硬截,无分页参数)—
read id 非本人/不存在200 恒 true 静默 0 行(quirk)—
bind 失败/空 body等价全标已读(_ = c.Bind 静默,notify_handlers.go:45——与 DIF-29-23 同族形态,M9 DIF-30-2 同注)—
8 权限与数据规则

authed + amw 全部按 token user_id 隔离(越权静默不暴露存在性);写入方五源形态兼容(content 可空 TEXT)。

F5.02 公告公开面(announcements/active)

对应 PRD:§4 M5 · GET /api/announcements/active ○ | 状态:实现 | 实现落点:notify_handlers.go:53-63、service.go(announcements 段)+routes.go:102(pub 组无 amw)| UI:App.vue 全局公告条 | 场景挂钩:E2E-NAV-01(公开路由巡检覆盖)

1 功能定义

启用中公告列表(管理台 M12 写侧的公开读镜像)。

2 触发条件与前置状态

公开面无鉴权(routes.go:102 pub 组——PRD ③;冻结 index.js:485 无 authRequired 同形)。

3 输入与校验

无参数。

4 处理流程

SELECT id, title, content, active, created_at FROM announcements WHERE active=1 ORDER BY created_at DESC LIMIT 10(显式 5 列非 SELECT *;LIMIT 10 硬截——冻结 index.js:485-487 同;active int64 1/0)。

5 输出与结果状态

AnnouncementRow 数组(id/title/content/active/created_at 蛇形,service.go:30-36);最多 10 条(LIMIT 10 硬截,service.go:87)。

6 状态流转

active 由 M12 admin 面翻转(本域只读)。

7 边界与异常
条件系统行为提示/码
无启用公告空数组(nil→[],DIF-29-1 同族形态)—
启用公告 >10 条仅返回最近 10 条(LIMIT 10 硬截,冻结 index.js:487 同)—
未登录访问200 正常返回(公开面)—
8 权限与数据规则

公开面零鉴权零属主;content 全文下发;admin 写侧三条路由(:288-290)归 M12——本册对账不含。


册尾端点覆盖对账(4/4)

对账 backend/cmd/server/routes.go:96-102 亲数 4 条 ↔ 本册 F5.01~F5.02:

#端点(routes.go:line)节
1GET /notifications(:99)F5.01
2GET /notifications/unread-count(:100)F5.01
3POST /notifications/read(:101)F5.01
4GET /announcements/active(:102,pub 无 amw)F5.02

差异纪律:PRD §4 M5 ①~④ 全引用不重立;本册零新立 DIF(bind 静默已随 DIF-30-2 族注记;quirk 均双方一致照抄)。