From 3368744d4a8ae17f0b9e39c9c8a7a08b1772c3ec Mon Sep 17 00:00:00 2001 From: lhx Date: Thu, 12 Feb 2026 14:49:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B0=B4=E5=87=86=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E6=9F=A5=E8=AF=A2=E8=B4=A6=E5=8F=B7=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/comprehensive_data.py | 64 ++++++++++++++++++++++++ app/schemas/comprehensive_data.py | 4 ++ app/services/account.py | 81 +++++++++++++++++++++++++++++++ app/services/level_data.py | 6 +++ 4 files changed, 155 insertions(+) diff --git a/app/api/comprehensive_data.py b/app/api/comprehensive_data.py index c431eeb..3f1ac23 100644 --- a/app/api/comprehensive_data.py +++ b/app/api/comprehensive_data.py @@ -18,6 +18,7 @@ from ..schemas.comprehensive_data import ( SettlementDataCheckpointQueryRequest, LevelDataQueryRequest, LinecodeRequest, + LinecodeAccountRequest, NYIDRequest, SectionByAccountRequest, PointByAccountRequest, @@ -30,6 +31,7 @@ from ..services.settlement_data import SettlementDataService from ..services.level_data import LevelDataService from ..services.original_data import OriginalDataService from ..services.comprehensive import ComprehensiveDataService +from ..services.account import AccountService from ..utils.get_operating_mode import OperatingModePredictor import logging router = APIRouter(prefix="/comprehensive_data", tags=["综合数据管理"]) @@ -727,4 +729,66 @@ def get_checkpoint_by_point(request: LevelDataQueryRequest, db: Session = Depend total=0, data=[] ) + +@router.post("/get_accounts_by_linecode", response_model=DataResponse) +def get_accounts_by_linecode(request: LinecodeAccountRequest, db: Session = Depends(get_db)): + """ + 通过水准线路编码查询账号信息 + 业务逻辑: + 1. 根据linecode在水准数据表查询最新的NYID + 2. 根据NYID在沉降数据表查询所有point_id(去重) + 3. 根据point_id在观测点表查询所有section_id(去重) + 4. 根据section_id在断面表查询所有account_id(去重) + 5. 根据account_id在账号表查询账号信息并返回 + + 优化:使用批量IN查询,避免循环查询数据库 + """ + try: + linecode = request.linecode + logger.info(f"接口请求:根据linecode={linecode}查询账号信息") + + # 调用服务层方法 + accounts = AccountService.get_accounts_by_linecode(db, linecode) + + if not accounts: + return DataResponse( + code=ResponseCode.SUCCESS, + message=f"未找到linecode={linecode}对应的账号信息", + total=0, + data=[] + ) + + # 转换为字典列表 + account_data = [] + for account in accounts: + account_dict = { + "id": account.id, + "username": account.username, + "status": account.status, + "today_updated": account.today_updated, + "project_name": account.project_name, + "created_at": account.created_at.strftime("%Y-%m-%d %H:%M:%S") if account.created_at else None, + "updated_at": account.updated_at.strftime("%Y-%m-%d %H:%M:%S") if account.updated_at else None, + "update_time": account.update_time, + "max_variation": account.max_variation, + "yh_id": account.yh_id, + "cl_name": account.cl_name + } + account_data.append(account_dict) + + return DataResponse( + code=ResponseCode.SUCCESS, + message=f"查询成功,共获取{len(account_data)}个账号", + total=len(account_data), + data=account_data + ) + + except Exception as e: + logger.error(f"查询账号信息失败:{str(e)}", exc_info=True) + return DataResponse( + code=ResponseCode.QUERY_FAILED, + message=f"查询失败:{str(e)}", + total=0, + data=[] + ) diff --git a/app/schemas/comprehensive_data.py b/app/schemas/comprehensive_data.py index 74901d4..d28817e 100644 --- a/app/schemas/comprehensive_data.py +++ b/app/schemas/comprehensive_data.py @@ -290,6 +290,10 @@ class ComprehensiveDataImportRequest(BaseModel): data: Dict[str, Any] class LinecodeRequest(BaseModel): linecode: str + +class LinecodeAccountRequest(BaseModel): + linecode: str + class ComprehensiveDataImportResponse(BaseModel): success: bool message: str diff --git a/app/services/account.py b/app/services/account.py index 2dfa7d9..2f41ba3 100644 --- a/app/services/account.py +++ b/app/services/account.py @@ -103,3 +103,84 @@ class AccountService: db.commit() return True return False + + @staticmethod + def get_accounts_by_linecode(db: Session, linecode: str) -> List[Account]: + """ + 通过水准线路编码查询账号信息(优化版,减少数据库查询次数) + 业务逻辑: + 1. 根据linecode在水准数据表查询最新的NYID + 2. 根据NYID在沉降数据表批量查询所有point_id(去重) + 3. 根据point_id列表在观测点表批量查询所有section_id(去重) + 4. 根据section_id列表在断面表批量查询所有account_id(去重) + 5. 根据account_id列表在账号表批量查询账号信息 + + 使用IN查询避免循环,大幅提升性能 + """ + from ..models.level_data import LevelData + from ..models.settlement_data import SettlementData + from ..models.checkpoint import Checkpoint + from ..models.section_data import SectionData + + try: + logger.info(f"开始通过linecode={linecode}查询账号信息") + + # 1. 根据linecode查询最新的水准数据(按NYID降序取第一条) + level_data = db.query(LevelData).filter( + LevelData.linecode == linecode + ).order_by(LevelData.NYID.desc()).first() + + if not level_data: + logger.warning(f"未找到linecode={linecode}对应的水准数据") + return [] + + nyid = level_data.NYID + logger.info(f"找到最新期数NYID={nyid}") + + # 2. 根据NYID批量查询沉降数据,提取所有point_id(去重) + settlement_list = db.query(SettlementData.point_id).filter( + SettlementData.NYID == nyid + ).distinct().all() + + if not settlement_list: + logger.warning(f"未找到NYID={nyid}对应的沉降数据") + return [] + + point_ids = [s.point_id for s in settlement_list if s.point_id] + logger.info(f"找到{len(point_ids)}个观测点ID") + + # 3. 根据point_id列表批量查询观测点数据,提取所有section_id(去重) + checkpoint_list = db.query(Checkpoint.section_id).filter( + Checkpoint.point_id.in_(point_ids) + ).distinct().all() + + if not checkpoint_list: + logger.warning(f"未找到对应的观测点数据") + return [] + + section_ids = [c.section_id for c in checkpoint_list if c.section_id] + logger.info(f"找到{len(section_ids)}个断面ID") + + # 4. 根据section_id列表批量查询断面数据,提取所有account_id(去重) + section_list = db.query(SectionData.account_id).filter( + SectionData.section_id.in_(section_ids) + ).distinct().all() + + if not section_list: + logger.warning(f"未找到对应的断面数据") + return [] + + account_ids = [s.account_id for s in section_list if s.account_id] + logger.info(f"找到{len(account_ids)}个账号ID") + + # 5. 根据account_id列表批量查询账号信息 + accounts = db.query(Account).filter( + Account.id.in_(account_ids) + ).all() + + logger.info(f"查询完成,共找到{len(accounts)}个账号") + return accounts + + except Exception as e: + logger.error(f"通过linecode={linecode}查询账号失败: {str(e)}", exc_info=True) + raise e diff --git a/app/services/level_data.py b/app/services/level_data.py index 34b1089..8ea6647 100644 --- a/app/services/level_data.py +++ b/app/services/level_data.py @@ -30,6 +30,12 @@ class LevelDataService(BaseService[LevelData]): """根据水准线路编码获取水准数据""" return self.get_by_field(db, "linecode", linecode) + def get_last_by_linecode(self, db: Session, linecode: str) -> Optional[LevelData]: + """根据水准线路编码获取最新的水准数据(按NYID降序)""" + return db.query(LevelData).filter( + LevelData.linecode == linecode + ).order_by(LevelData.NYID.desc()).first() + def search_level_data(self, db: Session, id: Optional[str] = None, linecode: Optional[str] = None,