New file |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- 顶部标题 --> |
| | | <view class="header"> |
| | | <text class="title">优惠券领取</text> |
| | | <text class="subtitle">领取您的专属优惠券</text> |
| | | </view> |
| | | |
| | | <!-- 单个优惠券展示 --> |
| | | <view class="coupon-container" v-if="couponInfo"> |
| | | <view class="coupon-card"> |
| | | <!-- 商品图片 --> |
| | | <view class="goods-image-container"> |
| | | <u-image |
| | | :src="couponInfo.goodsImage || '/static/default_goods.png'" |
| | | width="100%" |
| | | height="300rpx" |
| | | mode="aspectFit" |
| | | border-radius="16" |
| | | @click="previewImage(couponInfo.goodsImage)" |
| | | ></u-image> |
| | | </view> |
| | | |
| | | <!-- 优惠券信息 --> |
| | | <view class="coupon-info"> |
| | | <view class="coupon-name">{{ couponInfo.couponName || couponInfo.name }}</view> |
| | | <view class="goods-name">{{ couponInfo.skuName }}</view> |
| | | <view class="coupon-no">编号:{{ couponInfo.couponNo }}</view> |
| | | <view class="time-info"> |
| | | <text class="create-time">创建时间:{{ formatDate(couponInfo.createTime) }}</text> |
| | | </view> |
| | | <view class="status"> |
| | | <u-tag |
| | | :text="couponInfo.claimStatus === 'CLAIM' ? '已领取' : '未领取'" |
| | | :type="couponInfo.claimStatus === 'CLAIM' ? 'success' : 'warning'" |
| | | size="mini" |
| | | /> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 领取按钮 --> |
| | | <view class="claim-btn-container"> |
| | | <button |
| | | class="claim-btn" |
| | | :class="{ 'claimed': couponInfo.claimStatus === 'CLAIM' }" |
| | | :disabled="couponInfo.claimStatus === 'CLAIM'" |
| | | @click="claimCoupon" |
| | | > |
| | | {{ couponInfo.claimStatus === 'CLAIM' ? '已领取' : '立即领取' }} |
| | | </button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 加载中状态 --> |
| | | <view class="loading-container" v-else-if="loading"> |
| | | <u-loading mode="circle" size="40"></u-loading> |
| | | <text class="loading-text">加载中...</text> |
| | | </view> |
| | | |
| | | <!-- 空状态 --> |
| | | <u-empty |
| | | v-else |
| | | text="暂无优惠券" |
| | | mode="coupon" |
| | | icon-size="120" |
| | | margin-top="200" |
| | | ></u-empty> |
| | | |
| | | <!-- 去购物弹窗 --> |
| | | <u-modal |
| | | v-model="showShoppingModal" |
| | | :content="'恭喜您领取成功,是否立即使用优惠券去购物?'" |
| | | :show-cancel-button="true" |
| | | confirm-text="去购物" |
| | | cancel-text="稍后再说" |
| | | @confirm="goShopping" |
| | | @cancel="closeModal" |
| | | ></u-modal> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getVirtualCouponDetail, claimVirtualCoupon } from '@/api/coupon.js'; |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | couponInfo: null, // 单个优惠券信息 |
| | | loading: false, |
| | | showShoppingModal: false ,// 控制去购物弹窗显示 |
| | | couponId:'' |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | // 通过参数传递优惠券ID |
| | | // 例如: /pages/order/claim-coupon/claim-coupon?id=123 |
| | | options.id = '1966390012058017794' |
| | | |
| | | this.couponId = '' |
| | | if (options.id) { |
| | | this.loadCouponInfo(options.id); |
| | | } else { |
| | | // 如果没有传递ID,显示空状态 |
| | | uni.showToast({ |
| | | title: '缺少优惠券ID参数', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }, |
| | | methods: { |
| | | // 加载指定ID的优惠券信息 |
| | | async loadCouponInfo(id) { |
| | | if (this.loading) return; |
| | | this.loading = true; |
| | | |
| | | try { |
| | | // 调用获取单个优惠券详情的接口 |
| | | const res = await getVirtualCouponDetail(id); |
| | | |
| | | if (res.data.code===200) { |
| | | this.couponInfo = res.data.data; |
| | | } else { |
| | | throw new Error(res.message || '获取优惠券失败'); |
| | | } |
| | | } catch (err) { |
| | | console.error('获取优惠券信息失败:', err); |
| | | uni.showToast({ |
| | | title: err.message || '获取优惠券失败', |
| | | icon: 'none' |
| | | }); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // 领取优惠券 |
| | | async claimCoupon() { |
| | | if (!this.couponInfo || this.couponInfo.claimStatus === 'CLAIM') { |
| | | uni.showToast({ |
| | | title: '该优惠券已领取', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | uni.showLoading({ |
| | | title: '领取中...' |
| | | }); |
| | | |
| | | // 调用领取优惠券接口 |
| | | const res = await claimVirtualCoupon(this.couponInfo.id); |
| | | |
| | | if (res.data.code===200) { |
| | | // 更新本地状态 |
| | | this.couponId = res.data.data |
| | | this.$set(this.couponInfo, 'claimStatus', 'CLAIM'); |
| | | this.$set(this.couponInfo, 'claimTime', new Date()); |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: '领取成功', |
| | | icon: 'success' |
| | | }); |
| | | |
| | | // 显示去购物弹窗 |
| | | this.showShoppingModal = true; |
| | | } else { |
| | | throw new Error(res.message || '领取失败'); |
| | | } |
| | | } catch (err) { |
| | | uni.hideLoading(); |
| | | console.error('领取优惠券失败:', err); |
| | | uni.showToast({ |
| | | title: err.message || '领取失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | // 去购物 |
| | | goShopping() { |
| | | // 关闭弹窗 |
| | | this.showShoppingModal = false; |
| | | |
| | | // 这里可以添加跳转到购物页面的逻辑 |
| | | // 例如跳转到商品详情页或购物车页面 |
| | | // 根据实际需求调整跳转路径 |
| | | if (this.couponInfo && this.couponInfo.skuId) { |
| | | // 如果有商品ID,跳转到商品详情页 |
| | | uni.navigateTo({ |
| | | url: `/pages/commodity-square/coups-goods-list?promotionsId=${this.couponId}&promotionType=COUPON` |
| | | }); |
| | | } else { |
| | | // 否则跳转到首页或其他页面 |
| | | uni.switchTab({ |
| | | url: '/pages/tabbar/index/home' |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | // 关闭弹窗 |
| | | closeModal() { |
| | | this.showShoppingModal = false; |
| | | // 关闭弹窗后返回上一页 |
| | | uni.navigateBack(); |
| | | }, |
| | | |
| | | // 格式化日期 |
| | | formatDate(date) { |
| | | if (!date) return ''; |
| | | const d = new Date(date); |
| | | return `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')} ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | // 预览图片 |
| | | previewImage(url) { |
| | | if (url) { |
| | | uni.previewImage({ |
| | | urls: [url] |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | padding: 20rpx; |
| | | background-color: #f5f5f5; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | .header { |
| | | background-color: #fff; |
| | | padding: 30rpx; |
| | | border-radius: 16rpx; |
| | | margin-bottom: 20rpx; |
| | | text-align: center; |
| | | |
| | | .title { |
| | | font-size: 36rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | display: block; |
| | | margin-bottom: 10rpx; |
| | | } |
| | | |
| | | .subtitle { |
| | | font-size: 28rpx; |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | .coupon-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | min-height: 60vh; |
| | | } |
| | | |
| | | .coupon-card { |
| | | background-color: #fff; |
| | | border-radius: 16rpx; |
| | | padding: 30rpx; |
| | | width: 90%; |
| | | box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | text-align: center; |
| | | |
| | | .goods-image-container { |
| | | margin-bottom: 30rpx; |
| | | border-radius: 16rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .coupon-info { |
| | | margin-bottom: 30rpx; |
| | | |
| | | .coupon-name { |
| | | font-size: 36rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .goods-name { |
| | | font-size: 30rpx; |
| | | color: #666; |
| | | margin-bottom: 20rpx; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .coupon-no { |
| | | font-size: 26rpx; |
| | | color: #999; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .time-info { |
| | | font-size: 26rpx; |
| | | color: #999; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .status { |
| | | margin-bottom: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .claim-btn-container { |
| | | .claim-btn { |
| | | width: 80%; |
| | | height: 80rpx; |
| | | background-color: #ff6b6b; |
| | | color: #fff; |
| | | border-radius: 40rpx; |
| | | font-size: 32rpx; |
| | | border: none; |
| | | margin: 0 auto; |
| | | |
| | | &:active { |
| | | background-color: #ff5252; |
| | | } |
| | | |
| | | &.claimed { |
| | | background-color: #ccc; |
| | | } |
| | | |
| | | &[disabled] { |
| | | background-color: #ccc; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .loading-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 60vh; |
| | | |
| | | .loading-text { |
| | | margin-top: 20rpx; |
| | | color: #999; |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | </style> |