绿满眶商城微信小程序-uniapp
peng
2025-09-12 e3a79d7726ad7788f08a335483ca852cded4a704
礼品卡领取页面
1个文件已修改
2个文件已添加
439 ■■■■■ 已修改文件
api/coupon.js 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/order/claim-coupon/claim-coupon.vue 350 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/coupon.js
New file
@@ -0,0 +1,74 @@
import { http, Method } from "@/utils/request.js";
/**
 * 获取虚拟商品优惠券列表
 * @param {Object} params - 查询参数
 * @param {number} params.pageNumber - 页码
 * @param {number} params.pageSize - 每页数量
 * @param {string} params.claimStatus - 领取状态 (NOT_CLAIM: 未领取, CLAIM: 已领取)
 * @param {string} params.userId - 用户ID
 * @param {string} params.orderId - 订单ID
 * @returns {Promise} 返回优惠券列表
 */
export function getVirtualCoupons(params) {
  return http.request({
    url: "/lmk/coupon/virtual",
    method: Method.GET,
    needToken: true,
    params,
  });
}
/**
 * 领取虚拟商品优惠券
 * @param {string|number} id - 优惠券ID
 * @returns {Promise} 返回领取结果
 */
export function claimVirtualCoupon(id) {
  return http.request({
    url: `/lmk/coupon/card/${id}`,
    method: Method.POST,
    needToken: true,
  });
}
/**
 * 根据订单ID获取虚拟商品优惠券
 * @param {string} orderId - 订单ID
 * @returns {Promise} 返回优惠券列表
 */
export function getVirtualCouponsByOrderId(orderId) {
  return http.request({
    url: `/lmk/coupon/virtual/order/${orderId}`,
    method: Method.GET,
    needToken: true,
  });
}
/**
 * 根据优惠卷领取ID获取虚拟商品优惠券
 * @param {string} userId - 用户ID
 * @returns {Promise} 返回优惠券列表
 */
export function getVirtualCouponsByUserId(userId) {
  return http.request({
    url: `/lmk/coupon/card/couponCardInfo/${userId}`,
    method: Method.GET,
    needToken: true,
  });
}
/**
 * 获取优惠券详情
 * @param {string|number} id - 优惠券ID
 * @returns {Promise} 返回优惠券详情
 */
export function getVirtualCouponDetail(id) {
  return http.request({
    url: `/lmk/coupon/card/couponCardInfo/${id}`,
    method: Method.POST,
    needToken: true,
  });
}
pages.json
@@ -1777,6 +1777,21 @@
              "u-notice-bar": "view"
            }
          }
        },
        {
            "path" : "claim-coupon/claim-coupon",
            "style" :
            {
                "navigationBarTitleText" : "优惠券领取",
                "enablePullDownRefresh" : true,
                "componentPlaceholder": {
                  "u-image": "view",
                  "u-tag": "view",
                  "u-loading": "view",
                  "u-empty": "view",
                  "u-modal":"view"
                }
            }
        }
      ]
    },
pages/order/claim-coupon/claim-coupon.vue
New file
@@ -0,0 +1,350 @@
<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>