更新记录

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

✨ 新增功能


平台兼容性

uni-app(3.6.13)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 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协议