Bubble 消息操作区改造:复制、重新生成和反馈

Bubble 消息操作区改造:复制、重新生成和反馈

前言

如果继续沿着"从简单到复杂"的路线往下走,新增 variant 之后,比较适合作为第三步的改造就是:

扩展 Bubble 的 header、footer 和 actions 区域。

普通聊天产品里,消息一般只需要展示文本内容。

但 Agent 产品不太一样。Agent 的回复通常更长,也更像一次任务执行结果。用户看完之后,往往还需要做一些操作,比如:

  • 复制回答
  • 重新生成
  • 点赞
  • 点踩
  • 查看执行过程
  • 展开详情
  • 收起内容

所以在 Agent 场景里,Bubble 不应该只是一个"消息气泡",还应该具备一定的消息操作能力。

这篇文章主要梳理:如何基于 Bubble 的 header / footer 能力,设计一个更适合 Agent 产品的消息操作区。

为什么要改消息操作区

普通聊天消息一般是这样的:

txt 复制代码
AI:你好,我可以帮你做什么?

这种消息比较短,展示文本就够了。

但 Agent 产品里的消息可能是这样的:

txt 复制代码
AI Assistant

我已经分析了 Bubble 组件的结构,主要结论如下:

1. Bubble.vue 负责单条消息渲染
2. interface.ts 定义组件 props
3. content.ts 负责 variant 和 shape 样式
4. hooks 负责 typing 等交互逻辑

[复制] [重新生成] [有帮助] [无帮助]

这时候操作区就很重要。

因为用户不只是"看消息",还会继续对这条消息做操作。

在真实 Agent 产品中,常见操作包括:

操作 作用
复制 复制 AI 回复内容
重新生成 对当前问题重新生成答案
点赞 标记回答有帮助
点踩 标记回答不满意
展开 展开较长内容或执行过程
查看过程 查看 Agent 思考链或工具调用

所以,消息操作区可以看作 Agent 对话体验里非常基础的一环。

先看 src/bubble/interface.ts

BubbleProps 中已经有:

ts 复制代码
header?: AvoidValidation<VNode | string | ((content: ContentType, info: SlotInfoType) => VNode | string)>;
footer?: AvoidValidation<VNode | string | ((content: ContentType, info: SlotInfoType) => VNode | string)>;

也就是说,Bubble 本身已经支持:

  • header
  • footer

这两个区域。

再看 src/bubble/Bubble.vue,里面会计算 _header_footer

tsx 复制代码
const _header = slots.header
  ? slots.header({ content: typedContent.value as T, info: { key: _key } })
  : typeof header === 'function'
    ? header(typedContent.value as T, { key: _key })
    : header;

const _footer = slots.footer
  ? slots.footer({ content: typedContent.value as T, info: { key: _key } })
  : typeof footer === 'function'
    ? footer(typedContent.value as T, { key: _key })
    : footer;

这段逻辑说明:

  1. 如果外部传了 header slot,就优先用 slot。
  2. 如果没有 slot,但传了 header prop,就用 prop。
  3. footer 也是同样逻辑。

然后组件会把它们渲染出来:

tsx 复制代码
<div class={`${prefixCls}-content-wrapper`}>
  {_header && (
    <div class={`${prefixCls}-header`}>
      {_header}
    </div>
  )}

  {_content}

  {_footer && (
    <div class={`${prefixCls}-footer`}>
      {_footer}
    </div>
  )}
</div>

所以当前 Bubble 其实已经具备扩展消息头部和底部的能力。

这对我们做 actions 改造很有帮助。

header、footer 和 actions 的区别

这三个概念容易混在一起。

可以先这样区分:

区域 主要作用 例子
header 消息头部信息 AI 名称、模型名、时间
content 消息主体内容 文本、Markdown、代码块
footer 消息底部区域 操作按钮、状态、反馈
actions footer 中的一组操作 复制、重新生成、点赞、点踩

也就是说:

txt 复制代码
actions 通常是 footer 里面的一部分。

当前 Bubble 已经有 footer,但没有专门的 actions prop。

所以我们有两种改造思路:

  1. 先用 footer slot 实现 actions。
  2. 后续如果需求稳定,再新增 actions prop。

我更建议先走第一种。

因为它风险更低,不需要马上改组件 API。

