yfs/pages/other/prize_draw.vue
2025-04-09 21:48:56 +08:00

594 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<page-container title="每日免费送" :showBack="true">
<view class="prize-draw">
<view style="height: 512rpx;"></view>
<view class="choujiang">
<view style="height:52rpx;"></view>
<view class="neiquan">
<view class="grid-container">
<view class="jiangping" v-for="(item, index) in prizes"
:class="{ 'xuanzhong': currentIndex === index && !isFinalWin, 'win-flash': currentIndex === index && isFinalWin }"
:key="index">
<!-- 奖品图片将在这里显示 -->
<image :src="item.image"
style="width:95%;height:95%;margin-left: 1rpx;border-radius: 25rpx;">
</image>
</view>
</view>
</view>
<view class="draw-btn-container">
<view class="draw-btn" @click="startDraw"></view>
</view>
</view>
<view class="bottom-buttons">
<view class="button-item gzsm" @click="showRules">
<image src="https://image.zfunbox.cn/huodong/gzsm.png" style="width: 136.11rpx;height: 53.47rpx;">
</image>
</view>
<view class="button-item zjjl" @click="showRecords">
<image src="https://image.zfunbox.cn/huodong/zbtn.png" style="width: 136.11rpx;height: 53.47rpx;">
</image>
</view>
</view>
</view>
<rule-pop ref="rulePop"></rule-pop>
<!-- 中奖记录弹窗 -->
<uni-popup ref="recordsPop" type="center" mask-background-color="rgba(0,0,0,0.8)">
<view class="records-pop">
<view class="records-pop-title">中奖记录</view>
<scroll-view scroll-y class="records-pop-content">
<view v-if="prizeRecords.length > 0" class="records-list">
<view v-for="(item, index) in prizeRecords" :key="index" class="record-card">
<view class="flex row align-center"
style="width: 100%; height: 100%; justify-content: space-between;">
<view class="flex column" style="margin-left: 24rpx;">
<text style="font-size: 20rpx; color: #999999;">{{ item.title }}</text>
<text style="font-size: 20rpx; color: #999999; margin-top: 8rpx;">{{ item.time
}}</text>
</view>
</view>
</view>
</view>
<view v-else class="empty-tip">暂无中奖记录</view>
</scroll-view>
<view class="close-btn" @click="$refs.recordsPop.close()">
<image :src="$img1('common/close.png')" style="width: 48rpx;height: 48rpx;"></image>
</view>
</view>
</uni-popup>
</page-container>
</template>
<script>
import PageContainer from '@/components/page-container/page-container.vue'
export default {
components: {
PageContainer
},
data() {
return {
goods_id: 0,
isDrawing: false,
prizes: [
// 这里可以放置奖品数据
],
currentIndex: -1, // 当前选中的索引
timer: null, // 定时器
speed: 100, // 初始速度,数值越小速度越快
times: 0, // 动画运行次数计数
targetIndex: 0, // 最终中奖索引
isFinalWin: false, // 是否到达最终中奖状态
animationType: 1, // 动画类型1=顺序遍历2=8字形
path8Index: 0, // 8字形路径当前位置
animationTypes: {
SEQUENTIAL: 1, // 顺序遍历
FIGURE_EIGHT: 2 // 8字形走法
},
pathFigureEight: [0, 1, 2, 5, 4, 3, 6, 7, 8, 5, 4, 3], // 8字形路径
goods: null,
useMoney: true,
useIntegral: true,
useMoney2: true,
selectPrizes: null,
prizeRecords: [] // 中奖记录列表
};
},
onLoad() {
this.load();
},
methods: {
async load() {
let goods_id = this.$config.getAppSetting('daily_free_draw_id');
this.goods_id = goods_id;
//infinite_goodsdetail
const { status, data, msg } = await this.$request.post('infinite_goodsdetail', { goods_id: goods_id });
console.log(status, data, msg);
let { goods, goods_list } = data;
this.goods = goods;
let p = [];
goods_list.data.map(item => {
console.log(item);
p.push({
image: item.imgurl,
title: item.title,
id: item.id
});
});
this.prizes = p;
console.log(goods_list);
},
async startDraw() {
if (this.isDrawing) return;
this.isDrawing = true;
this.isFinalWin = false; // 重置中奖闪烁状态
// 清除可能存在的定时器
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
if (this.goods == null && this.goods.price == '') {
this.isDrawing = false;
this.$c.msg('抽奖失败')
return false;
}
console.log('免费');
try {
const goods_list_Id = await this.confirmSubmit([1, 1]);
let targetIndex = 0;
// console.log(goods_list_Id, targetIndex, this.prizes);
let selectPrizes = null;
this.prizes.forEach((item, index, array) => {
// console.log(item); // 当前元素
// console.log(index); // 当前索引
// console.log(array); // 数组本身
if (item.id == goods_list_Id) {
targetIndex = index;
selectPrizes = item;
}
});
this.selectPrizes = selectPrizes;
console.log(this.selectPrizes);
this.targetIndex = targetIndex;
} catch (error) {
this.$c.msg(error)
this.isDrawing = false;
return;
}
// 重置计数和速度
this.times = 0;
this.speed = 100;
this.path8Index = 0;
// 随机选择动画类型1-2之间
this.animationType = Math.floor(Math.random() * 2) + 1;
let animationName = "顺序遍历";
if (this.animationType === this.animationTypes.FIGURE_EIGHT) {
animationName = "8字形";
}
console.log('抽奖动画类型:', animationName);
// 随机生成中奖索引0-8之间
// this.targetIndex = Math.floor(Math.random() * 9);
// 开始动画
this.runAnimation();
},
runAnimation() {
this.timer = setInterval(() => {
this.times++;
// 根据不同的动画类型选择下一个格子
if (this.animationType === this.animationTypes.SEQUENTIAL) {
// 顺序遍历方式
this.currentIndex = (this.currentIndex + 1) % 9;
} else {
// 8字形路径
this.path8Index = (this.path8Index + 1) % this.pathFigureEight.length;
this.currentIndex = this.pathFigureEight[this.path8Index];
}
// 动画速度控制
if (this.times > 20) { // 前20次保持高速
if (this.times > 30) { // 30次后开始减速
this.speed += 10; // 速度递减
}
// 如果速度减到一定程度,并且当前索引接近中奖索引,则停止
if (this.speed > 300 && this.currentIndex === this.targetIndex) {
clearInterval(this.timer);
this.timer = null;
this.startWinAnimation();
return; // 重要:确保不再继续执行
}
// 只有在需要改变速度时才重新设置定时器
clearInterval(this.timer);
this.timer = null;
this.runAnimation();
}
}, this.speed);
},
startWinAnimation() {
// 开始中奖闪烁动画
this.isFinalWin = true;
// 播放闪烁效果后显示结果
setTimeout(() => {
this.showResult();
}, 1500); // 闪烁1.5秒后显示结果
},
showResult() {
// 动画结束后的操作
setTimeout(() => {
this.isDrawing = false;
if (this.selectPrizes == null) {
uni.showToast({
title: '获取奖品失败',
icon: 'none',
duration: 2000
});
return;
}
uni.showToast({
title: '恭喜获得' + this.selectPrizes.title + '奖品!',
icon: 'none',
duration: 2000
});
// 这里可以添加中奖弹窗或其他效果
}, 500);
},
// 显示规则说明
showRules() {
if (this.isDrawing) {
uni.showToast({
title: '请等待抽奖完成',
icon: 'none'
});
return;
}
this.$refs.rulePop.getRule(22, '规则说明')
},
// 显示中奖记录
showRecords() {
if (this.isDrawing) {
uni.showToast({
title: '请等待抽奖完成',
icon: 'none'
});
return;
}
// 加载中奖记录
this.loadPrizeRecords();
// 打开弹窗
this.$refs.recordsPop.open();
},
// 加载中奖记录
async loadPrizeRecords() {
try {
const { status, data, msg } = await this.$request.post('infinite_prizerecords', {
goods_id: this.goods_id
});
if (status !== 1) {
this.$c.msg(msg || '获取中奖记录失败');
return;
}
if (data && data.data && data.data.length > 0) {
// 格式化中奖记录数据
this.prizeRecords = data.data.map(item => ({
title: item.goodslist_title || '未知奖品',
time: item.addtime || ''
}));
} else {
this.prizeRecords = [];
}
} catch (error) {
console.error('加载中奖记录失败', error);
this.$c.msg('获取中奖记录失败');
}
},
async confirmSubmit([type, num, flag]) {
let url = 'infinite_ordermoney'
if (type == 1) {
url = 'infinite_orderbuy'
}
let psotData = {
goods_id: this.goods_id,
prize_num: num,
use_money_is: 1,
use_integral_is: 2,
use_money2_is: 2,
coupon_id: '',
};
let res = await this.$request.post(url, psotData);
const { status, data, msg } = res;
if (status !== 1) {
// this.$c.msg(msg);
throw msg;
}
console.log(data.order_num);
if (data.order_num != null) {
const prize = await this.getPrize(data.order_num);
console.log(prize);//goodslist_id
if (prize.goodslist_id != null) {
return prize.goodslist_id;
}
}
throw '出现异常';
},
async getPrize(order_num) {
if (!order_num) {
return
}
const res = await this.$request.post('infinite_prizeorderlog', {
order_num
});
let { status, data, msg } = res;
if (status !== 1) {
throw msg;
}
return data.data[0];
},
}
}
</script>
<style lang="scss">
.prize-draw {
background: url($baseurl+'huodong/bg.png') no-repeat center center;
background-size: 100% 100%;
height: 1495.14rpx;
width: 100vw;
.choujiang {
background: url($baseurl+'huodong/ke.png') no-repeat center center;
background-size: 100% 100%;
margin: 0px auto;
height: 829.86rpx;
width: 90%;
position: relative;
.neiquan {
width: 430rpx;
height: 465rpx;
margin: 0px auto;
padding: 15rpx;
box-sizing: border-box;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 10rpx;
width: 100%;
height: 100%;
}
.jiangping {
// background: url($baseurl+'huodong/kuang.png') no-repeat center center;
// background-size: 100% 100%;
// border: 1px dashed #75C5FF;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(255, 255, 255, 0.7);
transition: all 0.05s; // 加快过渡效果让动画更流畅
&:active {
transform: scale(0.95);
}
}
.draw-btn-container {
position: absolute;
bottom: 95rpx;
left: 50%;
transform: translateX(-50%);
width: 100%;
display: flex;
justify-content: center;
}
.draw-btn {
width: 298.61rpx;
height: 118.75rpx;
background: url($baseurl+'huodong/anniu.png') no-repeat;
background-size: 100% 100%;
font-size: 32rpx;
font-weight: bold;
//border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
//box-shadow: 0 4rpx 8rpx rgba(255, 87, 34, 0.3);
transition: all 0.3s;
&:active {
transform: scale(0.95);
//box-shadow: 0 2rpx 4rpx rgba(255, 87, 34, 0.3);
}
}
}
.xuanzhong {
background: url($baseurl+'huodong/xuanzhong.png') no-repeat !important;
background-size: 100% 100% !important;
width: 100% !important;
height: 100% !important;
}
.win-flash {
background: url($baseurl+'huodong/xuanzhong.png') no-repeat !important;
background-size: 100% 100% !important;
width: 100% !important;
height: 100% !important;
animation: win-blink 0.3s 5 alternate;
}
.bottom-buttons {
position: relative;
top: -20rpx;
width: 100%;
display: flex;
justify-content: space-evenly;
padding: 10rpx;
box-sizing: border-box;
.button-item {
width: 136.11rpx;
height: 53.47rpx;
font-size: 28rpx;
border-radius: 35rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
// box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
&:active {
transform: scale(0.95);
// background-color: rgba(255, 255, 255, 0.9);
}
}
}
.gzsm {
animation: pulse 0.3s 5 alternate;
width: 136.11rpx;
height: 53.47rpx;
}
.zjjl {
animation: pulse 0.3s 5 alternate;
width: 136.11rpx;
height: 53.47rpx;
}
@keyframes win-blink {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0.5;
transform: scale(1.05);
}
}
@keyframes pulse {
from {
opacity: 1;
}
to {
opacity: 0.8;
}
}
}
// 中奖记录弹窗样式
.records-pop {
width: 600rpx;
height: 750rpx;
background-color: #fff;
border-radius: 20rpx;
display: flex;
flex-direction: column;
position: relative;
.records-pop-title {
text-align: center;
font-size: 36rpx;
font-weight: bold;
color: #333;
padding: 30rpx 0;
border-bottom: 1px solid #eee;
}
.records-pop-content {
flex: 1;
padding: 20rpx;
.records-list {
width: 94%;
.record-item {
padding: 20rpx 0;
border-bottom: 1px solid #f5f5f5;
.prize-info {
display: flex;
flex-direction: column;
.prize-title {
font-size: 30rpx;
color: #333;
margin-bottom: 10rpx;
}
.prize-time {
font-size: 24rpx;
color: #999;
}
}
}
}
.empty-tip {
text-align: center;
color: #999;
font-size: 28rpx;
margin-top: 200rpx;
}
}
.close-btn {
position: absolute;
left: 50%;
bottom: -80rpx;
transform: translateX(-50%);
width: 48rpx;
height: 48rpx;
display: flex;
justify-content: center;
align-items: center;
}
.record-card {
width: 100%;
height: 88rpx;
background-color: #F8F8F8;
margin: 0 auto 0rpx;
border-radius: 25rpx;
}
}
</style>