"""告警记录 API""" from datetime import datetime from typing import Optional from fastapi import APIRouter, Depends, Query from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_db from app.core.auth import get_current_user from app.models.device import Device from app.models.alert_event import AlertEvent, AlertTypeEnum from app.models.user import User from app.schemas.alert import AlertEventOut router = APIRouter(prefix="/api/alerts", tags=["告警记录"]) @router.get("", response_model=dict) async def list_alerts( page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), device_id: Optional[int] = None, alert_type: Optional[str] = None, is_resolved: Optional[bool] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): """查询告警记录,支持分页和过滤""" query = select(AlertEvent) count_query = select(func.count(AlertEvent.id)) # 过滤条件 if device_id: query = query.where(AlertEvent.device_id == device_id) count_query = count_query.where(AlertEvent.device_id == device_id) if alert_type: query = query.where(AlertEvent.alert_type == alert_type) count_query = count_query.where(AlertEvent.alert_type == alert_type) if is_resolved is not None: query = query.where(AlertEvent.is_resolved == is_resolved) count_query = count_query.where(AlertEvent.is_resolved == is_resolved) if start_time: query = query.where(AlertEvent.created_at >= start_time) count_query = count_query.where(AlertEvent.created_at >= start_time) if end_time: query = query.where(AlertEvent.created_at <= end_time) count_query = count_query.where(AlertEvent.created_at <= end_time) # 总数 total_result = await db.execute(count_query) total = total_result.scalar() or 0 # 分页 offset = (page - 1) * page_size query = query.order_by(AlertEvent.created_at.desc()).offset(offset).limit(page_size) result = await db.execute(query) events = list(result.scalars().all()) # 关联设备信息 device_ids = {e.device_id for e in events if e.device_id > 0} devices_map = {} if device_ids: dev_result = await db.execute(select(Device).where(Device.id.in_(device_ids))) devices_map = {d.id: d for d in dev_result.scalars().all()} items = [] for e in events: dev = devices_map.get(e.device_id) items.append(AlertEventOut( id=e.id, device_id=e.device_id, device_name=dev.name if dev else "系统", device_ip=dev.ip if dev else "", device_type=dev.device_type.value if dev else "", location=dev.location if dev else "", project_name=dev.project_name if dev else "", alert_type=e.alert_type.value, message=e.message, start_at=e.start_at, end_at=e.end_at, duration_minutes=e.duration_minutes, is_resolved=e.is_resolved, notification_sent=e.notification_sent, created_at=e.created_at, )) return {"items": items, "total": total, "page": page, "page_size": page_size} @router.get("/latest", response_model=list[AlertEventOut]) async def get_latest_alerts( limit: int = Query(10, ge=1, le=50), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): """获取最近的告警""" result = await db.execute( select(AlertEvent) .order_by(AlertEvent.created_at.desc()) .limit(limit) ) events = list(result.scalars().all()) device_ids = {e.device_id for e in events if e.device_id > 0} devices_map = {} if device_ids: dev_result = await db.execute(select(Device).where(Device.id.in_(device_ids))) devices_map = {d.id: d for d in dev_result.scalars().all()} items = [] for e in events: dev = devices_map.get(e.device_id) items.append(AlertEventOut( id=e.id, device_id=e.device_id, device_name=dev.name if dev else "系统", device_ip=dev.ip if dev else "", device_type=dev.device_type.value if dev else "", location=dev.location if dev else "", project_name=dev.project_name if dev else "", alert_type=e.alert_type.value, message=e.message, start_at=e.start_at, end_at=e.end_at, duration_minutes=e.duration_minutes, is_resolved=e.is_resolved, notification_sent=e.notification_sent, created_at=e.created_at, )) return items