生成帧完成后自动刷新项目封面

- 项目库生成帧任务入队后继续轮询任务进度,解析成功后重新拉取项目列表和当前项目对象。

- 成功后显示视频帧生成完成提示,并让后端写入的 thumbnail_url 立即刷新到项目卡片封面。

- 补充 ProjectLibrary 回归测试,覆盖生成帧完成后自动显示新封面。

- 更新前端审计、设计冻结、测试计划、状态机和项目指南文档。
This commit is contained in:
2026-05-04 05:07:22 +08:00
parent 85de1ffbb2
commit 02635abab1
7 changed files with 92 additions and 12 deletions

View File

@@ -60,7 +60,7 @@
| 点击项目进入工作区 | 真实可用 | 设置 `currentProject` 后切到 `workspace` |
| 新建项目 | 真实可用 | 调用 `POST /api/projects` |
| 导入视频文件 | 真实可用 | 创建项目、上传源视频、刷新项目列表;不会自动拆帧;上传期间显示项目库导入进度条、百分比和已上传字节 |
| 生成帧按钮 | 真实可用 | 仅对已导入源视频且尚无帧、非 parsing 状态的项目显示,调用 `parseMedia(projectId, { parseFps })` |
| 生成帧按钮 | 真实可用 | 仅对已导入源视频且尚无帧、非 parsing 状态的项目显示,调用 `parseMedia(projectId, { parseFps })`;任务入队后项目库继续轮询 `GET /api/tasks/{task_id}`,解析成功后立即重新拉取项目列表,使后端新写入的 `thumbnail_url` 自动刷新到项目封面 |
| 生成帧 FPS 滑块 | 真实可用 | 值传入 `/api/media/parse?parse_fps=...`,决定后台拆帧目标 FPS |
| 项目卡片 FPS 徽标 | 真实可用 | 右上角显示关键帧序列目标 `parse_fps`;原始视频帧率只在卡片底部以“原 xx fps”显示 |
| 导入 DICOM 序列 | 真实可用 | 可上传 `.dcm` 并触发解析;上传前按文件名自然顺序排序,后端解析也保持同一顺序;上传期间显示导入进度条、有效 DICOM 文件数量和已上传字节,上传完成后继续显示解析任务进度直到完成、失败或取消 |

View File

@@ -96,13 +96,13 @@
1. `ProjectLibrary` 创建项目。
2. 导入视频时上传源视频到 `/api/media/upload` 并关联项目;该步骤不调用 `/api/media/parse`。上传期间项目库显示导入进度条、百分比和已上传字节,完成后短暂显示“视频导入完成”。
3. 用户在项目卡片点击“生成帧”,在弹窗中选择目标 FPS。
3. 用户在项目卡片点击“生成帧”,在弹窗中选择目标 FPS。任务入队后项目库会继续轮询任务进度,解析成功后自动重新拉取项目列表和当前项目对象,使后端生成的 `thumbnail_url` 立即显示为项目封面,无需刷新页面或重新进入项目库。
4. 前端调用 `/api/media/parse` 创建异步拆帧任务;可通过 `parse_fps``max_frames``target_width` 指定标准帧序列参数。
5. Celery worker 执行 FFmpeg/OpenCV/pydicom 拆帧DICOM 在前端选择、后端上传、worker 下载和 pydicom 读取时都按文件名自然顺序排序;视频/DICOM 解析结果都按 `frame_%06d.jpg``frame_000000.jpg` 连续命名,视频帧按目标宽度缩放。
6. worker 写入 `frames.timestamp_ms``frames.source_frame_number`,并在任务 `result.frame_sequence` 中记录 FPS、帧数、时长、尺寸和对象存储前缀。
7. worker 持续更新 `processing_tasks`,并发布 Redis `seg:progress`
8. 刷新项目列表;项目卡片右上角 FPS 徽标显示生成关键帧序列时选择的 `parse_fps`,原始视频 FPS 仅作为底部“原 xx fps”辅助信息显示。
9. 导入视频、生成帧、上传 DICOM 和失败反馈使用 `TransientNotice`,不再使用浏览器 `alert()` 阻塞操作;提示默认数秒后自动消失。视频和 DICOM 上传阶段额外显示项目库内的导入进度面板DICOM 面板显示有效文件数量,并在上传完成后切换为解析任务进度轮询 `GET /api/tasks/{task_id}` 直到成功、失败或取消。
9. 导入视频、生成帧、上传 DICOM 和失败反馈使用 `TransientNotice`,不再使用浏览器 `alert()` 阻塞操作;提示默认数秒后自动消失。视频和 DICOM 上传阶段额外显示项目库内的导入进度面板DICOM 面板显示有效文件数量,并在上传完成后切换为解析任务进度;视频生成帧也会显示解析进度并轮询 `GET /api/tasks/{task_id}` 直到成功、失败或取消。
10. DICOM 和视频帧序列写入同一 `frames` 表并共用工作区、时间轴、AI 传播、标注保存、GT 导入和导出链路,差异只存在于项目库导入入口和后端解析器。
### 任务控制

