From b79cd379326e2ddec48835eb9ebc937b34431323 Mon Sep 17 00:00:00 2001 From: ty200947752 Date: Mon, 15 Dec 2025 11:02:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=97=A5=E5=BF=97=EF=BC=8C?= =?UTF-8?q?=E4=B8=80=E7=95=AA=E8=B5=8F=E7=A7=BB=E9=99=A4=E9=81=93=E5=85=B7?= =?UTF-8?q?=E5=8D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 8 +- api/appUser.js | 62 +++ console-1763271273297.log | 146 ----- manifest.json | 3 +- pages.json | 13 + pages/activity/duiduipeng.vue | 65 --- pages/activity/duiduipeng/index.vue | 2 +- pages/activity/wuxianshang.vue | 65 --- pages/activity/wuxianshang/index.vue | 153 +++++- pages/activity/yifanshang.vue | 66 --- pages/activity/yifanshang/index.vue | 90 +-- pages/cabinet/index.vue | 794 ++++++++++++++++++++++++++- pages/index/index.vue | 2 +- pages/login/index.vue | 133 ++++- pages/mine/index.vue | 744 ++++++++++++++++++++++++- pages/orders/index.vue | 59 +- pages/shop/index.vue | 19 +- 17 files changed, 1984 insertions(+), 440 deletions(-) delete mode 100644 console-1763271273297.log delete mode 100644 pages/activity/duiduipeng.vue delete mode 100644 pages/activity/wuxianshang.vue delete mode 100644 pages/activity/yifanshang.vue diff --git a/App.vue b/App.vue index d22b78e..841f8ed 100644 --- a/App.vue +++ b/App.vue @@ -1,8 +1,12 @@ - - \ No newline at end of file diff --git a/pages/activity/duiduipeng/index.vue b/pages/activity/duiduipeng/index.vue index e44d131..a66117f 100644 --- a/pages/activity/duiduipeng/index.vue +++ b/pages/activity/duiduipeng/index.vue @@ -5,7 +5,7 @@ {{ detail.name || detail.title || '-' }} - 参与价:¥{{ detail.price_draw }} + 参与价:¥{{ (Number(detail.price_draw || 0) / 100).toFixed(2) }} diff --git a/pages/activity/wuxianshang.vue b/pages/activity/wuxianshang.vue deleted file mode 100644 index a65a6c6..0000000 --- a/pages/activity/wuxianshang.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/activity/wuxianshang/index.vue b/pages/activity/wuxianshang/index.vue index 954b074..a81f871 100644 --- a/pages/activity/wuxianshang/index.vue +++ b/pages/activity/wuxianshang/index.vue @@ -5,11 +5,11 @@ {{ detail.name || detail.title || '-' }} - 单次抽选:¥{{ detail.price_draw }} + 单次抽选:¥{{ (Number(detail.price_draw || 0) / 100).toFixed(2) }} - - + + @@ -27,6 +27,13 @@ + @@ -35,7 +42,8 @@ import { ref, computed, getCurrentInstance } from 'vue' import ElCard from '../../../components/ElCard.vue' import FlipGrid from '../../../components/FlipGrid.vue' import { onLoad } from '@dcloudio/uni-app' -import { getActivityDetail, getActivityIssues, getActivityIssueRewards, drawActivityIssue } from '../../../api/appUser' +import PaymentPopup from '../../../components/PaymentPopup.vue' +import { getActivityDetail, getActivityIssues, getActivityIssueRewards, joinLottery, createWechatOrder, getLotteryResult, getItemCards, getUserCoupons } from '../../../api/appUser' const detail = ref({}) const statusText = ref('') @@ -56,6 +64,14 @@ const currentIssueTitle = computed(() => { const points = ref(0) const flipRef = ref(null) const showFlip = ref(false) +const paymentVisible = ref(false) +const paymentAmount = ref('0.00') +const coupons = ref([]) +const propCards = ref([]) +const pendingCount = ref(1) +const selectedCoupon = ref(null) +const selectedCard = ref(null) +const pricePerDrawYuan = computed(() => ((Number(detail.value.price_draw || 0) / 100) || 0)) function statusToText(s) { if (s === 1) return '进行中' @@ -220,27 +236,134 @@ function onPreviewBanner() { if (url) uni.previewImage({ urls: [url], current: url }) } +function openPayment(count) { + const times = Math.max(1, Number(count || 1)) + pendingCount.value = times + paymentAmount.value = (pricePerDrawYuan.value * times).toFixed(2) + const token = uni.getStorageSync('token') + const phoneBound = !!uni.getStorageSync('phone_bound') + if (!token || !phoneBound) { + uni.showModal({ + title: '提示', + content: '请先登录并绑定手机号', + confirmText: '去登录', + success: (res) => { if (res.confirm) uni.navigateTo({ url: '/pages/login/index' }) } + }) + return + } + paymentVisible.value = true + fetchPropCards() + fetchCoupons() +} -function onMachineDraw(count) { +async function onPaymentConfirm(data) { + selectedCoupon.value = data && data.coupon ? data.coupon : null + selectedCard.value = data && data.card ? data.card : null + paymentVisible.value = false + await onMachineDraw(pendingCount.value) +} + +async function fetchPropCards() { + const user_id = uni.getStorageSync('user_id') + if (!user_id) return + try { + const res = await getItemCards(user_id) + let list = [] + if (Array.isArray(res)) list = res + else if (res && Array.isArray(res.list)) list = res.list + else if (res && Array.isArray(res.data)) list = res.data + propCards.value = list.map((i, idx) => ({ + id: i.id ?? i.card_id ?? String(idx), + name: i.name ?? i.title ?? '道具卡' + })) + } catch (e) { + propCards.value = [] + } +} + +async function fetchCoupons() { + const user_id = uni.getStorageSync('user_id') + if (!user_id) return + try { + const res = await getUserCoupons(user_id, 0, 1, 100) + let list = [] + if (Array.isArray(res)) list = res + else if (res && Array.isArray(res.list)) list = res.list + else if (res && Array.isArray(res.data)) list = res.data + coupons.value = list.map((i, idx) => { + const amountCents = (i.remaining !== undefined && i.remaining !== null) ? Number(i.remaining) : Number(i.amount ?? i.value ?? 0) + const amt = isNaN(amountCents) ? 0 : (amountCents / 100) + return { + id: i.id ?? i.coupon_id ?? String(idx), + name: i.name ?? i.title ?? '优惠券', + amount: Number(amt).toFixed(2) + } + }) + } catch (e) { + coupons.value = [] + } +} + +async function onMachineDraw(count) { showFlip.value = true try { if (flipRef.value && flipRef.value.reset) flipRef.value.reset() } catch (_) {} const aid = activityId.value || '' const iid = currentIssueId.value || '' if (!aid || !iid) { uni.showToast({ title: '期数未选择', icon: 'none' }); return } + const token = uni.getStorageSync('token') + const phoneBound = !!uni.getStorageSync('phone_bound') + if (!token || !phoneBound) { + uni.showModal({ + title: '提示', + content: '请先登录并绑定手机号', + confirmText: '去登录', + success: (res) => { if (res.confirm) uni.navigateTo({ url: '/pages/login/index' }) } + }) + return + } + const openid = uni.getStorageSync('openid') + if (!openid) { uni.showToast({ title: '缺少OpenID,请重新登录', icon: 'none' }); return } drawLoading.value = true - const times = Math.max(1, Number(count || 1)) - const calls = Array(times).fill(0).map(() => drawActivityIssue(aid, iid)) - Promise.allSettled(calls).then(list => { - drawLoading.value = false - const items = list.map(r => { - const obj = r.status === 'fulfilled' ? r.value : {} - const data = obj && (obj.data || obj.result || obj.reward || obj.item || obj) - const title = String((data && (data.title || data.name || data.product_name)) || '未知奖励') - const image = String((data && (data.image || data.img || data.pic || data.product_image)) || '') + try { + const times = Math.max(1, Number(count || 1)) + const joinRes = await joinLottery({ + activity_id: Number(aid), + issue_id: Number(iid), + channel: 'miniapp', + count: times, + coupon_id: selectedCoupon.value && selectedCoupon.value.id ? Number(selectedCoupon.value.id) : 0, + item_card_id: selectedCard.value && selectedCard.value.id ? Number(selectedCard.value.id) : 0 + }) + const orderNo = joinRes && (joinRes.order_no || joinRes.data?.order_no || joinRes.result?.order_no) + if (!orderNo) throw new Error('未获取到订单号') + const payRes = await createWechatOrder({ openid, order_no: orderNo }) + await new Promise((resolve, reject) => { + uni.requestPayment({ + provider: 'wxpay', + timeStamp: payRes.timeStamp || payRes.timestamp, + nonceStr: payRes.nonceStr || payRes.noncestr, + package: payRes.package, + signType: payRes.signType || 'MD5', + paySign: payRes.paySign, + success: resolve, + fail: reject + }) + }) + const resultRes = await getLotteryResult(orderNo) + const raw = resultRes && (resultRes.list || resultRes.items || resultRes.data || resultRes.result || resultRes) + const arr = Array.isArray(raw) ? raw : (Array.isArray(resultRes?.data) ? resultRes.data : [raw]) + const items = arr.filter(Boolean).map(d => { + const title = String((d && (d.title || d.name || d.product_name)) || '奖励') + const image = String((d && (d.image || d.img || d.pic || d.product_image)) || '') return { title, image } }) if (flipRef.value && flipRef.value.revealResults) flipRef.value.revealResults(items) - }).catch(() => { drawLoading.value = false; if (flipRef.value && flipRef.value.revealResults) flipRef.value.revealResults([{ title: '抽选失败', image: '' }]) }) + } catch (e) { + if (flipRef.value && flipRef.value.revealResults) flipRef.value.revealResults([{ title: e.message || '抽选失败', image: '' }]) + uni.showToast({ title: e.message || '操作失败', icon: 'none' }) + } finally { + drawLoading.value = false + } } function onMachineTry() { diff --git a/pages/activity/yifanshang.vue b/pages/activity/yifanshang.vue deleted file mode 100644 index 72c6d59..0000000 --- a/pages/activity/yifanshang.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/activity/yifanshang/index.vue b/pages/activity/yifanshang/index.vue index 8da00cd..0f29be7 100644 --- a/pages/activity/yifanshang/index.vue +++ b/pages/activity/yifanshang/index.vue @@ -5,13 +5,9 @@ {{ detail.name || detail.title || '-' }} - 抽选价:¥{{ detail.price_draw }} - - - - - + 抽选价:¥{{ (Number(detail.price_draw || 0) / 100).toFixed(2) }} + @@ -19,6 +15,17 @@ + + + + + + @@ -35,7 +42,8 @@ import { ref, computed, getCurrentInstance } from 'vue' import ElCard from '../../../components/ElCard.vue' import { onLoad } from '@dcloudio/uni-app' import FlipGrid from '../../../components/FlipGrid.vue' -import { getActivityDetail, getActivityIssues, getActivityIssueRewards, drawActivityIssue, getActivityWinRecords } from '../../../api/appUser' +import YifanSelector from '@/components/YifanSelector.vue' +import { getActivityDetail, getActivityIssues, getActivityIssueRewards, getActivityWinRecords } from '../../../api/appUser' const detail = ref({}) const issues = ref([]) @@ -242,34 +250,38 @@ function onPreviewBanner() { } -function onMachineDraw(count) { +function onPaymentSuccess(payload) { + console.log('Payment Success:', payload) + + const result = payload.result + let wonItems = [] + + // 尝试解析返回结果中的奖励列表 + if (Array.isArray(result)) { + wonItems = result + } else if (result && Array.isArray(result.list)) { + wonItems = result.list + } else if (result && Array.isArray(result.data)) { + wonItems = result.data + } else if (result && Array.isArray(result.rewards)) { + wonItems = result.rewards + } else { + // 兜底:如果是单对象或无法识别,尝试作为单个物品处理 + wonItems = result ? [result] : [] + } + + const items = wonItems.map(data => { + const title = String((data && (data.title || data.name || data.product_name || data.reward_name)) || '未知奖励') + const image = String((data && (data.image || data.img || data.pic || data.product_image || data.reward_image)) || '') + return { title, image } + }) + showFlip.value = true try { if (flipRef.value && flipRef.value.reset) flipRef.value.reset() } catch (_) {} - const aid = activityId.value || '' - const iid = currentIssueId.value || '' - if (!aid || !iid) { uni.showToast({ title: '期数未选择', icon: 'none' }); return } - drawLoading.value = true - const times = Math.max(1, Number(count || 1)) - const calls = Array(times).fill(0).map(() => drawActivityIssue(aid, iid)) - Promise.allSettled(calls).then(list => { - drawLoading.value = false - const items = list.map(r => { - const obj = r.status === 'fulfilled' ? r.value : {} - const data = obj && (obj.data || obj.result || obj.reward || obj.item || obj) - const title = String((data && (data.title || data.name || data.product_name)) || '未知奖励') - const image = String((data && (data.image || data.img || data.pic || data.product_image)) || '') - return { title, image } - }) + + setTimeout(() => { if (flipRef.value && flipRef.value.revealResults) flipRef.value.revealResults(items) - }).catch(() => { drawLoading.value = false; if (flipRef.value && flipRef.value.revealResults) flipRef.value.revealResults([{ title: '抽选失败', image: '' }]) }) -} - -function onMachineTry() { - const list = rewardsMap.value[currentIssueId.value] || [] - if (!list.length) { uni.showToast({ title: '暂无奖池', icon: 'none' }); return } - const idx = Math.floor(Math.random() * list.length) - const it = list[idx] - uni.showModal({ title: '试一试', content: it.title || '随机预览', showCancel: false, success: () => { if (it.image) uni.previewImage({ urls: [it.image], current: it.image }) } }) + }, 100) } onLoad((opts) => { @@ -307,7 +319,19 @@ function closeFlip() { showFlip.value = false } .issues-title { font-size: 30rpx; font-weight: 600; margin-bottom: 12rpx } .issues-list { } .issue-switch { display: flex; align-items: center; justify-content: center; gap: 12rpx; margin: 0 24rpx 24rpx } -.switch-btn { width: 72rpx; height: 72rpx; border-radius: 999rpx; background: #fff3df; border: 2rpx solid #f0c58a; color: #8a5a2b } +.switch-btn { + width: 72rpx; + height: 72rpx; + border-radius: 999rpx; + background: #fff3df; + border: 2rpx solid #f0c58a; + color: #8a5a2b; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + line-height: 1; +} .issue-title { font-size: 28rpx; color: #6b4b1f; background: #ffdfaa; border-radius: 12rpx; padding: 8rpx 16rpx } .reward { display: flex; align-items: center; margin-bottom: 8rpx } .reward-img { width: 80rpx; height: 80rpx; border-radius: 8rpx; margin-right: 12rpx; background: #f5f5f5 } diff --git a/pages/cabinet/index.vue b/pages/cabinet/index.vue index cfc3ba7..f990f13 100644 --- a/pages/cabinet/index.vue +++ b/pages/cabinet/index.vue @@ -1,13 +1,123 @@ \ No newline at end of file +.item-status { + font-size: 24rpx; + color: #007AFF; + margin-top: 4rpx; +} +.item-meta { font-size: 22rpx; color: #666; margin-top: 4rpx } + +.wrap { padding: 30rpx; } + +.tabs { + display: flex; + background: #f5f5f5; + border-radius: 16rpx; + padding: 8rpx; + margin-bottom: 20rpx; +} + +.action-bar { + display: flex; + align-items: center; + margin-bottom: 20rpx; + padding: 0 10rpx; +} + +.select-all { + display: flex; + align-items: center; + font-size: 28rpx; + color: #333; +} + +.select-all .checkbox { + margin-right: 12rpx; +} + +.tab-item { + flex: 1; + text-align: center; + font-size: 28rpx; + color: #666; + padding: 20rpx 0; + border-radius: 12rpx; + transition: all 0.3s ease; + display: flex; + justify-content: center; + align-items: center; + gap: 8rpx; +} + +.tab-item.active { + background: #fff; + color: #007AFF; + font-weight: bold; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); +} + +.tab-text { + font-size: 28rpx; +} + +.tab-count { + font-size: 24rpx; + opacity: 0.8; +} + +.header { font-size: 32rpx; font-weight: bold; margin-bottom: 30rpx; } +.status-text { text-align: center; color: #999; margin-top: 100rpx; } + +.inventory-grid { + display: flex; + flex-direction: column; + gap: 20rpx; +} + +.inventory-item { + background: #fff; + border-radius: 12rpx; + padding: 24rpx; + display: flex; + flex-direction: row; + align-items: center; + box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05); +} + +.item-image { + width: 120rpx; + height: 120rpx; + margin-right: 24rpx; + margin-bottom: 0; + border-radius: 8rpx; + background-color: #f5f5f5; + flex-shrink: 0; +} + +.item-info { + flex: 1; + text-align: left; + display: flex; + flex-direction: column; + justify-content: center; +} + +.item-name { + font-size: 26rpx; + color: #333; + display: block; + margin-bottom: 4rpx; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.item-count { + font-size: 24rpx; + color: #999; + margin-bottom: 4rpx; +} + +.item-price { + font-size: 24rpx; + color: #ff4d4f; +} + +.checkbox-area { + padding: 10rpx 20rpx 10rpx 0; + display: flex; + align-items: center; +} + +.checkbox { + width: 40rpx; + height: 40rpx; + border: 2rpx solid #ccc; + border-radius: 50%; + position: relative; +} + +.checkbox.checked { + background-color: #007AFF; + border-color: #007AFF; +} + +.checkbox.checked::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -60%) rotate(45deg); + width: 10rpx; + height: 20rpx; + border-right: 4rpx solid #fff; + border-bottom: 4rpx solid #fff; +} + +.item-actions { + margin-top: 10rpx; + display: flex; + align-items: center; +} + +.stepper { + display: flex; + align-items: center; + border: 1px solid #ddd; + border-radius: 8rpx; + height: 48rpx; +} + +.step-btn { + width: 48rpx; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #f8f8f8; + font-size: 32rpx; + color: #666; +} + +.step-btn.minus { border-right: 1px solid #ddd; } +.step-btn.plus { border-left: 1px solid #ddd; } + +.step-num { + width: 60rpx; + text-align: center; + font-size: 26rpx; + color: #333; +} + +.bottom-bar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 100rpx; + background-color: #fff; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 30rpx; + box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.05); + z-index: 100; + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); +} + +.selected-info { + font-size: 28rpx; + color: #333; + font-weight: bold; +} + +.btn-group { + display: flex; + gap: 20rpx; +} + +.action-btn { + margin: 0; + height: 64rpx; + line-height: 64rpx; + font-size: 26rpx; + border-radius: 32rpx; + padding: 0 40rpx; +} + +.btn-ship { + background-color: #f0ad4e; + color: #fff; +} + +.btn-redeem { + background-color: #dd524d; + color: #fff; +} + +.bottom-spacer { + height: 120rpx; + height: calc(120rpx + constant(safe-area-inset-bottom)); + height: calc(120rpx + env(safe-area-inset-bottom)); +} + diff --git a/pages/index/index.vue b/pages/index/index.vue index bca5b27..bd43b71 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -173,7 +173,7 @@ export default { const base = i.subTitle ?? i.sub_title ?? i.subtitle ?? i.desc ?? i.description ?? '' if (base) return base const cat = i.category_name ?? i.categoryName ?? '' - const price = (i.price_draw !== undefined && i.price_draw !== null) ? `¥${i.price_draw}` : '' + const price = (i.price_draw !== undefined && i.price_draw !== null) ? `¥${(Number(i.price_draw || 0) / 100).toFixed(2)}` : '' const parts = [cat, price].filter(Boolean) return parts.join(' · ') }, diff --git a/pages/login/index.vue b/pages/login/index.vue index e720bc7..d71e622 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -1,9 +1,50 @@ \ No newline at end of file + +/* 积分弹窗样式 */ +.popup-mask { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.6); + z-index: 999; + display: flex; + align-items: flex-end; +} + +.popup-content { + width: 100%; + height: 70vh; + background-color: #fff; + border-radius: 24rpx 24rpx 0 0; + display: flex; + flex-direction: column; +} + +.popup-header { + padding: 30rpx; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1rpx solid #eee; +} + +.popup-title { + font-size: 32rpx; + font-weight: bold; +} + +.close-btn { + font-size: 40rpx; + color: #999; + padding: 0 10rpx; +} + +.points-list { + flex: 1; + overflow-y: auto; + padding: 0 30rpx; + box-sizing: border-box; /* 确保 padding 不增加宽度 */ +} + +.point-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24rpx 0; + border-bottom: 1rpx solid #f5f5f5; + width: 100%; /* 确保子项占满 */ +} + +.point-left { + display: flex; + flex-direction: column; + flex: 1; /* 占据剩余空间 */ + min-width: 0; /* 关键:允许 flex 子项缩小,防止内容撑开 */ + margin-right: 20rpx; +} + +.point-desc { + font-size: 28rpx; + color: #333; + margin-bottom: 8rpx; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.point-time { + font-size: 24rpx; + color: #999; +} + +.point-right { + flex-shrink: 0; /* 防止被压缩 */ + margin-left: auto; /* 靠右对齐 */ + text-align: right; + max-width: 40%; /* 限制最大宽度 */ +} + +.point-amount { + font-size: 32rpx; + font-weight: bold; + color: #333; + display: block; +} + +.point-amount.positive { + color: #ff4d4f; +} + +.point-amount.negative { + color: #52c41a; +} + +.status-text { + text-align: center; + color: #999; + margin-top: 60rpx; + font-size: 28rpx; +} + +.loading-more, .no-more { + text-align: center; + color: #999; + padding: 20rpx 0; + font-size: 24rpx; +} + +/* 优惠券弹窗样式 */ +.popup-tabs { + display: flex; + border-bottom: 1rpx solid #eee; +} +.popup-tab { + flex: 1; + text-align: center; + padding: 24rpx 0; + font-size: 28rpx; + color: #666; + position: relative; +} +.popup-tab.active { + color: #007AFF; + font-weight: bold; +} +.popup-tab.active::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 40rpx; + height: 4rpx; + background-color: #007AFF; + border-radius: 2rpx; +} +.redeem-container { + padding: 40rpx; + display: flex; + flex-direction: column; + align-items: center; +} +.redeem-input { + width: 100%; + height: 80rpx; + border: 1rpx solid #ddd; + border-radius: 8rpx; + padding: 0 20rpx; + margin-bottom: 40rpx; + font-size: 28rpx; + box-sizing: border-box; +} +.redeem-btn { + width: 100%; + height: 80rpx; + line-height: 80rpx; + background-color: #007AFF; + color: #fff; + font-size: 32rpx; + border-radius: 40rpx; +} +.coupon-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24rpx; + margin: 20rpx 0; + background: #f9f9f9; + border-radius: 12rpx; + border: 1rpx solid #eee; +} +.coupon-left { + display: flex; + flex-direction: column; + flex: 1; +} +.coupon-name { + font-size: 30rpx; + font-weight: bold; + color: #333; +} +.coupon-desc { + font-size: 24rpx; + color: #666; + margin-top: 8rpx; +} +.coupon-time { + font-size: 22rpx; + color: #999; + margin-top: 8rpx; +} +.coupon-right { + margin-left: 20rpx; + display: flex; + flex-direction: column; + align-items: flex-end; +} +.coupon-amount-wrapper { + color: #ff4d4f; + margin-bottom: 8rpx; + display: flex; + align-items: baseline; +} +.symbol { + font-size: 24rpx; + font-weight: bold; +} +.amount-value { + font-size: 40rpx; + font-weight: bold; + line-height: 1; +} +.coupon-status { + font-size: 26rpx; + color: #999; +} + +.task-item { display: flex; justify-content: space-between; align-items: flex-start; padding: 24rpx; margin: 20rpx 0; background: #f9f9f9; border-radius: 12rpx; border: 1rpx solid #eee } +.task-left { flex: 1; display: flex; flex-direction: column } +.task-name { font-size: 30rpx; font-weight: 700; color: #333 } +.task-desc { margin-top: 6rpx; font-size: 24rpx; color: #666 } +.task-time { margin-top: 6rpx; font-size: 22rpx; color: #999 } +.reward-list { margin-top: 10rpx } +.reward-label, .tier-label { font-size: 24rpx; color: #666 } +.reward-tags, .tier-tags { margin-top: 8rpx; display: flex; flex-wrap: wrap; gap: 8rpx } +.reward-item, .tier-item { background: #fff; border: 1rpx solid #eee; border-radius: 999rpx; padding: 8rpx 12rpx; display: flex; align-items: center; gap: 8rpx } +.reward-type { font-size: 24rpx; color: #333 } +.reward-qty { font-size: 22rpx; color: #999 } +.tier-text { font-size: 24rpx; color: #333 } +.task-right { margin-left: 12rpx; display: flex; align-items: center } +.task-status { font-size: 26rpx; color: #007AFF } + diff --git a/pages/orders/index.vue b/pages/orders/index.vue index 3b47f0c..f634d9d 100644 --- a/pages/orders/index.vue +++ b/pages/orders/index.vue @@ -13,7 +13,7 @@ {{ formatAmount(item.total_amount || item.amount || item.price) }} - {{ statusText(item.status || item.pay_status || item.state) }} + {{ statusText(item) }} 加载中... @@ -50,13 +50,18 @@ function formatAmount(a) { if (a === undefined || a === null) return '' const n = Number(a) if (Number.isNaN(n)) return String(a) - return `¥${n.toFixed(2)}` + const yuan = n / 100 + return `¥${yuan.toFixed(2)}` } -function statusText(s) { - const v = String(s || '').toLowerCase() - if (v.includes('pend')) return '待付款' - if (v.includes('paid') || v.includes('complete') || v.includes('done')) return '已完成' +function statusText(item) { + const v = item && (item.is_draw ?? item.drawed ?? item.completed) + const ok = v === true || v === 1 || String(v) === 'true' || String(v) === '1' + if (ok) return '已完成' + const s = item && (item.status || item.pay_status || item.state) + const t = String(s || '').toLowerCase() + if (t.includes('pend')) return '待付款' + if (t.includes('paid') || t.includes('complete') || t.includes('done')) return '已完成' return s || '' } @@ -87,15 +92,20 @@ async function fetchOrders(append) { }) return } - if (append) { + if (!append) { + if (currentTab.value === 'completed') { + await fetchAllOrders() + return + } else { + loading.value = true + page.value = 1 + hasMore.value = true + orders.value = [] + } + } else { if (!hasMore.value || loadingMore.value) return loadingMore.value = true page.value = page.value + 1 - } else { - loading.value = true - page.value = 1 - hasMore.value = true - orders.value = [] } error.value = '' try { @@ -119,6 +129,29 @@ async function fetchOrders(append) { } } +async function fetchAllOrders() { + const user_id = uni.getStorageSync('user_id') + loading.value = true + page.value = 1 + hasMore.value = false + orders.value = [] + try { + const first = await getOrders(user_id, apiStatus(), 1, pageSize.value) + const itemsFirst = Array.isArray(first) ? first : (first && first.items) || (first && first.list) || [] + const total = (first && first.total) || 0 + orders.value = itemsFirst + const totalPages = Math.max(1, Math.ceil(Number(total) / pageSize.value)) + for (let p = 2; p <= totalPages; p++) { + const res = await getOrders(user_id, apiStatus(), p, pageSize.value) + const items = Array.isArray(res) ? res : (res && res.items) || (res && res.list) || [] + orders.value = orders.value.concat(items) + } + } catch (e) { + error.value = e && (e.message || e.errMsg) || '获取订单失败' + } finally { + loading.value = false + } +} onLoad((opts) => { const s = (opts && opts.status) || '' if (s === 'completed' || s === 'pending') currentTab.value = s @@ -146,4 +179,4 @@ onReachBottom(() => { .error { color: #e43; margin-bottom: 12rpx } .loading { text-align: center; color: #666; margin: 20rpx 0 } .end { text-align: center; color: #999; margin: 20rpx 0 } - \ No newline at end of file + diff --git a/pages/shop/index.vue b/pages/shop/index.vue index 2e26794..2b9cea9 100644 --- a/pages/shop/index.vue +++ b/pages/shop/index.vue @@ -1,15 +1,15 @@