<template>
|
<view class="container">
|
<!-- 优惠券卡片 -->
|
<view class="coupon-card" v-if="couponInfo.storeCoupRef">
|
<u-card :border="false" :head-style="{ padding: '30rpx' }" :body-style="{ padding: '0 30rpx 30rpx' }">
|
<!-- 头部:店铺信息 -->
|
<view slot="head" class="card-head">
|
<view class="store-info">
|
<u-icon name="home" size="36" color="#999"></u-icon>
|
<text class="store-name">{{ couponInfo.storeName }}</text>
|
</view>
|
<u-tag v-if="couponInfo.claimStatus === 'NOT_CLAIM'" text="未领取" type="warning" mode="plain" size="mini" />
|
<u-tag v-else-if="couponInfo.claimStatus === 'CLAIM'" text="已领取" type="success" mode="plain" size="mini" />
|
<u-tag v-else text="已过期" type="info" mode="plain" size="mini" />
|
</view>
|
|
<!-- 主体:优惠券信息 -->
|
<view slot="body" class="card-body">
|
<view class="coupon-title">
|
<text class="title">{{ couponInfo.couponName }}</text>
|
<text class="coupon-no">编号:{{ couponInfo.couponNo }}</text>
|
</view>
|
|
<view class="coupon-desc" v-if="couponInfo.couponDesc">
|
<text class="desc">{{ couponInfo.couponDesc }}</text>
|
</view>
|
|
<view class="coupon-rule" v-if="couponInfo.couponRule">
|
<text class="rule-title">使用规则:</text>
|
<text class="rule-content">{{ couponInfo.couponRule }}</text>
|
</view>
|
|
<view class="coupon-time" v-if="couponInfo.startTime && couponInfo.endTime">
|
<u-icon name="clock" size="28" color="#999"></u-icon>
|
<text class="time-text">有效期:{{ formatDate(couponInfo.startTime) }} 至 {{ formatDate(couponInfo.endTime) }}</text>
|
</view>
|
|
<view class="coupon-condition" v-if="couponInfo.consumeThreshold > 0">
|
<u-icon name="coupon" size="28" color="#999"></u-icon>
|
<text class="condition-text">满{{ formatAmount(couponInfo.consumeThreshold) }}元可用</text>
|
</view>
|
</view>
|
|
<!-- 底部:操作按钮 -->
|
<view slot="foot" class="card-foot">
|
<u-button
|
:type="couponInfo.claimStatus === 'NOT_CLAIM' ? 'primary' : 'default'"
|
:disabled="couponInfo.claimStatus !== 'NOT_CLAIM'"
|
:loading="loading"
|
@click="claimCoupon"
|
:ripple="true"
|
:hair-line="false"
|
>
|
{{ couponInfo.claimStatus === 'NOT_CLAIM' ? '立即领取' : couponInfo.claimStatus === 'CLAIM' ? '已领取' : '已过期' }}
|
</u-button>
|
</view>
|
</u-card>
|
</view>
|
|
<!-- 空状态 -->
|
<view class="empty-state" v-else>
|
<u-empty text="优惠券信息不存在" mode="coupon" :icon-size="200"></u-empty>
|
</view>
|
|
<!-- 使用说明 -->
|
<view class="instructions">
|
<view class="instructions-title">
|
<u-icon name="info-circle" size="28" color="#999"></u-icon>
|
<text class="title-text">使用说明</text>
|
</view>
|
<view class="instructions-content">
|
<text class="content-text">1. 优惠券仅限在指定店铺使用\n2. 每个用户限领一张\n3. 优惠券不可兑换现金\n4. 请在有效期内使用</text>
|
</view>
|
</view>
|
|
<!-- 空白占位 -->
|
<view class="placeholder"></view>
|
</view>
|
</template>
|
|
<script>
|
import { getStoreCouponDetail, claimStoreCoupon } from '@/api/store-coupon.js';
|
import { formatPrice } from '@/utils/Foundation.js';
|
|
export default {
|
data() {
|
return {
|
loading: false,
|
storeCoupRef: '', // 店铺优惠券关联ID
|
couponInfo: {
|
id: "",
|
storeCoupRef: "",
|
storeId: "",
|
storeName: "",
|
couponId: "",
|
couponName: "",
|
couponNo: "",
|
couponAmount: 0, // 优惠金额
|
couponDesc: "", // 优惠券描述
|
couponRule: "", // 使用规则
|
startTime: "", // 开始时间
|
endTime: "", // 结束时间
|
consumeThreshold: 0, // 消费门槛
|
claimStatus: "NOT_CLAIM", // 领取状态
|
}
|
}
|
},
|
onShow() {
|
this.getCouponDetail(this.storeCoupRef);
|
},
|
onLoad(options) {
|
// 获取传递的店铺优惠券关联ID
|
if (options.storeCoupRef) {
|
this.storeCoupRef = options.storeCoupRef;
|
this.getCouponDetail(options.storeCoupRef);
|
} else if (options.id) {
|
// 兼容旧参数
|
this.storeCoupRef = options.id;
|
this.getCouponDetail(options.id);
|
}else if(options.q){
|
// 双重解码:微信对URL进行了两次编码
|
const decodedUrl = decodeURIComponent(decodeURIComponent(options.q));
|
console.log('原始URL:', decodedUrl);
|
|
// 解析URL中的查询参数
|
const params = this.parseUrlParams(decodedUrl);
|
this.storeCoupRef = params.id;
|
this.getCouponDetail(this.storeCoupRef);
|
}
|
else {
|
this.$u.toast('参数错误');
|
}
|
},
|
methods: {
|
// 解析URL参数
|
parseUrlParams(url) {
|
const params = {};
|
// 处理可能存在的hash(如果有的话)
|
const cleanUrl = url.split('#')[0];
|
const queryStr = cleanUrl.split('?')[1] || '';
|
|
queryStr.split('&').forEach(pair => {
|
const [key, value] = pair.split('=');
|
if (key) {
|
// 如果值存在,则解码,否则设为空字符串
|
params[key] = value ? decodeURIComponent(value) : '';
|
}
|
});
|
|
return params;
|
},
|
// 格式化金额
|
formatAmount(amount) {
|
if (!amount) return '0';
|
return formatPrice(parseFloat(amount));
|
},
|
|
// 格式化日期
|
formatDate(dateStr) {
|
if (!dateStr) return '';
|
return dateStr.split(' ')[0];
|
},
|
|
// 获取优惠券详情
|
async getCouponDetail(storeCoupRef) {
|
uni.showLoading({
|
title: '加载中...'
|
});
|
|
try {
|
const res = await getStoreCouponDetail(storeCoupRef);
|
console.log(JSON.stringify(res))
|
if (res.data.code === 200) {
|
this.couponInfo = {
|
...this.couponInfo,
|
...res.data.data,
|
couponAmount: res.data.data.couponAmount || 0,
|
consumeThreshold: res.data.data.consumeThreshold || 0
|
};
|
} else {
|
this.$u.toast(res.data.message || '获取优惠券详情失败');
|
}
|
} catch (err) {
|
this.$u.toast('获取优惠券详情失败,请稍后重试');
|
console.error('获取优惠券详情失败:', err);
|
} finally {
|
uni.hideLoading();
|
}
|
},
|
|
// 领取优惠券
|
async claimCoupon() {
|
if (this.couponInfo.claimStatus !== 'NOT_CLAIM') {
|
return;
|
}
|
|
// 确认领取
|
uni.showModal({
|
title: '提示',
|
content: `确定要领取"${this.couponInfo.couponName}"优惠券吗?`,
|
success: (res) => {
|
if (res.confirm) {
|
this.doClaimCoupon();
|
}
|
}
|
});
|
},
|
|
// 执行领取优惠券操作
|
async doClaimCoupon() {
|
this.loading = true;
|
try {
|
// 调用领取优惠券接口
|
const res = await claimStoreCoupon(this.storeCoupRef);
|
if (res.data.code === 200) {
|
this.$u.toast('领取成功');
|
this.couponInfo.claimStatus = 'CLAIM';
|
|
// 延迟返回上一页,让用户看到领取成功的提示
|
setTimeout(() => {
|
uni.navigateBack();
|
}, 1500);
|
} else {
|
this.$u.toast(res.data.message || '领取失败');
|
}
|
} catch (err) {
|
this.$u.toast('领取失败,请稍后重试');
|
console.error('领取优惠券失败:', err);
|
} finally {
|
this.loading = false;
|
}
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.container {
|
background-color: #f5f5f5;
|
min-height: 100vh;
|
}
|
|
.coupon-card {
|
margin: 20rpx;
|
}
|
|
.card-head {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.store-info {
|
display: flex;
|
align-items: center;
|
}
|
|
.store-name {
|
margin-left: 10rpx;
|
font-size: 32rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.card-body {
|
padding-top: 20rpx;
|
}
|
|
.coupon-title {
|
margin-bottom: 30rpx;
|
display: flex;
|
align-items: center;
|
flex-wrap: wrap;
|
}
|
|
.title {
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.coupon-no {
|
font-size: 24rpx;
|
color: #999;
|
margin-left: 20rpx;
|
}
|
|
.coupon-desc {
|
margin-bottom: 30rpx;
|
}
|
|
.desc {
|
font-size: 28rpx;
|
color: #666;
|
}
|
|
.coupon-rule {
|
margin-bottom: 30rpx;
|
}
|
|
.rule-title {
|
font-size: 28rpx;
|
color: #333;
|
font-weight: bold;
|
}
|
|
.rule-content {
|
font-size: 26rpx;
|
color: #666;
|
}
|
|
.coupon-time, .coupon-condition {
|
display: flex;
|
align-items: center;
|
margin-bottom: 20rpx;
|
}
|
|
.time-text, .condition-text {
|
font-size: 24rpx;
|
color: #999;
|
margin-left: 10rpx;
|
}
|
|
.card-foot {
|
padding: 20rpx 0;
|
}
|
|
.instructions {
|
background-color: #ffffff;
|
margin: 20rpx;
|
padding: 30rpx;
|
border-radius: 16rpx;
|
}
|
|
.instructions-title {
|
display: flex;
|
align-items: center;
|
margin-bottom: 20rpx;
|
}
|
|
.title-text {
|
margin-left: 10rpx;
|
font-size: 30rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.instructions-content {
|
padding-left: 40rpx;
|
}
|
|
.content-text {
|
font-size: 26rpx;
|
color: #666;
|
line-height: 1.6;
|
}
|
|
.placeholder {
|
height: 40rpx;
|
}
|
|
.empty-state {
|
margin-top: 200rpx;
|
}
|
</style>
|