848f804169
- FastAPI 后端 + Vue 3 前端 - Docker Compose 一键部署 - Casdoor OAuth 认证集成 - LogHive 集中式日志 - 设备批量 CSV 导入/导出 - WebSocket 实时状态推送 - 企业微信告警通知 - fping 高性能并发 Ping 检测 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
134 lines
4.7 KiB
Python
134 lines
4.7 KiB
Python
"""告警记录 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
|