feat: 任务轮询 + Token刷新容错 + 提交防抖 + 文件上传Hook (0.0.20)
### 任务状态轮询 - 新增 useTaskPolling hook:批量轮询非终态任务,递归 setTimeout + next_poll_ms 自适应间隔 - TaskHistory 集成批量轮询,OutputPreview 移除独立轮询改为状态转换监听 - batchTaskStatus 修复数组参数序列化(GET + 逗号拼接,避免 bracket 格式) - 统一 POLLING_STATUSES 常量管理非终态状态 ### Token 刷新容错 - 双轨刷新:主动续期(JWT exp 75% 时间点 setTimeout)+ 被动兜底(handle401) - 刷新失败分级:永久失败(throw RefreshTokenExpiredError)→清token弹登录;临时失败(return null)→仅拒绝当前请求 - AppProvider 登录/自动登录/退出 启停主动刷新定时器 ### 提交按钮防抖 - 2s 节流防抖("你点击的太快了")+ 二次确认弹窗("您已提交,确认要再次提交吗?") - 修复 useAsyncMutation.execute 返回值判空(原 try/catch 死代码) ### 文件上传 Hook - 新增 useFileUpload hook:封装 request.upload() 为 antd Upload 兼容 customRequest - ImageInput/ImageListInput/AudioListInput 集成 customRequest - uploadValidation beforeUpload 返回值修正(false→true) ### 其他 - AnnouncementDrawer 接入公告 API + EnumResolver - billing/announcement/banner 服务模块完善 - CLAUDE.md 补充架构约定文档
This commit is contained in:
47
CLAUDE.md
47
CLAUDE.md
@@ -1,6 +1,43 @@
|
||||
# 回答语言
|
||||
# 基本交代
|
||||
|
||||
- 所有交互、解释、代码注释与生成内容均使用简体中文,专有技术名词可保留英文,但需附带中文说明;
|
||||
- 有需要请自行调用MCP服务;
|
||||
|
||||
# 业务设计思路
|
||||
|
||||
- 进行任务时都需要考虑安全、性能、主题切换、业务自定义错误、事件总线驱动方式以及日志记录;
|
||||
- 进行系统级别的操作时,需要考虑系统差异,并处理兼容性。如WINDOWS、MAC OS;
|
||||
- 处理业务时,需要同时考虑兜底机制和业务自定义错误捕获;
|
||||
- 所有设计思路、代码实现均需要考虑以上三个条件。
|
||||
|
||||
# 架构约定
|
||||
|
||||
## 任务状态轮询
|
||||
|
||||
- **两层轮询 + Context 桥接**:`useTaskPolling`(批量轮询 `batchTaskStatus`)负责广度覆盖,`OutputPreview` 通过 `selectedTask.status` 变化检测终态转换后触发 `refetch()` 获取详情——二者通过 Context 同步,避免重复请求。
|
||||
- **非终态统一管理**:`POLLING_STATUSES = ['pending', 'submitted', 'processing']` 定义在 `task.ts`,所有轮询逻辑引用此常量。
|
||||
- **自适应间隔**:递归 `setTimeout`(非 `setInterval`)+ 服务端 `next_poll_ms`,本地 clamp 2s~30s,出错 10s 重试。
|
||||
- **useRef 打破闭包陷阱**:`mergedRef.current` 确保递归回调读到最新任务列表。
|
||||
|
||||
## Token 刷新
|
||||
|
||||
- **双轨刷新**:主动刷新(`scheduleProactiveRefresh`)在 JWT `exp` 的 75% 时间点通过 `setTimeout` 提前续期;被动刷新(`handle401` → `refreshHandler`)兜底。
|
||||
- **失败分级处理**:`refreshHandler` 永久失败(`RefreshTokenExpiredError`)→ throw → `handle401` 清 token + 弹登录;临时失败(网络超时)→ return null → 仅拒绝当前请求,不登出。
|
||||
- **JWT 解码驱动定时器**:从 `atob(token.split('.')[1])` 取 `exp` 声明,无需额外持久化 `expires_in`。
|
||||
- **刷新接口隔离**:`/api/v1/auth/refresh` 在 `request.ts` 中特殊处理(`isRefreshRequest`),防止 401→刷新→401 死循环。
|
||||
|
||||
## 文件上传
|
||||
|
||||
- **customRequest 集成模式**:`useFileUpload` hook 封装 `request.upload()`,返回 antd Upload 兼容的 `customRequest`——避免直接设 `action` 导致 Token 缺失,复用全局拦截器的认证和错误处理。
|
||||
- **beforeUpload 语义修正**:校验通过返回 `true`(放行至 `customRequest`),失败返回 `Upload.LIST_IGNORE`。
|
||||
|
||||
## 表单提交
|
||||
|
||||
- **两级防护**:防抖(2s 节流,"你点击的太快了")+ 二次确认(`Modal.confirm`,"您已提交,确认要再次提交吗?")。
|
||||
- **useRef 存储时序状态**:`lastClickTimeRef` / `submitCountRef` 避免不必要的重渲染。
|
||||
- **useAsyncMutation 返回值判空**:`execute()` 内部 catch 所有错误返回 `undefined`,调用方应检查返回值而非 try/catch。
|
||||
|
||||
## GET 数组参数
|
||||
|
||||
- **逗号拼接优于 bracket 序列化**:`task_ids=a,b,c` 比 `task_ids[]=a&task_ids[]=b` 更具跨框架兼容性,避免 axios 默认 `paramsSerializer` 的 PHP/Rack 风格。
|
||||
|
||||
- 所有交互、解释、代码注释与生成内容均使用简体中文,专有技术名词可保留英文,但需附带中文说明
|
||||
- 进行任务时都需要考虑安全、性能、主题切换、业务自定义错误、事件总线驱动方式以及日志记录
|
||||
- 进行系统级别的操作时,需要考虑系统差异,并处理兼容性。如WINDOWS、MAC OS。
|
||||
- 有需要请自己调用MCP服务
|
||||
|
||||
Reference in New Issue
Block a user