Files

96 lines
5.9 KiB
Markdown
Raw Permalink 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.
# INBOX
> 本轮任务:K100 后台剧集多选上传(分片 + 断点续传 + 进度展示)。**[已处理]**
> 开工前置:先读 `AGENTS.md`、`CODING_STANDARDS.md`、`GIT_WORKFLOW.md` 本文件,再读
> `ReelShortWeb/src/utils/uploader.ts`、`src/api/admin/media.ts`、`src/views/contentManagement/EpisodeManagementView.vue`。
### Codex 回执(K100)
- ReelShortWeb 分支:`feature/episode-batch-upload` → `--no-ff` 合入 `develop` 并 push
- 提交:`feat(admin): 剧集多选分片上传与断点续传`
- 门禁:`pnpm lint:eslint` 零错误;`pnpm build:dev` 成功
- 未验证:PM 手工多选/暂停/刷新续传/批量建集(8080+3005)
- 风险:续传需重选相同本地文件;暂停不 abort 进行中分片
## 现状(已勘察,不要重复排查)
- 后端分片上传已具备且不改:`POST /admin/media/upload/init` → `POST /admin/media/upload/chunk` →
`POST /admin/media/upload/complete`;断点查询 `GET /admin/media/upload/{uploadId}`
返回 `receivedChunks/totalChunks/chunkSize/percent/status/assetId/url`。
- 前端已有 `src/utils/uploader.ts`:`uploadFile()` 分片并发 3、`resumeUpload()` 按服务端已收片数续传、
`probeVideoDuration()` 探测时长。**这两个函数已可用,本次在其上做批量队列 UI**。
- 当前剧集管理 `EpisodeManagementView.vue` 只有一个 `el-upload` 单文件入口(`http-request="uploadVideo"`),
**不支持多选、没有进度条、没有断点续传入口**,`onSession` 也没有落盘。
## 目标
在剧集管理页提供「批量上传」:一次选多个视频 → 队列分片上传 → 每个文件独立进度 → 失败可重试 →
刷新/重进页面能续传 → 上传完成后批量创建分集。
## A. 上传队列(新建 `src/views/contentManagement/upload/useUploadQueue.ts`)
1. 输入:`File[]` + `dramaId` + 可选 `bizType`
2. 每项状态机:`waiting → uploading → merging → done / failed / paused`;对外暴露 `items`、`overallPercent`、
`start()`、`pause()`、`retry(id)`、`retryAll()`、`remove(id)`、`clear()`
3. 队列并发:同时最多 2 个文件上传(文件内分片并发沿用 `uploadFile` 的 3)
4. 进度:文件内 `onProgress` 回调更新单项百分比;总进度 = 各文件字节加权,不是简单平均
5. 失败隔离:单文件失败不影响其它文件,错误原因记在该项 `error`
6. 暂停语义(本轮简化,不做 abort):暂停后不再派发新任务,已在传的分片让其完成
7. 上传完成后 `completeUploadApi` 拿到 `assetId/url/durationSec` 写回该项
## B. 断点续传(关键)
1. 上传开始(拿到 `uploadId`)即写入 `localStorage`:键 `reel_upload_sessions`,
值数组项含 `{ uploadId, fileName, fileSize, lastModified, dramaId, bizType, createdAt }`
2. 页面进入时读取该键,过滤 `dramaId` 匹配且 24 小时内的会话,弹出提示「发现 N 个未完成上传,是否续传」
3. 续传前用 `file.name + size + lastModified` 匹配本地重新选择的文件;
**文件匹配不上(换机器/改名)则不自动续传,提示后由用户手动重选**
4. 续传走现有 `resumeUpload(file, uploadId)`;`GET /admin/media/upload/{uploadId}` 返回 404 或已 completed 的会话要从 localStorage 清理
5. 上传成功、用户移除、用户放弃续传三种情况都要清理对应记录
## C. 批量创建分集
1. 上传完成列表提供「批量创建分集」按钮
2. 默认值:按文件名自然排序(去扩展名后再比较,`第2集` 排在 `第10集` 之前);
集号 = 该剧当前最大集号 + 1 起顺延;标题取文件名去扩展名;是否免费沿用现有新建默认值
3. 弹窗内每行可改:集号、标题、是否免费;冲突集号在提交前本地校验并标红
4. 提交:逐条调用现有 `createEpisodeApi`(`src/api/admin/episode.ts`),
逐条显示成功/失败,失败的保留在弹窗内可重试;全部结束后刷新剧集列表
5. **不新增后端接口**,契约不动
## D. 组件拆分(红线:单文件 ≤ 500 行)
- `src/views/contentManagement/upload/BatchUploadDialog.vue`:多选、队列列表、总进度、暂停/重试/移除
- `src/views/contentManagement/upload/UploadTaskRow.vue`:单行(文件名、大小、进度条、状态、操作)
- `src/views/contentManagement/upload/CreateEpisodesDialog.vue`:批量建分集表单
- `src/views/contentManagement/upload/useUploadQueue.ts`:队列逻辑(纯逻辑单元,不写 UI)
- `EpisodeManagementView.vue` 只加一个「批量上传」入口按钮,并保持原单文件上传入口可用
## E. 细节要求
- 文件类型白名单:`mp4/mov/mkv/webm`(`accept="video/*"` + `before-upload` 二次校验)
- 单文件大小上限从现有常量取值,超限直接标红不入队
- 所有文案走 `src/locales/zh-CN.ts` / `en.ts`,禁止硬编码中文
- 进度与错误展示用项目现有样式变量,不新引入 UI 依赖
- 上传期间:关闭页面前用 `beforeunload` 提示存在未完成上传
## F. 门禁
- `pnpm lint:eslint` 零错误
- `pnpm build:dev` 构建成功
- 手工验证(PM 会复核):本地起 8080 + 3005,多选 3 个视频 → 三条并行进度 → 中途暂停 → 刷新页面 → 出现续传提示 → 续传完成 → 批量建分集成功
## Git
- ReelShortWeb:从 `develop` 拉 `feature/episode-batch-upload` → 提交
`feat(admin): 剧集多选分片上传与断点续传` → `--no-ff` 合回 `develop` 并 push
- 作者 `Zhou Weidong <502333560@qq.com>`;禁止 `git add -A`;源码首行 `// Author: fruit.com.cn`
## 约束
- 先写计划 `docs/plans/2026-10-21-K100-episode-batch-upload.md`,再改代码
- 每跑一个命令,把「命令 + 原始输出 + 解读」追加到 `docs/plans/PROGRESS.md`
- 不改 FruitServer、不改 ReelShort 客户端、不改接口契约
- 禁止 `git add -A`;不要操作真机
- 完成后停住等 PM 验收,回执需贴门禁原始输出