# 聊天模块 V2.1 优化更新
## 📅 更新日期
2025年10月14日
## 🎯 本次优化内容
### 1. ✅ 右侧对话列表可折叠
**功能描述**:右侧的对话列表现在支持折叠/展开,节省屏幕空间。
**实现细节**:
- 在对话头部添加折叠按钮
- 按钮图标根据状态变化(ChevronLeft / ChevronRight)
- 按钮文字显示"显示列表" / "隐藏列表"
- 使用 CSS transition 实现平滑动画
**代码实现**:
```vue
{{ showSidebar ? '隐藏列表' : '显示列表' }}
```
**使用方法**:
- 点击对话头部右上角的折叠按钮
- 对话列表会平滑地隐藏/显示
- 响应式设计:小屏幕时自动变为浮动面板
---
### 2. ✅ AI 模型选择列表动态加载
**功能描述**:模型选择器现在会动态读取"模型服务"中已配置的所有可用模型。
**实现细节**:
```typescript
// 从 modelStore 动态读取模型列表
const modelOptions = computed(() => {
const services = modelStore.providers
const options: any[] = []
services.forEach((service: any) => {
if (service.enabled && service.models) {
service.models.forEach((model: any) => {
options.push({
label: `${service.name} | ${model.name}`,
key: `${service.id}:${model.id}`,
icon: () => h(NIcon, { component: BrainIcon })
})
})
}
})
return options
})
// 显示选中的模型名称
const selectedModelName = computed(() => {
if (!selectedModel.value) return undefined
const [serviceId, modelId] = selectedModel.value.split(':')
const service = modelStore.providers.find((s: any) => s.id === serviceId)
const model = service?.models?.find((m: any) => m.id === modelId)
return model ? `${service?.name} | ${model.name}` : undefined
})
```
**工作流程**:
1. 用户在"模型服务"页面添加服务(如火山引擎、OpenAI)
2. 服务连接成功后,其模型会自动出现在聊天页面的模型选择器中
3. 选择模型后,该模型会被用于当前对话
4. 模型信息格式:`服务名 | 模型名`(如"火山引擎 | doubao-1.5-pro-32k")
**特性**:
- ✅ 实时同步:添加新服务后立即可用
- ✅ 多服务支持:同时显示所有服务的模型
- ✅ 清晰标识:服务名和模型名分开显示
- ✅ 图标辅助:每个选项都有模型图标
---
### 3. ✅ MCP 服务支持(基础架构)
**功能描述**:聊天对话中现在支持选择和使用 MCP 服务器。
**实现细节**:
#### 3.1 MCP 服务器列表动态加载
```typescript
// 从 mcpStore 读取已连接的服务器
const mcpOptions = computed(() => {
const options: any[] = [
{
label: '不启用 MCP 服务',
key: 'none'
}
]
// 添加已连接的服务器
mcpStore.connectedServers.forEach((server) => {
const toolCount = server.capabilities?.tools?.length || 0
options.push({
label: `${server.name} (${toolCount} 个工具)`,
key: server.id,
icon: () => h(NIcon, { component: PlugIcon })
})
})
return options
})
// 显示选中的 MCP 服务器名称
const selectedMCPName = computed(() => {
if (!selectedMCP.value || selectedMCP.value === 'none') return '不启用 MCP 服务'
const server = mcpStore.servers.find(s => s.id === selectedMCP.value)
return server?.name || '未知服务'
})
```
#### 3.2 MCP 服务器传递到聊天服务
```typescript
// ChatLayout.vue - 发送消息时传递 MCP 服务器 ID
const handleSendMessage = async () => {
const mcpId = selectedMCP.value === 'none' ? undefined : selectedMCP.value
await store.sendMessageStream(
content,
selectedModel.value,
mcpId, // 传递 MCP 服务器 ID
() => { scrollToBottom() }
)
}
// chatStore.ts - 转发到 chatService
const sendMessageStream = async (
content: string,
model?: string,
mcpServerId?: string, // 新增参数
onChunk?: (chunk: string) => void
) => {
await chatService.sendMessageStream(
{ topicId, content, model, stream: true },
onChunk,
mcpServerId // 传递给 service
)
}
// chatService.ts - 接收并准备使用
async sendMessageStream(
options: SendMessageOptions,
onChunk: (event: StreamEvent) => void,
mcpServerId?: string // 接收 MCP 服务器 ID
): Promise {
// TODO: 在这里实现 MCP 工具调用逻辑
await this.callModelStream(conversation, model, onChunk, mcpServerId)
}
```
#### 3.3 自动加载和重连
```typescript
// 初始化时加载 MCP 服务器
onMounted(async () => {
store.initialize()
scrollToBottom()
// 加载 MCP 服务器配置
mcpStore.loadServers()
// 尝试自动重连之前已连接的服务器
try {
await mcpStore.autoReconnect()
} catch (error) {
console.warn('自动重连 MCP 服务器失败:', error)
}
})
```
**工作流程**:
1. 用户在"MCP 设置"页面添加并连接服务器
2. 服务器连接成功后,自动出现在聊天页面的 MCP 选择器中
3. 选择服务器后,该服务器 ID 会被传递到聊天服务
4. 聊天服务可以使用该服务器的工具(待实现)
**当前状态**:
- ✅ 基础架构完成:MCP 服务器 ID 可以从 UI 传递到服务层
- ✅ 服务器列表动态加载:实时显示已连接的服务器和工具数量
- ✅ 自动重连:页面刷新后自动重连之前的服务器
- ⏳ 工具调用逻辑:已预留接口,等待实现
**下一步实现**:
```typescript
// 在 callModelStream 中检测 AI 的工具调用请求
private async callModelStream(
conversation: Conversation,
model: string | undefined,
onChunk: (chunk: string) => void,
mcpServerId?: string
): Promise {
if (mcpServerId) {
// 1. 获取 MCP 服务器的可用工具列表
const server = mcpStore.servers.find(s => s.id === mcpServerId)
const tools = server?.capabilities?.tools || []
// 2. 将工具列表传递给 AI 模型
// 让 AI 知道可以调用哪些工具
// 3. 如果 AI 返回工具调用请求,执行工具
// const toolResult = await mcpStore.callTool(mcpServerId, toolName, params)
// 4. 将工具结果返回给 AI,让它生成最终回复
}
// 正常的流式响应
// ...
}
```
---
## 📊 完整功能清单
### 已完成功能
1. ✅ 左侧导航可折叠(V2.0)
2. ✅ 右侧对话列表(V2.0)
3. ✅ **右侧对话列表可折叠(V2.1 新增)**
4. ✅ 工具栏 - MCP 服务选择
5. ✅ **工具栏 - 模型动态加载(V2.1 优化)**
6. ✅ **MCP 服务集成基础架构(V2.1 新增)**
7. ✅ 快捷操作按钮
8. ✅ 消息实时更新
9. ✅ 消息条数正确显示
### 待实现功能
1. ⏳ MCP 工具调用实际逻辑
2. ⏳ Markdown 渲染
3. ⏳ 代码语法高亮
4. ⏳ 真正的流式响应(SSE)
5. ⏳ 图片和文件消息
---
## 🎬 使用示例
### 场景1:使用特定模型对话
1. **添加模型服务**
```
侧边栏 → 模型服务 → 添加服务
例如:添加"火山引擎"服务
```
2. **在聊天中选择模型**
```
聊天页面 → 工具栏 → 点击"选择模型▼"
选择:火山引擎 | doubao-1.5-pro-32k-character
```
3. **发送消息**
```
输入框 → 输入"你好" → Enter
AI 使用选中的模型回复
```
### 场景2:使用 MCP 服务器扩展能力
1. **添加 MCP 服务器**
```
侧边栏 → MCP 设置 → 添加服务器
例如:添加"xhs-sse"服务器
URL: http://localhost:3200
```
2. **连接服务器**
```
点击"连接"按钮
等待连接成功,显示可用工具数量
```
3. **在聊天中选择 MCP**
```
聊天页面 → 工具栏 → 点击"不启用 MCP 服务▼"
选择:xhs-sse (5 个工具)
```
4. **发送消息(准备使用工具)**
```
输入框 → 输入"搜索最新的 Vue 3 教程"
AI 可以调用 MCP 工具进行搜索(功能待实现)
```
### 场景3:折叠对话列表获得更大空间
1. **隐藏对话列表**
```
点击右上角"隐藏列表"按钮
对话列表平滑隐藏
主对话区域扩大
```
2. **再次显示**
```
点击"显示列表"按钮
对话列表平滑显示
```
---
## 🔧 技术细节
### 数据流:模型选择
```
用户添加服务
↓
ModelService 连接
↓
modelStore.providers 更新
↓
modelOptions 计算属性更新
↓
下拉列表自动刷新
↓
用户选择模型
↓
selectedModel = "serviceId:modelId"
↓
发送消息时使用该模型
↓
modelServiceManager.sendChatRequest(serviceId, messages, modelId)
```
### 数据流:MCP 集成
```
用户添加 MCP 服务器
↓
MCPClientService 连接
↓
mcpStore.servers 更新
↓
mcpOptions 计算属性更新
↓
下拉列表自动刷新
↓
用户选择 MCP 服务器
↓
selectedMCP = serverId
↓
发送消息时传递 serverId
↓
chatService.sendMessageStream(..., mcpServerId)
↓
callModelStream(..., mcpServerId)
↓
[待实现] mcpStore.callTool(mcpServerId, toolName, params)
```
### 关键组件关系
```
ChatLayout.vue
├─ uses chatStore (聊天状态管理)
├─ uses modelStore (模型列表)
├─ uses mcpStore (MCP 服务器列表)
└─ calls sendMessageStream(content, model, mcpServerId)
chatStore.ts
└─ calls chatService.sendMessageStream(options, onChunk, mcpServerId)
chatService.ts
└─ calls callModelStream(conversation, model, onChunk, mcpServerId)
└─ [TODO] 实现 MCP 工具调用逻辑
```
---
## 📝 配置示例
### 模型服务配置示例
```json
{
"id": "volcengine-001",
"name": "火山引擎",
"type": "volcengine",
"url": "https://ark.cn-beijing.volces.com/api/v3",
"apiKey": "your-api-key",
"enabled": true,
"models": [
{
"id": "doubao-1.5-pro-32k",
"name": "豆包-1.5-pro-32k",
"type": "chat"
},
{
"id": "doubao-1.5-pro-32k-character",
"name": "豆包-1.5-pro-32k-角色扮演",
"type": "chat"
}
]
}
```
### MCP 服务器配置示例
```json
{
"id": "mcp-xhs-001",
"name": "xhs-sse",
"url": "http://localhost:3200",
"transport": "sse",
"status": "connected",
"capabilities": {
"tools": [
{
"name": "search",
"description": "搜索互联网内容"
},
{
"name": "read_file",
"description": "读取本地文件"
}
]
}
}
```
---
## 🎯 下一步开发计划
### 优先级1:MCP 工具调用实现
```typescript
// 实现 AI 工具调用流程
1. 将 MCP 工具列表格式化为 OpenAI Function Calling 格式
2. 在调用模型时传递工具定义
3. 解析 AI 返回的工具调用请求
4. 执行 MCP 工具
5. 将结果返回给 AI
6. 显示完整的对话过程
```
### 优先级2:模型切换优化
```typescript
// 记住每个对话的模型选择
1. 在 Topic 中保存 modelId
2. 切换对话时自动选择对应模型
3. 支持为不同对话设置默认模型
```
### 优先级3:UI 优化
```typescript
// 更好的用户体验
1. 工具调用进度显示
2. MCP 工具调用结果可视化
3. 模型和 MCP 状态指示器
4. 更多的快捷键支持
```
---
## ⚠️ 注意事项
### MCP 服务器要求
1. **必须先配置**:在"MCP 设置"中添加并连接服务器
2. **连接状态**:只有已连接的服务器才会出现在选择器中
3. **自动重连**:页面刷新后会自动尝试重连
4. **工具数量**:选择器显示每个服务器的工具数量
### 模型服务要求
1. **必须先配置**:在"模型服务"中添加服务
2. **启用状态**:只有启用的服务的模型才会出现
3. **连接状态**:建议先测试连接再使用
4. **API Key**:确保 API Key 有效且有足够配额
### 性能建议
1. **服务器数量**:建议不超过 5 个 MCP 服务器同时连接
2. **模型选择**:根据对话复杂度选择合适的模型
3. **工具调用**:复杂工具可能需要更长时间
---
## 📖 更新记录
### V2.1(2025/10/14)
- ✅ 右侧对话列表支持折叠
- ✅ 模型选择器动态加载已配置的模型
- ✅ MCP 服务集成基础架构完成
- ✅ 自动重连 MCP 服务器
- ✅ 完善的数据流和状态管理
### V2.0(2025/10/14)
- ✅ 左侧导航可折叠
- ✅ 右侧对话列表布局
- ✅ 完整工具栏
- ✅ 消息实时更新
- ✅ 消息条数修复
---
**优化完成!** 🎉
现在您可以:
1. ✅ 折叠对话列表获得更大空间
2. ✅ 使用已配置的任意模型对话
3. ✅ 选择 MCP 服务器(基础架构就绪)
继续完善 MCP 工具调用功能,敬请期待 V2.2!