左侧历史对话模块:使用 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 维护。
当前左侧包含什么
当前左侧主要包含四块:
新建应用按钮
搜索框
能力入口
历史对话
页面结构大概是:
其中:
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 工作台中“历史对话管理”的需求。