diff --git a/internal/service/role/service.go b/internal/service/role/service.go index 1481ae8..867aa03 100644 --- a/internal/service/role/service.go +++ b/internal/service/role/service.go @@ -223,10 +223,19 @@ func (s *Service) AssignPermissions(ctx context.Context, roleID uint, permIDs [] return nil, errors.New(errors.CodeInvalidParam, fmt.Sprintf("权限 %v 不适用于此角色类型", invalidPermIDs)) } + // 批量获取已有权限集合,避免逐条 Exists 查询 + existingPermIDs, err := s.rolePermissionStore.GetPermIDsByRoleID(ctx, roleID) + if err != nil { + return nil, errors.Wrap(errors.CodeInternalError, err, "获取已有权限失败") + } + existingSet := make(map[uint]bool, len(existingPermIDs)) + for _, id := range existingPermIDs { + existingSet[id] = true + } + var rps []*model.RolePermission for _, permID := range permIDs { - exists, _ := s.rolePermissionStore.Exists(ctx, roleID, permID) - if exists { + if existingSet[permID] { continue } diff --git a/internal/store/postgres/role_permission_store.go b/internal/store/postgres/role_permission_store.go index 20e6eaf..8ae83be 100644 --- a/internal/store/postgres/role_permission_store.go +++ b/internal/store/postgres/role_permission_store.go @@ -23,9 +23,13 @@ func NewRolePermissionStore(db *gorm.DB, redisClient *redis.Client) *RolePermiss } } -// Create 创建角色-权限关联 +// Create 创建角色-权限关联,唯一约束冲突时幂等处理 func (s *RolePermissionStore) Create(ctx context.Context, rp *model.RolePermission) error { if err := s.db.WithContext(ctx).Create(rp).Error; err != nil { + // 并发竞态导致唯一约束冲突,视为已存在,幂等返回 + if isUniqueViolation(err) { + return nil + } return err } s.clearRoleUsersCaches(ctx, rp.RoleID)