20260929
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<view class="coupon-page">
|
||||
<view class="page-hero">
|
||||
<AppNavbar title="优惠券中心" show-back/>
|
||||
<view class="intro-card">
|
||||
<view class="card-title">
|
||||
<view class="title-bar"></view>
|
||||
<text>优惠券中心</text>
|
||||
</view>
|
||||
<text class="intro-text">领券大厅与我的优惠券</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card subsection">
|
||||
<view class="tabs">
|
||||
<view
|
||||
v-for="tab in tabs"
|
||||
:key="tab.value"
|
||||
:class="['tab', activeTab === tab.value ? 'active' : '']"
|
||||
@tap="changeTab(tab.value)"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card block">
|
||||
<view class="section-title">{{ activeTab === 'lobby' ? '领券大厅' : '我的优惠券' }}</view>
|
||||
<view v-if="loading" class="empty">加载中...</view>
|
||||
<view v-else-if="currentCoupons.length === 0" class="empty">暂无优惠券</view>
|
||||
<view v-else class="coupon-list">
|
||||
<view class="coupon-card" v-for="coupon in currentCoupons" :key="coupon.id">
|
||||
<view class="coupon-main">
|
||||
<!-- <view class="coupon-amount">¥{{ coupon.amount }}</view>-->
|
||||
<view class="coupon-info">
|
||||
<view class="coupon-title">{{ coupon.title }}</view>
|
||||
<!-- <view class="coupon-meta">{{ coupon.desc }}</view>-->
|
||||
<view class="coupon-meta">
|
||||
有效期:{{ coupon.expireType === 1 ? coupon.expireEndDate : `领取后${coupon.expireDay}天过期` }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="activeTab === 'lobby'" class="coupon-action">
|
||||
<view class="primary-btn" @tap="receiveCoupon(coupon)">领取</view>
|
||||
</view>
|
||||
<view v-else class="coupon-status">{{ coupon.statusText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {couponListReq, userCouponAddReq, userCouponListReq} from "@/api/coupon";
|
||||
import AppNavbar from "@/components/AppNavbar.vue";
|
||||
|
||||
export default {
|
||||
components: {AppNavbar},
|
||||
data() {
|
||||
return {
|
||||
tabs: [
|
||||
{label: '领券大厅', value: 'lobby'},
|
||||
{label: '我的优惠券', value: 'mine'}
|
||||
],
|
||||
activeTab: 'lobby',
|
||||
lobbyCoupons: [],
|
||||
myCoupons: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentCoupons() {
|
||||
return this.activeTab === 'lobby' ? this.lobbyCoupons : this.myCoupons
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.fetchCoupons()
|
||||
},
|
||||
methods: {
|
||||
changeTab(value) {
|
||||
this.activeTab = value
|
||||
this.fetchCoupons()
|
||||
},
|
||||
async fetchCoupons() {
|
||||
this.loading = true
|
||||
try {
|
||||
if (this.activeTab === 'lobby') {
|
||||
const {data} = await couponListReq()
|
||||
const list = Array.isArray(data) ? data : (data && data.list ? data.list : [])
|
||||
this.lobbyCoupons = list.map(this.normalizeCoupon)
|
||||
} else {
|
||||
const {data} = await userCouponListReq()
|
||||
const list = Array.isArray(data) ? data : (data && data.list ? data.list : [])
|
||||
this.myCoupons = list.map(this.normalizeUserCoupon)
|
||||
}
|
||||
} catch (err) {
|
||||
uni.showToast({
|
||||
title: '加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
normalizeCoupon(item) {
|
||||
const amount = Number(item.amount || item.faceValue || item.money || 0)
|
||||
return {
|
||||
id: item.id || item.couponId || item.coupon_id,
|
||||
amount: amount.toFixed(2),
|
||||
title: item.title || item.name || '优惠券',
|
||||
desc: item.desc || item.description || item.useRule || '无门槛使用',
|
||||
expire: item.expire || item.expireTime || item.endTime || '-',
|
||||
expireType: item.expireType,
|
||||
expireEndDate: item.expireEndDate,
|
||||
expireDay: item.expireDay,
|
||||
}
|
||||
},
|
||||
normalizeUserCoupon(item) {
|
||||
const amount = Number(item.amount || item.faceValue || item.money || 0)
|
||||
const statusValue = Number(item.used || item.status)
|
||||
let statusText = '未使用'
|
||||
if (statusValue === 1) statusText = '已使用'
|
||||
if (statusValue === 2) statusText = '已过期'
|
||||
return {
|
||||
id: item.id || item.userCouponId || item.couponId,
|
||||
amount: amount.toFixed(2),
|
||||
title: item.coupon.title || item.name || '优惠券',
|
||||
desc: item.desc || item.description || item.useRule || '无门槛使用',
|
||||
expire: item.expire || item.expireTime || item.endTime || '-',
|
||||
statusText,
|
||||
expireType: item.coupon.expireType,
|
||||
expireEndDate: item.coupon.expireEndDate,
|
||||
expireDay: item.coupon.expireDay,
|
||||
}
|
||||
},
|
||||
async receiveCoupon(coupon) {
|
||||
if (!coupon.id) {
|
||||
uni.showToast({
|
||||
title: '缺少优惠券ID',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
const res = await userCouponAddReq({
|
||||
couponId: coupon.id
|
||||
}).catch(e => {
|
||||
uni.showToast({
|
||||
title: e.message,
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: '领取成功',
|
||||
icon: 'success'
|
||||
})
|
||||
this.fetchCoupons()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.coupon-page {
|
||||
min-height: 100vh;
|
||||
//padding: 0 20rpx 40rpx;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.page-hero {
|
||||
//padding: 30rpx 6rpx 18rpx;
|
||||
background: url('https://yaodongxiao.oss-cn-guangzhou.aliyuncs.com/20260126/462bfa04cf0eff8698884c38b9d17519.png') no-repeat top center / 100% auto;
|
||||
}
|
||||
|
||||
.page-navbar {
|
||||
padding: 0 6rpx;
|
||||
}
|
||||
|
||||
.intro-card {
|
||||
margin: 18rpx 20rpx 0;
|
||||
padding: 20rpx 18rpx;
|
||||
border-radius: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
width: 6rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #2fc6a7;
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
margin-top: 12rpx;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.subsection {
|
||||
margin: 18rpx 20rpx 0;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 10rpx 18rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #f5f8ff;
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
border: 1rpx solid #e1e8f5;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
color: #ffffff;
|
||||
background: var(--brand-primary);
|
||||
border-color: var(--brand-primary);
|
||||
}
|
||||
|
||||
.block {
|
||||
margin: 18rpx 20rpx 0;
|
||||
}
|
||||
|
||||
.coupon-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14rpx;
|
||||
}
|
||||
|
||||
.coupon-card {
|
||||
border: 1rpx solid #e7eef8;
|
||||
border-radius: 16rpx;
|
||||
padding: 16rpx;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.coupon-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
}
|
||||
|
||||
.coupon-amount {
|
||||
font-size: 34rpx;
|
||||
font-weight: 800;
|
||||
color: #ff3b30;
|
||||
min-width: 110rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.coupon-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.coupon-title {
|
||||
font-weight: 700;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.coupon-meta {
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.coupon-action {
|
||||
margin-top: 12rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.coupon-status {
|
||||
margin-top: 12rpx;
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.empty {
|
||||
color: var(--text-sub);
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user