feat(task-2.14): 剪辑计划编辑器完整版 — 三栏布局 + 拖拽 + 素材面板 #145

Merged
xiaoxia merged 2 commits from feature/task-2.14-editing-planner-full into develop 2026-07-01 16:15:34 +08:00
Owner

任务 2.14:剪辑计划编辑器(完整版)

改动内容

  • 新增 editPlans API 模块(Mock 数据,预留真实接口)

    • EditPlan / EditPlanClip / MediaAsset 类型定义
    • CRUD: GET/POST/PUT /api/v1/edit-plans
    • 素材库: GET /api/v1/media-assets
    • 转场效果常量、素材类型图标映射
  • 新增 MediaPanel 组件(左侧面板)

    • Tab 切换:📂 模板 / 🎬 素材
    • 模板搜索 + 分类筛选
    • 素材搜索 + 类型筛选
    • 素材卡片支持 HTML5 拖拽(application/x-media-asset
  • 重写 TimelinePanel 组件(中间时间线)

    • 可视化时长条:按比例显示各片段彩色条
    • 片段卡片:序号徽标 + 文案预览 + 迷你时长条 + 转场标签
    • 内部拖拽排序(application/x-clip-index
    • 外部素材拖入接收(空状态拖放区 + 片段间插入指示器)
  • 新增 ClipPropertiesPanel 组件(右侧属性面板)

    • 未选中时:显示全局统计(总片段数/总时长)
    • 选中后:文案编辑、时长滑块、转场效果网格、素材关联
  • 升级 EditingPlanner 主页面

    • 三栏布局集成
    • 剪辑计划 CRUD(保存/更新)
    • 模板加载 → 自动转换为片段列表
    • 顶部工具栏:模式切换 + 模板名称 + 保存/生成按钮
  • 重写 EditingPlanner.css

    • 全新 V21 设计系统样式(690+ 行)
    • 响应式断点:1200px / 900px / 768px / 480px

验收标准

  • 时间线编辑(片段增删改、拖拽排序)
  • 素材拖拽(从素材库拖入时间线)
  • 保存/加载正常(剪辑计划 CRUD)
  • TypeScript 零错误
  • 响应式布局

技术细节

  • 使用 CSS 变量(全局设计系统),无硬编码颜色值
  • HTML5 原生 Drag-and-Drop API,无第三方拖拽库
  • React Query 管理数据缓存
  • Mock 数据与真实 API 接口隔离,后续迁移只需替换 queryFn
## 任务 2.14:剪辑计划编辑器(完整版) ### 改动内容 - **新增 `editPlans` API 模块**(Mock 数据,预留真实接口) - EditPlan / EditPlanClip / MediaAsset 类型定义 - CRUD: GET/POST/PUT /api/v1/edit-plans - 素材库: GET /api/v1/media-assets - 转场效果常量、素材类型图标映射 - **新增 MediaPanel 组件**(左侧面板) - Tab 切换:📂 模板 / 🎬 素材 - 模板搜索 + 分类筛选 - 素材搜索 + 类型筛选 - 素材卡片支持 HTML5 拖拽(`application/x-media-asset`) - **重写 TimelinePanel 组件**(中间时间线) - 可视化时长条:按比例显示各片段彩色条 - 片段卡片:序号徽标 + 文案预览 + 迷你时长条 + 转场标签 - 内部拖拽排序(`application/x-clip-index`) - 外部素材拖入接收(空状态拖放区 + 片段间插入指示器) - **新增 ClipPropertiesPanel 组件**(右侧属性面板) - 未选中时:显示全局统计(总片段数/总时长) - 选中后:文案编辑、时长滑块、转场效果网格、素材关联 - **升级 EditingPlanner 主页面** - 三栏布局集成 - 剪辑计划 CRUD(保存/更新) - 模板加载 → 自动转换为片段列表 - 顶部工具栏:模式切换 + 模板名称 + 保存/生成按钮 - **重写 EditingPlanner.css** - 全新 V21 设计系统样式(690+ 行) - 响应式断点:1200px / 900px / 768px / 480px ### 验收标准 - ✅ 时间线编辑(片段增删改、拖拽排序) - ✅ 素材拖拽(从素材库拖入时间线) - ✅ 保存/加载正常(剪辑计划 CRUD) - ✅ TypeScript 零错误 - ✅ 响应式布局 ### 技术细节 - 使用 CSS 变量(全局设计系统),无硬编码颜色值 - HTML5 原生 Drag-and-Drop API,无第三方拖拽库 - React Query 管理数据缓存 - Mock 数据与真实 API 接口隔离,后续迁移只需替换 queryFn
xiaoxia added 1 commit 2026-07-01 14:48:13 +08:00
feat(phase8): 实现剪辑计划 CRUD API (任务 2.04)
Deploy / Build Production Runtime Images (push) Has been skipped
Deploy / Deploy Production (push) Has been skipped
Deploy / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 189h51m12s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 189h51m15s
Deploy / Deploy Staging (push) Failing after 189h51m46s
CI/CD Pipeline / Frontend Lint (push) Failing after 189h52m16s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 189h52m19s
2730d2ce8d
- 新增 /api/v1/edit-plans 五个端点 (GET list/detail, POST, PUT, DELETE)
- 支持分页、按模板ID/状态筛选
- PUT 端点集成状态机流转 (draft→editing→rendering→completed/failed)
- 非法状态流转返回 400,资源不存在返回 404
- 注册 edit_plans_router 到 API Router
- 编写 28 个单元测试覆盖 CRUD + 状态机 + 异常场景
- 全部测试通过
xiaoxia added 1 commit 2026-07-01 15:04:03 +08:00
feat(task-2.14): 剪辑计划编辑器完整版 — 三栏布局 + 拖拽 + 素材面板
Deploy / Build Production Runtime Images (push) Has been skipped
Deploy / Deploy Production (push) Has been skipped
Deploy / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 189h47m20s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 189h47m22s
Deploy / Deploy Staging (push) Failing after 189h47m51s
CI/CD Pipeline / Frontend Lint (push) Failing after 189h48m17s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 189h48m22s
16bf124a60
- 新增 editPlans API 模块(Mock 数据,预留真实接口)
- 新增 MediaPanel 组件:左侧 Tab 切换(模板+素材),素材可拖拽
- 重写 TimelinePanel:可视化时长条 + 片段卡片 + 拖拽排序 + 素材接收
- 新增 ClipPropertiesPanel:右侧片段属性编辑(文案/时长/转场/素材关联)
- 升级 EditingPlanner 主页面:集成三栏布局 + 剪辑计划 CRUD
- 重写 EditingPlanner.css:全新 V21 设计系统样式 + 响应式适配
- 修复 TypeScript 类型错误

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xiaoxia changed title from feat(phase8): 任务 2.04 — 剪辑计划 CRUD API to feat(task-2.14): 剪辑计划编辑器完整版 — 三栏布局 + 拖拽 + 素材面板 2026-07-01 15:06:40 +08:00
Author
Owner

代码审查结果: 通过

PR #145 — feat(phase8): 任务 2.04 — 剪辑计划 CRUD API + 任务 2.14 前端编辑器重构
变更: 9 文件,+2733/-578
分支: feature/task-2.14-editing-planner-fulldevelop
审查范围: 后端 API (304行) + 前端 API 层 (336行) + 编辑器重构 (CSS/TSX/组件) + 测试 (496行)


👍 优点

后端 API (edit_plans.py)

  1. RESTful 设计规范 — 5 个端点 (GET list/detail, POST create, PUT update, DELETE) HTTP 方法和状态码正确 (201/204/400/404/422)
  2. Pydantic Schema 分离 — CreateRequest/UpdateRequest/Response/ListResponse 职责清晰
  3. 状态机集成优雅_apply_status_transition() 使用 transition_map 将目标状态映射到领域方法,非法流转自动抛 ValueError → 400
  4. 分页 + 筛选完整 — page/page_size + status_filter (alias="status") + template_id
  5. 日志规范 — create/update/delete 均记录 entity id + user id
  6. 28 个测试覆盖充分 — 创建(5) + 列表(7) + 详情(2) + 更新(12) + 删除(2),覆盖正常/异常/边界路径
  7. 状态机流转测试完善 — 完整 happy path (draft→editing→rendering→completed) + failure reset (failed→draft) + 非法跳转 400 + 同状态 noop

前端编辑器重构
8. 组件架构升级 — 三栏布局重构为 MediaPanel(素材+模板 Tab) / TimelinePanel(时间线) / ClipPropertiesPanel(片段属性),职责清晰
9. 拖拽交互完整 — 素材从左侧拖入时间线、片段间拖拽排序、拖放指示器动画
10. CSS 变量全覆盖 — 无硬编码颜色,响应式三级断点 (1200/768/480)
11. 可视化时长条 — 按比例显示片段时长,颜色区分,hover 缩放效果
12. 前端 API 层规范 — TypeScript 类型完整,Mock + TODO 注释清晰,常量集中管理


🔧 建议

P2-1:list_plans 按 template_id 筛选时全量查询计算 total

# edit_plans.py L160-167
if template_id:
    plans = repo.list_by_template(template_id, status=status_enum, skip=skip, limit=page_size)
    # count() 不支持 template_id 筛选,通过全量查询计算 total
    all_matching = repo.list_by_template(template_id, status=status_enum, skip=0, limit=10000)
    total = len(all_matching)

查两次数据库,第二次拉取最多 10000 条只为算 count。测试中的 StubEditPlanRepository.count() 已支持 template_id 参数,说明接口已具备。建议:

# 扩展 SQLAlchemyEditPlanRepository.count() 支持 template_id 参数
total = repo.count(template_id=template_id, status=status_enum)
plans = repo.list_by_template(template_id, status=status_enum, skip=skip, limit=page_size)

这样只需一次查询。

P2-2:handleSave 同时保存剪辑计划 + 模板,存在部分失败风险

// EditingPlanner.tsx handleSave()
if (editPlanId) {
  updatePlanMutation.mutate({ ... });
} else {
  savePlanMutation.mutate({ ... });
}
// 同时保存模板
if (loadedTemplateId) {
  updateMutation.mutate({ ... });  // 两个 mutation 同时触发
}

用户点击「保存」可能同时触发两个 API 调用(剪辑计划 + 模板),一个成功一个失败时状态不一致。建议后续拆分为明确的「保存计划」和「保存模板」操作,或使用 Promise.all + 错误回滚。

P3-1:_to_response hasattr 可简化

status=p.status.value if hasattr(p.status, "value") else p.status,

EditPlan 领域实体的 status 应为 EditPlanStatus 枚举,hasattr 检查不必要。与 PR #144 同模式,建议后续统一清理。

P3-2:delete_plan 使用硬删除,与 edit_templates 软删除不一致
edit_templates (PR #144) 使用 deactivate() 软删除,edit_plans 使用 repo.delete() 硬删除。如为有意设计(剪辑计划无需回收站),建议加注释说明。

P3-3:handleAssetDragStart 为空函数

const handleAssetDragStart = useCallback((_asset: MediaAsset) => {
  // 素材拖拽开始时的回调(可用于高亮时间线等)
}, []);

TODO 占位可接受,建议后续任务中实现或移除。


📊 审查总结

维度 评分 说明
后端 API 设计 RESTful 规范、状态码正确、Schema 分离
状态机集成 transition_map 优雅、非法流转 400、同状态 noop
前端架构 组件拆分合理、拖拽交互完整,双保存耦合待优化
CSS 规范 变量全覆盖、三级响应式、动效得当
测试覆盖 28 用例,正常/异常/边界全覆盖

结论: 通过,可合并到 develop。 2 个 P2 建议(list_plans N+1 查询、双保存逻辑)建议在后续迭代中优化。

## 代码审查结果:✅ 通过 **PR #145** — feat(phase8): 任务 2.04 — 剪辑计划 CRUD API + 任务 2.14 前端编辑器重构 **变更**: 9 文件,+2733/-578 **分支**: `feature/task-2.14-editing-planner-full` → `develop` **审查范围**: 后端 API (304行) + 前端 API 层 (336行) + 编辑器重构 (CSS/TSX/组件) + 测试 (496行) --- ### 👍 优点 **后端 API (edit_plans.py)** 1. **RESTful 设计规范** — 5 个端点 (GET list/detail, POST create, PUT update, DELETE) HTTP 方法和状态码正确 (201/204/400/404/422) 2. **Pydantic Schema 分离** — CreateRequest/UpdateRequest/Response/ListResponse 职责清晰 3. **状态机集成优雅** — `_apply_status_transition()` 使用 transition_map 将目标状态映射到领域方法,非法流转自动抛 ValueError → 400 4. **分页 + 筛选完整** — page/page_size + status_filter (alias="status") + template_id 5. **日志规范** — create/update/delete 均记录 entity id + user id 6. **28 个测试覆盖充分** — 创建(5) + 列表(7) + 详情(2) + 更新(12) + 删除(2),覆盖正常/异常/边界路径 7. **状态机流转测试完善** — 完整 happy path (draft→editing→rendering→completed) + failure reset (failed→draft) + 非法跳转 400 + 同状态 noop **前端编辑器重构** 8. **组件架构升级** — 三栏布局重构为 MediaPanel(素材+模板 Tab) / TimelinePanel(时间线) / ClipPropertiesPanel(片段属性),职责清晰 9. **拖拽交互完整** — 素材从左侧拖入时间线、片段间拖拽排序、拖放指示器动画 10. **CSS 变量全覆盖** — 无硬编码颜色,响应式三级断点 (1200/768/480) 11. **可视化时长条** — 按比例显示片段时长,颜色区分,hover 缩放效果 12. **前端 API 层规范** — TypeScript 类型完整,Mock + TODO 注释清晰,常量集中管理 --- ### 🔧 建议 **P2-1:list_plans 按 template_id 筛选时全量查询计算 total** ```python # edit_plans.py L160-167 if template_id: plans = repo.list_by_template(template_id, status=status_enum, skip=skip, limit=page_size) # count() 不支持 template_id 筛选,通过全量查询计算 total all_matching = repo.list_by_template(template_id, status=status_enum, skip=0, limit=10000) total = len(all_matching) ``` 查两次数据库,第二次拉取最多 10000 条只为算 count。测试中的 StubEditPlanRepository.count() 已支持 `template_id` 参数,说明接口已具备。建议: ```python # 扩展 SQLAlchemyEditPlanRepository.count() 支持 template_id 参数 total = repo.count(template_id=template_id, status=status_enum) plans = repo.list_by_template(template_id, status=status_enum, skip=skip, limit=page_size) ``` 这样只需一次查询。 **P2-2:handleSave 同时保存剪辑计划 + 模板,存在部分失败风险** ```typescript // EditingPlanner.tsx handleSave() if (editPlanId) { updatePlanMutation.mutate({ ... }); } else { savePlanMutation.mutate({ ... }); } // 同时保存模板 if (loadedTemplateId) { updateMutation.mutate({ ... }); // 两个 mutation 同时触发 } ``` 用户点击「保存」可能同时触发两个 API 调用(剪辑计划 + 模板),一个成功一个失败时状态不一致。建议后续拆分为明确的「保存计划」和「保存模板」操作,或使用 `Promise.all` + 错误回滚。 **P3-1:_to_response hasattr 可简化** ```python status=p.status.value if hasattr(p.status, "value") else p.status, ``` EditPlan 领域实体的 status 应为 EditPlanStatus 枚举,hasattr 检查不必要。与 PR #144 同模式,建议后续统一清理。 **P3-2:delete_plan 使用硬删除,与 edit_templates 软删除不一致** edit_templates (PR #144) 使用 `deactivate()` 软删除,edit_plans 使用 `repo.delete()` 硬删除。如为有意设计(剪辑计划无需回收站),建议加注释说明。 **P3-3:handleAssetDragStart 为空函数** ```typescript const handleAssetDragStart = useCallback((_asset: MediaAsset) => { // 素材拖拽开始时的回调(可用于高亮时间线等) }, []); ``` TODO 占位可接受,建议后续任务中实现或移除。 --- ### 📊 审查总结 | 维度 | 评分 | 说明 | |------|------|------| | 后端 API 设计 | ⭐⭐⭐⭐⭐ | RESTful 规范、状态码正确、Schema 分离 | | 状态机集成 | ⭐⭐⭐⭐⭐ | transition_map 优雅、非法流转 400、同状态 noop | | 前端架构 | ⭐⭐⭐⭐ | 组件拆分合理、拖拽交互完整,双保存耦合待优化 | | CSS 规范 | ⭐⭐⭐⭐⭐ | 变量全覆盖、三级响应式、动效得当 | | 测试覆盖 | ⭐⭐⭐⭐⭐ | 28 用例,正常/异常/边界全覆盖 | **结论:✅ 通过,可合并到 develop。** 2 个 P2 建议(list_plans N+1 查询、双保存逻辑)建议在后续迭代中优化。
xiaoxia merged commit d7120562f9 into develop 2026-07-01 16:15:34 +08:00
Sign in to join this conversation.