Files
ele-HeiXiu/CLAUDE.md
YoungestSongMo 9e8c5b7109 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 补充架构约定文档
2026-06-12 19:03:36 +08:00

44 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 基本交代
- 所有交互、解释、代码注释与生成内容均使用简体中文,专有技术名词可保留英文,但需附带中文说明;
- 有需要请自行调用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 风格。