documents.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import math
  2. from typing import Literal, Optional
  3. from fastapi import APIRouter, Depends, Query
  4. from sqlalchemy.ext.asyncio import AsyncSession
  5. from app.api.v1 import ok
  6. from app.core.dependencies import get_db
  7. from app.schemas.document import (
  8. CreateDocumentRequest,
  9. DocumentListItem,
  10. DocumentResponse,
  11. Pagination,
  12. )
  13. from app.services.document_service import DocumentService
  14. router = APIRouter(prefix="/documents", tags=["Documents"])
  15. @router.post("", summary="创建文档(下载 Word 解析为 Blocks)")
  16. async def create_document(
  17. body: CreateDocumentRequest,
  18. db: AsyncSession = Depends(get_db),
  19. ) -> dict:
  20. svc = DocumentService(db)
  21. doc = await svc.create_document(body)
  22. return ok({
  23. "documentId": doc.id,
  24. "contentDbPath": doc.content_db_path,
  25. "createdAt": int(doc.created_at.timestamp() * 1000),
  26. })
  27. @router.get("", summary="获取文档列表")
  28. async def list_documents(
  29. userId: str = Query(...),
  30. page: int = Query(1, ge=1),
  31. pageSize: int = Query(20, ge=1, le=100),
  32. sessionId: Optional[str] = Query(None),
  33. sortBy: Literal["created_at", "updated_at"] = Query("updated_at"),
  34. sortOrder: Literal["asc", "desc"] = Query("desc"),
  35. db: AsyncSession = Depends(get_db),
  36. ) -> dict:
  37. svc = DocumentService(db)
  38. docs, total = await svc.list_documents(
  39. user_id=userId,
  40. page=page,
  41. page_size=pageSize,
  42. session_id=sessionId,
  43. sort_by=sortBy,
  44. sort_order=sortOrder,
  45. )
  46. items = [DocumentListItem.model_validate(d).model_dump(by_alias=True) for d in docs]
  47. pagination = Pagination(
  48. page=page,
  49. page_size=pageSize,
  50. total=total,
  51. total_pages=math.ceil(total / pageSize) if pageSize else 1,
  52. ).model_dump(by_alias=True)
  53. return ok({"documents": items, "pagination": pagination})
  54. @router.get("/{documentId}", summary="获取文档详情")
  55. async def get_document(
  56. documentId: str,
  57. includeBlocks: bool = Query(False, description="是否包含 blocks"),
  58. db: AsyncSession = Depends(get_db),
  59. ) -> dict:
  60. svc = DocumentService(db)
  61. doc = await svc.get_document(documentId, include_blocks=includeBlocks)
  62. # 构建响应数据
  63. data = {
  64. "id": doc.id,
  65. "contentDbPath": doc.content_db_path,
  66. "sessionId": doc.session_id,
  67. "userId": doc.created_by,
  68. "createdAt": int(doc.created_at.timestamp() * 1000),
  69. "updatedAt": int(doc.updated_at.timestamp() * 1000),
  70. }
  71. # 如果请求包含 blocks,则添加
  72. if includeBlocks and hasattr(doc, 'blocks'):
  73. data["blocks"] = doc.blocks
  74. return ok(data)
  75. @router.delete("/{sessionId}", summary="删除会话的所有文档")
  76. async def delete_documents_by_session(
  77. sessionId: str,
  78. db: AsyncSession = Depends(get_db),
  79. ) -> dict:
  80. svc = DocumentService(db)
  81. deleted_count = await svc.delete_documents_by_session(sessionId)
  82. return {"code": 0, "message": f"Deleted {deleted_count} document(s) successfully"}