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>
<script src="../../common/i18n.js?v=20260606-1"></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/params.js?v=20260611-invite-referrer"></script>
<script src="../../common/toast.js"></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> </body>
</html> </html>

View File

@ -20,13 +20,6 @@
'ios_url', 'ios_url',
'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 params = new URLSearchParams(window.location.search);
var state = { var state = {
inviteCode: firstParam(INVITE_CODE_KEYS), inviteCode: firstParam(INVITE_CODE_KEYS),
@ -34,6 +27,9 @@
inviterAvatar: firstParam(SHARE_AVATAR_KEYS), inviterAvatar: firstParam(SHARE_AVATAR_KEYS),
inviteLink: '', inviteLink: '',
inviteRewardStatus: null, inviteRewardStatus: null,
rankRows: [],
rankLoaded: false,
rankLoading: false,
claiming: {}, claiming: {},
}; };
@ -258,6 +254,36 @@
if (node) node.textContent = value; 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) { function pad(value) {
return String(Math.max(0, value)).padStart(2, '0'); return String(Math.max(0, value)).padStart(2, '0');
} }
@ -281,8 +307,21 @@
function renderRank() { function renderRank() {
var list = $('#rankList'); var list = $('#rankList');
if (!list) return;
list.textContent = ''; 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 row = document.createElement('article');
var rank = document.createElement('span'); var rank = document.createElement('span');
var medal = document.createElement('img'); var medal = document.createElement('img');
@ -306,10 +345,14 @@
rank.textContent = item.rank; 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 = ''; avatar.alt = '';
name.textContent = item.name; name.textContent = item.name;
score.textContent = formatPeople(item.score); score.textContent = formatPeople(formatNumber(item.score));
row.appendChild(rank); row.appendChild(rank);
row.appendChild( 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) { function claimInviteReward(tier) {
var api = window.HyAppAPI && window.HyAppAPI.inviteActivityReward; var api = window.HyAppAPI && window.HyAppAPI.inviteActivityReward;
var rewardType = tierRewardType(tier); var rewardType = tierRewardType(tier);
@ -639,6 +712,7 @@
$('#transportPane').classList.toggle('is-active', !isQuota); $('#transportPane').classList.toggle('is-active', !isQuota);
$('#quotaPane').classList.toggle('is-active', isQuota); $('#quotaPane').classList.toggle('is-active', isQuota);
$('#rankPanel').hidden = !isQuota; $('#rankPanel').hidden = !isQuota;
if (isQuota) loadInviteActivityLeaderboard(false);
} }
function copyTextFrom(selector) { function copyTextFrom(selector) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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