406 lines
8.2 KiB
Vue
406 lines
8.2 KiB
Vue
<template>
|
||
<view class="up-coupon" :class="[`up-coupon--${shape}`, `up-coupon--${type}`, `up-coupon--${size}`, {'up-coupon--disabled': disabled}]"
|
||
:style="[couponStyle]" @click="handleClick">
|
||
<view class="up-coupon__content">
|
||
<!-- 左侧金额区域 -->
|
||
<view class="up-coupon__amount">
|
||
<slot name="unit" :unit="unit" :unitPosition="unitPosition" v-if="unitPosition === 'left'">
|
||
<text class="up-coupon__amount-unit" v-if="unitPosition === 'left'">{{ unit }}</text>
|
||
</slot>
|
||
<slot name="amount" :amount="amount">
|
||
<text class="up-coupon__amount-value">{{ amount }}</text>
|
||
</slot>
|
||
<slot name="unit" :unit="unit" :unitPosition="unitPosition" v-if="unitPosition === 'right'">
|
||
<text class="up-coupon__amount-unit" v-if="unitPosition === 'right'">{{ unit }}</text>
|
||
</slot>
|
||
<slot name="limit" :limit="limit">
|
||
<text class="up-coupon__amount-limit" v-if="limit">{{ limit }}</text>
|
||
</slot>
|
||
</view>
|
||
|
||
<!-- 中间描述区域 -->
|
||
<view class="up-coupon__info">
|
||
<slot name="title" :title="title">
|
||
<text class="up-coupon__info-title">{{ title }}</text>
|
||
</slot>
|
||
<slot name="desc" :desc="desc">
|
||
<text class="up-coupon__info-desc" v-if="desc">{{ desc }}</text>
|
||
</slot>
|
||
<slot name="time" :time="time">
|
||
<text class="up-coupon__info-time" v-if="time">{{ time }}</text>
|
||
</slot>
|
||
</view>
|
||
|
||
<!-- 右侧操作区域 -->
|
||
<view class="up-coupon__action u-padding-right-20">
|
||
<slot name="action" :actionText="actionText" :circle="circle">
|
||
<up-tag type="error" :bgColor="type ? 'transparent' : '#eb433d'"
|
||
:borderColor="type ? '#eee' : '#eb433d'" borderRadius="6px"
|
||
size="medium" class="up-coupon__action-text"
|
||
:shape="circle ? 'circle': 'circle'">{{ actionText }}</up-tag>
|
||
</slot>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 红包绳子效果 -->
|
||
<view v-if="shape === 'envelope'" class="up-coupon__rope"></view>
|
||
|
||
<!-- 默认插槽,可用于添加额外内容 -->
|
||
<slot></slot>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'up-coupon',
|
||
props: {
|
||
// 金额
|
||
amount: {
|
||
type: [String, Number],
|
||
default: ''
|
||
},
|
||
// 金额单位
|
||
unit: {
|
||
type: String,
|
||
default: '¥'
|
||
},
|
||
// 单位位置
|
||
unitPosition: {
|
||
type: String,
|
||
default: 'left'
|
||
},
|
||
// 使用限制
|
||
limit: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 标题
|
||
title: {
|
||
type: String,
|
||
default: '优惠券'
|
||
},
|
||
// 描述
|
||
desc: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 有效期
|
||
time: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 操作按钮文字
|
||
actionText: {
|
||
type: String,
|
||
default: '使用'
|
||
},
|
||
// 形状:coupon-优惠券, envelope-红包, card-卡片
|
||
shape: {
|
||
type: String,
|
||
default: 'coupon'
|
||
},
|
||
// 尺寸:small, medium, large
|
||
size: {
|
||
type: String,
|
||
default: 'medium'
|
||
},
|
||
// 是否圆形按钮
|
||
circle: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 是否禁用
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 背景颜色
|
||
bgColor: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 文字颜色
|
||
color: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 内置背景类型
|
||
type: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
},
|
||
computed: {
|
||
couponStyle() {
|
||
const style = {};
|
||
if (this.bgColor) style.background = this.bgColor;
|
||
if (this.color) style.color = this.color;
|
||
return style;
|
||
},
|
||
dotCount() {
|
||
// 根据尺寸计算锯齿数量
|
||
const map = {
|
||
small: 8,
|
||
medium: 10,
|
||
large: 12
|
||
};
|
||
return map[this.size] || 10;
|
||
}
|
||
},
|
||
methods: {
|
||
handleClick() {
|
||
if (this.disabled) return;
|
||
this.$emit('click');
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.up-coupon {
|
||
position: relative;
|
||
overflow: hidden;
|
||
border-radius: 8rpx;
|
||
background: #ffebf0;
|
||
color: $u-main-color;
|
||
|
||
&--coupon {
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: -24rpx;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
background-color: #fff;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
right: -24rpx;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
background-color: #fff;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
|
||
&--envelope {
|
||
border-radius: 16rpx;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
right: 0;
|
||
height: 20rpx;
|
||
background: repeating-linear-gradient(-45deg, #ffd000, #ffd000 10rpx, #ffa000 10rpx, #ffa000 20rpx);
|
||
}
|
||
}
|
||
|
||
&--card {
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
width: 100%;
|
||
|
||
&--small {
|
||
// width: 520rpx;
|
||
height: 160rpx;
|
||
}
|
||
|
||
&--medium {
|
||
// width: 600rpx;
|
||
height: 180rpx;
|
||
}
|
||
|
||
&--large {
|
||
// width: 700rpx;
|
||
height: 220rpx;
|
||
}
|
||
|
||
&--disabled {
|
||
opacity: 0.5;
|
||
}
|
||
|
||
&__content {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: 100%;
|
||
padding: 0 30rpx;
|
||
position: relative;
|
||
z-index: 2;
|
||
}
|
||
|
||
&__amount {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
padding-left: 10rpx;
|
||
padding-right: 30rpx;
|
||
border-right: 1px dashed #ccc;
|
||
|
||
&-unit {
|
||
font-size: 24rpx;
|
||
font-weight: normal;
|
||
}
|
||
|
||
&-value {
|
||
font-size: 56rpx;
|
||
font-weight: bold;
|
||
color: red;
|
||
line-height: 1;
|
||
margin: 10rpx 0;
|
||
}
|
||
|
||
&-limit {
|
||
font-size: 24rpx;
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
|
||
&__info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
padding-left: 30rpx;
|
||
|
||
&-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
&-desc {
|
||
font-size: 24rpx;
|
||
opacity: 0.9;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
&-time {
|
||
font-size: 20rpx;
|
||
opacity: 0.8;
|
||
}
|
||
}
|
||
|
||
&__action {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
&__dots {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
padding: 30rpx 0;
|
||
z-index: 1;
|
||
}
|
||
|
||
&__dot {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
background-color: #fff;
|
||
border-radius: 50%;
|
||
margin: 0 -16rpx;
|
||
z-index: 3;
|
||
}
|
||
|
||
&__rope {
|
||
position: absolute;
|
||
top: -40rpx;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
background: linear-gradient(to right, #ffd000, #ffa000);
|
||
border-radius: 40rpx 40rpx 0 0;
|
||
z-index: 1;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -20rpx;
|
||
width: 20rpx;
|
||
height: 40rpx;
|
||
background: linear-gradient(to bottom, #ffd000, #ffa000);
|
||
border-radius: 10rpx 0 0 10rpx;
|
||
}
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
right: -20rpx;
|
||
width: 20rpx;
|
||
height: 40rpx;
|
||
background: linear-gradient(to bottom, #ffd000, #ffa000);
|
||
border-radius: 0 10rpx 10rpx 0;
|
||
}
|
||
}
|
||
|
||
// 不同主题样式
|
||
&--primary {
|
||
background: linear-gradient(90deg, #43afff, #3b8cff);
|
||
color: #fff;
|
||
.up-coupon__amount {
|
||
border-right: 1px dashed #eee;
|
||
}
|
||
.up-coupon__amount-value {
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
&--success {
|
||
background: linear-gradient(90deg, #67dda9, #19be6b);
|
||
color: #fff !important;
|
||
.up-coupon__amount {
|
||
border-right: 1px dashed #eee;
|
||
}
|
||
.up-coupon__amount-value {
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
&--warning {
|
||
background: linear-gradient(90deg, #ff9739, #ff6a39);
|
||
color: #fff;
|
||
.up-coupon__amount {
|
||
border-right: 1px dashed #eee;
|
||
}
|
||
.up-coupon__amount-value {
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
&--error {
|
||
background: linear-gradient(90deg, #ff7070, #ff4747);
|
||
color: #fff;
|
||
.up-coupon__amount {
|
||
border-right: 1px dashed #eee;
|
||
}
|
||
.up-coupon__amount-value {
|
||
color: #fff;
|
||
}
|
||
}
|
||
}
|
||
</style> |