143 lines
4.4 KiB
Go
143 lines
4.4 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"bj_power_mes/ent"
|
|
"bj_power_mes/ent/alert"
|
|
"bj_power_mes/ent/alertrule"
|
|
)
|
|
|
|
// CreateAlertRule 新增预警规则
|
|
func (s *Service) CreateAlertRule(ctx context.Context, name, typ string, threshold float64, receiver string, enabled bool, createdBy string) error {
|
|
if name == "" || typ == "" {
|
|
return errors.New("规则名称与类型必填")
|
|
}
|
|
_, err := s.ctx.EntClient.AlertRule.Create().
|
|
SetName(name).SetType(typ).SetThreshold(threshold).
|
|
SetReceiver(receiver).SetEnabled(enabled).SetCreatedBy(createdBy).Save(ctx)
|
|
return err
|
|
}
|
|
|
|
// UpdateAlertRule 修改预警规则
|
|
func (s *Service) UpdateAlertRule(ctx context.Context, id int, name, typ string, threshold float64, receiver string, enabled bool) error {
|
|
if id <= 0 {
|
|
return errors.New("规则ID无效")
|
|
}
|
|
if name == "" || typ == "" {
|
|
return errors.New("规则名称与类型必填")
|
|
}
|
|
_, err := s.ctx.EntClient.AlertRule.UpdateOneID(id).
|
|
SetName(name).SetType(typ).SetThreshold(threshold).
|
|
SetReceiver(receiver).SetEnabled(enabled).Save(ctx)
|
|
return err
|
|
}
|
|
|
|
// DeleteAlertRule 删除预警规则
|
|
func (s *Service) DeleteAlertRule(ctx context.Context, id int) error {
|
|
if id <= 0 {
|
|
return errors.New("规则ID无效")
|
|
}
|
|
return s.ctx.EntClient.AlertRule.DeleteOneID(id).Exec(ctx)
|
|
}
|
|
|
|
// ListAlertRules 查询全部预警规则
|
|
func (s *Service) ListAlertRules(ctx context.Context) ([]*ent.AlertRule, error) {
|
|
return s.ctx.EntClient.AlertRule.Query().
|
|
Order(ent.Desc(alertrule.FieldCreatedAt), ent.Desc(alertrule.FieldID)).All(ctx)
|
|
}
|
|
|
|
// AlertQuery 预警查询条件:status/type 空=不限;from/to 为 YYYY-MM-DD(空=不限);page<=0 表示不分页。
|
|
type AlertQuery struct {
|
|
Status string
|
|
Type string
|
|
From string
|
|
To string
|
|
Page int
|
|
PageSize int
|
|
}
|
|
|
|
// ListAlerts 查询预警消息(支持状态/类型/时间范围筛选 + 分页),返回当前页数据与命中总数
|
|
func (s *Service) ListAlerts(ctx context.Context, q AlertQuery) ([]*ent.Alert, int, error) {
|
|
query := s.ctx.EntClient.Alert.Query()
|
|
if q.Status != "" {
|
|
query = query.Where(alert.Status(q.Status))
|
|
}
|
|
if q.Type != "" {
|
|
query = query.Where(alert.Type(q.Type))
|
|
}
|
|
if q.From != "" {
|
|
if f, err := time.Parse("2006-01-02", q.From); err == nil {
|
|
query = query.Where(alert.CreatedAtGTE(f))
|
|
}
|
|
}
|
|
if q.To != "" {
|
|
if t, err := time.Parse("2006-01-02", q.To); err == nil {
|
|
query = query.Where(alert.CreatedAtLT(t.Add(24 * time.Hour)))
|
|
}
|
|
}
|
|
total, err := query.Count(ctx)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if q.Page > 0 {
|
|
size := q.PageSize
|
|
if size <= 0 {
|
|
size = 20
|
|
}
|
|
query = query.Offset((q.Page - 1) * size).Limit(size)
|
|
}
|
|
list, err := query.Order(ent.Desc(alert.FieldCreatedAt), ent.Desc(alert.FieldID)).All(ctx)
|
|
return list, total, err
|
|
}
|
|
|
|
// UnreadAlertCount 未读预警数
|
|
func (s *Service) UnreadAlertCount(ctx context.Context) (int, error) {
|
|
return s.ctx.EntClient.Alert.Query().Where(alert.Status("UNREAD")).Count(ctx)
|
|
}
|
|
|
|
// MarkAlertRead 标记预警已读
|
|
func (s *Service) MarkAlertRead(ctx context.Context, id int) error {
|
|
if id <= 0 {
|
|
return errors.New("预警ID无效")
|
|
}
|
|
_, err := s.ctx.EntClient.Alert.UpdateOneID(id).SetStatus("READ").Save(ctx)
|
|
return err
|
|
}
|
|
|
|
// alertDirection 阈值比较方向:inventory_low 为 <=,其余为 >=
|
|
func alertDirection(typ string) int {
|
|
if typ == "inventory_low" {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
|
|
// Evaluate 预警规则评估:遍历启用且类型匹配的规则,命中阈值则写 alert 消息。
|
|
// 由业务事件触发(如拧紧不合格),也可手动调用。
|
|
func (s *Service) Evaluate(ctx context.Context, typ string, value float64, title, content, refType, refId string) {
|
|
rules, err := s.ctx.EntClient.AlertRule.Query().
|
|
Where(alertrule.Type(typ), alertrule.Enabled(true)).All(ctx)
|
|
if err != nil || len(rules) == 0 {
|
|
return
|
|
}
|
|
dir := alertDirection(typ)
|
|
for _, r := range rules {
|
|
hit := (dir == 1 && value >= r.Threshold) || (dir == -1 && value <= r.Threshold)
|
|
if !hit {
|
|
continue
|
|
}
|
|
_ = s.createAlert(ctx, r.ID, typ, title, content, refType, refId, r.Receiver)
|
|
}
|
|
}
|
|
|
|
func (s *Service) createAlert(ctx context.Context, ruleId int, typ, title, content, refType, refId, receiver string) error {
|
|
_, err := s.ctx.EntClient.Alert.Create().
|
|
SetRuleId(ruleId).SetType(typ).SetTitle(title).
|
|
SetContent(content).SetRefType(refType).SetRefId(refId).
|
|
SetReceiver(receiver).SetStatus("UNREAD").Save(ctx)
|
|
return err
|
|
}
|