export_records.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. """export_records.py — 导出记录管理路由及管理端存储查询。"""
  2. import math
  3. from fastapi import APIRouter
  4. from fastapi.responses import FileResponse
  5. from app.core.database import AsyncSessionLocal
  6. from app.core.exceptions import RecordNotFoundError
  7. from app.services.export_record_service import ExportRecordService
  8. from app.services.storage_monitor import get_storage_info
  9. router = APIRouter(tags=["Export Records"])
  10. def _ok(data: dict) -> dict:
  11. return {"code": 0, "data": data}
  12. # ------------------------------------------------------------------ #
  13. # GET /export/records — 分页查询导出记录
  14. # ------------------------------------------------------------------ #
  15. @router.get("/export/records", summary="获取导出记录列表")
  16. async def list_export_records(
  17. userId: str,
  18. page: int = 1,
  19. pageSize: int = 20,
  20. sortOrder: str = "desc",
  21. ) -> dict:
  22. page = max(1, page)
  23. page_size = min(max(1, pageSize), 100)
  24. async with AsyncSessionLocal() as db:
  25. svc = ExportRecordService(db)
  26. records, total = await svc.list_records(
  27. user_id=userId,
  28. page=page,
  29. page_size=page_size,
  30. sort_order=sortOrder,
  31. )
  32. total_pages = math.ceil(total / page_size) if total > 0 else 1
  33. return _ok(
  34. {
  35. "records": [
  36. {
  37. "recordId": r.id,
  38. "userId": r.user_id,
  39. "fileName": r.file_name,
  40. "fileSize": r.file_size,
  41. "downloadUrl": r.download_url,
  42. "documentId": r.document_id,
  43. "styleId": r.style_id,
  44. "createdAt": int(r.created_at.timestamp() * 1000),
  45. }
  46. for r in records
  47. ],
  48. "pagination": {
  49. "page": page,
  50. "pageSize": page_size,
  51. "total": total,
  52. "totalPages": total_pages,
  53. },
  54. }
  55. )
  56. # ------------------------------------------------------------------ #
  57. # GET /export/records/{recordId}/download — 重新下载文件
  58. # ------------------------------------------------------------------ #
  59. @router.get("/export/records/{recordId}/download", summary="重新下载导出文件")
  60. async def download_export_record(recordId: str, userId: str) -> FileResponse:
  61. from pathlib import Path
  62. async with AsyncSessionLocal() as db:
  63. svc = ExportRecordService(db)
  64. record = await svc.get_record(recordId, userId)
  65. file_path = Path(record.file_path)
  66. if not file_path.exists():
  67. raise RecordNotFoundError(recordId)
  68. return FileResponse(
  69. path=str(file_path),
  70. filename=record.file_name,
  71. media_type="application/msword",
  72. )
  73. # ------------------------------------------------------------------ #
  74. # DELETE /export/records/{recordId} — 删除记录(同步删文件)
  75. # ------------------------------------------------------------------ #
  76. @router.delete("/export/records/{recordId}", summary="删除导出记录")
  77. async def delete_export_record(recordId: str, userId: str) -> dict:
  78. async with AsyncSessionLocal() as db:
  79. svc = ExportRecordService(db)
  80. await svc.delete_record(recordId, userId)
  81. return {"code": 0, "message": "Record deleted successfully"}
  82. # ------------------------------------------------------------------ #
  83. # GET /admin/storage — 管理端存储查询
  84. # ------------------------------------------------------------------ #
  85. @router.get("/admin/storage", summary="管理端:存储使用情况")
  86. async def admin_storage() -> dict:
  87. info = get_storage_info()
  88. return _ok(
  89. {
  90. "diskTotalBytes": info["disk_total_bytes"],
  91. "diskUsedBytes": info["disk_used_bytes"],
  92. "tmpTotalBytes": info["tmp_total_bytes"],
  93. "quotaBytes": info["quota_bytes"],
  94. "quotaExceeded": info["quota_exceeded"],
  95. "activeUsers": info["active_users"],
  96. "perUserQuotaBytes": info["per_user_quota_bytes"],
  97. "users": [
  98. {
  99. "userId": u["user_id"],
  100. "usedBytes": u["used_bytes"],
  101. "quotaExceeded": u["quota_exceeded"],
  102. }
  103. for u in info["users"]
  104. ],
  105. }
  106. )