fix(alarm): 修复告警列表和汇总显示 camera_code 问题
问题: - 告警列表和汇总页面显示 camera_code(例如 cam_1f0e3dad9990)而不是中文摄像头名称 - _get_camera_info 函数过早检查 token 导致查询失败 修复: 1. 移除 camera_code 查询路径中不必要的 token 检查 - /api/ai/camera/get 已加入白名单,不需要认证 - 仅对 app/stream 格式保留 token 检查 2. 修复告警列表页面摄像头名称显示 - 将 _alarm_to_camel 改为 async 函数 - 添加摄像头名称查询逻辑(三级 fallback) - 使用 asyncio.gather 并发查询提升性能 3. 添加调试日志 - 记录摄像头查询请求和响应 - 便于排查问题 测试结果: - 告警汇总: cam_1f0e3dad9990 → "大堂吧台3" ✓ - 告警列表: cam_1f0e3dad9990 → "大堂吧台3" ✓ 相关文件: - app/routers/yudao_aiot_alarm.py
This commit is contained in:
@@ -29,7 +29,7 @@ from app.utils.logger import logger
|
|||||||
router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"])
|
router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"])
|
||||||
|
|
||||||
|
|
||||||
def _alarm_to_camel(alarm_dict: dict) -> dict:
|
async def _alarm_to_camel(alarm_dict: dict, current_user: dict = None) -> dict:
|
||||||
"""将 alarm_event 字典转换为前端 camelCase 格式(兼容前端旧字段名)"""
|
"""将 alarm_event 字典转换为前端 camelCase 格式(兼容前端旧字段名)"""
|
||||||
# snapshot_url: 根据存储方式转为可访问 URL
|
# snapshot_url: 根据存储方式转为可访问 URL
|
||||||
storage = get_oss_storage()
|
storage = get_oss_storage()
|
||||||
@@ -61,6 +61,27 @@ def _alarm_to_camel(alarm_dict: dict) -> dict:
|
|||||||
|
|
||||||
alarm_id = alarm_dict.get("alarm_id")
|
alarm_id = alarm_dict.get("alarm_id")
|
||||||
|
|
||||||
|
# 查询摄像头名称(三级 fallback 策略)
|
||||||
|
device_id = alarm_dict.get("device_id")
|
||||||
|
device_name = device_id # 默认使用 device_id
|
||||||
|
|
||||||
|
if current_user and device_id:
|
||||||
|
try:
|
||||||
|
camera_info = await _get_camera_info(device_id, current_user)
|
||||||
|
if camera_info:
|
||||||
|
# 1. 优先使用 gb_name(去除 "/" 后缀)
|
||||||
|
gb_name = camera_info.get("gbName") or camera_info.get("gb_name")
|
||||||
|
if gb_name:
|
||||||
|
device_name = gb_name.split("/")[0]
|
||||||
|
# 2. 其次使用 name 字段
|
||||||
|
elif camera_info.get("name"):
|
||||||
|
device_name = camera_info.get("name")
|
||||||
|
# 3. 最后才使用 app 字段
|
||||||
|
elif camera_info.get("app"):
|
||||||
|
device_name = camera_info.get("app")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"告警列表查询摄像头信息失败: device_id={device_id}, error={e}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
# 新字段(三表结构)
|
# 新字段(三表结构)
|
||||||
"alarmId": alarm_id,
|
"alarmId": alarm_id,
|
||||||
@@ -68,7 +89,7 @@ def _alarm_to_camel(alarm_dict: dict) -> dict:
|
|||||||
"alarmTypeName": _get_alarm_type_name(alarm_dict.get("alarm_type")),
|
"alarmTypeName": _get_alarm_type_name(alarm_dict.get("alarm_type")),
|
||||||
"algorithmCode": alarm_dict.get("algorithm_code"),
|
"algorithmCode": alarm_dict.get("algorithm_code"),
|
||||||
"deviceId": alarm_dict.get("device_id"),
|
"deviceId": alarm_dict.get("device_id"),
|
||||||
"deviceName": alarm_dict.get("device_id"),
|
"deviceName": device_name,
|
||||||
"sceneId": alarm_dict.get("scene_id"),
|
"sceneId": alarm_dict.get("scene_id"),
|
||||||
"eventTime": alarm_dict.get("event_time"),
|
"eventTime": alarm_dict.get("event_time"),
|
||||||
"firstFrameTime": alarm_dict.get("first_frame_time"),
|
"firstFrameTime": alarm_dict.get("first_frame_time"),
|
||||||
@@ -140,7 +161,8 @@ async def get_alert_page(
|
|||||||
page_size=pageSize,
|
page_size=pageSize,
|
||||||
)
|
)
|
||||||
|
|
||||||
alarm_list = [_alarm_to_camel(a.to_dict()) for a in alarms]
|
# 并发查询所有告警的摄像头名称
|
||||||
|
alarm_list = await asyncio.gather(*[_alarm_to_camel(a.to_dict(), current_user) for a in alarms])
|
||||||
|
|
||||||
return YudaoResponse.page(
|
return YudaoResponse.page(
|
||||||
list_data=alarm_list,
|
list_data=alarm_list,
|
||||||
@@ -165,7 +187,7 @@ async def get_alert(
|
|||||||
if not alarm_dict:
|
if not alarm_dict:
|
||||||
raise HTTPException(status_code=404, detail="告警不存在")
|
raise HTTPException(status_code=404, detail="告警不存在")
|
||||||
|
|
||||||
return YudaoResponse.success(_alarm_to_camel(alarm_dict))
|
return YudaoResponse.success(await _alarm_to_camel(alarm_dict, current_user))
|
||||||
|
|
||||||
|
|
||||||
@router.put("/alert/handle")
|
@router.put("/alert/handle")
|
||||||
@@ -359,13 +381,6 @@ async def _get_camera_info(device_id: str, current_user: dict) -> Optional[dict]
|
|||||||
从 WVP 查询摄像头信息
|
从 WVP 查询摄像头信息
|
||||||
支持 camera_code 和 app/stream 两种格式
|
支持 camera_code 和 app/stream 两种格式
|
||||||
"""
|
"""
|
||||||
# 获取 token
|
|
||||||
token = current_user.get("access_token") or current_user.get("token")
|
|
||||||
if not token:
|
|
||||||
return None
|
|
||||||
|
|
||||||
headers = {"Authorization": f"Bearer {token}"}
|
|
||||||
|
|
||||||
# 如果是 camera_code 格式(cam_xxxxxxxxxxxx)
|
# 如果是 camera_code 格式(cam_xxxxxxxxxxxx)
|
||||||
if device_id.startswith("cam_"):
|
if device_id.startswith("cam_"):
|
||||||
try:
|
try:
|
||||||
@@ -375,8 +390,10 @@ async def _get_camera_info(device_id: str, current_user: dict) -> Optional[dict]
|
|||||||
f"{WVP_API_BASE}/api/ai/camera/get",
|
f"{WVP_API_BASE}/api/ai/camera/get",
|
||||||
params={"cameraCode": device_id},
|
params={"cameraCode": device_id},
|
||||||
)
|
)
|
||||||
|
logger.info(f"查询摄像头: device_id={device_id}, status={resp.status_code}")
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
data = resp.json()
|
data = resp.json()
|
||||||
|
logger.info(f"WVP 响应: {data}")
|
||||||
if data.get("code") == 0:
|
if data.get("code") == 0:
|
||||||
return data.get("data")
|
return data.get("data")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -384,6 +401,13 @@ async def _get_camera_info(device_id: str, current_user: dict) -> Optional[dict]
|
|||||||
|
|
||||||
# 如果是 app/stream 格式
|
# 如果是 app/stream 格式
|
||||||
elif "/" in device_id:
|
elif "/" in device_id:
|
||||||
|
# 获取 token(app/stream 查询需要认证)
|
||||||
|
token = current_user.get("access_token") or current_user.get("token")
|
||||||
|
if not token:
|
||||||
|
logger.warning(f"查询 app/stream 失败: 缺少 token, device_id={device_id}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
parts = device_id.split("/", 1)
|
parts = device_id.split("/", 1)
|
||||||
if len(parts) == 2:
|
if len(parts) == 2:
|
||||||
app, stream = parts
|
app, stream = parts
|
||||||
|
|||||||
Reference in New Issue
Block a user