更新记录

1.0.0(2025-11-06) 下载此版本

✨ 新增功能


平台兼容性

uni-app(3.6.13)

Vue2 Vue2插件版本 Vue3 Vue2插件版本 Chrome Chrome插件版本 Safari Safari插件版本 app-vue app-vue插件版本 app-nvue app-nvue插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本
1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 16.0 1.0.0 18 1.0.0 1.0.0
微信小程序 微信小程序插件版本 支付宝小程序 支付宝小程序插件版本 抖音小程序 抖音小程序插件版本 百度小程序 百度小程序插件版本 快手小程序 快手小程序插件版本 京东小程序 京东小程序插件版本 鸿蒙元服务 鸿蒙元服务插件版本 QQ小程序 QQ小程序插件版本 飞书小程序 飞书小程序插件版本 快应用-华为 快应用-华为插件版本 快应用-联盟 快应用-联盟插件版本
1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0 1.0.0

uni-app x(3.6.13)

Chrome Chrome插件版本 Safari Safari插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本 微信小程序 微信小程序插件版本
1.0.0 1.0.0 16.0 1.0.0 18 1.0.0 1.0.0 1.0.0

其他

多语言 暗黑模式 宽屏模式

hy-lotteryGrid 九宫格跑马灯抽奖组件

功能强大、高度可定制的九宫格跑马灯抽奖组件,支持多平台、多种自定义配置

Version License Platform

✨ 特性

  • 🎯 灵活配置 - 支持自定义格子数量(9宫格、16宫格等)
  • 🎨 高度可定制 - 丰富的样式配置,支持插槽自定义
  • 📊 概率控制 - 精确的概率算法,支持服务端控制
  • 🎬 流畅动画 - 可配置的加速减速效果,视觉体验流畅
  • 🔊 音效系统 - 内置音效管理,支持自定义音效
  • 📱 多端支持 - 完美支持 H5、小程序、App 等多个平台
  • 🎮 交互友好 - 支持多次抽奖、结果确认等多种交互模式
  • 💾 记录管理 - 内置中奖记录存储功能
  • 🔒 类型安全 - 完整的 TypeScript 类型定义

📦 安装

方式一:uni_modules(推荐)

在 HBuilderX 中,通过插件市场导入 hy-lotteryGrid 插件。

方式二:npm 安装

npm install hy-lotteryGrid

🚀 快速开始

基础用法

<template>
  <view class="container">
    <hy-lottery-grid
      title="幸运大抽奖"
      :prizeList="prizes"
      @draw-end="onDrawEnd"
      @confirm="onConfirm"
    />
  </view>
</template>

<script>
export default {
  data() {
    return {
      prizes: [
        { name: '一等奖', image: '/static/prize1.png', probability: 0.1 },
        { name: '二等奖', image: '/static/prize2.png', probability: 0.2 },
        { name: '三等奖', image: '/static/prize3.png', probability: 0.3 },
        { name: '谢谢参与', image: '/static/thanks.png', probability: 0.4 }
      ]
    }
  },
  methods: {
    onDrawEnd(result) {
      console.log('抽奖结束:', result.prize.name)
    },
    onConfirm(result) {
      console.log('确认结果:', result.prize.name)
    }
  }
}
</script>

高级用法

<template>
  <hy-lottery-grid
    title="超级抽奖"
    :gridCount="9"
    :prizeList="prizes"
    :speed="100"
    :circleCount="3"
    :enableMultipleDraw="true"
    :enableSound="true"
    :showProbability="true"
    :beforeDraw="beforeDraw"
    @draw-start="onDrawStart"
    @draw-end="onDrawEnd"
  >
    <!-- 自定义奖品显示 -->
    <template v-slot:prize="{ item, index, active }">
      <view class="custom-prize" :class="{ 'active': active }">
        <image :src="item.image" class="prize-img" />
        <text class="prize-text">{{ item.name }}</text>
      </view>
    </template>

    <!-- 自定义抽奖按钮 -->
    <template v-slot:center-btn="{ disabled }">
      <view class="custom-btn" :class="{ 'disabled': disabled }">
        <text>点我抽奖</text>
      </view>
    </template>

    <!-- 自定义结果弹窗 -->
    <template v-slot:result="{ result }">
      <view class="custom-result">
        <image :src="result.image" class="result-img" />
        <text class="result-title">恭喜获得</text>
        <text class="result-name">{{ result.name }}</text>
      </view>
    </template>
  </hy-lottery-grid>
