aiyushanuninew/pages/menu/coupon-float.vue
yindongqi 891ee783a5 feat: 新增优惠券功能与优化用户体验
- 新增商品券类型支持,包括商品券的领取、使用和展示
- 优化优惠券领取流程,支持兑换码兑换和自动跳转登录
- 新增优惠活动功能,支持活动商品折扣
- 重构优惠券页面布局,区分领取和使用页面
- 新增分销商信息编辑功能
- 优化小程序更新机制,改进更新提示流程
- 修复优惠券使用条件判断逻辑
- 调整UI样式,统一主题色为绿色
- 新增电话客服功能,支持动态电话号码
- 优化订单详情页,展示商品券信息
2025-07-14 10:00:22 +08:00

217 lines
5.3 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<uv-popup ref="popup" mode="center" width="90%" @change="onChange" :safe-area-inset-bottom="true" class="coupon-float-popup" :zIndex="9999">
<view class="coupon-float-container">
<view class="header">
<image class="icon" src="/static/images/coupon-icon.png" />
<text class="title">我的优惠券</text>
<view class="close-btn" @tap="onClose">
<uv-icon name="close" size="28" color="#999" />
</view>
</view>
<scroll-view scroll-y class="coupon-list">
<uv-empty v-if="coupons.length === 0" mode="coupon" text="暂无可用优惠券"></uv-empty>
<view v-else class="wrapper">
<view class="coupon-card" v-for="(item, index) in coupons" :key="item.id">
<view class="left">
<image class="picture" :src="item.image" mode="aspectFill">
<view class="coupon-type">{{ item.couponType === 1 ? '满减券' : '商品券' }}</view>
</image>
<view class="introduce">
<view class="top">
<view v-if="item.couponType === 1" class="price">
<text></text>
<text class="big">{{ item.value }}</text>
</view>
<view v-if="item.couponType === 2" class="price">
<text>商品</text>
<text class="big">{{ item.productName }}</text>
</view>
<view v-if="item.couponType === 1">{{ item.least }}{{ item.value }}</view>
</view>
<view class="type">{{ item.title }}</view>
<view class="date">有效期{{ formatDate(item.startTime) }} - {{ formatDate(item.endTime) }}</view>
</view>
</view>
<view class="right">
<uv-icon name="gift" size="32" color="#f9ae3d" />
</view>
</view>
</view>
</scroll-view>
</view>
</uv-popup>
</template>
<script setup>
import { defineProps, defineEmits, watch, ref, nextTick } from 'vue'
import { formatDateTime } from '@/utils/util'
const props = defineProps({
show: {
type: Boolean,
default: false
},
coupons: {
type: Array,
default: () => []
}
})
const popup = ref(null)
// 添加调试信息
watch(() => props.show, (newVal) => {
// console.log('优惠券弹框显示状态变化:', newVal)
if (newVal) {
nextTick(() => {
popup.value?.open()
})
} else {
popup.value?.close()
}
})
watch(() => props.coupons, (newVal) => {
// console.log('优惠券数据变化:', newVal)
}, { deep: true })
const emit = defineEmits(['close'])
const onChange = (e) => {
// console.log('弹框状态变化:', e)
if (!e.show) {
emit('close')
}
}
const formatDate = (date) => formatDateTime(date, 'yyyy-MM-dd')
const onClose = () => {
popup.value?.close()
}
</script>
<style lang="scss" scoped>
.coupon-float-popup {
z-index: 3002;
}
.coupon-float-container {
background: #fff;
border-radius: 24rpx;
padding: 0 0 32rpx 0;
min-height: 400rpx;
max-height: 70vh;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.08);
overflow: hidden;
}
.header {
display: flex;
align-items: center;
justify-content: center;
position: relative;
padding: 32rpx 0 16rpx 0;
.icon {
width: 48rpx;
height: 48rpx;
margin-right: 12rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #f9ae3d;
letter-spacing: 2rpx;
}
.close-btn {
position: absolute;
right: 32rpx;
top: 32rpx;
z-index: 2;
padding: 8rpx;
}
}
.coupon-list {
max-height: 60vh;
min-height: 200rpx;
padding: 0 32rpx 0 32rpx;
}
.wrapper {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.coupon-card {
display: flex;
align-items: stretch;
background: linear-gradient(90deg, #fffbe6 0%, #fff 100%);
border-radius: 18rpx;
box-shadow: 0 2rpx 12rpx rgba(249,174,61,0.08);
padding: 24rpx 20rpx;
position: relative;
.left {
display: flex;
flex: 1;
.picture {
width: 120rpx;
height: 120rpx;
border-radius: 16rpx;
margin-right: 18rpx;
position: relative;
.coupon-type {
position: absolute;
left: 0;
bottom: 0;
background: #f9ae3d;
color: #fff;
font-size: 22rpx;
border-radius: 0 0 0 12rpx;
padding: 2rpx 10rpx;
}
}
.introduce {
display: flex;
flex-direction: column;
justify-content: center;
.top {
font-size: 28rpx;
color: #f9ae3d;
.price {
display: flex;
align-items: baseline;
.big {
font-weight: bold;
margin: 0 8rpx;
}
}
.product {
display: flex;
align-items: baseline;
font-size: 28rpx;
color: #333;
.big {
font-size: 48rpx;
font-weight: bold;
margin: 0 8rpx;
}
}
}
.type {
font-size: 26rpx;
color: #666;
margin: 4rpx 0 0 0;
}
.date {
font-size: 22rpx;
color: #aaa;
margin-top: 6rpx;
}
}
}
.right {
display: flex;
align-items: center;
justify-content: center;
width: 60rpx;
margin-left: 10rpx;
}
}
</style>