scheme.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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
  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. class CardType(str, Enum):
  16. pokemon = "pokemon"
  17. basketball = "basketball"
  18. baseball = "baseball"
  19. class ResultImagePathType(str, Enum):
  20. detection = "detection"
  21. modified = "modified"
  22. class SortBy(str, Enum):
  23. card_name = "card_name"
  24. created_at = "created_at"
  25. updated_at = "updated_at"
  26. detection_score = "detection_score"
  27. modified_score = "modified_score"
  28. class SortOrder(str, Enum):
  29. asc = "ASC"
  30. desc = "DESC"
  31. # "图片类型和计算分数分数类型映射表"
  32. # [CHANGED] 更新映射关系以匹配 score_service.py
  33. IMAGE_TYPE_TO_SCORE_TYPE = {
  34. "front_coaxial": "front_coaxial",
  35. "back_coaxial": "back_coaxial",
  36. "front_ring": "front_ring",
  37. "back_ring": "back_ring",
  38. "front_gray": None,
  39. "back_gray": None
  40. }
  41. # --- Pydantic 数据模型 ---
  42. class CardImageResponse(BaseModel):
  43. """用于API响应的图片数据模型 (主键为 id)"""
  44. id: int
  45. card_id: int
  46. image_type: str
  47. image_name: Optional[str] = None
  48. image_path: str
  49. # Gray images need these fields to be Optional/None
  50. detection_image_path: Optional[str] = None
  51. modified_image_path: Optional[str] = None
  52. detection_json: Dict[str, Any]
  53. modified_json: Optional[Dict[str, Any]] = None
  54. is_edited: bool = False
  55. created_at: datetime
  56. updated_at: datetime
  57. class Config:
  58. from_attributes = True
  59. @field_validator('detection_json', 'modified_json', mode='before')
  60. @classmethod
  61. def parse_json_string(cls, v):
  62. if v is None:
  63. return None
  64. if isinstance(v, str):
  65. try:
  66. return json.loads(v)
  67. except json.JSONDecodeError:
  68. raise ValueError("Invalid JSON string in database")
  69. return v
  70. class CardDetailResponse(BaseModel):
  71. """用于响应单个卡牌详细信息的模型 (主键为 id)"""
  72. id: int
  73. id_prev: Optional[int] = None
  74. id_next: Optional[int] = None
  75. card_name: Optional[str] = None
  76. cardNo: Optional[str] = None
  77. created_at: datetime
  78. updated_at: datetime
  79. card_type: str
  80. is_edited: bool
  81. detection_score: Optional[float] = None
  82. modified_score: Optional[float] = None
  83. detection_score_detail: Optional[Dict[str, Any]] = None
  84. modified_score_detail: Optional[Dict[str, Any]] = None
  85. images: List[CardImageResponse] = []
  86. class Config:
  87. from_attributes = True
  88. class ImageJsonPairResponse(BaseModel):
  89. id: int
  90. detection_json: Dict[str, Any]
  91. modified_json: Optional[Dict[str, Any]] = None
  92. class Config:
  93. from_attributes = True
  94. @field_validator('detection_json', 'modified_json', mode='before')
  95. @classmethod
  96. def parse_json_string(cls, v):
  97. if v is None:
  98. return None
  99. if isinstance(v, str):
  100. try:
  101. return json.loads(v)
  102. except json.JSONDecodeError:
  103. raise ValueError("Invalid JSON string in database")
  104. return v
  105. class CardImageInListResponse(BaseModel):
  106. id: int
  107. image_type: str
  108. image_path: str
  109. detection_image_path: Optional[str] = None
  110. modified_image_path: Optional[str] = None
  111. class Config:
  112. from_attributes = True
  113. class CardListDetailResponse(BaseModel):
  114. id: int
  115. card_name: Optional[str] = None
  116. cardNo: Optional[str] = None
  117. card_type: str
  118. detection_score: Optional[float] = None
  119. modified_score: Optional[float] = None
  120. is_edited: bool
  121. created_at: datetime
  122. updated_at: datetime
  123. image_path_list: Dict[str, Optional[str]] = {}
  124. detection_image_path_list: Dict[str, Optional[str]] = {}
  125. modified_image_path_list: Dict[str, Optional[str]] = {}
  126. class Config:
  127. from_attributes = True
  128. class CardListWithTotal(BaseModel):
  129. total: int
  130. list: List[CardListDetailResponse]
  131. class CardListResponseWrapper(BaseModel):
  132. data: CardListWithTotal