正则相关

This commit is contained in:
2026-05-06 00:40:18 +08:00
parent f843a74715
commit 9faccc2c03
32 changed files with 4814 additions and 346 deletions

238
SWIPE_TEST_GUIDE.md Normal file
View File

@@ -0,0 +1,238 @@
# 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`