diff --git a/apps/api/app/api/routes/drafts_standalone.py b/apps/api/app/api/routes/drafts_standalone.py new file mode 100644 index 000000000..0327c1a10 --- /dev/null +++ b/apps/api/app/api/routes/drafts_standalone.py @@ -0,0 +1,103 @@ +"""独立的草稿端点(不依赖 template_id 路径参数,兼容旧前端路径). + +提供以下别名端点,与 /api/v1/templates/{template_id}/editor/draft 功能一致: +- GET /api/v1/editor/drafts 获取草稿详情(template_id 从 query/body/默认模板兜底) +- PUT /api/v1/editor/drafts 更新草稿(兼容前端 useDraftAutoSave 调用) + +根因:前端 useDraftAutoSave 调用 /api/v1/editor/drafts(复数、无 template_id), +与后端以 template_id 为路径参数的设计不一致,导致 404 并触发 10s timeout。 +本模块参照 clips_standalone.py 的模式,通过默认模板兜底复用 draft.py 的核心逻辑。 +""" + +from __future__ import annotations + +import logging + +from fastapi import APIRouter, Depends, HTTPException, Query, status +from sqlalchemy.orm import Session + +from app.auth import AuthenticatedUser, get_current_user +from app.dependencies import get_db_session +from app.services.edit_plan_service import EditPlanService +from app.services.edit_template_service import EditTemplateService + +from ._default_template import get_or_create_default_template_id +from .templates_editor.dependencies import resolve_draft_plan_id +from .templates_editor.draft import get_editor_draft, update_editor_draft +from .templates_editor.schemas import EditorDraftResponse, EditorUpdateRequest + +logger = logging.getLogger(__name__) +router = APIRouter(tags=["Editor Legacy Alias"]) + + +def _resolve_editor_services(db: Session) -> tuple[EditTemplateService, EditPlanService]: + return EditTemplateService(db), EditPlanService(db) + + +def _resolve_template_id( + template_id: str | None, + db: Session, + current_user: AuthenticatedUser, +) -> str: + """解析 template_id:query/body 优先,否则兜底默认模板。""" + tid = (template_id or "").strip() + if tid: + return tid + user_id = str(current_user.user.id) + tid = get_or_create_default_template_id(db, user_id) + if not tid: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="无法自动创建默认模板,请刷新页面重试", + ) + return tid + + +@router.get("/drafts", response_model=EditorDraftResponse) +def get_editor_drafts_alias( + template_id: str | None = Query(default=None, description="模板ID,不传则兜底默认模板"), + db: Session = Depends(get_db_session), + current_user: AuthenticatedUser = Depends(get_current_user), +) -> EditorDraftResponse: + """获取草稿详情(复数路径别名,兼容旧前端调用)。""" + tid = _resolve_template_id(template_id, db, current_user) + services = _resolve_editor_services(db) + plan_id = resolve_draft_plan_id( + template_id=tid, + services=services, + current_user=current_user, + db=db, + auto_create_default=False, + ) + return get_editor_draft( + template_id=tid, + plan_id=plan_id, + services=services, + _=current_user, + ) + + +@router.put("/drafts", response_model=EditorDraftResponse) +def update_editor_drafts_alias( + req: EditorUpdateRequest, + template_id: str | None = Query(default=None, description="模板ID,不传则兜底默认模板"), + db: Session = Depends(get_db_session), + current_user: AuthenticatedUser = Depends(get_current_user), +) -> EditorDraftResponse: + """更新草稿(复数路径别名,兼容前端 useDraftAutoSave 调用)。""" + tid = _resolve_template_id(template_id, db, current_user) + services = _resolve_editor_services(db) + plan_id = resolve_draft_plan_id( + template_id=tid, + services=services, + current_user=current_user, + db=db, + auto_create_default=False, + ) + return update_editor_draft( + template_id=tid, + req=req, + plan_id=plan_id, + services=services, + _=current_user, + )