feat: generate-cover 支持 cover_type=upload + /generate 传递 custom_title/cover_url #1410

Merged
xiaoxia merged 4 commits from feat/upload-cover-and-title-in-generate into develop 2026-08-17 22:38:18 +08:00
Owner

改动

generate-cover 支持 cover_type=upload

  • GenerateCoverRequest 新增 cover_url 字段
  • cover_type=upload 时直接保存前端上传的封面图片 URL 到 plan config
  • 跳过预览视频查找,不需要预览视频也能设置封面

/generate 传递 custom_title 和 cover_url

  • 新增 EditPlanGenerateRequest 请求体(含 title_config 可选字段)
  • 从 plan.config.cover.image_url 读取封面 URL 传递给 CreateGenerationTaskCommand
  • title_config 序列化为 JSON 存入 custom_title 传递给 Worker
  • 标题变更时跳过预览产物复用,确保最终视频标题与前端预览一致

测试

  • 4 个新测试覆盖 upload 封面逻辑(test_generation_cover.py)
  • 3 个新测试覆盖 /generate 传递 title/cover(test_generate_title_and_cover.py)

关联

  • 后续任务:清理冗余的预览视频生成相关代码
  • 等待前端 Agent 完成 CSS 预览实现后联调验证
## 改动 ### generate-cover 支持 cover_type=upload - GenerateCoverRequest 新增 cover_url 字段 - cover_type=upload 时直接保存前端上传的封面图片 URL 到 plan config - 跳过预览视频查找,不需要预览视频也能设置封面 ### /generate 传递 custom_title 和 cover_url - 新增 EditPlanGenerateRequest 请求体(含 title_config 可选字段) - 从 plan.config.cover.image_url 读取封面 URL 传递给 CreateGenerationTaskCommand - title_config 序列化为 JSON 存入 custom_title 传递给 Worker - 标题变更时跳过预览产物复用,确保最终视频标题与前端预览一致 ### 测试 - 4 个新测试覆盖 upload 封面逻辑(test_generation_cover.py) - 3 个新测试覆盖 /generate 传递 title/cover(test_generate_title_and_cover.py) ## 关联 - 后续任务:清理冗余的预览视频生成相关代码 - 等待前端 Agent 完成 CSS 预览实现后联调验证
xiaoxia added 1 commit 2026-08-17 22:11:51 +08:00
feat: generate-cover 支持 cover_type=upload + /generate 传递 custom_title/cover_url
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 45s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m35s
AI Code Review / AI Code Review (pull_request) Failing after 1m38s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m45s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m49s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m11s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m15s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m29s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
81a8dc46c0
- GenerateCoverRequest 新增 cover_url 字段
- cover_type=upload 时直接保存前端上传的封面图片 URL 到 plan config,跳过预览视频查找
- /generate 端点新增 EditPlanGenerateRequest 请求体(含 title_config)
- 从 plan.config.cover.image_url 读取封面 URL 传递给 CreateGenerationTaskCommand
- title_config 序列化为 JSON 存入 custom_title 传递给 Worker
- 标题变更时跳过预览产物复用,确保最终视频标题与前端预览一致
- 新增 4+3=7 个单测覆盖

🚀 预览环境已部署

项目 详情
PR号 #1410
预览链接 https://pr-1410.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1410 | | 预览链接 | [https://pr-1410.preview.xiaoxiajianji.com](https://pr-1410.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia added 1 commit 2026-08-17 22:15:56 +08:00
fix: 标题移除场景跳过预览产物复用 + 2个新测试
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 44s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m34s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m39s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m41s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m56s
AI Code Review / AI Code Review (pull_request) Failing after 2m18s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m39s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m34s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 2m56s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m3s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
978d5743a5
AI Review 发现的逻辑 bug:当用户移除标题(原来有、现在没有)时,
代码没有跳过复用,导致生成的视频仍包含旧标题。

