优惠券组件直接用 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>
相关推荐
Cutecat_2 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
dsyyyyy11012 小时前
JavaScript变量
开发语言·javascript·ecmascript
qq_422152572 小时前
PDF 加水印工具怎么选?2026 年文档版权保护方案对比
前端·pdf·github
kyriewen2 小时前
手写 Promise.all、race、any:不到 30 行代码,解决并发异步的所有姿势
前端·javascript·面试
brucelee1863 小时前
OpenClaw 浏览器控制(Chrome MCP)完整教程
前端·chrome
ct9783 小时前
React 状态管理方案深度对比
开发语言·前端·react
胡志辉的博客4 小时前
深入浅出理解浏览器事件循环:从一道输出题讲到 Chrome 源码
前端·javascript·chrome·chromium·event loop
代码不加糖4 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
懂懂tty4 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js
AI焦点4 小时前
跨越协议鸿沟:Tool Use状态机从Anthropic到OpenAI兼容体系的适配要点
前端·人工智能