diff --git a/cloudfunctions/leaderboard/index.js b/cloudfunctions/leaderboard/index.js index 0ecacbc..2f53498 100644 --- a/cloudfunctions/leaderboard/index.js +++ b/cloudfunctions/leaderboard/index.js @@ -43,11 +43,11 @@ const tsOf = (d) => { // per openid. Uses cursor pagination (_id > lastId) instead of skip(N): // skip is O(N) and degrades as the collection grows; a cursor is constant // cost per page, and default get() order (_id ascending) won't drop/dup. -const _fetchLatestByOpenid = async () => { - if (_docsCache && (Date.now() - _docsCache.ts) < CACHE_TTL) { +const _fetchLatestByOpenid = async (force) => { + if (!force && _docsCache && (Date.now() - _docsCache.ts) < CACHE_TTL) { return _docsCache.latestByOpenid } - // 缓存过期:复用 in-flight promise,避免并发请求各自全表扫描(缓存击穿) + // 缓存过期或强刷(force):复用 in-flight promise,避免并发请求各自全表扫描(缓存击穿) if (_docsCachePromise) return _docsCachePromise _docsCachePromise = (async () => { const latestByOpenid = new Map() @@ -81,7 +81,7 @@ const _fetchLatestByOpenid = async () => { } exports.main = async (event) => { - const { period, maxRank } = event || {} + const { period, maxRank, force } = event || {} const limit = Math.max(1, Math.min(parseInt(maxRank) || DEFAULT_MAX_RANK, 500)) if (!period) return { err: 'missing period' } @@ -107,7 +107,7 @@ exports.main = async (event) => { // start add() bug; only the latest updatedAt counts, else we'd sum the // same records N times and inflate the board. Latest (not first) also // gives the freshest profile.nickname before admin-dedupe runs. - const latestByOpenid = await _fetchLatestByOpenid() + const latestByOpenid = await _fetchLatestByOpenid(force) // Second pass: each openid appears exactly once, so the accumulation // logic doesn't need any dedup guards. diff --git a/config.js b/config.js index ff9be66..94b681f 100644 --- a/config.js +++ b/config.js @@ -7,7 +7,7 @@ module.exports = { version: 'v3.01', /** 最后更新日期,外显在设置页「关于」 */ - updatedAt: '2026-07-27', + updatedAt: '2026-07-28', /** 开发者名称 / 微信号,设置页点击可复制 */ developer: '刘承', diff --git a/pages/leaderboard/leaderboard.js b/pages/leaderboard/leaderboard.js index 8a8b377..d907617 100644 --- a/pages/leaderboard/leaderboard.js +++ b/pages/leaderboard/leaderboard.js @@ -35,16 +35,20 @@ Page({ const tb = this.getTabBar() if (tb) tb.setData({ selected: 2 }) } catch (e) {} - if (this._firstShow) { - this._firstShow = false - this.fetchRank() - return - } - this.fetchRank() + // 训练完设的强刷标志:下次进排行榜跳过云函数缓存,立刻拿到含新记录的数据 + let force = false + try { + if (wx.getStorageSync('_lb_force_refresh')) { + force = true + wx.removeStorageSync('_lb_force_refresh') + } + } catch (e) {} + this._firstShow = false + this.fetchRank(undefined, force) }, onPullDownRefresh() { - this.fetchRank(() => wx.stopPullDownRefresh()) + this.fetchRank(() => wx.stopPullDownRefresh(), true) }, switchPeriod(e) { @@ -54,7 +58,7 @@ Page({ this.fetchRank() }, - fetchRank(cb) { + fetchRank(cb, force) { // 序列号:快速切换周期时丢弃旧响应,避免旧 period 的数据覆盖新 period this._fetchSeq = (this._fetchSeq || 0) + 1 const seq = this._fetchSeq @@ -81,7 +85,8 @@ Page({ name: 'leaderboard', data: { period, - maxRank: config.leaderboardMaxRank + maxRank: config.leaderboardMaxRank, + force: !!force } }).then(res => { if (seq !== this._fetchSeq) { if (cb) cb(); return } // 过期响应,丢弃 diff --git a/pages/timer/timer.js b/pages/timer/timer.js index 971f9e3..8e50cd5 100644 --- a/pages/timer/timer.js +++ b/pages/timer/timer.js @@ -403,6 +403,8 @@ Page({ // Flag for the index page's "训练完成" highlight try { wx.setStorageSync('_last_train_at', Date.now()) } catch (e) {} + // 标记排行榜强刷:下次打开排行榜跳过云函数缓存,让刚训练的数据立即可见 + try { wx.setStorageSync('_lb_force_refresh', true) } catch (e) {} const finalStreak = storage.getStreak().count