Commit 79818049 authored by 李科's avatar 李科

feat: 预警列表批量推送&批量关闭

parent f5e222de
...@@ -24,6 +24,7 @@ type AlertList struct { ...@@ -24,6 +24,7 @@ type AlertList struct {
Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭 Status int `json:"status"` // 状态,1:已恢复 2:未恢复 3:已关闭
IsDisposed int `json:"is_disposed"` // 是否处置(工单管理),1:已处置,2:未处置 IsDisposed int `json:"is_disposed"` // 是否处置(工单管理),1:已处置,2:未处置
DisposalContent string `json:"disposal_content"` // 处置内容(工单管理,结果反馈) DisposalContent string `json:"disposal_content"` // 处置内容(工单管理,结果反馈)
CloseRemark string `json:"close_remark"` // 关闭备注,预警关闭提醒
CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人 CreatedBy string `json:"created_by" xorm:"'created_by'"` // 创建人
CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间 CreatedAt jsontime.Time `json:"created_at" xorm:"'created_at'"` // 创建时间
UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人 UpdatedBy string `json:"updated_by" xorm:"'updated_by'"` // 更新人
......
...@@ -45,5 +45,5 @@ type AlertFrequencyDistribution struct { ...@@ -45,5 +45,5 @@ type AlertFrequencyDistribution struct {
} }
func (a *AlertOverview) TableName() string { func (a *AlertOverview) TableName() string {
return "alert_overview.go" return "alert_overview"
} }
...@@ -14,7 +14,7 @@ type AlertRules struct { ...@@ -14,7 +14,7 @@ type AlertRules struct {
Duration int `json:"duration" xorm:"'duration'"` // 持续时间 Duration int `json:"duration" xorm:"'duration'"` // 持续时间
DurationUnit string `json:"duration_unit" xorm:"'duration_unit'"` // 持续时间单位 s m h DurationUnit string `json:"duration_unit" xorm:"'duration_unit'"` // 持续时间单位 s m h
CheckPeriod int `json:"check_period" xorm:"'check_period'"` // 检查周期 单位:分钟 CheckPeriod int `json:"check_period" xorm:"'check_period'"` // 检查周期 单位:分钟
NotifyMethod string `json:"notify_method" xorm:"'notify_method'"` // 预警通知方式 all dingtalk sms NotifyMethod string `json:"notify_method" xorm:"'notify_method'"` // 预警通知方式 dingtalk sms
NotifyRecipients string `json:"notify_recipients" xorm:"notify_recipients"` // 预警推送用户 NotifyRecipients string `json:"notify_recipients" xorm:"notify_recipients"` // 预警推送用户
NotifyPushCount int `json:"notify_push_count" xorm:"'notify_push_count'"` // 消息推送次数 NotifyPushCount int `json:"notify_push_count" xorm:"'notify_push_count'"` // 消息推送次数
NotifyPushFrequency int `json:"notify_push_frequency" xorm:"'notify_push_frequency'"` // 消息推送频率 分钟 NotifyPushFrequency int `json:"notify_push_frequency" xorm:"'notify_push_frequency'"` // 消息推送频率 分钟
...@@ -44,5 +44,5 @@ type AlertCondition struct { ...@@ -44,5 +44,5 @@ type AlertCondition struct {
type NotifyRecipients struct { type NotifyRecipients struct {
SystemAccount string `json:"system_account" form:"system_account" binding:"required"` SystemAccount string `json:"system_account" form:"system_account" binding:"required"`
UserName string `json:"user_name" form:"user_name" binding:"required"` UserName string `json:"user_name" form:"user_name" binding:"required"`
Phone string `json:"phone" form:"phone" binding:"required"` Phone string `json:"phone" form:"phone" binding:"required,phone"`
} }
...@@ -6,7 +6,7 @@ type PushRecord struct { ...@@ -6,7 +6,7 @@ type PushRecord struct {
Id int `json:"id" xorm:"'id' pk autoincr"` // 主键id Id int `json:"id" xorm:"'id' pk autoincr"` // 主键id
AlertRulesId string `json:"alert_rules_id" xorm:"'alert_rules_id'"` // 告警规则id AlertRulesId string `json:"alert_rules_id" xorm:"'alert_rules_id'"` // 告警规则id
RiskLevel int `json:"risk_level" xorm:"'risk_level'"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 RiskLevel int `json:"risk_level" xorm:"'risk_level'"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
NotifyMethod string `json:"notify_method" xorm:"'notify_method'"` // 预警通知方式 all dingtalk sms NotifyMethod string `json:"notify_method" xorm:"'notify_method'"` // 预警通知方式 dingtalk sms
SystemAccount string `json:"system_account" xorm:"system_account"` // 预警推送用户(NotifyRecipient) // 账号 SystemAccount string `json:"system_account" xorm:"system_account"` // 预警推送用户(NotifyRecipient) // 账号
PushTime jsontime.Time `json:"push_time" xorm:"'push_time'"` // 推送时间 PushTime jsontime.Time `json:"push_time" xorm:"'push_time'"` // 推送时间
PushType int `json:"push_type" xorm:"'push_type'"` // 推送类型,1:自动推送,2:手动推送 PushType int `json:"push_type" xorm:"'push_type'"` // 推送类型,1:自动推送,2:手动推送
......
package request package request
import "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
type DetailAlertList struct { type DetailAlertList struct {
Id int `json:"id" form:"id" binding:"required"` Id int `json:"id" form:"id" binding:"required"`
} }
...@@ -10,6 +12,20 @@ type UpdateAlertList struct { ...@@ -10,6 +12,20 @@ type UpdateAlertList struct {
Keyword string `json:"keyword" form:"keyword"` // 预警点/分类/指标 Keyword string `json:"keyword" form:"keyword"` // 预警点/分类/指标
} }
type BatchPushAlertList struct {
Id string `json:"id" form:"id"`
Ids []string `json:"ids" form:"ids" binding:"required_without=Id"` // 预警ids
NotifyMethod []string `json:"notify_method" form:"notify_method" binding:"max=2,dive,oneof=dingtalk sms"` // 预警通知方式 dingtalk sms
NotifyRecipients []entity.NotifyRecipients `json:"notify_recipients" form:"notify_recipients" binding:"dive"` // 预警推送用户
}
type BatchCloseAlertList struct {
Id string `json:"id" form:"id"`
Ids []string `json:"ids" form:"ids" binding:"required_without=Id"` // 预警ids
CloseRemark string `json:"close_remark" form:"close_remark" binding:"required"` // 关闭备注
DeferPush int `json:"defer_push" form:"defer_push" binding:"omitempty,oneof=0 1"` // 延迟三天推送: 0:否 1:是 三天内将不再自动推送该告警信息给处置人员,可手动推送,但告警数据依然会出现
}
type ListAlertList struct { type ListAlertList struct {
Id int `json:"id" form:"id"` Id int `json:"id" form:"id"`
RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险 RiskLevel int `json:"risk_level" form:"risk_level" binding:"omitempty,oneof=1 2 3 4"` // 风险等级,1:低风险,2:一般风险,3:较大风险,4:重大风险
......
...@@ -19,7 +19,7 @@ type AddAlertRules struct { ...@@ -19,7 +19,7 @@ type AddAlertRules struct {
Duration int `json:"duration" form:"duration" binding:"gte=0"` // 持续时间 Duration int `json:"duration" form:"duration" binding:"gte=0"` // 持续时间
DurationUnit string `json:"duration_unit" form:"duration_unit" binding:"oneof=s m h"` // 持续时间单位 s m h DurationUnit string `json:"duration_unit" form:"duration_unit" binding:"oneof=s m h"` // 持续时间单位 s m h
CheckPeriod int `json:"check_period" form:"check_period" binding:"oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟 CheckPeriod int `json:"check_period" form:"check_period" binding:"oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟
NotifyMethod []string `json:"notify_method" form:"notify_method" binding:"max=2,dive,oneof=dingtalk sms"` // 预警通知方式 all dingtalk sms NotifyMethod []string `json:"notify_method" form:"notify_method" binding:"max=2,dive,oneof=dingtalk sms"` // 预警通知方式 dingtalk sms
NotifyRecipients []entity.NotifyRecipients `json:"notify_recipients" form:"notify_recipients" binding:"dive"` // 预警推送用户 NotifyRecipients []entity.NotifyRecipients `json:"notify_recipients" form:"notify_recipients" binding:"dive"` // 预警推送用户
NotifyPushCount int `json:"notify_push_count" form:"notify_push_count" binding:"gte=1"` // 消息推送次数 NotifyPushCount int `json:"notify_push_count" form:"notify_push_count" binding:"gte=1"` // 消息推送次数
NotifyPushFrequency int `json:"notify_push_frequency" form:"notify_push_frequency" binding:"gte=1"` // 消息推送频率 分钟 NotifyPushFrequency int `json:"notify_push_frequency" form:"notify_push_frequency" binding:"gte=1"` // 消息推送频率 分钟
...@@ -42,7 +42,7 @@ type UpdateAlertRules struct { ...@@ -42,7 +42,7 @@ type UpdateAlertRules struct {
Duration int `json:"duration" form:"duration" binding:"gte=0"` // 持续时间 Duration int `json:"duration" form:"duration" binding:"gte=0"` // 持续时间
DurationUnit string `json:"duration_unit" form:"duration_unit" binding:"oneof=s m h"` // 持续时间单位 s m h DurationUnit string `json:"duration_unit" form:"duration_unit" binding:"oneof=s m h"` // 持续时间单位 s m h
CheckPeriod int `json:"check_period" form:"check_period" binding:"oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟 CheckPeriod int `json:"check_period" form:"check_period" binding:"oneof=1 3 5 10 20 30"` // 检查周期 单位:分钟
NotifyMethod []string `json:"notify_method" form:"notify_method" binding:"max=2,dive,oneof=dingtalk sms"` // 预警通知方式 all dingtalk sms NotifyMethod []string `json:"notify_method" form:"notify_method" binding:"max=2,dive,oneof=dingtalk sms"` // 预警通知方式 dingtalk sms
NotifyRecipients []entity.NotifyRecipients `json:"notify_recipients" form:"notify_recipients" binding:"dive"` // 预警推送用户 NotifyRecipients []entity.NotifyRecipients `json:"notify_recipients" form:"notify_recipients" binding:"dive"` // 预警推送用户
NotifyPushCount int `json:"notify_push_count" form:"notify_push_count" binding:"gte=1"` // 消息推送次数 NotifyPushCount int `json:"notify_push_count" form:"notify_push_count" binding:"gte=1"` // 消息推送次数
NotifyPushFrequency int `json:"notify_push_frequency" form:"notify_push_frequency" binding:"gte=1"` // 消息推送频率 分钟 NotifyPushFrequency int `json:"notify_push_frequency" form:"notify_push_frequency" binding:"gte=1"` // 消息推送频率 分钟
...@@ -66,7 +66,7 @@ type DetailAlertRules struct { ...@@ -66,7 +66,7 @@ type DetailAlertRules struct {
type ListAlertRules struct { type ListAlertRules struct {
// 请输入预警规则名称/预警对象/预警分类/预警指标 // 请输入预警规则名称/预警对象/预警分类/预警指标
Id string `json:"id" form:"id"` Id string `json:"id" form:"id"`
NotifyMethod string `json:"notify_method" form:"notify_method" binding:"omitempty,oneof=all dingtalk sms"` // 预警通知方式 all dingtalk sms NotifyMethod string `json:"notify_method" form:"notify_method" binding:"omitempty,oneof=all dingtalk sms"` // 预警通知方式 dingtalk sms
IsEnabled int `json:"is_enabled" form:"is_enabled" binding:"omitempty,oneof=1 2"` // 是否开启 1:是 2:否 IsEnabled int `json:"is_enabled" form:"is_enabled" binding:"omitempty,oneof=1 2"` // 是否开启 1:是 2:否
Keyword string `json:"keyword" form:"keyword"` // 预警规则名称(指标名称) Keyword string `json:"keyword" form:"keyword"` // 预警规则名称(指标名称)
StartTime string `json:"start_time" form:"start_time" binding:"omitempty,datetime=2006-01-02 15:04:05"` StartTime string `json:"start_time" form:"start_time" binding:"omitempty,datetime=2006-01-02 15:04:05"`
......
package response
import (
"fmt"
json "github.com/json-iterator/go"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"sort"
"testing"
)
func BuildTree(nodes []entity.AlertClass) ([]*AlertClassNode, error) {
nodeMap := make(map[int]*AlertClassNode)
// 创建所有节点并存储到映射表中
for _, node := range nodes {
tree := &AlertClassNode{
AlertClass: node,
Children: []*AlertClassNode{},
}
nodeMap[node.ClassId] = tree
}
var rootNodes []*AlertClassNode
for _, node := range nodes {
if node.ParentId == 0 {
rootNodes = append(rootNodes, nodeMap[node.ClassId])
} else {
parent := nodeMap[node.ParentId]
if parent == nil {
return nil, fmt.Errorf("parent node not found for ClassId: %d", node.ClassId)
}
parent.Children = append(parent.Children, nodeMap[node.ClassId])
}
}
sortTree(rootNodes)
return rootNodes, nil
}
func sortTree(nodes []*AlertClassNode) {
sort.Slice(nodes, func(i, j int) bool {
return nodes[i].SortOrder < nodes[j].SortOrder
})
for _, node := range nodes {
sortTree(node.Children)
}
}
func TestTree(t *testing.T) {
// 示例数据
data := []entity.AlertClass{
{ClassId: 1, ClassName: "Root", ParentId: 0, SortOrder: 0},
{ClassId: 2, ClassName: "Child 1", ParentId: 1, SortOrder: 0},
{ClassId: 3, ClassName: "Child 2", ParentId: 1, SortOrder: 0},
{ClassId: 4, ClassName: "Grandchild 3", ParentId: 2, SortOrder: 3},
{ClassId: 5, ClassName: "Grandchild 1", ParentId: 2, SortOrder: 1},
{ClassId: 6, ClassName: "Grandchild 2", ParentId: 2, SortOrder: 2},
}
rootNodes, err := BuildTree(data)
if err != nil {
fmt.Println("Failed to build tree:", err)
return
}
// 将树形结构转换为 JSON 字符串
jsonData, err := json.Marshal(rootNodes)
if err != nil {
fmt.Println("Failed to marshal tree:", err)
return
}
fmt.Println(string(jsonData))
}
...@@ -30,6 +30,48 @@ func UpdateAlertList(c *gin.Context) { ...@@ -30,6 +30,48 @@ func UpdateAlertList(c *gin.Context) {
SendJsonResponse(c, resp.OK, nil) SendJsonResponse(c, resp.OK, nil)
} }
func BatchPushAlertList(c *gin.Context) {
var req request.BatchPushAlertList
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
svc := service.AlertListSvc{User: header.GetUser(c)}
db, err := client.GetDbClient()
if err != nil {
SendJsonResponse(c, resp.DbConnectError.WithError(err), nil)
return
}
err = svc.BatchPushAlertList(db.NewSession(), req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, nil)
}
func BatchCloseAlertList(c *gin.Context) {
var req request.BatchCloseAlertList
if err := c.ShouldBind(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.TranslateError(err), nil)
return
}
svc := service.AlertListSvc{User: header.GetUser(c)}
db, err := client.GetDbClient()
if err != nil {
SendJsonResponse(c, resp.DbConnectError.WithError(err), nil)
return
}
err = svc.BatchCloseAlertList(db.NewSession(), req)
if err != nil {
SendJsonResponse(c, resp.FAIL.WithError(err), nil)
return
}
SendJsonResponse(c, resp.OK, nil)
}
func DetailAlertList(c *gin.Context) { func DetailAlertList(c *gin.Context) {
var req request.DetailAlertList var req request.DetailAlertList
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBind(&req); err != nil {
......
...@@ -14,5 +14,7 @@ func InitAlertListRouter(e *gin.Engine) { ...@@ -14,5 +14,7 @@ func InitAlertListRouter(e *gin.Engine) {
group.GET("", controller.DetailAlertList) group.GET("", controller.DetailAlertList)
group.GET("list", controller.ListAlertList) group.GET("list", controller.ListAlertList)
group.PUT("", controller.UpdateAlertList) group.PUT("", controller.UpdateAlertList)
group.PUT("batch/push", controller.BatchPushAlertList)
group.PUT("batch/close", controller.BatchCloseAlertList)
} }
} }
...@@ -5,7 +5,9 @@ import ( ...@@ -5,7 +5,9 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime"
"go.uber.org/zap"
"xorm.io/xorm" "xorm.io/xorm"
) )
...@@ -27,6 +29,22 @@ func (a *AlertListSvc) Update(session *xorm.Session, req request.UpdateAlertList ...@@ -27,6 +29,22 @@ func (a *AlertListSvc) Update(session *xorm.Session, req request.UpdateAlertList
return nil return nil
} }
func (a *AlertListSvc) BatchPushAlertList(session *xorm.Session, req request.BatchPushAlertList) error {
now := jsontime.Now()
_ = now
// TODO 批量推送用户告警
conf.Logger.Info("batch push", zap.Any("payload", req))
return nil
}
func (a *AlertListSvc) BatchCloseAlertList(session *xorm.Session, req request.BatchCloseAlertList) error {
now := jsontime.Now()
_ = now
// TODO 批量推送用户告警
conf.Logger.Info("batch close", zap.Any("payload", req))
return nil
}
func (a *AlertListSvc) GetDataById(req request.DetailAlertList) (resp response.AlertListItem, err error) { func (a *AlertListSvc) GetDataById(req request.DetailAlertList) (resp response.AlertListItem, err error) {
now := jsontime.Now() now := jsontime.Now()
data := response.AlertListItem{ data := response.AlertListItem{
......
package util
import (
"github.com/google/uuid"
"strings"
)
func NewUUID() string {
return uuid.New().String()
}
func NewUUIDNoHyphens() string {
id := uuid.New().String()
return strings.Replace(id, "-", "", -1)
}
...@@ -7,7 +7,10 @@ import ( ...@@ -7,7 +7,10 @@ import (
ut "github.com/go-playground/universal-translator" ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
translations "github.com/go-playground/validator/v10/translations/zh" translations "github.com/go-playground/validator/v10/translations/zh"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"go.uber.org/zap"
"reflect" "reflect"
"regexp"
) )
var ( var (
...@@ -34,5 +37,35 @@ func RegValid() { ...@@ -34,5 +37,35 @@ func RegValid() {
return fld.Name return fld.Name
}) })
//validate.RegisterValidation("required_if", requiredIf) err := validate.RegisterValidation("phone", validatePhone)
if err != nil {
conf.Logger.Info("validate register failed", zap.Error(err))
}
setTranslation(validate, Trans)
}
// 校验手机号
func validatePhone(fl validator.FieldLevel) bool {
phone := fl.Field().String()
pattern := "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"
regex, err := regexp.Compile(pattern)
if err != nil {
return false
}
isValid := regex.MatchString(phone)
return isValid
}
// 中文翻译
func setTranslation(validate *validator.Validate, trans ut.Translator) {
validate.RegisterTranslation(
"phone",
trans,
func(ut ut.Translator) error {
return ut.Add("phone", "{0}不是一个有效的手机号码!", true)
},
func(ut ut.Translator, fe validator.FieldError) string {
return fmt.Sprintf("%s不是一个有效的手机号码!", fe.Field())
},
)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment