Appearance
排行榜页面
这个 Recipe 适合游戏结算页、挑战榜、耗时榜等场景:公开榜单可以直接读取;当前用户记录和成绩提交由平台代管能力自行校验 Host 登录状态。
基础封装
ts
import hbSDK, { HbMiniProgramSDKError } from '@heybox/hb-sdk'
const LEADERBOARD_KEY = 'cube_run_total'
export async function loadLeaderboard(cursor?: string) {
const page = await hbSDK.cloud.leaderboard.getList({
key: LEADERBOARD_KEY,
limit: 20,
cursor,
})
let current
try {
current = await hbSDK.cloud.leaderboard.getCurrentUserEntry({
key: LEADERBOARD_KEY,
})
} catch (error) {
// 未登录(401)与平台限流(RATE_LIMITED / RATE_LIMITED_BY_RUNTIME)都不应阻断公开列表。
if (
!(error instanceof HbMiniProgramSDKError) ||
!['UNAUTHORIZED', 'RATE_LIMITED', 'RATE_LIMITED_BY_RUNTIME'].includes(error.code)
) {
throw error
}
}
return {
entries: page.entries,
current,
cursor: page.cursor,
hasMore: page.hasMore,
}
}
export async function submitScore(score: number) {
try {
return await hbSDK.cloud.leaderboard.submit({
key: LEADERBOARD_KEY,
score,
})
} catch (error) {
if (error instanceof HbMiniProgramSDKError) {
console.log('[leaderboard]', error.code, error.message)
return undefined
}
throw error
}
}提交后刷新
ts
async function handleGameFinished(totalScore: number) {
const entry = await submitScore(totalScore)
if (!entry) return
console.log(entry.ranked ? `当前排名:${entry.rank}` : '已保存成绩')
renderLeaderboard(await loadLeaderboard())
}注意事项
- 不要仅为探测登录态而预先调用用户资料 API。
submit()和当前用户记录读取会在未登录时返回UNAUTHORIZED,业务按正常错误提示处理。 - 遇到
RATE_LIMITED(上游 403/429 或 Runtime 熔断窗口)或RATE_LIMITED_BY_RUNTIME(Runtime 本地配额 / 循环检测拒绝)时不要立即重试:按error.data.retryAfterMs(可能缺失)退避,或直接展示「稍后再试」;反复重试会把用户 IP 打成被网关封禁。 auth.login()是获取后端授权码的入口,不依赖network,也不是排行榜平台代管身份的必需前置步骤。- 公开榜单读取不要求登录;当前用户记录失败不应阻断公开列表展示。
cursor只能原样传回下一页请求。ranked: false时不要把rank: 0展示成真实排名。
附带用户展示资料
需要展示昵称、头像时,额外声明 userInfo 权限(见权限声明),读取资料并随成绩写入 extra:
ts
export async function submitScoreWithProfile(score: number) {
const result = await hbSDK.user.getInfo()
const profile = result.isHeyboxAppLoggedIn ? result.userInfo?.profile : null
return hbSDK.cloud.leaderboard.submit({
key: LEADERBOARD_KEY,
score,
extra: profile
? { nickname: profile.nickname, avatar: profile.avatar }
: {},
})
}读取榜单时,从 entry.extra.nickname、entry.extra.avatar 取出展示,缺失时使用默认值。 用户资料是可选展示信息,未取得时可以只提交分数。资料是随成绩保存的快照,提交相同或更差的分数也不会更新 extra。