feat(alarm): 统一使用stream编号作为摄像头ID

- 设备汇总和告警列表统一使用stream(012、008等)作为cameraId
- 支持camera_code格式:从WVP API查询获取stream
- 支持app/stream格式:直接解析提取stream部分
- 优化批量查询性能,使用camera_info_map减少重复查询
This commit is contained in:
2026-02-24 14:49:36 +08:00
parent 4bd369813e
commit 0d27e98d09

View File

@@ -28,12 +28,13 @@ from app.utils.logger import logger
router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"]) router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"])
async def _alarm_to_camel(alarm_dict: dict, name_map: dict = None) -> dict: async def _alarm_to_camel(alarm_dict: dict, camera_info_map: dict = None, camera_service=None) -> dict:
"""将 alarm_event 字典转换为前端 camelCase 格式(兼容前端旧字段名) """将 alarm_event 字典转换为前端 camelCase 格式(兼容前端旧字段名)
Args: Args:
alarm_dict: 告警字典 alarm_dict: 告警字典
name_map: 摄像头名称映射 {device_id: display_name},可选 camera_info_map: 摄像头信息映射 {device_id: camera_info},可选
camera_service: 摄像头服务实例,可选
""" """
# snapshot_url: 根据存储方式转为可访问 URL # snapshot_url: 根据存储方式转为可访问 URL
storage = get_oss_storage() storage = get_oss_storage()
@@ -64,13 +65,29 @@ async def _alarm_to_camel(alarm_dict: dict, name_map: dict = None) -> dict:
duration_minutes = round(duration_ms / 60000, 1) if duration_ms else None duration_minutes = round(duration_ms / 60000, 1) if duration_ms else None
alarm_id = alarm_dict.get("alarm_id") alarm_id = alarm_dict.get("alarm_id")
# 获取摄像头显示名称(从缓存映射中获取)
device_id = alarm_dict.get("device_id") device_id = alarm_dict.get("device_id")
device_name = device_id # 默认使用 device_id
if name_map and device_id in name_map: # 获取摄像头信息
device_name = name_map[device_id] camera_info = None
if camera_info_map and device_id in camera_info_map:
camera_info = camera_info_map[device_id]
# 获取摄像头名称
device_name = device_id # 默认值
if camera_service and camera_info:
device_name = camera_service.format_display_name(device_id, camera_info)
# 提取摄像头ID统一使用stream作为编号
camera_id = device_id # 默认值
if camera_info:
stream = camera_info.get("stream")
if stream:
camera_id = stream
elif device_id and "/" in device_id:
# app/stream 格式,直接解析
parts = device_id.split("/", 1)
if len(parts) == 2:
camera_id = parts[1]
return { return {
# 新字段(三表结构) # 新字段(三表结构)
@@ -102,8 +119,9 @@ async def _alarm_to_camel(alarm_dict: dict, name_map: dict = None) -> dict:
# 兼容前端旧字段名 # 兼容前端旧字段名
"id": alarm_id, "id": alarm_id,
"alertNo": alarm_id, "alertNo": alarm_id,
"cameraId": alarm_dict.get("device_id"), # 保持原始ID用于查询 "deviceId": device_id, # 原始ID用于查询
"cameraName": device_name, # 显示用的中文名称 "cameraId": camera_id, # 摄像头IDstream编号
"cameraName": device_name, # 摄像头名称
"alertType": alarm_dict.get("alarm_type"), "alertType": alarm_dict.get("alarm_type"),
"alertTypeName": _get_alarm_type_name(alarm_dict.get("alarm_type")), "alertTypeName": _get_alarm_type_name(alarm_dict.get("alarm_type")),
"confidence": confidence_pct, "confidence": confidence_pct,
@@ -155,12 +173,12 @@ async def get_alert_page(
# 提取所有唯一的 device_id # 提取所有唯一的 device_id
device_ids = list(set(a.device_id for a in alarms if a.device_id)) device_ids = list(set(a.device_id for a in alarms if a.device_id))
# 批量查询摄像头名称(去重+并发优化) # 批量查询摄像头信息(去重+并发优化)
camera_service = get_camera_name_service() camera_service = get_camera_name_service()
name_map = await camera_service.get_display_names_batch(device_ids) camera_info_map = await camera_service.get_camera_infos_batch(device_ids)
# 转换为 camelCase 格式(使用缓存的名称映射) # 转换为 camelCase 格式(使用摄像头信息映射)
alarm_list = [await _alarm_to_camel(a.to_dict(), name_map) for a in alarms] alarm_list = [await _alarm_to_camel(a.to_dict(), camera_info_map, camera_service) for a in alarms]
return YudaoResponse.page( return YudaoResponse.page(
list_data=alarm_list, list_data=alarm_list,
@@ -274,12 +292,29 @@ async def get_device_summary_page(
compat_list = [] compat_list = []
for item in result.get("list", []): for item in result.get("list", []):
device_id = item.get("deviceId") device_id = item.get("deviceId")
# 使用配置化服务获取显示名称
device_name = await camera_service.get_display_name(device_id)
item["cameraId"] = device_id # 批量查询摄像头信息
item["cameraName"] = device_name camera_info = await camera_service.get_camera_info(device_id)
item["deviceName"] = device_name
# 提取摄像头名称
device_name = camera_service.format_display_name(device_id, camera_info)
# 提取摄像头ID统一使用stream作为编号
camera_id = device_id # 默认值
if camera_info:
stream = camera_info.get("stream")
if stream:
camera_id = stream
elif "/" in device_id:
# app/stream 格式,直接解析
parts = device_id.split("/", 1)
if len(parts) == 2:
camera_id = parts[1]
item["deviceId"] = device_id # 原始ID用于查询
item["cameraId"] = camera_id # 摄像头IDstream编号
item["cameraName"] = device_name # 摄像头名称
item["deviceName"] = device_name # 摄像头名称(兼容)
item["pendingCount"] = item.get("unhandledCount") item["pendingCount"] = item.get("unhandledCount")
item["lastAlertTime"] = item.get("lastEventTime") item["lastAlertTime"] = item.get("lastEventTime")
item["lastAlertType"] = item.get("lastAlarmType") item["lastAlertType"] = item.get("lastAlarmType")