فهرست منبع

修改上传接口以及修改put接口

袁威 1 هفته پیش
والد
کامیت
8e6a5496aa
2فایلهای تغییر یافته به همراه67 افزوده شده و 42 حذف شده
  1. 40 31
      app/api/auto_import.py
  2. 27 11
      app/api/formate_xy.py

+ 40 - 31
app/api/auto_import.py

@@ -223,7 +223,7 @@ async def create_card_record(
         raise HTTPException(status_code=response.status, detail=f"创建卡牌记录失败: {text}")
 
 
-async def upload_fusion_image(
+async def upload_main_image(
         session: aiohttp.ClientSession,
         base_url: str,
         card_id: int,
@@ -232,7 +232,7 @@ async def upload_fusion_image(
         filename: str,
         score_json: Dict[str, Any],
 ):
-    """融合图带 JSON 走主图入库接口。"""
+    """带 JSON 的图走主图入库接口(fusion / ring / stripe 共用同一面的 detection_json)。"""
     url = f"{base_url}{settings.API_PREFIX}/images/insert/{card_id}"
 
     form_fields = {
@@ -250,10 +250,10 @@ async def upload_fusion_image(
     )
     if status != 201:
         logger.error(
-            "[融合图上传失败] image_type=%s status=%s msg=%s",
+            "[主表图上传失败] image_type=%s status=%s msg=%s",
             image_type, status, body.decode("utf-8", errors="ignore")[:200],
         )
-        raise HTTPException(status_code=500, detail=f"融合图保存失败: {image_type}")
+        raise HTTPException(status_code=500, detail=f"主表图保存失败: {image_type}")
 
 
 async def upload_auxiliary_image(
@@ -307,9 +307,15 @@ async def _run_import_flow(
         card_type: CardType,
         strict_mode: bool,
         bytes_map: Dict[str, Tuple[bytes, str]],
+        non_gray_to_main: bool = False,
 ) -> Dict[str, Any]:
     """
     共用导入流程:bytes_map 的 key 是 image_type,value 是 (bytes, filename)。
+
+    non_gray_to_main:
+        False -> 仅融合图进主表(带 JSON),ring/gray/stripe 进辅助表(无 JSON)。
+        True  -> 除灰度图外(fusion/ring/stripe)都进主表,并共用所在面的 detection_json;
+                 灰度图仍进辅助表。
     """
     expected_types = _flat_image_types()
     provided = [t for t in expected_types if t in bytes_map]
@@ -362,41 +368,42 @@ async def _run_import_flow(
         upload_count = 0
         for side in ("front", "back"):
             side_map = SIDE_IMAGE_TYPES[side]
-            fusion_type = side_map["fusion"]
-            fusion_data = bytes_map.get(fusion_type)
             score_json = side_score_json.get(side)
 
-            if fusion_data is not None:
-                f_bytes, f_name = fusion_data
-                if score_json is not None:
-                    await upload_fusion_image(
+            # 按 fusion -> ring -> gray -> stripe1..4 顺序处理该面所有图
+            for field in ["fusion"] + STITCH_FORM_FIELDS:
+                image_type = side_map[field]
+                data = bytes_map.get(image_type)
+                if data is None:
+                    continue
+                f_bytes, f_name = data
+
+                is_gray = (field == "gray")
+                # 进主表(带该面 detection_json)的条件:
+                #   - 非灰度图
+                #   - 该面有 stitch 结果
+                #   - URL 模式(non_gray_to_main) 下所有非灰度图都进;文件模式仅 fusion 进
+                to_main = (
+                    not is_gray
+                    and score_json is not None
+                    and (non_gray_to_main or field == "fusion")
+                )
+
+                if to_main:
+                    await upload_main_image(
                         session, local_base_url, card_id,
-                        fusion_type, f_bytes, f_name, score_json,
+                        image_type, f_bytes, f_name, score_json,
                     )
-                    upload_count += 1
                 else:
-                    # 没有该面推理结果,融合图退化为辅助图,避免主表 detection_json 为空
-                    logger.warning(
-                        "%s 面缺少 stitch 推理结果,融合图 %s 退化为辅助图入库",
-                        side, fusion_type,
-                    )
+                    if field == "fusion" and score_json is None:
+                        logger.warning(
+                            "%s 面缺少 stitch 推理结果,融合图 %s 退化为辅助图入库",
+                            side, image_type,
+                        )
                     await upload_auxiliary_image(
                         session, local_base_url, card_id,
-                        fusion_type, f_bytes, f_name,
+                        image_type, f_bytes, f_name,
                     )
-                    upload_count += 1
-
-            # ring / gray / stripe1..4 走辅助表
-            for field in STITCH_FORM_FIELDS:
-                aux_type = side_map[field]
-                aux_data = bytes_map.get(aux_type)
-                if aux_data is None:
-                    continue
-                a_bytes, a_name = aux_data
-                await upload_auxiliary_image(
-                    session, local_base_url, card_id,
-                    aux_type, a_bytes, a_name,
-                )
                 upload_count += 1
 
         logger.info(
@@ -499,6 +506,7 @@ async def auto_import_script_api(
             card_type=card_type,
             strict_mode=strict_mode,
             bytes_map=bytes_map,
+            non_gray_to_main=True,
         )
     except HTTPException as e:
         logger.error(
@@ -601,6 +609,7 @@ async def auto_import_url_script_api(
             card_type=card_type,
             strict_mode=strict_mode,
             bytes_map=bytes_map,
+            non_gray_to_main=True,
         )
     except HTTPException:
         raise

+ 27 - 11
app/api/formate_xy.py

@@ -15,7 +15,7 @@ from app.core.logger import get_logger
 from app.core.database_loader import get_db_connection
 from app.api.users import check_card_permission, get_current_user
 from app.utils.scheme import (
-    CardDetailResponse, IMAGE_TYPE_TO_SCORE_TYPE, ImageType
+    CardDetailResponse, ImageType
 )
 from app.crud import crud_card
 from app.utils.xy_process import convert_internal_to_xy_format, convert_xy_to_internal_format
@@ -33,6 +33,27 @@ class QueryMode(str, Enum):
     prev = "prev"
 
 
+def _resolve_recalc_score_type(image_type: str):
+    """
+    将任意 image_type 归一到 score_recalculate 接口接受的 score_type。
+    该接口只接受 front_coaxial / front_ring / back_coaxial / back_ring。
+    coaxial / ring 直接透传;fusion / gray / stripe 等按正反面归到对应 ring。
+    """
+    passthrough = {
+        ImageType.front_coaxial.value,
+        ImageType.front_ring.value,
+        ImageType.back_coaxial.value,
+        ImageType.back_ring.value,
+    }
+    if image_type in passthrough:
+        return image_type
+    if image_type.startswith("front"):
+        return ImageType.front_ring.value
+    if image_type.startswith("back"):
+        return ImageType.back_ring.value
+    return None
+
+
 def _is_center_box_shapes_empty(center_result: dict) -> bool:
     """
     判断 center_result 中 inner/outer box 的 shapes 是否都为空。
@@ -387,15 +408,9 @@ async def update_image_modified_json(
         check_card_permission(db_conn, current_user, card_id_to_update)
         image_type = row["image_type"]
         
-        # 针对融合图,在调用外部服务算分时直接把它当成对应的 ring 图
-        # 否则它在映射表里是 None,会导致报错
-        target_score_type = image_type
-        if image_type == ImageType.front_fusion.value:
-            target_score_type = ImageType.front_ring.value
-        elif image_type == ImageType.back_fusion.value:
-            target_score_type = ImageType.back_ring.value
-            
-        score_type = IMAGE_TYPE_TO_SCORE_TYPE.get(target_score_type)
+        # score_recalculate 接口只接受 coaxial / ring 类型的 score_type,
+        # 融合图/灰度图/调光图都按正反面归到对应 ring。
+        score_type = _resolve_recalc_score_type(image_type)
         if not score_type:
             raise HTTPException(status_code=400, detail=f"未知的 image_type: {image_type}")
 
@@ -635,7 +650,8 @@ async def update_gray_image_json(
                 ring_defects.append(new_defect)
 
         # 6. 调用计算服务 (对 Ring 图数据进行重算)
-        score_type = IMAGE_TYPE_TO_SCORE_TYPE.get(target_ring_type)  # e.g., 'front_ring'
+        # score_recalculate 接口接受 ring 类型,直接用目标 ring 类型即可
+        score_type = _resolve_recalc_score_type(target_ring_type)
 
         logger.info(f"开始重计算 Ring 图分数 (GrayID: {id} -> RingID: {ring_image_id}, Type: {score_type})")