From e24f05f6acc9efe90908ad79d213ae0bf6c49dd8 Mon Sep 17 00:00:00 2001 From: tsui110 Date: Wed, 31 Dec 2025 12:37:00 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=87=A0?= =?UTF-8?q?=E4=B8=AA=E6=98=BE=E7=A4=BA=E4=B8=8D=E5=AE=8C=E6=95=B4=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98,=E7=A7=BB=E9=99=A4=E4=BA=86=E5=8E=9F?= =?UTF-8?q?=E6=9C=89=E7=9A=84=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=97=A0=E9=99=90=E5=A2=9E=E9=95=BF=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/SplashScreen.vue | 17 +++- pages-activity/activity/duiduipeng/index.vue | 82 +++++++++++++------- pages-activity/composables/useRecords.js | 38 ++++++++- 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/components/SplashScreen.vue b/components/SplashScreen.vue index 8433317..711405c 100644 --- a/components/SplashScreen.vue +++ b/components/SplashScreen.vue @@ -29,9 +29,17 @@ onMounted(() => { const today = new Date() const dateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}` - // 获取今天的显示记录 - const splashKey = `splash_count_${dateStr}` - const todayCount = uni.getStorageSync(splashKey) || 0 + // 获取所有日期的显示记录(JSON对象) + const splashKey = 'splash_count' + let splashData = uni.getStorageSync(splashKey) + + // 如果缓存不存在或格式错误,初始化为空对象 + if (!splashData || typeof splashData !== 'object') { + splashData = {} + } + + // 获取今天的显示次数 + const todayCount = splashData[dateStr] || 0 // 每天前10次启动显示开屏动画 if (todayCount < 10) { @@ -39,7 +47,8 @@ onMounted(() => { visible.value = true // 更新今天的显示次数 - uni.setStorageSync(splashKey, todayCount + 1) + splashData[dateStr] = todayCount + 1 + uni.setStorageSync(splashKey, splashData) // 停留5秒后开始淡出动画 setTimeout(() => { diff --git a/pages-activity/activity/duiduipeng/index.vue b/pages-activity/activity/duiduipeng/index.vue index 7cbc61e..e6ad4c2 100644 --- a/pages-activity/activity/duiduipeng/index.vue +++ b/pages-activity/activity/duiduipeng/index.vue @@ -459,6 +459,37 @@ function cleanUrl(u) { return s.replace(/[`'\"]/g, '').trim() } +function cleanAvatar(avatar) { + if (!avatar) return '' + + // 如果是 base64 格式,确保格式正确 + const avatarStr = String(avatar).trim() + + // 检查是否已经是 data:image 格式 + if (avatarStr.startsWith('data:image/')) { + return avatarStr + } + + // 如果是 http(s) URL,直接返回 + if (avatarStr.startsWith('http://') || avatarStr.startsWith('https://')) { + return avatarStr + } + + // 如果是相对路径,直接返回 + if (avatarStr.startsWith('/')) { + return avatarStr + } + + // 其他情况,可能是不完整的 base64,尝试修复 + // 如果不包含 data:image 前缀,添加默认的 png 前缀 + if (avatarStr.match(/^[A-Za-z0-9+/=]+$/)) { + // 看起来像 base64 编码 + return `data:image/png;base64,${avatarStr}` + } + + return avatarStr +} + const MATCHING_GAME_CACHE_KEY = 'matching_game_cache_v1' function getMatchingGameCache() { @@ -672,24 +703,19 @@ async function fetchWinRecords(actId, issId) { try { const res = await getIssueDrawLogs(actId, issId) const list = (res && res.list) || (Array.isArray(res) ? res : []) - // 聚合同一奖品的记录 - const aggregate = {} - list.forEach(it => { - const key = it.reward_id || it.id - if (!aggregate[key]) { - aggregate[key] = { - id: key, - title: it.reward_name || it.title || it.name || '-', - image: it.reward_image || it.image || '', - count: 0 - } - } - aggregate[key].count += 1 - }) - const total = list.length || 1 - winRecords.value = Object.values(aggregate).map(it => ({ - ...it, - percent: ((it.count / total) * 100).toFixed(1) + + // 不再聚合,直接使用原始记录列表,保留用户信息 + winRecords.value = list.map(it => ({ + id: it.id, + title: it.reward_name || it.title || it.name || '-', + image: it.reward_image || it.image || '', + count: 1, + // 用户信息 + user_id: it.user_id, + user_name: it.user_name || '匿名用户', + avatar: cleanAvatar(it.avatar), + // 时间信息 + created_at: it.created_at })) } catch (e) { console.error('fetchWinRecords error', e) @@ -1063,9 +1089,9 @@ async function finishAndReport() { console.log('[对对碰] currentIssueRewards:', currentIssueRewards.value?.length, 'items') console.log('[对对碰] rewardsMap keys:', Object.keys(rewardsMap.value || {})) - // 解析中奖结果 - 后端返回格式是 { reward: { reward_id, name, level } } + // 解析中奖结果 - 后端返回格式是 { reward: { reward_id, name, level, product_image } } let wonItems = [] - + // 后端返回单个 reward 对象的情况 if (checkRes?.reward && checkRes.reward.reward_id) { const reward = checkRes.reward @@ -1073,14 +1099,16 @@ async function finishAndReport() { // 从本地 rewardsMap 查找图片 const allRewards = rewardsMap.value[issueId] || currentIssueRewards.value || [] console.log('[对对碰] 本地奖励数据:', allRewards.length, 'items') - const foundReward = allRewards.find(r => - String(r.id) === String(reward.reward_id) || + const foundReward = allRewards.find(r => + String(r.id) === String(reward.reward_id) || String(r.reward_id) === String(reward.reward_id) ) console.log('[对对碰] 匹配到的奖励:', foundReward) + // 优先使用后端返回的 product_image,没有则使用本地数据,最后才用 logo + const rewardImage = cleanUrl(reward.product_image || foundReward?.image || foundReward?.pic || foundReward?.img || foundReward?.product_image || '') wonItems = [{ title: reward.name || foundReward?.name || foundReward?.title || '神秘奖励', - image: foundReward?.image || foundReward?.pic || foundReward?.img || foundReward?.product_image || '', + image: rewardImage || '/static/logo.png', reward_id: reward.reward_id }] } @@ -1106,13 +1134,15 @@ async function finishAndReport() { // 如果已经有 title,直接使用 if (item.title) return item // 否则尝试从本地数据匹配 - const found = allRewards.find(r => - String(r.id) === String(item.reward_id) || + const found = allRewards.find(r => + String(r.id) === String(item.reward_id) || String(r.reward_id) === String(item.reward_id) ) + // 优先使用后端返回的 product_image,没有则使用本地数据,最后才用 logo + const itemImage = cleanUrl(item.product_image || item.image || item.img || found?.image || found?.pic || found?.product_image || '') return { title: item.title || item.name || found?.name || found?.title || '神秘奖励', - image: cleanUrl(item.image || item.img || found?.image || found?.pic || found?.product_image || ''), + image: itemImage || '/static/logo.png', reward_id: item.reward_id || item.id } }) diff --git a/pages-activity/composables/useRecords.js b/pages-activity/composables/useRecords.js index 0762fff..994b808 100644 --- a/pages-activity/composables/useRecords.js +++ b/pages-activity/composables/useRecords.js @@ -36,7 +36,7 @@ export function useRecords() { // 用户信息 user_id: it.user_id, user_name: it.user_name || '匿名用户', - avatar: it.avatar, + avatar: cleanAvatar(it.avatar), // 清理 avatar 数据 // 时间信息 created_at: it.created_at, @@ -60,6 +60,42 @@ export function useRecords() { return alpha + '赏' } + /** + * 清理和验证 avatar 数据 + * @param {string} avatar - 原始 avatar 数据(可能是 base64 或 URL) + * @returns {string} - 清理后的 avatar 数据 + */ + function cleanAvatar(avatar) { + if (!avatar) return '' + + // 如果是 base64 格式,确保格式正确 + const avatarStr = String(avatar).trim() + + // 检查是否已经是 data:image 格式 + if (avatarStr.startsWith('data:image/')) { + return avatarStr + } + + // 如果是 http(s) URL,直接返回 + if (avatarStr.startsWith('http://') || avatarStr.startsWith('https://')) { + return avatarStr + } + + // 如果是相对路径,直接返回 + if (avatarStr.startsWith('/')) { + return avatarStr + } + + // 其他情况,可能是不完整的 base64,尝试修复 + // 如果不包含 data:image 前缀,添加默认的 png 前缀 + if (avatarStr.match(/^[A-Za-z0-9+/=]+$/)) { + // 看起来像 base64 编码 + return `data:image/png;base64,${avatarStr}` + } + + return avatarStr + } + function clearRecords() { winRecords.value = [] }