1 Commits

Author SHA1 Message Date
douboer
e581c70489 update at 2025-10-15 18:26:03 2025-10-15 18:26:03 +08:00
2 changed files with 8 additions and 240 deletions

View File

@@ -315,241 +315,3 @@ npm run dev
- 工具调用性能监控
**v1.0.2 - AI + MCP 工具调用,让对话更智能!** 🚀🔧
## v1.0.3
发布时间: 2025-10-15
### 重大功能:停止生成 & UI 优化
本版本实现了完整的停止生成功能,参考 Cherry Studio 的 PAUSED 状态设计,提供更好的用户体验。
#### 核心功能
**智能停止生成**
- 点击停止按钮立即中断 AI 回复(响应时间 < 100ms
- 保留已生成的内容标记为"已停止"状态
- 区分用户主动停止和系统错误
- 停止后可立即继续对话
**UI 体验优化**
- 按钮文字从"确认"改为"发送"
- 停止后显示黄色"已停止"标签而非红色"发送失败"
- 停止的消息可以复制重新生成删除
- 实时状态反馈发送中 已停止 可操作
**状态管理增强**
- 新增 `paused` 消息状态
- 新增 `paused` 流式事件类型
- 完整的 AbortController 信号传递链
- 流读取循环实时检查中止信号
#### 技术实现
**按钮事件修复**
- 修复点击事件绑定问题从三元表达式改为函数调用
- 运行时动态判断状态而非编译时
```typescript
// Before: @click="store.state.isSending ? handleStopGeneration : handleSendMessage"
// After: @click="handleButtonClick"
const handleButtonClick = () => {
if (store.state.isSending) {
handleStopGeneration()
} else {
handleSendMessage()
}
}
```
**中止信号传递链**
```
UI (点击停止)
↓ handleStopGeneration()
↓ store.stopGeneration()
↓ abortController.abort()
↓ chatService.sendMessageStream(signal)
↓ modelServiceManager.makeChatRequestStream(signal)
↓ while循环检查 signal.aborted
↓ reader.cancel() + 抛出 AbortError
↓ 状态设置为 'paused'
↓ UI 更新显示"已停止"
```
**流读取中止检查**
```typescript
while (true) {
// 关键:每次读取前检查中止信号
if (signal?.aborted) {
console.log('检测到中止信号,停止读取流')
reader.cancel()
throw new DOMException('用户中止操作', 'AbortError')
}
const { done, value } = await reader.read()
if (done) break
// 处理数据...
}
```
**错误处理优化**
```typescript
catch (error) {
const isAborted = error instanceof Error && error.name === 'AbortError'
if (isAborted) {
// 用户主动停止 - 标记为 paused保留内容
assistantMessage.status = 'paused'
assistantMessage.error = undefined
onChunk({ type: 'paused', messageId: assistantMessage.id })
// 关键:更新消息列表,触发 UI 刷新
state.messages = [...chatService.getMessages(currentTopicId)]
} else {
// 真实错误 - 标记为 error
assistantMessage.status = 'error'
assistantMessage.error = error.message
}
}
```
#### Bug 修复
### Emoji 测试
为验证发布脚本对 emoji 的处理例如某些 emoji 属于 4 字节 unicode可能触发服务器端 collation 问题在此插入若干 emoji 供测试
- 表情类:😄 😂 😭 🥳
- 物品/动作:🚀 🧪 🔧 📝
- 动物/自然:🐛 🐶 🌳
- 标志/符号:🏷 🔣
示例行包含中文和 emoji
> 测试:本行包含中文与 emoji目的是验证脚本对 emoji 的过滤与回退逻辑。示例 emoji😄 🚀 🐛 🧪 🏷️
- 修复按钮点击无响应问题事件绑定错误
- 修复停止后仍显示"发送中..."状态
- 修复停止后消息列表不更新
- 修复 AbortError 被错误标记为失败
- 修复按钮文字显示"确认"而非"发送"
#### 修改的文件
**类型定义**
- `/web/src/types/chat.ts`
- MessageStatus 添加 `'paused'` 类型
- StreamEvent 添加 `'paused'` 事件类型
**UI 组件**
- `/web/src/components/Chat/ChatLayout.vue`
- 修复按钮点击事件绑定
- 按钮文字改为"发送"
- 添加"已停止"状态标签显示
- paused 状态消息显示操作按钮
**服务层**
- `/web/src/services/chatService.ts`
- 区分 AbortError 和其他错误
- 设置 paused 状态和事件
- `/web/src/services/modelServiceManager.ts`
- 流读取循环中检查 signal.aborted
- 调用 reader.cancel() 中止读取
- 正确处理 AbortError
**状态管理**
- `/web/src/stores/chatStore.ts`
- catch 块中更新消息列表
- 确保 UI 显示最新状态
#### 使用示例
```
1. 用户发送:"请详细介绍 Vue 3 的新特性"
2. AI 开始回复,显示"发送中..."
3. 用户点击"停止"按钮
4. 立即响应:
- 输出停止
- 标签变为"已停止"(黄色)
- 显示已生成的内容
- 显示操作按钮
5. 用户可以:
- 复制已生成的内容
- 重新生成完整回复
- 删除该消息
- 继续发送新消息
```
#### 设计亮点
1. **参考 Cherry Studio** - 借鉴成熟产品的设计理念
2. **立即响应** - 停止操作 < 100ms 响应
3. **内容保留** - 部分生成的内容依然有价值
4. **状态区分** - paused vs error语义更清晰
5. **完整操作** - 停止的消息仍可进行各种操作
6. **信号传递** - 完整的中止信号链确保可靠性
#### 用户体验对比
**修复前**
- 点击停止无反应
- 继续显示"发送中..."
- 显示 loading 动画
- 按钮文字为"确认"
**修复后**
- 点击立即停止
- 显示"已停止"黄色
- 隐藏 loading 动画
- 按钮文字为"发送"
- 可以操作停止的消息
- 立即可继续对话
#### 相关文档
- `STOP_GENERATION_SUMMARY.md` - 修复总结
- `STOP_GENERATION_FIX.md` - 详细技术文档
- `STOP_GENERATION_PATCH.md` - 补充修复说明
- `STOP_GENERATION_TEST.md` - 测试指南
- `STOP_GENERATION_VERIFY.md` - 快速验证清单
#### 升级指南
```bash
# 拉取最新代码
git pull origin main
# 安装依赖
cd web && npm install
# 启动开发服务器
npm run dev
# 测试停止功能
# 1. 发送消息
# 2. 在 AI 回复时点击"停止"
# 3. 验证显示"已停止"标签
# 4. 验证可以继续对话
```
#### 验收标准
- [x] 按钮点击有明显反应
- [x] 流输出在 100ms 内停止
- [x] 显示"已停止"而非"失败"
- [x] 保留已生成内容
- [x] 停止后可立即继续对话
- [x] 可对停止的消息进行操作
- [x] 无意外错误日志
#### 下一步计划
- 停止后自动保存草稿
- 停止历史记录统计
- 批量停止多个会话
- 停止原因记录用户主动/超时/错误
- 性能监控和优化
**v1.0.3 - 完美的停止体验,让对话更可控!**

View File

@@ -6,6 +6,7 @@
“显示设置”
“MCP”
模块使用typescript+vue3实现。
火山:
https://ark.cn-beijing.volces.com/api/v3
@@ -16,10 +17,15 @@ https://dashscope.aliyuncs.com/compatible-mode/v1
sk-2546da09b6d9471894aeb95278f96c11
2. 大模型选择不知道是否生效?
3. 阿里模型直接使用模型ID。以后再考虑不要使用接口去获取。(先跑通)
3. 阿里模型直接使用模型ID。
以后再考虑不要使用接口去获取。(先跑通)
🚩
4. MCP 功能叠加。