示例:
使用的是一个插件可以在多种环境下运行的插件:九宫格 LuckyGrid | 基于 Js / TS / Vue / React / 微信小程序 / uni-app / Taro 的【大转盘 & 九宫格 & 老虎机】抽奖插件
安装插件
# npm 安装
npm install @lucky-canvas/vue@latest
# 或者 yarn 安装
yarn add @lucky-canvas/vue@latest
按需引入(就当前文件使用)
import { LuckyWheel, LuckyGrid } from 'vue-luck-draw'
?仅供参考,基础样式修改可以查看官网文档修改在 Vue 中使用 | 基于 Js / TS / Vue / React / 微信小程序 / uni-app / Taro 的【大转盘 & 九宫格 & 老虎机】抽奖插件
<script>
import { LuckyWheel, LuckyGrid } from "vue-luck-draw";//引入
import turntable from "../../../api/turntable";//api
import Card from "./common/card.vue";//封装的卡券列表
import tipPop from "../common/tipPop.vue";//封装的弹窗
export default {
components: {
tipPop,
Head,
LuckyWheel,
LuckyGrid,
Card,
},
data() {
return {
dataList: [
{ telephone: "157xxxx5554", offerName: "商品xxx" },
{ telephone: "177xxxx5434", offerName: "商品xxx" },
],
blocks: [
{
padding: "10px",
},
],
prizes: [],
buttons: [
{
x: 1,
y: 1,
imgs: [
{
src: require("../../../assets/img/turntable/djcj.png"), // 转盘中心开始图片
width: "100%",
top: "-2%",
},
],
},
],
// shop1:'0',
defaultConfig: {
accelerationTime: 2000,
decelerationTime: 2000,
},
timeNums: 3, //剩余次数
activeName: "a",//卡券类型
showAll: false,
serviceClose: false, //权益服务弹窗关闭按钮
popShow: false, // 弹窗控制
safeguardShow: false,
prizeLists: [],
prizeName: "", //抽中的奖品
};
},
async mounted() {
await this.getPrizeLists();
this.getPrizeCounts();
this.getAllPrizeOrderLists();
//顺序没有规律,是按九宫格顺时针执行
const arr1 = [
{
x: 0,
y: 0,
background: "#E8FCFF",
},
{
x: 1,
y: 0,
background: "#E8FCFF",
},
{
x: 2,
y: 0,
background: "#E8FCFF",
},
{
x: 2,
y: 1,
background: "#E8FCFF",
},
{//开始抽奖的位置
x: 1,
y: 1,
background: "#E8FCFF",
},
{
x: 2,
y: 2,
background: "#E8FCFF",
},
{
x: 1,
y: 2,
background: "#E8FCFF",
},
{
x: 0,
y: 2,
background: "#E8FCFF",
},
{
x: 0,
y: 1,
background: "#E8FCFF",
},
];
// 将接口请求到的奖品结果填充到固定顺序的内容
const arr = this.prizeLists.map((item, index) => {
return {
...arr1[index],
fonts: [
{
text: item.offerName,
top: "30%",
fontColor: "#474747",
fontSize: "14px",
},
],
};
});
// 将中间的坐标为(1,1)的点击抽奖删除
if (arr.length > 4) {
arr.splice(4, 1);
}
this.prizes = arr;
console.log(this.prizes);
},
computed: {},
methods: {
startCallback() {
if (this.timeNums == 0) {
return this.$dialog
.alert({
message: `本月剩余${this.timeNums}次,次月刷新`,
theme: "round-button",
})
.then(() => {
});
}
// 调用抽奖组件的play方法开始游戏
this.$refs.myLucky.play();
// 模拟调用接口异步抽奖
setTimeout(() => {
// 可以由后端返回的中奖索引控制,暂定随机数
const randomNum = parseInt(Math.floor(Math.random() * 8));
// 调用stop停止旋转并传递中奖索引
this.$refs.myLucky.stop(randomNum);
}, 3000);
},
// 抽奖结束会触发end回调
endCallback(prize) {
console.log(prize);
this.prizeName = prize.fonts[0].text;
this.popShow = true;
this.serviceClose = true;
const name = this.prizeName;
if (name =='谢谢惠顾') {
return
}else{
const datas = this.prizeLists.find((item) => item.offerName === name);
console.log(this.prizeLists, this.prizeName, datas);
delete datas.id;
const res = turntable.createPrizeOrder({
...datas,
telephone: sessionStorage.getItem("mobileNumber"),
});
console.log(res);
}
},
//关闭弹窗
handleMessageClose() {
this.popShow = false;
this.serviceClose = false;
this.getPrizeLists();
this.getPrizeCounts();
this.getAllPrizeOrderLists();
this.$refs.carda.onRefresh();
},
//查询奖池列表数据
async getPrizeLists() {
const res = await turntable.getPrizeList({
telephone: sessionStorage.getItem("mobileNumber"),
});
this.prizeLists = res.data
console.log(this.prizeLists,121);
if (this.prizeLists.length > 4) {
//将中间的坐标为(1,1)的点击抽奖赋值为空
this.prizeLists.splice(4, 0, {});
}
},
//查询当月抽奖总数
async getPrizeCounts() {
const res = await turntable.getPrizeCount({
telephone: sessionStorage.getItem("mobileNumber"),
});
this.timeNums = res.data;
},
//查询所有抽奖订单数据
async getAllPrizeOrderLists() {
const res = await turntable.getAllPrizeOrderList();
if (res.data.length !==0) {
this.dataList = res.data.map((item) => ({
telephone: item.telephone,
offerName: item.offerName,
}));
}
},
//切换卡券类型
changeTitle(name, title) {
console.log(name, title);
// 根据名字来区分类型刷新对应的卡券类型
this.$nextTick(() => {
this.$refs["card" + name].onRefresh();
});
},
//号码脱敏
desensitizePhoneNumber(phoneNumber) {
return phoneNumber.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
},
},
};
</script>
<template>
<div class="app-cantent">
<div class="turntable">
<div class="turntable-top">
<div class="turntable-num">剩余{{ timeNums }}次抽奖机会</div>
<div class="turntable-main">
<img src="../../../assets/img/turntable/bg1.png" alt="" />
<div class="prizeDraw" v-if="prizes.length > 0">
<LuckyGrid
ref="myLucky"
width="7.7rem"
height="7.7rem"
:prizes="prizes"
:blocks="blocks"
:buttons="buttons"
rows
cols
:default-config="defaultConfig"
@start="startCallback"
@end="endCallback"
/>
</div>
<div class="prizeMsg">
<div class="fl">
<van-swipe
:touchable="false"
:show-indicators="false"
vertical
:autoplay="3000"
class="fl-swiper"
>
<van-swipe-item
v-for="(item, index) in dataList"
:key="index + 1"
>
恭喜用户{{
item.telephone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2")
}}获取{{ item.offerName }}</van-swipe-item
>
</van-swipe>
</div>
</div>
</div>
</div>
<div class="turntable-bottom">
<div class="tab-content">
<div class="my-prize">
<div class="title-img">
<img src="../../../assets/img/turntable/table-title.png" alt="" />
</div>
<div class="title-header">
<div class="content-title">我的奖品</div>
</div>
</div>
<div>
<van-tabs
v-model="activeName"
line-width="20px"
@click="changeTitle"
>
<van-tab title="可使用" name="a">
<card :activeName="activeName" ref="carda"></card>
</van-tab>
<van-tab title="已使用" name="b">
<card :activeName="activeName" ref="cardb"></card>
</van-tab>
<van-tab title="已过期" name="c">
<card :activeName="activeName" ref="cardc"></card>
</van-tab>
</van-tabs>
</div>
</div>
<tipPop class="" v-show="popShow">
<div class="IDBox">
<div class="ids-title">提示</div>
<div class="ids-top" v-if="prizeName!=='谢谢惠顾'">恭喜您抽到了{{ prizeName }}</div>
<div class="ids-top" v-else>{{ prizeName }},下次再来</div>
<div class="toCopy">
<van-button round type="info" block @click="handleMessageClose()"
>{{prizeName=='谢谢惠顾'? '确认':"收下"}}</van-button
>
</div>
</div>
</tipPop>
</div>
</div>
</div>
</template>
<style scoped lang='less'>
.app-cantent {
// width: 100vw;
height: 100%;
.turntable {
height: 100%;
padding: 0 10px;
background-color: #2892ff;
background: url("@/assets/img/turntable/bg.png") no-repeat center/cover;
.turntable-top {
padding-top: 30px;
// padding-bottom: 20px;
.turntable-num {
// width: 100%;
height: 30px;
margin-top: 10px;
border-radius: 10px;
line-height: 30px;
text-align: center;
background: url("@/assets/img/turntable/yy.png") no-repeat center/cover;
}
.turntable-main {
height: 450px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
.prizeDraw {
position: absolute;
top: 23vw;
left: 9vw;
}
.prizeMsg {
width: 300px;
position: absolute;
top: 7vw;
left: 10vw;
display: flex;
justify-content: center;
.fl {
margin-top: 0px;
display: flex;
align-items: center;
justify-content: center;
height: 30px;
text-align: center;
.fl-swiper {
margin-left: 5px;
height: 22px;
line-height: 23px;
font-size: 11px;
}
}
}
.time {
position: absolute;
top: 55%;
left: 50%;
margin-left: -70px;
color: #fff;
width: 140px !important;
text-align: center;
}
}
}
.turntable-bottom {
border: 2px solid #81d3f8;
.tab-content {
width: 100%;
background-color: #fff;
.my-prize {
position: relative;
}
.title-img {
position: absolute;
width: 60%;
top: -10%;
left: 20%;
z-index: 99;
}
.title-header {
position: relative;
height: 35px;
}
.content-title {
position: absolute;
width: 20%;
top: 0;
left: 40%;
z-index: 99;
text-align: center;
color: #fff;
font-size: 16px;
font-weight: 700;
}
}
}
}
.IDBox {
.ids-title {
text-align: center;
padding: 10px 0;
font-size: 18px;
font-weight: 700;
}
.ids-top {
margin-top: 5px;
text-align: center;
padding: 10px 0;
font-size: 16px;
}
.toCopy {
margin-top: 15px;
text-align: center;
font-size: 16px;
}
}
}
</style>