scheme.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. created_at: datetime
  77. updated_at: datetime
  78. card_type: str
  79. is_edited: bool
  80. detection_score: Optional[float] = None
  81. modified_score: Optional[float] = None
  82. detection_score_detail: Optional[Dict[str, Any]] = None
  83. modified_score_detail: Optional[Dict[str, Any]] = None
  84. images: List[CardImageResponse] = []
  85. class Config:
  86. from_attributes = True
  87. class ImageJsonPairResponse(BaseModel):
  88. id: int
  89. detection_json: Dict[str, Any]
  90. modified_json: Optional[Dict[str, Any]] = None
  91. class Config:
  92. from_attributes = True
  93. @field_validator('detection_json', 'modified_json', mode='before')
  94. @classmethod
  95. def parse_json_string(cls, v):
  96. if v is None:
  97. return None
  98. if isinstance(v, str):
  99. try:
  100. return json.loads(v)
  101. except json.JSONDecodeError:
  102. raise ValueError("Invalid JSON string in database")
  103. return v
  104. class CardImageInListResponse(BaseModel):
  105. id: int
  106. image_type: str
  107. image_path: str
  108. detection_image_path: Optional[str] = None
  109. modified_image_path: Optional[str] = None
  110. class Config:
  111. from_attributes = True
  112. class CardListDetailResponse(BaseModel):
  113. id: int
  114. card_name: Optional[str] = None
  115. card_type: str
  116. detection_score: Optional[float] = None
  117. modified_score: Optional[float] = None
  118. is_edited: bool
  119. created_at: datetime
  120. updated_at: datetime
  121. image_path_list: Dict[str, Optional[str]] = {}
  122. detection_image_path_list: Dict[str, Optional[str]] = {}
  123. modified_image_path_list: Dict[str, Optional[str]] = {}
  124. class Config:
  125. from_attributes = True
  126. class CardListWithTotal(BaseModel):
  127. total: int
  128. list: List[CardListDetailResponse]
  129. class CardListResponseWrapper(BaseModel):
  130. data: CardListWithTotal