### 任务状态轮询 - 新增 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 补充架构约定文档
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
// ============================================================
|
||
// AudioListInput — audioList → Dragger(音频文件拖拽上传)
|
||
// 用于声纹克隆的音频样本上传场景
|
||
// ============================================================
|
||
|
||
import { Upload } from 'antd';
|
||
import { InboxOutlined } from '@ant-design/icons';
|
||
import type { UploadFile } from 'antd/es/upload';
|
||
import type { WidgetProps } from './types';
|
||
import { useFileUpload } from '@/hooks/use-api';
|
||
|
||
const { Dragger } = Upload;
|
||
|
||
export function AudioListInput({ value, onChange, disabled, config }: WidgetProps) {
|
||
const fileList = (value as UploadFile[]) || [];
|
||
const maxSizeMb = (config.maxFileSizeMb as number) || 10;
|
||
const maxCount = (config.maxFiles as number) || 10;
|
||
const filters = config.fileFilter as string[] | undefined;
|
||
|
||
const { customRequest } = useFileUpload();
|
||
|
||
return (
|
||
<Dragger
|
||
multiple
|
||
accept={
|
||
filters
|
||
? filters.map((ext) => `.${ext}`).join(',')
|
||
: '.wav,.mp3,.m4a,.flac'
|
||
}
|
||
fileList={fileList}
|
||
customRequest={customRequest}
|
||
onChange={({ fileList: newList }) => onChange?.(newList)}
|
||
disabled={disabled}
|
||
beforeUpload={() => true}
|
||
maxCount={maxCount}
|
||
>
|
||
<p className="ant-upload-drag-icon">
|
||
<InboxOutlined />
|
||
</p>
|
||
<p className="ant-upload-text">点击或拖拽音频文件到此区域上传</p>
|
||
<p className="ant-upload-hint">
|
||
支持 {filters?.join(' / ').toUpperCase() || 'WAV / MP3 / M4A / FLAC'}
|
||
,单文件不超过 {maxSizeMb}MB
|
||
</p>
|
||
</Dragger>
|
||
);
|
||
}
|