package adminpush import ( "context" "encoding/json" "errors" "gorm.io/gorm" ) type Repository struct { db *gorm.DB } func NewRepository(db *gorm.DB) *Repository { return &Repository{db: db} } // ── 渠道 CRUD ── func (r *Repository) ListChannels(ctx context.Context) ([]ChannelDTO, error) { var rows []pushChannel if err := r.db.WithContext(ctx).Order("id ASC").Find(&rows).Error; err != nil { return nil, err } items := make([]ChannelDTO, 0, len(rows)) for _, row := range rows { items = append(items, toChannelDTO(row)) } return items, nil } func (r *Repository) CreateChannel(ctx context.Context, req CreateChannelRequest) (*ChannelDTO, error) { cfgJSON, err := json.Marshal(req.Config) if err != nil { return nil, err } row := pushChannel{ Name: req.Name, Type: req.Type, Config: cfgJSON, Enabled: true, } if err := r.db.WithContext(ctx).Create(&row).Error; err != nil { return nil, err } dto := toChannelDTO(row) return &dto, nil } func (r *Repository) UpdateChannel(ctx context.Context, id uint64, req UpdateChannelRequest) (*ChannelDTO, error) { var row pushChannel if err := r.db.WithContext(ctx).First(&row, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrChannelNotFound } return nil, err } if req.Name != nil { row.Name = *req.Name } if req.Config != nil { cfgJSON, err := json.Marshal(req.Config) if err != nil { return nil, err } row.Config = cfgJSON } if req.Enabled != nil { row.Enabled = *req.Enabled } if err := r.db.WithContext(ctx).Save(&row).Error; err != nil { return nil, err } dto := toChannelDTO(row) return &dto, nil } func (r *Repository) DeleteChannel(ctx context.Context, id uint64) error { result := r.db.WithContext(ctx).Delete(&pushChannel{}, id) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return ErrChannelNotFound } return nil } // ── 规则 CRUD ── func (r *Repository) ListRules(ctx context.Context) ([]RuleDTO, error) { var rows []pushRule if err := r.db.WithContext(ctx).Order("id ASC").Find(&rows).Error; err != nil { return nil, err } items := make([]RuleDTO, 0, len(rows)) for _, row := range rows { items = append(items, toRuleDTO(row)) } return items, nil } func (r *Repository) UpdateRule(ctx context.Context, id uint64, req UpdateRuleRequest) (*RuleDTO, error) { var row pushRule if err := r.db.WithContext(ctx).First(&row, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrRuleNotFound } return nil, err } if req.Enabled != nil { row.Enabled = *req.Enabled } if req.Threshold != nil { row.Threshold = *req.Threshold } if req.MessageTemplate != nil { row.MessageTemplate = *req.MessageTemplate } if err := r.db.WithContext(ctx).Save(&row).Error; err != nil { return nil, err } dto := toRuleDTO(row) return &dto, nil } // ── 推送调用方使用 ── func (r *Repository) GetChannel(ctx context.Context, id uint64) (*ChannelDTO, error) { var row pushChannel if err := r.db.WithContext(ctx).First(&row, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrChannelNotFound } return nil, err } dto := toChannelDTO(row) return &dto, nil } func (r *Repository) GetActiveChannels(ctx context.Context) ([]ChannelDTO, error) { var rows []pushChannel if err := r.db.WithContext(ctx).Where("enabled = ?", true).Find(&rows).Error; err != nil { return nil, err } items := make([]ChannelDTO, 0, len(rows)) for _, row := range rows { items = append(items, toChannelDTO(row)) } return items, nil } func (r *Repository) GetRule(ctx context.Context, event string) (*RuleDTO, error) { var row pushRule if err := r.db.WithContext(ctx).Where("event = ?", event).First(&row).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } dto := toRuleDTO(row) return &dto, nil }