Kaynağa Gözat

增加前后id字段

AnlaAnla 1 ay önce
ebeveyn
işleme
984a756bd1
3 değiştirilmiş dosya ile 82 ekleme ve 35 silme
  1. 25 2
      app/api/cards.py
  2. 55 33
      app/api/formate_xy.py
  3. 2 0
      app/utils/scheme.py

+ 25 - 2
app/api/cards.py

@@ -49,11 +49,34 @@ def create_card(
 
 @router.get("/query", response_model=CardDetailResponse, summary="获取指定卡牌的详细信息")
 def get_card_details(card_id: int, db_conn: PooledMySQLConnection = db_dependency):
-    """获取卡牌元数据以及所有与之关联的图片信息。分数是预先计算好的。"""
-    # REFACTORED: Use CRUD function
+    """获取卡牌元数据以及所有与之关联的图片信息,包含 id_prev 和 id_next。"""
+
+    # 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. 获取 id_prev 和 id_next
+    try:
+        with db_conn.cursor() as cursor:
+            # 查询上一个ID (ID < current ORDER BY DESC LIMIT 1)
+            sql_prev = f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} WHERE id < %s ORDER BY id DESC LIMIT 1"
+            cursor.execute(sql_prev, (card_id,))
+            row_prev = cursor.fetchone()
+            card_data['id_prev'] = row_prev[0] if row_prev else None
+
+            # 查询下一个ID (ID > current ORDER BY ASC LIMIT 1)
+            sql_next = f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} WHERE id > %s ORDER BY id ASC LIMIT 1"
+            cursor.execute(sql_next, (card_id,))
+            row_next = cursor.fetchone()
+            card_data['id_next'] = row_next[0] if row_next else None
+
+    except Exception as e:
+        logger.error(f"获取卡牌 {card_id} 的前后ID失败: {e}")
+        # 不中断主流程,可以设为 None
+        card_data['id_prev'] = None
+        card_data['id_next'] = None
+
     return CardDetailResponse.model_validate(card_data)
 
 

+ 55 - 33
app/api/formate_xy.py

@@ -61,50 +61,72 @@ def get_card_details(
 ):
     """
     获取卡牌元数据以及所有与之关联的图片信息,并将坐标转换为 xy 格式。
+    同时返回上一张和下一张卡牌的ID。
 
     - **current**: 查询 card_id 对应的卡牌。
     - **next**: 查询 ID 比 card_id 大的第一张卡牌。
     - **prev**: 查询 ID 比 card_id 小的第一张卡牌。
     """
     target_id = card_id
+    cursor = None
 
-    # 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="数据库查询失败")
+    try:
+        cursor = db_conn.cursor(dictionary=True)
+
+        # 1. 如果是查询上一个或下一个,先计算目标ID
+        if mode != QueryMode.current:
+            if mode == QueryMode.next:
+                query_target = (f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} "
+                                f"WHERE id > %s ORDER BY id ASC LIMIT 1")
+            else:  # mode == QueryMode.prev
+                query_target = (f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} "
+                                f"WHERE id < %s ORDER BY id DESC LIMIT 1")
+
+            cursor.execute(query_target, (card_id,))
+            row = cursor.fetchone()
+
+            if not row:
+                msg = "没有下一张" if mode == QueryMode.next else "没有上一张"
+                raise HTTPException(status_code=200, detail=msg)
+
+            target_id = row['id']
 
-    # 2. 获取目标卡牌的详细数据 (Dict 格式)
-    card_data = crud_card.get_card_with_details(db_conn, target_id)
+        # 2. 获取目标卡牌的详细数据 (Dict 格式)
+        card_data = crud_card.get_card_with_details(db_conn, target_id)
 
-    if not card_data:
-        raise HTTPException(status_code=404, detail=f"ID为 {target_id} 的卡牌未找到。")
+        if not card_data:
+            raise HTTPException(status_code=404, detail=f"ID为 {target_id} 的卡牌未找到。")
 
-    # 3. 遍历图片,转换格式 (使用抽取出的辅助函数)
-    _process_images_to_xy_format(card_data)
+        # 3. 补充当前目标卡牌的 id_prev 和 id_next
+        # 注意:这里需要重新获取 cursor,或者使用 cursor (非 dict 模式可能更方便取值,但 dict 模式也行)
+        # 这里为了简单直接用 raw SQL
 
-    # 4. 验证并返回
-    return CardDetailResponse.model_validate(card_data)
+        # 查询上一个ID
+        sql_prev = f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} WHERE id < %s ORDER BY id DESC LIMIT 1"
+        cursor.execute(sql_prev, (target_id,))
+        row_prev = cursor.fetchone()
+        card_data['id_prev'] = row_prev['id'] if row_prev else None
+
+        # 查询下一个ID
+        sql_next = f"SELECT id FROM {settings.DB_CARD_TABLE_NAME} WHERE id > %s ORDER BY id ASC LIMIT 1"
+        cursor.execute(sql_next, (target_id,))
+        row_next = cursor.fetchone()
+        card_data['id_next'] = row_next['id'] if row_next else None
+
+        # 4. 遍历图片,转换格式 (使用抽取出的辅助函数)
+        _process_images_to_xy_format(card_data)
+
+        # 5. 验证并返回
+        return CardDetailResponse.model_validate(card_data)
+
+    except HTTPException:
+        raise
+    except Exception as e:
+        logger.error(f"查询卡牌详情失败 (Mode: {mode}, BaseID: {card_id}): {e}")
+        raise HTTPException(status_code=500, detail="数据库查询失败")
+    finally:
+        if cursor:
+            cursor.close()
 
 
 @router.put("/update/json/{id}", status_code=200, summary="接收xy格式, 还原后重计算分数并保存")

+ 2 - 0
app/utils/scheme.py

@@ -84,6 +84,8 @@ class CardImageResponse(BaseModel):
 class CardDetailResponse(BaseModel):
     """用于响应单个卡牌详细信息的模型 (主键为 id)"""
     id: int
+    id_prev: Optional[int] = None
+    id_next: Optional[int] = None
     card_name: Optional[str] = None
     created_at: datetime
     updated_at: datetime