955 lines
34 KiB
Vue
955 lines
34 KiB
Vue
<script setup>
|
|
import { ref, computed } from 'vue';
|
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
|
import { useThemeStore } from '@/store/useThemeStore';
|
|
import { useAppStore } from '@/store/useAppStore';
|
|
import Boardcast from './components/Boardcast.vue';
|
|
import config from '@/config/global.config';
|
|
import { checkRedepositApi, getRepositLotteryApi } from '@/api/promo';
|
|
import Congratulation from '@/components/popup/Congratulation.vue';
|
|
import { useUserStore } from '@/store/useUserStore';
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
const { t } = useI18n()
|
|
const appStore = useAppStore();
|
|
const themeStore = useThemeStore();
|
|
const userStore = useUserStore();
|
|
const dw = computed(() => themeStore.theme.depositWheel);
|
|
const active = ref(0);
|
|
const imgBgs = [dw.value.wheelBg0, dw.value.wheelBg1, dw.value.wheelBg2, dw.value.wheelBg3];
|
|
const statusBarHeight = ref(20)
|
|
const imgPaths = [
|
|
config.canvasImage + '/deposit_wheel/image_zpwk_silver.png',
|
|
config.canvasImage + '/deposit_wheel/image_zpwk_gold.png',
|
|
config.canvasImage + '/deposit_wheel/image_zpwk_diamond.png',
|
|
config.canvasImage + '/deposit_wheel/image_zpwk_supreme.png',
|
|
];
|
|
const pointImgs = [
|
|
config.canvasImage + '/deposit_wheel/image_zhizhen_silver.png',
|
|
config.canvasImage + '/deposit_wheel/image_zhizhen_gold.png',
|
|
config.canvasImage + '/deposit_wheel/image_zhizhen_diamond.png',
|
|
config.canvasImage + '/deposit_wheel/image_zhizhen_supreme.png',
|
|
]
|
|
|
|
const spinBg = config.canvasImage + '/deposit_wheel/image_zpdk.png';
|
|
const jinbi = config.canvasImage + '/spins/image_jinbi.png';
|
|
const zhibi = config.canvasImage + '/spins/image_zhibi.png';
|
|
|
|
const typeEnum = ['Amount', 'Sliver Spin', 'Gold Spin', 'Diamond Spin', 'Supreme Spin'];
|
|
const isSpinning = ref(false);
|
|
|
|
const size = 260;
|
|
const innerSize = 228;
|
|
const duration = 5000
|
|
let targetIndex = 0
|
|
const activityContent = ref([])
|
|
const lottery = ref([])
|
|
const prizes = computed(() => activityContent.value[active.value]?.prizes ?? [])
|
|
const rechargeAmount = ref(0)
|
|
const disabledIndex = ref(3)
|
|
const spinCounts = ref([0, 0, 0, 0])
|
|
const uptoAmount = [377, 777, 1777, 3777]
|
|
const spinCount = computed(() => {
|
|
if (lottery.value.length > 0) {
|
|
return lottery.value[active.value].curCount
|
|
}
|
|
return 0
|
|
})
|
|
const rotationResult = ref(0)
|
|
const awardAmount = ref('')
|
|
const awardPopup = ref(null)
|
|
const currency = computed(() => import.meta.env.VITE_CURRENCY_SYMBOL)
|
|
const currency2 = ref('')
|
|
const percent = ref(0)
|
|
const autoRotation = ref(0);
|
|
const isAutoRotating = ref(false);
|
|
const autoRotateSpeed = 0.003;
|
|
const sliceWidth = ref(0);
|
|
const totalW = ref(0);
|
|
const canvasSpace = ref(0);
|
|
const startPoint = ref([0, 0]);
|
|
const moveWidth = ref(0);
|
|
const scale = ref(1);
|
|
const scaleMin = 0.8;
|
|
const scaleSpeed = 0.001;
|
|
|
|
// claude gen
|
|
const currentIndex = ref(0);
|
|
const wheelRefs = ref([]);
|
|
const isDragging = ref(false);
|
|
const startX = ref(0);
|
|
const translateX = ref(0);
|
|
const initialTranslateX = ref(0);
|
|
const animating = ref(false);
|
|
|
|
const wheelCanvasIds = ['depositWheel0', 'depositWheel1', 'depositWheel2', 'depositWheel3'];
|
|
const wheelContexts = ref([null, null, null, null]);
|
|
const wheelRotations = ref([0, 0, 0, 0]);
|
|
|
|
let autoTimer = null
|
|
const wheelsDrawnComplete = ref(false);
|
|
const wheelDrawnStatus = ref([false, false, false, false]);
|
|
// 计算缩放比例的方法
|
|
const calculateScale = (index) => {
|
|
if (index === currentIndex.value) {
|
|
return 1;
|
|
} else {
|
|
const distance = Math.abs(index - currentIndex.value);
|
|
return Math.max(1 - distance * 0.2, scaleMin);
|
|
}
|
|
};
|
|
|
|
// 处理触摸开始事件
|
|
const onTouchStart = (e) => {
|
|
if (animating.value || isSpinning.value) return;
|
|
|
|
const touch = e.touches[0];
|
|
startX.value = touch.clientX;
|
|
initialTranslateX.value = translateX.value;
|
|
isDragging.value = true;
|
|
};
|
|
|
|
// 处理触摸移动事件
|
|
const onTouchMove = (e) => {
|
|
if (!isDragging.value || animating.value || isSpinning.value) return;
|
|
|
|
const touch = e.touches[0];
|
|
const deltaX = touch.clientX - startX.value;
|
|
translateX.value = initialTranslateX.value + deltaX;
|
|
};
|
|
|
|
// 处理触摸结束事件
|
|
const onTouchEnd = () => {
|
|
if (!isDragging.value || animating.value || isSpinning.value) return;
|
|
|
|
isDragging.value = false;
|
|
animating.value = true;
|
|
|
|
// 计算应该滑动到哪个索引
|
|
const moveDistance = translateX.value - initialTranslateX.value;
|
|
let targetIndex = currentIndex.value;
|
|
|
|
if (Math.abs(moveDistance) > sliceWidth.value * 0.2) {
|
|
if (moveDistance > 0 && currentIndex.value > 0) {
|
|
targetIndex = currentIndex.value - 1;
|
|
} else if (moveDistance < 0 && currentIndex.value < activityContent.value.length - 1) {
|
|
targetIndex = currentIndex.value + 1;
|
|
} else if (moveDistance < 0 && currentIndex.value < activityContent.value.length - 1) {
|
|
// 检查是否可以滑动到最后一个转盘
|
|
if (currentIndex.value === activityContent.value.length - 2 && rechargeAmount.value <= 1777) {
|
|
// 如果是倒数第二个转盘且充值金额不足,不允许滑动到最后一个
|
|
targetIndex = currentIndex.value;
|
|
} else {
|
|
targetIndex = currentIndex.value + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 滑动到目标索引
|
|
slideToIndex(targetIndex);
|
|
};
|
|
|
|
// 滑动到指定索引
|
|
const slideToIndex = (index) => {
|
|
if (index === activityContent.value.length - 1 && rechargeAmount.value <= 1777) {
|
|
// 如果是最后一个转盘且充值金额不足,不允许滑动
|
|
index = activityContent.value.length - 2;
|
|
uni.showToast({
|
|
title: t('redeposit.supreme'),
|
|
icon: 'none',
|
|
duration: 3500
|
|
})
|
|
}
|
|
if (index === currentIndex.value) {
|
|
// 如果是当前索引,回弹到原位
|
|
const windowInfo = uni.getWindowInfo();
|
|
const w = windowInfo.windowWidth;
|
|
const initialOffset = (w - sliceWidth.value) / 2;
|
|
translateX.value = initialOffset - currentIndex.value * sliceWidth.value;
|
|
animating.value = false;
|
|
return;
|
|
}
|
|
|
|
// 设置动画
|
|
const startTranslateX = translateX.value;
|
|
const windowInfo = uni.getWindowInfo();
|
|
const w = windowInfo.windowWidth;
|
|
const initialOffset = (w - sliceWidth.value) / 2;
|
|
const targetTranslateX = initialOffset - index * sliceWidth.value;
|
|
const startTime = Date.now();
|
|
const duration = 600; // 动画持续时间
|
|
|
|
const animate = () => {
|
|
const elapsed = Date.now() - startTime;
|
|
const progress = Math.min(elapsed / duration, 1);
|
|
const easedProgress = easeInOutQuad(progress);
|
|
|
|
translateX.value = startTranslateX + (targetTranslateX - startTranslateX) * easedProgress;
|
|
|
|
if (progress < 1) {
|
|
// #ifdef H5
|
|
requestAnimationFrame(animate);
|
|
// #endif
|
|
// #ifndef H5
|
|
setTimeout(animate, 16.6);
|
|
// #endif
|
|
} else {
|
|
translateX.value = targetTranslateX;
|
|
currentIndex.value = index;
|
|
animating.value = false;
|
|
active.value = index;
|
|
calPercent();
|
|
}
|
|
};
|
|
|
|
animate();
|
|
};
|
|
|
|
// 缓动函数
|
|
const easeInOutQuad = (t) => {
|
|
return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
|
|
};
|
|
function drawSpin(context, rotation) {
|
|
const actualRotation = isAutoRotating.value && !isSpinning.value ? autoRotation.value : rotation;
|
|
const center = size / 2;
|
|
const innerCenter = innerSize / 2;
|
|
context.translate(center, center);
|
|
context.rotate(actualRotation);
|
|
context.translate(-center, -center);
|
|
context.drawImage(spinBg, center - innerCenter, center - innerCenter, innerSize, innerSize);
|
|
}
|
|
|
|
function drawWheel(rotation = 0, wheelIndex = active.value) {
|
|
const actualRotation = isAutoRotating.value && !isSpinning.value ? autoRotation.value : rotation;
|
|
wheelRotations.value[wheelIndex] = actualRotation;
|
|
const context = uni.createCanvasContext(wheelCanvasIds[wheelIndex]);
|
|
wheelContexts.value[wheelIndex] = context;
|
|
const center = size / 2;
|
|
|
|
const radius = center - 10;
|
|
const sliceAngle = (2 * Math.PI) / activityContent.value[wheelIndex].prizes.length;
|
|
context.clearRect(0, 0, size, size);
|
|
context.save();
|
|
drawSpin(context, rotation);
|
|
|
|
for (let index = 0, len = prizes.value.length; index < len; index++) {
|
|
// const prize = prizes.value[index];
|
|
const prize = activityContent.value[wheelIndex].prizes[index];
|
|
context.save();
|
|
context.translate(center, center);
|
|
// Rotate to the middle of the slice
|
|
context.rotate(index * sliceAngle);
|
|
// Rotate 90 degrees to make text perpendicular
|
|
context.rotate(Math.PI / 2);
|
|
// 0: sliver,1:gold,2:diamond,3:supreme
|
|
// Text settings
|
|
context.setTextAlign('center');
|
|
context.setTextBaseline('bottom');
|
|
context.setFillStyle('#fff');
|
|
context.font = '11px sans-serif';
|
|
let startY = -radius * 0.73;
|
|
if (prize.type === 0) {
|
|
context.fillText(`${currency.value}${prize.amount}`, 0, startY)
|
|
} else {
|
|
context.fillText(`${typeEnum[prize.type]}`, 0, startY)
|
|
startY = -radius * 0.63
|
|
context.fillText(`x ${prize.amount}`, 0, startY)
|
|
}
|
|
|
|
// const img2 = index % 2 === 0 ? jinbi : zhibi
|
|
const img2 = config.canvasImage + '/deposit_wheel/' + prizes.value[index]['icon']
|
|
// const img2 = await loadImg(config.canvasImage + currentImg)
|
|
// const img2 = config.canvasImage + currentImg
|
|
|
|
let _radius = center * 0.44;
|
|
let iconSize = 30;
|
|
if (prizes.value[index].type === 0) {
|
|
iconSize = 38
|
|
_radius = center * 0.46;
|
|
}
|
|
context.drawImage(
|
|
img2,
|
|
-19, // Center horizontally
|
|
-_radius - 17, // Position at sector center,
|
|
iconSize,
|
|
iconSize);
|
|
// Rotate to the middle of the slice
|
|
// context.rotate(index * sliceAngle);
|
|
context.restore();
|
|
}
|
|
context.restore();
|
|
|
|
context.translate(center, center)
|
|
context.rotate(0);
|
|
context.translate(-center, -center)
|
|
context.drawImage(imgPaths[wheelIndex], 0, 0, size, size);
|
|
context.save();
|
|
context.restore();
|
|
context.translate(center, center)
|
|
context.rotate(0)
|
|
// Draw fixed pointer in center (after rotation restore)
|
|
// const img = await loadImg(config.canvasImage + pointImgs[wheelIndex])
|
|
const img = pointImgs[wheelIndex]
|
|
context.drawImage(img, -32.5, -53.75, 65, 87.5);
|
|
context.save();
|
|
|
|
// Draw spin count
|
|
context.restore();
|
|
// context.translate(center, center);
|
|
context.rotate(0);
|
|
context.setTextAlign('center');
|
|
context.setTextBaseline('middle');
|
|
context.setFillStyle('#C14F21');
|
|
context.font = 'bold 16px sans-serif';
|
|
context.fillText('GO', 0, -6);
|
|
context.font = 'bold 11px sans-serif';
|
|
context.fillText(`Spin*${spinCount.value}`, 0, 12);
|
|
context.draw(false, () => {
|
|
// 标记当前转盘已绘制完成
|
|
wheelDrawnStatus.value[wheelIndex] = true;
|
|
|
|
// 检查所有需要显示的转盘是否都已绘制完成
|
|
const visibleWheelsCount = rechargeAmount.value > 1777 ? 4 : 3;
|
|
const allDrawn = wheelDrawnStatus.value.slice(0, visibleWheelsCount).every(status => status);
|
|
|
|
if (allDrawn && !wheelsDrawnComplete.value) {
|
|
wheelsDrawnComplete.value = true;
|
|
// 所有转盘绘制完成后,开始自动旋转
|
|
setTimeout(() => {
|
|
startAutoRotate();
|
|
|
|
}, 1000); // 添加短暂延迟确保UI更新
|
|
}
|
|
});
|
|
}
|
|
|
|
const calculateTargetRotation = (targetIndex) => {
|
|
// Calculate base rotation needed to align the target index
|
|
const sliceAngle = (2 * Math.PI) / prizes.value.length;
|
|
|
|
// Calculate the angle needed to rotate the target index to 12 o'clock
|
|
// We add Math.PI/2 to start from 12 o'clock (instead of 3 o'clock)
|
|
// We subtract the target index angle to rotate counterclockwise
|
|
// We add sliceAngle/2 to center the slice
|
|
const baseAngle = Math.PI - ((targetIndex - 2) * sliceAngle);
|
|
|
|
// Add extra rotations (5-8 full spins)
|
|
const extraRotations = Math.PI * 2 * (5 + Math.floor(Math.random() * 3));
|
|
|
|
// Return total rotation (extra rotations + base angle)
|
|
return extraRotations + baseAngle;
|
|
};
|
|
const startAutoRotate = () => {
|
|
// if(!isAutoRotating.value) {
|
|
// return;
|
|
// }
|
|
console.log("startAutoRotate", isAutoRotating.value, isSpinning.value, wheelsDrawnComplete.value);
|
|
|
|
if (isAutoRotating.value || isSpinning.value || !wheelsDrawnComplete.value) return;
|
|
isAutoRotating.value = true;
|
|
const animate = () => {
|
|
// 增加旋转角度
|
|
autoRotation.value += autoRotateSpeed;
|
|
// 确保角度在0-2π之间循环
|
|
if (autoRotation.value >= Math.PI * 2) {
|
|
autoRotation.value -= Math.PI * 2;
|
|
}
|
|
|
|
// drawWheel(rotationResult.value);
|
|
for (let i = 0; i < wheelCanvasIds.length; i++) {
|
|
if (activityContent.value[i]) {
|
|
drawWheel(autoRotation.value, i);
|
|
}
|
|
}
|
|
// 继续下一帧动画
|
|
// #ifdef H5
|
|
requestAnimationFrame(animate);
|
|
// #endif
|
|
// #ifndef H5
|
|
setTimeout(animate, 16.6);
|
|
// #endif
|
|
};
|
|
console.log("startAutoRotate animate", isAutoRotating.value);
|
|
animate();
|
|
};
|
|
const startSpin = async () => {
|
|
if (isSpinning.value) return;
|
|
isAutoRotating.value = false;
|
|
wheelsDrawnComplete.value = true;
|
|
isSpinning.value = true;
|
|
// If targetIndex is provided and valid, use it; otherwise random
|
|
let finalIndex;
|
|
if (targetIndex >= 0 && targetIndex < prizes.value.length) {
|
|
finalIndex = targetIndex;
|
|
} else {
|
|
finalIndex = Math.floor(Math.random() * prizes.value.length);
|
|
}
|
|
|
|
const targetRotation = calculateTargetRotation(finalIndex);
|
|
rotationResult.value = targetRotation
|
|
autoRotation.value = targetRotation
|
|
const startTime = Date.now();
|
|
|
|
const animate = () => {
|
|
const currentTime = Date.now();
|
|
const elapsed = currentTime - startTime;
|
|
const progress = Math.min(elapsed / duration, 1);
|
|
|
|
const easedProgress = easeOut(progress);
|
|
const rotation = targetRotation * easedProgress;
|
|
|
|
drawWheel(rotation);
|
|
|
|
if (progress < 1) {
|
|
// #ifdef H5
|
|
requestAnimationFrame(animate);
|
|
// #endif
|
|
// #ifndef H5
|
|
setTimeout(animate, 16.6);
|
|
// #endif
|
|
} else {
|
|
// isSpinning.value = false;
|
|
console.log('Final Index:', finalIndex, 'Prize:', prizes.value[finalIndex]);
|
|
const prize = prizes.value[finalIndex]
|
|
if (prize.type === 0) {
|
|
currency2.value = currency.value
|
|
awardAmount.value = prizes.value[finalIndex].amount
|
|
} else {
|
|
currency2.value = ''
|
|
awardAmount.value = typeEnum[prize.type] + ' x ' + prizes.value[finalIndex].amount
|
|
}
|
|
awardPopup.value?.open()
|
|
// drawWheel(rotationResult.value);
|
|
// TODO emit('spin-end', prizes.value[finalIndex]);
|
|
|
|
}
|
|
};
|
|
|
|
animate();
|
|
};
|
|
|
|
const easeOut = (t) => {
|
|
return 1 - Math.pow(1 - t, 5);
|
|
};
|
|
const calPercent = () => {
|
|
const stepItem = activityContent.value[active.value]
|
|
const val = Math.ceil((rechargeAmount.value / stepItem.amounts[stepItem.amounts.length - 1]) * 100)
|
|
percent.value = val >= 100 ? 100 : val
|
|
}
|
|
const handleTabClick = (idx) => {
|
|
// if (idx >= disabledIndex.value) return
|
|
// active.value = idx
|
|
// calPercent()
|
|
// drawWheel()
|
|
// console.log("handleTabClick", idx, disabledIndex.value);
|
|
|
|
if (idx === 3 && rechargeAmount.value < 1777) {
|
|
uni.showToast({
|
|
title: t('redeposit.supreme'),
|
|
icon: 'none',
|
|
duration: 3500
|
|
})
|
|
return
|
|
}
|
|
if (idx >= disabledIndex.value || animating.value || isSpinning.value) return;
|
|
active.value = idx;
|
|
slideToIndex(idx);
|
|
}
|
|
const getRedepositAct = async () => {
|
|
const { code, data } = await checkRedepositApi();
|
|
|
|
if (code == 200) {
|
|
console.log('checkRedepositApi:', JSON.parse(data.activity.content));
|
|
if (data?.activity?.content) {
|
|
const _content = JSON.parse(data.activity.content)
|
|
activityContent.value = _content.map((item, index) => {
|
|
return {
|
|
...item,
|
|
bgImg: imgBgs[index]
|
|
}
|
|
})
|
|
}
|
|
if (data?.lottery) {
|
|
rechargeAmount.value = data?.lottery?.rechargeAmount
|
|
lottery.value = JSON.parse(data?.lottery?.lottery)
|
|
// const last = activityContent.value[2]
|
|
if (rechargeAmount.value >= 1777) {
|
|
disabledIndex.value = 4
|
|
}
|
|
console.log('disabledIndex:', disabledIndex.value);
|
|
|
|
// spinCount.value = lottery.value[active.value].curCount
|
|
spinCounts.value = lottery.value.reduce((acc, cur) => {
|
|
acc.push(cur.curCount)
|
|
return acc
|
|
}, [])
|
|
calPercent()
|
|
}
|
|
}
|
|
|
|
}
|
|
const requestLottery = async () => {
|
|
const { data } = await getRepositLotteryApi({ id: activityContent.value[active.value].level })
|
|
console.log("getRepositLotteryApi:", data);
|
|
targetIndex = data
|
|
}
|
|
const handleStart = async () => {
|
|
const count = spinCounts.value[active.value]
|
|
if (count === 0) {
|
|
uni.showToast({
|
|
title: t('redeposit.noCount'),
|
|
icon: 'none',
|
|
duration: 3500
|
|
})
|
|
return
|
|
}
|
|
await requestLottery()
|
|
setTimeout(() => {
|
|
// drawWheel()
|
|
startSpin()
|
|
}, 200);
|
|
}
|
|
const onClose = async () => {
|
|
// isSpinning.value = false;
|
|
await getRedepositAct()
|
|
// drawWheel()
|
|
isSpinning.value = false;
|
|
wheelsDrawnComplete.value = false;
|
|
// startAutoRotate();
|
|
// setTimeout(() => {
|
|
// isSpinning.value = false;
|
|
// wheelsDrawnComplete.value = false;
|
|
// startAutoRotate();
|
|
// }, 1000);
|
|
}
|
|
const toRules = () => {
|
|
uni.navigateTo({ url: '/pages/redeposit/WheelRules' })
|
|
}
|
|
const toHistory = () => {
|
|
uni.navigateTo({ url: '/pages/redeposit/WheelHistory' })
|
|
}
|
|
const depositNow = () => {
|
|
uni.navigateTo({ url: '/pages/wallet/Deposit' })
|
|
}
|
|
|
|
function start() {
|
|
const windowInfo = uni.getWindowInfo();
|
|
statusBarHeight.value = windowInfo.statusBarHeight;
|
|
const w = windowInfo.windowWidth;
|
|
const space = (w - size) / 2;
|
|
sliceWidth.value = sliceWidth.value = w * 0.8;;
|
|
|
|
canvasSpace.value = space / 2;
|
|
const visibleWheels = rechargeAmount.value > 1777 ? 4 : 3;
|
|
sliceWidth.value = w * 0.68;
|
|
totalW.value = sliceWidth.value * visibleWheels;
|
|
const initialOffset = (w - sliceWidth.value) / 2;
|
|
translateX.value = initialOffset;
|
|
// reset status
|
|
wheelDrawnStatus.value = [false, false, false, false];
|
|
wheelsDrawnComplete.value = false;
|
|
// isAutoRotating.value = false; // 先禁用自动旋转
|
|
setTimeout(() => {
|
|
console.log("setTimeout---------");
|
|
|
|
for (let i = 0; i < wheelCanvasIds.length; i++) {
|
|
if (activityContent.value[i]) {
|
|
drawWheel(0, i);
|
|
}
|
|
}
|
|
}, 600);
|
|
|
|
}
|
|
|
|
// onLoad(async () => {
|
|
// console.log("mounted---------");
|
|
|
|
// await getRedepositAct()
|
|
// start()
|
|
// });
|
|
onLoad(async () => {
|
|
console.log("mounted---------");
|
|
await getRedepositAct()
|
|
start()
|
|
})
|
|
onUnload(() => {
|
|
isAutoRotating.value = false;
|
|
// clearTimeout(autoTimer);
|
|
});
|
|
</script>
|
|
<template>
|
|
<mobile-custom-layout :bgColor="dw.bgColor">
|
|
<template #head-right>
|
|
<view class="count-box flex items-center" :style="{ background: dw.dark2, borderColor: dw.pentary }">
|
|
<theme-image class="icon-coin" src="@/static/deposit_wheel/icon_coin.png" />
|
|
<text class="coin-amount" :style="{ color: dw.quaternary }">
|
|
{{ userStore.userInfo?.totalAssets ?? 0 }}
|
|
</text>
|
|
</view>
|
|
</template>
|
|
<view style="position: fixed;top: -11111px;left: -11111px;">
|
|
<theme-image src="@/static/deposit_wheel/bg_silver.png" />
|
|
<theme-image src="@/static/deposit_wheel/bg_gold.png" />
|
|
<theme-image src="@/static/deposit_wheel/bg_diamond.png" />
|
|
<theme-image src="@/static/deposit_wheel/bg_supreme.png" />
|
|
<theme-image v-for="(item, index) in imgPaths" :key="index" :src="item" />
|
|
<theme-image v-for="(item, index) in pointImgs" :key="index" :src="item" />
|
|
<image :src="spinBg" mode="scaleToFill" />
|
|
<image :src="jinbi" mode="scaleToFill" />
|
|
<image :src="zhibi" mode="scaleToFill" />
|
|
<!-- <theme-image src="@/static/deposit_wheel/image_zpwk_gold.png" />
|
|
<theme-image src="@/static/deposit_wheel/image_zpwk_diamond.png" />
|
|
<theme-image src="@/static/deposit_wheel/image_zpwk_supreme.png" />
|
|
<theme-image src="@/static/deposit_wheel/image_zhizhen_silver.png" />
|
|
<theme-image src="@/static/deposit_wheel/image_zhizhen_gold" />
|
|
<theme-image src="@/static/deposit_wheel/image_zhizhen_supreme.png" />
|
|
<theme-image src="@/static/deposit_wheel/image_zhizhen_diamond.png" /> -->
|
|
<!-- <theme-image src="@/static/deposit_wheel/image_zpdk.png" />
|
|
<theme-image src="@/static/spins/image_jinbi.png" />
|
|
<theme-image src="@/static/spins/image_jinbi.png" /> -->
|
|
</view>
|
|
<view class="content w-full" :style="{ background: dw.bgImg, paddingTop: (statusBarHeight + 50) + 'px' }">
|
|
<view class="slogan w-full flex flex-column items-center">
|
|
<theme-image class="slogan-img" src="@/static/deposit_wheel/bt.png" />
|
|
<view class="desc" :style="{ color: dw.text }">
|
|
{{ $t('redeposit.slogan1') }}
|
|
</view>
|
|
<view class="desc" :style="{ color: dw.text }">{{ $t('redeposit.slogan2') }}</view>
|
|
<view class="deposit-btn flex-center" @click="depositNow"
|
|
:style="{ background: dw.btnBg, color: dw.secondary }">
|
|
{{ $t('redeposit.depositNow') }}
|
|
</view>
|
|
<view class="notice">
|
|
<Boardcast />
|
|
</view>
|
|
</view>
|
|
<view class="wheel-content w-full" :style="{ background: imgBgs[active] }">
|
|
<view class="wheel-tab w-full grid-col-4">
|
|
<view v-for="(item, index) in activityContent" :key="index" @click.stop="handleTabClick(index)"
|
|
class="wheel-item flex-1 flex flex-column items-center justify-end relative"
|
|
:style="{ color: dw.light }">
|
|
<template v-if="index === 3">
|
|
<template v-if="disabledIndex == 3">
|
|
<view class="upto">Supreme</view>
|
|
<view class="amount">Wheel</view>
|
|
</template>
|
|
<template v-else>
|
|
<view class="upto">upto</view>
|
|
<view class="amount">{{ currency }}3777</view>
|
|
</template>
|
|
<theme-image v-if="disabledIndex <= 3" class="icon-lock"
|
|
src="@/static/deposit_wheel/image_lock.png" />
|
|
<view v-if="disabledIndex >= 3" class="lot-count flex-center"
|
|
:style="{ color: item.bgImg }">
|
|
{{ spinCounts[index] }}
|
|
</view>
|
|
</template>
|
|
<template v-else>
|
|
<view class="upto">{{ $t('redeposit.upto') }}</view>
|
|
<view class="amount">₹{{ uptoAmount[index] }}</view>
|
|
<theme-image v-if="index >= disabledIndex" class="icon-lock"
|
|
src="@/static/deposit_wheel/image_lock.png" />
|
|
<view class="lot-count flex-center" :style="{ color: item.bgImg }">
|
|
{{ spinCounts[index] }}
|
|
</view>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
<view class="wheel-box">
|
|
<view class="progress-box relative">
|
|
<view class="progress-wrapper">
|
|
<view class="progress-inner" :style="{ width: percent + '%' }"></view>
|
|
</view>
|
|
<view class="float-step flex justify-between pos-absolute">
|
|
<view class="step-item">
|
|
<view class="flex flex-column items-center" :style="{ color: dw.light }">
|
|
<view class="step-img"></view>
|
|
<view class="step-currency"></view>
|
|
<view class="step-count"></view>
|
|
</view>
|
|
</view>
|
|
<view class="step-item" v-for="(item, index) in activityContent[active]?.amounts"
|
|
:key="index">
|
|
<view class="flex flex-column items-center" :style="{ color: dw.light }">
|
|
<view class="step-img">
|
|
<theme-image src="@/static/deposit_wheel/wheel_image.png" class="icon-step" />
|
|
</view>
|
|
<view class="step-currency">{{ currency }} {{ item }}</view>
|
|
<view class="step-count" :style="{ color: dw.tertiary }"> +1 Spin</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- <view class="canvas-content flex items-center"
|
|
:style="{ width: totalW + 'px', height: size + 'px', 'padding-left': canvasSpace + 'px' }">
|
|
<view class="canvas-wrapper relative"
|
|
:style="{ width: size + 'px', height: size + 'px', 'margin-left': canvasSpace + 'px', 'margin-right': canvasSpace + 'px' }">
|
|
<canvas canvas-id="depositWheel" id="depositWheel"
|
|
:style="{ width: size + 'px', height: size + 'px' }"></canvas>
|
|
<view class="click-area pos-absolute" @click.stop="handleStart"></view>
|
|
</view>
|
|
</view> -->
|
|
<view class="wheel-carousel" @touchstart="onTouchStart" @touchmove="onTouchMove"
|
|
@touchend="onTouchEnd">
|
|
<view class="wheel-carousel-inner"
|
|
:style="{ transform: `translateX(${translateX}px)`, transition: animating ? 'transform 0.2s ease' : 'none' }">
|
|
<view v-for="(item, index) in activityContent" :key="index" class="wheel-carousel-item"
|
|
:style="{
|
|
transform: `scale(${calculateScale(index)})`,
|
|
opacity: currentIndex === index ? 1 : 0.8,
|
|
transition: animating ? 'transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease' : 'transform 0.3s ease',
|
|
width: sliceWidth + 'px',
|
|
display: (index === activityContent.length - 1 && rechargeAmount <= 1777) ? 'none' : 'flex'
|
|
}">
|
|
<view class="canvas-wrapper relative"
|
|
:style="{ width: size + 'px', height: size + 'px', margin: '0 auto' }"
|
|
:ref="el => { if (el) wheelRefs[index] = el }">
|
|
<canvas :canvas-id="wheelCanvasIds[index]" :id="wheelCanvasIds[index]"
|
|
:style="{ width: size + 'px', height: size + 'px' }"></canvas>
|
|
<view class="click-area pos-absolute" @click.stop="handleStart"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<theme-image src="@/static/deposit_wheel/bg_lasheng.png" class="w-full bottom-img"
|
|
mode="aspectFill"></theme-image>
|
|
</view>
|
|
<view @click="toRules" class="rules flex-center" :style="{ background: dw.awardBg, color: dw.light }">Rules
|
|
</view>
|
|
<view @click="toHistory" class="rules history flex-center" :style="{ background: dw.awardBg, color: dw.light }">
|
|
History
|
|
</view>
|
|
<Congratulation ref="awardPopup" :prize-amount="awardAmount" :currency="currency" @close="onClose" />
|
|
</mobile-custom-layout>
|
|
</template>
|
|
<style lang="scss" scoped>
|
|
.content {
|
|
min-height: 100vh;
|
|
overflow-x: hidden;
|
|
|
|
.slogan-img {
|
|
width: 458rpx;
|
|
height: 114rpx;
|
|
}
|
|
|
|
.desc {
|
|
font-family: Roboto;
|
|
font-weight: 400;
|
|
font-size: 23rpx;
|
|
color: #F797A1;
|
|
}
|
|
|
|
.deposit-btn {
|
|
width: 350rpx;
|
|
height: 78rpx;
|
|
margin-top: 15rpx;
|
|
font-family: Roboto;
|
|
font-weight: 600;
|
|
font-size: 31rpx;
|
|
color: #7B0810;
|
|
}
|
|
|
|
.notice {
|
|
width: 575rpx;
|
|
margin-top: 34rpx;
|
|
}
|
|
|
|
.bottom-img {
|
|
height: 300rpx;
|
|
}
|
|
|
|
.wheel-content {
|
|
height: 854rpx;
|
|
margin-top: 27rpx;
|
|
// overflow-x: hidden;
|
|
|
|
.wheel-tab {
|
|
height: 146rpx;
|
|
|
|
.wheel-item {
|
|
font-family: Roboto;
|
|
font-weight: 400;
|
|
font-size: 23rpx;
|
|
color: #FFFFFF;
|
|
line-height: 25rpx;
|
|
|
|
.amount {
|
|
margin-bottom: 4rpx;
|
|
margin-top: 4rpx;
|
|
}
|
|
|
|
.icon-lock {
|
|
width: 28rpx;
|
|
height: 36rpx;
|
|
position: absolute;
|
|
top: 47rpx;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.lot-count {
|
|
width: 36rpx;
|
|
height: 36rpx;
|
|
background: linear-gradient(0deg, #C62D2C, #ED6556);
|
|
border-radius: 50%;
|
|
font-family: Roboto;
|
|
font-weight: 400;
|
|
font-size: 23rpx;
|
|
color: #FFFFFF;
|
|
line-height: 25rpx;
|
|
position: absolute;
|
|
top: -8rpx;
|
|
right: -2rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.grid-col-4 {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
grid-template-rows: auto;
|
|
column-gap: 20rpx;
|
|
}
|
|
|
|
.wheel-box {
|
|
width: 100%;
|
|
margin-top: 20rpx;
|
|
overflow-x: hidden;
|
|
|
|
.progress-box {
|
|
width: 688rpx;
|
|
height: 94rpx;
|
|
padding: 0 16rpx;
|
|
padding-top: 14rpx;
|
|
margin: 0 auto;
|
|
|
|
.progress-wrapper {
|
|
width: 100%;
|
|
height: 27rpx;
|
|
background: linear-gradient(0deg, #670003, #88000E);
|
|
border-radius: 14rpx;
|
|
border: 1px solid #F3B459;
|
|
|
|
.progress-inner {
|
|
height: 100%;
|
|
background: linear-gradient(0deg, #EDC148, #EAAB32, #FFF237, #FFFCA0, #FFF137);
|
|
border-radius: 13rpx;
|
|
}
|
|
}
|
|
|
|
.float-step {
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
.step-item {
|
|
position: relative;
|
|
right: -14rpx;
|
|
}
|
|
|
|
.step-img {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
}
|
|
|
|
.icon-step {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
display: block;
|
|
}
|
|
|
|
.step-currency {
|
|
font-size: 25rpx;
|
|
line-height: 24rpx;
|
|
}
|
|
|
|
.step-count {
|
|
font-size: 22rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.canvas-content {
|
|
margin-top: 24rpx;
|
|
}
|
|
|
|
.canvas-wrapper {
|
|
|
|
.click-area {
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
z-index: 100;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.count-box {
|
|
min-width: 164rpx;
|
|
height: 42rpx;
|
|
background: #050202;
|
|
border-radius: 21rpx;
|
|
border: 2px solid #301A1A;
|
|
|
|
.icon-coin {
|
|
width: 34rpx;
|
|
height: 32rpx;
|
|
margin-left: 4rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.coin-amount {
|
|
font-family: Roboto;
|
|
font-weight: 400;
|
|
font-size: 21rpx;
|
|
color: #FFD45B;
|
|
margin-left: 16rpx;
|
|
}
|
|
}
|
|
|
|
.wheel-carousel {
|
|
width: 100%;
|
|
overflow: hidden;
|
|
position: relative;
|
|
margin-top: 24rpx;
|
|
}
|
|
|
|
.wheel-carousel-inner {
|
|
display: flex;
|
|
width: 100%;
|
|
will-change: transform;
|
|
}
|
|
|
|
.wheel-carousel-item {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
transform-origin: center center;
|
|
}
|
|
|
|
.rules {
|
|
position: fixed;
|
|
left: 0;
|
|
top: 220rpx;
|
|
width: 96rpx;
|
|
height: 52rpx;
|
|
z-index: 999;
|
|
font-family: Roboto;
|
|
font-weight: 400;
|
|
font-size: 23rpx;
|
|
color: #FFFFFF;
|
|
}
|
|
|
|
.history {
|
|
top: 300rpx;
|
|
}
|
|
</style> |