12 Commits

  1. 2
      src/api/API.js
  2. BIN
      src/assets/dong.mp3
  3. BIN
      src/assets/music.mp3
  4. BIN
      src/assets/worldcup.mp3
  5. BIN
      src/data/music.mp3
  6. 311
      src/views/choujiang/hxl-cj/cj.vue
  7. 171
      src/views/choujiang/index.vue
  8. 40
      src/views/choujiang/lottery/MusicPlayer.vue
  9. 140
      src/views/choujiang/lottery/PrizePanel.vue

2
src/api/API.js

@ -26,7 +26,7 @@ export const getGetPrizeUserListApi = function (params) {
return request({
url: `${APIurl}/api/winUser/list`,
method: "POST",
data: params,
data: new URLSearchParams(params),
});
};

BIN
src/assets/dong.mp3

BIN
src/assets/music.mp3

BIN
src/assets/worldcup.mp3

BIN
src/data/music.mp3

311
src/views/choujiang/hxl-cj/cj.vue

@ -1,10 +1,11 @@
<template>
<div class="homepage">
<img src="../../../assets/qilin.webp" alt="麒麟" class="hllogo" />
<div class="music" @click="musicPlay()">
<audio id="music" :src="musicFile" class="music-item" loop></audio>
<div id="musicBox" class="music-box" title="播放/暂停背景音乐">Music</div>
</div>
<!-- 添加worldcup音频元素 -->
<audio ref="worldcupAudioRef" :src="worldcup" preload="auto" loop></audio>
<!-- 添加dong音频元素 -->
<audio ref="dongAudioRef" :src="dong" preload="auto"></audio>
<div ref="qipaoTextRef" class="qipao">{{ qipaoText }}</div>
@ -91,6 +92,16 @@
</div>
</div>
</el-scrollbar>
<div class="tableFoot">
<span @click="leftPage()" style="cursor: pointer"><</span>
{{ currentPage }}
<span @click="rightPage()" style="cursor: pointer">></span>
<span class="tableTotalPage">
<span>{{ totalPage }}</span>
</span>
</div>
</div>
</div>
</div>
@ -104,22 +115,6 @@
</div>
</div>
<!-- <img
src="../../../assets/img/展开.png"
alt="向右"
@click="rightPage()"
class="rightPage"
id="rightPage"
/>
<img
src="../../../assets/img/展开.png"
alt="向左"
@click="leftPage()"
class="leftPage"
id="leftPage"
/> -->
<div id="menu">
<div id="enter" ref="enterRef" @click="enterLottery()" class="btn">
进入抽奖
@ -137,7 +132,6 @@
<script setup>
import { ref, onMounted, reactive, nextTick } from "vue";
import { useRouter } from "vue-router";
import musicFile from "../../../data/music.mp3";
import * as THREE from "three";
import axios from "axios";
import "../../../assets/css/animate.min.css";
@ -146,6 +140,8 @@ import { NUMBER_MATRIX } from "../../../utils/config";
import { CSS3DObject, CSS3DRenderer } from "../../../utils/CSS3DRenderer.js";
import { TrackballControls } from "../../../utils/TrackballControls.js";
import TWEEN from "@tweenjs/tween.js";
import worldcup from "../../../assets/worldcup.mp3";
import dong from "../../../assets/dong.mp3";
import {
getPrizeListApi,
@ -214,6 +210,42 @@ let prizeElement = {};
const qipaoText = ref("");
const qipaoTextRef = ref(null);
const worldcupAudioRef = ref(null);
const dongAudioRef = ref(null);
// worldcup
const playWorldcupAudio = () => {
if (worldcupAudioRef.value) {
worldcupAudioRef.value.currentTime = 0; //
worldcupAudioRef.value.play().catch((error) => {
console.log("音频播放失败:", error);
});
}
};
// worldcup
const pauseWorldcupAudio = () => {
if (worldcupAudioRef.value) {
worldcupAudioRef.value.pause();
}
};
const playDongAudio = () => {
if (dongAudioRef.value) {
dongAudioRef.value.currentTime = 0; //
dongAudioRef.value.play().catch((error) => {
console.log("音频播放失败:", error);
});
}
};
// dong
const pauseDongAudio = () => {
if (dongAudioRef.value) {
dongAudioRef.value.pause();
}
};
const addQipao = (text) => {
qipaoTextRef.value.style.display = "block";
qipaoTextRef.value.style.opacity = "1";
@ -233,14 +265,25 @@ const addQipao = (text) => {
const getPrizeUserList = ref([]);
const isOpen = ref(false);
const pageObj = ref({
pageNum: 1,
pageSize: 14,
});
const currentPage = ref(1);
const totalPage = ref(10);
const openGetPrize = async () => {
if (!prizes.value[prizes.value.length - 1].isLook) {
addQipao("请先揭晓奖品。");
return;
}
let res = await getGetPrizeUserListApi({});
let res = await getGetPrizeUserListApi(pageObj.value);
getPrizeUserList.value = res.data.list;
currentPage.value = res.data.pageNum;
totalPage.value = res.data.pages;
isOpen.value = true;
// console.log("currentPrize", currentPrize.value);
prizes.value.forEach((item) => {
@ -267,6 +310,23 @@ const closeGetPrize = () => {
// scroll.style.height = "650px";
};
const leftPage = async (item) => {
if (currentPage.value == 1) return;
currentPage.value--;
pageObj.value.pageNum = currentPage;
let res = await getGetPrizeUserListApi(pageObj.value);
getPrizeUserList.value = res.data.list;
currentPage.value = res.data.pageNum;
};
const rightPage = async (item) => {
if (currentPage.value == totalPage.value) return;
currentPage.value++;
pageObj.value.pageNum = currentPage;
let res = await getGetPrizeUserListApi(pageObj.value);
getPrizeUserList.value = res.data.list;
currentPage.value = res.data.pageNum;
};
//
const lookPrize = async (item) => {
//
@ -648,132 +708,6 @@ function render() {
renderer.render(scene, camera);
}
//
// const rightPage = () => {
// if (pageIndex == pageMaxIndex) return;
// console.log("");
// //
// resetCard(300).then(() => {
// pageIndex++;
// selectCard(600, pageIndex);
// });
// };
// const leftPage = () => {
// if (pageIndex == 0) return;
// console.log("");
// //
// resetCard(300).then(() => {
// pageIndex--;
// selectCard(600, pageIndex);
// });
// };
//
// function selectCard(duration = 600, index = 0) {
// console.log("pageIndex", pageIndex, "pageMaxIndex", pageMaxIndex);
// let right = document.getElementById("rightPage");
// let left = document.getElementById("leftPage");
// right.style.display = "flex";
// left.style.display = "flex";
// pageMaxIndex = Math.ceil(selectedCardIndex.length / 10) - 1;
// let getCurrentIndex = [];
// for (let i = 0; i < selectedCardIndex.length; i += 10) {
// getCurrentIndex.push(selectedCardIndex.slice(i, i + 10));
// }
// let getCurrentLucky = [];
// for (let i = 0; i < currentLuckys.length; i += 10) {
// getCurrentLucky.push(currentLuckys.slice(i, i + 10));
// }
// console.log("getCurrentIndex", getCurrentIndex);
// console.log("getCurrentLucky", getCurrentLucky);
// rotate = false; //
// let width = 180;
// let tag = -(getCurrentLucky[index].length - 1) / 2;
// let locates = [];
// // , 5
// if (getCurrentLucky[index].length > 5) {
// let yPosition = [-120, 120];
// let l = getCurrentIndex[index].length;
// let mid = Math.ceil(l / 2);
// tag = -(mid - 1) / 2;
// for (let i = 0; i < mid; i++) {
// locates.push({
// x: tag * width * Resolution,
// y: yPosition[0] * Resolution,
// });
// tag++;
// }
// console.log("locates", locates);
// // console.log("selectedCardIndex", selectedCardIndex);
// // console.log("currentLuckys", currentLuckys);
// tag = -(l - mid - 1) / 2;
// for (let i = mid; i < l; i++) {
// locates.push({
// x: tag * width * Resolution,
// y: yPosition[1] * Resolution,
// });
// tag++;
// }
// } else {
// for (let i = getCurrentIndex[index].length; i > 0; i--) {
// locates.push({
// x: tag * width * Resolution,
// y: 0 * Resolution,
// });
// tag++;
// }
// }
// getCurrentIndex[index].forEach((cardIndex, iindex) => {
// changeCard(cardIndex, getCurrentLucky[index][iindex]);
// var object = threeDCards[cardIndex];
// new TWEEN.Tween(object.position)
// .to(
// {
// x: locates[iindex].x,
// y: locates[iindex].y * Resolution,
// z: 2000,
// },
// Math.random() * duration + duration
// )
// .easing(TWEEN.Easing.Exponential.InOut)
// .start();
// new TWEEN.Tween(object.rotation)
// .to(
// {
// x: 0,
// y: 0,
// z: 0,
// },
// Math.random() * duration + duration
// )
// .easing(TWEEN.Easing.Exponential.InOut)
// .start();
// object.element.classList.add("prize");
// });
// new TWEEN.Tween(this)
// .to({}, duration * 2)
// .onUpdate(render)
// .start()
// .onComplete(() => {
// //
// setLotteryStatus();
// });
// }
const threeContainer = ref(null);
function selectCard(duration = 600) {
return new Promise((resolve) => {
@ -1118,6 +1052,9 @@ const lotteryBtn = () => {
return;
}
// worldcup
playWorldcupAudio();
getPrizeUsers.value = [];
let params = {
gradeId: currentPrize.value.gradeId,
@ -1186,6 +1123,10 @@ const lottery = () => {
const stopLottery = () => {
lotteryRef.value.innerHTML = "开始抽奖";
rotateObj.stop();
// worldcup
pauseWorldcupAudio();
playDongAudio();
};
const changePrize = async () => {
@ -1284,70 +1225,6 @@ const createHighlight = () => {
return highlight;
};
//
const initMusicPlayer = () => {
const musicBox = document.querySelector("#musicBox");
if (musicBox) {
// 1
setTimeout(() => {
musicPlay();
}, 1000);
}
};
const musicPlay = () => {
console.log("musicPlay 方法被调用");
const music = document.querySelector("#music");
const musicBox = document.querySelector("#musicBox");
if (!music || !musicBox) {
console.error("音乐元素未找到");
return;
}
if (music.paused) {
music
.play()
.then(() => {
console.log("音乐开始播放");
startRotateAnimation(musicBox);
})
.catch((error) => {
console.error("音乐播放失败:", error);
});
} else {
console.log("音乐暂停");
music.pause();
stopRotateAnimation();
}
};
//
let rotationState = { rotated: 0, stopAnimate: false, animationId: null };
const startRotateAnimation = (element) => {
rotationState.stopAnimate = false;
function animate() {
if (rotationState.stopAnimate) return;
rotationState.rotated = (rotationState.rotated + 1) % 360;
element.style.transform = `rotate(${rotationState.rotated}deg)`;
rotationState.animationId = requestAnimationFrame(animate);
}
animate();
};
const stopRotateAnimation = () => {
rotationState.stopAnimate = true;
if (rotationState.animationId) {
cancelAnimationFrame(rotationState.animationId);
rotationState.animationId = null;
}
};
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
@ -1736,7 +1613,7 @@ a {
display: flex;
margin-top: 50px;
width: 100%;
height: 54vh;
height: 50vh;
justify-content: center;
overflow-y: auto;
/* 启用垂直滚动 */
@ -1772,6 +1649,14 @@ a {
text-align: center;
}
.tableFoot {
color: black;
}
.tableTotalPage {
font-size: 10px;
}
.readyLook {
width: 100%;
height: 100%;

171
src/views/choujiang/index.vue

@ -9,7 +9,7 @@
@reset="handleReset"
@export="handleExport"
/>
<MusicPlayer ref="musicPlayerRef" />
<!-- <MusicPlayer ref="musicPlayerRef" /> -->
<Mascot />
<!-- 透明弹窗 -->
@ -41,13 +41,15 @@
/> -->
<!-- <Qipao :text="qipaoText" :show="showQipao" /> -->
</div>
<audio ref="audioRef" :src="musicSrc" loop preload="auto"></audio>
<audio ref="audioRef1" :src="musicSrc1" preload="auto"></audio>
</template>
<script setup>
import Lottery3D from "./lottery/Lottery3D.vue";
import PrizePanel from "./lottery/PrizePanel.vue";
import ControlBar from "./lottery/ControlBar.vue";
import MusicPlayer from "./lottery/MusicPlayer.vue";
// import MusicPlayer from "./lottery/MusicPlayer.vue";
import Qipao from "./lottery/Qipao.vue";
import UserList from "./lottery/UserList.vue";
import Mascot from "./lottery/Mascot.vue";
@ -109,7 +111,7 @@ const lotteryEngine = useLotteryEngine(dataManager, {
onMounted(async () => {
isDisabled.value = true;
await dataManager.getBasicData();
await dataManager.getUsers();
@ -117,19 +119,30 @@ onMounted(async () => {
isDisabled.value = false;
}, 3800);
// dataManager window 使
window.dataManager = dataManager;
//
setTimeout(() => {
if (musicPlayerRef.value && !musicPlayerRef.value.isPlaying()) {
//
musicPlayerRef.value.toggleMusic();
}
}, 1000);
//
preloadAudio();
});
//
function preloadAudio() {
if (audioRef.value) {
audioRef.value.load();
//
audioRef.value.addEventListener('canplaythrough', () => {
console.log('背景音乐预加载完成');
});
}
if (audioRef1.value) {
audioRef1.value.load();
audioRef1.value.addEventListener('canplaythrough', () => {
console.log('音效预加载完成');
});
}
}
function showLotteryQipao() {
const luckys = dataManager.state.currentLuckys;
const prize = dataManager.state.currentPrize;
@ -145,6 +158,75 @@ function showLotteryQipao() {
}, 3000);
}
import musicFile from "/src/assets/worldcup.mp3";
import musicFile1 from "/src/assets/dong.mp3";
const musicSrc = musicFile;
const audioRef = ref(null);
const playing = ref(false);
const musicSrc1 = musicFile1;
const audioRef1 = ref(null);
const playing1 = ref(false);
async function toggleMusic() {
if (!audioRef.value) return;
try {
if (audioRef.value.paused) {
//
if (audioRef.value.readyState < 2) {
await new Promise((resolve) => {
audioRef.value.addEventListener('canplay', resolve, { once: true });
audioRef.value.load();
});
}
await audioRef.value.play();
playing.value = true;
} else {
audioRef.value.pause();
playing.value = false;
}
} catch (error) {
console.error('播放音乐失败:', error);
}
}
async function playMusic1() {
if (!audioRef1.value) return;
try {
//
audioRef1.value.currentTime = 0;
//
if (audioRef1.value.readyState < 2) {
await new Promise((resolve) => {
audioRef1.value.addEventListener('canplay', resolve, { once: true });
audioRef1.value.load();
});
}
await audioRef1.value.play();
playing1.value = true;
//
audioRef1.value.addEventListener('ended', () => {
playing1.value = false;
}, { once: true });
} catch (error) {
console.error('播放音效失败:', error);
}
}
function isPlaying1() {
return playing1.value;
}
//
function isPlaying() {
return playing.value;
}
async function handleLotteryClick() {
if (isDisabled.value) return; // 2
isDisabled.value = true;
@ -191,20 +273,25 @@ async function handleLotteryClick() {
break;
}
if (lastRevealed.value === 0 && dataManager.state.basicData.prizes[lastRevealed.value].remainNum === 0) {
if (
lastRevealed.value === 0 &&
dataManager.state.basicData.prizes[lastRevealed.value].remainNum === 0
) {
// 0
// const currentPrize = dataManager.state.basicData.prizes[lastRevealed.value];
// if (currentPrize && currentPrize.remainNum === 0) {
showPrizeExhaustedModal2.value = true;
setTimeout(() => {
showPrizeExhaustedModal2.value = false;
}, 1000);
isDisabled.value = false;
showPrizeExhaustedModal2.value = true;
setTimeout(() => {
showPrizeExhaustedModal2.value = false;
}, 1000);
isDisabled.value = false;
break;
// }
}
toggleMusic();
console.log("lotteryState 变更前:", lotteryState.value, "-> rotating");
lotteryState.value = "rotating";
console.log("lotteryState 变更后:", lotteryState.value);
@ -228,6 +315,16 @@ async function handleLotteryClick() {
}, 2000);
console.log("drawLottery 调用成功,结果:", winnerList.value);
//
// if (window.dataManager && window.dataManager.updatePrizeList) {
// try {
// await window.dataManager.updatePrizeList();
// console.log("");
// } catch (error) {
// console.error(":", error);
// }
// }
} catch (error) {
console.error("drawLottery 调用失败:", error);
}
@ -239,24 +336,17 @@ async function handleLotteryClick() {
setTimeout(() => {
isDisabled.value = false;
}, 2000);
//
// const prize = dataManager.state.basicData.prizes[lastRevealed.value];
// console.log(" drawLotteryprize:", prize);
// console.log("lastRevealed.value:", lastRevealed.value);
// try {
// winnerList.value = await drawLottery({
// perWin: prize.perWin,
// remainNum: prize.remainNum,
// gradeId: prize.gradeId,
// prizeId: prize.prizeId,
// });
// console.log("drawLottery :", winnerList.value);
// } catch (error) {
// console.error("drawLottery :", error);
// }
// toggleMusic();
// toggleMusic();
await lottery3DRef.value?.rotateBallStop?.();
toggleMusic();
playMusic1();
await lotteryEngine.executeLottery();
await nextTick();
showLotteryQipao();
console.log("lotteryState 变更前:", lotteryState.value, "-> idle");
@ -359,13 +449,20 @@ function handleNextPrize() {
font-weight: bold;
margin: 0;
white-space: nowrap;
}
@keyframes fadeInOut {
0% { opacity: 0; }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; }
0% {
opacity: 0;
}
20% {
opacity: 1;
}
80% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>

40
src/views/choujiang/lottery/MusicPlayer.vue

@ -1,13 +1,14 @@
<template>
<div class="music-box" @click="toggleMusic">
<audio ref="audioRef" :src="musicSrc" loop></audio>
<div class="music-icon" :class="{ playing }"></div>
<!-- <div class="music-icon" :class="{ playing }">music</div> -->
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const musicSrc = '/src/assets/music.mp3';
import musicFile from '/src/assets/music.mp3';
const musicSrc = musicFile;
const audioRef = ref(null);
const playing = ref(false);
@ -27,19 +28,19 @@ function isPlaying() {
return playing.value;
}
//
onMounted(() => {
//
setTimeout(() => {
if (audioRef.value) {
audioRef.value.play().then(() => {
playing.value = true;
}).catch((error) => {
console.log('自动播放失败,可能需要用户交互:', error);
});
}
}, 500);
});
// //
// onMounted(() => {
// //
// setTimeout(() => {
// if (audioRef.value) {
// audioRef.value.play().then(() => {
// playing.value = true;
// }).catch((error) => {
// console.log(':', error);
// });
// }
// }, 500);
// });
//
defineExpose({
@ -62,12 +63,17 @@ defineExpose({
.music-icon {
width: 100%;
height: 100%;
background: url('/src/assets/lottery/edifier.jpg') no-repeat center/cover;
background: orangered;
border-radius: 50%;
transition: box-shadow 0.2s;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
color: #fff;
}
.music-icon.playing {
animation: rotate 1.2s linear infinite;
animation: rotate 3s linear infinite;
/* box-shadow: 0 0 12px #0078ff; */
}
@keyframes rotate {

140
src/views/choujiang/lottery/PrizePanel.vue

@ -137,7 +137,7 @@
></div>
<ul class="winner-list">
<li
v-for="(user, idx) in fakeWinners"
v-for="(user, idx) in paginatedWinners"
:key="idx"
style="
display: flex;
@ -150,6 +150,24 @@
<span>{{ user.prizeName }}</span>
</li>
</ul>
<!-- 分页控件 -->
<div class="pagination-controls">
<button
class="pagination-btn prev-btn"
@click="prevPage"
:disabled="currentPage === 1"
>
&lt;
</button>
<span class="page-info">{{ currentPage }} / {{ totalPages }}</span>
<button
class="pagination-btn next-btn"
@click="nextPage"
:disabled="currentPage === totalPages"
>
&gt;
</button>
</div>
</div>
</div>
</div>
@ -199,12 +217,27 @@ const winners = computed({
set: (val) => lotteryStore.setWinners(val),
});
//
const lotteryState = computed({
get: () => lotteryStore.lotteryState,
set: (val) => lotteryStore.setLotteryState(val),
});
// watchwinners
// watch(winners, (newVal) => {
// console.log("winners", newVal);
// fakeWinners.value = newVal;
// });
//
watch(lotteryState, (newState, oldState) => {
if (oldState === 'rotating' && newState === 'result') {
//
console.log("开奖完成,开始更新获奖名单数据");
updateWinners();
}
});
const lastRevealedIdx = ref(-1);
lastRevealedIdx.value = lastRevealed.value;
@ -283,16 +316,62 @@ const fakeWinners = ref([]);
// fakeWinners.value = winners.value;
console.log("fakeWinners", fakeWinners.value);
//
const currentPage = ref(1);
const pageSize = ref(16); // 20
const totalPages = ref(1);
//
const paginatedWinners = computed(() => {
const startIndex = (currentPage.value - 1) * pageSize.value;
const endIndex = startIndex + pageSize.value;
return fakeWinners.value.slice(startIndex, endIndex);
});
//
const calculateTotalPages = () => {
totalPages.value = Math.ceil(fakeWinners.value.length / pageSize.value);
if (totalPages.value === 0) totalPages.value = 1;
};
//
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--;
}
};
//
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
};
import { getGetPrizeUserListApi } from "../../../api/API";
const updateWinners = async () => {
try {
const response = await getGetPrizeUserListApi({
pageSize: 1000,
pageSize: 1000000,
pageNum: 1,
});
console.log("updatePrizeList response", response);
fakeWinners.value = response.data.list;
// createTimeid
const sortedWinners = response.data.list.sort((a, b) => {
if (a.createTime && b.createTime) {
return new Date(b.createTime) - new Date(a.createTime);
}
// id
return (b.id || 0) - (a.id || 0);
});
fakeWinners.value = sortedWinners;
console.log("updateWinners fakeWinners", fakeWinners.value);
//
currentPage.value = 1;
calculateTotalPages();
} catch (error) {
console.error("updatePrizeList error", error);
}
@ -374,6 +453,7 @@ function getProgressPercent(prize) {
onMounted(() => {
updateWinners();
calculateTotalPages();
});
</script>
@ -590,6 +670,7 @@ onMounted(() => {
justify-content: center;
}
.winner-modal {
height: 700px;
background: rgba(255, 210, 131, 0.8);
border-radius: 12px;
padding-top: 12px;
@ -623,7 +704,7 @@ onMounted(() => {
cursor: pointer;
}
.winner-list {
max-height: 260px;
height: 580px;
/* background: rgba(255, 210, 131, 0.8);/ */
overflow-y: auto;
padding: 0;
@ -638,7 +719,7 @@ onMounted(() => {
display: none; /* Chrome, Safari and Opera */
}
.winner-list li {
padding: 8px 0;
padding: 7px 0;
/* border-bottom: 1px solid #f2f2f2; */
font-size: 17px;
color: #d84315;
@ -704,7 +785,7 @@ onMounted(() => {
}
.prize-panel-item.revealed-highlight {
/* border: 3px solid #ff9800; */
box-shadow: 0 0 16px 4px #ff9800aa;
box-shadow: 0 0 16px 4px #ff9800ff, 0 0 20px 6px #ffcc80ff;
transform: scale(1.03);
z-index: 2;
transition: all 0.3s;
@ -741,4 +822,51 @@ onMounted(() => {
.prize-panel-item.disabled:hover::after {
opacity: 1;
}
/* 分页控件样式 */
.pagination-controls {
display: flex;
justify-content: center;
align-items: center;
gap: 15px;
margin-top: 15px;
padding: 10px 0;
}
.pagination-btn {
background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%);
color: white;
border: none;
border-radius: 50%;
width: 35px;
height: 35px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.pagination-btn:hover:not(:disabled) {
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.pagination-btn:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.page-info {
font-size: 18px;
font-weight: bold;
color: #d84315;
min-width: 60px;
text-align: center;
}
</style>
Loading…
Cancel
Save