# 停止生成功能测试指南 ## 快速测试 ### 测试步骤 1. **启动开发服务器** ```bash cd web npm run dev ``` 2. **创建测试场景** - 打开浏览器访问应用 - 确保已连接至少一个模型服务 - 创建或选择一个对话 3. **测试停止按钮** **场景 1:正常停止** ``` 1. 输入一个较长的问题(例如:"请详细解释量子计算的原理,包括量子叠加、量子纠缠等概念") 2. 点击"确认"按钮发送 3. 等待 AI 开始回复(看到文字开始输出) 4. 立即点击"停止"按钮 5. 验证: - ✅ 输出立即停止 - ✅ 消息显示"已停止"的黄色标签 - ✅ 已生成的内容完整显示 - ✅ 可以看到操作按钮(复制、重新生成、删除) - ✅ 输入框恢复可用 ``` **场景 2:快速停止** ``` 1. 输入问题并发送 2. 在 AI 输出第一个字后立即点击停止 3. 验证:即使只输出了很少内容,也能正确停止 ``` **场景 3:继续对话** ``` 1. 停止一条消息后 2. 立即发送新消息 3. 验证:新消息能正常发送和接收 ``` **场景 4:重新生成** ``` 1. 停止一条消息 2. 点击该消息的"重新生成"按钮 3. 验证:能重新生成完整回复 ``` ### 检查点 #### UI 检查 - [ ] 按钮文字正确切换("确认" ↔ "停止") - [ ] 按钮颜色正确变化(primary ↔ error) - [ ] 停止的消息显示黄色"已停止"标签 - [ ] 停止的消息能显示操作按钮 - [ ] 输入框在发送时禁用,停止后恢复 #### 功能检查 - [ ] 点击停止后流式输出立即中断 - [ ] 已生成的内容被保留 - [ ] 可以复制停止的消息内容 - [ ] 可以重新生成停止的消息 - [ ] 可以删除停止的消息 - [ ] 停止后可以继续发送新消息 #### 控制台日志检查 打开浏览器控制台,点击停止时应该看到: ``` 🛑 [handleStopGeneration] 用户请求停止生成 🛑 [makeChatRequestStream] 检测到中止信号,停止读取流 ⚠️ [makeChatRequestStream] 请求被中止: 用户中止操作 ⏸️ [sendMessageStream] 用户主动停止生成,保留已生成内容 ``` ### 常见问题排查 #### 问题 1:点击停止按钮没反应 **原因**:按钮事件未正确绑定 **检查**: - 查看控制台是否有 JS 错误 - 确认 `handleButtonClick` 函数存在 - 确认 `store.state.isSending` 状态正确 #### 问题 2:输出没有停止 **原因**:中止信号未正确传递或检查 **检查**: - 确认 `state.abortController` 已创建 - 确认 signal 正确传递到 API 调用 - 确认流式读取循环中检查了 `signal.aborted` #### 问题 3:停止后显示错误 **原因**:未正确处理 AbortError **检查**: - 查看 `chatService.ts` 中的 catch 块 - 确认区分了 `AbortError` 和其他错误 - 确认 paused 状态设置正确 #### 问题 4:停止后无法发送新消息 **原因**:`isSending` 状态未重置 **检查**: - 确认 finally 块执行 - 确认 `state.isSending = false` - 确认 `abortController` 被清空 ### 调试模式 如需详细调试,在控制台运行: ```javascript // 查看当前状态 console.log('isSending:', store.state.isSending) console.log('abortController:', store.state.abortController) console.log('currentTopicId:', store.state.currentTopicId) console.log('messages:', store.state.messages) // 监听状态变化 watch(() => store.state.isSending, (val) => { console.log('isSending changed:', val) }) ``` ### 性能验证 测量停止响应时间: ```javascript // 在点击停止前 const stopTime = performance.now() // 点击停止 // 在停止完成后(看控制台日志) const endTime = performance.now() console.log('停止响应时间:', endTime - stopTime, 'ms') // 预期:< 100ms ``` ## 自动化测试(可选) 如果要编写自动化测试: ```typescript describe('Stop Generation', () => { it('should stop streaming when stop button clicked', async () => { // 模拟发送消息 const promise = store.sendMessageStream('test message') // 等待开始发送 await nextTick() expect(store.state.isSending).toBe(true) // 停止生成 store.stopGeneration() // 验证状态 expect(store.state.isSending).toBe(false) expect(store.state.abortController).toBe(null) }) it('should mark message as paused', async () => { // 发送并停止 const promise = store.sendMessageStream('test') await nextTick() store.stopGeneration() await promise.catch(() => {}) // 忽略中止错误 // 检查最后一条消息 const lastMessage = store.state.messages[store.state.messages.length - 1] expect(lastMessage.status).toBe('paused') }) }) ``` ## 成功标准 ✅ **所有以下条件都满足才算修复成功**: 1. 点击停止按钮有明显反应(按钮状态变化) 2. 流式输出在 100ms 内完全停止 3. 停止的消息显示"已停止"标签而非"发送失败" 4. 已生成的内容完整保留 5. 停止后立即可以发送新消息 6. 可以对停止的消息进行各种操作 7. 控制台无错误日志(AbortError 除外) 8. 连续多次停止-发送循环不会出现问题 ## 回归测试 确保修复不影响其他功能: - [ ] 正常发送消息仍然工作 - [ ] 消息历史正确保存 - [ ] 话题切换正常 - [ ] MCP 工具调用正常 - [ ] 多模型切换正常