seaislee1209
c53144b2ac
feat(notification): 站内通知系统 — Notification 模型 + 4 个 API + Sidebar 铃铛 + 通知中心页
后端 — 新建 app apps.notifications:
- Notification model:type/title/content/link_url/is_read,索引 (recipient, is_read, -created_at)
- 4 个 endpoint:
- GET /api/v1/notifications/ (列表 + 总未读数,unread_only/page/page_size)
- GET /api/v1/notifications/unread-count (轻量,前端 60s 轮询用)
- PATCH /api/v1/notifications/<id>/read (标单条已读)
- POST /api/v1/notifications/read-all (一键全部已读)
- 严格守 user 隔离:所有查询都 filter(recipient=request.user)
- INSTALLED_APPS 注册 + urls.py include
- migration 0001_initial 应用成功
- MySQL 严格模式:所有 CharField 加 default=''(memory feedback_mysql_default)
后端 — anomaly_detector 集成:
- _RULE_LABELS / _team_admin_recipients() / _notify_user_disabled() / _notify_team_disabled() helper
- process_anomalies 里 _disable_user/_disable_team 之后调对应 notify
- 接收人 = 同团队的主管+副管(is_team_admin OR is_team_owner)
- 用 bulk_create 一次写多条
- try/except 保护:通知失败不阻断封禁主流程
前端:
- types/index.ts:AppNotification / NotificationListResponse(避开浏览器 Web API Notification 冲突)
- lib/api.ts:notificationApi (list/getUnreadCount/markRead/markAllRead)
- store/notification.ts:Zustand store 乐观更新(markRead 先动 UI 再发请求)
- pages/NotificationsPage.tsx:标题 + 全部标记已读按钮 + 未读蓝点 + 相对时间 + 点击跳 link_url + 分页
- App.tsx:/notifications 路由(ProtectedRoute 不限 role)
- Sidebar.tsx(用户 76px):铃铛 SVG + 红点 + 60s 轮询 + visibilitychange 立即刷新
- AdminLayout.tsx(超管 220px):同步加铃铛(本来 sub-agent 只加了用户侧 sidebar,我补全 admin 侧)
测试:
- 新建 web/test/v0.20.1-smoke.mjs:11 项 — 铃铛/红点/跳页/标题/100dvh/min-height:0/调试折叠/poster
- 11/11 通过 + v2-smoke 25/25 + modal-interaction 8/8 全部基线 OK
- 后端 4 endpoint 用 curl 验过:list / unread-count / PATCH read / POST read-all 都正常
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:32:29 +08:00
..
2026-03-16 05:49:21 +08:00
2026-05-12 18:32:29 +08:00
2026-05-12 18:32:29 +08:00
2026-05-12 18:32:29 +08:00
2026-05-12 18:32:29 +08:00
2026-05-12 18:32:29 +08:00
2026-05-12 18:32:29 +08:00
2026-05-11 20:24:24 +08:00
2026-03-13 10:35:49 +08:00
2026-03-13 09:59:33 +08:00