feat(ui): 排行榜与首页打卡卡片多项优化
排行榜性能: - 客户端乐观缓存:进页面/切周期秒显旧数据,后台静默刷新,消除 2-3s 空白 - 云函数实例缓存 TTL 60s -> 5min,降低全表扫描频率 排行榜 UI: - 空状态重设计:奖杯光环插画(径向光晕 + 闪光漂浮) - 领奖台 slot 撑满对齐列表、金银铜底座配色、角标与昵称间距修复、底线对齐 首页打卡卡片: - 火焰光晕脉动 + 72rpx 大数字 + 分段进度格子 - 计划 >10 天时进度退化为里程碑连续条 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ Page({
|
||||
rankedList: [],
|
||||
myEntry: null,
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
empty: false,
|
||||
icons: iconsMod.build()
|
||||
},
|
||||
@@ -58,7 +59,24 @@ Page({
|
||||
this._fetchSeq = (this._fetchSeq || 0) + 1
|
||||
const seq = this._fetchSeq
|
||||
const period = this.data.activePeriod
|
||||
this.setData({ loading: true, empty: false })
|
||||
|
||||
// 乐观缓存:命中该 period 的近期缓存就先秒显旧数据,后台再静默拉新。
|
||||
// 命中时不进 loading 骨架屏(避免旧数据被空白覆盖),用 refreshing 标记
|
||||
// 后台刷新状态;未命中才显示骨架屏。云函数全表扫描冷启动可达 2-3s,
|
||||
// 这层客户端缓存把"重复进入 / 切 period"的等待几乎降到无感。
|
||||
const cached = storage.getLeaderboardCache(period)
|
||||
if (cached && cached.rankedList) {
|
||||
this.setData({
|
||||
rankedList: cached.rankedList,
|
||||
myEntry: cached.myEntry,
|
||||
loading: false,
|
||||
empty: cached.empty,
|
||||
refreshing: true
|
||||
})
|
||||
} else {
|
||||
this.setData({ loading: true, empty: false, refreshing: false })
|
||||
}
|
||||
|
||||
wx.cloud.callFunction({
|
||||
name: 'leaderboard',
|
||||
data: {
|
||||
@@ -76,7 +94,12 @@ Page({
|
||||
// them into thinking the cloud is broken.
|
||||
console.warn('[leaderboard] cloud function failed, using local fallback:', err)
|
||||
if (seq !== this._fetchSeq) { if (cb) cb(); return }
|
||||
this._applyLocal()
|
||||
// 已有缓存秒显时后台刷新失败:保持旧数据,不打断用户;仅无缓存才走本地兜底。
|
||||
if (cached && cached.rankedList) {
|
||||
this.setData({ refreshing: false })
|
||||
} else {
|
||||
this._applyLocal()
|
||||
}
|
||||
if (cb) cb()
|
||||
})
|
||||
},
|
||||
@@ -91,12 +114,16 @@ Page({
|
||||
durationText: util.formatDuration(result.myEntry.duration),
|
||||
isMe: true
|
||||
} : null
|
||||
const empty = list.length === 0 && !myEntry
|
||||
this.setData({
|
||||
rankedList: list,
|
||||
myEntry,
|
||||
loading: false,
|
||||
empty: list.length === 0 && !myEntry
|
||||
refreshing: false,
|
||||
empty
|
||||
})
|
||||
// 写入乐观缓存:下次进页面 / 切 period 秒显
|
||||
storage.setLeaderboardCache(this.data.activePeriod, { rankedList: list, myEntry, empty })
|
||||
},
|
||||
|
||||
/** Local fallback: use local storage when cloud function isn't deployed */
|
||||
@@ -122,9 +149,9 @@ Page({
|
||||
rank: 1, openid: 'local', name: localName, nickname: profile.nickname || '',
|
||||
duration, durationText: util.formatDuration(duration), sessions
|
||||
}
|
||||
this.setData({ rankedList: [entry], myEntry: { ...entry, isMe: true }, loading: false, empty: false })
|
||||
this.setData({ rankedList: [entry], myEntry: { ...entry, isMe: true }, loading: false, refreshing: false, empty: false })
|
||||
} else {
|
||||
this.setData({ loading: false, empty: true })
|
||||
this.setData({ loading: false, refreshing: false, empty: true })
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user