package business import ( "context" "errors" "gorm.io/gorm" "kra/internal/biz/business" "time" ) type alertRuleRepo struct{ data Provider } func NewAlertRuleRepo(data Provider) business.AlertRuleRepo { return &alertRuleRepo{data: data} } func toBizAlertRule(po alertRulePO) *business.AlertRule { return &business.AlertRule{ID: po.ID, Name: po.RuleName, Type: po.RuleType, Metric: po.MonitorMetric, StatPeriodDays: po.StatPeriodDays, MomDirection: po.MomDirection, MomThreshold: po.MomThreshold, UnloginDays: po.UnloginDays, MonitorScope: po.MonitorScope, WarningColor: po.WarningColor, CreatorID: po.CreatorID, Enabled: po.Enabled, IsDeleted: po.IsDeleted, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt} } func newAlertRule(r *business.AlertRule) alertRulePO { return alertRulePO{ID: r.ID, RuleName: r.Name, RuleType: r.Type, MonitorMetric: r.Metric, StatPeriodDays: r.StatPeriodDays, MomDirection: r.MomDirection, MomThreshold: r.MomThreshold, UnloginDays: r.UnloginDays, MonitorScope: r.MonitorScope, WarningColor: r.WarningColor, CreatorID: r.CreatorID, Enabled: r.Enabled, IsDeleted: r.IsDeleted} } func applyOwnerScope(db *gorm.DB, scope business.LevelOneScope, column string) *gorm.DB { if scope.All { return db } if scope.Empty { return db.Where("1=0") } return db.Where(column+" = ?", scope.UserID) } func (r *alertRuleRepo) List(ctx context.Context, scope business.LevelOneScope, filter business.AlertRuleFilter, options ...business.ListOption) ([]*business.AlertRule, int64, error) { db := applyOwnerScope(r.data.DB().WithContext(ctx).Table("sys_alert_rule r").Where("r.is_deleted = ?", 0), scope, "r.creator_id") if filter.Type != "" { db = db.Where("r.rule_type = ?", filter.Type) } if filter.Name != "" { db = db.Where("r.rule_name LIKE ?", "%"+filter.Name+"%") } if filter.Metric != nil { db = db.Where("r.monitor_metric = ?", *filter.Metric) } var total int64 if err := db.Count(&total).Error; err != nil { return nil, 0, business.ErrStorage } var pos []struct { Rule alertRulePO `gorm:"embedded"` CreatorName string } o := business.NewListOptions(options...) if err := db.Select("r.*,u.username AS creator_name").Joins("LEFT JOIN sys_users u ON u.id=r.creator_id AND u.deleted_at IS NULL").Order("r.created_at DESC,r.id DESC").Offset(o.Offset).Limit(o.Limit).Scan(&pos).Error; err != nil { return nil, 0, business.ErrStorage } rows := make([]*business.AlertRule, 0, len(pos)) for _, po := range pos { rule := toBizAlertRule(po.Rule) rule.CreatorName = po.CreatorName rows = append(rows, rule) } return rows, total, nil } func (r *alertRuleRepo) Find(ctx context.Context, id uint64) (*business.AlertRule, error) { var po alertRulePO err := r.data.DB().WithContext(ctx).First(&po, "id = ?", id).Error if errors.Is(err, gorm.ErrRecordNotFound) { return nil, business.ErrAlertRuleNotFound } if err != nil { return nil, business.ErrStorage } rule := toBizAlertRule(po) if err := r.data.DB().WithContext(ctx).Table("sys_users").Where("id = ? AND deleted_at IS NULL", rule.CreatorID).Select("username").Scan(&rule.CreatorName).Error; err != nil { return nil, business.ErrStorage } return rule, nil } func (r *alertRuleRepo) Create(ctx context.Context, rule *business.AlertRule) error { po := newAlertRule(rule) if err := r.data.DB().WithContext(ctx).Create(&po).Error; err != nil { return storageError(err) } rule.ID, rule.CreatedAt, rule.UpdatedAt = po.ID, po.CreatedAt, po.UpdatedAt return nil } func (r *alertRuleRepo) Update(ctx context.Context, rule *business.AlertRule) error { // 编辑不覆盖启停、删除和创建人字段,避免并发启停被旧配置覆盖。 return storageError(r.data.DB().WithContext(ctx).Model(&alertRulePO{}).Where("id = ?", rule.ID).Updates(map[string]any{"rule_name": rule.Name, "rule_type": rule.Type, "monitor_metric": rule.Metric, "stat_period_days": rule.StatPeriodDays, "mom_direction": rule.MomDirection, "mom_threshold": rule.MomThreshold, "unlogin_days": rule.UnloginDays, "monitor_scope": 1, "warning_color": rule.WarningColor, "updated_at": time.Now()}).Error) } func (r *alertRuleRepo) SetDeleted(ctx context.Context, id uint64) error { return storageError(r.data.DB().WithContext(ctx).Model(&alertRulePO{}).Where("id = ?", id).Updates(map[string]any{"is_deleted": 1, "updated_at": time.Now()}).Error) } func (r *alertRuleRepo) SetEnabled(ctx context.Context, id uint64, enabled int) error { return storageError(r.data.DB().WithContext(ctx).Model(&alertRulePO{}).Where("id = ?", id).Updates(map[string]any{"enabled": enabled, "updated_at": time.Now()}).Error) } func (r *alertRuleRepo) TypesFromRecords(ctx context.Context, scope business.LevelOneScope) ([]string, error) { rows := []string{} err := applyOwnerScope(r.data.DB().WithContext(ctx).Table("sys_alert_record").Where("rule_type IS NOT NULL AND TRIM(rule_type) <> ''"), scope, "business_id").Distinct("rule_type").Order("rule_type").Pluck("rule_type", &rows).Error return rows, storageError(err) }