需求:后台返回对应的奖品数据,小程序以九宫格形式展示奖品信息,点击抽奖后转动转盘,通过接口获取奖品对应的位置,并把奖品位置高亮显示。
实现的效果:
①未抽奖
2、抽奖中
③抽奖完成
实现代码
<template><div class="model_lottery" ref="model_lottery"><div class=lottery_block v-if="lotteryBlock && lotteryBlock.length > 1"><div class="lottery_o"v-for="(item, index) in lotteryBlock"@click="startLottery(item)":class="{lottery_btn: index === 4,_active: item.positionIdx === startPosition,disabled: lotteryState !== 0 && index === 4,is_selected: item.positionIdx === startPosition && lotteryState === 2}":key="index"><span>{{ index === 4 ? '立即抽奖' : item.prizeName }}</span></div></div><van-empty v-else description="暂无抽奖活动" /><div class="mes_model" v-if="sussessMesVisible"><div><p>{{ this.receiveState ? lotteyName : '领取失败,请重新领取' }}</p><van-button@click="submitLottery"type="info" size="small">{{ this.receiveState ? '确认' : '重新领取' }}</van-button></div></div><div class="bg_wrap" :style="{ backgroundImage: `url(${bgUrl})`}"></div></div></template><script>import axios from 'axios'import { findLuckyDrawPrize, drawLuckyDrawPrize, getHitPrizeV2 } from '@/api/allServeMethods'export default {data () {return {positionMap: { 0: 0, 1: 1, 2: 2, 3: 7, 5: 3, 6: 6, 7: 5, 8: 4 }, // 奖品位置-顺时针旋转lotteryBlock: [], // 奖品数据startPosition: -1, // 旋转的位置lotterySpeed: 160, // 抽奖转动速度rotateTimes: 1, // 当前抽奖旋转周数lotteryTimer: null,lotteryState: 0, // 抽奖状态 0 未开始 1 进行中 2 抽奖结束lotteryItem: '', // 抽奖活动数据searchParams: {},selectedLottery: '', // 抽中的奖品sussessMesVisible: false,receiveState: true,lotteyName: '',hitPosition: 0, // 抽中奖品位置bgUrl: '',getPrizeStatus: true // 获取奖品状态}},created () {document.title = '抽奖'this.findLuckyDrawPrize()},methods: {// 查询抽奖活动奖品findLuckyDrawPrize () {const searchParams = {}let serverName = location.search.substring(1)serverName = serverName.split('&')serverName.forEach(item => {if (item.split('=')[0] !== 'contextPath') {searchParams[item.split('=')[0]] = item.split('=')[1]}})this.searchParams = searchParamsfindLuckyDrawPrize(searchParams).then(res => {this.lotteryItem = res.datathis.bgUrl = res.data.backgroundImageUrl || []let lotteryBlock = res.data.prizeList || []if (lotteryBlock.length) {lotteryBlock.splice(4, 0, {})this.lotteryBlock = lotteryBlock.map((item, index) => {return {...item,prizePosition: item.prizePosition - 1, // 接口返回奖品位置从1开始index,positionIdx: this.positionMap[index]}})}console.log(this.lotteryBlock)if (this.lotteryItem.enableDraw === '0') {this.lotteryState = 1this.$toast(res.msg)}})},// 开始抽奖startLottery (lotteryItem) {// lotteryItem.positionIdx || lotteryItem.positionIdx === 0 -- 点击立即抽奖之外无效if (lotteryItem.positionIdx || lotteryItem.positionIdx === 0 || this.lotteryState !== 0) returnthis.setTimeoutLottery()this.getHitPrize()},// 抽奖转盘动画setTimeoutLottery () {this.lotteryState = 1this.startPosition++if (this.startPosition === 8) { // 转了一周this.startPosition = 0this.rotateTimes++}if (this.rotateTimes === 1) {this.lotterySpeed -= 15}if (this.rotateTimes >= 7) {this.lotterySpeed += (20 * this.lotteryBlock.find(item => item.positionIdx === this.startPosition).index / 2)}if (this.lotteryTimer) {clearTimeout(this.lotteryTimer)}let selectLottery = this.lotteryBlock.find(o => o.prizePosition === this.hitPosition)if (!this.getPrizeStatus) {clearTimeout(this.lotteryTimer)} else if (!(this.rotateTimes === 8 && selectLottery && this.startPosition === selectLottery.positionIdx)) {this.lotteryTimer = setTimeout(() => {this.setTimeoutLottery()}, this.lotterySpeed)} else {this.lotteryState = 2this.drawLuckyDrawPrize()}},// 获取抽奖奖品getHitPrize () {const searchParams = {...this.searchParams,activityId: this.lotteryItem.activityId,batchKey: this.lotteryItem.batchKey,randomKey: this.lotteryItem.randomKey}getHitPrizeV2(searchParams).then(res => {this.hitPosition = res.data - 1 // 接口返回奖品位置从1开始this.getPrizeStatus = true}).catch(() => {this.getPrizeStatus = false})},// 领取抽奖奖品drawLuckyDrawPrize () {this.selectedLottery = this.lotteryBlock.find(item => item.prizePosition === this.hitPosition)const searchParams = {...this.searchParams,activityId: this.lotteryItem.activityId,batchKey: this.lotteryItem.batchKey,prizeId: this.selectedLottery.prizeId,randomKey: this.lotteryItem.randomKey}drawLuckyDrawPrize(searchParams).then(res => {this.sussessMesVisible = truethis.receiveState = truethis.lotteyName = res.msgthis.sendTextMessage()}).catch(() => {this.sussessMesVisible = truethis.receiveState = false})},// 领取奖品成功发送通知sendTextMessage () {if (this.selectedLottery.prizeType === '9' || !this.searchParams.notifyUrl) returnconst searchParams = {touser: this.searchParams.weiCode,content: `恭喜您,抽中了奖品【${this.selectedLottery.prizeName}】`}axios.post(this.searchParams.notifyUrl, searchParams).then(res => {console.log(res)})},// 确认或重新领取submitLottery () {if (!this.receiveState) {this.drawLuckyDrawPrize()}this.sussessMesVisible = false},iframePostMessage (data) {window.addEventListener('message', function (event) {console.log(event)top.postMessage(data, '*')}, false)}}}</script><style scoped lang="less">.model_lottery {height: 100%;font-size: 14px;overflow: hidden;color: #4c4c4c;position: relative;.bg_wrap {width: 100%;height: 100%;position: absolute;left: 0;top: 0;background-size: 100% 100%;background-repeat: no-repeat no-repeat;z-index: -1;opacity: 0.3;}.lottery_block {width: 320px;height: 320px;margin: 50% calc(50% - 160px);display: flex;flex-wrap: wrap;justify-content: space-between;.lottery_o {width: ~"calc(320px / 3 - 10px)";margin: 5px;height: ~"calc(320px / 3 - 10px)";background: #f1f1f1;border-radius: 2px;position: relative;span {display: block;word-break:break-all;word-wrap:break-word;position: absolute;top: 50%;left: 5px;transform: translateY(-50%);width: ~"calc(100% - 10px)";text-align: center;}&._active {background: orange;span {color: #fff;}}&.lottery_btn {width: ~"calc(320px / 3 - 30px)";height: ~"calc(320px / 3 - 30px)";border-radius: 50%;background: orangered;margin-top: 15px;cursor: pointer;transition: .1s;span {color: #fff;letter-spacing: 2px;font-size: 14px;padding: 0;}}&.disabled {opacity: .2;}&.is_selected {animation: selectLottery 1.8s linear;animation-delay: 1s;}}}@keyframes selectLottery {0% {opacity: .1;}20% {opacity: 1;}40% {opacity: .1;}60% {opacity: 1;}80% {opacity: .1;}100% {opacity: 1;}}.mes_model {width: 60%;height: 120px;background: #fff;position: absolute;top: 50%;margin-top: -60px;left: 20%;border-radius: 4px;z-index: 999;box-shadow: 0 0 4px rgba(0,0,0,.3);text-align: center;& > div {position: absolute;top: 50%;transform: translateY(-50%);left: 0;right: 0;text-align: center;padding: 0 10px;& > p {font-size: 14px;text-align: center;padding-bottom: 10px;}}/deep/.van-button__text {letter-spacing: 2px;}}}</style>
findLuckyDrawPrize查询奖品数据,对应的数据结构如下:
getHitPrize获取奖品对应的位置,返回数据结构如下: