388 lines
9.2 KiB
Vue
388 lines
9.2 KiB
Vue
<template>
|
|
<view class="my-coupons-page">
|
|
<view class="header-fixed-wrapper" :style="{ height: headerHeight + 'px' }">
|
|
<NavHeader title="我的优惠卷" />
|
|
</view>
|
|
<view class="main-wrap" :style="{ paddingTop: headerHeight + 'px' }">
|
|
<!-- Tab 切换 -->
|
|
<view class="tab-bar">
|
|
<view
|
|
class="tab-item"
|
|
:class="{ active: currentTab === '0' }"
|
|
@click="switchTab('0')"
|
|
>
|
|
<text class="tab-text">待使用</text>
|
|
</view>
|
|
<view
|
|
class="tab-item"
|
|
:class="{ active: currentTab === '1' }"
|
|
@click="switchTab('1')"
|
|
>
|
|
<text class="tab-text">已使用</text>
|
|
</view>
|
|
<view
|
|
class="tab-item"
|
|
:class="{ active: currentTab === '2' }"
|
|
@click="switchTab('2')"
|
|
>
|
|
<text class="tab-text">已过期</text>
|
|
</view>
|
|
<view
|
|
class="tab-item"
|
|
:class="{ active: currentTab === 'all' }"
|
|
@click="switchTab('all')"
|
|
>
|
|
<text class="tab-text">全部</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 列表内容 -->
|
|
<scroll-view
|
|
class="coupon-list"
|
|
scroll-y="true"
|
|
:refresher-enabled="true"
|
|
:refresher-triggered="refreshing"
|
|
@refresherrefresh="handleRefresh"
|
|
@scrolltolower="handleLoadMore"
|
|
:lower-threshold="100"
|
|
>
|
|
<!-- 空数据提示 -->
|
|
<view class="empty-state" v-if="!loading && coupons.length === 0">
|
|
<image
|
|
class="empty-icon"
|
|
src="/static/home/entry_icon.png"
|
|
mode="aspectFit"
|
|
></image>
|
|
<text class="empty-text">暂无优惠卷</text>
|
|
</view>
|
|
|
|
<view
|
|
class="coupon-item"
|
|
v-for="(item, index) in coupons"
|
|
:key="index"
|
|
:class="{ disabled: isCouponDisabled(item) }"
|
|
>
|
|
<view class="coupon-left">
|
|
<!-- 折扣类 -->
|
|
<view class="coupon-price" v-if="item.type === 2">
|
|
<text class="amount">{{ (item.discountPercent / 10).toFixed(1).replace(/\.0$/, '') }}</text>
|
|
<text class="symbol" style="font-size: 24rpx; margin-left: 4rpx;">折</text>
|
|
</view>
|
|
<!-- 金额类 -->
|
|
<view class="coupon-price" v-else>
|
|
<text class="symbol">¥</text>
|
|
<text class="amount">{{ formatAmount(item.discountAmount || item.discountPrice || item.price || 0) }}</text>
|
|
</view>
|
|
|
|
<view class="coupon-condition" v-if="item.usePrice">
|
|
满{{ formatAmount(item.usePrice) }}可用
|
|
</view>
|
|
<view class="coupon-condition" v-else>
|
|
无门槛
|
|
</view>
|
|
</view>
|
|
<view class="coupon-right">
|
|
<view class="coupon-name">{{ item.name }}</view>
|
|
<view class="coupon-time" v-if="item.type === 2 && item.discountLimit > 0" style="margin-bottom: 6rpx;">最多抵扣: ¥{{ formatAmount(item.discountLimit) }}</view>
|
|
<view class="coupon-time" v-if="item.validEndTime">有效期至: {{ formatTimeStr(item.validEndTime) }}</view>
|
|
</view>
|
|
<view class="coupon-status-stamp" v-if="item.status === 1">已使用</view>
|
|
<view class="coupon-status-stamp" v-else-if="item.status === 2">已过期</view>
|
|
<view class="coupon-status-stamp" v-else-if="item.status === 3">已作废</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
|
import { getLuCouponPage } from "@/api/service.js";
|
|
import { formatTime } from "@/utils/date.js";
|
|
|
|
export default {
|
|
components: {
|
|
NavHeader,
|
|
},
|
|
data() {
|
|
return {
|
|
statusBarHeight: 0,
|
|
currentTab: '0', // 默认待使用
|
|
coupons: [],
|
|
pageNo: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
loading: false,
|
|
refreshing: false,
|
|
hasMore: true,
|
|
};
|
|
},
|
|
computed: {
|
|
headerHeight() {
|
|
return this.statusBarHeight + 44;
|
|
},
|
|
},
|
|
onLoad() {
|
|
const systemInfo = uni.getSystemInfoSync();
|
|
this.statusBarHeight = systemInfo.statusBarHeight || 0;
|
|
this.loadData();
|
|
},
|
|
methods: {
|
|
switchTab(tab) {
|
|
if (this.currentTab === tab) return;
|
|
this.currentTab = tab;
|
|
this.refreshData();
|
|
},
|
|
async loadData() {
|
|
if (this.loading || !this.hasMore) return;
|
|
this.loading = true;
|
|
|
|
try {
|
|
const params = {
|
|
pageNo: this.pageNo,
|
|
pageSize: this.pageSize
|
|
};
|
|
|
|
if (this.currentTab !== 'all') {
|
|
params.status = Number(this.currentTab);
|
|
}
|
|
|
|
const res = await getLuCouponPage(params);
|
|
if (res && res.list) {
|
|
if (this.pageNo === 1) {
|
|
this.coupons = res.list;
|
|
} else {
|
|
this.coupons = this.coupons.concat(res.list);
|
|
}
|
|
this.total = res.total || 0;
|
|
this.hasMore = this.coupons.length < this.total;
|
|
this.pageNo++;
|
|
} else {
|
|
this.hasMore = false;
|
|
}
|
|
} catch (error) {
|
|
console.error("加载优惠卷失败:", error);
|
|
uni.showToast({
|
|
title: "加载失败",
|
|
icon: "none"
|
|
});
|
|
} finally {
|
|
this.loading = false;
|
|
this.refreshing = false;
|
|
}
|
|
},
|
|
refreshData() {
|
|
this.pageNo = 1;
|
|
this.hasMore = true;
|
|
this.coupons = [];
|
|
this.loadData();
|
|
},
|
|
handleRefresh() {
|
|
if (this.refreshing) return;
|
|
this.refreshing = true;
|
|
this.pageNo = 1;
|
|
this.hasMore = true;
|
|
this.loadData();
|
|
},
|
|
handleLoadMore() {
|
|
this.loadData();
|
|
},
|
|
isCouponDisabled(item) {
|
|
return item.status === 1 || item.status === 2 || item.status === 3;
|
|
},
|
|
formatTimeStr(timestamp) {
|
|
if (!timestamp) return '';
|
|
return formatTime(timestamp, 'YYYY-MM-DD HH:mm:ss');
|
|
},
|
|
// 将分转换为元,并处理小数显示
|
|
formatAmount(amount) {
|
|
if (!amount) return '0';
|
|
const yuan = amount / 100;
|
|
return Number.isInteger(yuan) ? yuan.toString() : yuan.toFixed(2).replace(/\.?0+$/, '');
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.my-coupons-page {
|
|
min-height: 100vh;
|
|
background-color: #f5f5f5;
|
|
}
|
|
|
|
.header-fixed-wrapper {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
z-index: 100;
|
|
background-color: #fff;
|
|
}
|
|
|
|
.main-wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.tab-bar {
|
|
display: flex;
|
|
background-color: #fff;
|
|
height: 88rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
.tab-item {
|
|
flex: 1;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
position: relative;
|
|
|
|
.tab-text {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
}
|
|
|
|
&.active {
|
|
.tab-text {
|
|
color: #d51c3c;
|
|
font-weight: 500;
|
|
}
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 40rpx;
|
|
height: 6rpx;
|
|
background-color: #d51c3c;
|
|
border-radius: 4rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.coupon-list {
|
|
flex: 1;
|
|
padding: 20rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding-top: 200rpx;
|
|
|
|
.empty-icon {
|
|
width: 200rpx;
|
|
height: 200rpx;
|
|
margin-bottom: 20rpx;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 28rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.coupon-item {
|
|
position: relative;
|
|
display: flex;
|
|
background-color: #fff;
|
|
border-radius: 16rpx;
|
|
margin-bottom: 20rpx;
|
|
padding: 30rpx;
|
|
align-items: center;
|
|
overflow: hidden;
|
|
|
|
&.disabled {
|
|
opacity: 0.6;
|
|
background-color: #fafafa;
|
|
|
|
.coupon-price {
|
|
color: #999 !important;
|
|
}
|
|
|
|
.coupon-name {
|
|
color: #999 !important;
|
|
}
|
|
}
|
|
|
|
.coupon-left {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 160rpx;
|
|
border-right: 2rpx dashed #eee;
|
|
padding-right: 20rpx;
|
|
|
|
.coupon-price {
|
|
color: #d51c3c;
|
|
|
|
.symbol {
|
|
font-size: 24rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.amount {
|
|
font-size: 48rpx;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
.coupon-condition {
|
|
font-size: 20rpx;
|
|
color: #666;
|
|
margin-top: 10rpx;
|
|
}
|
|
}
|
|
|
|
.coupon-right {
|
|
flex: 1;
|
|
padding-left: 20rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
|
|
.coupon-name {
|
|
font-size: 32rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
margin-bottom: 16rpx;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 2;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.coupon-time {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.coupon-status-stamp {
|
|
position: absolute;
|
|
right: -20rpx;
|
|
top: 20rpx;
|
|
width: 120rpx;
|
|
height: 40rpx;
|
|
line-height: 40rpx;
|
|
text-align: center;
|
|
background-color: rgba(153, 153, 153, 0.1);
|
|
color: #999;
|
|
font-size: 20rpx;
|
|
transform: rotate(45deg);
|
|
transform-origin: center;
|
|
border: 1rpx solid #999;
|
|
}
|
|
}
|
|
</style>
|