diff --git a/components/activity/CabinetPreviewPopup.vue b/components/activity/CabinetPreviewPopup.vue index d0f8d08..283f132 100644 --- a/components/activity/CabinetPreviewPopup.vue +++ b/components/activity/CabinetPreviewPopup.vue @@ -4,34 +4,29 @@ 我的盒柜 - × + + 查看全部 + × + - - - 📦 - 加载中... - - - - 🎁 - 暂无物品 - 参与活动获得奖品后会显示在这里 - - - - - - - {{ item.name }} - x{{ item.count }} - + + 加载中... + + + + 暂无物品,参与活动获取奖品 + + + + + + + x{{ item.count }} + + + +{{ items.length - maxDisplay }} - - - - 查看全部 {{ total }} 件物品 - @@ -40,16 +35,11 @@ + diff --git a/components/activity/LotteryResultPopup.vue b/components/activity/LotteryResultPopup.vue index bf70eb5..2a3a939 100644 --- a/components/activity/LotteryResultPopup.vue +++ b/components/activity/LotteryResultPopup.vue @@ -81,13 +81,17 @@ const groupedResults = computed(() => { const arr = Array.isArray(props.results) ? props.results : [] arr.forEach(item => { - const key = item.title || item.name || '神秘奖品' + // 使用reward_id作为唯一key,避免同名不同产品被错误合并 + const rewardId = item.reward_id || item.rewardId || item.id + const key = rewardId != null ? `rid_${rewardId}` : (item.title || item.name || '神秘奖品') + if (map.has(key)) { map.get(key).quantity++ } else { map.set(key, { - title: key, + title: item.title || item.name || '神秘奖品', image: item.image || item.img || item.pic || '', + reward_id: rewardId, quantity: 1 }) } diff --git a/pages.json b/pages.json index 1d73aee..449c7bb 100644 --- a/pages.json +++ b/pages.json @@ -54,6 +54,12 @@ "navigationBarTitleText": "我的道具卡" } }, + { + "path": "pages/invite/landing", + "style": { + "navigationBarTitleText": "好友邀请" + } + }, { "path": "pages/invites/index", "style": { @@ -158,12 +164,6 @@ "navigationBarBackgroundColor": "#000000", "navigationBarTextStyle": "white" } - }, - { - "path": "pages/register/register", - "style": { - "navigationBarTitleText": "" - } } ], "tabBar": { diff --git a/pages/activity/wuxianshang/index.vue b/pages/activity/wuxianshang/index.vue index 7c48dcc..40b7d8e 100644 --- a/pages/activity/wuxianshang/index.vue +++ b/pages/activity/wuxianshang/index.vue @@ -207,8 +207,8 @@ function openPayment(count) { return } paymentVisible.value = true - fetchPropCards() - fetchCoupons() + // 并行获取道具卡和优惠券 + Promise.all([fetchPropCards(), fetchCoupons()]) } async function onPaymentConfirm(data) { @@ -291,6 +291,7 @@ function mapResultsToFlipItems(resultRes, poolRewards) { const fromName = !fromId && rewardName ? poolArr.find(x => x?.title === rewardName) : null const it = fromId || fromName || null return { + reward_id: rewardId, // 添加reward_id用于正确分组 title: rewardName || it?.title || '奖励', image: d.image || it?.image || d.img || d.pic || d.product_image || '' } @@ -352,7 +353,19 @@ async function onMachineDraw(count) { }) }) - const resultRes = await getLotteryResult(orderNo) + // 轮询等待开奖完成 + let resultRes = await getLotteryResult(orderNo) + let pollCount = 0 + const maxPolls = 15 // 最多轮询15次,每次2秒,共30秒 + + while (resultRes?.status === 'paid_waiting' && + resultRes?.completed < resultRes?.count && + pollCount < maxPolls) { + await new Promise(r => setTimeout(r, resultRes?.nextPollMs || 2000)) + resultRes = await getLotteryResult(orderNo) + pollCount++ + } + const items = mapResultsToFlipItems(resultRes, currentIssueRewards.value) drawResults.value = items @@ -367,15 +380,16 @@ async function onMachineDraw(count) { // ============ 生命周期 ============ onLoad(async (opts) => { const id = opts?.id || '' - if (id) { - activityId.value = id - await fetchDetail() - setNavigationTitle('无限赏') - await fetchIssues() - await fetchRewardsForIssues(issues.value) - if (currentIssueId.value) { - fetchWinRecords(id, currentIssueId.value) - } + if (!id) return + activityId.value = id + // 并行获取活动详情和期数信息 + await Promise.all([fetchDetail(), fetchIssues()]) + setNavigationTitle('无限赏') + // 期数获取完成后获取奖励 + await fetchRewardsForIssues(issues.value) + // 异步获取记录(不阻塞渲染) + if (currentIssueId.value) { + fetchWinRecords(id, currentIssueId.value) } }) diff --git a/pages/activity/yifanshang/index.vue b/pages/activity/yifanshang/index.vue index 005e7f2..d2f4324 100644 --- a/pages/activity/yifanshang/index.vue +++ b/pages/activity/yifanshang/index.vue @@ -298,15 +298,16 @@ function onPaymentSuccess(payload) { onLoad(async (opts) => { startNowTicker() const id = opts?.id || '' - if (id) { - activityId.value = id - await fetchDetail() - setNavigationTitle('一番赏') - await fetchIssues() - await fetchRewardsForIssues(issues.value) - if (currentIssueId.value) { - fetchWinRecords(id, currentIssueId.value) - } + if (!id) return + activityId.value = id + // 并行获取活动详情和期数信息 + await Promise.all([fetchDetail(), fetchIssues()]) + setNavigationTitle('一番赏') + // 期数获取完成后获取奖励 + await fetchRewardsForIssues(issues.value) + // 异步获取记录(不阻塞渲染) + if (currentIssueId.value) { + fetchWinRecords(id, currentIssueId.value) } }) diff --git a/pages/invite/landing.vue b/pages/invite/landing.vue new file mode 100644 index 0000000..cd27107 --- /dev/null +++ b/pages/invite/landing.vue @@ -0,0 +1,531 @@ + + + + + diff --git a/pages/login/index.vue b/pages/login/index.vue index 2340412..c9e93f0 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -61,10 +61,6 @@ - - - 没有账号?立即注册 - @@ -126,8 +122,6 @@ function toggleAgreement() { agreementChecked.value = !agreementChecked.value } -function goToRegister() { uni.navigateTo({ url: '/pages/register/register' }) } - function handleLogin() { if (!agreementChecked.value) { uni.showToast({ title: '请先阅读并同意协议', icon: 'none' }) diff --git a/pages/mine/index.vue b/pages/mine/index.vue index 4344d1d..7718891 100644 --- a/pages/mine/index.vue +++ b/pages/mine/index.vue @@ -31,7 +31,7 @@ - {{ pointsBalance || 0 }} + {{ formatPoints(pointsBalance) }} 积分 @@ -190,7 +190,7 @@ - {{ Number(item.points) > 0 ? '+' : '' }}{{ item.points }} + {{ Number(item.points) > 0 ? '+' : '' }}{{ formatPoints(item.points) }} @@ -516,7 +516,7 @@ export default { try { uni.setStorageSync('inviter_code', v) } catch (_) {} const token = uni.getStorageSync('token') if (!token) { - uni.navigateTo({ url: `/pages/register/register?invite_code=${encodeURIComponent(v)}` }) + uni.navigateTo({ url: '/pages/login/index' }) } } }, @@ -526,17 +526,17 @@ export default { onShareAppMessage() { const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || '' return { - title: '给你一个宝藏应用,快来!', - path: inviteCode ? `/pages/register/register?invite_code=${inviteCode}` : '/pages/register/register', - imageUrl: '/static/logo.png' + title: '🎁 好友邀请你一起玩,快来领福利!', + path: inviteCode ? `/pages/invite/landing?invite_code=${inviteCode}` : '/pages/invite/landing', + imageUrl: '/static/share_invite.png' } }, onShareTimeline() { const inviteCode = uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || '' return { - title: '给你一个宝藏应用,快来!', + title: '🎁 好友邀请你一起玩,快来领福利!', query: inviteCode ? `invite_code=${inviteCode}` : '', - imageUrl: '/static/logo.png' + imageUrl: '/static/share_invite.png' } }, methods: { @@ -544,6 +544,12 @@ export default { const v = this.inviteCode || uni.getStorageSync('invite_code') || (uni.getStorageSync('user_info') || {}).invite_code || '' return String(v || '').trim() }, + formatPoints(v) { + const n = Number(v) || 0 + if (n === 0) return '0' + const f = n / 100 + return Number.isInteger(f) ? String(f) : f.toFixed(2).replace(/\.?0+$/, '') + }, copyInviteCode() { const code = this.getInviteCode() if (!code) { @@ -559,7 +565,7 @@ export default { }, getInviteSharePath() { const code = this.getInviteCode() - return code ? `/pages/register/register?invite_code=${encodeURIComponent(code)}` : '/pages/register/register' + return code ? `/pages/invite/landing?invite_code=${encodeURIComponent(code)}` : '/pages/invite/landing' }, normalizePointsBalance(v) { if (v && typeof v === 'object') { diff --git a/pages/points/index.vue b/pages/points/index.vue index b8e2c70..43bde87 100644 --- a/pages/points/index.vue +++ b/pages/points/index.vue @@ -33,7 +33,7 @@ {{ getActionText(item.action) || item.title || item.reason || '积分变更' }} - {{ (item.points ?? 0) > 0 ? '+' : '' }}{{ item.points ?? 0 }} + {{ (item.points ?? 0) > 0 ? '+' : '' }}{{ formatPoints(item.points) }} @@ -65,6 +65,12 @@ const error = ref('') const page = ref(1) const pageSize = ref(20) const hasMore = ref(true) +function formatPoints(v) { + const n = Number(v) || 0 + if (n === 0) return '0' + const f = n / 100 + return Number.isInteger(f) ? String(f) : f.toFixed(2).replace(/\.?0+$/, '') +} function formatTime(t) { if (!t) return '' diff --git a/pages/register/register.vue b/pages/register/register.vue deleted file mode 100644 index f4d32eb..0000000 --- a/pages/register/register.vue +++ /dev/null @@ -1,172 +0,0 @@ - - - - - diff --git a/static/share_invite.png b/static/share_invite.png new file mode 100644 index 0000000..3f11c92 Binary files /dev/null and b/static/share_invite.png differ diff --git a/utils/request.js b/utils/request.js index d926771..0e97173 100644 --- a/utils/request.js +++ b/utils/request.js @@ -22,7 +22,6 @@ function handleAuthExpired() { export function request({ url, method = 'GET', data = {}, header = {} }) { return new Promise((resolve, reject) => { const finalHeader = { ...buildDefaultHeaders(), ...header } - try { console.log('HTTP request', method, url, 'data', data, 'headers', finalHeader) } catch (e) { } uni.request({ url: BASE_URL + url, method, @@ -31,7 +30,6 @@ export function request({ url, method = 'GET', data = {}, header = {} }) { timeout: 15000, success: (res) => { const code = res.statusCode - try { console.log('HTTP response', method, url, 'status', code, 'body', res.data) } catch (e) { } if (code >= 200 && code < 300) { const body = res.data resolve(body && body.data !== undefined ? body.data : body) @@ -47,7 +45,6 @@ export function request({ url, method = 'GET', data = {}, header = {} }) { } }, fail: (err) => { - try { console.error('HTTP fail', method, url, 'err', err) } catch (e) { } reject(err) } })