fix: 模板不存在时降级为空计划,保持向后兼容 + black format
CI Build & Deploy Pipeline / Build Staging API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production API Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 11s
AI Code Review / AI Code Review (pull_request) Successful in 57s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 45s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 1m50s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m40s
Auto Approve CI PRs / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m19s
Auto Merge CI PRs / Auto Merge on CI Green + Approved (pull_request) Successful in 7m42s

This commit is contained in:
CI Bot
2026-07-17 12:24:20 +08:00
parent ce405e706d
commit bf56bcca5d
2 changed files with 43 additions and 22 deletions
+32 -17
View File
@@ -368,7 +368,8 @@ def create_plan(
"""创建剪辑计划
基于模板自动生成片段结构:
- 从模板的 clip_configs 生成初始 clips
- 模板存在时:从模板的 clip_configs 生成初始 clips
- 模板不存在时:降级为空计划(保持向后兼容)
- 用户传入的 config 与模板 config 合并(用户配置优先级更高)
- total_duration 自动根据 clips 总时长计算
"""
@@ -380,24 +381,39 @@ def create_plan(
if project_id:
check_project_access(project_id, current_user.user.id, project_repository)
template_svc = EditTemplateService(db)
# 校验模板存在
try:
template = template_svc.get_template_or_raise(body.template_id)
except ValueError as exc:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(exc),
) from exc
# 获取模板片段配置
clip_configs = template_svc.list_clip_configs(body.template_id, skip=0, limit=200)
# 标准化用户传入的 config
normalized_config = normalize_plan_config(body.config or {})
# 从模板生成剪辑计划(包含 clips)
template_svc = EditTemplateService(db)
svc = EditPlanService(db)
# 尝试从模板生成(模板不存在时降级为空计划)
template = None
clips = []
try:
template = template_svc.get_template_or_raise(body.template_id)
except ValueError:
# 模板不存在,降级为普通空计划
logger.info("模板不存在,创建空计划: template_id=%s", body.template_id)
plan = svc.create_plan(
template_id=body.template_id,
name=body.name,
config=normalized_config,
project_id=project_id,
created_by_user_id=current_user.user.id,
total_duration=body.total_duration if body.total_duration > 0 else 0.0,
)
logger.info(
"创建空剪辑计划: id=%s name=%s by user=%s",
plan.id,
plan.name,
current_user.user.id,
)
return _to_response(plan)
# 模板存在,从模板生成计划+片段
clip_configs = template_svc.list_clip_configs(body.template_id, skip=0, limit=200)
generator = PlanGeneratorService(db)
try:
result = generator.generate_from_template(
@@ -419,7 +435,6 @@ def create_plan(
# 如果用户传入了自定义 config,合并覆盖模板配置
if body.config:
svc = EditPlanService(db)
base_config = template.config or {}
merged_config = {**base_config, **normalized_config}
# 重新标准化确保默认值填充正确
+11 -5
View File
@@ -245,7 +245,9 @@ class TestCreatePlan:
mock_template_svc = MagicMock()
mock_template_svc.get_template_or_raise.return_value = MagicMock(
id="tpl-001", name="测试模板", config={},
id="tpl-001",
name="测试模板",
config={},
)
mock_template_svc.list_clip_configs.return_value = []
mock_template_svc_cls.return_value = mock_template_svc
@@ -273,12 +275,11 @@ class TestCreatePlan:
mock_gen.generate_from_template.assert_called_once()
@patch("app.api.routes.edit_plans.EditTemplateService")
def test_create_template_not_found_returns_400(self, mock_template_svc_cls, client):
"""模板不存在时返回 400"""
def test_create_template_not_found_falls_back_empty(self, mock_template_svc_cls, client):
"""模板不存在时降级为空计划(向后兼容)"""
c, repo = client
mock_template_svc = MagicMock()
from packages.domain.edit_template import EditTemplateStatus
mock_template_svc.get_template_or_raise.side_effect = ValueError("模板不存在")
mock_template_svc_cls.return_value = mock_template_svc
@@ -286,7 +287,12 @@ class TestCreatePlan:
"/api/v1/edit-plans",
json={"template_id": "nonexistent", "name": "测试"},
)
assert resp.status_code == 400
assert resp.status_code == 201
data = resp.json()
assert data["name"] == "测试"
assert data["template_id"] == "nonexistent"
# 空计划没有片段
assert "clips" not in data or len(data.get("clips", [])) == 0
def test_create_empty_name_returns_422(self, client):
c, repo = client