添加降雨量与持续时间接口
This commit is contained in:
@@ -195,6 +195,7 @@ class DbnRepository:
|
||||
COUNT(*) as record_count
|
||||
FROM xian_meteorology
|
||||
WHERE datetime BETWEEN %s AND %s
|
||||
AND is_delete = 0
|
||||
AND rainfall_1h IS NOT NULL
|
||||
AND CAST(rainfall_1h AS DOUBLE PRECISION) > 0
|
||||
GROUP BY lon, lat
|
||||
@@ -259,6 +260,7 @@ class DbnRepository:
|
||||
ST_SetSRID(ST_MakePoint(%s, %s), 4326)
|
||||
) as dist
|
||||
FROM xian_meteorology
|
||||
WHERE is_delete = 0
|
||||
) t
|
||||
WHERE dist < 50000
|
||||
ORDER BY dist
|
||||
@@ -283,6 +285,7 @@ class DbnRepository:
|
||||
CAST(rainfall_1h AS DOUBLE PRECISION) as rainfall
|
||||
FROM xian_meteorology
|
||||
WHERE lon = %s AND lat = %s
|
||||
AND is_delete = 0
|
||||
AND datetime BETWEEN %s AND %s
|
||||
ORDER BY datetime DESC
|
||||
"""
|
||||
@@ -326,7 +329,7 @@ class DbnRepository:
|
||||
"""一次性加载所有气象站点坐标到内存(188个站点,约2KB)"""
|
||||
if cls._cached_stations is not None:
|
||||
return cls._cached_stations
|
||||
sql = "SELECT DISTINCT lon, lat FROM xian_meteorology"
|
||||
sql = "SELECT DISTINCT lon, lat FROM xian_meteorology WHERE is_delete = 0"
|
||||
cls._cached_stations = db_helper.execute_query(sql)
|
||||
logger.info(f"已缓存 {len(cls._cached_stations)} 个气象站点坐标")
|
||||
return cls._cached_stations
|
||||
@@ -407,6 +410,7 @@ class DbnRepository:
|
||||
SELECT lon, lat, datetime, CAST(rainfall_1h AS DOUBLE PRECISION) as rainfall
|
||||
FROM xian_meteorology
|
||||
WHERE (lon, lat) IN ({placeholders})
|
||||
AND is_delete = 0
|
||||
AND datetime BETWEEN %s AND %s
|
||||
ORDER BY lon, lat, datetime DESC
|
||||
"""
|
||||
@@ -688,6 +692,21 @@ class DbnRepository:
|
||||
return float(result['aspect'])
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_inference_result(inference_id: int) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
根据ID获取推理结果
|
||||
|
||||
Returns:
|
||||
{id, name, event_type, occurred_time, operation_type, condition, result}
|
||||
"""
|
||||
sql = """
|
||||
SELECT id, name, event_type, occurred_time, operation_type, condition, result
|
||||
FROM xian_inference_result
|
||||
WHERE id = %s AND is_delete = 0
|
||||
"""
|
||||
return db_helper.execute_query_one(sql, (inference_id,))
|
||||
|
||||
@staticmethod
|
||||
def save_inference_result(disaster_name: str, event_type: str, occurred_time, operation_type: str,
|
||||
condition: dict, result: list) -> int:
|
||||
|
||||
@@ -12,7 +12,7 @@ class QgisRepository:
|
||||
sql = """
|
||||
SELECT id, name, event_type, occurred_time, condition
|
||||
FROM xian_inference_result
|
||||
WHERE id = %s
|
||||
WHERE id = %s AND is_delete = 0
|
||||
"""
|
||||
rows = db_helper.execute_query(sql, (inference_id,))
|
||||
if not rows:
|
||||
|
||||
@@ -28,6 +28,7 @@ class RainfallRepository:
|
||||
SELECT max(id) as max_id
|
||||
FROM xian_meteorology
|
||||
WHERE datetime BETWEEN %s AND %s
|
||||
AND is_delete = 0
|
||||
"""
|
||||
|
||||
result = db_helper.execute_query_one(sql, (start_time, end_time))
|
||||
@@ -58,6 +59,7 @@ class RainfallRepository:
|
||||
CAST(rainfall_1h AS DOUBLE PRECISION) as rainfall_1h
|
||||
FROM xian_meteorology
|
||||
WHERE datetime BETWEEN %s AND %s
|
||||
AND is_delete = 0
|
||||
ORDER BY lon, lat, datetime DESC
|
||||
"""
|
||||
|
||||
@@ -100,5 +102,100 @@ class RainfallRepository:
|
||||
return station_data
|
||||
|
||||
|
||||
def get_district_rainfall_summary(self, query_time, region_code: Optional[str] = None) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
按行政区聚合降雨统计(取区内最大站点值)
|
||||
|
||||
Args:
|
||||
query_time: 查询时间
|
||||
region_code: 行政区划代码,不传则返回所有区
|
||||
|
||||
Returns:
|
||||
[{district_name, district_code, rainfall, duration_hours}, ...]
|
||||
"""
|
||||
start_time, end_time = time_converter.to_db_time_range(query_time, hours=72)
|
||||
|
||||
# 一次查询:area_code + lon + lat + rainfall_1h
|
||||
sql = """
|
||||
SELECT area_code, lon, lat, datetime,
|
||||
CAST(rainfall_1h AS DOUBLE PRECISION) as rainfall_1h
|
||||
FROM xian_meteorology
|
||||
WHERE datetime BETWEEN %s AND %s
|
||||
AND is_delete = 0
|
||||
ORDER BY area_code, lon, lat, datetime DESC
|
||||
"""
|
||||
rows = db_helper.execute_query(sql, (start_time, end_time))
|
||||
if not rows:
|
||||
return []
|
||||
|
||||
# 按站点分组,计算 accum_rain + duration_hours(复用现有算法)
|
||||
from itertools import groupby
|
||||
|
||||
station_stats: Dict[tuple, Dict[str, Any]] = {} # (area_code, lon, lat) → stats
|
||||
for (area_code, lon, lat), group in groupby(rows,
|
||||
key=lambda r: (r['area_code'], r['lon'], r['lat'])):
|
||||
accum_rain = 0.0
|
||||
duration_hours = 0
|
||||
consecutive_no_rain = 0
|
||||
for row in group:
|
||||
rainfall = float(row['rainfall_1h']) if row['rainfall_1h'] else 0.0
|
||||
if rainfall > 0:
|
||||
accum_rain += rainfall
|
||||
duration_hours += 1
|
||||
consecutive_no_rain = 0
|
||||
else:
|
||||
consecutive_no_rain += 1
|
||||
if consecutive_no_rain >= 3:
|
||||
break
|
||||
if accum_rain > 0:
|
||||
duration_hours += 1
|
||||
|
||||
key = (area_code, lon, lat)
|
||||
station_stats[key] = {
|
||||
'area_code': area_code,
|
||||
'accum_rain': accum_rain,
|
||||
'duration_hours': duration_hours
|
||||
}
|
||||
|
||||
# 按 area_code 聚合:取区内最大降雨站点
|
||||
district_max: Dict[str, Dict[str, Any]] = {}
|
||||
for key, stats in station_stats.items():
|
||||
code = stats['area_code']
|
||||
if region_code and code != region_code:
|
||||
continue
|
||||
if code not in district_max or stats['accum_rain'] > district_max[code]['rainfall']:
|
||||
district_max[code] = {
|
||||
'district_code': code,
|
||||
'rainfall': round(stats['accum_rain'], 1),
|
||||
'duration_hours': stats['duration_hours']
|
||||
}
|
||||
|
||||
if not district_max:
|
||||
return []
|
||||
|
||||
# 查 xian_district 获取名称
|
||||
codes = list(district_max.keys())
|
||||
placeholders = ', '.join(['%s'] * len(codes))
|
||||
sql = f"SELECT code, name FROM xian_district WHERE code IN ({placeholders}) AND is_delete = 0"
|
||||
district_rows = db_helper.execute_query(sql, tuple(codes))
|
||||
code_to_name = {r['code']: r['name'] for r in district_rows}
|
||||
|
||||
result = []
|
||||
for code, info in district_max.items():
|
||||
name = code_to_name.get(code)
|
||||
if name is None:
|
||||
continue # 跳过 xian_district 中不存在的代码
|
||||
result.append({
|
||||
'district_name': name,
|
||||
'district_code': code,
|
||||
'rainfall': info['rainfall'],
|
||||
'duration_hours': info['duration_hours']
|
||||
})
|
||||
|
||||
# 按名称排序
|
||||
result.sort(key=lambda x: x['district_name'])
|
||||
return result
|
||||
|
||||
|
||||
# 创建全局实例
|
||||
rainfall_repository = RainfallRepository()
|
||||
|
||||
Reference in New Issue
Block a user