docs:ClarificationCard 选项切换修复设计
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
---
|
||||
author: AI Assistant
|
||||
created_at: 2026-07-22
|
||||
purpose: 修复 ClarificationCard 选项无法切换的 bug
|
||||
---
|
||||
|
||||
# ClarificationCard 选项切换修复设计
|
||||
|
||||
## 问题概述
|
||||
|
||||
### 现象
|
||||
|
||||
在"心愿实现"页面(生成剧本页面),当后端返回澄清卡片(`clarification_card` 事件)时,用户在选项卡中选择了一个选项后,无法切换到其他选项。
|
||||
|
||||
### 根本原因
|
||||
|
||||
`ClarificationCard.vue` 组件的 `toggleOption` 函数(第 80-95 行)依赖 `card_type` 字段判断是单选还是多选:
|
||||
|
||||
```javascript
|
||||
function toggleOption(opt) {
|
||||
const value = opt.value
|
||||
if (isSingle.value) { // 仅当 card_type === 'single_select' 时执行
|
||||
selectedValues.value = [value]
|
||||
} else if (isMulti.value) { // 仅当 card_type === 'multi_select' 或 'mixed' 时执行
|
||||
// 多选逻辑...
|
||||
}
|
||||
// 如果 card_type 不是上述任何值,函数什么都不做!
|
||||
}
|
||||
```
|
||||
|
||||
**关键问题**:如果后端返回的 `card.card_type` 不是 `'single_select'`、`'multi_select'` 或 `'mixed'`(可能是 `undefined`、`null` 或其他未定义的值),`toggleOption` 函数**不会执行任何逻辑**,导致:
|
||||
|
||||
- 用户点击选项 A → `selectedValues` 不更新
|
||||
- 用户点击选项 B → `selectedValues` 仍不更新
|
||||
- 视觉上表现为"无法切换选项"
|
||||
|
||||
### 代码位置
|
||||
|
||||
**文件:** `mini-program/src/components/ClarificationCard.vue:80-95`
|
||||
|
||||
## 设计目标
|
||||
|
||||
1. **选项可自由切换**:无论 `card_type` 是什么值,用户都能正常切换选项
|
||||
2. **保持现有功能**:不破坏单选、多选、文本输入的现有行为
|
||||
3. **向后兼容**:对于正常的 `card_type` 值(`single_select`、`multi_select`、`text_input`),行为保持不变
|
||||
4. **不破坏其他业务功能**:不修改 ScriptView.vue 或后端代码
|
||||
|
||||
## 技术方案
|
||||
|
||||
### 方案:增强 `toggleOption` 容错性
|
||||
|
||||
**核心思路**:将条件判断从"是否为单选"改为"是否为多选或文本输入",如果都不是则默认当作单选处理。
|
||||
|
||||
**修改位置:** `mini-program/src/components/ClarificationCard.vue:80-95`
|
||||
|
||||
**修改前的代码:**
|
||||
```javascript
|
||||
function toggleOption(opt) {
|
||||
const value = opt.value
|
||||
if (isSingle.value) {
|
||||
selectedValues.value = [value]
|
||||
} else if (isMulti.value) {
|
||||
const idx = selectedValues.value.indexOf(value)
|
||||
if (idx >= 0) {
|
||||
selectedValues.value.splice(idx, 1)
|
||||
} else {
|
||||
const maxSel = props.card.max_selections || selectedValues.value.length + 1
|
||||
if (selectedValues.value.length < maxSel) {
|
||||
selectedValues.value.push(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**修改后的代码:**
|
||||
```javascript
|
||||
function toggleOption(opt) {
|
||||
const value = opt.value
|
||||
// 修复:默认当作单选处理(当不是多选也不是文本输入时)
|
||||
if (isMulti.value) {
|
||||
// 多选逻辑
|
||||
const idx = selectedValues.value.indexOf(value)
|
||||
if (idx >= 0) {
|
||||
selectedValues.value.splice(idx, 1)
|
||||
} else {
|
||||
const maxSel = props.card.max_selections || selectedValues.value.length + 1
|
||||
if (selectedValues.value.length < maxSel) {
|
||||
selectedValues.value.push(value)
|
||||
}
|
||||
}
|
||||
} else if (!isTextInput.value) {
|
||||
// 单选逻辑(默认行为,包括 card_type 未定义或未知的情况)
|
||||
selectedValues.value = [value]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**关键变更:**
|
||||
- 将 `if (isSingle.value)` 改为 `else if (!isTextInput.value)`
|
||||
- 这意味着:只要不是多选(`isMulti.value`)也不是文本输入(`isTextInput.value`),就当作单选处理
|
||||
- 这样即使 `card_type` 是 `undefined`、`null` 或其他未定义的值,选项也能正常切换
|
||||
|
||||
**保留的多选逻辑:**
|
||||
- 多选条件(`isMulti.value`)保持不变
|
||||
- 多选逻辑(添加/删除选项)保持不变
|
||||
- 最大选择数限制(`max_selections`)保持不变
|
||||
|
||||
**保留的文本输入逻辑:**
|
||||
- 文本输入卡片(`isTextInput.value`)不会有选项,所以 `toggleOption` 不会被调用
|
||||
- 但保留这个判断是为了代码的可读性和未来的扩展性
|
||||
|
||||
## 行为对照表
|
||||
|
||||
| card_type 值 | 修改前行为 | 修改后行为 |
|
||||
|--------------|-----------|-----------|
|
||||
| `'single_select'` | ✅ 单选切换 | ✅ 单选切换(行为不变) |
|
||||
| `'multi_select'` | ✅ 多选切换 | ✅ 多选切换(行为不变) |
|
||||
| `'mixed'` | ✅ 多选切换 | ✅ 多选切换(行为不变) |
|
||||
| `'text_input'` | ✅ 无选项,不调用 | ✅ 无选项,不调用(行为不变) |
|
||||
| `undefined` / `null` | ❌ 无法切换 | ✅ 默认单选切换 |
|
||||
| 其他未知值 | ❌ 无法切换 | ✅ 默认单选切换 |
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 第一步:修改 ClarificationCard.vue
|
||||
|
||||
打开 `mini-program/src/components/ClarificationCard.vue`,定位到第 80-95 行的 `toggleOption` 函数,将其修改为上述"修改后的代码"。
|
||||
|
||||
### 第二步:构建小程序
|
||||
|
||||
```bash
|
||||
cd mini-program
|
||||
npm run build:mp-weixin
|
||||
```
|
||||
|
||||
预期输出:`DONE Build complete.`
|
||||
|
||||
### 第三步:提交修改
|
||||
|
||||
```bash
|
||||
git add mini-program/src/components/ClarificationCard.vue
|
||||
git commit -m "fix: 修复 ClarificationCard 选项无法切换的 bug(增强 toggleOption 容错性)"
|
||||
```
|
||||
|
||||
### 第四步:用户验证
|
||||
|
||||
在微信小程序中:
|
||||
1. 进入"心愿实现"页面
|
||||
2. 输入心愿文本,触发澄清卡片
|
||||
3. 点击选项 A(应该被选中)
|
||||
4. 点击选项 B(应该切换到 B,A 取消选中)
|
||||
5. 再次点击选项 A(应该切换回 A)
|
||||
6. 验证:选项可以自由切换
|
||||
|
||||
## 风险评估
|
||||
|
||||
### 风险 1:影响现有正常的卡片类型
|
||||
|
||||
**可能性**:低
|
||||
|
||||
**缓解措施**:
|
||||
- 修改前的行为对照表显示,所有正常的 `card_type` 值行为不变
|
||||
- 只改变了未知值的默认行为(从"不响应"改为"单选响应")
|
||||
|
||||
### 风险 2:破坏其他业务功能
|
||||
|
||||
**可能性**:极低
|
||||
|
||||
**缓解措施**:
|
||||
- 只修改了 ClarificationCard.vue 一个文件
|
||||
- 不修改 ScriptView.vue 的事件处理
|
||||
- 不修改后端代码
|
||||
|
||||
### 风险 3:响应式更新问题
|
||||
|
||||
**可能性**:低
|
||||
|
||||
**缓解措施**:
|
||||
- `selectedValues.value = [value]` 是 Vue 3 标准的响应式赋值
|
||||
- 在原有代码中已经使用这种方式,应该是有效的
|
||||
|
||||
## 测试用例
|
||||
|
||||
### 测试用例 1:单选卡片切换
|
||||
|
||||
1. 输入心愿文本
|
||||
2. 收到澄清卡片(单选类型)
|
||||
3. 点击选项 A
|
||||
4. 验证:选项 A 被选中(有 ✓ 标记)
|
||||
5. 点击选项 B
|
||||
6. **验证:选项 B 被选中,选项 A 取消选中**(这是修复的关键点)
|
||||
|
||||
### 测试用例 2:多选卡片(保持原有行为)
|
||||
|
||||
1. 收到澄清卡片(多选类型)
|
||||
2. 点击选项 A
|
||||
3. 验证:选项 A 被选中
|
||||
4. 点击选项 B
|
||||
5. **验证:选项 A 和 B 都被选中**(多选行为不变)
|
||||
|
||||
### 测试用例 3:未知 card_type(修复场景)
|
||||
|
||||
1. 后端返回 `card_type: undefined` 或其他未知值
|
||||
2. 收到澄清卡片
|
||||
3. 点击选项 A
|
||||
4. **验证:选项 A 被选中**
|
||||
5. 点击选项 B
|
||||
6. **验证:选项 B 被选中,选项 A 取消选中**(这是修复的核心场景)
|
||||
|
||||
## 完成标准
|
||||
|
||||
1. ✅ ClarificationCard.vue 的 `toggleOption` 函数已修改
|
||||
2. ✅ 小程序构建成功
|
||||
3. ✅ 修改已提交到 git
|
||||
4. ✅ 用户验证:选项可以自由切换
|
||||
5. ✅ 现有功能(单选、多选、文本输入)未受影响
|
||||
Reference in New Issue
Block a user