Files
aiops/backend/internal/api/handlers/alert_contacts.go
T
attacker e1cfbaf45e feat: 网络双线图+告警联系人/联系组+Agent v2.0.0 + 一键报警阈值
- HostMonitor: 网络改为双线图 rx/tx 网卡带宽吞吐(双Area线), 移除单rx图
- Agent: 默认版本号从 dev 改为 v2.0.0, 重建二进制 5.2MB
- 告警中心: 新增报警联系人/报警联系组 Tab, ContactDialog/ContactGroupDialog
- 后端: AlertContact/AlertContactGroup 模型+CRUD, monitor_alert_contacts/groups 表
- 路由: /alerts/contacts + /alerts/contact-groups 8个REST端点
- 一键报警: 更新描述为6条规则(含TCP+进程), 切换到 /alerts/quick-setup
- 测试规则: 内存>10% 触发告警已创建, 飞书通知验证通过
2026-06-24 08:47:40 +00:00

152 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"encoding/json"
"net/http"
"strconv"
"ezops/internal/models"
"github.com/gin-gonic/gin"
)
// 告警联系人 + 联系组 CRUD(AlertHandler 方法接收者) // Logan.Li
// ==================== 联系人 ====================
// ListContacts GET /alerts/contacts
func (h *AlertHandler) ListContacts(c *gin.Context) {
var contacts []models.AlertContact
h.db.Order("created_at DESC").Find(&contacts)
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: models.ListResponse{List: contacts, Total: int64(len(contacts))},
})
}
// CreateContact POST /alerts/contacts
func (h *AlertHandler) CreateContact(c *gin.Context) {
var req models.CreateContactRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "请求参数错误: " + err.Error()})
return
}
contact := models.AlertContact{
Name: req.Name,
Phone: req.Phone,
Email: req.Email,
Dingtalk: req.Dingtalk,
Feishu: req.Feishu,
Wechat: req.Wechat,
}
if err := h.db.Create(&contact).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "创建失败"})
return
}
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "创建成功", Data: contact})
}
// UpdateContact PUT /alerts/contacts/:id
func (h *AlertHandler) UpdateContact(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var req models.UpdateContactRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "请求参数错误"})
return
}
var contact models.AlertContact
if err := h.db.First(&contact, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "联系人不存在"})
return
}
updates := map[string]interface{}{}
if req.Name != "" { updates["name"] = req.Name }
if req.Phone != "" { updates["phone"] = req.Phone }
if req.Email != "" { updates["email"] = req.Email }
if req.Dingtalk != "" { updates["dingtalk"] = req.Dingtalk }
if req.Feishu != "" { updates["feishu"] = req.Feishu }
if req.Wechat != "" { updates["wechat"] = req.Wechat }
h.db.Model(&contact).Updates(updates)
h.db.First(&contact, id)
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "更新成功", Data: contact})
}
// DeleteContact DELETE /alerts/contacts/:id
func (h *AlertHandler) DeleteContact(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
if err := h.db.Delete(&models.AlertContact{}, id).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "删除失败"})
return
}
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "删除成功"})
}
// ==================== 联系组 ====================
// ListContactGroups GET /alerts/contact-groups
func (h *AlertHandler) ListContactGroups(c *gin.Context) {
var groups []models.AlertContactGroup
h.db.Order("created_at DESC").Find(&groups)
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: models.ListResponse{List: groups, Total: int64(len(groups))},
})
}
// CreateContactGroup POST /alerts/contact-groups
func (h *AlertHandler) CreateContactGroup(c *gin.Context) {
var req models.CreateContactGroupRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "请求参数错误: " + err.Error()})
return
}
idsJSON, _ := json.Marshal(req.ContactIDs)
group := models.AlertContactGroup{
GroupName: req.GroupName,
Notes: req.Notes,
ContactIDs: string(idsJSON),
}
if err := h.db.Create(&group).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "创建失败"})
return
}
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "创建成功", Data: group})
}
// UpdateContactGroup PUT /alerts/contact-groups/:id
func (h *AlertHandler) UpdateContactGroup(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var req models.UpdateContactGroupRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "请求参数错误"})
return
}
var group models.AlertContactGroup
if err := h.db.First(&group, id).Error; err != nil {
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "联系组不存在"})
return
}
updates := map[string]interface{}{}
if req.GroupName != "" { updates["group_name"] = req.GroupName }
if req.Notes != "" { updates["notes"] = req.Notes }
if len(req.ContactIDs) > 0 {
idsJSON, _ := json.Marshal(req.ContactIDs)
updates["contact_ids"] = string(idsJSON)
}
h.db.Model(&group).Updates(updates)
h.db.First(&group, id)
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "更新成功", Data: group})
}
// DeleteContactGroup DELETE /alerts/contact-groups/:id
func (h *AlertHandler) DeleteContactGroup(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
if err := h.db.Delete(&models.AlertContactGroup{}, id).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "删除失败"})
return
}
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "删除成功"})
}