template.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. """
  2. 模板 API 路由
  3. """
  4. from fastapi import APIRouter, HTTPException
  5. from pydantic import BaseModel
  6. from typing import Optional, List, Dict
  7. from services.template_service import get_template_service
  8. from models.schemas import (
  9. CreateTemplateResponse,
  10. GetTemplateResponse,
  11. TemplateApplyResponse,
  12. DeleteTemplateResponse,
  13. )
  14. router = APIRouter(prefix="/api/templates", tags=["templates"])
  15. class CreateTemplateRequest(BaseModel):
  16. """创建模板请求"""
  17. name: str
  18. structure: Dict
  19. image_size: Dict
  20. description: Optional[str] = ""
  21. class PreviewApplyRequest(BaseModel):
  22. """预览应用请求"""
  23. target_image_size: Dict
  24. target_table_bbox: Optional[List] = None # 目标页面的 table_bbox [x1, y1, x2, y2]
  25. mode: Optional[str] = "relative" # "relative" 或 "absolute"
  26. class ApplyTemplateRequest(BaseModel):
  27. """应用模板请求"""
  28. target_image_size: Dict
  29. target_table_bbox: Optional[List] = None # 目标页面的 table_bbox [x1, y1, x2, y2]
  30. mode: Optional[str] = "relative"
  31. class TemplateInfo(BaseModel):
  32. """模板信息"""
  33. name: str
  34. description: Optional[str] = ""
  35. created_at: Optional[str] = ""
  36. stats: Optional[Dict] = {}
  37. source_image_size: Optional[Dict] = {}
  38. class TemplateListResponse(BaseModel):
  39. """模板列表响应"""
  40. templates: List[Dict]
  41. total: int
  42. @router.get("", response_model=TemplateListResponse)
  43. async def list_templates():
  44. """列出所有模板"""
  45. service = get_template_service()
  46. templates = service.list_templates()
  47. return TemplateListResponse(
  48. templates=templates,
  49. total=len(templates)
  50. )
  51. @router.post("", response_model=CreateTemplateResponse)
  52. async def create_template(request: CreateTemplateRequest):
  53. """从当前结构创建模板"""
  54. service = get_template_service()
  55. try:
  56. result = service.create_template(
  57. name=request.name,
  58. structure=request.structure,
  59. image_size=request.image_size,
  60. description=request.description or ""
  61. )
  62. return CreateTemplateResponse(
  63. success=True,
  64. data=result,
  65. message="模板创建成功"
  66. )
  67. except ValueError as e:
  68. raise HTTPException(status_code=400, detail=str(e))
  69. except Exception as e:
  70. raise HTTPException(status_code=500, detail=f"创建模板失败: {str(e)}")
  71. @router.get("/{name}", response_model=GetTemplateResponse)
  72. async def get_template(name: str):
  73. """获取模板详情"""
  74. service = get_template_service()
  75. template = service.get_template(name)
  76. if not template:
  77. raise HTTPException(status_code=404, detail=f"模板 '{name}' 不存在")
  78. return GetTemplateResponse(
  79. success=True,
  80. data=template,
  81. message="获取成功"
  82. )
  83. @router.delete("/{name}", response_model=DeleteTemplateResponse)
  84. async def delete_template(name: str):
  85. """删除模板"""
  86. service = get_template_service()
  87. if service.delete_template(name):
  88. return DeleteTemplateResponse(
  89. success=True,
  90. message=f"模板 '{name}' 已删除"
  91. )
  92. raise HTTPException(status_code=404, detail=f"模板 '{name}' 不存在")
  93. @router.post("/{name}/preview", response_model=TemplateApplyResponse)
  94. async def preview_apply(name: str, request: PreviewApplyRequest):
  95. """预览模板应用效果"""
  96. service = get_template_service()
  97. try:
  98. structure = service.preview_apply(
  99. template_name=name,
  100. target_image_size=request.target_image_size,
  101. target_table_bbox=request.target_table_bbox,
  102. mode=request.mode or "relative"
  103. )
  104. return TemplateApplyResponse(
  105. success=True,
  106. data=structure,
  107. message="预览成功"
  108. )
  109. except ValueError as e:
  110. raise HTTPException(status_code=404, detail=str(e))
  111. except Exception as e:
  112. raise HTTPException(status_code=500, detail=f"预览失败: {str(e)}")
  113. @router.post("/{name}/apply", response_model=TemplateApplyResponse)
  114. async def apply_template(name: str, request: ApplyTemplateRequest):
  115. """确认应用模板"""
  116. service = get_template_service()
  117. try:
  118. structure = service.apply_template(
  119. template_name=name,
  120. target_image_size=request.target_image_size,
  121. target_table_bbox=request.target_table_bbox,
  122. mode=request.mode or "relative"
  123. )
  124. return TemplateApplyResponse(
  125. success=True,
  126. data=structure,
  127. message="应用成功"
  128. )
  129. except ValueError as e:
  130. raise HTTPException(status_code=404, detail=str(e))
  131. except Exception as e:
  132. raise HTTPException(status_code=500, detail=f"应用模板失败: {str(e)}")