scheme.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import json
  2. from datetime import datetime
  3. from pathlib import Path
  4. from typing import Optional, Dict, Any, List
  5. from pydantic import BaseModel, field_validator, Field, field_serializer
  6. from enum import Enum
  7. class ImageType(str, Enum):
  8. front_coaxial = "front_coaxial"
  9. back_coaxial = "back_coaxial"
  10. front_ring = "front_ring"
  11. back_ring = "back_ring"
  12. # 灰度图类型
  13. front_gray = "front_gray"
  14. back_gray = "back_gray"
  15. # 融合图类型
  16. front_fusion = "front_fusion"
  17. back_fusion = "back_fusion"
  18. class ScoreType(str, Enum):
  19. front_corner_edge = "front_corner_edge"
  20. front_face = "front_face"
  21. front_face_ring_light = "front_face_ring_light"
  22. back_corner_edge = "back_corner_edge"
  23. back_face = "back_face"
  24. back_face_ring_light = "back_face_ring_light"
  25. class CardType(str, Enum):
  26. pokemon = "pokemon"
  27. basketball = "basketball"
  28. football = "football"
  29. class ResultImagePathType(str, Enum):
  30. detection = "detection"
  31. modified = "modified"
  32. class SortBy(str, Enum):
  33. card_name = "card_name"
  34. created_at = "created_at"
  35. updated_at = "updated_at"
  36. detection_score = "detection_score"
  37. modified_score = "modified_score"
  38. class SortOrder(str, Enum):
  39. asc = "ASC"
  40. desc = "DESC"
  41. class CardNoList(BaseModel):
  42. cardNoList: List[str]
  43. # 图片类型和推理服务 score_type 映射表
  44. IMAGE_TYPE_TO_SCORE_TYPE = {
  45. ImageType.front_coaxial.value: ScoreType.front_face.value,
  46. ImageType.back_coaxial.value: ScoreType.back_face.value,
  47. ImageType.front_ring.value: ScoreType.front_corner_edge.value,
  48. ImageType.back_ring.value: ScoreType.back_corner_edge.value,
  49. "front_gray": None,
  50. "back_gray": None,
  51. "front_fusion": None,
  52. "back_fusion": None
  53. }
  54. # --- Pydantic 数据模型 ---
  55. class CardImageResponse(BaseModel):
  56. """用于API响应的图片数据模型 (主键为 id)"""
  57. id: int
  58. card_id: int
  59. image_type: str
  60. image_name: Optional[str] = None
  61. image_path: str
  62. # Gray images need these fields to be Optional/None
  63. detection_image_path: Optional[str] = None
  64. modified_image_path: Optional[str] = None
  65. detection_json: Dict[str, Any]
  66. modified_json: Optional[Dict[str, Any]] = None
  67. is_edited: bool = False
  68. created_at: datetime
  69. updated_at: datetime
  70. class Config:
  71. from_attributes = True
  72. @field_validator('detection_json', 'modified_json', mode='before')
  73. @classmethod
  74. def parse_json_string(cls, v):
  75. if v is None:
  76. return None
  77. if isinstance(v, str):
  78. try:
  79. return json.loads(v)
  80. except json.JSONDecodeError:
  81. raise ValueError("Invalid JSON string in database")
  82. return v
  83. # 拦截序列化,格式化掉中间的 "T"
  84. @field_serializer('created_at', 'updated_at', check_fields=False)
  85. def serialize_datetime(self, dt: datetime, _info):
  86. if dt is not None:
  87. return dt.strftime('%Y-%m-%d %H:%M:%S')
  88. return dt
  89. class CardDetailResponse(BaseModel):
  90. """用于响应单个卡牌详细信息的模型 (主键为 id)"""
  91. id: int
  92. id_prev: Optional[int] = None
  93. id_next: Optional[int] = None
  94. card_name: Optional[str] = None
  95. cardNo: Optional[str] = None
  96. created_at: datetime
  97. updated_at: datetime
  98. card_type: str
  99. is_edited: bool
  100. review_state: int = 1
  101. detection_score: Optional[float] = None
  102. modified_score: Optional[float] = None
  103. detection_score_detail: Optional[Dict[str, Any]] = None
  104. modified_score_detail: Optional[Dict[str, Any]] = None
  105. images: List[CardImageResponse] = []
  106. class Config:
  107. from_attributes = True
  108. # 拦截序列化,格式化掉中间的 "T"
  109. @field_serializer('created_at', 'updated_at', check_fields=False)
  110. def serialize_datetime(self, dt: datetime, _info):
  111. if dt is not None:
  112. return dt.strftime('%Y-%m-%d %H:%M:%S')
  113. return dt
  114. class ImageJsonPairResponse(BaseModel):
  115. id: int
  116. detection_json: Dict[str, Any]
  117. modified_json: Optional[Dict[str, Any]] = None
  118. class Config:
  119. from_attributes = True
  120. @field_validator('detection_json', 'modified_json', mode='before')
  121. @classmethod
  122. def parse_json_string(cls, v):
  123. if v is None:
  124. return None
  125. if isinstance(v, str):
  126. try:
  127. return json.loads(v)
  128. except json.JSONDecodeError:
  129. raise ValueError("Invalid JSON string in database")
  130. return v
  131. class CardImageInListResponse(BaseModel):
  132. id: int
  133. image_type: str
  134. image_path: str
  135. detection_image_path: Optional[str] = None
  136. modified_image_path: Optional[str] = None
  137. class Config:
  138. from_attributes = True
  139. class CardListDetailResponse(BaseModel):
  140. id: int
  141. card_name: Optional[str] = None
  142. cardNo: Optional[str] = None
  143. card_type: str
  144. detection_score: Optional[float] = None
  145. modified_score: Optional[float] = None
  146. is_edited: bool
  147. review_state: int = 1
  148. created_at: datetime
  149. updated_at: datetime
  150. image_path_list: Dict[str, Optional[str]] = {}
  151. detection_image_path_list: Dict[str, Optional[str]] = {}
  152. modified_image_path_list: Dict[str, Optional[str]] = {}
  153. is_bound: bool = False
  154. class Config:
  155. from_attributes = True
  156. # 拦截序列化,格式化掉中间的 "T"
  157. @field_serializer('created_at', 'updated_at', check_fields=False)
  158. def serialize_datetime(self, dt: datetime, _info):
  159. if dt is not None:
  160. return dt.strftime('%Y-%m-%d %H:%M:%S')
  161. return dt
  162. class CardListWithTotal(BaseModel):
  163. total: int
  164. list: List[CardListDetailResponse]
  165. class CardListResponseWrapper(BaseModel):
  166. data: CardListWithTotal
  167. class ReviewUpdate(BaseModel):
  168. review_state: int = Field(..., ge=1, le=4, description="审核状态 (1待复检, 2已复检, 3审核未通过, 4审核通过)")
  169. class CardTable(BaseModel):
  170. id: int
  171. card_name: Optional[str] = None
  172. cardNo: Optional[str] = None
  173. card_type: str = "pokemon"
  174. detection_score: Optional[float] = None
  175. modified_score: Optional[float] = None
  176. is_edited: bool = False
  177. created_at: datetime
  178. updated_at: datetime
  179. review_state: int = 1
  180. class Config:
  181. from_attributes = True
  182. @field_serializer("created_at", "updated_at", check_fields=False)
  183. def serialize_datetime(self, dt: datetime, _info):
  184. if dt is not None:
  185. return dt.strftime("%Y-%m-%d %H:%M:%S")
  186. return dt
  187. class CardImageTable(BaseModel):
  188. id: int
  189. card_id: int
  190. image_type: str
  191. image_name: Optional[str] = None
  192. image_path: str
  193. detection_image_path: Optional[str] = None
  194. modified_image_path: Optional[str] = None
  195. detection_json: Dict[str, Any]
  196. modified_json: Optional[Dict[str, Any]] = None
  197. is_edited: bool = False
  198. created_at: datetime
  199. updated_at: datetime
  200. class Config:
  201. from_attributes = True
  202. @field_validator("detection_json", "modified_json", mode="before")
  203. @classmethod
  204. def parse_json_string(cls, v):
  205. if v is None:
  206. return None
  207. if isinstance(v, str):
  208. try:
  209. return json.loads(v)
  210. except json.JSONDecodeError:
  211. raise ValueError("Invalid JSON string in database")
  212. return v
  213. @field_serializer("created_at", "updated_at", check_fields=False)
  214. def serialize_datetime(self, dt: datetime, _info):
  215. if dt is not None:
  216. return dt.strftime("%Y-%m-%d %H:%M:%S")
  217. return dt
  218. class CardGrayImageTable(BaseModel):
  219. id: int
  220. card_id: int
  221. image_type: str
  222. image_path: str
  223. created_at: datetime
  224. updated_at: datetime
  225. class Config:
  226. from_attributes = True
  227. @field_serializer("created_at", "updated_at", check_fields=False)
  228. def serialize_datetime(self, dt: datetime, _info):
  229. if dt is not None:
  230. return dt.strftime("%Y-%m-%d %H:%M:%S")
  231. return dt