Ver código fonte

2个前后查询改进

AnlaAnla 1 mês atrás
pai
commit
8dc01ce2d6
1 arquivos alterados com 52 adições e 85 exclusões
  1. 52 85
      app/api/formate_xy.py

+ 52 - 85
app/api/formate_xy.py

@@ -1,5 +1,6 @@
 import requests
 import json
+from enum import Enum
 
 from fastapi import APIRouter, Depends, HTTPException, Query, Body
 from fastapi.concurrency import run_in_threadpool
@@ -21,6 +22,12 @@ router = APIRouter()
 db_dependency = Depends(get_db_connection)
 
 
+class QueryMode(str, Enum):
+    current = "current"
+    next = "next"
+    prev = "prev"
+
+
 def _process_images_to_xy_format(card_data: dict):
     """
     内部辅助函数:遍历卡牌数据中的图片,将 JSON 格式转换为前端需要的 XY 格式。
@@ -46,98 +53,58 @@ def _process_images_to_xy_format(card_data: dict):
     return card_data
 
 
-@router.get("/query", response_model=CardDetailResponse, summary="获取指定卡牌的详细信息(格式化xy)")
-def get_card_details(card_id: int, db_conn: PooledMySQLConnection = db_dependency):
-    """
-    获取卡牌元数据以及所有与之关联的图片信息。
-    【特殊处理】:会将 json 中的 points 坐标转换为 [{"id":..., "x":..., "y":...}] 格式。
+@router.get("/query", response_model=CardDetailResponse, summary="获取卡牌详细信息(格式化xy), 支持前后翻页")
+def get_card_details(
+        card_id: int = Query(..., description="基准卡牌ID"),
+        mode: QueryMode = Query(QueryMode.current, description="查询模式: current(当前), next(下一个), prev(上一个)"),
+        db_conn: PooledMySQLConnection = db_dependency
+):
     """
-    # 1. 获取原始数据
-    card_data = crud_card.get_card_with_details(db_conn, card_id)
-
-    if not card_data:
-        raise HTTPException(status_code=404, detail=f"ID为 {card_id} 的卡牌未找到。")
-
-    # 2. 转换格式 (提取为公共函数)
-    _process_images_to_xy_format(card_data)
-
-    # 3. 验证并返回
-    return CardDetailResponse.model_validate(card_data)
-
+    获取卡牌元数据以及所有与之关联的图片信息,并将坐标转换为 xy 格式。
 
-@router.get("/query_next", response_model=CardDetailResponse, summary="获取下一个卡牌的详细信息(格式化xy)")
-def get_next_card_details(card_id: int, db_conn: PooledMySQLConnection = db_dependency):
-    """
-    获取指定ID的下一张卡牌的信息,并格式化为xy坐标结构。
+    - **current**: 查询 card_id 对应的卡牌。
+    - **next**: 查询 ID 比 card_id 大的第一张卡牌。
+    - **prev**: 查询 ID 比 card_id 小的第一张卡牌。
     """
-    try:
-        with db_conn.cursor(dictionary=True) as cursor:
-            # 1. 查询下一个ID (ID > current ORDER BY ID ASC)
-            query_next = (
-                f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} "
-                f"WHERE id > %s ORDER BY id ASC LIMIT 1"
-            )
-            cursor.execute(query_next, (card_id,))
-            row = cursor.fetchone()
-
-            if not row:
-                # 保持与 cards.py 一致的行为,没有下一张时返回 200 或 404 视业务需求定,这里参考 cards.py 逻辑
-                raise HTTPException(status_code=200, detail=f"没有下一张")
-
-            next_card_id = row['id']
-
-            # 2. 获取数据
-            card_data = crud_card.get_card_with_details(db_conn, next_card_id)
-            if not card_data:
-                raise HTTPException(status_code=404, detail=f"下一个卡牌ID {next_card_id} 数据异常。")
-
-            # 3. 转换格式
-            _process_images_to_xy_format(card_data)
-
-            return CardDetailResponse.model_validate(card_data)
+    target_id = card_id
 
-    except HTTPException:
-        raise
-    except Exception as e:
-        logger.error(f"查询下一个卡牌(xy)失败 (基准ID: {card_id}): {e}")
-        raise HTTPException(status_code=500, detail="查询失败")
-
-
-@router.get("/query_prev", response_model=CardDetailResponse, summary="获取上一个卡牌的详细信息(格式化xy)")
-def get_prev_card_details(card_id: int, db_conn: PooledMySQLConnection = db_dependency):
-    """
-    获取指定ID的上一张卡牌的信息,并格式化为xy坐标结构。
-    """
-    try:
-        with db_conn.cursor(dictionary=True) as cursor:
-            # 1. 查询上一个ID (ID < current ORDER BY ID DESC)
-            query_prev = (
-                f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} "
-                f"WHERE id < %s ORDER BY id DESC LIMIT 1"
-            )
-            cursor.execute(query_prev, (card_id,))
-            row = cursor.fetchone()
-
-            if not row:
-                raise HTTPException(status_code=200, detail=f"没有上一张")
-
-            prev_card_id = row['id']
+    # 1. 如果是查询上一个或下一个,先计算目标ID
+    if mode != QueryMode.current:
+        try:
+            with db_conn.cursor(dictionary=True) as cursor:
+                if mode == QueryMode.next:
+                    query = (f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} "
+                             f"WHERE id > %s ORDER BY id ASC LIMIT 1")
+                else:  # mode == QueryMode.prev
+                    query = (f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} "
+                             f"WHERE id < %s ORDER BY id DESC LIMIT 1")
+
+                cursor.execute(query, (card_id,))
+                row = cursor.fetchone()
+
+                if not row:
+                    # 按照项目习惯,找不到上/下一个时返回 200 + 提示信息,或根据需求改为 404
+                    msg = "没有下一张" if mode == QueryMode.next else "没有上一张"
+                    raise HTTPException(status_code=200, detail=msg)
+
+                target_id = row['id']
+        except HTTPException:
+            raise
+        except Exception as e:
+            logger.error(f"查询卡牌ID失败 (Mode: {mode}, BaseID: {card_id}): {e}")
+            raise HTTPException(status_code=500, detail="数据库查询失败")
 
-            # 2. 获取数据
-            card_data = crud_card.get_card_with_details(db_conn, prev_card_id)
-            if not card_data:
-                raise HTTPException(status_code=404, detail=f"上一个卡牌ID {prev_card_id} 数据异常。")
+    # 2. 获取目标卡牌的详细数据 (Dict 格式)
+    card_data = crud_card.get_card_with_details(db_conn, target_id)
 
-            # 3. 转换格式
-            _process_images_to_xy_format(card_data)
+    if not card_data:
+        raise HTTPException(status_code=404, detail=f"ID为 {target_id} 的卡牌未找到。")
 
-            return CardDetailResponse.model_validate(card_data)
+    # 3. 遍历图片,转换格式 (使用抽取出的辅助函数)
+    _process_images_to_xy_format(card_data)
 
-    except HTTPException:
-        raise
-    except Exception as e:
-        logger.error(f"查询上一个卡牌(xy)失败 (基准ID: {card_id}): {e}")
-        raise HTTPException(status_code=500, detail="查询失败")
+    # 4. 验证并返回
+    return CardDetailResponse.model_validate(card_data)
 
 
 @router.put("/update/json/{id}", status_code=200, summary="接收xy格式, 还原后重计算分数并保存")
@@ -232,4 +199,4 @@ async def update_image_modified_json(
         raise HTTPException(status_code=500, detail=f"更新JSON数据失败: {e}")
     finally:
         if cursor:
-            cursor.close()
+            cursor.close()