""" 企微回调路由 处理安保人员在企微卡片上的操作(前往处理/已处理/误报忽略)。 提供告警详情接口供 H5 页面使用。 """ from datetime import datetime from fastapi import APIRouter, Depends, Query from pydantic import BaseModel from typing import Optional from app.yudao_compat import YudaoResponse from app.models import get_session, AlarmEvent, AlarmLlmAnalysis from app.services.alarm_event_service import get_alarm_event_service, AlarmEventService from app.utils.logger import logger router = APIRouter(prefix="/api/wechat", tags=["企微回调"]) class AlarmActionRequest(BaseModel): """企微卡片操作请求""" alarm_id: str action: str # confirm / complete / ignore operator_uid: str # 企微 userid remark: Optional[str] = None @router.get("/alarm_detail") async def get_alarm_detail(alarm_id: str = Query(..., description="告警ID")): """ 告警详情接口(供 H5 页面使用,无认证) 返回告警基本信息 + VLM 分析描述 """ db = get_session() try: alarm = db.query(AlarmEvent).filter(AlarmEvent.alarm_id == alarm_id).first() if not alarm: return YudaoResponse.error(404, "告警不存在") # 查 VLM 分析结果 vlm_desc = "" analysis = db.query(AlarmLlmAnalysis).filter( AlarmLlmAnalysis.alarm_id == alarm_id ).order_by(AlarmLlmAnalysis.id.desc()).first() if analysis: vlm_desc = analysis.summary or "" return YudaoResponse.success({ "alarm_id": alarm.alarm_id, "alarm_type": alarm.alarm_type, "device_id": alarm.device_id, "scene_id": alarm.scene_id, "event_time": alarm.event_time.strftime('%Y-%m-%d %H:%M:%S') if alarm.event_time else "", "alarm_level": alarm.alarm_level, "alarm_status": alarm.alarm_status, "handle_status": alarm.handle_status, "snapshot_url": alarm.snapshot_url or "", "handler": alarm.handler or "", "handle_remark": alarm.handle_remark or "", "vlm_description": vlm_desc, }) finally: db.close() @router.post("/callback/alarm_action") async def alarm_action_callback( req: AlarmActionRequest, service: AlarmEventService = Depends(get_alarm_event_service), ): """ 企微告警操作回调(无认证,由 H5 页面调用) action: - confirm: 前往处理 → handle_status=HANDLING - complete: 已处理完成 → handle_status=DONE, alarm_status=CLOSED - ignore: 误报忽略 → alarm_status=FALSE, handle_status=DONE """ action_map = { "confirm": { "alarm_status": "CONFIRMED", "handle_status": "HANDLING", "remark": "前往处理", }, "complete": { "alarm_status": "CLOSED", "handle_status": "DONE", "remark": "手动结单", }, "ignore": { "alarm_status": "FALSE", "handle_status": "DONE", "remark": "标记误报", }, } action_cfg = action_map.get(req.action) if not action_cfg: return YudaoResponse.error(400, f"无效操作: {req.action}") result = service.handle_alarm( alarm_id=req.alarm_id, alarm_status=action_cfg["alarm_status"], handle_status=action_cfg["handle_status"], handler=req.operator_uid, remark=req.remark or action_cfg["remark"], ) if not result: return YudaoResponse.error(404, "告警不存在") logger.info( f"企微操作: alarm={req.alarm_id}, action={req.action}, " f"operator={req.operator_uid}" ) return YudaoResponse.success(True)