diff --git a/apps/api/app/api/routes/templates_editor.py b/apps/api/app/api/routes/templates_editor.py index 1fb6ae6b7..58b5310c9 100644 --- a/apps/api/app/api/routes/templates_editor.py +++ b/apps/api/app/api/routes/templates_editor.py @@ -639,19 +639,84 @@ def get_draft_plan_id( template_id: str, services: tuple[EditTemplateService, EditPlanService] = Depends(get_editor_services), current_user: AuthenticatedUser = Depends(get_current_user), + db: Session = Depends(get_db_session), ) -> str: """ 路径依赖:根据 template_id 获取或创建草稿,返回 plan_id。 这是模板编辑器路由的核心依赖——所有编辑器端点都先经过这里, 确保 template_id → plan_id 的映射始终存在。 + + 兼容策略:优先从新模板系统(edit_templates 表)查找, + 若不存在则回退到旧模板系统(templates 表),确保用户自建模板可用。 """ - tpl_svc, _ = services - draft = tpl_svc.get_or_create_draft( - template_id, - user_id=str(current_user.user.id), + tpl_svc, plan_svc = services + user_id = str(current_user.user.id) + + # 1. 草稿已存在 → 直接返回 + draft = tpl_svc.get_template_draft(template_id) + if draft is not None: + return draft.id + + # 2. 新系统有模板 → 用新服务创建草稿 + if tpl_svc.get_template(template_id) is not None: + draft = tpl_svc.create_template_draft(template_id, user_id=user_id) + return draft.id + + # 3. 回退到旧模板系统(templates 表) + old_repo = SQLAlchemyTemplateRepository(db) + old_template = old_repo.get(template_id, user_id=user_id) + if old_template is None: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="模板不存在") + + # 4. 基于旧模板创建草稿计划 + from app.services.plan_generator_service import PlanGeneratorService + + from packages.domain.edit_template import EditTemplate, EditTemplateStatus + from packages.domain.template_clip_config import ClipType, TemplateClipConfig + + # 构造伪 EditTemplate 对象(只填 generate_from_template 需要的字段) + pseudo_template = EditTemplate( + id=old_template.id, + name=old_template.name, + editing_mode=old_template.mode, + status=EditTemplateStatus.ACTIVE, ) - return draft.id + + # 将旧模板 segments 转换为 clip_configs + clip_configs: list[TemplateClipConfig] = [] + for seg in old_template.segments or []: + clip_configs.append( + TemplateClipConfig( + id=f"seg_{seg.id}", + template_id=old_template.id, + clip_type=ClipType.MAIN, + order=seg.segment_order, + min_duration=seg.duration_min, + max_duration=seg.duration_max, + ) + ) + + generator = PlanGeneratorService(db) + result = generator.generate_from_template( + template=pseudo_template, + clip_configs=clip_configs, + asset_ids=[], + created_by_user_id=user_id, + name=f"{old_template.name} - 草稿", + ) + plan = result["plan"] + + # 标记为模板草稿(后续可复用 tpl_svc.get_template_draft 的查找逻辑) + plan_svc.update_plan_config(plan.id, {"is_template_draft": True}) + + logger.info( + "旧模板自动创建草稿: template_id=%s draft_plan_id=%s user_id=%s", + template_id, + plan.id, + user_id, + ) + return plan.id # ── 草稿核心端点 ────────────────────────────────────────────────────────────