1. 页面概览

协同动态页(GothamCollaborationPage.vue)是 LightGotham 项目协作域(TAD-11)的实时协同中心:选中一个协作项目后,集中展示三块内容——成员对情报对象的评论列表、项目活动时间线、以及个人通知中心。页面最独特的是 WebSocket 实时通道:登录即自动连接 /gotham-api/v1/ws,订阅当前项目 room 后,其他人的评论、任务状态变化、系统告警会以 notification / activity 消息实时推送到页面,通知列表自动刷新并弹 toast 提示,无需手动刷新。

一句话总结:协同动态页把"谁在项目里说了什么、做了什么、通知了我什么"通过 WebSocket 变为实时可见。

2. 访问入口

3. 界面布局

+--------------------------------------------------+
| Gotham 协同动态    [项目下拉]   [刷新]            |
+--------------------------------------------------+
| [alert 操作结果提示条(可关闭)]                  |
+--------------------------------------------------+
| [ws-bar 实时推送状态条]  ● 实时通知已连接/未连接   |
+--------------------------------------------------+
| [评论(N)]                 | [活动时间线(N)]   |
|   [评论输入(@ 补全下拉)][类型][对象ID][发表]     |
|   评论项:作者/对象徽标/时间/内容/提及N人/删除     |
|                             |   [分页:上一页/下一页] |
+--------------------------------------------------+
| [通知中心(N)]  [刷新] [全部已读]  [仅看未读]    |
|   类型 | 标题 | 内容 | 时间 | 状态 | 标记已读      |
+--------------------------------------------------+

4. 交互元素

