← 返回AI变现
🌐 其他

左侧历史对话模块:使用 Conversations 搭建会话入口

来源:掘金 · 发布于 2026-08-18 10:52:20
本文主要介绍 AI 工作台左侧历史对话模块的设计与实现,说明如何使用 Ant Design X Vue 的 Conversations 组件,同时展示预设能力入口和历史会话列表,并梳理新建会话、切换会

左侧历史对话模块:使用 Conversations 搭建会话入口

one_last_FE 2026-08-18 0 阅读6分钟

左侧历史对话模块:使用 Conversations 搭建会话入口

前言

在 AI 工作台里,左侧通常会有一个会话列表。

它的作用类似很多 AI 产品里的历史记录区域:

左侧选择会话
中间展示当前会话内容

在当前项目中,左侧区域不是自己从零写列表,而是基于 Ant Design X Vue 提供的 Conversations 组件实现。

这篇文章简单介绍一下:

  • 左侧历史对话模块是做什么的;
  • 为什么用了 Conversations;
  • 当前页面有哪些功能;
  • 对应代码在哪里;
  • 如何使用这个组件。

模块位置

左侧历史对话模块对应的文件是:

src/features/workbench/components/HistoryPanel.vue

它被工作台页面使用:

src/pages/workbench/WorkbenchPage.vue

整体关系可以理解成:

WorkbenchPage
  ├── HistoryPanel      左侧历史对话
  ├── ChatWorkspace     中间 AI 对话区
  └── InspectorPanel    右侧过程和产物区

HistoryPanel 只负责左侧区域。

它不负责真正保存所有业务数据,数据主要由父组件 WorkbenchPage 维护。

当前左侧包含什么

当前左侧主要包含四块:

新建应用按钮
搜索框
能力入口
历史对话

页面结构大概是:

image.png

其中:

  • Chat 和 AI Coding 是预设好的能力入口;
  • 历史对话 是用户真实创建或之前存在的会话;
  • 新建应用时,会根据当前选中的能力入口创建不同类型的会话。

为什么要分成能力入口和历史对话

官方 Conversations 示例里,Help Me Write、AI Coding、Create Image 更像是预设能力入口,而不是历史记录本身。

所以当前项目也改成了两层:

第一层:能力入口
第二层:历史对话

这样更符合真实产品逻辑。

比如:

  • 用户先选择 Chat;
  • 然后点击新建应用;
  • 系统创建一个普通对话类任务;
  • 用户选择 AI Coding;
  • 再点击新建应用;
  • 系统创建一个代码修改类任务。

能力入口决定“接下来要创建什么类型的会话”。调用什么模型。不同的任务使用不同模型的效果也有差异,价格也有所差异

历史对话决定“当前正在查看哪一个已有会话”。

Conversations 是什么

Conversations 是 Ant Design X Vue 提供的会话列表组件。

它适合用来做:

  • 历史对话列表;
  • 多会话切换;
  • Agent 能力入口;
  • 会话分组展示。

在当前项目里,我们直接引入它:

import { Conversations } from 'ant-design-x-vue';

然后在模板里使用:

<Conversations
  :items="conversationItems"
  :activeKey="activeKey"
  :groupable="true"
  :onActiveChange="(key) => emit('activeChange', key)"
/>

它最核心的几个参数是:

参数作用
items列表数据
activeKey当前选中的会话
groupable是否开启分组
onActiveChange选中项变化时触发

预设能力入口怎么写

当前项目里,预设能力入口是这样定义的:

const activeCapability = ref<WorkbenchCapability>('chat');

const capabilityItems = [
  {
    key: 'chat',
    label: 'Chat',
    icon: h(CommentOutlined),
  },
  {
    key: 'coding',
    label: 'AI Coding',
    icon: h(CodeOutlined),
  },
];

这里有两个概念。

第一个是:

activeCapability

它表示当前选中的能力入口。

默认值是:

'chat'

也就是默认选中 Chat。

第二个是:

capabilityItems

它就是要展示的预设入口数据。

当前只有两个:

Chat
AI Coding

然后在页面里使用:

<Conversations
  :items="capabilityItems"
  :activeKey="activeCapability"
  :onActiveChange="handleCapabilityChange"
/>

这段的意思是:

  • 展示 Chat 和 AI Coding;
  • 当前选中项由 activeCapability 控制;
  • 用户点击切换时,调用 handleCapabilityChange。

