---
name: async-confirm-dialog-loading
description: 当 cook-web 的确认弹窗会触发重修、删除、恢复等异步请求时，使用本技能保证按钮防重复点击、loading 状态与弹窗关闭时机和请求完成保持一致。
---

# 异步确认弹窗请求态

## 核心规则

- 当确认弹窗触发的是 `DELETE`、重修、恢复或其他会改写学习状态的异步请求时，确认按钮必须在请求 pending 期间显示 loading，并保持禁用，避免重复提交。
- 弹窗关闭时机要和请求完成绑定；不要在发起请求后立刻关闭弹窗，否则用户会误以为操作已经结束。
- 若页面上存在多个入口触发同一个异步动作，优先复用同一个 store 请求态或共享 hook，不要为每个入口各写一套分散的 loading 判断。
- 对触发弹窗的同步入口按钮优先补轻量防抖，避免双击导致多次打开弹窗；对确认后的异步请求再使用 single-flight 保护，避免重复发起同一请求。
- 请求进行中时，要同时拦截关闭按钮、遮罩点击和 `Escape` 关闭，保证用户看到真实的 pending 状态。

## 工作流

1. 先确认异步动作是否已经在 store、query 或 service 层暴露了稳定的 pending 标记，例如 `resettingLessonId`、`isLoading`、`mutation.isPending`。
2. 若已有请求态，优先直接把确认按钮、关闭能力和弹窗显隐绑定到这份状态，而不是新增一份容易漂移的本地 loading。
3. 若用户可能连续点击确认按钮，在组件层补 single-flight 包装，确保首个异步请求未完成前后续点击直接返回。
4. 对触发弹窗的同步入口按钮增加短时间防抖，避免双击造成重复埋点、重复打开或事件冒泡副作用；不要误以为 single-flight 能覆盖这类同步打开动作。
5. 修改后重点验证“快速双击入口按钮”“快速连点确认按钮”“请求失败后弹窗是否仍保留并允许再次提交”三条路径。

## 验证要点

- 请求发出后，确认按钮立即进入 loading，直到接口从 pending 变为完成或失败才恢复。
- 请求 pending 期间，弹窗不能通过右上角关闭、点击遮罩或按 `Escape` 被提前关闭。
- 同一个 lesson / chapter 不会因为双击而发出重复的重修或删除请求。
- 复用同一请求态的其他入口，视觉和关闭时机保持一致。
