feat(ui): 记录页月份联动与多项 UI 美化/修复
- records: 底部列表与月份选择器联动,新增 [本月|最近] 分段控件;标题/空态随模式切换 - leaderboard: 领奖台布局(冠军居中+皇冠)、次数标注于底座且三档水平对齐;头像 cloud:// 批量预解析提速(云函数需重新部署) - index/timer: 主色底图标改白色变体修复隐形;目标数字按微信字体缩放补偿真机遮挡 - settings: 配色方案横滑渐变色卡;头像上传前压缩至 200px - theme: 新增 teal 主题;暗黑背景统一对齐 - 圆形头像双保险(image 自身 border-radius)修复月/年榜方图 注: cloudfunctions/leaderboard 改动须在开发者工具重新部署才生效。
This commit is contained in:
@@ -126,7 +126,8 @@ exports.main = async (event) => {
|
||||
openid,
|
||||
duration,
|
||||
sessions,
|
||||
nickname: profile.nickname || ''
|
||||
nickname: profile.nickname || '',
|
||||
avatarUrl: profile.avatarUrl || ''
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -152,9 +153,23 @@ exports.main = async (event) => {
|
||||
nickname: item.nickname || '',
|
||||
name: _displayName(item),
|
||||
duration: item.duration,
|
||||
sessions: item.sessions
|
||||
sessions: item.sessions,
|
||||
avatarUrl: item.avatarUrl || ''
|
||||
}))
|
||||
|
||||
// Pre-resolve cloud:// avatar fileIDs into temporary HTTPS URLs so the
|
||||
// client <image> doesn't pay a getTempFileURL round-trip at render time
|
||||
// (that lazy round-trip is what made avatars lag 1-2s behind the text).
|
||||
// Non-cloud values (wx qlogo links, empty strings, base64 data URIs)
|
||||
// pass through untouched. If the resolve fails we keep the original fileID
|
||||
// — the client can still load it, just without the speed-up.
|
||||
const _avatarUrls = ranked.map(r => r.avatarUrl).concat(myEntry ? [myEntry.avatarUrl] : [])
|
||||
const _resolved = await _resolveAvatars(_avatarUrls)
|
||||
_resolved.forEach((url, i) => {
|
||||
if (i < ranked.length) ranked[i].avatarUrl = url
|
||||
else if (myEntry) myEntry.avatarUrl = url
|
||||
})
|
||||
|
||||
return {
|
||||
period,
|
||||
ranked,
|
||||
@@ -165,12 +180,39 @@ exports.main = async (event) => {
|
||||
nickname: myEntry.nickname || '',
|
||||
name: _displayName(myEntry),
|
||||
duration: myEntry.duration,
|
||||
sessions: myEntry.sessions
|
||||
sessions: myEntry.sessions,
|
||||
avatarUrl: myEntry.avatarUrl || ''
|
||||
} : null,
|
||||
updatedAt: now.toISOString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch-resolve cloud:// avatar fileIDs into temporary HTTPS URLs.
|
||||
* The client <image> would otherwise perform this getTempFileURL round-trip
|
||||
* lazily at render time — the root of the 1-2s avatar delay. Only cloud://
|
||||
* IDs are resolved; any other value passes through untouched. getTempFileURL
|
||||
* accepts ≤50 fileIDs per call, so we page in batches of 50. On failure we
|
||||
* return the original URLs so the client degrades to its normal cloud:// load.
|
||||
*/
|
||||
const _resolveAvatars = async (urls) => {
|
||||
const cloudUrls = (urls || []).filter(u => typeof u === 'string' && u.startsWith('cloud://'))
|
||||
if (cloudUrls.length === 0) return urls || []
|
||||
const map = {}
|
||||
for (let i = 0; i < cloudUrls.length; i += 50) {
|
||||
const batch = cloudUrls.slice(i, i + 50)
|
||||
try {
|
||||
const res = await cloud.getTempFileURL({ fileList: batch })
|
||||
;(res.fileList || []).forEach(f => {
|
||||
if (f && f.fileID && f.tempFileURL) map[f.fileID] = f.tempFileURL
|
||||
})
|
||||
} catch (e) {
|
||||
console.warn('[leaderboard] getTempFileURL batch failed:', e)
|
||||
}
|
||||
}
|
||||
return (urls || []).map(u => (u && map[u]) ? map[u] : u)
|
||||
}
|
||||
|
||||
function maskOpenid(openid) {
|
||||
if (!openid || openid === 'unknown') return '未知用户'
|
||||
if (openid.length <= 4) return '****' + openid
|
||||
|
||||
Reference in New Issue
Block a user