feat(assets): 上传即入库——批量上传队列化(并发3)+真实进度+刷新不丢 #1557
Reference in New Issue
Block a user
Delete Branch "feat/upload-instant-assets"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
批量上传视频后素材库很久才显示:①直传阶段只有内存乐观卡片、刷新即丢,服务端 complete 后才有记录;②10 路并发直传瓜分上行带宽;③直传完还要等 worker 转码约 3 分钟才可见。
前端改造(本 PR),后端配合在
/upload/direct/prepare预创建status=uploading的 asset 并返回asset_id(后端任务并行,前端对旧返回做降级兼容)。改动
API 层(api/assets)
DirectUploadPrepareResult新增可选asset_id(后端预建素材 id;旧后端不返回 → 降级为原行为)prepareDirectUploadHandle():把直传拆为 prepare → transfer(OSS, onProgress) → complete 三段,支持队列调度与失败重试;uploadAssetDirect()旧签名保留为「一次性完成」封装,配音库/克隆音色等既有调用方零改动useAssetUpload 重写(队列式批量)
preparing → uploading(真实 XHR 进度) → ingesting → done/errorduplicated去重提示逻辑不变UI
UploadProgressModal,新增UploadQueuePanel:每文件独立进度条/状态/重试/移除/清空已完成AssetUploadZone多文件拖入即入队,文案显示「上传中…(进行 N 个,排队 M 个)」AssetCard:上传中遮罩显示真实百分比 + 进度条;转码中遮罩与上传中区分useAssetsData:列表存在 uploading/ingesting/processing/pending 素材时每 3s 轮询(refetchInterval 动态求值),全部就绪自动停止;status 全量参数不变不改动
去重逻辑、单文件/配音上传流程、上传弹窗交互、素材筛选/播放、clips 提交链路。
测试
useAssetUpload.test.tsx3 用例:5 文件并发不超过 3 且全部完成/刷新列表、传输失败重试成功、duplicated 去重标记验收(依赖后端 prepare 返回 asset_id 上线后端到端完整;旧后端下队列/并发/进度/重试仍生效,仅卡片即时出现降级为 complete 后出现)
拖入 5 个视频 → 素材库立刻出现 5 张「上传中」卡片显示真实进度 → 刷新不消失 → 传完依次变「转码中」→ 完成可播放;同时直传不超过 3 路;去重提示正常。
🚀 预览环境已部署
【阻塞级判定】
📊 审查概览
🔴 阻塞级问题(必须修复)
无
💡 改进建议(不阻塞合并)
无
✅ 良好实践
[apps/web/src/api/assets/upload.ts] 模块化设计
putToOSS、prepareDirectUploadHandle和uploadAssetDirect,实现了职责分离,既保留了向后兼容的简单调用方式,又提供了支持队列和重试的细粒度控制接口(Handle 模式)。[apps/web/src/api/assets/upload.ts] 错误处理完善
XMLHttpRequest的onload事件中,不仅检查了状态码,还尝试解析响应体中的错误信息(res.message),有助于排查上传失败原因。[apps/web/src/pages/assets/AssetLibrary.tsx] 性能优化
useMemo缓存uploadProgressMap,避免在每次渲染时重新创建 Map 对象,减少子组件不必要的重渲染。[apps/web/src/pages/assets/components/AssetCard.tsx] 状态互斥逻辑
!isUploading),避免状态冲突导致 UI 混乱。✅ 格式检查通过 | ✅ 逻辑审查通过 | ✅ 性能良好
🤖 由 AI 代码审查机器人自动生成 | 2026-08-30 09:43:58 | 模型:
CI全绿,自动审批通过。
CI全绿,自动审批通过。
🗑️ 预览环境已清理
PR #1557 已关闭或合并,对应的预览环境已被清理。