From 53c6e66eaa5ae76a01abfc93b782bd49e10929c8 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Fri, 17 Jul 2026 15:53:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(api):=20create=5Fplan=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0asset=5Fids=E5=8F=82=E6=95=B0=E5=B9=B6?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E7=BB=99PlanGeneratorService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EditPlanCreateRequest增加asset_ids字段 - create_plan调用generate_from_template时传递body.asset_ids而非硬编码空数组 - asset_ids同时写入plan.config,供generate时兜底分配 - 新增test_create_with_asset_ids测试验证参数传递 --- apps/api/app/api/routes/edit_plans.py | 10 ++++++- tests/unit/test_edit_plans_api.py | 41 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/apps/api/app/api/routes/edit_plans.py b/apps/api/app/api/routes/edit_plans.py index de0a5c5bf..ec347a32a 100755 --- a/apps/api/app/api/routes/edit_plans.py +++ b/apps/api/app/api/routes/edit_plans.py @@ -50,6 +50,7 @@ class EditPlanCreateRequest(BaseModel): config: dict[str, Any] = Field(default_factory=dict, description="计划配置 (JSON)") total_duration: float = Field(default=0.0, ge=0.0, description="总时长 (秒)") project_id: str = Field(default="", description="所属项目 ID") + asset_ids: List[str] = Field(default_factory=list, description="素材 ID 列表,创建时自动分配给片段") class EditPlanUpdateRequest(BaseModel): @@ -419,7 +420,7 @@ def create_plan( result = generator.generate_from_template( template=template, clip_configs=clip_configs, - asset_ids=[], + asset_ids=body.asset_ids, project_id=project_id, created_by_user_id=current_user.user.id, name=body.name, @@ -445,6 +446,13 @@ def create_plan( total_duration=body.total_duration if body.total_duration > 0 else None, ) + # 把 asset_ids 写入 plan.config,供生成时兜底分配使用 + if body.asset_ids: + current_config = plan.config or {} + if current_config.get("asset_ids") != body.asset_ids: + current_config["asset_ids"] = body.asset_ids + plan = svc.update_plan(plan.id, config=normalize_plan_config(current_config)) + logger.info( "创建剪辑计划: id=%s name=%s clips=%d by user=%s", plan.id, diff --git a/tests/unit/test_edit_plans_api.py b/tests/unit/test_edit_plans_api.py index 3314a3ce8..5e44e6575 100755 --- a/tests/unit/test_edit_plans_api.py +++ b/tests/unit/test_edit_plans_api.py @@ -238,6 +238,47 @@ class TestCreatePlan: assert call_kwargs["name"] == "我的剪辑计划" assert call_kwargs["created_by_user_id"] == "user-001" + @patch("app.api.routes.edit_plans.EditTemplateService") + @patch("app.services.PlanGeneratorService") + def test_create_with_asset_ids(self, mock_generator_cls, mock_template_svc_cls, client): + """创建计划时传入 asset_ids,应传递给生成器并写入 plan.config""" + c, repo = client + + mock_template_svc = MagicMock() + mock_template_svc.get_template_or_raise.return_value = MagicMock( + id="tpl-001", + name="测试模板", + config={}, + ) + mock_template_svc.list_clip_configs.return_value = [] + mock_template_svc_cls.return_value = mock_template_svc + + mock_gen = MagicMock() + test_plan = self._make_test_plan(name="带素材计划") + test_plan.status = EditPlanStatus.EDITING + repo.create(test_plan) + mock_gen.generate_from_template.return_value = { + "plan": test_plan, + "clips": [], + } + mock_generator_cls.return_value = mock_gen + + asset_ids = ["asset-001", "asset-002", "asset-003"] + resp = c.post( + "/api/v1/edit-plans", + json={ + "template_id": "tpl-001", + "name": "带素材计划", + "asset_ids": asset_ids, + }, + ) + assert resp.status_code == 201 + + # 验证 asset_ids 传递给了生成器 + mock_gen.generate_from_template.assert_called_once() + call_kwargs = mock_gen.generate_from_template.call_args[1] + assert call_kwargs["asset_ids"] == asset_ids + @patch("app.api.routes.edit_plans.EditTemplateService") @patch("app.services.PlanGeneratorService") def test_create_minimal(self, mock_generator_cls, mock_template_svc_cls, client):