package invite import ( "context" "strings" ) type inviteRankRow struct { UserID int64 Nickname string Avatar string InviteCount int64 RewardGoldCoins int64 } // GetRank 返回累计邀请排行榜。排行榜不按月重置。 func (s *InviteService) GetRank(ctx context.Context, user AuthUser, limit int) (*InviteRankResponse, error) { limit = normalizeInviteRankLimit(limit) rows := make([]inviteRankRow, 0, limit) if err := s.repo.DB.WithContext(ctx).Raw(` SELECT invite_rank.user_id AS user_id, COALESCE(NULLIF(user_info.user_nickname, ''), invite_code.account, '') AS nickname, COALESCE(user_info.user_avatar, '') AS avatar, invite_rank.invite_count AS invite_count, COALESCE(reward_rank.reward_gold_coins, 0) AS reward_gold_coins FROM ( SELECT inviter_user_id AS user_id, COUNT(1) AS invite_count FROM invite_campaign_relation WHERE sys_origin = ? AND eligible_status = ? GROUP BY inviter_user_id ) invite_rank LEFT JOIN ( SELECT target_user_id AS user_id, COALESCE(SUM(gold_amount), 0) AS reward_gold_coins FROM invite_campaign_reward_log WHERE sys_origin = ? AND status = ? AND target_user_id = inviter_user_id GROUP BY target_user_id ) reward_rank ON reward_rank.user_id = invite_rank.user_id LEFT JOIN user_base_info user_info ON user_info.id = invite_rank.user_id LEFT JOIN invite_code_mapping invite_code ON invite_code.user_id = invite_rank.user_id ORDER BY invite_rank.invite_count DESC, reward_gold_coins DESC, invite_rank.user_id ASC LIMIT ? `, user.SysOrigin, relationStatusEligible, user.SysOrigin, rewardLogStatusSuccess, limit).Scan(&rows).Error; err != nil { return nil, err } items := make([]InviteRankItem, 0, len(rows)) for index, row := range rows { items = append(items, InviteRankItem{ Rank: index + 1, UserID: row.UserID, Nickname: strings.TrimSpace(row.Nickname), Avatar: strings.TrimSpace(row.Avatar), InviteCount: row.InviteCount, RewardGoldCoins: row.RewardGoldCoins, }) } return &InviteRankResponse{ SysOrigin: user.SysOrigin, Limit: limit, Items: items, }, nil } func normalizeInviteRankLimit(limit int) int { if limit <= 0 { return defaultInviteRankLimit } if limit > maxInviteRankLimit { return maxInviteRankLimit } return limit }