feat: 实现聊天取消功能,提升用户交互体验
- 在教练页面中添加用户取消发送或终止回复的能力 - 更新发送按钮状态,支持发送和取消状态切换 - 在流式回复中显示取消按钮,允许用户中断助手的生成 - 增强请求管理,添加请求序列号和有效性验证,防止延迟响应影响用户体验 - 优化错误处理,区分用户主动取消和网络错误,提升系统稳定性 - 更新相关文档,详细描述取消功能的实现和用户体验设计
This commit is contained in:
@@ -247,4 +247,90 @@ choiceButtonRecommended: {
|
||||
4. **错误处理**:完整的错误处理机制,确保用户体验流畅
|
||||
5. **性能优化**:避免不必要的重渲染,保持界面响应性
|
||||
|
||||
这个实现完全符合API文档的要求,支持饮食记录的两阶段确认流程,并保持了与现有功能的兼容性。
|
||||
## 选择状态管理与用户体验优化
|
||||
|
||||
### 防重复点击机制
|
||||
|
||||
为了防止用户重复发送消息,实现了完善的状态管理:
|
||||
|
||||
```typescript
|
||||
const [selectedChoices, setSelectedChoices] = useState<Record<string, string>>({}); // messageId -> choiceId
|
||||
const [pendingChoiceConfirmation, setPendingChoiceConfirmation] = useState<Record<string, boolean>>({}); // messageId -> loading
|
||||
```
|
||||
|
||||
### 选择状态逻辑
|
||||
|
||||
1. **状态检查**:点击前检查是否已选择
|
||||
2. **立即锁定**:点击后立即设置选中状态,防止重复点击
|
||||
3. **视觉反馈**:选中项显示特殊样式,其他选项变为禁用状态
|
||||
4. **加载指示**:发送过程中显示loading动画
|
||||
5. **错误恢复**:发送失败时重置状态,允许重新选择
|
||||
|
||||
### UI状态展示
|
||||
|
||||
- **正常状态**:常规样式,可点击
|
||||
- **推荐状态**:特殊边框和背景色,显示"推荐"标签
|
||||
- **选中状态**:深色边框,绿色背景,显示"已选择"标签
|
||||
- **禁用状态**:灰色透明,不可点击
|
||||
- **加载状态**:显示旋转加载动画
|
||||
|
||||
### 触觉反馈
|
||||
|
||||
- **选择时**:`Haptics.selectionAsync()` - 轻微选择反馈
|
||||
- **成功时**:`Haptics.NotificationFeedbackType.Success` - 成功通知
|
||||
- **失败时**:`Haptics.NotificationFeedbackType.Error` - 错误通知
|
||||
|
||||
### 代码示例
|
||||
|
||||
```typescript
|
||||
// 状态管理
|
||||
const isSelected = selectedChoices[item.id] === choice.id;
|
||||
const isAnySelected = selectedChoices[item.id] != null;
|
||||
const isPending = pendingChoiceConfirmation[item.id];
|
||||
const isDisabled = isAnySelected && !isSelected;
|
||||
|
||||
// 点击处理
|
||||
onPress={() => {
|
||||
if (!isDisabled && !isPending) {
|
||||
Haptics.selectionAsync();
|
||||
handleChoiceSelection(choice, item);
|
||||
}
|
||||
}}
|
||||
|
||||
// 选择处理逻辑
|
||||
async function handleChoiceSelection(choice: AiChoiceOption, message: ChatMessage) {
|
||||
// 防重复检查
|
||||
if (selectedChoices[message.id] != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 立即设置状态
|
||||
setSelectedChoices(prev => ({ ...prev, [message.id]: choice.id }));
|
||||
setPendingChoiceConfirmation(prev => ({ ...prev, [message.id]: true }));
|
||||
|
||||
try {
|
||||
// 发送确认
|
||||
await sendStreamWithConfirmation(confirmationText, choice.id, confirmationData);
|
||||
|
||||
// 成功反馈
|
||||
setPendingChoiceConfirmation(prev => ({ ...prev, [message.id]: false }));
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
||||
} catch (e) {
|
||||
// 失败时重置状态
|
||||
setSelectedChoices(prev => {
|
||||
const { [message.id]: _, ...rest } = prev;
|
||||
return rest;
|
||||
});
|
||||
setPendingChoiceConfirmation(prev => {
|
||||
const { [message.id]: _, ...rest } = prev;
|
||||
return rest;
|
||||
});
|
||||
|
||||
// 错误反馈
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
|
||||
Alert.alert('选择失败', e?.message || '选择失败,请重试');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这个实现完全符合API文档的要求,支持饮食记录的两阶段确认流程,并保持了与现有功能的兼容性。同时提供了优秀的用户体验,包括防重复点击、状态反馈、触觉反馈等功能。
|
||||
|
||||
Reference in New Issue
Block a user