2026-04-27 19:12:00 +08:00

75 lines
2.5 KiB
Go

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 relation.inviter_user_id AS user_id, COUNT(1) AS invite_count
FROM invite_campaign_invitee_progress AS progress
INNER JOIN invite_campaign_relation AS relation ON relation.id = progress.relation_id
WHERE relation.sys_origin = ? AND relation.eligible_status = ? AND progress.valid_user = 1
GROUP BY relation.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
}