</template>

<script>
export default {
  data() {
    return {
      prizes: [
        { 
          name: 'iPhone 15 Pro', 
          image: '/static/iphone.png', 
          probability: 0.01,
          description: '256GB 蓝色钛金属',
          value: 8999
        },
        { 
          name: '100元红包', 
          image: '/static/money.png', 
          probability: 0.1,
          description: '现金红包'
        },
        { 
          name: '10元优惠券', 
          image: '/static/coupon.png', 
          probability: 0.3,
          description: '全场通用'
        },
        { 
          name: '谢谢参与', 
          image: '/static/thanks.png', 
          probability: 0.59,
          description: '再接再厉'
        }
      ]
    }
  },
  methods: {
    // 抽奖前置检查
    async beforeDraw() {
      // 检查用户是否有抽奖次数
      const hasChance = await this.checkDrawChance()
      if (!hasChance) {
        uni.showToast({ title: '抽奖次数不足', icon: 'none' })
        return false
      }
      return true
    },

    async checkDrawChance() {
      // 这里可以调用后端接口检查
      return true
    },

    onDrawStart() {
      console.log('开始抽奖')
    },

    onDrawEnd(result) {
      console.log('抽奖结束:', result)
      // 可以在这里上报中奖结果到服务器
      this.reportResult(result)
    },

    async reportResult(result) {
      // 上报到服务器
      await uni.request({
        url: '/api/lottery/report',
        method: 'POST',
        data: {
          prizeId: result.prize.id,
          prizeName: result.prize.name
        }
      })
    }
  }
}
</script>

📖 API 文档

Props

参数 说明 类型 默认值 必填
title 抽奖标题 String ''
gridCount 格子数量(必须是平方数:9、16、25等) Number 9
prizeList 奖品列表 Array<PrizeItem> []
gridSize 网格尺寸(rpx) Number 600
itemStyle 格子自定义样式 Object {}
activeStyle 激活状态样式 Object {}
titleStyle 标题自定义样式 Object {}
containerStyle 容器自定义样式 Object {}
centerBtnStyle 中心按钮自定义样式 Object {}
resultStyle 结果弹窗自定义样式 Object {}
confirmBtnStyle 确认按钮自定义样式 Object {}
againBtnStyle 再抽一次按钮自定义样式 Object {}
speed 初始转动速度(ms) Number 100
accelerateSpeed 加速度(ms,每步减少) Number 10
decelerateSpeed 减速度(ms,每步增加) Number 30
circleCount 转动圈数 Number 3
animationDuration 动画持续时间(ms) Number 300
enableMultipleDraw 是否允许多次抽奖 Boolean false
autoStart 是否自动开始 Boolean false
disabled 是否禁用 Boolean false
showProbability 是否显示概率 Boolean false
enableSound 是否启用音效 Boolean false
drawBtnText 抽奖按钮文字 String '开始抽奖'
drawingText 抽奖中按钮文字 String '抽奖中...'
resultTitle 结果标题 String '恭喜您获得'
confirmBtnText 确认按钮文字 String '确定'
againBtnText 再抽一次按钮文字 String '再抽一次'
maskClosable 点击遮罩是否关闭结果弹窗 Boolean false
prizeIndexMap 奖品索引映射关系(高级配置) Array []
beforeDraw 开始抽奖前的钩子函数 Function null
customDrawLogic 自定义抽奖逻辑(用于服务器控制) Function null

PrizeItem

奖品项数据结构:

interface PrizeItem {
  name: string              // 奖品名称(必填)
  image?: string            // 奖品图片URL
  icon?: string             // 奖品图标URL(别名)
  probability: number       // 中奖概率(0-1之间,必填)
  description?: string      // 奖品描述
  id?: string | number      // 奖品ID
  color?: string            // 奖品名称颜色
  stock?: number            // 奖品库存数量
  value?: number            // 奖品价值
  [key: string]: any        // 其他自定义数据
}

Events

事件名 说明 回调参数
draw-start 开始抽奖时触发 -
draw-end 抽奖结束时触发 result: DrawResult
confirm 确认结果时触发 result: DrawResult
item-click 格子点击时触发 data: { item: PrizeItem, index: number }

