diff --git a/video-gen-api/app/api/v1/generation.py b/video-gen-api/app/api/v1/generation.py index 620bffb4..9ead3b15 100644 --- a/video-gen-api/app/api/v1/generation.py +++ b/video-gen-api/app/api/v1/generation.py @@ -5,7 +5,7 @@ from datetime import datetime from fastapi import APIRouter, Depends, HTTPException, Query, Request, UploadFile, File, status from fastapi.responses import RedirectResponse -from sqlalchemy import select +from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from app.config import settings @@ -17,6 +17,7 @@ from app.schemas.generation import ( OptimizeParams, GenerateParams, GenerationRecordOut, + GenerationRecordPageListOut, OptimizeResult, UpdatePromptRequest, GenerationType, @@ -90,32 +91,89 @@ def _record_to_out(record: GenerationRecord, project_name: str) -> GenerationRec ) -@router.get("", response_model=list[GenerationRecordOut]) +@router.get("", response_model=GenerationRecordPageListOut) async def list_records( - project_id: str | None = Query(None, alias="project_id"), + project_id: str | None = Query( + None, + alias="project_id", + description="查询单个项目的生成记录", + ), + status: str | None = Query( + None, + description="查询状态,可以不传。prompt_optimized:待生成 | generating:生成中 | failed:失败 | completed:成功", + examples=["completed"], + ), + page: int = Query( + 1, + ge=1, + description="分页页码,从1开始", + examples=[1], + ), + page_size: int = Query( + 10, + ge=1, + le=100, + description="每页返回的生成记录数量,范围 1~100", + examples=[10], + ), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): + allowed_statuses = { + "prompt_optimized", + "generating", + "failed", + "completed", + } + + if status and status not in allowed_statuses: + raise HTTPException( + status_code=400, + detail="状态参数错误,仅支持:prompt_optimized、generating、failed、completed", + ) + + offset = (page - 1) * page_size + + conditions = [ + GenerationRecord.user_id == current_user.id, + GenerationRecord.deleted_at.is_(None), + Project.deleted_at.is_(None), + ] + + if project_id: + conditions.append(GenerationRecord.project_id == project_id) + + if status: + conditions.append(GenerationRecord.status == status) + + total_result = await db.execute( + select(func.count(GenerationRecord.id)) + .join(Project, GenerationRecord.project_id == Project.id) + .where(*conditions) + ) + total = total_result.scalar_one() or 0 + query = ( select(GenerationRecord, Project.name) .join(Project, GenerationRecord.project_id == Project.id) - .where( - GenerationRecord.user_id == current_user.id, - GenerationRecord.deleted_at.is_(None), - Project.deleted_at.is_(None), - ) + .where(*conditions) .order_by(GenerationRecord.created_at.desc()) + .offset(offset) + .limit(page_size) ) - if project_id: - query = query.where(GenerationRecord.project_id == project_id) result = await db.execute(query) rows = result.all() - return [ - _record_to_out(record, project_name) - for record, project_name in rows - ] + return { + "total": int(total), + "page": page, + "page_size": page_size, + "items": [ + _record_to_out(record, project_name) + for record, project_name in rows + ], + } @router.post("/optimize", response_model=OptimizeResult) async def optimize( diff --git a/video-gen-api/app/schemas/generation.py b/video-gen-api/app/schemas/generation.py index d04569df..83885fe5 100644 --- a/video-gen-api/app/schemas/generation.py +++ b/video-gen-api/app/schemas/generation.py @@ -48,7 +48,6 @@ class OptimizeResult(BaseModel): # text_tokens_used: int record: "GenerationRecordOut" - class GenerationRecordOut(BaseModel): id: str project_id: str @@ -78,6 +77,13 @@ class GenerationRecordOut(BaseModel): model_config = {"from_attributes": True} +class GenerationRecordPageListOut(BaseModel): + """生成记录分页返回API。""" + page: int = Field(..., description="当前日期分组分页页码") + page_size: int = Field(..., description="当前每页返回的日期分组数量") + total: int = Field(..., description="当前生成日期下的生成成功记录总数") + items: list[GenerationRecordOut] = Field(default_factory=list,) + class UpdatePromptRequest(BaseModel): optimized_prompt: str = Field(..., max_length=2000)