239 lines
5.9 KiB
Markdown
239 lines
5.9 KiB
Markdown
# Swipe 功能测试指南
|
||
|
||
## 测试场景
|
||
|
||
### 场景1:首次重roll(消息没有swipes数组)
|
||
|
||
**初始状态:**
|
||
```javascript
|
||
message = {
|
||
id: "ai_123456",
|
||
floor: 2,
|
||
mes: "这是AI的第一次回复",
|
||
is_user: false,
|
||
// 没有 swipes 字段
|
||
}
|
||
```
|
||
|
||
**执行重roll后:**
|
||
```javascript
|
||
message = {
|
||
id: "ai_123456",
|
||
floor: 2,
|
||
mes: "这是AI的第二次回复", // 显示新生成的内容
|
||
is_user: false,
|
||
swipes: [
|
||
"这是AI的第一次回复", // 旧版本
|
||
"这是AI的第二次回复" // 新版本
|
||
],
|
||
swipe_id: 1 // 自动切换到新版本
|
||
}
|
||
```
|
||
|
||
**前端显示:**
|
||
- 因为有 `swipes` 数组,所以显示 `swipes[1]` = "这是AI的第二次回复"
|
||
- 显示 swipe 控制按钮:◀ 2/2 ▶
|
||
|
||
---
|
||
|
||
### 场景2:第二次重roll(消息已有swipes数组)
|
||
|
||
**初始状态:**
|
||
```javascript
|
||
message = {
|
||
id: "ai_123456",
|
||
floor: 2,
|
||
mes: "这是AI的第二次回复",
|
||
is_user: false,
|
||
swipes: [
|
||
"这是AI的第一次回复",
|
||
"这是AI的第二次回复"
|
||
],
|
||
swipe_id: 1
|
||
}
|
||
```
|
||
|
||
**执行重roll后:**
|
||
```javascript
|
||
message = {
|
||
id: "ai_123456",
|
||
floor: 2,
|
||
mes: "这是AI的第三次回复", // 显示新生成的内容
|
||
is_user: false,
|
||
swipes: [
|
||
"这是AI的第一次回复",
|
||
"这是AI的第二次回复",
|
||
"这是AI的第三次回复" // 新版本
|
||
],
|
||
swipe_id: 2 // 自动切换到新版本
|
||
}
|
||
```
|
||
|
||
**前端显示:**
|
||
- 显示 `swipes[2]` = "这是AI的第三次回复"
|
||
- 显示 swipe 控制按钮:◀ 3/3 ▶
|
||
|
||
---
|
||
|
||
### 场景3:用户手动切换swipe
|
||
|
||
**初始状态:**
|
||
```javascript
|
||
message = {
|
||
id: "ai_123456",
|
||
floor: 2,
|
||
mes: "这是AI的第三次回复",
|
||
is_user: false,
|
||
swipes: [
|
||
"这是AI的第一次回复",
|
||
"这是AI的第二次回复",
|
||
"这是AI的第三次回复"
|
||
],
|
||
swipe_id: 2
|
||
}
|
||
|
||
// 用户点击左箭头
|
||
currentSwipeId = { 2: 1 } // 切换到第二个版本
|
||
```
|
||
|
||
**前端显示:**
|
||
- 因为 `currentSwipeId[2]` 存在,所以使用它而不是 `swipe_id`
|
||
- 显示 `swipes[1]` = "这是AI的第二次回复"
|
||
- 显示 swipe 控制按钮:◀ 2/3 ▶
|
||
|
||
---
|
||
|
||
## 关键逻辑说明
|
||
|
||
### 1. 后端逻辑(ChatBoxSlice.jsx)
|
||
|
||
#### chunk 事件(流式输出)
|
||
```javascript
|
||
if (isReroll) {
|
||
// ✅ 重roll模式:不更新 mes,只在内部累积 assistantMessage
|
||
// mes 保持不变,直到 complete 事件才更新
|
||
} else {
|
||
// 正常模式:更新新创建的消息
|
||
set((state) => ({
|
||
messages: state.messages.map((msg) =>
|
||
msg.id === newMessageId ? { ...msg, mes: assistantMessage } : msg
|
||
)
|
||
}));
|
||
}
|
||
```
|
||
|
||
#### complete 事件(生成完成)
|
||
```javascript
|
||
if (isReroll) {
|
||
const existingSwipes = msg.swipes || [];
|
||
const currentMes = msg.mes; // 当前显示的内容(旧版本)
|
||
|
||
let updatedSwipes = [...existingSwipes];
|
||
|
||
// 如果当前 mes 不在 swipes 中,先添加它
|
||
if (!updatedSwipes.includes(currentMes)) {
|
||
updatedSwipes.push(currentMes);
|
||
}
|
||
|
||
// 添加新生成的内容
|
||
updatedSwipes.push(assistantMessage);
|
||
|
||
return {
|
||
...msg,
|
||
mes: assistantMessage, // 显示新生成的内容
|
||
swipes: updatedSwipes, // 更新 swipes 数组
|
||
swipe_id: updatedSwipes.length - 1 // 自动切换到新版本
|
||
};
|
||
}
|
||
```
|
||
|
||
### 2. 前端逻辑(ChatBox.jsx)
|
||
|
||
```javascript
|
||
// 确定当前显示的消息内容
|
||
let currentMes = message.mes; // 默认使用 mes
|
||
let hasSwipes = message.swipes && message.swipes.length > 0;
|
||
let currentSwipeIndex = message.swipe_id;
|
||
|
||
if (hasSwipes) {
|
||
// 如果有swipes数组
|
||
if (currentSwipeId[message.floor] !== undefined) {
|
||
// 如果用户已经切换过版本,使用用户选择的版本
|
||
currentSwipeIndex = currentSwipeId[message.floor];
|
||
} else {
|
||
// 否则使用默认的swipe_id
|
||
currentSwipeIndex = message.swipe_id;
|
||
}
|
||
|
||
if (currentSwipeIndex >= 0 && currentSwipeIndex < message.swipes.length) {
|
||
currentMes = message.swipes[currentSwipeIndex]; // 从 swipes 中读取
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 测试步骤
|
||
|
||
### 1. 测试首次重roll
|
||
1. 发送一条消息,等待AI回复
|
||
2. 右键点击AI消息,选择"重roll"
|
||
3. 观察:
|
||
- ✅ 流式输出时,消息内容不变(不显示流式过程)
|
||
- ✅ 完成后,消息更新为新内容
|
||
- ✅ 出现 swipe 控制按钮:◀ 2/2 ▶
|
||
- ✅ 点击左箭头可以切换到旧版本
|
||
|
||
### 2. 测试多次重roll
|
||
1. 继续重roll几次
|
||
2. 观察:
|
||
- ✅ 每次重roll都在 swipes 数组中添加新版本
|
||
- ✅ swipe 计数器正确更新:2/3, 3/4, 4/5...
|
||
- ✅ 可以通过左右箭头切换所有版本
|
||
|
||
### 3. 测试手动切换
|
||
1. 重roll几次后,有多个版本
|
||
2. 点击左箭头切换到旧版本
|
||
3. 观察:
|
||
- ✅ 消息内容切换为旧版本
|
||
- ✅ swipe 计数器正确更新
|
||
- ✅ 再次重roll时,新版本添加到末尾
|
||
|
||
### 4. 测试键盘快捷键
|
||
1. 使用左右箭头键切换 swipe
|
||
2. 在最后一个版本时按右键触发重roll
|
||
3. 观察:
|
||
- ✅ 左右键正确切换版本
|
||
- ✅ 右键在最后一个版本时触发重roll
|
||
- ✅ 重roll后自动切换到新版本
|
||
|
||
---
|
||
|
||
## 常见问题排查
|
||
|
||
### Q1: 重roll后没有出现 swipe 按钮
|
||
**原因**:swipes 数组没有正确创建
|
||
**检查**:
|
||
- 查看控制台日志:`[ChatBoxStore] 📊 Swipes 更新:`
|
||
- 确认 `newCount` 大于 0
|
||
- 确认消息对象中有 `swipes` 字段
|
||
|
||
### Q2: 重roll后显示的是旧内容
|
||
**原因**:`mes` 字段没有更新
|
||
**检查**:
|
||
- 确认 complete 事件中更新了 `mes: assistantMessage`
|
||
- 确认 `assistantMessage` 有正确的内容
|
||
|
||
### Q3: 切换 swipe 后内容不变
|
||
**原因**:前端渲染逻辑有问题
|
||
**检查**:
|
||
- 确认 `currentMes` 正确从 `swipes[currentSwipeIndex]` 读取
|
||
- 确认 `currentSwipeIndex` 的值正确
|
||
- 确认 `currentSwipeId` 状态正确更新
|
||
|
||
### Q4: 重roll时看到流式输出覆盖了原内容
|
||
**原因**:chunk 事件中错误地更新了 `mes`
|
||
**检查**:
|
||
- 确认 chunk 事件中,重roll模式不更新 `mes`
|
||
- 应该只有正常模式才更新 `mes`
|