#!/usr/bin/env python # -*- coding: utf-8 -*- """ 地图数据推送API路由 实现地图数据推送时的动作点和库区数据存储功能 """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from typing import Any, Dict from data.session import get_db from services.map_data_service import MapDataService from routes.model.base import ApiResponse from routes.model.map_model import ( MapDataPushRequest, MapDataPushResponse, MapDataQueryRequest, MapDataQueryResponse ) from routes.common_api import format_response, error_response from utils.logger import get_logger # 创建路由 router = APIRouter(prefix="/api/vwed-map-data", tags=["地图数据推送"]) # 设置日志 logger = get_logger("app.map_data_api") # 标准API响应格式 def api_response(code: int = 200, message: str = "操作成功", data: Any = None) -> Dict[str, Any]: """ 标准API响应格式 Args: code: 状态码 message: 响应消息 data: 响应数据 Returns: Dict[str, Any]: 格式化的响应数据 """ return { "code": code, "message": message, "data": data } @router.post("/push", response_model=ApiResponse[MapDataPushResponse]) async def push_map_data( request: MapDataPushRequest, db: Session = Depends(get_db) ): """ 推送地图数据 当用户推送新的地图时,将地图相关的动作点和库区数据存入数据库 支持库区分类(密集库区、一般库区)和动作点分层存储 重要功能: - 自动为新创建的库位层同步所有已启用的扩展属性 - 新库位层会自动包含系统中定义的扩展属性配置 - 扩展属性使用默认值进行初始化 Args: request: 地图数据推送请求 db: 数据库会话 Returns: ApiResponse[MapDataPushResponse]: 推送结果响应 """ try: # 调用服务层方法推送地图数据 result = MapDataService.push_map_data(db=db, request=request) return api_response(message="地图数据推送成功", data=result) except ValueError as e: # 数据验证错误 return error_response(str(e), 400) except Exception as e: logger.error(f"地图数据推送失败: {str(e)}") return error_response(f"地图数据推送失败: {str(e)}", 500) @router.post("/query", response_model=ApiResponse[MapDataQueryResponse]) async def query_map_data( request: MapDataQueryRequest, db: Session = Depends(get_db) ): """ 查询地图数据 根据场景ID查询地图中的库区和动作点数据 支持按库区类型筛选和是否包含分层数据的选项 Args: request: 地图数据查询请求 db: 数据库会话 Returns: ApiResponse[MapDataQueryResponse]: 查询结果响应 """ try: # 调用服务层方法查询地图数据 result = MapDataService.query_map_data(db=db, request=request) return api_response(message="查询成功", data=result) except ValueError as e: # 数据验证错误 return error_response(str(e), 400) except Exception as e: logger.error(f"查询地图数据失败: {str(e)}") return error_response(f"查询地图数据失败: {str(e)}", 500) @router.delete("/scene/{scene_id}") async def delete_scene_data( scene_id: str, db: Session = Depends(get_db) ): """ 删除场景数据 删除指定场景的所有地图数据,包括库区、动作点和分层数据 Args: scene_id: 场景ID db: 数据库会话 Returns: ApiResponse: 删除结果响应 """ try: # 调用服务层的删除方法 MapDataService._delete_existing_data(db=db, scene_id=scene_id) db.commit() logger.info(f"场景数据删除成功: 场景ID={scene_id}") return api_response(message="场景数据删除成功") except Exception as e: db.rollback() logger.error(f"删除场景数据失败: {str(e)}") return error_response(f"删除场景数据失败: {str(e)}", 500) @router.get("/scene/{scene_id}/summary") async def get_scene_summary( scene_id: str, db: Session = Depends(get_db) ): """ 获取场景数据摘要 获取指定场景的数据统计信息,包括库区和动作点的数量统计 Args: scene_id: 场景ID db: 数据库会话 Returns: ApiResponse: 场景摘要信息 """ try: # 构造查询请求 query_request = MapDataQueryRequest( scene_id=scene_id, include_layers=True ) # 调用服务层方法获取数据 result = MapDataService.query_map_data(db=db, request=query_request) # 提取摘要信息 summary = { "scene_id": result.scene_id, "total_storage_areas": len(result.storage_areas), "total_operate_points": len(result.operate_points), "total_capacity": result.total_capacity, "used_capacity": result.used_capacity, "capacity_usage_rate": round( (result.used_capacity / result.total_capacity * 100) if result.total_capacity > 0 else 0, 2 ), "dense_areas_count": result.dense_areas_count, "general_areas_count": result.general_areas_count, "total_layers": result.total_layers, "occupied_layers": result.occupied_layers, "layer_usage_rate": round( (result.occupied_layers / result.total_layers * 100) if result.total_layers > 0 else 0, 2 ) } return api_response(message="获取场景摘要成功", data=summary) except Exception as e: logger.error(f"获取场景摘要失败: {str(e)}") return error_response(f"获取场景摘要失败: {str(e)}", 500)