models.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. """Pydantic 数据模型"""
  2. from datetime import datetime
  3. from typing import Any
  4. from pydantic import BaseModel, Field
  5. # ── 题目 ─────────────────────────────────────────────────
  6. class ProblemBase(BaseModel):
  7. difficulty: float = Field(default=0.5, ge=0.0, le=1.0)
  8. question_type: str = ""
  9. import_type: str = "精选题"
  10. knowledge_codes: list[str] = Field(default_factory=list)
  11. comment: str = ""
  12. source: str = ""
  13. class ProblemSummary(BaseModel):
  14. id: str
  15. difficulty: float
  16. question_type: str
  17. import_type: str
  18. chapters: list[str] = []
  19. knowledge_codes: list[str] = []
  20. comment: str = ""
  21. source: str = ""
  22. created_at: str = ""
  23. updated_at: str = ""
  24. class ProblemDetail(ProblemSummary):
  25. render_html: str | None = None
  26. metadata_html: str | None = None # 答案区 HTML
  27. class ProblemUpdate(BaseModel):
  28. difficulty: float | None = None
  29. question_type: str | None = None
  30. import_type: str | None = None
  31. comment: str | None = None
  32. class KnowledgeUpdate(BaseModel):
  33. knowledge_codes: list[str]
  34. # ── 分页 ─────────────────────────────────────────────────
  35. class PaginatedResponse(BaseModel):
  36. items: list[dict]
  37. total: int
  38. page: int
  39. page_size: int
  40. # ── 统计 ─────────────────────────────────────────────────
  41. class StatsResponse(BaseModel):
  42. total: int
  43. by_question_type: dict[str, int]
  44. by_import_type: dict[str, int]
  45. by_chapter: dict[str, int]
  46. # ── 搜索 ────────────────────────────────────────────────
  47. class SearchResult(BaseModel):
  48. id: str
  49. body_snippet: str = ""
  50. difficulty: float = 0.5
  51. question_type: str = ""
  52. import_type: str = ""
  53. chapters: list[str] = []
  54. # ── 导入 ─────────────────────────────────────────────────
  55. class ImportTaskStatus(BaseModel):
  56. id: str
  57. status: str
  58. total: int
  59. completed: int
  60. message: str
  61. result: Any = {}
  62. # ── 试题篮 ───────────────────────────────────────────────
  63. class CartCreate(BaseModel):
  64. name: str
  65. class CartSummary(BaseModel):
  66. id: int
  67. name: str
  68. item_count: int
  69. created_at: str = ""
  70. class CartDetail(CartSummary):
  71. items: list[ProblemSummary] = []
  72. # ── 导出 ─────────────────────────────────────────────────
  73. class ExportRequest(BaseModel):
  74. chapter: str | None = None
  75. import_type: str | None = None
  76. cart_id: int | None = None
  77. title: str | None = None
  78. # ── 知识点 ───────────────────────────────────────────────
  79. class KnowledgeNode(BaseModel):
  80. code: str
  81. path: str
  82. leaf_name: str
  83. chapter_code: str = ""
  84. chapter_name: str = ""
  85. # ── 认证 ─────────────────────────────────────────────────
  86. class TokenVerify(BaseModel):
  87. token: str
  88. # ── WebDAV 配置 ──────────────────────────────────────────
  89. class WebDAVConfig(BaseModel):
  90. url: str
  91. username: str
  92. password: str
  93. remote_path: str = "/tiku-backup"
  94. # ── API 错误 ─────────────────────────────────────────────
  95. class APIError(BaseModel):
  96. error: dict # {"code": "xxx", "message": "..."}