优惠券组件直接用 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>
相关推荐
To_OC13 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
腻害兔13 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
不好听61313 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus14 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
前端小李子14 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech14 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
小林ixn15 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧16 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展
窝子面17 小时前
手搓最简前后端协作-node
javascript·数据库