控件位置含义与作用
项目下拉页头选择协作项目(#id 名称);切换时先退订旧项目 room 再订阅新项目 room,并刷新评论/活动/通知
「刷新」页头并行重新加载项目、评论、活动、通知
评论内容输入框评论卡片顶部placeholder「输入评论,可 @用户名 提及成员,如:请 @bob 核实法人信息」,回车即发表
@ 自动补全下拉评论输入框下方输入 @ 前缀(字符集同后端正则 @([\w\p{Han}]+))时浮出候选:当前项目成员(GET /collab/projects/:id/members,最多 8 条,按 username(登录名)子串过滤);点选以 @username 回填(后端按 username 解析提及;成员 user_id 为 UUID 不可命中)
「编辑」评论项操作行进入行内编辑态(textarea + 保存/取消);入口仅对「评论作者本人或本项目 owner」显示(后端 PUT /collab/comments/:id 二次校验:非作者且非 owner → 403);保存时后端重新解析 @ 提及并刷新 updated_at
已编辑标记评论项头部updated_at 晚于 created_at 1 秒以上时显示「已编辑 时间」(存量行 updated_at 为零值,不显示)
对象类型下拉评论输入行target_type 五选一:实体 entity / 关系 relationship / 告警 alert / 报告 report / 任务 task
对象 ID 输入框评论输入行target_id,placeholder「对象 ID,如 graph:org:xuanwu」
「发表」评论输入行提交评论(需先选项目、内容非空);成功后清空内容并刷新评论与活动
「提及 N 人」评论项展开显示该评论被 @ 的用户 ID 列表(N 为 mentions 数组长度)
活动分页「上一页/下一页」活动时间线卡片底部服务端分页:每页 20 条,翻页即以 limit=20&offset=(page-1)*20 重新请求后端;页码由响应同级字段 total(项目活动总数)推导,信息条显示「第 X / Y 页 · 每页 20 条 · 共 N 条(服务端分页)」;请求中按钮禁用
「刷新」/「全部已读」通知中心标题栏重新加载通知 / 调 POST /collab/notifications/read-all
「仅看未读」勾选通知中心勾选后仅加载未读通知(unread_only=1)
「标记已读」通知表格操作列仅未读行显示,调 POST /collab/notifications/:id/read

5. 后端关联

方法路径用途
GET/collab/projects列出当前用户参与的项目
GET/collab/projects/:id/members项目成员列表(本页用于构建 @ 自动补全候选:username + role;ListMembers 批量回填登录名)
GET/collab/projects/:id/comments项目评论列表
POST/collab/projects/:id/comments发表评论 {target_type, target_id, content},@ 用户自动提取
PUT/collab/comments/:id编辑评论 {content}(仅作者本人或项目 owner;重新解析 @ 提及、刷新 updated_at)
GET/collab/projects/:id/activities?limit=20&offset=0项目活动时间线(limit 默认 100/上限 500、offset 分页;响应同级 total 为项目活动总数)
GET/collab/projects/:id/member-candidates成员候选用户搜索(本页未用;项目协作页用)
GET/collab/notifications?unread_only=1当前用户通知(可仅未读)
POST/collab/notifications/:id/read标记单条已读
POST/collab/notifications/read-all全部标记已读
WS/ws?token=WebSocket 实时通道

关键机制

WebSocket 协议:客户端发 {"type":"subscribe","project_id":"1"} 订阅项目 room、{"type":"unsubscribe","project_id":"1"} 退订;服务端每 30s Ping、读超时 60s;连接断开后前端 5s 自动重连。收到消息经 window 自定义事件 gotham:ws 广播,页面按消息 type 处理:connected(标记在线并重新订阅当前项目)、notification(toast「新通知:标题」+ 刷新通知)、activity(刷新活动时间线)、alert(toast「系统告警:规则名」+ 刷新通知)。

推送链路:collab 服务的 Notifier(ws.Hub 实现)完成推送——SendToUser 推个人通知({"type":"notification","data":{...}},如 @ 提及、任务状态变化)、SendToProject 广播活动到项目 room({"type":"activity","data":{...}})。

权限模型:collab 服务内校验——读操作需为项目成员,写操作(评论/任务/成员管理)需 owner/editor,成员增删仅 owner。

6. 权限与安全

7. 常见问题与排错

7.1 状态条长期显示「实时通知未连接(自动重连中)」

7.2 通知一直收不到

7.3 发表评论报错

7.4 通知列表与实时推送不同步

8. 已知缺陷与边界

缺陷/边界说明
评论编辑权限口径后端 PUT /collab/comments/:id 为「作者本人或项目 owner」;项目 editor 只能改自己的评论,改他人评论 403(入口在前端已按同口径收敛,后端仍二次校验)。~~评论无编辑~~ 已于 2026-09-17 收口(D1b)
已编辑时间的存量数据gotham_comments.updated_at 为本次新增列,AutoMigrate 补列后存量行取零值时间,前端按「明显晚于 created_at」判定是否显示「已编辑」,零值行不显示
@ 自动补全候选范围候选来自当前项目成员列表(GET /collab/projects/:id/members),非全局用户枚举(本页不走 /collab/projects/:id/member-candidates,该端点供项目协作页加成员用);非项目成员或成员列表拉取失败时无候选,仍可手输 @username(登录名),后端按正则 @([\w\p{Han}]+) 提取并按 username 查 users 表映射,提及不到真实用户则不发通知
活动时间线分页口径~~渲染层分页~~ 已于 2026-09-17 收口(D1b):GET /collab/projects/:id/activities 支持 limit(默认 100,上限 500)+ offset,响应同级字段 total 为项目活动总数;页面按 total 渲染页码并服务端翻页
WS 依赖全局事件组件通过 window 事件 gotham:ws 订阅,推送消息会广播到所有监听者
token 走 queryWS 地址带 token 可能出现在代理日志,安全性由短生命周期 token 兜底

注:评论删除入口已于 2026-09-06 修复(删除按钮作者本人可见,调用后端 DELETE)。

注:评论编辑(D1b)与活动服务端分页(D1b)已于 2026-09-17 补齐,见 wiki/changelog/2026-09-17-7-gotham-collab-and-paging.md。