Files
taimed-international-app/components/order/Coupon.vue

328 lines
8.0 KiB
Vue
Raw 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>
<view>
<view class="price-item" @click="showCouponPopup = true">
<view class="label-row">
<text class="label">{{ $t('order.coupon') }}</text>
</view>
<view class="value-row">
<template v-if="!selectedCoupon">
<view v-if="availableCouponCount > 0" class="coupon-badge">
<text>{{ $t('order.couponCount', { count: availableCouponCount }) }}</text>
</view>
<text v-else-if="couponList.length === 0" class="unavailable-text">
{{ $t('order.noCoupon') }}
</text>
<text v-else class="unavailable-text">
{{ $t('order.unavailable') }}
</text>
</template>
<template v-else>
<text class="discount-value">-{{ selectedCoupon.couponEntity.couponAmount }}</text>
<text class="reselect-btn">{{ $t('order.reselect') }}</text>
</template>
<image
v-if="availableCouponCount > 0 || selectedCoupon"
src="/static/icon/icon_right.png"
class="arrow-icon"
/>
</view>
</view>
<!-- 优惠券选择弹窗 -->
<wd-popup
v-model="showCouponPopup"
position="bottom"
:close-on-click-modal="false"
>
<view class="coupon-popup">
<view class="popup-header">
<text class="popup-title">{{ $t('order.selectCoupon') }}</text>
<wd-icon name="close" @click="showCouponPopup = false" />
</view>
<view class="coupon-list">
<view
v-for="(coupon, index) in couponList"
:key="index"
:class="['coupon-item', coupon.canUse === 0 ? 'disabled' : '', selectedCoupon?.couponId === coupon.couponId ? 'selected' : '']"
@click="handleCouponSelect(coupon)"
>
<view class="coupon-type-badge">
{{ getCouponTypeText(coupon.couponEntity.couponRange) }}
</view>
<view class="coupon-amount">
<text class="currency"></text>
<text class="amount">{{ coupon.couponEntity.couponAmount }}</text>
</view>
<view class="coupon-info">
<text class="coupon-name">{{ coupon.couponEntity.couponName }}</text>
<text class="coupon-condition">
{{ $t('order.couponUseLevel', { level: coupon.couponEntity.useLevel }) }}
</text>
<text class="coupon-expiry">
{{ $t('order.couponExpiry') }}
{{ coupon.effectType === 0 ? $t('order.couponForever') : coupon.endTime }}
</text>
<text v-if="coupon.canUse === 0" class="unavailable-reason">
{{ $t('order.couponReason') }}{{ coupon.canUseReason }}
</text>
</view>
<view class="coupon-select">
<wd-icon
v-if="coupon.canUse === 1"
:name="selectedCoupon?.couponId === coupon.couponId ? 'checkmark-circle-fill' : 'circle'"
:color="selectedCoupon?.couponId === coupon.couponId ? '#fd6004' : '#d9d9d9'"
size="20"
/>
</view>
</view>
<view v-if="couponList.length === 0" class="empty-coupon">
<text>{{ $t('order.noCoupon') }}</text>
</view>
</view>
<view class="popup-footer">
<wd-button
v-if="availableCouponCount > 0"
type="default"
@click="handleCouponConfirm(null)"
>
{{ $t('order.notUseCoupon') }}
</wd-button>
<wd-button
v-if="availableCouponCount > 0"
type="primary"
@click="handleCouponConfirm(selectedCoupon)"
>
{{ $t('order.selected') }}
</wd-button>
<wd-button
v-else
type="default"
@click="showCouponPopup = false"
>
{{ $t('order.confirm') }}
</wd-button>
</view>
</view>
</wd-popup>
</view>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { orderApi } from '@/api/modules/order'
import { t } from '@/utils/i18n'
import type {
ICoupon
} from '@/types/order'
const emit = defineEmits(['selectCoupon'])
const couponList = ref<ICoupon[]>([])
const selectedCoupon = ref<ICoupon | null>(null)
const showCouponPopup = ref(false)
/**
* 可用优惠券数量
*/
const availableCouponCount = computed(() => {
return couponList.value.filter(c => c.canUse === 1).length
})
/**
* 获取优惠券类型文本
*/
const getCouponTypeText = (type: number) => {
const typeMap: Record<number, string> = {
0: 'couponType0',
1: 'couponType1',
2: 'couponType2'
}
return typeMap[type] || 'couponType0'
}
/**
* 选择优惠券
*/
const handleCouponSelect = (coupon: ICoupon) => {
if (coupon.canUse === 0) {
return
}
if (selectedCoupon.value?.couponId === coupon.couponId) {
selectedCoupon.value = null
} else {
selectedCoupon.value = coupon
}
}
/**
* 确认优惠券选择
*/
const handleCouponConfirm = (coupon: ICoupon | null) => {
selectedCoupon.value = coupon
showCouponPopup.value = false
// 回传优惠券选择
emit('selectCoupon', coupon)
}
</script>
<style lang="scss" scoped>
.coupon-badge {
padding: 4rpx 20rpx;
background-color: #fceeeb;
color: #ec4729;
font-size: 24rpx;
border-radius: 10rpx;
}
.unavailable-text {
font-size: 24rpx;
color: #999;
}
.reselect-btn {
padding: 4rpx 12rpx;
background-color: #fe6035;
color: #fff;
font-size: 24rpx;
border-radius: 30rpx;
}
.arrow-icon {
width: 24rpx;
height: 24rpx;
}
.coupon-popup {
max-height: 80vh;
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
.popup-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
}
.coupon-list {
max-height: 60vh;
overflow-y: auto;
padding: 20rpx;
.coupon-item {
position: relative;
display: flex;
align-items: center;
padding: 30rpx 20rpx;
margin-bottom: 20rpx;
background: linear-gradient(to top right, #fff, #fef2f4);
border: 1px solid #d9d9d9;
border-radius: 10rpx;
&.selected {
border-color: #fd6004;
}
&.disabled {
background: linear-gradient(to top right, #fafafa, #fafafa);
color: #979797;
.coupon-amount {
color: #979797;
}
}
.coupon-type-badge {
position: absolute;
top: 10rpx;
right: 10rpx;
padding: 6rpx;
background-color: #ffe3e9;
color: #c81346;
font-size: 20rpx;
border-radius: 10rpx;
}
.coupon-amount {
width: 25%;
text-align: center;
color: #ff0043;
.currency {
font-size: 24rpx;
}
.amount {
font-size: 45rpx;
font-weight: bold;
}
}
.coupon-info {
flex: 1;
padding-left: 5%;
display: flex;
flex-direction: column;
gap: 10rpx;
.coupon-name {
font-size: 28rpx;
font-weight: 500;
color: #333;
}
.coupon-condition {
font-size: 24rpx;
color: #666;
}
.coupon-expiry {
font-size: 22rpx;
color: #999;
}
.unavailable-reason {
font-size: 20rpx;
color: #333;
}
}
.coupon-select {
width: 7%;
display: flex;
justify-content: center;
}
}
.empty-coupon {
padding: 60rpx 0;
text-align: center;
color: #999;
font-size: 28rpx;
}
}
.popup-footer {
display: flex;
gap: 20rpx;
padding: 20rpx;
border-top: 1px solid #f0f0f0;
}
}
</style>