DrawResult

抽奖结果数据结构:

interface DrawResult {
  prize: PrizeItem    // 中奖奖品信息
  index: number       // 奖品在列表中的索引
}

Slots

插槽名 说明 作用域数据
prize 奖品格子内容 { item: PrizeItem, index: number, active: boolean }
center-btn 中心抽奖按钮 { disabled: boolean }
result 结果弹窗内容 { result: PrizeItem }

Methods

通过 ref 调用组件方法:

<hy-lottery-grid ref="lottery" />

<script>
export default {
  methods: {
    start() {
      this.$refs.lottery.startLottery()
    },
    reset() {
      this.$refs.lottery.reset()
    }
  }
}
</script>
方法名 说明 参数 返回值
startLottery 开始抽奖 - -
reset 重置抽奖状态 - -
confirmResult 确认结果 - -
drawAgain 再抽一次 - -

🎯 使用场景

1. 服务器控制中奖

<template>
  <hy-lottery-grid
    :prizeList="prizes"
    :customDrawLogic="serverDraw"
    @draw-end="onDrawEnd"
  />
</template>

<script>
export default {
  data() {
    return {
      prizes: [...]
    }
  },
  methods: {
    // 服务器控制中奖逻辑
    async serverDraw() {
      const res = await uni.request({
        url: '/api/lottery/draw',
        method: 'POST'
      })
      // 返回服务器指定的中奖奖品索引
      return res.data.prizeIndex
    },

    onDrawEnd(result) {
      // 抽奖完成后处理
      console.log('中奖:', result.prize.name)
    }
  }
}
</script>

2. 限制抽奖次数

<template>
  <hy-lottery-grid
    :prizeList="prizes"
    :beforeDraw="checkDrawTimes"
    :disabled="drawTimes <= 0"
  />
  <view>剩余抽奖次数:{{ drawTimes }}</view>
</template>

<script>
export default {
  data() {
    return {
      prizes: [...],
      drawTimes: 3
    }
  },
  methods: {
    async checkDrawTimes() {
      if (this.drawTimes <= 0) {
        uni.showToast({
          title: '抽奖次数已用完',
          icon: 'none'
        })
        return false
      }
      this.drawTimes--
      return true
    }
  }
}
</script>

3. 中奖记录管理

<script>
import { saveLotteryRecord, getLotteryRecords } from '@/uni_modules/hy-lotteryGrid/js_sdk/utils.js'

export default {
  data() {
    return {
      records: []
    }
  },
  mounted() {
    this.loadRecords()
  },
  methods: {
    onDrawEnd(result) {
      // 保存中奖记录
      saveLotteryRecord({
        prizeName: result.prize.name,
        prizeImage: result.prize.image
      })

      // 重新加载记录
      this.loadRecords()
    },

    loadRecords() {
      this.records = getLotteryRecords()
    }
  }
}
</script>

🎨 样式定制

自定义颜色主题

<hy-lottery-grid
  :containerStyle="{
    background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
  }"
  :itemStyle="{
    backgroundColor: '#f5f5f5',
    borderRadius: '16rpx'
  }"
  :activeStyle="{
    backgroundColor: '#ff6b6b',
    transform: 'scale(0.9)',
    boxShadow: '0 0 30rpx rgba(255, 107, 107, 0.8)'
  }"
  :centerBtnStyle="{
    background: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)'
  }"
/>

调整网格大小

<hy-lottery-grid
  :gridSize="750"
  :gridCount="16"
/>

⚠️ 注意事项

  1. 概率配置:所有奖品的 probability 总和应该为 1
  2. 格子数量gridCount 必须是平方数(9、16、25等)
  3. 音效文件:启用音效前需要准备音效文件并配置路径
  4. 服务器控制:使用 customDrawLogic 时,需要返回有效的奖品索引
  5. 性能优化:大量奖品时,建议使用懒加载图片

📝 更新日志

查看 CHANGELOG.md

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📄 License

MIT License

💬 技术支持

如有问题,欢迎通过以下方式联系:

  • 插件市场评论区
  • GitHub Issues
  • QQ群:[待补充]

Made with ❤️ by HY Team

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议