You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

552 lines
12 KiB

<template>
<view class="coupon-list-container">
<!-- 状态筛选 -->
<view class="filter-tabs">
<view
class="tab-item"
:class="[{ active: activeTab === 'all' }]"
@click="switchTab('all')"
>
全部
</view>
<view
class="tab-item"
:class="[{ active: activeTab === 'unused' }]"
@click="switchTab('unused')"
>
未使用
</view>
<view
class="tab-item"
:class="[{ active: activeTab === 'used' }]"
@click="switchTab('used')"
>
已使用
</view>
<view
class="tab-item"
:class="[{ active: activeTab === 'expired' }]"
@click="switchTab('expired')"
>
已过期
</view>
</view>
<!-- 优惠券列表 -->
<view class="coupon-list">
<view
v-for="(coupon, index) in filteredCoupons"
:key="index"
class="coupon-item"
:class="[
{
used: coupon.status === 1,
expired: coupon.status === 2,
},
]"
>
<!-- 优惠券主体 -->
<view class="coupon-main">
<!-- 左侧金额区域 -->
<view class="coupon-amount">
<view class="amount-value">
<text class="currency">¥</text>
<text class="value">{{ formatAmount(coupon) }}</text>
</view>
<view class="amount-desc" v-if="coupon.minAmount > 0">
满{{ coupon.minAmount }}可用
</view>
<view class="amount-desc" v-else> 无门槛 </view>
</view>
<!-- 右侧信息区域 -->
<view class="coupon-info">
<view class="coupon-type">{{
getCouponTypeName(coupon.type)
}}</view>
<view class="coupon-scope" v-if="coupon.scope === 0">
全场通用
</view>
<view class="coupon-scope" v-else>
<view class="scope-title" @click="toggleProductList(coupon.id)">
指定商品可用
<text
class="expand-icon"
:class="{ expanded: coupon.showProducts }"
>▼</text
>
</view>
<view class="product-list" v-if="coupon.showProducts">
<view
class="product-item"
v-for="product in coupon.products"
:key="product.id"
>
{{ product.name }}
</view>
</view>
</view>
</view>
<!-- 状态标识 -->
<view class="coupon-status">
<view class="status-tag" :class="[getStatusClass(coupon.status)]">
{{ getStatusText(coupon.status) }}
</view>
</view>
</view>
<!-- 有效期和使用按钮 -->
<view class="coupon-bottom">
<view class="coupon-validity">
<text class="validity-label">有效期:</text>
<text class="validity-date"
>{{ coupon.startDate }} - {{ coupon.endDate }}</text
>
</view>
<view class="coupon-action" v-if="coupon.status === 0">
<button class="use-btn" @click="useCoupon(coupon)">立即使用</button>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="filteredCoupons.length === 0">
<view class="empty-icon">📋</view>
<view class="empty-text">暂无优惠券</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
activeTab: "all",
coupons: [
{
id: 1,
type: 1, // 满减券
amount: 20,
minAmount: 100,
status: 0, // 0:未使用 1:已使用 2:已过期
startDate: "2024-01-01",
endDate: "2024-12-31",
scope: 0, // 0:不限商品 1:指定商品
showProducts: false,
},
{
id: 2,
type: 2, // 折扣券
discount: 8.5, // 8.5折
minAmount: 50,
status: 1,
startDate: "2024-01-01",
endDate: "2024-06-30",
scope: 1,
showProducts: false,
products: [
{ id: 1, name: "iPhone 15 Pro" },
{ id: 2, name: "MacBook Air M2" },
{ id: 3, name: "AirPods Pro" },
],
},
{
id: 3,
type: 3, // 立减券
amount: 10,
minAmount: 0,
status: 2,
startDate: "2023-12-01",
endDate: "2023-12-31",
scope: 0,
showProducts: false,
},
{
id: 4,
type: 4, // 兑换券
amount: 0,
minAmount: 0,
status: 0,
startDate: "2024-01-01",
endDate: "2024-12-31",
scope: 1,
showProducts: false,
products: [
{ id: 4, name: "星巴克咖啡券" },
{ id: 5, name: "肯德基套餐券" },
],
},
],
};
},
computed: {
filteredCoupons() {
if (this.activeTab === "all") {
return this.coupons;
}
if (this.activeTab === "unused") {
return this.coupons.filter((coupon) => coupon.status === 0);
}
if (this.activeTab === "used") {
return this.coupons.filter((coupon) => coupon.status === 1);
}
if (this.activeTab === "expired") {
return this.coupons.filter((coupon) => coupon.status === 2);
}
return [];
},
},
mounted() {
console.log("couponList mounted");
console.log("activeTab:", this.activeTab);
console.log("coupons:", this.coupons);
console.log("filteredCoupons:", this.filteredCoupons);
},
methods: {
switchTab(tab) {
this.activeTab = tab;
},
getCouponTypeName(type) {
const typeMap = {
1: "满减券",
2: "折扣券",
3: "立减券",
4: "兑换券",
};
return typeMap[type] || "未知类型";
},
formatAmount(coupon) {
if (coupon.type === 2) {
// 折扣券显示折扣
return coupon.discount + "折";
} else if (coupon.type === 4) {
// 兑换券
return "兑换";
} else {
// 满减券和立减券显示金额
return coupon.amount;
}
},
getStatusText(status) {
const statusMap = {
0: "未使用",
1: "已使用",
2: "已过期",
};
return statusMap[status] || "未知状态";
},
getStatusClass(status) {
const classMap = {
0: "unused",
1: "used",
2: "expired",
};
return classMap[status] || "";
},
useCoupon(coupon) {
// 跳转到商品页面或购物车
uni.showToast({
title: "跳转到商品页面",
icon: "none",
});
},
toggleProductList(couponId) {
console.log("toggleProductList called with couponId:", couponId);
const couponIndex = this.coupons.findIndex((c) => c.id === couponId);
console.log("found coupon index:", couponIndex);
if (couponIndex !== -1) {
const newShowProducts = !this.coupons[couponIndex].showProducts;
console.log(
"toggling showProducts from",
this.coupons[couponIndex].showProducts,
"to",
newShowProducts
);
// 使用 Vue.set 确保响应式更新
this.$set(this.coupons[couponIndex], "showProducts", newShowProducts);
console.log(
"after toggle, showProducts is:",
this.coupons[couponIndex].showProducts
);
}
},
},
onLoad() {
// 页面加载时获取优惠券数据
// this.loadCoupons();
},
};
</script>
<style lang="scss" scoped>
.coupon-list-container {
min-height: 100vh;
background-color: #f5f5f5;
}
.header {
background: #fff;
padding: 20rpx 30rpx;
border-bottom: 1rpx solid #eee;
.header-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
text-align: center;
}
}
.filter-tabs {
display: flex;
background: #fff;
padding: 0 30rpx;
border-bottom: 1rpx solid #eee;
.tab-item {
flex: 1;
padding: 30rpx 0;
text-align: center;
font-size: 28rpx;
color: #666;
position: relative;
&.active {
color: #77f3f9;
font-weight: 600;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background: #77f3f9;
border-radius: 2rpx;
}
}
}
}
.coupon-list {
padding: 20rpx 30rpx;
}
.coupon-item {
background: #fff;
border-radius: 16rpx;
margin-bottom: 20rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
position: relative;
&.used,
&.expired {
opacity: 0.6;
&::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.1);
pointer-events: none;
}
}
}
.coupon-main {
display: flex;
padding: 30rpx;
position: relative;
&::after {
content: "";
position: absolute;
right: 200rpx;
top: 20rpx;
bottom: 20rpx;
width: 2rpx;
background: linear-gradient(
to bottom,
transparent 0%,
#ddd 20%,
#ddd 80%,
transparent 100%
);
}
}
.coupon-amount {
width: 200rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.amount-value {
display: flex;
align-items: baseline;
margin-bottom: 10rpx;
.currency {
font-size: 24rpx;
color: #ff4d4f;
font-weight: 600;
}
.value {
font-size: 48rpx;
color: #ff4d4f;
font-weight: 700;
margin-left: 4rpx;
}
}
.amount-desc {
font-size: 22rpx;
color: #999;
}
}
.coupon-info {
flex: 1;
padding-left: 30rpx;
display: flex;
flex-direction: column;
justify-content: center;
.coupon-type {
font-size: 32rpx;
color: #333;
font-weight: 600;
margin-bottom: 12rpx;
}
.coupon-scope {
font-size: 24rpx;
color: #666;
margin-bottom: 8rpx;
}
.coupon-scope {
.scope-title {
display: flex;
align-items: center;
cursor: pointer;
.expand-icon {
margin-left: 8rpx;
font-size: 20rpx;
transition: transform 0.3s ease;
&.expanded {
transform: rotate(180deg);
}
}
}
.product-list {
margin-top: 8rpx;
padding: 8rpx 12rpx;
background: #f8f8f8;
border-radius: 8rpx;
.product-item {
font-size: 20rpx;
color: #666;
line-height: 1.5;
margin-bottom: 4rpx;
&:last-child {
margin-bottom: 0;
}
}
}
}
}
.coupon-status {
position: absolute;
top: 20rpx;
right: 20rpx;
.status-tag {
padding: 8rpx 16rpx;
border-radius: 20rpx;
font-size: 20rpx;
color: #fff;
&.unused {
background: #52c41a;
}
&.used {
background: #999;
}
&.expired {
background: #ff4d4f;
}
}
}
.coupon-bottom {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
border-top: 1rpx solid #f0f0f0;
.coupon-validity {
flex: 1;
font-size: 22rpx;
color: #999;
.validity-label {
margin-right: 8rpx;
}
.validity-date {
line-height: 1.4;
}
}
.coupon-action {
.use-btn {
width: 160rpx;
height: 60rpx;
background: linear-gradient(135deg, #fffdb7 0%, #97fffa 100%);
color: #000;
border: none;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 600;
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
.empty-icon {
font-size: 120rpx;
margin-bottom: 30rpx;
opacity: 0.3;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
}
</style>