Files
frontend-app/pages/order_package/order_submit/coupon-dialog.vue
T
2026-07-25 09:12:36 +08:00

383 lines
8.7 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 class="content">
<up-popup
:show="show"
:round="20"
:closeOnClickOverlay="false"
:closeable="true"
:safeAreaInsetBottom="false"
@close="handleClose"
>
<view class="coupon-popup">
<!-- 固定的标题头部 -->
<view class="popup-header">
<text class="title">选择优惠券</text>
</view>
<!-- 固定的切换标签 -->
<view class="tab-container">
<view
v-for="(tab, index) in tabs"
:key="index"
:class="['tab-item', { active: activeTab === index }]"
@click="activeTab = index"
>
<text class="tab-text">{{ tab.name }}</text>
<view class="active-line" v-if="activeTab === index"></view>
</view>
</view>
<!-- 可上下滚动的优惠券列表区域 -->
<scroll-view
class="coupon-scroll"
scroll-y
:enhanced="true"
:show-scrollbar="false"
>
<view class="coupon-list">
<view
class="coupon-card"
v-for="(coupon, index) in filteredCoupons"
:key="index"
:class="{ 'disabled': coupon.status === 'expired' }"
>
<!-- 左侧:金额与门槛 -->
<view class="card-left">
<view class="price-box">
<text class="currency">¥</text>
<text class="amount">{{ coupon.amount }}</text>
</view>
<text class="condition">{{ coupon.condition }}</text>
</view>
<!-- 带有上下半圆凹槽的虚线分割线 -->
<view class="divider-wrapper">
<view class="notch top-notch"></view>
<view class="divider-line"></view>
<view class="notch bottom-notch"></view>
</view>
<!-- 右侧:详细内容 -->
<view class="card-right">
<view class="info-content">
<view class="title">{{ coupon.title }}</view>
<view class="description">{{ coupon.description }}</view>
<!-- 状态/倒计时文本 -->
<view v-if="coupon.status === 'active'" class="countdown">
仅剩 {{ coupon.timeLeft }}
</view>
<view v-else class="expired-text">
已失效
</view>
</view>
<!-- 按钮:仅在有效状态下显示 -->
<view v-if="coupon.status === 'active'" class="use-btn" @click="useCoupon(coupon)">
使用
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</up-popup>
</view>
</template>
<script>
export default {
name: "CouponDialog",
props: {
show: {
type: Boolean,
default: false,
},
},
data() {
return {
activeTab: 0,
tabs: [
{ name: "全部", value: "all" },
{ name: "可使用", value: "active" },
{ name: "已失效", value: "expired" },
],
coupons: [
{
amount: 12,
condition: "无门槛",
title: "限时秒杀优惠券",
description: "云南白药牙膏儿膏儿膏儿...",
timeLeft: "14:20:55",
status: "active"
},
{
amount: 12,
condition: "无门槛",
title: "限时秒杀优惠券",
description: "云南白药牙膏儿膏儿膏儿...",
timeLeft: "14:20:55",
status: "active"
},
],
};
},
computed: {
filteredCoupons() {
if (this.activeTab === 0) {
return this.coupons;
} else if (this.activeTab === 1) {
return this.coupons.filter(c => c.status === 'active');
} else if (this.activeTab === 2) {
return [];
} else {
return this.coupons.filter(c => c.status === 'expired');
}
}
},
methods: {
handleClose() {
this.$emit("close");
},
useCoupon(coupon) {
this.$emit("select", coupon);
this.$emit("close");
},
},
};
</script>
<style lang="scss" scoped>
.coupon-popup {
height: 85vh;
background-color: #f6f6f6;
border-radius: 20rpx 20rpx 0 0;
display: flex;
flex-direction: column;
}
.popup-header {
text-align: center;
font-size: 32rpx;
background-color: #ffffff;
color: #333333;
font-weight: 500;
padding: 30rpx 0;
position: relative;
border-radius: 20rpx 20rpx 0 0;
}
.tab-container {
display: flex;
width: 100%;
background-color: #ffffff;
height: 88rpx;
align-items: center;
padding-left: 28rpx;
box-sizing: border-box;
border-top: 2rpx solid #f6f6f6;
.tab-item {
margin-right: 48rpx;
position: relative;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: pointer;
.tab-text {
font-size: 28rpx;
color: #7f7f7f;
transition: all 0.2s ease;
}
&.active {
.tab-text {
color: #7A35F6;
font-weight: bold;
}
}
.active-line {
position: absolute;
bottom: 4rpx;
width: 44rpx;
height: 4rpx;
background-color: #7A35F6;
border-radius: 2rpx;
}
}
}
.coupon-scroll {
flex: 1;
height: 0;
overflow: hidden;
}
.coupon-list {
padding: 28rpx 28rpx;
box-sizing: border-box;
display: flex;
background-color: #ffffff;
flex-direction: column;
gap: 32rpx;
.coupon-card {
background: rgba(102,102,102,0.06);
border-radius: 16rpx;
display: flex;
height: 196rpx;
position: relative;
.card-left {
width: 190rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-shrink: 0;
.price-box {
display: flex;
align-items: flex-end;
color: #ff1224;
font-weight: bold;
margin-bottom: 10rpx;
.currency {
font-size: 32rpx;
margin-right: 2rpx;
}
.amount {
font-size: 64rpx;
line-height: 64rpx;
}
}
.condition {
font-size: 24rpx;
color: #ff1224;
margin-top: 10rpx;
}
}
.divider-wrapper {
width: 2rpx;
position: relative;
margin: 10rpx 0;
display: flex;
justify-content: center;
.divider-line {
width: 0;
height: 100%;
border-left: 2rpx dashed rgba(253,28,36,0.3);
}
.notch {
position: absolute;
width: 16rpx;
height: 16rpx;
background-color: #f7f8fa;
border-radius: 50%;
left: 50%;
transform: translateX(-50%);
}
.top-notch {
top: -18rpx;
}
.bottom-notch {
bottom: -18rpx;
}
}
.card-right {
flex: 1;
padding: 26rpx 24rpx 24rpx 36rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
.info-content {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
overflow: hidden;
.title {
font-size: 36rpx;
color: #2c2c2c;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.description {
font-size: 28rpx;
color: #6a6a6a;
margin-top: 8rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.countdown {
font-size: 24rpx;
color: #ff5260;
margin-top: 14rpx;
}
}
.use-btn {
width: 116rpx;
height: 56rpx;
background-color: #FD1C24;
color: #ffffff;
font-size: 28rpx;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-left: 16rpx;
font-weight: 500;
&:active {
opacity: 0.8;
}
}
}
&.disabled {
background-color: #f4f4f4;
.card-left {
.price-box { color: #9c9c9c; }
.condition { color: #9c9c9c; }
}
.divider-wrapper {
.divider-line { border-left-color: #e2e2e2; }
}
.card-right {
.info-content {
.title { color: #2c2c2c; }
.description { color: #9c9c9c; }
}
.expired-text {
font-size: 22rpx;
color: #bcbcbc;
margin-top: 14rpx;
}
}
}
}
}
</style>