This commit is contained in:
zhx 2026-06-11 16:57:10 +08:00
parent 1a1bb33b48
commit 20bdbc6a37
9 changed files with 104 additions and 12 deletions

View File

@ -253,9 +253,9 @@
})();
</script>
<script src="../../common/i18n.js?v=20260606-1"></script>
<script src="../../common/api.js?v=20260611-invite-reward"></script>
<script src="../../common/api.js?v=20260611-invite-rank"></script>
<script src="../../common/params.js?v=20260611-invite-referrer"></script>
<script src="../../common/toast.js"></script>
<script src="./script.js?v=20260611-invite-reward"></script>
<script src="./script.js?v=20260611-invite-rank"></script>
</body>
</html>

View File

@ -20,13 +20,6 @@
'ios_url',
'url',
];
var rankRows = Array.from({ length: 30 }, function (_, index) {
return {
rank: index + 1,
name: 'hanneem',
score: '123',
};
});
var params = new URLSearchParams(window.location.search);
var state = {
inviteCode: firstParam(INVITE_CODE_KEYS),
@ -34,6 +27,9 @@
inviterAvatar: firstParam(SHARE_AVATAR_KEYS),
inviteLink: '',
inviteRewardStatus: null,
rankRows: [],
rankLoaded: false,
rankLoading: false,
claiming: {},
};
@ -258,6 +254,36 @@
if (node) node.textContent = value;
}
function normalizeRankPayload(payload) {
if (!payload || typeof payload !== 'object') return [];
var items = field(payload, 'entries', 'entries');
if (!Array.isArray(items)) items = field(payload, 'items', 'items');
if (!Array.isArray(items)) return [];
return items
.map(function (item, index) {
var user = field(item, 'user', 'user') || {};
var userID = textValue(field(item, 'user_id', 'userId'));
return {
rank:
numberValue(field(item, 'rank_no', 'rankNo')) ||
index + 1,
name:
textValue(field(user, 'username', 'username')) ||
textValue(
field(user, 'display_user_id', 'displayUserId')
) ||
(userID ? 'ID ' + userID : '--'),
avatar: textValue(field(user, 'avatar', 'avatar')),
score: numberValue(
field(item, 'valid_invite_count', 'validInviteCount')
),
};
})
.filter(function (item) {
return item.rank > 0 && item.score > 0;
});
}
function pad(value) {
return String(Math.max(0, value)).padStart(2, '0');
}
@ -281,8 +307,21 @@
function renderRank() {
var list = $('#rankList');
if (!list) return;
list.textContent = '';
rankRows.forEach(function (item) {
if (state.rankLoading && !state.rankRows.length) {
list.appendChild(
emptyTaskNode(t('invite.rankLoading', 'Loading rank...'))
);
return;
}
if (!state.rankRows.length) {
list.appendChild(
emptyTaskNode(t('invite.noRankData', 'No rank data'))
);
return;
}
state.rankRows.forEach(function (item) {
var row = document.createElement('article');
var rank = document.createElement('span');
var medal = document.createElement('img');
@ -306,10 +345,14 @@
rank.textContent = item.rank;
}
avatar.src = './assets/rank-avatar.png';
avatar.src = item.avatar || './assets/rank-avatar.png';
avatar.onerror = function () {
avatar.onerror = null;
avatar.src = './assets/rank-avatar.png';
};
avatar.alt = '';
name.textContent = item.name;
score.textContent = formatPeople(item.score);
score.textContent = formatPeople(formatNumber(item.score));
row.appendChild(rank);
row.appendChild(
@ -583,6 +626,36 @@
});
}
function loadInviteActivityLeaderboard(force) {
var api = window.HyAppAPI && window.HyAppAPI.inviteActivityReward;
if (
state.rankLoading ||
(state.rankLoaded && !force) ||
!api ||
!api.leaderboard ||
!window.HyAppAPI.getAccessToken()
) {
renderRank();
return Promise.resolve();
}
state.rankLoading = true;
renderRank();
return api
.leaderboard({ page: 1, page_size: 50 })
.then(function (payload) {
state.rankRows = normalizeRankPayload(payload);
state.rankLoaded = true;
state.rankLoading = false;
renderRank();
})
.catch(function () {
state.rankRows = [];
state.rankLoaded = true;
state.rankLoading = false;
renderRank();
});
}
function claimInviteReward(tier) {
var api = window.HyAppAPI && window.HyAppAPI.inviteActivityReward;
var rewardType = tierRewardType(tier);
@ -639,6 +712,7 @@
$('#transportPane').classList.toggle('is-active', !isQuota);
$('#quotaPane').classList.toggle('is-active', isQuota);
$('#rankPanel').hidden = !isQuota;
if (isQuota) loadInviteActivityLeaderboard(false);
}
function copyTextFrom(selector) {

View File

@ -681,6 +681,12 @@ var default_api = 'https://api.global-interaction.com/';
method: 'GET',
});
},
leaderboard: function (params) {
return request('/api/v1/activities/invite-reward/leaderboard', {
method: 'GET',
query: params || {},
});
},
claim: function (payload) {
return request('/api/v1/activities/invite-reward/claim', {
method: 'POST',

View File

@ -104,6 +104,8 @@
"invite.validInviteTaskDescription": "ادع {threshold} أصدقاء مؤهلين، المكافأة {reward} عملة",
"invite.rank": "الترتيب",
"invite.peopleSuffix": "{value} أشخاص",
"invite.rankLoading": "جار تحميل الترتيب...",
"invite.noRankData": "لا توجد بيانات ترتيب",
"invite.copied": "تم النسخ",
"invite.copyFailed": "فشل النسخ",
"invite.notAvailable": "غير متاح الآن",

View File

@ -104,6 +104,8 @@
"invite.validInviteTaskDescription": "Invite {threshold} valid friends, reward {reward} coins",
"invite.rank": "Rank",
"invite.peopleSuffix": "{value} people",
"invite.rankLoading": "Loading rank...",
"invite.noRankData": "No rank data",
"invite.copied": "Copied",
"invite.copyFailed": "Copy failed",
"invite.notAvailable": "Not available yet",

View File

@ -104,6 +104,8 @@
"invite.validInviteTaskDescription": "Invita a {threshold} amigos válidos, recompensa {reward} monedas",
"invite.rank": "Ranking",
"invite.peopleSuffix": "{value} personas",
"invite.rankLoading": "Cargando ranking...",
"invite.noRankData": "No hay datos de ranking",
"invite.copied": "Copiado",
"invite.copyFailed": "Error al copiar",
"invite.notAvailable": "Aún no disponible",

View File

@ -74,6 +74,8 @@
"invite.validInviteTaskDescription": "Undang {threshold} teman valid, hadiah {reward} koin",
"invite.rank": "Peringkat",
"invite.peopleSuffix": "{value} orang",
"invite.rankLoading": "Memuat peringkat...",
"invite.noRankData": "Belum ada data peringkat",
"invite.copied": "Disalin",
"invite.copyFailed": "Gagal menyalin",
"invite.notAvailable": "Belum tersedia",

View File

@ -74,6 +74,8 @@
"invite.validInviteTaskDescription": "{threshold} geçerli arkadaş davet et, ödül {reward} coin",
"invite.rank": "Sıralama",
"invite.peopleSuffix": "{value} kişi",
"invite.rankLoading": "Sıralama yükleniyor...",
"invite.noRankData": "Sıralama verisi yok",
"invite.copied": "Kopyalandı",
"invite.copyFailed": "Kopyalama başarısız",
"invite.notAvailable": "Henüz kullanılamaz",

View File

@ -74,6 +74,8 @@
"invite.validInviteTaskDescription": "邀请 {threshold} 位有效用户,奖励 {reward} 金币",
"invite.rank": "排行榜",
"invite.peopleSuffix": "{value}人",
"invite.rankLoading": "排行榜加载中...",
"invite.noRankData": "暂无排行榜数据",
"invite.copied": "已复制",
"invite.copyFailed": "复制失败",
"invite.notAvailable": "暂不可领取",