chore: update meessage
This commit is contained in:
@@ -84,7 +84,6 @@ func (nc *NotificationController) TestChannel(c *gin.Context) {
|
||||
utils.Success(c, result)
|
||||
}
|
||||
|
||||
|
||||
// GetBindings 获取事件绑定列表
|
||||
func (nc *NotificationController) GetBindings(c *gin.Context) {
|
||||
bindings := nc.notifyService.GetBindings()
|
||||
@@ -94,11 +93,12 @@ func (nc *NotificationController) GetBindings(c *gin.Context) {
|
||||
// SaveBinding 保存事件绑定
|
||||
func (nc *NotificationController) SaveBinding(c *gin.Context) {
|
||||
var req struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Event string `json:"event"`
|
||||
WayID string `json:"way_id"`
|
||||
DataID string `json:"data_id"`
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Event string `json:"event"`
|
||||
WayID string `json:"way_id"`
|
||||
DataID string `json:"data_id"`
|
||||
Extra models.BigText `json:"extra"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
@@ -116,6 +116,7 @@ func (nc *NotificationController) SaveBinding(c *gin.Context) {
|
||||
Event: req.Event,
|
||||
WayID: req.WayID,
|
||||
DataID: req.DataID,
|
||||
Extra: req.Extra,
|
||||
}
|
||||
|
||||
if err := nc.notifyService.SaveBinding(binding); err != nil {
|
||||
@@ -142,6 +143,31 @@ func (nc *NotificationController) DeleteBinding(c *gin.Context) {
|
||||
utils.SuccessMsg(c, "删除成功")
|
||||
}
|
||||
|
||||
// BatchSaveBindings 批量保存事件绑定
|
||||
func (nc *NotificationController) BatchSaveBindings(c *gin.Context) {
|
||||
var req struct {
|
||||
Type string `json:"type"`
|
||||
DataID string `json:"data_id"`
|
||||
Bindings []models.NotifyBinding `json:"bindings"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Type == "" {
|
||||
utils.BadRequest(c, "类型不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
if err := nc.notifyService.BatchSaveBindings(req.Type, req.DataID, req.Bindings); err != nil {
|
||||
utils.ServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessMsg(c, "保存成功")
|
||||
}
|
||||
|
||||
// SendNotification API 发送通知(供脚本调用)
|
||||
func (nc *NotificationController) SendNotification(c *gin.Context) {
|
||||
var req struct {
|
||||
|
||||
@@ -13,11 +13,18 @@ type NotifyBinding struct {
|
||||
Event string `json:"event" gorm:"size:50;not null;index"` // 事件类型
|
||||
WayID string `json:"way_id" gorm:"size:20;not null;index"` // 通知渠道ID
|
||||
DataID string `json:"data_id" gorm:"size:20;index"` // 关联ID,系统事件为空,任务事件为任务ID
|
||||
Extra BigText `json:"extra"` // 额外配置(如是否开启日志推送等,对应 BindingExtra 结构)
|
||||
CreatedAt LocalTime `json:"created_at"`
|
||||
UpdatedAt LocalTime `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
}
|
||||
|
||||
// BindingExtra 存储在 Extra 字段中的 JSON 配置
|
||||
type BindingExtra struct {
|
||||
EnableLog bool `json:"enable_log"`
|
||||
LogLimit int `json:"log_limit"` // 日志字数限制,默认 1000
|
||||
}
|
||||
|
||||
func (NotifyBinding) TableName() string {
|
||||
return constant.TablePrefix + "notify_bindings"
|
||||
}
|
||||
|
||||
@@ -231,6 +231,7 @@ func registerNotificationRoutes(g *gin.RouterGroup, c *Controllers) {
|
||||
notify.POST("/channels/test", c.Notification.TestChannel)
|
||||
notify.GET("/bindings", c.Notification.GetBindings)
|
||||
notify.POST("/bindings", c.Notification.SaveBinding)
|
||||
notify.POST("/bindings/batch", c.Notification.BatchSaveBindings)
|
||||
notify.DELETE("/bindings/:id", c.Notification.DeleteBinding)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
"github.com/engigu/baihu-panel/internal/utils"
|
||||
|
||||
"github.com/engigu/baihu-panel/internal/sdk/messenger"
|
||||
"gorm.io/gorm"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// NotifyChannel 通知渠道配置
|
||||
@@ -155,9 +157,13 @@ func (s *NotificationService) SaveBinding(binding *models.NotifyBinding) error {
|
||||
res := database.DB.Where("type = ? AND event = ? AND way_id = ? AND data_id = ?",
|
||||
binding.Type, binding.Event, binding.WayID, binding.DataID).Limit(1).Find(&existing)
|
||||
if res.Error == nil && res.RowsAffected > 0 {
|
||||
// 如果已存在且未删除,直接返回(或者更新它)
|
||||
*binding = existing
|
||||
return nil
|
||||
// 如果已存在且未删除,更新现有记录(特别是 Extra 字段)
|
||||
existing.Extra = binding.Extra
|
||||
err := database.DB.Save(&existing).Error
|
||||
if err == nil {
|
||||
*binding = existing
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
binding.ID = utils.GenerateID()
|
||||
@@ -166,6 +172,29 @@ func (s *NotificationService) SaveBinding(binding *models.NotifyBinding) error {
|
||||
return database.DB.Save(binding).Error
|
||||
}
|
||||
|
||||
// BatchSaveBindings 批量保存事件绑定
|
||||
func (s *NotificationService) BatchSaveBindings(bindingType, dataID string, bindings []models.NotifyBinding) error {
|
||||
return database.DB.Transaction(func(tx *gorm.DB) error {
|
||||
// 如果指定了 dataID,先清理该对象的所有现有绑定
|
||||
if dataID != "" {
|
||||
if err := tx.Unscoped().Where("type = ? AND data_id = ?", bindingType, dataID).Delete(&models.NotifyBinding{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 批量插入新绑定
|
||||
for i := range bindings {
|
||||
bindings[i].ID = utils.GenerateID()
|
||||
bindings[i].Type = bindingType
|
||||
bindings[i].DataID = dataID
|
||||
if err := tx.Create(&bindings[i]).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteBinding 删除事件绑定
|
||||
func (s *NotificationService) DeleteBinding(id string) error {
|
||||
return database.DB.Unscoped().Where("id = ?", id).Delete(&models.NotifyBinding{}).Error
|
||||
@@ -288,6 +317,14 @@ func (s *NotificationService) SubscribeEvents(bus *eventbus.EventBus) {
|
||||
bus.Subscribe(constant.EventSystemNotice, s.handleEvent(constant.BindingTypeSystem))
|
||||
}
|
||||
|
||||
var ansiRegexp = regexp.MustCompile(`[\x1b\x9b][\[()#;?]*([0-9]{1,4}(;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]`)
|
||||
|
||||
// stripAnsi 移除字符串中的 ANSI 转义码(如颜色代码)
|
||||
func stripAnsi(str string) string {
|
||||
return ansiRegexp.ReplaceAllString(str, "")
|
||||
}
|
||||
|
||||
// handleEvent 处理事件订阅并发送通知
|
||||
func (s *NotificationService) handleEvent(bindingType string) eventbus.Handler {
|
||||
return func(e eventbus.Event) {
|
||||
payload, ok := e.Payload.(map[string]interface{})
|
||||
@@ -338,7 +375,6 @@ func (s *NotificationService) handleEvent(bindingType string) eventbus.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
msg := &NotifyMessage{Title: title, Text: text}
|
||||
bindings := s.GetBindingsByEvent(bindingType, e.Type, dataID)
|
||||
if len(bindings) == 0 {
|
||||
return
|
||||
@@ -355,12 +391,38 @@ func (s *NotificationService) handleEvent(bindingType string) eventbus.Handler {
|
||||
if !ok || !ch.Enabled {
|
||||
continue
|
||||
}
|
||||
go func(channel NotifyChannel) {
|
||||
result := s.SendToChannel(channel, msg)
|
||||
|
||||
// 克隆文本以便修改
|
||||
currentText := text
|
||||
|
||||
// 解析额外配置
|
||||
var extra models.BindingExtra
|
||||
if binding.Extra != "" {
|
||||
_ = json.Unmarshal([]byte(binding.Extra), &extra)
|
||||
}
|
||||
// 默认日志限制为 1000
|
||||
if extra.LogLimit <= 0 {
|
||||
extra.LogLimit = 1000
|
||||
}
|
||||
|
||||
// 如果开启了日志推送
|
||||
if extra.EnableLog {
|
||||
if output, ok := payload["output"].(string); ok && output != "" {
|
||||
// 仅保留指定字数的日志内容并移除 ANSI 颜色代码
|
||||
logSnippet := stripAnsi(output)
|
||||
if len(logSnippet) > extra.LogLimit {
|
||||
logSnippet = "...\n" + logSnippet[len(logSnippet)-extra.LogLimit:]
|
||||
}
|
||||
currentText += "\n\n【执行日志】\n" + logSnippet
|
||||
}
|
||||
}
|
||||
|
||||
go func(channel NotifyChannel, msgTitle, msgText string) {
|
||||
result := s.SendToChannel(channel, &NotifyMessage{Title: msgTitle, Text: msgText})
|
||||
if !result.Success {
|
||||
logger.Warnf("[Notify] 发送事件 %s 到渠道 %s(%s) 失败: %s", e.Type, channel.Name, channel.Type, result.Error)
|
||||
}
|
||||
}(ch)
|
||||
}(ch, title, currentText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,6 +269,8 @@ func (h *ServerSchedulerHandler) OnTaskCompleted(req *executor.ExecutionRequest,
|
||||
"task_name": task.Name,
|
||||
"status": result.Status,
|
||||
"duration": result.Duration,
|
||||
"output": result.Output,
|
||||
"error": result.Error,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -346,6 +348,7 @@ func (h *ServerSchedulerHandler) OnTaskFailed(req *executor.ExecutionRequest, er
|
||||
"task_id": taskID,
|
||||
"task_name": taskName,
|
||||
"error": err.Error(),
|
||||
"output": output,
|
||||
},
|
||||
})
|
||||
}()
|
||||
|
||||
Reference in New Issue
Block a user