You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1453 lines
36 KiB

<template>
<div class="wheel-container">
<!-- 顶部区域 -->
<div class="top-section">
<div class="expire-time">财富金轮到期时间{{ expireTime }}</div>
<div class="top-right">
<div class="icon-item" @click="toggleHistory">
<img :src="historyImg" class="history-icon" alt="历史记录">
<span class="icon-text">历史记录</span>
</div>
<div class="icon-item" @click="handleRuleClick">
<img :src="ruleImg" class="rule-icon" alt="活动规则">
<span class="icon-text">活动规则</span>
</div>
</div>
</div>
<!-- 主标题图片 -->
<img :src="titleImg" class="title-img" alt="转动财富金轮 开启财富人生">
<!-- 转盘区域 - 完全重构 -->
<div class="wheel-section">
<div class="wheel-wrapper">
<!-- 转盘图片 -->
<img
:src="wheelImg"
class="wheel-img"
alt="财富金轮"
>
<!-- 指针系统 - 使用绝对精确的定位 -->
<div class="pointer-system">
<!-- 中心固定点 - 作为旋转参考 -->
<div class="rotation-center"></div>
<!-- 指针图片 - 使用精确的transform-origin -->
<img
src="../../assets/img/wealthGoldenWheel/pointer.png"
class="pointer-img"
:class="{ spinning: isSpinning }"
:style="{ transform: `rotate(${pointerRotation}deg)` }"
alt="指针"
>
<!-- 指针中心盖 -->
<img :src="pointerCoverImg" class="pointer-cover-img" alt="指针盖">
</div>
</div>
</div>
<!-- 剩余次数 -->
<div class="remaining-section">
<img :src="remainingBgImg" class="remaining-bg" alt="今日剩余">
<span class="remaining-text">今日剩余{{ remainingTimes }}</span>
</div>
<!-- 转动按钮 -->
<button
class="spin-btn"
:disabled="isSpinning || showPrizeModal || showRuleModal || isFirstVisit"
@click="handleSpin"
>
<img
:src="(remainingTimes > 0 && !showPrizeModal && !showRuleModal && !isFirstVisit) ? spinBtnImg : disabledSpinBtnImg"
alt="转动金轮"
class="spin-btn-img"
>
</button>
<!-- 中奖弹窗 -->
<div class="prize-modal" v-if="showPrizeModal">
<div class="modal-overlay" @click="closeModal"></div>
<div class="modal-content">
<img :src="modalBgImg" class="modal-bg" alt="弹窗背景">
<!-- 右上角关闭按钮 -->
<button class="close-modal" @click="closeModal">
<img :src="closeBtnImg" alt="关闭弹窗">
</button>
<div class="prize-info">
<div class="prize-title">{{ prizeMessage }}</div>
<div class="prize-amount-wrapper">
<img :src="prizeAmountImg" class="prize-amount-bg" alt="奖品数量背景">
<div class="prize-amount" :class="{ scrolling: shouldScroll }">
<span class="prize-text" v-if="shouldScroll">
{{ prizeAmount }}&nbsp;&nbsp;&nbsp;{{ prizeAmount }}
</span>
<span v-else>{{ prizeAmount }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- 剩余次数为0时的提示弹窗 -->
<div class="no-times-modal" v-if="showNoTimesModal">
<div class="modal-overlay" @click="closeNoTimesModal"></div>
<div class="no-times-content">
<img :src="noTimesImg" class="no-times-bg" alt="今日次数已用完">
</div>
</div>
<!-- 活动规则弹窗 -->
<div class="rule-modal" v-if="showRuleModal">
<div class="modal-overlay" @click="closeRuleModal"></div>
<div class="rule-content">
<img :src="ruleBgImg" class="rule-bg" alt="活动规则背景">
<!-- 右上角关闭按钮 -->
<button class="close-rule-btn" @click="closeRuleModal">
<img :src="closeRuleBtnImg" alt="关闭活动规则">
</button>
<div class="rule-text">
<div class="rule-line">1.在财富金轮使用期限内每天可以转动一次</div>
<div class="rule-line">2.通过财富金轮可以获得免费Tonken和背包礼物等</div>
<div class="rule-line">3.用户通过财富金轮获得的物品以最终展示结果为准</div>
<div class="rule-line">4.Homily Link平台拥有最终解释权</div>
</div>
</div>
</div>
<!-- 首次访问活动规则弹窗 -->
<div class="rule-modal" v-if="isFirstVisit">
<div class="modal-overlay" @click="closeFirstVisitModal"></div>
<div class="rule-content">
<img :src="ruleBgImg" class="rule-bg" alt="活动规则背景">
<!-- 右上角关闭按钮 -->
<button class="close-rule-btn" @click="closeFirstVisitModal">
<img :src="closeRuleBtnImg" alt="关闭活动规则">
</button>
<div class="rule-text">
<div class="rule-line">1.在财富金轮使用期限内每天可以转动一次</div>
<div class="rule-line">2.通过财富金轮可以获得免费Tonken和背包礼物等</div>
<div class="rule-line">3.用户通过财富金轮获得的物品以最终展示结果为准</div>
<div class="rule-line">4.Homily Link平台拥有最终解释权</div>
</div>
</div>
</div>
<!-- 右侧历史记录侧板 -->
<div class="history-record" v-if="historyRecordListVisible">
<img src="../../assets/img/wealthGoldenWheel/foldUpIcon.png"
class="fold-up" @click="toggleHistory" />
<div class="history-title">中奖记录</div>
<div style="margin-left: 45px; margin-top: 18px;">
<button v-for="item in options" :key="item.value"
:style="{
backgroundColor: selected === item.value ? '#0003bf' : '#7475b2',
borderColor: selected === item.value ? '#0003bf' : '#7475b2',
color: '#fff',
marginRight: '24px',
padding: '6px 18px',
borderRadius: '8px',
border: 'none',
cursor: 'pointer'
}"
@click="changeTypeHistoryList(item)">
{{ item.label }}
</button>
</div>
<div class="history-contents">
<!-- nowMonths(当前年) -->
<div v-if="nowMonths && nowMonths.length > 0" style="padding-left:45px;">
<div v-for="m in nowMonths" :key="m.month">
<div class="month-row" @click="toggleMonthNow(m)">
<span class="month-text">{{ m.month }}</span>
<span class="month-caret">{{ m.open ? '▼' : '▲' }}</span>
</div>
<div v-if="m.open">
<div v-if="!m.records || m.records.length === 0" class="empty-month">暂无记录</div>
<div v-for="(item, idx) in m.records" :key="item.id || idx" class="history-record-item">
<div class="left">
<div class="title" v-if="selected == 1">
<span class="circle"></span>财富金轮—{{ item.type }}
</div>
<div class="title" v-else-if="selected == 3">
<span class="circle"></span>{{ item.type }}
</div>
<div class="time">{{ item.time }}</div>
</div>
<div class="right">
<span class="token">+ {{ item.amount }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- 历史年列表 -->
<div v-if="years && years.length > 0">
<div v-for="y in years" :key="y.year">
<div class="year-header" @click="toggleYear(y)" style="padding-left:14px;">
<span class="year-text">{{ y.year }}年</span>
<span class="year-caret">{{ y.expanded ? '▼' : '▲' }}</span>
</div>
<div v-if="y.expanded" class="months" style="padding-left:45px;">
<div v-for="m in y.months" :key="m.month">
<div class="month-row" @click="toggleMonth(m)">
<span class="month-text">{{ m.month }}</span>
<span class="month-caret">{{ m.open ? '▼' : '▲' }}</span>
</div>
<div v-if="m.open">
<div v-if="!m.records || m.records.length === 0" class="empty-month">暂无记录</div>
<div v-for="(item, idx) in m.records" :key="item.id || idx" class="history-record-item">
<div class="left">
<div class="title" v-if="selected == 1">
<span class="circle"></span>财富金轮—{{ item.type }}
</div>
<div class="title" v-else-if="selected == 3">
<span class="circle"></span>{{ item.type }}
</div>
<div class="time">{{ item.time }}</div>
</div>
<div class="right">
<span class="token">+ {{ item.amount }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 底部装饰 -->
<div class="history-decoration" aria-hidden="true"></div>
</div>
</div>
</template>
<script>
import api from '@/utils/common.js'
import { permissionApi, lotteryApi,historyApi } from '@/api/goldenWheel'
export default {
name: 'FortuneWheel',
data() {
return {
// 图片资源
historyImg: 'https://d31zlh4on95l9h.cloudfront.net/images/aed693de6beb9faae015fd0628c4f052.png',
ruleImg: 'https://d31zlh4on95l9h.cloudfront.net/images/9a3f7680b29e31b60151cf562c0d43cb.png',
titleImg: 'https://d31zlh4on95l9h.cloudfront.net/images/a87d19806fed47b7fdf18d4b5dd70e65.png',
wheelImg: 'https://d31zlh4on95l9h.cloudfront.net/images/caaf77a490be46c56ae824d2d9aa72f4.png',
pointerCoverImg: 'https://d31zlh4on95l9h.cloudfront.net/images/19f2ea90e2560330089214e88eff04b5.png',
remainingBgImg: 'https://d31zlh4on95l9h.cloudfront.net/images/a43f0c383d55fc56b34768f039a401a8.png',
spinBtnImg: 'https://d31zlh4on95l9h.cloudfront.net/images/11b749e0fd4b08238980b74c6e80b2e6.png',
disabledSpinBtnImg: 'https://d31zlh4on95l9h.cloudfront.net/images/9b7383c1f80bb32a279791879947791a.png',
modalBgImg: 'https://d31zlh4on95l9h.cloudfront.net/images/f75ce9ca2703662fd3176dd0493f6d7b.png',
prizeAmountImg: 'https://d31zlh4on95l9h.cloudfront.net/images/878b8ea0c78bcafdaf4f6eb63a0b2eef.png',
closeBtnImg: 'https://d31zlh4on95l9h.cloudfront.net/images/453475456dad8e6832e9904c901c1274.png',
noTimesImg: 'https://d31zlh4on95l9h.cloudfront.net/images/a67e8b3de6e441af7bcb8fbbb2153ec2.png',
ruleBgImg: 'https://d31zlh4on95l9h.cloudfront.net/images/9f585ee0ab251f348a4568355ad36816.png',
closeRuleBtnImg: 'https://d31zlh4on95l9h.cloudfront.net/images/ca2ddd411ffb85968bc261382477c984.png',
// 数据
token: '',
expireTime: '',
remainingTimes: 0,
isSpinning: false,
showPrizeModal: false,
showNoTimesModal: false,
showRuleModal: false,
isFirstVisit: true,
pointerRotation: -21.5, // 指针初始旋转角度
noTimesTimer: null,
prizeMessage: '',
prizeAmount: '',
textWidth: 0,
targetPointerRotation: 0, // 指针目标旋转角度
historyRecordListVisible: false,
nowMonths: [],
years: [],
selected: 1,
options: [
{ label: 'Token', value: 1 },
{ label: '卡券', value: 3 }
],
}
},
computed: {
// 判断是否需要滚动展示
shouldScroll() {
if (!this.prizeAmount) return false;
// 判断中文字符数量
const chineseCharCount = (this.prizeAmount.match(/[\u4e00-\u9fa5]/g) || []).length;
// 判断英文字母数量
const englishCharCount = (this.prizeAmount.match(/[a-zA-Z]/g) || []).length;
// 汉字超过7个或字母超过15个时启用滚动
return chineseCharCount > 7 || englishCharCount > 15;
}
},
mounted() {
this.getTokenFromURL();
this.fetchWheelInfo();
// 预加载图片
this.preloadImages();
api.packageFun('JWsetTitle', function () {}, {
platform: 5,
title: "财富金轮"
})
},
methods: {
toggleHistory() {
this.historyRecordListVisible = !this.historyRecordListVisible
this.selected = 1
if (this.historyRecordListVisible) {
this.loadHistoryRecord()
}
},
changeTypeHistoryList(item) {
this.selected = item.value
this.loadHistoryRecord()
},
async loadHistoryRecord() {
try {
const res = await historyApi({
token: this.token,
type: this.selected
});
if (res.code === 200) {
const now_year = res.data.now_year || []
const last_year_list = res.data.last_year_list || []
this.nowMonths = (Array.isArray(now_year) ? now_year : []).map((m, idx) => ({
month: m.month,
open: idx === 0,
records: (m.list || []).map((r, ridx) => ({
id: ridx,
time: r.time,
amount: parseFloat(r.num),
type: r.name
}))
}))
this.years = (Array.isArray(last_year_list) ? last_year_list : []).map((y) => ({
year: y.year,
expanded: false,
months: (y.list || []).map((m) => ({
month: m.month,
open: false,
records: (m.list || []).map((r, ridx) => ({
id: ridx,
time: r.time,
amount: parseFloat(r.num),
type: r.name
}))
}))
}))
} else {
this.nowMonths = []
this.years = []
}
} catch (err) {
this.nowMonths = []
this.years = []
}
},
toggleMonthNow(m) {
m.open = !m.open
},
toggleYear(y) {
y.expanded = !y.expanded
},
toggleMonth(m) {
m.open = !m.open
},
// 预加载图片以提高性能
preloadImages() {
const images = [
this.historyImg, this.ruleImg, this.titleImg, this.wheelImg,
this.pointerCoverImg, this.remainingBgImg,
this.spinBtnImg, this.disabledSpinBtnImg, this.modalBgImg,
this.prizeAmountImg, this.closeBtnImg, this.noTimesImg,
this.ruleBgImg, this.closeRuleBtnImg
];
images.forEach(src => {
const img = new Image();
img.src = src;
});
},
getTokenFromURL() {
// 首先尝试从URL获取token
const urlParams = new URLSearchParams(window.location.search);
const tokenParam = urlParams.get('token');
if (tokenParam) {
// 如果URL中有token,保存到localStorage并设置到组件
const decodedToken = decodeURIComponent(tokenParam);
localStorage.setItem('fortuneWheelToken', decodedToken);
this.token = decodedToken;
} else {
// 如果URL中没有token,尝试从localStorage获取
const storedToken = localStorage.getItem('fortuneWheelToken');
if (storedToken) {
this.token = storedToken;
} else {
console.log('URL和localStorage中都没有找到token');
// 这里可以添加处理没有token的情况,比如跳转到登录页
}
}
},
// 调用API获取财富金轮信息
fetchWheelInfo() {
if (!this.token) {
console.error('Token为空,无法调用API');
return;
}
permissionApi({ token: this.token }).then(res => {
if(res.code === 200){
this.expireTime = res.data.deadline;
this.remainingTimes = res.data.count;
} else {
console.error('API返回错误:', res.msg);
}
}).catch(error => {
console.error('API调用失败:', error);
});
},
// 调用抽奖API获取奖品信息
async fetchPrizeInfo() {
if (!this.token) {
console.error('Token为空,无法调用抽奖API');
return false;
}
try {
// 调用抽奖API
const res = await lotteryApi({ token: this.token });
if(res.code === 200){
// 解析API返回的字符串数据
const prizeData = res.data;
// 关键修改:按照第一个空格分割字符串
const firstSpaceIndex = prizeData.indexOf(' ');
if (firstSpaceIndex !== -1) {
// 第一个空格前面的部分作为prizeMessage
this.prizeMessage = prizeData.substring(0, firstSpaceIndex);
// 第一个空格后面的部分作为prizeAmount
this.prizeAmount = prizeData.substring(firstSpaceIndex + 1);
} else {
// 如果没有空格,整个字符串作为prizeMessage,prizeAmount为空
this.prizeMessage = prizeData;
this.prizeAmount = '';
}
// 抽奖API执行完成后,查询最新的剩余次数
await this.fetchWheelInfo();
return true;
} else {
console.error('抽奖API返回错误:', res.msg);
// 设置默认值
this.prizeMessage = '抽奖失败';
this.prizeAmount = '请重试';
// 即使抽奖失败,也查询最新的剩余次数
await this.fetchWheelInfo();
return false;
}
} catch (error) {
console.error('抽奖API调用失败:', error);
// 设置默认值
this.prizeMessage = '网络错误';
this.prizeAmount = '请重试';
// 即使抽奖失败,也查询最新的剩余次数
await this.fetchWheelInfo();
return false;
}
},
// 计算随机停止位置
calculateRandomStop() {
// 转盘有8个区域,每个区域45度
const sectorDegrees = 45;
// 随机选择一个区域 (0-7)
const randomSector = Math.floor(Math.random() * 8);
// 计算目标角度:从初始位置(-21.5度)到选中区域的中心
// 每个区域中心的角度 = 区域索引 * 45度 - 22.5度
const targetAngle = randomSector * sectorDegrees - 21.5;
// 计算需要旋转的总角度(确保多转几圈)
// 从当前位置旋转到目标位置,加上多转的圈数(3-5圈)
const extraRotations = 3 + Math.floor(Math.random() * 3); // 4-5圈
const extraDegrees = extraRotations * 360;
// 计算最终旋转角度
// 从当前角度旋转到目标角度,加上额外的圈数
// 注意:需要确保旋转方向正确
let rotationNeeded = targetAngle - this.pointerRotation;
// 如果旋转角度为负,加上360度使其为正
if (rotationNeeded < 0) {
rotationNeeded += 360;
}
// 加上额外的圈数
return this.pointerRotation + rotationNeeded + extraDegrees;
},
// 处理转动
async handleSpin() {
if (this.showRuleModal || this.isFirstVisit || this.isSpinning) return;
// 先查询剩余次数
try {
if (this.remainingTimes <= 0) {
this.showNoTimesModal = true;
if (this.noTimesTimer) {
clearTimeout(this.noTimesTimer);
}
this.noTimesTimer = setTimeout(() => {
this.showNoTimesModal = false;
}, 3000);
return;
}
// 有剩余次数,开始抽奖
this.isSpinning = true;
// 计算随机停止位置
this.targetPointerRotation = this.calculateRandomStop();
// 设置CSS变量,用于动画
document.documentElement.style.setProperty('--target-pointer-rotation', `${this.targetPointerRotation}deg`);
// 开始旋转动画
this.pointerRotation = this.targetPointerRotation;
// 调用抽奖API获取奖品信息
const success = await this.fetchPrizeInfo();
setTimeout(() => {
this.isSpinning = false;
if (success) {
// 直接显示弹窗,无需额外延迟
this.showPrizeModal = true;
}
}, 4000);
} catch (error) {
console.error('查询剩余次数失败:', error);
this.isSpinning = false;
}
},
// 处理活动规则点击
handleRuleClick() {
this.showRuleModal = true;
},
// 关闭弹窗
closeModal() {
this.showPrizeModal = false;
},
// 关闭无次数提示弹窗
closeNoTimesModal() {
this.showNoTimesModal = false;
if (this.noTimesTimer) {
clearTimeout(this.noTimesTimer);
}
},
// 关闭活动规则弹窗
closeRuleModal() {
this.showRuleModal = false;
},
// 关闭首次访问弹窗
closeFirstVisitModal() {
this.isFirstVisit = false;
},
// 跳转到历史记录页面
goToHistory() {
this.$router.push('/history');
},
// 计算文本宽度,动态设置动画
calcTextWidth() {
if (!this.shouldScroll || !this.prizeAmount) return;
// 创建临时元素,用于计算文本宽度
const tempSpan = document.createElement('span');
tempSpan.style.visibility = 'hidden';
tempSpan.style.position = 'absolute';
tempSpan.style.whiteSpace = 'nowrap';
tempSpan.style.fontSize = '25px';
tempSpan.style.fontWeight = 'bold';
tempSpan.style.fontFamily = 'inherit';
tempSpan.textContent = this.prizeAmount;
document.body.appendChild(tempSpan);
// 获取单个文本宽度
this.textWidth = tempSpan.offsetWidth;
document.body.removeChild(tempSpan);
// 移除现有的样式
const existingStyle = document.getElementById('scroll-animation-style');
if (existingStyle) {
existingStyle.remove();
}
// 动态设置滚动动画
const style = document.createElement('style');
style.id = 'scroll-animation-style';
style.textContent = `
@keyframes seamless-scroll {
0% { transform: translateX(0); }
100% { transform: translateX(-${this.textWidth + 20}px); }
}
@media (max-width: 380px) {
@keyframes seamless-scroll {
0% { transform: translateX(0); }
100% { transform: translateX(-${this.textWidth + 16}px); }
}
}
.prize-amount.scrolling .prize-text {
animation: seamless-scroll ${Math.max(5, this.textWidth / 30)}s linear infinite;
padding-right: 20px;
display: inline-block;
}
`;
document.head.appendChild(style);
}
},
watch: {
// 当奖品金额变化时,重新计算文本宽度
prizeAmount(newVal) {
if (newVal && this.shouldScroll) {
this.$nextTick(() => {
this.calcTextWidth();
});
}
}
}
}
</script>
<style scoped>
.wheel-container {
min-height: 100vh;
background-image: url('../../assets/img/wealthGoldenWheel/bg.png');
background-size: cover;
background-position: bottom center;
padding: 15px;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
/* 顶部区域样式 */
.top-section {
width: 100%;
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 15px;
}
.expire-time {
color: #fff;
font-size: 12px;
font-weight: bold;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
margin: 11px 0 0 12px;
}
.top-right {
display: flex;
gap: 20px;
align-items: center;
}
.icon-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
cursor: pointer;
}
.history-icon, .rule-icon {
width: 25px;
height: 25px;
cursor: pointer;
}
.icon-text {
color: #fff;
font-size: 11px;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
}
/* 主标题图片样式 */
.title-img {
width: 327px;
height: 144px;
margin-bottom: 20px;
}
/* 转盘区域样式 */
.wheel-section {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 15px;
position: relative;
}
.wheel-wrapper {
position: relative;
width: 333px;
height: 333px;
}
.wheel-img {
width: 100%;
height: 100%;
transform: rotate(-22.5deg);
}
/* 指针系统 - 完全重构 */
.pointer-system {
position: absolute;
top: 50%;
left: 50%;
width: 137px;
height: 137px;
transform: translate(-50%, -50%);
z-index: 2;
}
/* 中心固定点 - 用于调试和参考 */
.rotation-center {
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 4px;
background: red;
border-radius: 50%;
transform: translate(-50%, -50%);
z-index: 4;
opacity: 0; /* 调试时可设置为1查看中心点 */
}
/* 指针底座 - 提供固定参考点 */
.pointer-base {
position: relative;
width: 137px;
height: 137px;
display: flex;
justify-content: center;
align-items: center;
transform: translateZ(0); /* 启用GPU加速 */
}
/* 指针图片 - 关键优化 */
.pointer-img {
position: absolute;
top: 0;
left: 0;
width: 137px;
height: 137px;
/* 精确计算旋转中心点 */
transform-origin: 68.5px 68.5px; /* 137px / 2 = 68.5px */
transform: rotate(-21.5deg);
transition: transform 0.1s linear;
image-rendering: crisp-edges;
-webkit-font-smoothing: subpixel-antialiased;
backface-visibility: hidden;
perspective: 1000px;
will-change: transform;
}
/* 旋转动画 - 使用requestAnimationFrame优化 */
.pointer-img.spinning {
animation: smooth-spin 3s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
/* 添加这些属性确保性能 */
backface-visibility: hidden;
transform: translateZ(0);
will-change: transform;
}
@keyframes smooth-spin {
0% {
transform: rotate(-21.5deg);
animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
100% {
transform: rotate(var(--target-pointer-rotation, 1440deg));
}
}
/* 指针盖样式 */
.pointer-cover-img {
position: absolute;
top: 50%;
left: 50%;
width: 104px;
height: 104px;
transform: translate(-50%, -50%);
z-index: 3;
pointer-events: none;
}
/* 剩余次数样式 */
.remaining-section {
position: relative;
margin-bottom: 20px;
display: flex;
justify-content: center;
margin-top: -5px;
}
.remaining-bg {
width: 104px;
height: 21.5px;
}
.remaining-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
font-size: 12px;
font-weight: bold;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
width: 100%;
text-align: center;
white-space: nowrap;
}
/* 转动按钮样式 */
.spin-btn {
background: none;
border: none;
cursor: pointer;
transition: transform 0.2s ease;
padding: 0;
}
.spin-btn:active:not(:disabled) {
transform: scale(0.95);
}
.spin-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.spin-btn-img {
width: 240px;
height: 94px;
}
/* 弹窗样式 */
.prize-modal, .no-times-modal, .rule-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
}
/* 中奖弹窗内容区域尺寸为333x377 */
.modal-content {
position: relative;
width: 333px;
height: 377px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 1001;
animation: modal-appear 0.3s ease-out;
}
@keyframes modal-appear {
from {
opacity: 0;
transform: scale(0.8) translateY(-20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.modal-bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
}
/* 无次数提示弹窗样式 */
.no-times-content {
position: relative;
width: 333px;
height: 79px;
display: flex;
justify-content: center;
align-items: center;
z-index: 1001;
margin-top: 250px;
animation: slide-up 0.3s ease-out;
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.no-times-bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
}
/* 弹窗内容样式 */
.prize-info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
z-index: 2;
margin-top: 120px;
}
.prize-title {
color: #B82525;
font-size: 25px;
font-weight: bold;
margin-bottom: 35px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
animation: text-pulse 2s infinite;
}
@keyframes text-pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
/* 奖品数量样式 - 优化后的样式 */
.prize-amount-wrapper {
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
width: 272px;
height: 58px;
overflow: hidden;
}
.prize-amount-bg {
position: absolute;
width: 272px;
height: 58px;
z-index: 1;
}
.prize-amount {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #FFFFFF;
font-size: 25px;
font-weight: bold;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
width: 240px;
text-align: center;
white-space: nowrap;
z-index: 2;
overflow: hidden;
}
/* 滚动状态:限制文本显示区域,确保仅容器内文本可见 */
.prize-amount.scrolling {
width: 170px;
text-align: left;
}
/* 滚动文本容器 */
.prize-amount.scrolling .prize-text {
will-change: transform;
backface-visibility: hidden;
transform: translateZ(0);
}
/* 关闭按钮样式 - 修改位置 */
.close-modal {
position: absolute;
top: 115px;
right: 22px;
background: none;
border: none;
cursor: pointer;
z-index: 1002;
transition: transform 0.2s ease;
padding: 0;
}
.close-modal:hover {
transform: scale(1.1);
}
.close-modal img {
width: 35px;
height: 35px;
}
/* 活动规则弹窗样式 - 整体上移并增大字体 */
.rule-content {
position: relative;
width: 333px;
height: 239px;
display: flex;
flex-direction: column;
align-items: center;
z-index: 1001;
animation: modal-appear 0.3s ease-out;
/* 修改:将弹窗上移,从原来的margin-top: 80px调整为更小的值 */
margin-top: 10px; /* 上移了10px */
}
.rule-bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
}
/* 活动规则关闭按钮 - 修复:确保按钮层级高于背景 */
.close-rule-btn {
position: absolute;
top: 45.5px;
right: 35.5px;
background: none;
border: none;
cursor: pointer;
z-index: 1002;
transition: transform 0.2s ease;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
}
.close-rule-btn:hover {
transform: scale(1.1);
}
.close-rule-btn img {
width: 20px;
height: 20px;
display: block;
}
/* 活动规则文本 - 增大字体和行高 */
.rule-text {
position: absolute;
top: 83px;
left: 27px;
display: flex;
flex-direction: column;
gap: 8px; /* 增加行间距,从9.15px增加到12px */
width: calc(100% - 54px);
}
.rule-line {
color: #FFFFFF;
font-size: 14px; /* 增大字体,从12px增加到14px */
line-height: 1.2; /* 增加行高,从1.4增加到1.5 */
}
/* 媒体查询 - 适配小屏幕 */
@media (max-width: 380px) {
.title-img {
width: 280px;
height: 123px;
}
.wheel-wrapper {
width: 280px;
height: 280px;
}
.pointer-container {
width: 115px;
height: 115px;
}
.pointer-system {
width: 115px;
height: 115px;
}
.pointer-system {
width: 115px;
height: 115px;
}
.pointer-cover-img {
width: 70px;
height: 70px;
}
.spin-btn-img {
width: 200px;
height: 78px;
}
.top-right {
gap: 15px;
}
.remaining-section {
margin-top: -8px;
}
/* 小屏幕适配中奖弹窗 */
.modal-content {
width: 300px;
height: 340px;
}
.prize-info {
margin-top: 100px;
}
.prize-title {
margin-bottom: 30px;
}
.prize-amount-wrapper {
margin-top: 18px;
width: 240px;
height: 51px;
}
.prize-amount-bg {
width: 240px;
height: 51px;
}
.prize-amount {
font-size: 22px;
width: 210px;
}
.prize-amount.scrolling {
width: 190px;
}
.no-times-content {
width: 280px;
height: 66px;
margin-top: 200px;
}
/* 小屏幕适配关闭按钮位置 */
.close-modal {
top: 100px;
right: 18px;
}
.close-modal img {
width: 30px;
height: 30px;
}
/* 小屏幕适配活动规则弹窗 */
.rule-content {
width: 300px;
height: 215px;
margin-top: 20px; /* 小屏幕也相应上移 */
}
.close-rule-btn {
top: 41px;
right: 32px;
}
.rule-text {
top: 75px;
left: 24px;
width: calc(100% - 48px);
gap: 5px; /* 小屏幕行间距稍小 */
}
.rule-line {
font-size: 13px; /* 小屏幕字体稍小但依然比原来大 */
}
}
.fold-up {
width: 30px;
height: 30px;
position: absolute;
top: 20px;
left: 45px;
cursor: pointer;
z-index: 999;
}
.history-title {
padding-top: 12px;
display: flex;
justify-content: center;
width: 100%;
color: #00e5ff;
font-size: 32px;
font-weight: 700;
}
.history-record {
background: #080A6D;
position: fixed;
right: 0;
bottom: 0;
width: 90%;
height: 100vh;
display: flex;
flex-direction: column;
--bottom-cut-height: 220px;
overflow: hidden;
z-index: 2000;
box-shadow: -8px 0 24px rgba(0,0,0,0.6);
border-left: 1px solid rgba(255,255,255,0.03);
padding-bottom: 0;
}
.history-contents {
margin-top: 20px;
padding-right: 10px;
flex: 1 1 auto;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
direction: rtl;
}
.history-contents > * { direction: ltr; }
.history-contents * { direction: ltr; }
.history-contents::-webkit-scrollbar {
width: 14px;
background-color: #20086d;
}
.history-contents::-webkit-scrollbar-thumb {
background-color: #4a4de6;
border-radius: 4px;
}
.history-contents::-webkit-scrollbar-thumb:hover {
background-color: #6b6ef5;
}
.history-decoration {
flex: 0 0 200px;
height: var(--bottom-cut-height);
position: relative;
left: 50%;
transform: translateX(-50%);
width: 100%;
pointer-events: none;
z-index: 0;
background-image: url('../../assets/img/wealthGoldenWheel/bottomDecoration.png');
background-repeat: no-repeat;
background-position: center bottom;
background-size: contain;
margin-top: 0;
}
/* 记录项样式 */
.history-record-item {
background: #0b0d99;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
width: 80%;
padding: 8px;
border-radius: 8px;
}
.history-record-item .left {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
padding: 5px;
}
.history-record-item .title {
color: #f2f5ff;
font-size: 16px;
font-weight: 700;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: flex;
align-items: center;
}
.history-record-item .time {
font-size: 12px;
color: #e6ecff;
font-weight: 700;
margin-left: 28px;
}
.history-record-item .right {
display: flex;
align-items: center;
justify-content: flex-end;
min-width: 72px;
padding-right: 10px;
}
.history-record-item .token {
color: #00e6ff;
font-size: 16px;
font-weight: 700;
}
.circle {
width: 10px;
height: 10px;
background-color: #fff;
margin-right: 8px;
flex-shrink: 0;
margin-left: 10px;
border-radius: 50%;
}
.month-row,
.year-header {
display: flex;
align-items: center;
padding-bottom: 12px;
cursor: pointer;
color: #ffffff;
font-weight: 700;
}
.month-text,
.year-text {
font-weight: 700;
font-size: 16px;
color: #ffffff;
}
.month-caret,
.year-caret {
margin-left: 10px;
font-size: 16px;
color: #ffffff;
}
.empty-month {
padding: 8px;
color: #cfd9ff;
background: transparent;
}
@media (max-width: 900px) {
.history-record { width: 90%; }
.history-record-item { width: calc(100% - 60px); }
}
@media (max-width: 430px) {
.history-record-item .title {
font-size: 12px;
}
.history-record-item .time {
font-size: 10px;
margin-left:10px;
}
.history-record-item .token {
font-size: 14px;
}
.history-record-item .right {
padding-right: 5px;
}
.circle {
width: 8px;
height: 8px;
margin-left: 0px;
}
.month-caret,
.year-caret {
margin-left: 5px;
}
}
</style>