docs: add wechat message forwarding spec

This commit is contained in:
kris
2026-03-28 07:08:05 +08:00
parent f0735b31e5
commit a9e8bb9ddd

View File

@@ -0,0 +1,376 @@
# Boss 原生 Android 微信式消息转发设计
## 1. 背景
当前 `Boss` 原生 Android 客户端虽然已经恢复到微信式一级结构,但“消息转发”仍停留在过渡态:
- 原生入口还是单独的 `ProjectForwardActivity`
- 交互仍然是“选择目标项目 + 填写备注”
- 服务端接口 `POST /api/v1/projects/[projectId]/forwards` 也仍以 `targetProjectId + note` 为主
这条链路和用户要求的“微信最新逻辑”存在明显差距。用户已经明确要求:
1. 既支持单条消息转发,也支持多选消息合并转发
2. 转发流程要尽量按微信当前逻辑来
3. 单条消息转发后在目标会话里表现为普通转发消息
4. 多条消息转发后在目标会话里表现为聊天记录卡片
5. 当前一次转发先只允许选择一个目标会话
6. 转发链必须兼容现有线程会话、群聊会话和主 Agent 审批规则
因此,这次工作不是只换一个页面,而是要把“消息转发”升级成一条完整的微信式产品链路:
- 原生 Android 交互回到微信式
- 服务端账本结构能表达单条转发和聊天记录卡片
- 目标会话选择页与当前线程会话模型一致
- 群聊和审批规则能继续接入,而不是后续再重做
## 2. 目标
本次设计完成后,消息转发应满足以下目标:
1. 单条消息可从消息操作菜单直接进入转发流程。
2. 多条消息可通过多选模式进入合并转发流程。
3. 单条和多条转发共用一个微信式目标会话选择页。
4. 单次转发只允许选择一个目标会话。
5. 单条消息转发到目标会话后,显示为普通消息,但保留转发来源元数据。
6. 多条消息转发到目标会话后,显示为一张聊天记录卡片,不是多条普通消息的简单堆叠。
7. 转发目标可以是单线程会话、群聊、`主 Agent``审计对话`
8. 非开发任务状态下,如果转发行为会引发线程之间不应直接沟通的情况,后端必须能返回“需要主 Agent / 用户审批”的结果,而不是直接放行。
9. 这次改造不能破坏现有原生聊天页、会话信息页、群资料页和群聊创建链路。
## 3. 非目标
本次不做以下事项:
1. 不支持一次转发到多个目标会话。
2. 不支持转发前编辑消息内容。
3. 不支持微信收藏、逐条再编辑、转发到外部应用等额外能力。
4. 不在本次设计中完成“聊天记录卡片详情页”的完整浏览体验,只要求先把卡片消息结构和列表展示落下。
5. 不改变当前原生 Android 架构、登录恢复、群聊模型或主 Agent 主链执行方式。
## 4. 用户体验设计
### 4.1 单条消息转发
单条消息转发按微信式链路执行:
1. 用户在聊天页长按某条消息。
2. 弹出轻量消息操作菜单。
3. 菜单中点击 `转发`
4. 进入统一的 `选择一个会话` 页。
5. 用户选择一个目标会话。
6. 执行转发。
7. 返回目标会话或给出轻量成功提示。
单条转发后的展示规则:
- 在目标会话中显示为一条普通消息
- 这条消息保留 `转发` 的轻量来源标识,但整体视觉不能变成控制台卡片
- 账本结构中必须带上来源消息信息,便于后续扩展“查看原始消息”
### 4.2 多选消息合并转发
多选消息合并转发按微信式链路执行:
1. 用户在聊天页对消息执行 `多选`
2. 聊天页进入多选模式
3. 用户勾选多条消息
4. 点击底部 `转发`
5. 进入同一个 `选择一个会话`
6. 用户选择一个目标会话
7. 执行合并转发
多选转发后的展示规则:
- 在目标会话中只生成一条消息
- 该消息表现为“聊天记录卡片”
- 不能把多条消息逐条硬插入目标会话里
### 4.3 消息操作菜单
单条消息长按后的操作菜单,本次先保留以下动作:
- `转发`
- `多选`
- `复制`
- `删除`
- `取消`
规则:
1. `转发` 直接进入统一转发流程
2. `多选` 进入消息多选模式
3. 本次不再把“填写备注”作为主流程的一部分
### 4.4 多选模式
多选模式的页面行为如下:
顶部区域:
- 左侧为 `取消`
- 中间显示已选消息数量
- 不再显示普通聊天页标题和轻入口
消息区:
- 每条消息左侧出现勾选控件
- 已勾选消息有明显选中态
底部区域:
- 先只保留 `转发`
- 不在本次加入更多多选操作,避免偏离微信主链
### 4.5 目标会话选择页
单条转发和多选转发共用一个目标会话选择页,规则如下:
1. 页面标题为 `选择一个会话`
2. 页面第一屏直接显示微信式会话列表
3. 会话 cell 沿用当前首页微信式会话样式
4. 当前源会话本身不能作为目标被再次选中
5. 当前一次只能选中一个目标会话
6. 不要求用户填写备注
允许作为目标的会话类型:
- 单线程会话
- 群聊会话
- `主 Agent`
- `审计对话`
## 5. 数据模型设计
### 5.1 单条转发消息
单条消息转发后,在目标会话中仍表现为普通消息,但要补充“转发来源”元数据。
本次采用结构:
```ts
type ForwardSource = {
sourceProjectId: string;
sourceProjectName: string;
sourceThreadId?: string;
sourceThreadTitle?: string;
sourceMessageId: string;
forwardedBy: string;
forwardedAt: string;
};
```
落账本后的单条消息:
```ts
type Message = {
id: string;
kind: "text" | ...;
body: string;
forwardSource?: ForwardSource;
};
```
要求:
1. 转发后的消息仍可作为普通消息渲染
2. 必须保留来源项目、来源消息、来源线程的可追踪信息
3. 不能只把原消息正文复制过去就结束
### 5.2 多条聊天记录卡片
多条消息转发后,应写成一条新的 bundle 型消息。
本次采用结构:
```ts
type ForwardBundleItem = {
messageId: string;
senderLabel: string;
body: string;
kind: string;
sentAt: string;
};
type ForwardBundlePayload = {
sourceProjectId: string;
sourceProjectName: string;
sourceThreadId?: string;
sourceThreadTitle?: string;
itemCount: number;
startedAt: string;
endedAt: string;
items: ForwardBundleItem[];
};
```
落账本后的 bundle 消息:
```ts
type Message = {
id: string;
kind: "forward_bundle";
body: string;
forwardBundle?: ForwardBundlePayload;
};
```
要求:
1. 目标会话中只出现一张聊天记录卡片
2. 卡片中要能生成合理摘要,如消息数、来源会话、时间范围
3. bundle 的完整内容要落到账本,不能只存一个标题
## 6. 服务端接口设计
### 6.1 现有接口升级
当前已有:
- `POST /api/v1/projects/[projectId]/forwards`
这条接口应从“备注转发”升级成真正的微信式转发接口。
本次采用输入结构:
```ts
type ForwardProjectMessageInput =
| {
mode: "single";
targetProjectId: string;
sourceMessageId: string;
}
| {
mode: "bundle";
targetProjectId: string;
sourceMessageIds: string[];
};
```
当前旧字段 `note` 不再作为主语义字段,允许兼容但不再作为核心交互入口。
### 6.2 返回结构
接口返回需要至少表达:
```ts
{
ok: boolean;
message?: Message;
approvalRequired?: boolean;
approvalReason?: string;
}
```
要求:
1. 正常转发成功时返回目标会话中新生成的消息
2. 需要审批时,不直接写入目标会话,而是返回 `approvalRequired=true`
3. 失败时给出明确错误
## 7. 审批与群聊兼容设计
### 7.1 正常转发
以下情况可直接放行:
- 用户主动把消息转发到自己可见的单线程会话
- 用户主动把消息转发到群聊
- 用户主动把消息转发到 `主 Agent`
- 用户主动把消息转发到 `审计对话`
### 7.2 需要审批的场景
如果这次转发在业务语义上会触发:
- 非开发任务状态下的线程直接互相沟通
那么后端必须先命中治理规则:
1. 不直接放行
2. 返回 `approvalRequired`
3. 由主 Agent 再向用户请求批准
这次即使还不把完整审批 UI 全做完,也必须在接口和消息层预留这条分支。
### 7.3 和群聊的关系
转发目标页对群聊和单线程会话一视同仁,目标本质就是会话。
要求:
1. 群聊和单线程会话共用同一套目标选择页
2. 不能因为群聊存在,就做另一套“转群聊”专用流程
3. 后端只在治理规则阶段区分是否需要审批,不在选择页阶段区分
## 8. Android 原生页面设计
### 8.1 ProjectDetailActivity
需要补以下交互:
1. 单条消息长按弹出操作菜单
2. 进入多选模式
3. 多选模式顶部与底部状态切换
4. `转发` 入口跳转到统一会话选择页
### 8.2 新增原生活动页
本次新增:
- `ForwardTargetActivity`
- 统一目标会话选择页
- 同时服务单条转发和多选转发
`ProjectForwardActivity` 不再承担主转发链路,而是下沉为兼容入口;如果旧入口仍被触发,只负责立即跳转到新的 `ForwardTargetActivity`
### 8.3 转发后的返回行为
要求:
1. 转发成功后给出轻量反馈
2. 返回链符合手机直觉
3. 不能出现完成后回退错层、丢当前页状态、或直接退桌面
## 9. 测试与验收标准
### 9.1 单条转发验收
1. 长按某条消息,能看到消息菜单
2.`转发` 后进入目标会话选择页
3. 选择一个会话后,成功写入目标会话
4. 目标会话里显示普通转发消息
5. 服务端账本中能看到 `forwardSource`
### 9.2 多条转发验收
1. 进入多选模式并勾选多条消息
2. 点击底部 `转发`
3. 进入同一个目标会话选择页
4. 选择一个会话后,成功写入目标会话
5. 目标会话中只出现一张聊天记录卡片
6. 服务端账本中能看到 `forwardBundle`
### 9.3 目标选择页验收
1. 会话项样式和首页一致
2. 一次只能选中一个目标会话
3. 源会话本身不能被选中
4. 单线程、群聊、主 Agent、审计对话都能正常显示
### 9.4 审批兼容验收
1. 开发任务场景下,转发能直接通过
2. 命中非开发任务治理规则时,接口返回 `approvalRequired`
3. 命中审批规则时不会把消息错误地直接写进目标会话
### 9.5 本轮实现完成标准
本轮可以视为完成,当且仅当:
1. 原生 Android 已支持单条转发
2. 原生 Android 已支持多选合并转发
3. 目标会话选择页已经替换当前“备注转发页”
4. 服务端消息结构已经支持 `forwardSource``forwardBundle`
5. 转发接口已经支持 `single / bundle`
6. 审批闸口已经在接口层和账本层预留