feat(alerts): 飞书通知支持 Web 界面配置(数据库存储+热更新)
1. 新增 notification_config 模型,飞书配置存数据库(单行id=1) 2. feishu_service 改为从数据库读配置,支持热更新,Web保存即生效 3. alerts.py 新增接口: - GET /alerts/notify/feishu/config 读配置(secret只返回是否已设) - PUT /alerts/notify/feishu/config 保存配置+热更新 (status/test 同步改为走数据库配置) 4. 前端告警中心增加「飞书通知设置」弹窗: - 开关/Webhook/签名密钥/最低级别/类型白名单 - 保存配置、发送测试按钮 5. alert_service.create_alert 推送时按数据库配置判断 配置无需改文件/重启,前端界面直接保存即生效。
This commit is contained in:
@@ -185,11 +185,57 @@ def detect_offline_devices(db: Session = Depends(get_db)):
|
||||
|
||||
# ========== 飞书告警通知 ==========
|
||||
|
||||
@router.get("/notify/feishu/status", summary="获取飞书通知配置状态")
|
||||
def get_feishu_status():
|
||||
"""查看飞书通知是否已配置(不返回密钥等敏感信息)"""
|
||||
@router.get("/notify/feishu/config", summary="获取飞书通知配置")
|
||||
def get_feishu_config(db: Session = Depends(get_db)):
|
||||
"""读取飞书通知配置(Web 界面显示用,不返回 secret 原文只返回是否已设置)"""
|
||||
from app.models.notification import NotificationConfig
|
||||
row = NotificationConfig.get_singleton(db)
|
||||
return {
|
||||
"feishu_enabled": bool(row.feishu_enabled),
|
||||
"feishu_webhook_url": row.feishu_webhook_url or "",
|
||||
"feishu_secret_set": bool(row.feishu_secret),
|
||||
"feishu_min_severity": row.feishu_min_severity or "warning",
|
||||
"feishu_alert_types": row.feishu_alert_types or "",
|
||||
}
|
||||
|
||||
|
||||
@router.put("/notify/feishu/config", summary="保存飞书通知配置")
|
||||
def update_feishu_config(
|
||||
feishu_enabled: bool,
|
||||
feishu_webhook_url: str = "",
|
||||
feishu_secret: str = "",
|
||||
feishu_min_severity: str = "warning",
|
||||
feishu_alert_types: str = "",
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""保存飞书通知配置到数据库并热更新(无需重启后端)"""
|
||||
from app.models.notification import NotificationConfig
|
||||
row = NotificationConfig.get_singleton(db)
|
||||
row.feishu_enabled = bool(feishu_enabled)
|
||||
row.feishu_webhook_url = (feishu_webhook_url or "").strip()
|
||||
# 仅当传入新 secret 时才覆盖(避免 UI 回显时清空已有 secret)
|
||||
if feishu_secret:
|
||||
row.feishu_secret = feishu_secret.strip()
|
||||
row.feishu_min_severity = feishu_min_severity or "warning"
|
||||
row.feishu_alert_types = (feishu_alert_types or "").strip()
|
||||
db.commit()
|
||||
|
||||
# 热更新运行时的飞书服务
|
||||
from app.services.feishu_service import reload_feishu_service
|
||||
svc = reload_feishu_service(db)
|
||||
|
||||
return {
|
||||
"message": "飞书通知配置已保存并生效",
|
||||
"success": True,
|
||||
"configured": svc.is_configured(),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/notify/feishu/status", summary="获取飞书通知运行状态")
|
||||
def get_feishu_status(db: Session = Depends(get_db)):
|
||||
"""查看飞书通知运行状态"""
|
||||
from app.services.feishu_service import get_feishu_service
|
||||
svc = get_feishu_service()
|
||||
svc = get_feishu_service(db)
|
||||
return {
|
||||
"enabled": svc.enabled,
|
||||
"configured": bool(svc.webhook_url),
|
||||
@@ -202,14 +248,14 @@ def get_feishu_status():
|
||||
|
||||
|
||||
@router.post("/notify/feishu/test", summary="发送飞书测试告警")
|
||||
def test_feishu_notification():
|
||||
def test_feishu_notification(db: Session = Depends(get_db)):
|
||||
"""发送一条测试告警到飞书,验证 webhook 配置是否正确"""
|
||||
from app.services.feishu_service import get_feishu_service
|
||||
svc = get_feishu_service()
|
||||
svc = get_feishu_service(db)
|
||||
if not svc.is_configured():
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="飞书通知未启用或未配置 webhook。请在 backend/.env 设置 FEISHU_ENABLED=true 和 FEISHU_WEBHOOK_URL"
|
||||
detail="飞书通知未启用或未配置 webhook。请在告警中心「飞书通知设置」中配置并开启"
|
||||
)
|
||||
ok = svc.send_alert({
|
||||
"alert_type": "new_device_detected",
|
||||
|
||||
Reference in New Issue
Block a user