Files
boss/docs/superpowers/specs/2026-03-28-wechat-message-forwarding-design.md
2026-03-28 07:08:05 +08:00

10 KiB

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 单条转发消息

单条消息转发后,在目标会话中仍表现为普通消息,但要补充“转发来源”元数据。

本次采用结构:

type ForwardSource = {
  sourceProjectId: string;
  sourceProjectName: string;
  sourceThreadId?: string;
  sourceThreadTitle?: string;
  sourceMessageId: string;
  forwardedBy: string;
  forwardedAt: string;
};

落账本后的单条消息:

type Message = {
  id: string;
  kind: "text" | ...;
  body: string;
  forwardSource?: ForwardSource;
};

要求:

  1. 转发后的消息仍可作为普通消息渲染
  2. 必须保留来源项目、来源消息、来源线程的可追踪信息
  3. 不能只把原消息正文复制过去就结束

5.2 多条聊天记录卡片

多条消息转发后,应写成一条新的 bundle 型消息。

本次采用结构:

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 消息:

type Message = {
  id: string;
  kind: "forward_bundle";
  body: string;
  forwardBundle?: ForwardBundlePayload;
};

要求:

  1. 目标会话中只出现一张聊天记录卡片
  2. 卡片中要能生成合理摘要,如消息数、来源会话、时间范围
  3. bundle 的完整内容要落到账本,不能只存一个标题

6. 服务端接口设计

6.1 现有接口升级

当前已有:

  • POST /api/v1/projects/[projectId]/forwards

这条接口应从“备注转发”升级成真正的微信式转发接口。

本次采用输入结构:

type ForwardProjectMessageInput =
  | {
      mode: "single";
      targetProjectId: string;
      sourceMessageId: string;
    }
  | {
      mode: "bundle";
      targetProjectId: string;
      sourceMessageIds: string[];
    };

当前旧字段 note 不再作为主语义字段,允许兼容但不再作为核心交互入口。

6.2 返回结构

接口返回需要至少表达:

{
  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. 服务端消息结构已经支持 forwardSourceforwardBundle
  5. 转发接口已经支持 single / bundle
  6. 审批闸口已经在接口层和账本层预留