新增 elif not title_text_reuse and existing_custom_title 分支。
xiaoxia force-pushed feat/upload-cover-and-title-in-generate from f6068a5c0d to 978d5743a5 2026-08-17 22:15:56 +08:00 Compare
xiaoxia added 1 commit 2026-08-17 22:21:30 +08:00
fix(test): 修复 test_generate_title_and_cover mock get_plan_or_raise 调用次数
CI/CD Pipeline / Check if frontend-only change (pull_request) Failing after 1s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m14s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m38s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m39s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m18s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m31s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 3m45s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
164e96b935
side_effect 列表只有2个元素但函数调用3次,改用 return_value。
xiaoxia force-pushed feat/upload-cover-and-title-in-generate from 861913f977 to 164e96b935 2026-08-17 22:21:30 +08:00 Compare
auto-approve-bot added 1 commit 2026-08-17 22:26:07 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 46s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m27s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m44s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m44s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m48s
AI Code Review / AI Code Review (pull_request) Failing after 2m44s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m38s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m51s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 3m13s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m18s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 6m57s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m19s
CI/CD Pipeline / CI Gate (pull_request) Successful in 9s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 46s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 56s
77081f3cf0
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:是
  • 阻塞级问题数量:2 个

📊 审查概览

  • 整体评价:需修改
  • 建议级问题数量:2 个

🔴 阻塞级问题(必须修复)

  1. [apps/api/app/api/routes/generation_cover.py: 100] 潜在的 KeyError 异常风险

    • 问题类型:逻辑bug / 健壮性不足
    • 问题描述:代码直接通过 normalized["cover"] 访问字典键。如果 normalize_plan_config 函数内部逻辑严格(例如基于 Pydantic 模型验证),可能会过滤掉未在模型中定义的 cover 字段,导致此处抛出 KeyError,进而引发 500 错误。
    • 修改建议:建议使用 .get("cover") 安全访问,或者在调用 normalize_plan_config 前确认该函数支持保留 cover 字段。如果必须存在,应捕获异常或添加断言。
  2. [apps/api/app/api/routes/templates_editor/generation.py: 98] 标题复用逻辑存在键顺序敏感问题

    • 问题类型:逻辑bug
    • 问题描述:代码通过 json.dumps(title_config_reuse) 生成字符串并与数据库中的 existing_custom_title 进行对比。Python 3.7+ 虽然维护字典插入顺序,但如果前端传入的 JSON 字段顺序与数据库中存储的历史顺序不一致(例如 {"text": "a", "size": 1} vs {"size": 1, "text": "a"}),即使语义完全相同,字符串比较也会不相等,导致 reusable_task 被错误置空,从而触发不必要的重复渲染任务。
    • 修改建议:不要直接对比 JSON 字符串。应将数据库中的 existing_custom_title 反序列化为字典,然后对比两个字典对象;或者在序列化时使用 sort_keys=True 保证一致性。

