import math from typing import Literal, Optional from fastapi import APIRouter, Depends, Query from sqlalchemy.ext.asyncio import AsyncSession from app.api.v1 import ok from app.core.dependencies import get_db from app.schemas.document import ( CreateDocumentRequest, DocumentListItem, DocumentResponse, Pagination, ) from app.services.document_service import DocumentService router = APIRouter(prefix="/documents", tags=["Documents"]) @router.post("", summary="创建文档(下载 Word 解析为 Blocks)") async def create_document( body: CreateDocumentRequest, db: AsyncSession = Depends(get_db), ) -> dict: svc = DocumentService(db) doc = await svc.create_document(body) return ok({ "documentId": doc.id, "contentDbPath": doc.content_db_path, "createdAt": int(doc.created_at.timestamp() * 1000), }) @router.get("", summary="获取文档列表") async def list_documents( userId: str = Query(...), page: int = Query(1, ge=1), pageSize: int = Query(20, ge=1, le=100), sessionId: Optional[str] = Query(None), sortBy: Literal["created_at", "updated_at"] = Query("updated_at"), sortOrder: Literal["asc", "desc"] = Query("desc"), db: AsyncSession = Depends(get_db), ) -> dict: svc = DocumentService(db) docs, total = await svc.list_documents( user_id=userId, page=page, page_size=pageSize, session_id=sessionId, sort_by=sortBy, sort_order=sortOrder, ) items = [DocumentListItem.model_validate(d).model_dump(by_alias=True) for d in docs] pagination = Pagination( page=page, page_size=pageSize, total=total, total_pages=math.ceil(total / pageSize) if pageSize else 1, ).model_dump(by_alias=True) return ok({"documents": items, "pagination": pagination}) @router.get("/{documentId}", summary="获取文档详情") async def get_document( documentId: str, includeBlocks: bool = Query(False, description="是否包含 blocks"), db: AsyncSession = Depends(get_db), ) -> dict: svc = DocumentService(db) doc = await svc.get_document(documentId, include_blocks=includeBlocks) # 构建响应数据 data = { "id": doc.id, "contentDbPath": doc.content_db_path, "sessionId": doc.session_id, "userId": doc.created_by, "createdAt": int(doc.created_at.timestamp() * 1000), "updatedAt": int(doc.updated_at.timestamp() * 1000), } # 如果请求包含 blocks,则添加 if includeBlocks and hasattr(doc, 'blocks'): data["blocks"] = doc.blocks return ok(data) @router.delete("/{sessionId}", summary="删除会话的所有文档") async def delete_documents_by_session( sessionId: str, db: AsyncSession = Depends(get_db), ) -> dict: svc = DocumentService(db) deleted_count = await svc.delete_documents_by_session(sessionId) return {"code": 0, "message": f"Deleted {deleted_count} document(s) successfully"}