最简单的方式,是直接在使用 Bubble 时传入 footer。

示例:

vue 复制代码
<Bubble
  variant="agent"
  placement="start"
  content="我已经分析完 Bubble 组件,下面是主要结论。"
>
  <template #header>
    <div class="bubble-demo-header">
      AI Assistant
    </div>
  </template>

  <template #footer>
    <div class="bubble-demo-actions">
      <button>复制</button>
      <button>重新生成</button>
      <button>有帮助</button>
      <button>无帮助</button>
    </div>
  </template>
</Bubble>

这种方式的优点是:

  • 不用改 Bubble 源码
  • 能快速验证交互效果
  • 适合在 play 中做 demo
  • 不影响原有组件行为

缺点是:

  • 每次使用都要自己写 footer
  • actions 没有统一规范
  • 不方便做统一的 hover、loading、disabled 逻辑

所以它适合第一阶段验证,不一定适合作为最终组件库 API。

第二种方案:新增 actions prop

如果公司内部确实需要统一的消息操作区,可以考虑给 Bubble 增加 actions

比如在 interface.ts 中增加:

ts 复制代码
export interface BubbleAction {
  key: string;
  label?: string;
  icon?: VNode;
  disabled?: boolean;
  onClick?: () => void;
}

然后在 BubbleProps 中增加:

ts 复制代码
actions?: BubbleAction[];

使用时可以这样:

vue 复制代码
<Bubble
  variant="agent"
  placement="start"
  content="我已经分析完成。"
  :actions="[
    { key: 'copy', label: '复制' },
    { key: 'regenerate', label: '重新生成' },
    { key: 'like', label: '有帮助' },
    { key: 'dislike', label: '无帮助' },
  ]"
/>

这样业务侧就不用每次都自己写 footer。

组件内部可以统一处理:

  • 操作按钮样式
  • hover 展示
  • loading 隐藏
  • disabled 状态
  • 图标样式
  • 点击事件

但是这个方案会修改组件 API,所以要更谨慎。

它更适合在 footer slot 方案验证稳定之后再做。

第三种方案:footer 和 actions 共存

比较合理的最终方案是:

txt 复制代码
footer 用来承载完全自定义内容
actions 用来承载标准操作按钮

也就是说:

  • 如果用户传了 footer slot,就完全自定义底部。
  • 如果用户传了 actions,组件自动渲染标准操作区。
  • 如果两者都没有,就不显示底部。

大致优先级可以设计为:

txt 复制代码
footer slot > footer prop > actions prop > 不显示 footer

这样既保留了灵活性,也提供了标准化能力。

Agent 场景下 actions 应该怎么展示

我更建议 Agent 风格的 actions 采用"弱展示"。

原因是 AI 回复通常较长,如果操作按钮一直很醒目,会干扰阅读。

可以考虑:

状态 展示方式
默认 操作区弱展示或半透明
hover 消息 显示完整操作按钮
loading 中 隐藏重新生成和反馈
typing 中 可以隐藏全部 actions
error 显示重试或复制错误信息
用户消息 只显示复制
AI 消息 显示复制、重新生成、反馈

比如:

txt 复制代码
AI 消息完成后:
[复制] [重新生成] [有帮助] [无帮助]

AI 消息生成中:
不显示 actions,或者只显示停止生成

用户消息:
[复制]

这样会更符合真实 Agent 产品的体验。

loading 时为什么要隐藏 actions

Bubble 已经支持:

ts 复制代码
loading?: boolean;
typing?: TypingOption | boolean;

当 AI 消息还在生成时,内容可能还不完整。

这时候如果显示:

txt 复制代码
复制
重新生成
点赞
点踩

会有几个问题:

  • 复制到的是不完整内容
  • 重新生成时机不明确
  • 用户还没看完,反馈没有意义
  • 操作区会干扰 loading 状态

所以更合理的规则是:

txt 复制代码
loading 或 typing 时,不显示常规 actions。

等消息生成完成后,再显示操作区。

如果后续需要,也可以单独设计生成中的操作,比如:

txt 复制代码
停止生成

但这通常更适合放在 Sender 或全局运行状态里,不一定放在 Bubble 的 footer 中。

用户消息和 AI 消息的 actions 不一样

在对话产品里,用户消息和 AI 消息的操作通常不一样。

