package service import ( "errors" "fmt" "affiliate_dash/internal/model" "gorm.io/gorm" "gorm.io/gorm/clause" ) type AddMemberInput struct { UserID uint Role string IsDefault bool } func (s *MerchantService) AddMember(merchantID uint, in AddMemberInput, actorUserID uint) (*model.MerchantMember, error) { if !isValidMemberRole(in.Role) { return nil, errors.New("无效的商户成员角色") } member := &model.MerchantMember{ MerchantID: merchantID, UserID: in.UserID, Role: in.Role, Status: 1, IsDefault: in.IsDefault, } err := s.db.Transaction(func(tx *gorm.DB) error { var merchant model.Merchant if err := tx.Where("id = ? AND status = ?", merchantID, model.MerchantStatusActive).First(&merchant).Error; err != nil { return errors.New("商户不存在或已禁用") } var user model.User if err := tx.Where("id = ? AND status = ?", in.UserID, 1).First(&user).Error; err != nil { return errors.New("用户不存在或已禁用") } if err := tx.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "merchant_id"}, {Name: "user_id"}}, DoUpdates: clause.Assignments(map[string]interface{}{ "role": in.Role, "status": 1, "is_default": in.IsDefault, }), }).Create(member).Error; err != nil { return err } return writeAudit(tx, &merchantID, &actorUserID, nil, "merchant.member.upsert", "merchant_member", fmt.Sprintf("%d:%d", merchantID, in.UserID), map[string]string{"role": in.Role}) }) if err != nil { return nil, err } if err := s.db.Where("merchant_id = ? AND user_id = ?", merchantID, in.UserID).First(member).Error; err != nil { return nil, err } return member, nil } func (s *MerchantService) ListMembers(merchantID uint) ([]model.MerchantMember, error) { var members []model.MerchantMember err := s.db.Preload("User").Where("merchant_id = ?", merchantID).Order("id ASC").Find(&members).Error return members, err }