💡 改进建议(不阻塞合并)

  1. [apps/api/app/api/routes/templates_editor/generation.py: 98, 191] JSON 序列化缺乏异常保护

    • 具体内容:title_config 的类型定义为 Dict[str, Any]。虽然通常前端传入的是标准 JSON 类型,但如果 Any 中混入了不可序列化的对象(如某些特殊类型的内部对象,尽管在标准 API 请求中较少见),json.dumps 会抛出 TypeError。建议添加 try-except 块捕获序列化异常,或者将 Schema 中的 Any 改为更具体的类型定义。
  2. [apps/api/app/api/routes/generation_cover.py: 52] 缺少 cover_url 格式校验

    • 具体内容:cover_url 字段仅定义为 Optional[str],没有添加 URL 格式校验或域名白名单校验。虽然注释说明是“上传的封面图片 URL”,但用户可篡改请求传入任意字符串(如 file:///etc/passwd 或内网地址)。如果后续渲染服务会请求此 URL,存在 SSRF(服务端请求伪造)风险。建议添加 Pydantic 的 HttpUrl 类型校验或自定义正则校验。

良好实践

  • generation.py 中添加了 request: Optional[...] = None 并通过 req = request or ... 处理,很好地保持了向后兼容性。
  • generation_cover.py 中对 cover_url 进行了截断处理([:80])再记录日志,防止日志过长,是个好习惯。
  • 单元测试覆盖了标题变更、移除、新增等多种场景,测试覆盖率较高。

🤖 由 AI 代码审查机器人自动生成 | 2026-08-17 14:28:51 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/api/app/api/routes/generation_cover.py: 100] 潜在的 KeyError 异常风险** - 问题类型:逻辑bug / 健壮性不足 - 问题描述:代码直接通过 `normalized["cover"]` 访问字典键。如果 `normalize_plan_config` 函数内部逻辑严格(例如基于 Pydantic 模型验证),可能会过滤掉未在模型中定义的 `cover` 字段,导致此处抛出 `KeyError`,进而引发 500 错误。 - 修改建议:建议使用 `.get("cover")` 安全访问,或者在调用 `normalize_plan_config` 前确认该函数支持保留 `cover` 字段。如果必须存在,应捕获异常或添加断言。 2. **[apps/api/app/api/routes/templates_editor/generation.py: 98] 标题复用逻辑存在键顺序敏感问题** - 问题类型:逻辑bug - 问题描述:代码通过 `json.dumps(title_config_reuse)` 生成字符串并与数据库中的 `existing_custom_title` 进行对比。Python 3.7+ 虽然维护字典插入顺序,但如果前端传入的 JSON 字段顺序与数据库中存储的历史顺序不一致(例如 `{"text": "a", "size": 1}` vs `{"size": 1, "text": "a"}`),即使语义完全相同,字符串比较也会不相等,导致 `reusable_task` 被错误置空,从而触发不必要的重复渲染任务。 - 修改建议:不要直接对比 JSON 字符串。应将数据库中的 `existing_custom_title` 反序列化为字典,然后对比两个字典对象;或者在序列化时使用 `sort_keys=True` 保证一致性。 ### 💡 改进建议(不阻塞合并) 1. **[apps/api/app/api/routes/templates_editor/generation.py: 98, 191] JSON 序列化缺乏异常保护** - 具体内容:`title_config` 的类型定义为 `Dict[str, Any]`。虽然通常前端传入的是标准 JSON 类型,但如果 `Any` 中混入了不可序列化的对象(如某些特殊类型的内部对象,尽管在标准 API 请求中较少见),`json.dumps` 会抛出 `TypeError`。建议添加 `try-except` 块捕获序列化异常,或者将 Schema 中的 `Any` 改为更具体的类型定义。 2. **[apps/api/app/api/routes/generation_cover.py: 52] 缺少 cover_url 格式校验** - 具体内容:`cover_url` 字段仅定义为 `Optional[str]`,没有添加 URL 格式校验或域名白名单校验。虽然注释说明是“上传的封面图片 URL”,但用户可篡改请求传入任意字符串(如 `file:///etc/passwd` 或内网地址)。如果后续渲染服务会请求此 URL,存在 SSRF(服务端请求伪造)风险。建议添加 Pydantic 的 `HttpUrl` 类型校验或自定义正则校验。 ### ✅ 良好实践 - 在 `generation.py` 中添加了 `request: Optional[...] = None` 并通过 `req = request or ...` 处理,很好地保持了向后兼容性。 - `generation_cover.py` 中对 `cover_url` 进行了截断处理(`[:80]`)再记录日志,防止日志过长,是个好习惯。 - 单元测试覆盖了标题变更、移除、新增等多种场景,测试覆盖率较高。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-17 14:28:51 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-08-17 22:35:32 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-08-17 22:35:32 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia merged commit 7cd76084e6 into develop 2026-08-17 22:38:18 +08:00

🗑️ 预览环境已清理

PR #1410 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1410 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.