refactor(api): unify scheme query endpoints

This commit is contained in:
2026-07-30 11:01:45 +08:00
parent 03bb2d75c2
commit 31e2728db1
14 changed files with 457 additions and 261 deletions
+1 -64
View File
@@ -1,13 +1,11 @@
from datetime import datetime
from typing import Any
from fastapi import APIRouter, Depends, HTTPException, Query, Path, Body
from fastapi import APIRouter, Depends, HTTPException, Body
from pydantic import BaseModel, Field
from app.auth.keycloak_dependencies import get_current_keycloak_username
from app.services.burst_detection import (
get_burst_detection_scheme_detail,
list_burst_detection_schemes,
run_burst_detection,
)
@@ -78,64 +76,3 @@ async def detect_burst(
return run_burst_detection(**data.model_dump(), username=username)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.get(
"/schemes/",
summary="查询爆管检测方案列表",
description="获取指定网络的所有爆管检测方案"
)
async def query_burst_detection_schemes(
network: str = Query(..., description="管网名称(或数据库名称)"),
query_date: datetime | None = Query(None, description="查询日期(可选)"),
) -> list[dict[str, Any]]:
"""
获取爆管检测方案列表。
查询指定网络的所有已配置的爆管检测方案,
可按日期进行筛选。
Args:
network: 管网名称(或数据库名称)
query_date: 查询日期(可选)
Returns:
爆管检测方案列表
Raises:
HTTPException: 当查询失败时
"""
try:
return list_burst_detection_schemes(network=network, query_date=query_date)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.get(
"/schemes/{scheme_name}",
summary="获取爆管检测方案详情",
description="获取指定爆管检测方案的详细信息"
)
async def query_burst_detection_scheme_detail(
network: str = Query(..., description="管网名称(或数据库名称)"),
scheme_name: str = Path(..., description="爆管检测方案名称"),
) -> dict[str, Any]:
"""
获取爆管检测方案详情。
查询指定爆管检测方案的完整配置和参数信息。
Args:
network: 管网名称(或数据库名称)
scheme_name: 爆管检测方案名称
Returns:
包含方案详情的字典
Raises:
HTTPException: 当查询失败时
"""
try:
return get_burst_detection_scheme_detail(network=network, scheme_name=scheme_name)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
+1 -64
View File
@@ -3,13 +3,11 @@ from datetime import datetime
from typing import Literal
from fastapi import APIRouter, Depends, HTTPException, Query, Path, Body
from fastapi import APIRouter, Depends, HTTPException, Body
from pydantic import BaseModel, Field
from app.auth.keycloak_dependencies import get_current_keycloak_username
from app.services.burst_location import (
get_burst_location_scheme_detail,
list_burst_location_schemes,
run_burst_location_by_network,
)
@@ -68,64 +66,3 @@ async def locate_burst(
return run_burst_location_by_network(**data.model_dump(), username=username)
except (TypeError, ValueError) as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.get(
"/schemes/",
summary="查询爆管定位方案列表",
description="获取指定网络的所有爆管定位方案"
)
async def query_burst_schemes(
network: str = Query(..., description="管网名称(或数据库名称)"),
query_date: datetime | None = Query(None, description="查询日期(可选)")
) -> list[dict[str, Any]]:
"""
获取爆管定位方案列表。
查询指定网络的所有已配置的爆管定位方案,
可按日期进行筛选。
Args:
network: 管网名称(或数据库名称)
query_date: 查询日期(可选)
Returns:
爆管定位方案列表
Raises:
HTTPException: 当查询失败时
"""
try:
return list_burst_location_schemes(network=network, query_date=query_date)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.get(
"/schemes/{scheme_name}",
summary="获取爆管定位方案详情",
description="获取指定爆管定位方案的详细信息"
)
async def query_burst_scheme_detail(
network: str = Query(..., description="管网名称(或数据库名称)"),
scheme_name: str = Path(..., description="爆管定位方案名称")
) -> dict[str, Any]:
"""
获取爆管定位方案详情。
查询指定爆管定位方案的完整配置和参数信息。
Args:
network: 管网名称(或数据库名称)
scheme_name: 爆管定位方案名称
Returns:
包含方案详情的字典
Raises:
HTTPException: 当查询失败时
"""
try:
return get_burst_location_scheme_detail(network=network, scheme_name=scheme_name)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
+1 -66
View File
@@ -2,13 +2,11 @@ import os
from typing import Any
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, Query, Path, Body
from fastapi import APIRouter, Depends, HTTPException, Body
from pydantic import BaseModel, Field
from app.auth.keycloak_dependencies import get_current_keycloak_username
from app.services.leakage_identifier import (
get_leakage_identify_scheme_detail,
list_leakage_identify_schemes,
run_leakage_identification,
)
@@ -68,66 +66,3 @@ async def identify_leakage(
return run_leakage_identification(**data.model_dump(), username=username)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.get(
"/schemes/",
summary="查询漏损识别方案列表",
description="获取指定网络的所有漏损识别方案"
)
async def query_leakage_schemes(
network: str = Query(..., description="管网名称(或数据库名称)"),
query_date: datetime | None = Query(None, description="查询日期(可选)")
) -> list[dict[str, Any]]:
"""
获取漏损识别方案列表。
查询指定网络的所有已配置的漏损识别方案,
可按日期进行筛选。
Args:
network: 管网名称(或数据库名称)
query_date: 查询日期(可选)
Returns:
漏损识别方案列表
Raises:
HTTPException: 当查询失败时
"""
try:
return list_leakage_identify_schemes(network=network, query_date=query_date)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.get(
"/schemes/{scheme_name}",
summary="获取漏损识别方案详情",
description="获取指定漏损识别方案的详细信息"
)
async def query_leakage_scheme_detail(
network: str = Query(..., description="管网名称(或数据库名称)"),
scheme_name: str = Path(..., description="漏损识别方案名称")
) -> dict[str, Any]:
"""
获取漏损识别方案详情。
查询指定漏损识别方案的完整配置和参数信息。
Args:
network: 管网名称(或数据库名称)
scheme_name: 漏损识别方案名称
Returns:
包含方案详情的字典
Raises:
HTTPException: 当查询失败时
"""
try:
return get_leakage_identify_scheme_detail(
network=network, scheme_name=scheme_name
)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
+32 -4
View File
@@ -1,6 +1,9 @@
from fastapi import APIRouter, Query
from typing import Any, List, Dict
from datetime import datetime
from fastapi import APIRouter, HTTPException, Path, Query
from typing import Any
from app.services.tjnetwork import get_scheme_schema, get_scheme, get_all_schemes
from app.services.scheme_management import query_scheme_detail
from app.services.time_api import extract_date
router = APIRouter()
@@ -24,10 +27,35 @@ async def fastapi_get_scheme(network: str = Query(..., description="管网名称
@router.get("/schemes", summary="获取所有方案", description="获取指定网络的所有方案信息")
@router.get("/getallschemes/", summary="获取所有方案(旧路径)", description="获取指定网络的所有方案信息", deprecated=True)
async def fastapi_get_all_schemes(network: str = Query(..., description="管网名称(或数据库名称)")) -> list[dict[Any, Any]]:
async def fastapi_get_all_schemes(
network: str = Query(..., description="管网名称(或数据库名称)"),
scheme_type: str | None = Query(None, description="方案类型;为空时返回全部类型"),
query_date: datetime | None = Query(None, description="查询日期(可选)"),
) -> list[dict[Any, Any]]:
"""
获取所有方案列表
返回指定网络中所有可用的方案
"""
return get_all_schemes(network)
parsed_date = (
extract_date(query_date, field_name="query_date")
if query_date is not None
else None
)
return get_all_schemes(network, scheme_type=scheme_type, query_date=parsed_date)
@router.get("/schemes/{scheme_name}", summary="获取方案详情", description="按方案类型获取指定方案详情")
async def fastapi_get_scheme_detail(
scheme_name: str = Path(..., description="方案名称"),
network: str = Query(..., description="管网名称(或数据库名称)"),
scheme_type: str | None = Query(None, description="方案类型;为空时返回通用方案详情"),
) -> dict[Any, Any]:
result = query_scheme_detail(
name=network,
scheme_name=scheme_name,
scheme_type=scheme_type,
)
if not result:
raise HTTPException(status_code=404, detail=f"Scheme {scheme_name} not found")
return result
+1 -1
View File
@@ -476,7 +476,7 @@ def _get_simulation_scheme_burst_ids(
) -> list[str]:
if not scheme_name:
return []
rows = query_scheme_list(network) or []
rows = query_scheme_list(network, scheme_type=scheme_type) or []
for row in rows:
if len(row) < 7:
continue
+118 -3
View File
@@ -154,10 +154,16 @@ def delete_scheme_info(name: str, scheme_name: str) -> None:
# 2025/03/23
def query_scheme_list(name: str) -> list:
def query_scheme_list(
name: str,
scheme_type: str | None = None,
query_date: date | None = None,
) -> list:
"""
查询pg数据库中的scheme_list,按照 create_time 降序排列,离现在时间最近的记录排在最前面
:param name: 项目名称(数据库名称)
:param scheme_type: 方案类型;为空时返回全部类型
:param query_date: 查询日期;为空时不按日期过滤
:return: 返回查询结果的所有行
"""
try:
@@ -166,8 +172,38 @@ def query_scheme_list(name: str) -> list:
# 连接到 PostgreSQL 数据库(这里是数据库 "bb"
with psycopg.connect(conn_string) as conn:
with conn.cursor() as cur:
# 按 create_time 降序排列
cur.execute("SELECT * FROM scheme_list ORDER BY create_time DESC")
if scheme_type and query_date is not None:
cur.execute(
"""
SELECT *
FROM scheme_list
WHERE scheme_type = %s AND DATE(create_time) = %s
ORDER BY create_time DESC
""",
(scheme_type, query_date),
)
elif scheme_type:
cur.execute(
"""
SELECT *
FROM scheme_list
WHERE scheme_type = %s
ORDER BY create_time DESC
""",
(scheme_type,),
)
elif query_date is not None:
cur.execute(
"""
SELECT *
FROM scheme_list
WHERE DATE(create_time) = %s
ORDER BY create_time DESC
""",
(query_date,),
)
else:
cur.execute("SELECT * FROM scheme_list ORDER BY create_time DESC")
rows = cur.fetchall()
return rows
@@ -175,6 +211,85 @@ def query_scheme_list(name: str) -> list:
print(f"查询错误:{e}")
def _filter_scheme_detail_scope(
result: dict,
name: str,
scheme_type: str | None = None,
) -> dict:
if not result:
return {}
if scheme_type and result.get("scheme_type") != scheme_type:
return {}
network = result.get("network")
if network not in (None, name):
return {}
return result
def query_scheme_detail(
name: str,
scheme_name: str,
scheme_type: str | None = None,
) -> dict:
if scheme_type == "dma_leak_identification":
return _filter_scheme_detail_scope(
query_leakage_identify_scheme_detail(name, scheme_name),
name,
scheme_type,
)
if scheme_type == "burst_detection":
return _filter_scheme_detail_scope(
query_burst_detection_scheme_detail(name, scheme_name),
name,
scheme_type,
)
if scheme_type == "burst_location":
return _filter_scheme_detail_scope(
query_burst_location_scheme_detail(name, scheme_name),
name,
scheme_type,
)
conn_string = get_pgconn_string(db_name=name)
with psycopg.connect(conn_string) as conn:
with conn.cursor() as cur:
if scheme_type:
cur.execute(
"""
SELECT scheme_id, scheme_name, scheme_type, username, create_time, scheme_start_time, scheme_detail
FROM public.scheme_list
WHERE scheme_name = %s AND scheme_type = %s
LIMIT 1
""",
(scheme_name, scheme_type),
)
else:
cur.execute(
"""
SELECT scheme_id, scheme_name, scheme_type, username, create_time, scheme_start_time, scheme_detail
FROM public.scheme_list
WHERE scheme_name = %s
LIMIT 1
""",
(scheme_name,),
)
row = cur.fetchone()
if row is None:
return {}
detail = row[6] if isinstance(row[6], dict) else {}
return _filter_scheme_detail_scope({
"scheme_id": row[0],
"scheme_name": row[1],
"scheme_type": row[2],
"username": row[3],
"create_time": row[4],
"scheme_start_time": row[5],
"scheme_detail": detail,
"network": detail.get("network"),
"result_payload": detail.get("result_payload", {}),
}, name, scheme_type)
def store_leakage_identify_result(
name: str,
scheme_name: str,
+28 -4
View File
@@ -1312,8 +1312,34 @@ def get_scheme_schema(name: str) -> dict[str, dict[str, Any]]:
def get_scheme(name: str, schema_name: str) -> dict[str, Any]:
return api.get_scheme(name, schema_name)
def get_all_schemes(name: str) -> list[dict[str, Any]]:
return api.get_all_schemes(name)
def get_all_schemes(
name: str,
scheme_type: str | None = None,
query_date: Any | None = None,
) -> list[dict[str, Any]]:
if scheme_type is None and query_date is None:
return api.get_all_schemes(name)
from app.services.scheme_management import query_scheme_list
rows = query_scheme_list(name, scheme_type=scheme_type, query_date=query_date) or []
columns = [
"scheme_id",
"scheme_name",
"scheme_type",
"username",
"create_time",
"scheme_start_time",
"scheme_detail",
]
result = []
for row in rows:
item = dict(zip(columns, row, strict=False))
detail = item.get("scheme_detail")
if isinstance(detail, dict) and detail.get("network") not in (None, name):
continue
result.append(item)
return result
############################################################
# pipe_risk_probability 41
@@ -1345,5 +1371,3 @@ def get_all_sensor_placements(name: str) -> list[dict[Any, Any]]:
def get_all_burst_locate_results(name: str) -> list[dict[Any, Any]]:
return api.get_all_burst_locate_results(name)