package controller import ( "fmt" "net/http" "strings" "time" "ezops/model" "github.com/gin-gonic/gin" "gorm.io/gorm" ) const ( defaultNotifyTitleTemplate = "[{{severity_label}}] {{rule_name}} — {{hostname}} ({{metric}})" defaultNotifyFooterTemplate = "{{time}} | {{platform}}" defaultNotifyPlatformName = "AIOps 智能运维平台" ) // ensureNotifySettings 确保全局消息模版存在 // Logan.Li func ensureNotifySettings(db *gorm.DB) model.AlertNotifySettings { var s model.AlertNotifySettings if err := db.First(&s).Error; err != nil { s = model.AlertNotifySettings{ TitleTemplate: defaultNotifyTitleTemplate, FooterTemplate: defaultNotifyFooterTemplate, PlatformName: defaultNotifyPlatformName, } db.Create(&s) } if s.PlatformName == "" { s.PlatformName = defaultNotifyPlatformName } return s } // GetNotifyMessageSettings GET /alerts/notify-message-settings // Logan.Li func (h *AlertHandler) GetNotifyMessageSettings(c *gin.Context) { s := ensureNotifySettings(h.db) c.JSON(http.StatusOK, model.Response{Code: 200, Data: s}) } // SaveNotifyMessageSettings PUT /alerts/notify-message-settings // Logan.Li func (h *AlertHandler) SaveNotifyMessageSettings(c *gin.Context) { var req struct { TitleTemplate string `json:"title_template"` FooterTemplate string `json:"footer_template"` PlatformName string `json:"platform_name"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "请求参数错误: " + err.Error()}) return } s := ensureNotifySettings(h.db) updates := map[string]interface{}{ "title_template": strings.TrimSpace(req.TitleTemplate), "footer_template": strings.TrimSpace(req.FooterTemplate), "platform_name": strings.TrimSpace(req.PlatformName), } if updates["platform_name"] == "" { updates["platform_name"] = defaultNotifyPlatformName } h.db.Model(&s).Updates(updates) h.db.First(&s, s.ID) c.JSON(http.StatusOK, model.Response{Code: 200, Data: s, Message: "消息模版已保存"}) } // notifyTemplateVars 告警通知模版变量 // Logan.Li func notifyTemplateVars(ruleName, hostname, metric, severity, message string, value, threshold float64, platform string) map[string]string { sevLabel := "严重告警" switch severity { case "warning": sevLabel = "警告" case "info": sevLabel = "信息" } if platform == "" { platform = defaultNotifyPlatformName } return map[string]string{ "time": time.Now().Format("2006-01-02 15:04:05"), "platform": platform, "rule_name": ruleName, "hostname": hostname, "metric": metric, "severity": severity, "severity_label": sevLabel, "message": message, "value": fmt.Sprintf("%.2f", value), "threshold": fmt.Sprintf("%.2f", threshold), } } // renderNotifyTemplate 简单变量替换 {{key}} // Logan.Li func renderNotifyTemplate(tpl string, vars map[string]string) string { out := tpl for k, v := range vars { out = strings.ReplaceAll(out, "{{"+k+"}}", v) } return out } // buildNotifyTitle 按全局模版生成通知标题 // Logan.Li func buildNotifyTitle(db *gorm.DB, ruleName, hostname, metric, severity string) string { s := ensureNotifySettings(db) tpl := s.TitleTemplate if tpl == "" { tpl = defaultNotifyTitleTemplate } return renderNotifyTemplate(tpl, notifyTemplateVars(ruleName, hostname, metric, severity, "", 0, 0, s.PlatformName)) } // buildNotifyFooter 按全局模版生成卡片底部 // Logan.Li func buildNotifyFooter(db *gorm.DB) string { s := ensureNotifySettings(db) tpl := s.FooterTemplate if tpl == "" { tpl = defaultNotifyFooterTemplate } vars := map[string]string{ "time": time.Now().Format("2006-01-02 15:04:05"), "platform": s.PlatformName, } if vars["platform"] == "" { vars["platform"] = defaultNotifyPlatformName } return renderNotifyTemplate(tpl, vars) } // buildAlertContent 生成告警正文(字段列表,供飞书卡片解析) // Logan.Li func buildAlertContent(ruleName, hostname, metric, severity, message string, value, threshold float64) string { return fmt.Sprintf( "**规则名称:** %s\\n**目标主机:** %s\\n**指标类型:** %s\\n**告警级别:** %s\\n**当前值:** %.2f\\n**阈值:** %.2f\\n**详细信息:** %s\\n**触发时间:** %s", ruleName, hostname, metric, severity, value, threshold, message, time.Now().Format("2006-01-02 15:04:05"), ) }