View File

@@ -16,7 +16,7 @@
|------|----------|--------|
| R1 登录与会话 | `src/components/Login.test.tsx`, `src/components/Sidebar.test.tsx`, `src/components/UserAdmin.test.tsx`, `src/store/useStore.test.ts`, `backend/tests/test_auth.py`, `backend/tests/test_admin.py` | 成功登录、JWT/token 写入、当前用户写入、刷新恢复基础状态、失败提示、登录输入 autocomplete、后端 401、`/api/auth/me`、管理员入口、用户 CRUD、角色权限、审计日志、viewer 读写权限边界、改密码/删除用户站内确认、演示出厂设置站内二次确认和重置结果 |
| R2 项目管理 | `src/lib/api.test.ts`, `src/components/ProjectLibrary.test.tsx`, `backend/tests/test_projects.py` | 前端字段映射、PATCH 更新、项目卡片复制/删除、修改项目名称时隐藏生成帧、DICOM 项目不显示生成帧、复制项目 reset/full 契约、DELETE 契约、后端 CRUD、删除级联、帧列表、项目按当前 JWT 用户隔离 |
| R3 媒体上传与拆帧 | `src/components/ProjectLibrary.test.tsx`, `src/components/TransientNotice.test.tsx`, `backend/tests/test_media.py`, `backend/tests/test_tasks.py` | 视频导入不自动拆帧、视频/DICOM 上传进度可视化、DICOM 导入显示有效文件数量并在上传后持续显示解析任务进度、显式生成帧 FPS 选择、项目卡片显示目标 parse_fps 而非原视频 FPS、扩展名校验、自动建项目、关联项目、创建异步任务、非阻塞自动消失操作提示、标准帧序列参数、帧时间戳/源帧号、任务序列元数据、worker 注册帧、取消任务、重试任务、取消后 worker 停止 |
| R3 媒体上传与拆帧 | `src/components/ProjectLibrary.test.tsx`, `src/components/TransientNotice.test.tsx`, `backend/tests/test_media.py`, `backend/tests/test_tasks.py` | 视频导入不自动拆帧、视频/DICOM 上传进度可视化、DICOM 导入显示有效文件数量并在上传后持续显示解析任务进度、显式生成帧 FPS 选择、视频生成帧入队后轮询解析任务并在成功后自动刷新项目封面、项目卡片显示目标 parse_fps 而非原视频 FPS、扩展名校验、自动建项目、关联项目、创建异步任务、非阻塞自动消失操作提示、标准帧序列参数、帧时间戳/源帧号、任务序列元数据、worker 注册帧、取消任务、重试任务、取消后 worker 停止 |
| R4 工作区与帧浏览 | `src/components/VideoWorkspace.test.tsx`, `src/components/FrameTimeline.test.tsx` | 加载帧、无帧项目不自动解析并提示生成帧、工作区短状态自动消失、工作区/AI 画布底图默认居中且保留边距、工作区 mask 透明度、回显已保存标注时保留本地未保存 draft mask、选中 mask 后跨帧自动跟随同一传播链结果、左侧工具栏清空遮罩优先作用于当前帧选中 mask/无选中时作用于当前帧全部 mask、无传播链时直接执行、有传播链时可选取消/只清当前帧/按帧范围选择/清空所有传播帧且按范围清空需最终确认、按范围清空或清空所有传播帧遇到人工/AI 标注帧时二次询问并支持保留人工帧、顶栏不显示重复的清空片段遮罩、传播进度存在时任务 message 只显示在蓝色进度面板内且不重复出现在灰色状态文字里、传播链布尔操作按帧范围选择并二次确认、清空/删除前预检后端 annotation id 并跳过本地陈旧 id、删除单个传播 mask 后空帧不保留传播历史颜色、传播权重下拉深色可读配色、自动传播范围选择时显示传播权重和向前/向后帧数、缩略图/range/视频处理进度条、视频处理进度条点击跳帧、人工/AI 标注帧红色竖线和标识点击跳帧、自动传播帧通过 source/lineage metadata 识别为蓝色区段和标识点击跳帧、最近自动传播历史片段同一蓝色系按新旧递进纯色显示,旧记录第 5 次后统一阈值色、当前帧白色贯穿线、传播/布尔/清空范围边界贯穿线、缩略图红/蓝边框、人工/AI 标注帧叠加传播状态时红框优先保留并显示蓝色内描边、当前人工/AI 标注帧青色外框加红色内描边、普通状态不显示传播范围黄色选区、播放进度条和视频处理进度条选择传播/布尔/清空范围、左右方向键切帧、播放、按项目 FPS 显示当前/总时长 |
| R5 工具栏 | `src/components/ToolsPalette.test.tsx`, `src/components/CanvasArea.test.tsx`, `src/components/VideoWorkspace.test.tsx`, `src/lib/keyboardShortcuts.test.ts`, `src/store/useStore.test.ts` | 工具切换、切换到多边形/矩形/圆会保留旧 mask 选区、有选中 mask 时多边形/矩形/圆/画笔新几何会并入选中 mask 且不要求重叠、无选中 mask 时手工新建 mask 后自动选中新 mask 并显示创建后边界点、Esc 和左侧“取消选中”按钮清空当前 mask 选区和临时绘制状态、工具栏紧凑垂直布局和高度不足时滚动、工具栏低对比滚动条、工具栏外扩滚动条槽位不挤占按钮列、调整多边形工具、AI 跳转、清空遮罩唯一左侧工具栏入口、清空遮罩上方 DEL 删除按钮、橡皮擦下方彩色 AI自动推理入口、Canvas 右下角不再重复显示清空遮罩或应用分类按钮、GT Mask 导入位于清空遮罩分隔线之后且使用紫色底色、工具栏分隔线位于创建圆后、AI自动推理后和清空遮罩后、GT Mask 未知类别导入策略选择、工作区工具栏不展示 AI 正/反点和框选、左侧工具栏不重复撤销/重做、左侧工具栏不展示创建点/创建线段、矩形/圆/多边形手工 mask 绘制且未选分类时默认待分类、普通/导入 polygon mask 不显示黄色 seed point、画笔/橡皮擦尺寸控制、画笔无选中时新建当前类别 mask、画笔/橡皮擦模式下保留当前选中 mask 顶点提示且只读、画笔从图外落笔不创建 mask、靠边画笔生成几何裁剪到当前帧边界内、橡皮擦从选中 mask 扣除、未选中 mask 时画布按语义分类树内部优先级渲染、多边形 Enter/首节点闭合、上下文提示提示 Enter/Esc/首节点闭合且数秒后自动隐藏、polygon 顶点直接拖动/删除、顶点拖拽结束不改变 Canvas 视口、边中点插点、双击边界按位置插点、多 polygon/分离区域全部显示编辑顶点、中空 mask 与中空画笔 mask 内洞 ring 顶点和插点可编辑、整块 mask 删除、DEL 和 Delete/Backspace 删除共用传播链范围确认、同帧传播链分散 mask 点选联动高亮、传播链自动传播 mask 随 seed/传播结果删除、独立 AI 推理 mask 不被误删、区域合并/去除存在传播帧时弹窗选择当前帧/所有传播帧/按帧范围选择、范围确认前重新开始当前帧布尔操作会取消旧顶栏范围请求、区域合并/去除按帧范围同步到对应传播帧且保留传播 metadata、布尔选择主区域/扣除区域视觉区分和选择顺序提示、内含去除 hole 渲染和 ring 分组保存、合并模式隐藏编辑手柄、工作区顶栏撤销/重做按钮、顶栏撤销/重做图标强调色、撤销/重做快捷键 Ctrl/Cmd+Z、Ctrl/Cmd+Shift+Z、Ctrl/Cmd+Y、物理键码 fallback 和输入框快捷键跳过、撤销/重做历史栈 |
| R6 AI 推理 | `src/lib/api.test.ts`, `src/components/CanvasArea.test.tsx`, `src/components/AISegmentation.test.tsx`, `src/components/VideoWorkspace.test.tsx`, `src/components/ModelStatusBadge.test.tsx`, `backend/tests/test_ai.py`, `backend/tests/test_sam2_engine.py` | SAM 2.1 变体选择、点/框/interactive 契约、semantic 禁用、SAM 3 入口隐藏和后端拒绝、SAM 2.1 最高分候选去重、SAM 2.1 框选后正负点细化同一候选 mask、AI 页框选发送 box prompt、AI 页框选后加点发送 interactive prompt、AI 页提示工具上下文提示、AI 页重复执行替换旧候选、SAM 2.1 反向点启用背景过滤且空结果移除旧候选、AI 页不渲染工作区已有 mask、AI 页可在候选 mask 上继续添加正/反点、AI 页可单点删除提示点并删除最近锚点、AI 页可删除选中候选且不删除工作区 mask、AI 页清空只移除本页候选、AI 页参数开关可读性文案且 options 字段不变、AI 页/右侧共享遮罩透明度只改预览 opacity、AI 页生成 mask 自动选中并可通过分类树换标签、AI 页无语义候选禁止推送到工作区并用 error toast 提示、离开 AI 页时清理未分类候选、AI 页推送到工作区编辑保留选择和当前帧、SAM 2.1 视频以当前参考帧全部 mask 和起止帧范围自动传播、同类多实例按来源 id 分开传播、当前参考帧无遮罩提示、传播前只保存参考帧 draft/dirty seed mask、传播前独立选择 SAM 2.1 tiny/small/base+/large 权重、自动传播创建 Celery 任务、传播入队权重 id 规范化/拒绝不支持 id、传播 seed 来源 id/签名和历史平滑 metadata 兼容、中空传播 seed 扣除 holes 后注入 SAM 2 且传播结果保留 holes、历史平滑 seed 保存前对 forward/backward polygon 实际应用边缘平滑并减少密集轮廓点、边缘平滑强度缓入递进曲线、未编辑传播结果作为 seed 时继承原始签名并跳过重复传播、已编辑传播结果保留 lineage 但重算签名并清理旧结果、中间帧人工新增替代 seed 时清理下游同物体旧传播结果、中间帧 backward 传播清理旧 forward 结果、换权重传播先清理旧结果、旧临时 seed id 传播结果兼容清理、传播中轮询任务进度、传播任务取消/重试、传播来源 metadata 回显、空提示/空结果反馈、GPU/SAM2.1 状态、AI 参数 options、局部裁剪推理、背景过滤、状态徽标、坐标归一化、正负点 labels、polygons 转 path、后端 fake registry |
@@ -34,7 +34,7 @@
|------|--------|----------|----------|
| R1 | 登录页、默认开发管理员、JWT 写入、当前用户写入、刷新恢复基础状态、失败提示、后端 401、`/api/auth/me`、管理员用户管理、角色权限、审计日志、演示出厂设置二次确认、重置后只保留 admin、演示视频项目和已生成帧的自然排序演示 DICOM 项目 | `Login.test.tsx`, `Sidebar.test.tsx`, `UserAdmin.test.tsx`, `useStore.test.ts`, `test_auth.py`, `test_admin.py` | 已覆盖 |
| R2 | 项目列表/创建/选择/重命名/复制、重命名时不触发生成帧、DICOM 不显示生成帧、项目复制 reset/full、项目按用户隔离、视频导入、DICOM 导入、DICOM 前端选择自然排序、后端项目和帧 CRUD | `ProjectLibrary.test.tsx`, `api.test.ts`, `test_projects.py` | 已覆盖 |
| R3 | 文件类型校验、自动/指定项目上传、视频导入与生成帧分离、视频/DICOM 上传进度可视化、DICOM 导入显示有效文件数量并在上传后持续显示解析任务进度、显式 FPS 生成帧、项目卡片 FPS 徽标显示 `parse_fps`、视频/DICOM 拆帧任务、DICOM 上传/下载/读取自然排序、非阻塞自动消失操作提示、`parse_fps/max_frames/target_width`、标准帧序列 metadata、任务查询、取消、重试、worker 取消停止 | `ProjectLibrary.test.tsx`, `TransientNotice.test.tsx`, `api.test.ts`, `test_media.py`, `test_tasks.py` | 已覆盖 |
| R3 | 文件类型校验、自动/指定项目上传、视频导入与生成帧分离、视频/DICOM 上传进度可视化、DICOM 导入显示有效文件数量并在上传后持续显示解析任务进度、显式 FPS 生成帧、视频生成帧完成后自动刷新项目封面、项目卡片 FPS 徽标显示 `parse_fps`、视频/DICOM 拆帧任务、DICOM 上传/下载/读取自然排序、非阻塞自动消失操作提示、`parse_fps/max_frames/target_width`、标准帧序列 metadata、任务查询、取消、重试、worker 取消停止 | `ProjectLibrary.test.tsx`, `TransientNotice.test.tsx`, `api.test.ts`, `test_media.py`, `test_tasks.py` | 已覆盖 |
| R4 | 工作区加载帧、无帧项目不自动解析、工作区短状态自动消失、后端标注回显保留本地未保存 draft mask、Canvas/AI 底图居中适配且保留边距、工作区 mask 透明度、选中 mask 后跨帧自动跟随同一传播链结果、左侧工具栏当前帧清空优先作用于选中 mask、无传播链时直接执行、有传播链时可选当前帧/传播所有帧/取消、清空人工/AI 标注帧前二次确认、取消确认不删除、仅自动传播帧不确认、删除单个传播 mask 后空帧不保留传播历史颜色、传播权重下拉深色可读配色、缩略图/range/视频处理进度条、视频处理进度条点击跳帧、人工/AI 标注帧红色竖线和标识点击跳帧、自动传播帧蓝色区段和标识点击跳帧、最近自动传播历史片段同一蓝色系按新旧递进显示,旧记录第 5 次后统一阈值色、当前帧白色贯穿线、传播范围洋红/黄绿色边界贯穿线、缩略图红/蓝边框、人工/AI 标注帧叠加传播状态时红框优先保留并显示蓝色内描边、当前人工/AI 标注帧青色外框加红色内描边、普通状态不显示传播范围黄色选区、播放进度条/视频处理进度条拖拽选择传播范围、Canvas/AI 画布拖拽平移回写 position state、左右方向键切帧、播放、按 FPS 显示时间 | `VideoWorkspace.test.tsx`, `FrameTimeline.test.tsx`, `CanvasArea.test.tsx`, `AISegmentation.test.tsx` | 已覆盖 |
| R5 | 工具切换、工具栏紧凑滚动布局、低对比滚动条、外扩滚动条槽位、调整多边形入口、清空遮罩唯一左侧入口、Canvas 右下角旧清空/应用分类按钮移除、GT Mask 导入入口位置和紫色底色、工作区工具栏隐藏 AI 正/反点和框选、左侧工具栏不重复撤销/重做、AI 跳转、矩形/圆/线/点/多边形绘制、已有 mask 上继续绘制、多边形和布尔工具上下文提示、Canvas 上下文提示数秒后自动隐藏 | `ToolsPalette.test.tsx`, `CanvasArea.test.tsx` | 已覆盖 |
| R5 | 顶点直接拖动编辑、顶点拖拽结束不改变 Canvas 视口、边中点插点、双击边界按位置插点、中空 mask 与中空画笔 mask 内洞 ring 顶点和插点可编辑、顶点删除、整块删除、删除传播链自动传播 mask 且保留独立 AI 推理 mask、工作区顶栏撤销/重做按钮、顶栏撤销/重做图标强调色、撤销/重做快捷键 Ctrl/Cmd+Z、Ctrl/Cmd+Shift+Z、Ctrl/Cmd+Y 和 KeyZ/KeyY fallback、区域合并、区域去除、布尔选择主区域黄色实线/扣除区域红色虚线、布尔选择顺序提示、hole even-odd 渲染 | `CanvasArea.test.tsx`, `VideoWorkspace.test.tsx`, `keyboardShortcuts.test.ts`, `useStore.test.ts` | 已覆盖 |

View File

@@ -96,7 +96,7 @@
| 交互 | 状态机 | 测试 |
|------|--------|------|
| 视频/DICOM 上传 | 选择文件后显示上传进度DICOM 显示有效文件数量;上传后继续轮询解析任务进度 | `ProjectLibrary.test.tsx` |
| 显式生成帧 | 只对视频项目显示项目名称编辑状态不显示DICOM 项目不显示 | `ProjectLibrary.test.tsx` |
| 显式生成帧 | 只对视频项目显示项目名称编辑状态不显示DICOM 项目不显示;入队后轮询解析任务,成功后刷新项目列表并立即显示新封面 | `ProjectLibrary.test.tsx` |
| GT Mask 导入 | 选择文件后预览并选择未知 maskid 策略;非法格式返回错误;尺寸不一致最近邻拉伸;导入结果与普通 mask 同体验 | `VideoWorkspace.test.tsx`、后端 AI 测试 |
| 分割结果导出 | 默认当前帧;可选整体/范围;范围可用时间轴;导出前保存待归档 mask按钮带导出图标和绿色强调背景 | `VideoWorkspace.test.tsx``api.test.ts`、后端导出测试 |