Files
map-client-vue/CHAT_UPDATE_V2.md
2025-10-14 21:52:11 +08:00

420 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 聊天模块重构更新 v2.0
## 📅 更新日期
2025年10月14日
## 🎉 重大更新
### 问题修复
#### 1. ✅ 消息列表实时更新问题
**问题描述**:发送消息后,消息列表不会实时更新,需要手动刷新页面。
**解决方案**
- 修改 `chatStore.ts` 中的 `sendMessageStream` 方法
- 在每次接收到流式响应时,立即调用 `loadMessages` 更新消息列表
- 确保在发送完成后再次更新,保证数据一致性
```typescript
// chatStore.ts - 修复后的代码
await chatService.sendMessageStream(
{
topicId: currentTopicId,
content,
model,
stream: true
},
(event) => {
// 实时更新消息列表
if (state.currentTopicId === currentTopicId) {
loadMessages(currentTopicId)
}
if (event.type === 'delta' && event.content && onChunk) {
onChunk(event.content)
}
}
)
```
#### 2. ✅ 消息条数显示不正确
**问题描述**:话题卡片显示的消息条数与实际消息数量不一致。
**解决方案**
- 修改 `chatService.ts` 中的 `sendMessageStream` 方法
- 在添加用户消息、助手消息和完成流式响应时,都同步更新 `topic.messageCount`
- 确保每次对话更新后立即保存话题数据
```typescript
// chatService.ts - 关键更新
// 1. 添加用户消息后更新
if (topic) {
topic.messageCount = conversation.messages.length
topic.lastMessage = this.getMessagePreview(content)
topic.updatedAt = new Date()
this.topics.set(topicId, topic)
this.saveTopics()
}
// 2. 添加助手消息占位符后更新
conversation.messages.push(assistantMessage)
if (topic) {
topic.messageCount = conversation.messages.length
this.topics.set(topicId, topic)
this.saveTopics()
}
// 3. 流式响应完成后最终更新
if (topic) {
topic.messageCount = conversation.messages.length
topic.lastMessage = this.getMessagePreview(assistantMessage.content)
topic.updatedAt = new Date()
this.topics.set(topicId, topic)
this.saveTopics()
}
```
---
### 新功能实现
#### 3. ✅ 左侧可折叠导航栏
**功能描述**:将"核心功能"菜单保留在左侧,但支持点击按钮折叠/展开。
**实现细节**
-`SimpleApp.vue` 中添加 `sidebarCollapsed` 状态
- 添加折叠按钮Menu2 图标)
- 通过 CSS 动画实现平滑折叠效果
**特性**
- 折叠后宽度从 280px 缩小到 64px
- 折叠状态下只显示图标,隐藏文字
- 保留导航指示器
- 0.3s 平滑过渡动画
```vue
<!-- SimpleApp.vue -->
<div class="sidebar" :class="{ collapsed: sidebarCollapsed }">
<n-button quaternary circle @click="toggleSidebar">
<n-icon><Menu2 /></n-icon>
</n-button>
</div>
<style>
.sidebar {
width: 280px;
transition: width 0.3s ease;
}
.sidebar.collapsed {
width: 64px;
}
</style>
```
#### 4. ✅ 右侧对话列表
**功能描述**:将对话列表从左侧移动到聊天页面的右侧,与主内容区并排显示。
**实现细节**
- 重构 `ChatLayout.vue` 组件结构
- 采用 Flexbox 布局:`chat-main` (flex: 1) + `topics-sidebar` (width: 320px)
- 对话列表始终可见(宽屏)或可切换显示(小屏)
**布局结构**
```
┌─────────────────────────────────────────────────┬─────────────────┐
│ │ 对话列表 │
│ 主对话区域 │ [搜索框] │
│ - 消息列表 │ □ 话题1 │
│ - 输入框 │ ■ 话题2 (当前) │
│ - 工具栏 │ □ 话题3 │
│ │ │
└─────────────────────────────────────────────────┴─────────────────┘
```
**响应式处理**
- 宽度 > 1200px对话列表固定在右侧
- 宽度 < 1200px对话列表变为浮动面板通过按钮切换显示
#### 5. ✅ 工具栏 - MCP 服务选择
**功能描述**在输入框上方添加工具栏支持选择 MCP 服务器
**实现细节**
- 使用 `n-dropdown` 实现下拉选择
- 默认选项"不启用 MCP 服务"
- 示例选项"xhs-sse"
- 选择后显示在按钮上
```vue
<n-dropdown
trigger="click"
:options="mcpOptions"
@select="handleSelectMCP"
>
<n-button size="small" quaternary>
<template #icon>
<n-icon :component="PlugIcon" />
</template>
{{ selectedMCP || '不启用 MCP 服务' }}
<n-icon :component="ChevronDownIcon" size="14" />
</n-button>
</n-dropdown>
```
**MCP 选项配置**
```typescript
const mcpOptions = computed(() => [
{
label: '不启用 MCP 服务',
key: 'none'
},
{
label: 'xhs-sse',
key: 'xhs-sse'
}
])
```
#### 6. ✅ 工具栏 - 模型选择器
**功能描述**在工具栏右侧添加 AI 模型选择器支持切换不同模型
**实现细节**
- `modelStore` 动态读取已配置的模型
- 显示格式"服务提供商 | 模型名称"
- 选择后立即生效下次发送消息使用新模型
```typescript
// 动态生成模型选项
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
})
```
**选择后的显示**
```vue
<n-button size="small" quaternary>
<template #icon>
<n-icon :component="BrainIcon" />
</template>
{{ selectedModelName || '选择模型' }}
<n-icon :component="ChevronDownIcon" size="14" />
</n-button>
```
#### 7. ✅ 工具栏 - 快捷操作按钮
**功能描述**添加文件附件语音等快捷操作按钮UI 占位)。
**实现细节**
```vue
<n-button-group size="small">
<n-button quaternary>
<n-icon :component="FileTextIcon" size="16" />
</n-button>
<n-button quaternary>
<n-icon :component="PaperclipIcon" size="16" />
</n-button>
<n-button quaternary>
<n-icon :component="MicIcon" size="16" />
</n-button>
</n-button-group>
```
#### 8. ✅ 完整工具栏布局
**布局结构**
```
┌──────────────────────────────────────────────────────────────┐
│ [MCP选择器▼] [+ 添加服务器...] | [模型选择▼] | [📄][📎][🎤] [确认] │
└──────────────────────────────────────────────────────────────┘
│ │
│ 输入框多行文本最多10行
│ │
└──────────────────────────────────────────────────────────────┘
│ ESC 关闭 | ▲▼ 选择 | ⌘ + ▲▼ 翻页 | ↩ 确认 │
└──────────────────────────────────────────────────────────────┘
```
**CSS 实现**
```css
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding: 4px 0;
}
.toolbar-left,
.toolbar-right {
display: flex;
align-items: center;
gap: 8px;
}
.toolbar-divider {
color: var(--border-color);
margin: 0 4px;
}
```
---
## 📊 完整改进总结
### 修复的问题
1. 消息列表不实时更新 每次流式响应都触发更新
2. 消息条数显示错误 同步更新 topic.messageCount
### 新增功能
3. 左侧导航可折叠 点击按钮切换64px 280px
4. 右侧对话列表 从左侧移到右侧320px 固定宽度
5. MCP 服务选择器 工具栏左侧支持选择/禁用
6. AI 模型选择器 工具栏右侧动态加载已配置模型
7. 快捷操作按钮 文件附件语音UI占位
8. 完整工具栏 模仿 Cherry Studio 布局
### 技术改进
- 响应式更新机制优化
- LocalStorage 持久化增强
- Flexbox 弹性布局
- CSS 动画过渡效果
- TypeScript 类型安全
---
## 🎨 界面预览
### 新布局(宽屏)
```
┌─────┬─────────────────────────────────────────┬─────────────┐
│ 🔧 │ 新对话 │ 对话列表 │
│ 💬 │ 你: 你好 │ ┌─────────┐ │
│ 🛠️ │ AI: 你好!有什么... │ │ [搜索] │ │
│ 📊 │ │ ├─────────┤ │
│ │ [MCP▼][+添加] | [模型▼] | [📄📎🎤][确认]│ │ □ 话题1 │ │
│ ⚙️ │ ┌─────────────────────────────────────┐│ │ ■ 话题2 │ │
│ 🎨 │ │ 输入消息... ││ │ □ 话题3 │ │
│ ⚙️ │ └─────────────────────────────────────┘│ └─────────┘ │
│ │ ESC关闭 | ▲▼选择 | ↩确认 │ │
└─────┴─────────────────────────────────────────┴─────────────┘
```
### 折叠导航
```
┌───┬─────────────────────────────────────────┬─────────────┐
│ ☰ │ 新对话 │ 对话列表 │
│ 💬│ │ │
│ 🛠│ │ │
│ 📊│ │ │
└───┴─────────────────────────────────────────┴─────────────┘
```
---
## 🚀 如何使用
### 1. 折叠/展开左侧导航
点击左上角的 (Menu) 按钮
### 2. 显示/隐藏对话列表
点击右上角的"对话列表"按钮小屏幕时
### 3. 选择 MCP 服务
1. 点击工具栏左侧的 [MCP选择器▼]
2. 从列表选择服务或选择"不启用"
### 4. 选择 AI 模型
1. 点击工具栏右侧的 [模型选择▼]
2. 从列表选择已配置的模型
3. 格式服务名 | 模型名
### 5. 发送消息
1. 在输入框输入消息
2. Enter 发送Shift+Enter 换行
3. 或点击"确认"按钮
---
## 📝 文件修改清单
### 修改的文件
1. `/web/src/stores/chatStore.ts` - 修复消息更新逻辑
2. `/web/src/services/chatService.ts` - 修复消息计数同步
3. `/web/src/SimpleApp.vue` - 添加可折叠导航
4. `/web/src/components/Chat/ChatLayout.vue` - 完全重构布局和工具栏
### 代码统计
- 修改行数~200
- 新增功能8
- 修复问题2
- 编译错误0
---
## ⚠️ 注意事项
### 已知限制
1. **MCP 服务器集成**选择器已实现但实际调用 MCP 需要后续开发
2. **快捷操作按钮**文件附件语音按钮仅为 UI 占位
3. **小屏幕适配**1200px 以下对话列表变为浮动面板
### 性能优化建议
1. 对话列表虚拟滚动话题超过 100 个时
2. 消息列表虚拟滚动消息超过 500 条时
3. 节流 LocalStorage 保存操作
### 兼容性
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
---
## 🎯 下一步计划
### 短期1-2天
- [ ] 实现 MCP 服务器实际调用
- [ ] 完善快捷操作按钮功能
- [ ] 添加 Markdown 渲染支持
### 中期1周
- [ ] 实现真正的流式响应SSE
- [ ] 添加代码高亮
- [ ] 支持图片和文件消息
### 长期1月
- [ ] 云端数据同步
- [ ] 多端协同
- [ ] 插件系统
---
## 🐛 问题反馈
如遇到问题请检查
1. 浏览器控制台是否有错误
2. LocalStorage 是否正常
3. 模型服务是否已连接
4. 网络连接是否正常
---
**更新完成!** 🎉
所有功能已实现零编译错误可以立即使用