schemas.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. """
  2. Pydantic 数据模型定义
  3. """
  4. from pydantic import BaseModel, Field
  5. from typing import List, Dict, Optional, Any
  6. class TableStructure(BaseModel):
  7. """表格结构"""
  8. horizontal_lines: List[int] = Field(default_factory=list, description="横线Y坐标列表")
  9. vertical_lines: List[int] = Field(default_factory=list, description="竖线X坐标列表")
  10. table_bbox: Optional[List[int]] = Field(default=None, description="表格边界框 [x1, y1, x2, y2]")
  11. row_height: Optional[int] = Field(default=None, description="标准行高")
  12. col_widths: Optional[List[int]] = Field(default=None, description="列宽列表")
  13. total_rows: Optional[int] = Field(default=None, description="总行数")
  14. total_cols: Optional[int] = Field(default=None, description="总列数")
  15. mode: Optional[str] = Field(default="hybrid", description="分析模式")
  16. modified_h_lines: List[int] = Field(default_factory=list, description="被修改的横线索引")
  17. modified_v_lines: List[int] = Field(default_factory=list, description="被修改的竖线索引")
  18. image_rotation_angle: float = Field(default=0.0, description="图片旋转角度")
  19. skew_angle: float = Field(default=0.0, description="倾斜角度")
  20. is_skew_corrected: bool = Field(default=False, description="是否已校正倾斜")
  21. class ImageSize(BaseModel):
  22. """图片尺寸"""
  23. width: int
  24. height: int
  25. class UploadResponse(BaseModel):
  26. """上传响应"""
  27. success: bool
  28. image_base64: str = Field(description="Base64 编码的图片")
  29. structure: TableStructure = Field(description="表格结构")
  30. image_size: ImageSize = Field(description="图片尺寸")
  31. scale_factor: float = Field(default=1.0, description="缩放比例 (1.0 表示未缩放)")
  32. ocr_data: Optional[Dict[str, Any]] = Field(default=None, description="原始 OCR 数据 (用于重新分析)")
  33. suggested_filename: Optional[str] = Field(default=None, description="建议的文件名")
  34. message: Optional[str] = None
  35. class AnalyzeParams(BaseModel):
  36. """分析参数"""
  37. y_tolerance: int = Field(default=5, ge=1, le=50, description="Y轴聚类容差")
  38. x_tolerance: int = Field(default=10, ge=1, le=100, description="X轴聚类容差")
  39. min_row_height: int = Field(default=20, ge=5, le=100, description="最小行高")
  40. method: str = Field(default="auto", description="分析方法: auto/cluster/mineru")
  41. class AnalyzeRequest(BaseModel):
  42. """重新分析请求"""
  43. ocr_data: Dict[str, Any] = Field(description="OCR 数据")
  44. params: AnalyzeParams = Field(default_factory=AnalyzeParams)
  45. class AnalyzeResponse(BaseModel):
  46. """分析响应"""
  47. success: bool
  48. structure: TableStructure
  49. message: Optional[str] = None
  50. class SaveRequest(BaseModel):
  51. """保存请求"""
  52. structure: TableStructure = Field(description="表格结构")
  53. image_base64: Optional[str] = Field(default=None, description="Base64 编码的原始图片(可选,saveImage=false时不需要)")
  54. output_dir: str = Field(description="输出目录路径")
  55. filename: str = Field(description="结构文件名 (不含扩展名)")
  56. image_filename: Optional[str] = Field(default=None, description="图片文件名 (不含扩展名)")
  57. overwrite_mode: str = Field(default="overwrite", description="覆盖策略: overwrite/skip/new")
  58. structure_suffix: str = Field(default="_structure", description="结构文件后缀(不含.json扩展名)")
  59. image_suffix: str = Field(default="", description="图片文件后缀(不含.png扩展名)")
  60. line_width: int = Field(default=2, description="线条宽度")
  61. line_color: List[int] = Field(default=[0, 0, 0], description="线条颜色 RGB")
  62. class SaveResponse(BaseModel):
  63. """保存响应"""
  64. success: bool
  65. structure_path: Optional[str] = Field(default=None, description="结构文件路径")
  66. image_path: Optional[str] = Field(default=None, description="图片文件路径(可选)")
  67. message: Optional[str] = None
  68. class ErrorResponse(BaseModel):
  69. """错误响应"""
  70. success: bool = False
  71. error: str
  72. detail: Optional[str] = None
  73. class LoadByPathRequest(BaseModel):
  74. """按路径加载请求"""
  75. json_path: str = Field(description="JSON 文件路径")
  76. image_path: str = Field(description="图片文件路径")
  77. output_dir: Optional[str] = Field(default=None, description="输出目录路径(可选,用于查找已保存的标注结构)")
  78. structure_suffix: str = Field(default="_structure", description="结构文件后缀(不含.json)")
  79. image_suffix: str = Field(default="", description="图片文件后缀(不含.png)")
  80. class PreviewApplyRequest(BaseModel):
  81. """预览应用模板请求"""
  82. template_name: str = Field(description="模板名称")
  83. target_image_size: ImageSize = Field(description="目标图片尺寸")
  84. target_table_bbox: Optional[List[int]] = Field(default=None, description="目标表格边界框 [x1, y1, x2, y2]")
  85. class ApplyTemplateRequest(BaseModel):
  86. """应用模板请求"""
  87. template_name: str = Field(description="模板名称")
  88. structure: TableStructure = Field(description="原始表格结构")
  89. target_table_bbox: Optional[List[int]] = Field(default=None, description="目标表格边界框")
  90. class CreateTemplateRequest(BaseModel):
  91. """创建模板请求"""
  92. name: str = Field(description="模板名称")
  93. description: Optional[str] = Field(default=None, description="模板描述")
  94. structure: TableStructure = Field(description="表格结构")
  95. class TemplateInfo(BaseModel):
  96. """模板信息"""
  97. name: str
  98. description: Optional[str]
  99. created_at: str
  100. row_count: int
  101. col_count: int
  102. class TemplateListResponse(BaseModel):
  103. """模板列表响应"""
  104. success: bool
  105. templates: List[TemplateInfo]
  106. message: Optional[str] = None
  107. class TemplateResponse(BaseModel):
  108. """单个模板响应"""
  109. success: bool
  110. data: Dict
  111. message: Optional[str] = None
  112. class DeleteTemplateRequest(BaseModel):
  113. """删除模板请求"""
  114. name: str = Field(description="模板名称")
  115. class DeleteTemplateResponse(BaseModel):
  116. """删除模板响应"""
  117. success: bool
  118. message: str
  119. class CreateTemplateResponse(BaseModel):
  120. """创建模板响应"""
  121. success: bool
  122. data: Dict = Field(description="包含 name, path, stats, created_at")
  123. message: Optional[str] = None
  124. class GetTemplateResponse(BaseModel):
  125. """获取模板响应"""
  126. success: bool
  127. data: Dict = Field(description="模板完整信息")
  128. message: Optional[str] = None
  129. class TemplateApplyResponse(BaseModel):
  130. """预览/应用模板响应"""
  131. success: bool
  132. data: Dict = Field(description="应用后的表格结构")
  133. message: Optional[str] = None
  134. class HealthResponse(BaseModel):
  135. """健康检查响应"""
  136. status: str = Field(description="服务状态")
  137. service: str = Field(description="服务名称")
  138. class HomeDirectoryResponse(BaseModel):
  139. """主目录响应"""
  140. path: str = Field(description="用户主目录路径")