123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- <template>
- <view class="content">
- <view class="luckwheel">
- <almost-lottery
- :prize-list="prizeList"
- :prize-index="prizeIndex"
- @reset-index="prizeIndex = -1"
- @draw-start="handleDrawStart"
- @draw-end="handleDrawEnd"
- @finish="handleDrawFinish"
- v-if="prizeList.length"
- />
- <view class="synums">
- 抽奖剩余次数:
- <text>2</text>
- </view>
- </view>
- <!-- 获奖人员滚动列表 -->
- <view class="hjList">
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- <view>
- 恭喜
- <text>185****5252</text>
- 获得
- <text>7</text>
- 乐豆
- </view>
- </view>
- <!-- 抽奖规则 -->
- <view class="guize">
- <view>抽奖规则</view>
- <view>
- <text>1.活动时间:</text>
- <text>2020.12.10 至 2020.12.31</text>
- </view>
- <view>
- <text>2.奖品:</text>
- <view>
- <view>一等奖 华为P40</view>
- <view>二等奖 小米电动牙刷</view>
- <view>三等奖 瑞士军刀</view>
- <view>四等奖 20乐豆</view>
- <view>五等奖 7乐豆</view>
- </view>
- </view>
- <view><text>3.抽奖条件:</text></view>
- <view>①首次注册乐色管家小程序即可获得一次抽奖机会;</view>
- <view>②分享给好友或发送到朋友圈可获得1次抽奖机会;</view>
- <view><text>4.抽奖说明:</text></view>
- <view>本活动最终解释权归XXXXXX所有。</view>
- </view>
- </view>
- </template>
- <script>
- import AlmostLottery from '@/components/almost-lottery/almost-lottery.vue';
- import { clearCacheFile } from '@/almost-utils/almost-utils.js';
- export default {
- name: 'Home',
- components: {
- AlmostLottery
- },
- data() {
- return {
- // canvas 宽高
- canvasData: {
- width: 200,
- height: 200
- },
- // 奖品数据
- prizeList: [],
- // 中奖下标
- prizeIndex: -1,
- // 中奖类目名称
- targetName: '',
- // 奖品是否设有库存
- onStock: true,
- // 是否由前端控制概率,默认不开启
- onFrontend: false,
- // 权重随机数的最大值
- weightTotal: 0,
- // 权重数组
- weightArr: []
- };
- },
- methods: {
- // 重新生成
- handleInitCanvas() {
- clearCacheFile();
- this.targetName = '';
- this.prizeList = [];
- this.getPrizeList();
- },
- // 获取奖品列表
- async getPrizeList() {
- uni.showLoading({
- title: '奖品准备中...'
- });
- let res = await this.requestPrizeList();
- console.log('获取奖品列表', res);
- if (res.ok) {
- let data = res.data;
- if (data.length) {
- // stock 奖品库存
- // weight 中奖概率,数值越大中奖概率越高
- this.prizeList = data;
- // 如果开启了前端控制概率
- // 计算出权重的总和并生成权重数组
- if (this.onFrontend) {
- this.prizeList.forEach(item => (this.weightTotal += item.weight));
- this.weightArr = this.prizeList.map(item => item.weight);
- }
- }
- } else {
- uni.hideLoading();
- uni.showToast({
- title: '获取奖品失败'
- });
- }
- },
- // 模拟请求奖品列表接口
- requestPrizeList() {
- return new Promise((resolve, reject) => {
- let requestTimer = setTimeout(() => {
- clearTimeout(requestTimer);
- requestTimer = null;
- resolve({
- ok: true,
- data: [
- {
- prizeId: 1,
- name: '0.1元现金',
- stock: 10,
- weight: 0,
- prizeImage: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/56f085e0-bcfe-11ea-b244-a9f5e5565f30.png'
- },
- {
- prizeId: 2,
- name: '10元现金',
- stock: 0,
- weight: 0,
- prizeImage: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/56f085e0-bcfe-11ea-b244-a9f5e5565f30.png'
- },
- { prizeId: 3, name: '5元话费', stock: 1, weight: 0 },
- { prizeId: 4, name: '50元现金', stock: 0, weight: 0 },
- { prizeId: 5, name: '1卷抽纸', stock: 3, weight: 0 },
- { prizeId: 6, name: '0.2元现金', stock: 8, weight: 0 },
- { prizeId: 7, name: '谢谢参与', stock: 100, weight: 0 },
- { prizeId: 8, name: '100金币', stock: 100, weight: 0 }
- ]
- });
- }, 2000);
- });
- },
- // 本次抽奖开始
- handleDrawStart() {
- this.targetName = '';
- let list = [...this.prizeList];
- // 模拟请求
- let stoTimer = setTimeout(() => {
- clearTimeout(stoTimer);
- stoTimer = null;
- // 判断是否由前端控制概率
- // 前端控制概率的情况下,需要拿到最接近随机权重且大于随机权重的值
- // 后端控制概率的情况下,通常会直接返回 prizeId
- if (this.onFrontend) {
- if (!this.weightTotal) {
- console.warn('###当前已开启前端控制中奖概率,但是奖品数据列表中的 weight 参数似乎配置不正确###');
- return;
- }
- console.warn('###当前处于前端控制中奖概率,安全起见,强烈建议由后端控制###');
- console.log('当前权重总和为 =>', this.weightTotal);
- // 注意这里使用了 Math.ceil,如果某个权重的值为 0,则始终无法中奖
- let weight = Math.ceil(Math.random() * this.weightTotal);
- console.log('本次权重随机数 =>', weight);
- // 生成大于等于随机权重的数组
- let tempMaxArrs = [];
- list.forEach(item => {
- if (item.weight >= weight) {
- tempMaxArrs.push(item.weight);
- }
- });
- // 如果大于随机权重的数组有值,先对这个数组排序然后取值
- // 反之新建一个临时的包含所有权重的已排序数组,然后取值
- if (tempMaxArrs.length) {
- tempMaxArrs.sort((a, b) => a - b);
- this.prizeIndex = this.weightArr.indexOf(tempMaxArrs[0]);
- } else {
- let tempWeightArr = [...this.weightArr];
- tempWeightArr.sort((a, b) => a - b);
- this.prizeIndex = this.weightArr.indexOf(tempWeightArr[tempWeightArr.length - 1]);
- }
- } else {
- console.warn('###当前处于模拟的随机中奖概率,实际场景中,中奖概率应由后端控制###');
- // 这里随机产生的 prizeId 是模拟后端返回的 prizeId
- let prizeId = Math.floor(Math.random() * list.length + 1);
- list.forEach((item, index) => {
- if (item.prizeId === prizeId) {
- // 中奖下标
- this.prizeIndex = index;
- }
- });
- }
- console.log('本次抽中奖品 =>', this.prizeList[this.prizeIndex].name);
- if (this.onStock) {
- console.log('本次奖品库存 =>', this.prizeList[this.prizeIndex].stock);
- }
- }, 200);
- },
- // 本次抽奖结束
- handleDrawEnd() {
- // 旋转结束后,可以执行拿到结果后的逻辑
- let prizeName = this.prizeList[this.prizeIndex].name;
- if (this.onStock) {
- let prizeStock = this.prizeList[this.prizeIndex].stock;
- this.targetName = prizeName === '谢谢参与' ? prizeName : prizeStock ? `恭喜您,获得 ${prizeName}` : '很抱歉,您来晚了,当前奖品已无库存';
- }else{
- this.targetName = prizeName === '谢谢参与' ? prizeName : `恭喜您,获得 ${prizeName}`;
- }
- console.log(this.targetName)
- },
- // 抽奖转盘绘制完成
- handleDrawFinish(res) {
- console.log('抽奖转盘绘制完成', res);
- uni.showToast({
- title: res.msg,
- duration: 2000,
- mask: true,
- icon: 'none'
- });
- }
- },
- onLoad() {
- // 模拟请求奖品数据
- this.getPrizeList();
- },
- onUnload() {
- uni.hideLoading();
- }
- };
- </script>
- <style lang="less">
- .content {
- width: 100%;
- background: linear-gradient(#00287a, #002268);
- .luckwheel {
- padding: 30rpx 0;
- .synums {
- font-size: 28rpx;
- color: #fff;
- padding-top: 20rpx;
- text-align: center;
- text {
- color: #ffff00;
- margin-left: 6rpx;
- }
- }
- }
- .hjList {
- height: 30vh;
- overflow: auto;
- > view {
- width: 70%;
- margin: 10rpx auto;
- background: #acdbff;
- padding: 6rpx;
- border-radius: 50rpx;
- text-align: center;
- font-size: 24rpx;
- }
- }
- .guize {
- color: #ffffff;
- padding: 30rpx 0;
- width: 70%;
- margin: 0 auto;
- align-items: left;
- font-size: 24rpx;
- > view {
- display: flex;
- align-items: center;
- padding: 10rpx 0;
- width: 100%;
- }
- }
- }
- </style>
|