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:
@@ -23,6 +23,8 @@ import {
|
||||
setStoredRefreshToken,
|
||||
clearStoredRefreshToken,
|
||||
initRefreshTokenStore,
|
||||
scheduleProactiveRefresh,
|
||||
clearProactiveRefresh,
|
||||
} from '@/services/auth-token';
|
||||
import {initModelCache} from '@/services/cache/model-cache';
|
||||
|
||||
@@ -89,6 +91,8 @@ export function AppProvider({ children }: AppProviderProps) {
|
||||
const login = useCallback(async (auth: LoginResponseBody) => {
|
||||
await setToken(auth.access_token);
|
||||
await setStoredRefreshToken(auth.refresh_token);
|
||||
// 启动主动刷新定时器(在 access_token 过期前自动续期)
|
||||
scheduleProactiveRefresh(auth.access_token);
|
||||
setUser(auth);
|
||||
setIsLoggedIn(true);
|
||||
logger.info('auth', 'User logged in', {
|
||||
@@ -102,6 +106,7 @@ export function AppProvider({ children }: AppProviderProps) {
|
||||
logger.info('auth', 'User logged out');
|
||||
clearToken();
|
||||
clearStoredRefreshToken();
|
||||
clearProactiveRefresh();
|
||||
setUser(null);
|
||||
setIsLoggedIn(false);
|
||||
emit(EVENTS.LOGOUT);
|
||||
@@ -133,6 +138,7 @@ export function AppProvider({ children }: AppProviderProps) {
|
||||
if (aborted) return;
|
||||
await setToken(res.access_token);
|
||||
await setStoredRefreshToken(res.refresh_token);
|
||||
scheduleProactiveRefresh(res.access_token);
|
||||
setIsLoggedIn(true);
|
||||
logger.info('auth', 'Auto-login succeeded');
|
||||
// 补全用户信息
|
||||
|
||||
Reference in New Issue
Block a user