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
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:
@@ -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}
|
||||
# 重新标准化确保默认值填充正确
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user