用户消息常见操作:

  • 复制
  • 编辑
  • 重新发送

AI 消息常见操作:

  • 复制
  • 重新生成
  • 点赞
  • 点踩
  • 查看过程

如果现在只做简单版本,可以先定规则:

txt 复制代码
user 消息:只显示复制
assistant 消息:显示复制、重新生成、反馈

如果使用 BubbleList,可以通过 role 来控制不同角色的 footer。

比如:

ts 复制代码
const roles = {
  assistant: {
    placement: 'start',
    variant: 'agent',
    footer: () => renderAssistantActions(),
  },
  user: {
    placement: 'end',
    variant: 'filled',
    footer: () => renderUserActions(),
  },
};

这样业务侧不用每条消息都重复配置。

建议的落地顺序

为了避免一开始就改太多,我建议按这个顺序做。

第一步,在 play 中用 footer slot 做静态 demo。

先不改源码,只验证:

  • header 是否显示正常
  • footer 是否显示正常
  • actions 是否适合放在底部
  • AI 消息和用户消息是否需要不同操作

第二步,补充 actions 样式。

可以先在 demo 里写局部样式,确认效果后再考虑沉淀到组件样式里。

第三步,增加 hover 交互。

比如默认不显示,hover Bubble 时显示:

css 复制代码
.bubble-demo-actions {
  opacity: 0;
}

.ant-bubble:hover .bubble-demo-actions {
  opacity: 1;
}

第四步,处理 loading / typing。

当消息正在生成时,不显示常规 actions。

第五步,再考虑是否新增 actions prop。

如果 footer slot 已经能满足,就不一定马上改 API。

如果公司内部需要统一规范,再把它抽成 actions

如果要改源码,可能涉及哪些文件

第一阶段只用 footer slot,可以只改:

txt 复制代码
play/src/App.vue

用于展示 demo。

如果要沉淀样式,可能涉及:

txt 复制代码
src/bubble/style/index.ts
src/bubble/style/content.ts

如果要新增 actions API,可能涉及:

txt 复制代码
src/bubble/interface.ts
src/bubble/Bubble.vue
src/bubble/style/index.ts
play/src/App.vue

各文件职责大致是:

文件 作用
interface.ts 定义 actions 类型和 props
Bubble.vue 判断并渲染 actions
style/index.ts 增加 actions 基础样式
play/src/App.vue 验证交互效果

不过当前阶段建议先不要急着新增 API。

先用现有 footer 能力做出来,会更稳。

总结

Bubble 不只是展示消息文本,它也可以承载消息相关操作。

在 Agent 产品中,消息操作区非常常见,尤其是 AI 回复完成后,用户通常需要复制、重新生成、反馈或查看执行过程。

当前 Bubble 已经支持 headerfooter,所以第一阶段可以优先利用 footer slot 实现 actions,不需要马上修改组件 API。

比较推荐的路线是:

txt 复制代码
先用 footer slot 做 demo
-> 验证 AI / 用户消息操作差异
-> 增加 hover 和 loading 交互
-> 再决定是否抽象 actions prop

这样既能快速看到效果,也不会一开始就破坏原有组件设计。

相关推荐
LEE1 小时前
AI Agent 都在疯狂加功能,它说:我全砍了
前端·后端
张清悠1 小时前
用 TRAE Work 把 PRD + 设计稿注释,整理成 20 分钟可排期前端任务清单
前端
Brown.alexis2 小时前
es6知识点5-自备使用
前端·javascript·es6
杨利杰YJlio3 小时前
KB5121003更新详解:安全启动证书、AI组件、资源管理器与安装验证
前端·javascript·后端
紫菜猫一只3 小时前
Vue 3 与 React 常用写法对比
前端
jinggongszh3 小时前
使用AI协同开发产品条码规则功能——从“理解方案、原型、接口文档”到“落地真实前端代码”
前端·人工智能·mes系统·mes工程架构
渔夫正在掘金3 小时前
Cordis 中文教程:渐进式构建插件化应用
前端·node.js·ai编程
打呵欠的猫3 小时前
前端团队 3 个月 AI 实践复盘:哪些场景 ROI 最高,哪些是伪需求
前端·ai编程
gyx_这个杀手不太冷静3 小时前
高级前端开发职业规划(2026—2035)
前端·面试·agent