现象
带图片的用户消息把文字 caption 保存为 type: 'message' + message 字段,但复制和重新生成只读取 type: 'text' + text。正常情况下 caption 应沿用户操作保留下来;当前用户点击复制得到空字符串,点击重新生成则先删除原问答,再用空字符串调用发送函数并静默返回。
触发场景
用户上传或粘贴至少一张图片,同时输入文字说明后发送;随后复制这条多模态消息,或对最后一组问答点击“重新生成”。每个含 caption 的多模态消息都满足条件。
业务影响
复制操作稳定丢失用户输入的文字;重新生成会清掉当前问答却不发出新请求,图片状态也已被清空,用户只看到内容消失且没有错误提示。若复制结果进入知识库或工单,会造成业务信息缺失。
根因(设计层)
同一 MessageContent 联合契约在构造和消费路径被重复手写,判别字段不一致:
// Chat.tsx:297-300,发送路径
{ type : 'message' , message : value . trim ( ) }
// useMessageHandlers.ts:56-58,重新生成路径
userMessage . content . find ( ( item ) => item . type === 'text' ) ?. text || ''
MessageActions.tsx:55-59 的复制路径也只过滤 type === 'text'。
涉及文件
文件:行
说明
webchat/packages/webchat-ui/src/Chat.tsx:297
caption 构造为 message/message
webchat/packages/webchat-ui/src/hooks/useMessageHandlers.ts:56
重新生成只读 text/text
webchat/packages/webchat-ui/src/components/MessageActions.tsx:55
复制只读 text/text
webchat/packages/webchat-core/src/types.ts:9
联合类型同时允许两种文字形态,未提供统一提取器
调用链
flowchart TD
A["图片加 caption"] --> B["Chat 构造 message 类型内容项"]
B --> C["SessionManager 持久化"]
C --> D["复制只查 text 类型"]
C --> E["重新生成只查 text 类型"]
D -.-> F["剪贴板为空"]
E -.-> G["删除问答后空发送静默返回"]
Loading
证据 / 复现
weops/master@7611c6b44708 的发送、复制和重新生成三个相邻代码块仍使用互斥 discriminant。现有 content-chunks 和 core 测试未覆盖多模态复制或重新生成。最小复现:发送一张图片和文字 hello,复制结果不是 hello;点击重新生成后消息列表被截断,但 handleSendMessage('') 因没有上传图片而立即返回。
建议修复方向
在 core/UI 边界建立唯一的纯文本提取函数,按数组原顺序同时读取 text/text 和 message/message。
复制与重新生成共用该函数,保持普通 string 与既有 text/text 调用不变。
scoped 最小修复先让重新生成继续发送 caption 文本;是否连同图片引用完整重放另行定义,不要在本次改动中静默扩大上传契约。
增加 text-only、image-only、caption、混合顺序以及无 caption 的行为测试。
功能影响 / 回归风险
不改公开字段、鉴权或默认行为;旧 string 和 text/text 调用保持原结果,新增的是此前稳定丢失的 message/message caption。重新生成当前公开函数只接受 string,因此兼容型最小实现仅重发 caption,不自动重传图片;若后续要完整重放图片,应先盘点后端 payload、存储中的 data URL 和上传限制,再设计可回滚迁移。回滚可恢复旧提取器,但应保留测试以明确这是功能回退。
严重性判断
定 Medium:多模态功能已公开且常规复制/重新生成操作可稳定触发数据丢失和静默无效;不涉及越权或服务端数据破坏。共享提取器与聚焦测试即可修复,工作量 S。
严重度:Medium 工作量:S
负责人:@QiuJia-layla
现象
带图片的用户消息把文字 caption 保存为
type: 'message'+message字段,但复制和重新生成只读取type: 'text'+text。正常情况下 caption 应沿用户操作保留下来;当前用户点击复制得到空字符串,点击重新生成则先删除原问答,再用空字符串调用发送函数并静默返回。触发场景
用户上传或粘贴至少一张图片,同时输入文字说明后发送;随后复制这条多模态消息,或对最后一组问答点击“重新生成”。每个含 caption 的多模态消息都满足条件。
业务影响
复制操作稳定丢失用户输入的文字;重新生成会清掉当前问答却不发出新请求,图片状态也已被清空,用户只看到内容消失且没有错误提示。若复制结果进入知识库或工单,会造成业务信息缺失。
根因(设计层)
同一
MessageContent联合契约在构造和消费路径被重复手写,判别字段不一致:MessageActions.tsx:55-59的复制路径也只过滤type === 'text'。涉及文件
webchat/packages/webchat-ui/src/Chat.tsx:297message/messagewebchat/packages/webchat-ui/src/hooks/useMessageHandlers.ts:56text/textwebchat/packages/webchat-ui/src/components/MessageActions.tsx:55text/textwebchat/packages/webchat-core/src/types.ts:9调用链
flowchart TD A["图片加 caption"] --> B["Chat 构造 message 类型内容项"] B --> C["SessionManager 持久化"] C --> D["复制只查 text 类型"] C --> E["重新生成只查 text 类型"] D -.-> F["剪贴板为空"] E -.-> G["删除问答后空发送静默返回"]证据 / 复现
weops/master@7611c6b44708的发送、复制和重新生成三个相邻代码块仍使用互斥 discriminant。现有content-chunks和 core 测试未覆盖多模态复制或重新生成。最小复现:发送一张图片和文字hello,复制结果不是hello;点击重新生成后消息列表被截断,但handleSendMessage('')因没有上传图片而立即返回。建议修复方向
text/text和message/message。text/text调用不变。功能影响 / 回归风险
不改公开字段、鉴权或默认行为;旧 string 和
text/text调用保持原结果,新增的是此前稳定丢失的message/messagecaption。重新生成当前公开函数只接受 string,因此兼容型最小实现仅重发 caption,不自动重传图片;若后续要完整重放图片,应先盘点后端 payload、存储中的 data URL 和上传限制,再设计可回滚迁移。回滚可恢复旧提取器,但应保留测试以明确这是功能回退。严重性判断
定 Medium:多模态功能已公开且常规复制/重新生成操作可稳定触发数据丢失和静默无效;不涉及越权或服务端数据破坏。共享提取器与聚焦测试即可修复,工作量 S。
严重度:Medium 工作量:S
负责人:@QiuJia-layla