""" Cd通量移除计算API接口 @description: 提供籽粒移除和秸秆移除的Cd通量计算功能 """ from fastapi import APIRouter, HTTPException, Query, Path from pydantic import BaseModel, Field from typing import Dict, Any, Optional import logging from ..services.cd_flux_removal_service import CdFluxRemovalService router = APIRouter() # ============================================================================= # 数据模型定义 # ============================================================================= class CdFluxRemovalResponse(BaseModel): """ Cd通量移除计算响应模型 @description: 标准化的API响应格式 """ success: bool = Field(..., description="是否成功") message: str = Field(..., description="响应消息") data: Optional[Dict[str, Any]] = Field(None, description="计算结果数据") # 设置日志 logger = logging.getLogger(__name__) # ============================================================================= # Cd通量移除计算接口 # ============================================================================= @router.get("/grain-removal", summary="计算籽粒移除Cd通量", description="根据指定地区计算籽粒移除Cd通量,公式:EXP(LnCropCd)*F11*0.5*15/1000", response_model=CdFluxRemovalResponse) async def calculate_grain_removal( area: str = Query(..., description="地区名称,如:韶关") ) -> Dict[str, Any]: """ 计算籽粒移除Cd通量 @param area: 地区名称 @returns: 籽粒移除Cd通量计算结果 计算公式:籽粒移除(g/ha/a) = EXP(LnCropCd) * F11 * 0.5 * 15 / 1000 数据来源: - LnCropCd: CropCd_output_data表 - F11: Parameters表(作物亩产量) """ try: service = CdFluxRemovalService() result = service.calculate_grain_removal_by_area(area) if not result["success"]: raise HTTPException( status_code=404, detail=result["message"] ) return result except HTTPException: raise except Exception as e: logger.error(f"计算地区 '{area}' 的籽粒移除Cd通量失败: {str(e)}") raise HTTPException( status_code=500, detail=f"计算失败: {str(e)}" ) @router.get("/straw-removal", summary="计算秸秆移除Cd通量", description="根据指定地区计算秸秆移除Cd通量,公式:[EXP(LnCropCd)/(EXP(LnCropCd)*0.76-0.0034)]*F11*0.5*15/1000", response_model=CdFluxRemovalResponse) async def calculate_straw_removal( area: str = Query(..., description="地区名称,如:韶关") ) -> Dict[str, Any]: """ 计算秸秆移除Cd通量 @param area: 地区名称 @returns: 秸秆移除Cd通量计算结果 计算公式:秸秆移除(g/ha/a) = [EXP(LnCropCd)/(EXP(LnCropCd)*0.76-0.0034)] * F11 * 0.5 * 15 / 1000 数据来源: - LnCropCd: CropCd_output_data表 - F11: Parameters表(作物亩产量) """ try: service = CdFluxRemovalService() result = service.calculate_straw_removal_by_area(area) if not result["success"]: raise HTTPException( status_code=404, detail=result["message"] ) return result except HTTPException: raise except Exception as e: logger.error(f"计算地区 '{area}' 的秸秆移除Cd通量失败: {str(e)}") raise HTTPException( status_code=500, detail=f"计算失败: {str(e)}" ) @router.get("/both-removals", summary="同时计算籽粒移除和秸秆移除Cd通量", description="根据指定地区同时计算籽粒移除和秸秆移除Cd通量", response_model=CdFluxRemovalResponse) async def calculate_both_removals( area: str = Query(..., description="地区名称,如:韶关") ) -> Dict[str, Any]: """ 同时计算籽粒移除和秸秆移除Cd通量 @param area: 地区名称 @returns: 包含籽粒移除和秸秆移除Cd通量的计算结果 计算公式: - 籽粒移除(g/ha/a) = EXP(LnCropCd) * F11 * 0.5 * 15 / 1000 - 秸秆移除(g/ha/a) = [EXP(LnCropCd)/(EXP(LnCropCd)*0.76-0.0034)] * F11 * 0.5 * 15 / 1000 """ try: service = CdFluxRemovalService() result = service.calculate_both_removals_by_area(area) if not result["success"]: raise HTTPException( status_code=404, detail=result["message"] ) return result except HTTPException: raise except Exception as e: logger.error(f"计算地区 '{area}' 的Cd通量移除失败: {str(e)}") raise HTTPException( status_code=500, detail=f"计算失败: {str(e)}" ) @router.get("/sample/{farmland_id}/{sample_id}", summary="计算特定样点的Cd通量移除", description="根据特定农地ID和样点ID计算籽粒移除和秸秆移除Cd通量", response_model=CdFluxRemovalResponse) async def calculate_removal_by_sample( farmland_id: int = Path(..., description="农地ID", ge=1), sample_id: int = Path(..., description="样点ID", ge=1), area: str = Query(..., description="地区名称,如:韶关") ) -> Dict[str, Any]: """ 计算特定样点的Cd通量移除 @param farmland_id: 农地ID @param sample_id: 样点ID @param area: 地区名称 @returns: 特定样点的籽粒移除和秸秆移除Cd通量计算结果 计算公式: - 籽粒移除(g/ha/a) = EXP(LnCropCd) * F11 * 0.5 * 15 / 1000 - 秸秆移除(g/ha/a) = [EXP(LnCropCd)/(EXP(LnCropCd)*0.76-0.0034)] * F11 * 0.5 * 15 / 1000 """ try: service = CdFluxRemovalService() result = service.calculate_removal_by_sample(farmland_id, sample_id, area) if not result["success"]: raise HTTPException( status_code=404, detail=result["message"] ) return result except HTTPException: raise except Exception as e: logger.error(f"计算样点 {farmland_id}-{sample_id} 的Cd通量移除失败: {str(e)}") raise HTTPException( status_code=500, detail=f"计算失败: {str(e)}" )