绿满眶商城微信小程序-uniapp
peng
2 天以前 9653f4faa20699a2d9a03391f4a6175ff8ce59c3
pages/storeClaim/store-claim.vue
New file
@@ -0,0 +1,365 @@
<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>