小程序/公众号抽奖活动页面-逻辑

需求:后台返回对应的奖品数据,小程序以九宫格形式展示奖品信息,点击抽奖后转动转盘,通过接口获取奖品对应的位置,并把奖品位置高亮显示。

实现的效果:

①未抽奖

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 = searchParams
      findLuckyDrawPrize(searchParams).then(res => {
        this.lotteryItem = res.data
        this.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 = 1
          this.$toast(res.msg)
        }
      })
    },

    // 开始抽奖
    startLottery (lotteryItem) {
      // lotteryItem.positionIdx || lotteryItem.positionIdx === 0 -- 点击立即抽奖之外无效
      if (lotteryItem.positionIdx || lotteryItem.positionIdx === 0 || this.lotteryState !== 0) return
      this.setTimeoutLottery()
      this.getHitPrize()
    },

    // 抽奖转盘动画
    setTimeoutLottery () {
      this.lotteryState = 1
      this.startPosition++
      if (this.startPosition === 8) { // 转了一周
        this.startPosition = 0
        this.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 = 2
        this.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 = true
        this.receiveState = true
        this.lotteyName = res.msg
        this.sendTextMessage()
      }).catch(() => {
        this.sussessMesVisible = true
        this.receiveState = false
      })
    },

    // 领取奖品成功发送通知
    sendTextMessage () {
      if (this.selectedLottery.prizeType === '9' || !this.searchParams.notifyUrl) return
      const 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获取奖品对应的位置,返回数据结构如下:

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值