优惠券组件直接用 uview plus

使用

复制代码
    <!-- 优惠券弹窗 -->
    <CouponPopup 
      :show="couponPopupShow" 
      :couponList="couponList"
      @update:show="couponPopupShow = $event"
      @use="handleUseCoupon"
    />
  </view>
</template>

<script setup>

import CouponPopup from '@/pagesSubpg/hotel/components/CouponPopup/index.vue'
// 优惠券弹窗显示状态
const couponPopupShow = ref(false)

// 优惠券列表数据
const couponList = ref([
  {
    type: 'money',
    value: '10',
    condition: '150',
    name: '酒店消费券',
    startTime: '2026.04.20',
    endTime: '2026.05.20'
  },
  {
    type: 'money',
    value: '10',
    condition: '150',
    name: '酒店消费券',
    startTime: '2026.04.20',
    endTime: '2026.05.20'
  },
  {
    type: 'discount',
    value: '8.5',
    condition: '150',
    name: '酒店消费券',
    startTime: '2026.04.20',
    endTime: '2026.05.20'
  }
])

// 显示优惠券弹窗
const showCouponPopup = () => {
  couponPopupShow.value = true
}

// 使用优惠券
const handleUseCoupon = (coupon) => {
  console.log('使用优惠券:', coupon)
  uni.showToast({
    title: '已选择优惠券',
    icon: 'success'
  })
}

组件代码

复制代码
<template>
  <u-popup :show="show" mode="bottom" round="16" @close="handleClose">
    <view class="coupon-popup">
      <!-- 弹窗标题 -->
      <view class="popup-header">
        <text class="popup-title">优惠券</text>
        <view class="uicon">
          <u-icon  name="close" size="20" color="#999" @click="handleClose"></u-icon>
        </view>
      </view>

      <!-- 优惠券列表 -->
      <scroll-view scroll-y class="coupon-list">
        <view class="coupon-item" v-for="(coupon, index) in couponList" :key="index">
          <!-- 左侧金额/折扣区域 -->
          <view class="coupon-left">
            <text class="coupon-value" :class="{ 'is-discount': coupon.type === 'discount' }">
              <text class="symbol" v-if="coupon.type === 'money'">¥</text>
              {{ coupon.value }}
              <text class="unit" v-if="coupon.type === 'discount'">折</text>
            </text>
            <text class="coupon-condition">满{{ coupon.condition }}元可用</text>
          </view>

          <!-- 中间信息区域 -->
          <view class="coupon-center">
            <text class="coupon-name">{{ coupon.name }}</text>
            <text class="coupon-time">{{ coupon.startTime }} - {{ coupon.endTime }}</text>
            <text class="coupon-rule" @click="showRule(coupon)">使用规则</text>
          </view>

          <!-- 右侧操作按钮 -->
          <view class="coupon-right">
            <view class="use-btn" @click="handleUse(coupon)">去使用</view>
          </view>
        </view>
      </scroll-view>
    </view>
  </u-popup>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  show: {
    type: Boolean,
    default: false
  },
  couponList: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['update:show', 'use'])

// 关闭弹窗
const handleClose = () => {
  emit('update:show', false)
}

// 使用优惠券
const handleUse = (coupon) => {
  emit('use', coupon)
  handleClose()
}

// 查看规则
const showRule = (coupon) => {
  uni.showToast({
    title: '查看使用规则',
    icon: 'none'
  })
}
</script>

<style lang="scss" scoped>
.coupon-popup {
  background-color: #fff;
  border-radius: 32rpx 32rpx 0 0;
  max-height: 70vh;
  display: flex;
  flex-direction: column;

  .popup-header {
    display: flex;
    align-items: center;
    justify-content:center;
    padding: 32rpx;
    position: relative;
    border-bottom: 1rpx solid #f0f0f0;

    .popup-title {
      font-size: 32rpx;
      font-weight: bold;
      color: #333;
    }

    .uicon {
      position: absolute;
      right: 30rpx;
      top: 32rpx;
    }
  }

  .coupon-list {
    flex: 1;
    padding: 24rpx 32rpx;
  }

  .coupon-item {
    display: flex;
    background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%);
    border-radius: 16rpx;
    padding: 24rpx;
    margin-bottom: 20rpx;
    position: relative;
    overflow: hidden;

    // 虚线分隔效果
    &::before {
      content: '';
      position: absolute;
      left: 170rpx;
      top: 0;
      bottom: 0;
      width: 2rpx;
      background: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent 8rpx,
        #ddd 8rpx,
        #ddd 16rpx
      );
    }

    .coupon-left {
      width: 150rpx;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding-right: 20rpx;

      .coupon-value {
        font-size: 48rpx;
        font-weight: bold;
        color: #FF4D4F;
        line-height: 1;

        &.is-discount {
          font-size: 40rpx;
        }

        .symbol {
          font-size: 28rpx;
          margin-right: 4rpx;
        }

        .unit {
          font-size: 24rpx;
          margin-left: 4rpx;
        }
      }

      .coupon-condition {
        font-size: 22rpx;
        color: #FF4D4F;
        margin-top: 8rpx;
      }
    }

    .coupon-center {
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding: 0 20rpx;

      .coupon-name {
        font-size: 28rpx;
        font-weight: bold;
        color: #333;
        margin-bottom: 8rpx;
      }

      .coupon-time {
        font-size: 24rpx;
        color: #999;
        margin-bottom: 8rpx;
      }

      .coupon-rule {
        font-size: 24rpx;
        color: #999;
        // color: #42D0E0;
      }
    }

    .coupon-right {
      display: flex;
      align-items: center;

      .use-btn {
        background: linear-gradient(135deg, #42D0E0 0%, #5EDFFF 100%);
        color: #fff;
        font-size: 26rpx;
        padding: 12rpx 32rpx;
        border-radius: 24rpx;
        text-align: center;
      }
    }
  }
}
</style>
相关推荐
用户74090472362751 小时前
我用 curl 排查了一次 OpenAI-compatible API 连接失败:401、403、404 分别怎么定位
前端
kft13141 小时前
XSS深度剖析:从弹窗到持久化窃取Cookie
前端·web安全·xss·安全测试
烬羽1 小时前
《前端三权分立:HTML、CSS、JS为什么不能“乱搞”》
前端
恋爱脑1 小时前
vue自定义指令封装-是否点击当前元素以外区域
前端
川冰ICE1 小时前
TypeScript装饰器与元编程实战
前端·javascript·typescript
AI砖家2 小时前
Vue3组件传参大全,各种传参方式的对比
前端·javascript·vue.js
希望永不加班2 小时前
var局部变量类型推断的利弊
java·服务器·前端·javascript·html
threelab2 小时前
Three.js 3D 地图可视化 | 三维可视化 / AI 提示词
前端·javascript·人工智能·3d·着色器