package user import ( "context" "strings" "hyapp/pkg/xerr" userdomain "hyapp/services/user-service/internal/domain/user" ) const ( defaultContentBlacklistPageSize int32 = 50 maxContentBlacklistPageSize int32 = 200 maxContentBlacklistReasonRunes = 255 ) // UserContentBlacklistCommand 是后台增加/移除运营内容屏蔽的治理命令。 // 时间由 user-service owner 生成,不能信任后台进程或客户端传入的时钟。 type UserContentBlacklistCommand struct { UserID int64 OperatorAdminID int64 Reason string NowMs int64 } // ListUserContentBlacklist 分页读取当前 active 屏蔽用户。 func (s *Service) ListUserContentBlacklist(ctx context.Context, page int32, pageSize int32) ([]userdomain.ContentBlacklistEntry, int64, error) { if s.contentBlacklistRepository == nil { return nil, 0, xerr.New(xerr.Unavailable, "content blacklist repository is not configured") } if page < 1 { page = 1 } if pageSize <= 0 { pageSize = defaultContentBlacklistPageSize } if pageSize > maxContentBlacklistPageSize { pageSize = maxContentBlacklistPageSize } return s.contentBlacklistRepository.ListUserContentBlacklist(ctx, page, pageSize) } // AdminAddUserContentBlacklist 启用指定用户的运营内容屏蔽。 // 重复添加保持单行当前态并更新操作者和原因,不会把账号状态改成 banned/disabled。 func (s *Service) AdminAddUserContentBlacklist(ctx context.Context, command UserContentBlacklistCommand) (userdomain.ContentBlacklistEntry, error) { if s.contentBlacklistRepository == nil { return userdomain.ContentBlacklistEntry{}, xerr.New(xerr.Unavailable, "content blacklist repository is not configured") } normalized, err := s.normalizeUserContentBlacklistCommand(command) if err != nil { return userdomain.ContentBlacklistEntry{}, err } return s.contentBlacklistRepository.AddUserContentBlacklist(ctx, normalized) } // AdminRemoveUserContentBlacklist 关闭指定用户的运营内容屏蔽。 // 已经移除时返回 removed=false,允许后台重试同一个操作而不产生错误。 func (s *Service) AdminRemoveUserContentBlacklist(ctx context.Context, command UserContentBlacklistCommand) (bool, error) { if s.contentBlacklistRepository == nil { return false, xerr.New(xerr.Unavailable, "content blacklist repository is not configured") } normalized, err := s.normalizeUserContentBlacklistCommand(command) if err != nil { return false, err } return s.contentBlacklistRepository.RemoveUserContentBlacklist(ctx, normalized) } func (s *Service) normalizeUserContentBlacklistCommand(command UserContentBlacklistCommand) (UserContentBlacklistCommand, error) { if command.UserID <= 0 { return UserContentBlacklistCommand{}, xerr.New(xerr.InvalidArgument, "user_id is required") } if command.OperatorAdminID <= 0 { return UserContentBlacklistCommand{}, xerr.New(xerr.InvalidArgument, "operator_admin_id is required") } command.Reason = strings.TrimSpace(command.Reason) if len([]rune(command.Reason)) > maxContentBlacklistReasonRunes { return UserContentBlacklistCommand{}, xerr.New(xerr.InvalidArgument, "reason is too long") } // user-service 的 UTC 时钟是持久事实时间源,后台 RequestMeta.sent_at_ms 只用于链路追踪。 command.NowMs = s.now().UTC().UnixMilli() return command, nil }