对应函数是:

const handleCapabilityChange = (key: string) => {
  activeCapability.value = key as WorkbenchCapability;
};

它的作用就是:

用户点击哪个能力入口,就把当前能力改成哪个。

历史对话怎么写

历史对话的数据来自父组件传入:

const props = defineProps<{
  items: ConversationItem[];
  activeKey: string;
}>();

这里的:

items

表示所有历史会话。

activeKey

表示当前选中的历史会话。

因为业务里的会话数据字段比较多,而 Conversations 组件只需要一部分字段,所以这里做了一次转换:

const conversationItems = computed(() => props.items.map(item => ({
  key: item.key,
  label: item.label,
  group: item.group,
  icon: item.capability === 'coding' ? h(CodeOutlined) : h(CommentOutlined),
})));

这段代码的作用是:

把业务会话数据转换成 Conversations 可以展示的数据。

比如原始会话数据可能是:

{
  key: 'landing-page',
  label: '企业官网生成',
  group: '今天',
  capability: 'chat',
  description: '首页、服务、联系表单',
  status: 'done',
  messages: []
}

转换之后传给 Conversations 的数据是:

{
  key: 'landing-page',
  label: '企业官网生成',
  group: '今天',
  icon: h(CommentOutlined)
}

也就是说,左侧列表只关心:

  • 唯一标识;
  • 展示名称;
  • 分组;
  • 图标。

其他消息内容、描述、状态等字段,会留给中间对话区使用。

历史对话组件使用

历史对话列表对应的模板是:

<Conversations
  :items="conversationItems"
  :activeKey="activeKey"
  :groupable="true"
  :onActiveChange="(key) => emit('activeChange', key)"
/>

这里重点看:

:groupable="true"

它表示开启分组。

因为 conversationItems 里有:

group: item.group

所以列表会按照 group 展示。

当前 mock 数据里有:

group: '今天'

和:

group: '昨天'

所以左侧就会展示成:

今天
  企业官网生成
  作品集网站

昨天
  商城页面改造

点击历史对话时发生了什么

当用户点击某条历史对话时,会触发:

:onActiveChange="(key) => emit('activeChange', key)"

意思是:

用户点击了某条会话,把这个会话的 key 传给父组件。

父组件 WorkbenchPage 中这样接收:

<HistoryPanel
  :items="conversations"
  :activeKey="activeKey"
  @activeChange="handleActiveChange"
  @create="handleCreate"
/>

其中:

const handleActiveChange = (key: string) => {
  activeKey.value = key;
};

它会把当前选中的会话 key 改掉。

然后中间对话区会根据新的 activeKey 展示对应的消息。

完整流程是:

用户点击历史会话
  ↓
Conversations 触发 onActiveChange
  ↓
HistoryPanel emit('activeChange', key)
  ↓
WorkbenchPage 修改 activeKey
  ↓
ChatWorkspace 展示新的会话内容

点击新建应用时发生了什么

新建按钮代码是:

<a-button type="primary" block @click="emit('create', activeCapability)">
  <template #icon><PlusOutlined /></template>
  新建应用
</a-button>

主要是通知父组件新建应用,这里只需要知道大致功能,具体实现会在父组件介绍。

当前功能总结

当前左侧历史对话模块已经实现:

  • 新建应用按钮;
  • 搜索框样式预留;
  • 预设能力入口;
  • Chat 能力;
  • AI Coding 能力;
  • 历史会话列表;
  • 历史会话分组;
  • 当前会话选中;
  • 点击历史会话切换中间内容;
  • 根据能力入口创建不同类型会话。

其中最核心的组件是:

Conversations

这个组件帮我们省掉了很多重复工作,比如列表渲染、选中状态、分组展示等。

我们主要做的是:

  • 准备 items 数据;
  • 维护 activeKey;
  • 监听 onActiveChange;
  • 根据业务需要区分预设入口和历史对话。

总结

左侧历史对话模块的核心思路是:

使用 Conversations 组件,把预设能力入口和历史会话列表组合起来。

当前项目中,上半部分是预设能力:

Chat
AI Coding

下半部分是真实历史对话:

今天
  企业官网生成
  作品集网站

昨天
  商城页面改造

这样既保留了官方示例里“预设 item”的能力入口形式,也满足了实际 AI 工作台中“历史对话管理”的需求。