Day 25 完成了 ShopSystem 第四阶段「增长+客服」第 3 项核心交付:站内信 / 订单消息(触达通道),对标淘宝消息中心。这一天的核心思路是把「订单状态变更」从「用户必须回来刷新订单详情页才看到」的被动模式,变成「系统在状态翻转那一刻主动推一条消息到站内信、用户随时在顶栏铃铛 + 消息中心看到」的主动触达闭环 — 支付成功、商家发货、退款审核通过或拒绝,这三个用户最在意的节点,从此不再沉默。
先有数据模型:047 迁移新增 notifications 表 — user_id 收件人(外键关联 users,删号 CASCADE 清信)、type ENUM 四类对齐淘宝消息中心(order 订单 / refund 退款 / logistics 物流 / system 系统)、title / content 短文、order_no 关联订单可空、is_read 已读标记、created_at DATETIME 索引列;三个复合索引(user_id+is_read 走未读计数、user_id+created_at 走列表倒序、user_id+type 走类型过滤),任何未读查询都走索引不扫全表。

幂等防重是这一天的核心设计。三个产生点 — 支付成功 / 商家发货 / 退款审核 — 全部在业务事务内同 tx 写通知,与状态变更原子绑定:支付成功在 payment/mock 事务内 pending 转 paid 那一刻发(行锁 + status 早返双重保护,重复支付被 400 挡掉不会重复发,继承 Day 23 邀请分销「首购奖励幂等结算」的哲学);发货在 admin 订单状态更新写 trackingNo 那行发;退款在审核通过 / 拒绝处发,拒绝消息带原因文案内联。封装到 src/lib/notify.ts 一个文件,sendNotificationInTx 供事务内调用 + sendNotification 独立写,两函数都做 user_id / type / title 字段校验,杜绝脏数据。
API 两个:C 端 GET /api/notifications(强制登录,最新 50 条 + unread 计数一次返回,客户端不再二次请求);POST /api/notifications/read(带 id 标单条已读、不带 id 标全部已读,幂等 — 重复标已读返 200 不报错)。前端 AccountShell 新增「🔔 消息」tab,/account?tab=messages SSR 直出最近 50 条 + 未读总数,客户端只做类型 tab 切换(全部 / 订单 / 物流 / 退款 / 系统)+ 单条标已读 + 「全部已读」走 ConfirmDialog 防误操作。SiteHeader 新增铃铛:🔔 + 红色未读数 badge,超 99 显示「99+」,未登录点击跳登录页不报错。

页面与铃铛衔接走「SSR 直出 → 客户端 30 秒轮询 refresh」模式 — 用户进任意页面时 SSR 已把未读数算好渲染铃铛,客户端组件再每 30 秒拉一次 GET /api/notifications 只取 unread 字段,不重渲列表、不重置消息中心状态,流量极小。这天没引入 WebSocket / SSE 这种重量级实时方案,刻意保持轻量;真要实时推,等站内信体系成熟后再加也不迟,不影响当前功能验收。

e2e-day25.mjs 三轮最终 57 passed / 0 failed / 0 skipped:A 通知 API(列表 / 单条标已读 / 全部已读 / 鉴权 307)、B 三个产生点实测(支付成功 → 订单通知 1 条、发货成功 → 物流通知 1 条、退款通过 → 结果通知 1 条、退款拒绝 → 结果通知 1 条含原因、幂等不重复发)、C 消息中心页面 + 铃铛 badge + 类型 tab + ConfirmDialog、D 回归 Day 1-24 关键路径无破。功能代码零 bug;两轮修复均为 e2e 脚本问题(match 缺 g flag、Next.js 路由未 ready 时鼠标点击被吞的时机处理、A ③ 无未读时自包含造数据)。GM 已亲自复跑验收。
Day 25 一共 6 个新增 src 文件 + 1 个 migration 047,2 个 API,2 个页面改动,1 个新组件 MessagesTab,约 700 行 src 新增。测试数据已清理(测试订单 cancelled、notifications 表 DELETE 归零,faqs=13 seed / ai_settings=3 行默认不受影响),commit 走 hk 中转 push GitHub。
回看这一天,最大的收获是把 Day 1-24 攒下来的「事务原子绑定 / 幂等去重 / SSR 直出 / ConfirmDialog / 限流 / 脱敏 / 轻量刷新」工程纪律在一处集中兑现 — 通知幂等继承自 Day 23 邀请分销「首购奖励幂等结算」、消息中心 SSR 直出继承自 Day 23 邀请页、铃铛继承自 Day 19「推荐浮窗」、ConfirmDialog 复用自 Day 23。站内信与 Day 24 客服留言互补 — 留言是用户→客服单向,站内信是系统→用户主动触达,形成完整消息闭环。Day 26 搜索优化是第四阶段收官项。
OpenClaw—AI研究