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.

871 lines
22 KiB

4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
  1. <template>
  2. <div v-if="showOne">
  3. <div class="prize-panel-root">
  4. <div v-if="showNotification" class="auto-hide-notification">
  5. {{ notificationMessage }}
  6. </div>
  7. <div class="prize-panel-list" v-if="prizes && prizes.length">
  8. <div
  9. class="prize-panel-item"
  10. v-for="(prize, idx) in prizes"
  11. :key="prize.type || idx"
  12. :class="{
  13. 'revealed-highlight': idx === lastRevealedIdx,
  14. disabled: idx === nextRevealIdx && !canRevealPrize(idx),
  15. }"
  16. @click="handleReveal(idx)"
  17. :style="{
  18. cursor:
  19. idx === nextRevealIdx && !canRevealPrize(idx)
  20. ? 'not-allowed'
  21. : 'pointer',
  22. }"
  23. >
  24. <div v-if="isRevealed(idx)" class="prize-card">
  25. <div class="prize-img-wrap">
  26. <img class="prize-img" :src="prize.img" :alt="prize.title" />
  27. </div>
  28. <div class="prize-info">
  29. <div class="prize-row prize-row-top">
  30. <span class="prize-level">{{ prize.title }}</span>
  31. <span class="prize-name">{{ prize.text }}</span>
  32. </div>
  33. <div class="prize-row prize-row-bottom">
  34. <div class="progress-bar-bg">
  35. <div
  36. class="progress-bar-fill"
  37. :style="{ width: getProgressPercent(prize) + '%' }"
  38. ></div>
  39. <span class="progress-bar-text">
  40. {{ getLeftCount(prize) }}/{{ prize.count }}
  41. </span>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. <div v-else class="prize-card prize-card-mask">
  47. <img
  48. src="../../../assets/daijiemi.png"
  49. alt="待揭秘"
  50. class="prize-mask-img"
  51. />
  52. </div>
  53. </div>
  54. </div>
  55. <div class="prize-panel-footer">
  56. <div class="arrow-up" @click="openWinnerList"></div>
  57. <button ref="winnerBtnRef" class="winner-btn" @click="openWinnerList">
  58. 获奖名单
  59. </button>
  60. </div>
  61. </div>
  62. </div>
  63. <div v-else>
  64. <div class="prize-panel-root">
  65. <div
  66. class="prize-panel-list1"
  67. v-if="prizes && prizes.length && lastRevealedIdx >= 0"
  68. >
  69. <div
  70. class="prize-panel-item"
  71. :key="prizes[lastRevealedIdx].type || lastRevealedIdx"
  72. :class="{ 'revealed-highlight': true }"
  73. style="cursor: pointer"
  74. >
  75. <div class="prize-card">
  76. <div class="prize-img-wrap">
  77. <img
  78. class="prize-img"
  79. :src="prizes[lastRevealedIdx].img"
  80. :alt="prizes[lastRevealedIdx].title"
  81. />
  82. </div>
  83. <div class="prize-info">
  84. <div class="prize-row prize-row-top">
  85. <span class="prize-level">{{
  86. prizes[lastRevealedIdx].title
  87. }}</span>
  88. <span class="prize-name">{{
  89. prizes[lastRevealedIdx].text
  90. }}</span>
  91. </div>
  92. <div class="prize-row prize-row-bottom">
  93. <div class="progress-bar-bg">
  94. <div
  95. class="progress-bar-fill"
  96. :style="{
  97. width: getProgressPercent(prizes[lastRevealedIdx]) + '%',
  98. }"
  99. ></div>
  100. <span class="progress-bar-text">
  101. {{ getLeftCount(prizes[lastRevealedIdx]) }}/{{
  102. prizes[lastRevealedIdx].count
  103. }}
  104. </span>
  105. </div>
  106. <div class="prize-panel-footer">
  107. <div class="arrow-down" @click="toggleWinnerList"></div>
  108. <div
  109. v-if="showWinnerList"
  110. class="winner-modal-mask"
  111. @click="closeWinnerList"
  112. >
  113. <div
  114. class="winner-modal"
  115. :style="{
  116. position: 'absolute',
  117. left: modalLeft + 'px',
  118. top: modalTop + 'px',
  119. }"
  120. @click.stop
  121. >
  122. <div class="winner-modal-title">
  123. <span>Homily ID</span><span>奖项</span>
  124. </div>
  125. <div
  126. style="
  127. background: linear-gradient(
  128. to left,
  129. rgb(232 76 10),
  130. rgb(195 6 6),
  131. rgb(240 90 9)
  132. );
  133. height: 1px;
  134. "
  135. ></div>
  136. <ul class="winner-list">
  137. <li
  138. v-for="(user, idx) in paginatedWinners"
  139. :key="idx"
  140. style="
  141. display: flex;
  142. justify-content: space-between;
  143. align-items: center;
  144. "
  145. >
  146. <!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - -->
  147. <span>{{ user.jwcode }}</span>
  148. <span>{{ user.prizeName }}</span>
  149. </li>
  150. </ul>
  151. <!-- 分页控件 -->
  152. <div class="pagination-controls">
  153. <button
  154. class="pagination-btn prev-btn"
  155. @click="prevPage"
  156. :disabled="currentPage === 1"
  157. >
  158. &lt;
  159. </button>
  160. <span class="page-info">{{ currentPage }} / {{ totalPages }}</span>
  161. <button
  162. class="pagination-btn next-btn"
  163. @click="nextPage"
  164. :disabled="currentPage === totalPages"
  165. >
  166. &gt;
  167. </button>
  168. </div>
  169. </div>
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. </div>
  175. </div>
  176. </div>
  177. </div>
  178. </div>
  179. </template>
  180. <script setup>
  181. import { ref, computed, nextTick, watch, onMounted } from "vue";
  182. import { useLotteryStore } from "../../../store/lottery";
  183. import { useDataManager } from "../lottery/dataManager";
  184. const showNotification = ref(false);
  185. const notificationMessage = ref('');
  186. // 显示提示并自动消失
  187. const showAutoHideNotification = (message, duration = 1500) => {
  188. notificationMessage.value = message;
  189. showNotification.value = true;
  190. setTimeout(() => {
  191. showNotification.value = false;
  192. }, duration);
  193. };
  194. const props = defineProps({
  195. prizes: Array,
  196. });
  197. // 新增:控制已揭秘奖品数量
  198. const revealedCount = ref(0);
  199. // 新增:记录最新揭秘的奖品索引
  200. const lotteryStore = useLotteryStore();
  201. const lastRevealed = computed({
  202. get: () => lotteryStore.lastRevealedIdx,
  203. set: (val) => lotteryStore.setLastRevealedIdx(val),
  204. });
  205. const waitingForNextReveal = computed({
  206. get: () => lotteryStore.waitingForNextReveal,
  207. set: (val) => lotteryStore.setWaitingForNextReveal(val),
  208. });
  209. const winners = computed({
  210. get: () => lotteryStore.winners,
  211. set: (val) => lotteryStore.setWinners(val),
  212. });
  213. // 添加开奖状态的计算属性
  214. const lotteryState = computed({
  215. get: () => lotteryStore.lotteryState,
  216. set: (val) => lotteryStore.setLotteryState(val),
  217. });
  218. // 用watch监听winners的变化
  219. // watch(winners, (newVal) => {
  220. // console.log("中奖人数列表winners", newVal);
  221. // fakeWinners.value = newVal;
  222. // });
  223. // 监听开奖状态变化,当开奖完成后更新获奖名单
  224. watch(lotteryState, (newState, oldState) => {
  225. if (oldState === 'rotating' && newState === 'result') {
  226. // 开奖完成,更新获奖名单数据
  227. console.log("开奖完成,开始更新获奖名单数据");
  228. updateWinners();
  229. }
  230. });
  231. const lastRevealedIdx = ref(-1);
  232. lastRevealedIdx.value = lastRevealed.value;
  233. const showOne = ref(true);
  234. // 计算哪些奖品已揭秘
  235. const isRevealed = (idx) =>
  236. idx >= (props.prizes?.length || 0) - revealedCount.value;
  237. // 允许点击的卡片index
  238. const nextRevealIdx = computed(
  239. () => (props.prizes?.length || 0) - revealedCount.value - 1
  240. );
  241. // 检查指定奖品是否可以揭秘
  242. function canRevealPrize(idx) {
  243. // 如果这是第一个要揭秘的奖品,直接允许
  244. if (lastRevealedIdx.value === -1) {
  245. return true;
  246. }
  247. // 检查上一个揭秘的奖品是否已经抽完
  248. const lastPrize = props.prizes[lastRevealedIdx.value];
  249. if (lastPrize) {
  250. const leftCount = getLeftCount(lastPrize);
  251. // 如果上一个奖品还有剩余,则不能揭秘下一个
  252. if (leftCount > 0) {
  253. waitingForNextReveal.value = false;
  254. return false;
  255. }
  256. waitingForNextReveal.value = true;
  257. }
  258. return true;
  259. }
  260. // 卡片点击事件
  261. function handleReveal(idx) {
  262. // 检查是否可以揭秘这个奖品
  263. if (idx !== nextRevealIdx.value && !isRevealed(idx)) {
  264. // alert("请按顺序揭秘奖品!");
  265. showAutoHideNotification("请按顺序揭秘奖品!");
  266. return;
  267. }
  268. if (idx === nextRevealIdx.value && canRevealPrize(idx)) {
  269. revealedCount.value++;
  270. lastRevealedIdx.value = idx; // 记录最新揭秘的索引
  271. if (idx === 0) {
  272. waitingForNextReveal.value = false;
  273. }
  274. console.log("lastRevealedIdx.value", lastRevealedIdx.value);
  275. lastRevealed.value = idx;
  276. console.log("lastRevealed.value", lastRevealed.value);
  277. } else if (idx === nextRevealIdx.value && !canRevealPrize(idx)) {
  278. // 可以在这里添加提示信息,告知用户上一个奖品还未抽完
  279. console.log("上一个奖品还未抽完,不能揭秘下一个奖品");
  280. // 可以添加一个提示弹窗或toast
  281. // alert("上一个奖品还未抽完,请等待抽奖完成后再揭秘下一个奖品");
  282. }
  283. }
  284. // 计算未抽取数量
  285. function getLeftCount(prize) {
  286. // 这里假设奖品有 type 字段,且 dataManager.state.basicData.luckyUsers 可用
  287. // 由于本组件无 luckyUsers 数据,建议父组件传入或全局可访问
  288. // 这里用 window.dataManager 兼容演示
  289. let luckyUsers =
  290. (window.dataManager && window.dataManager.state.basicData.luckyUsers) || {};
  291. let got = luckyUsers[prize.type]?.length || 0;
  292. return prize.remainNum;
  293. }
  294. // 新增部分
  295. const showWinnerList = ref(false);
  296. const fakeWinners = ref([]);
  297. // fakeWinners.value = winners.value;
  298. console.log("fakeWinners", fakeWinners.value);
  299. // 分页相关状态
  300. const currentPage = ref(1);
  301. const pageSize = ref(16); // 每页显示20条记录,更好地利用列表空间
  302. const totalPages = ref(1);
  303. // 计算当前页的数据
  304. const paginatedWinners = computed(() => {
  305. const startIndex = (currentPage.value - 1) * pageSize.value;
  306. const endIndex = startIndex + pageSize.value;
  307. return fakeWinners.value.slice(startIndex, endIndex);
  308. });
  309. // 计算总页数
  310. const calculateTotalPages = () => {
  311. totalPages.value = Math.ceil(fakeWinners.value.length / pageSize.value);
  312. if (totalPages.value === 0) totalPages.value = 1;
  313. };
  314. // 上一页
  315. const prevPage = () => {
  316. if (currentPage.value > 1) {
  317. currentPage.value--;
  318. }
  319. };
  320. // 下一页
  321. const nextPage = () => {
  322. if (currentPage.value < totalPages.value) {
  323. currentPage.value++;
  324. }
  325. };
  326. import { getGetPrizeUserListApi } from "../../../api/API";
  327. const updateWinners = async () => {
  328. try {
  329. const response = await getGetPrizeUserListApi({
  330. pageSize: 1000000,
  331. pageNum: 1,
  332. });
  333. console.log("updatePrizeList response", response);
  334. // 按时间排序,后中奖的排序在前(假设有createTime字段,如果没有则按id倒序)
  335. const sortedWinners = response.data.list.sort((a, b) => {
  336. if (a.createTime && b.createTime) {
  337. return new Date(b.createTime) - new Date(a.createTime);
  338. }
  339. // 如果没有时间字段,按id倒序排列
  340. return (b.id || 0) - (a.id || 0);
  341. });
  342. fakeWinners.value = sortedWinners;
  343. console.log("updateWinners fakeWinners", fakeWinners.value);
  344. // 重置分页到第一页
  345. currentPage.value = 1;
  346. calculateTotalPages();
  347. } catch (error) {
  348. console.error("updatePrizeList error", error);
  349. }
  350. };
  351. async function openWinnerList() {
  352. // showWinnerList.value = true;
  353. if (!showWinnerList.value) {
  354. if (revealedCount.value === 0) {
  355. // alert("请先揭晓奖品,并抽奖!");
  356. showAutoHideNotification("请先揭晓奖品,并抽奖!");
  357. }
  358. // await updatePrizeList();
  359. }
  360. if (revealedCount.value > 0) {
  361. showWinnerList.value = true;
  362. }
  363. // 当存在最新揭秘的奖品时,点击获奖名单将showOne设置为false
  364. if (lastRevealedIdx.value >= 0) {
  365. showOne.value = false;
  366. }
  367. }
  368. function closeWinnerList() {
  369. showWinnerList.value = false;
  370. // 当关闭获奖名单且showOne为false时,将其切换回true
  371. if (!showOne.value) {
  372. showOne.value = true;
  373. }
  374. }
  375. const winnerBtnRef = ref(null);
  376. const modalLeft = ref(0);
  377. const modalTop = ref(0);
  378. async function toggleWinnerList() {
  379. await updateWinners();
  380. showWinnerList.value = !showWinnerList.value;
  381. console.log(
  382. "toggleWinnerList - showWinnerList:",
  383. showWinnerList.value,
  384. "showOne:",
  385. showOne.value,
  386. "lastRevealedIdx:",
  387. lastRevealedIdx.value
  388. );
  389. if (!showWinnerList.value) {
  390. if (revealedCount.value === 0) {
  391. // alert("请先揭晓奖品,并抽奖!");
  392. showAutoHideNotification("请先揭晓奖品,并抽奖!");
  393. }
  394. }
  395. if (showWinnerList.value) {
  396. // 当存在最新揭秘的奖品时,点击获奖名单将showOne设置为false
  397. if (lastRevealedIdx.value > 0) {
  398. showOne.value = false;
  399. console.log("设置 showOne 为 false");
  400. }
  401. } else {
  402. // 当关闭获奖名单且showOne为false时,将其切换回true
  403. if (!showOne.value) {
  404. showOne.value = true;
  405. console.log("设置 showOne 为 true");
  406. }
  407. }
  408. }
  409. function getProgressPercent(prize) {
  410. const total = prize.count || 1;
  411. const left = getLeftCount(prize);
  412. // 返回剩余数量的百分比,这样开始时是满的,抽完后是空的
  413. return Math.round((left / total) * 100);
  414. }
  415. onMounted(() => {
  416. updateWinners();
  417. calculateTotalPages();
  418. });
  419. </script>
  420. <style scoped>
  421. .auto-hide-notification {
  422. position: fixed;
  423. top: 300px;
  424. left: 50%;
  425. transform: translateX(-50%);
  426. color: #e61414;
  427. padding: 8px 16px;
  428. border-radius: 4px;
  429. font-size: 50px;
  430. z-index: 1000;}
  431. .prize-panel-list {
  432. position: relative;
  433. background: none;
  434. z-index: 10;
  435. min-width: 300px;
  436. max-width: 362px;
  437. text-align: left;
  438. display: flex;
  439. flex-direction: column;
  440. gap: 18px;
  441. max-height: 700px;
  442. overflow-x: hidden !important;
  443. /* overflow-y: auto; */
  444. padding-right: 10px;
  445. padding-left: 10px;
  446. scrollbar-width: thin;
  447. scrollbar-color: #ffd283 rgba(255, 210, 131, 0.3); /* Firefox */
  448. }
  449. .prize-panel-list1 {
  450. position: relative;
  451. background: none;
  452. z-index: 10;
  453. min-width: 320px;
  454. max-width: 342px;
  455. padding-right: 10px;
  456. padding-left: 10px;
  457. text-align: left;
  458. display: flex;
  459. }
  460. .prize-panel-list::-webkit-scrollbar {
  461. width: 6px;
  462. }
  463. .prize-panel-list::-webkit-scrollbar-track {
  464. background: rgba(255, 210, 131, 0.3);
  465. border-radius: 3px;
  466. }
  467. .prize-panel-list::-webkit-scrollbar-thumb {
  468. background-color: #ffd283;
  469. border-radius: 3px;
  470. }
  471. .prize-panel-item {
  472. background: #ffd283;
  473. border-radius: 6px 6px 6px 6px;
  474. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  475. display: flex;
  476. align-items: center;
  477. min-width: 320px;
  478. }
  479. .prize-card {
  480. display: flex;
  481. align-items: center;
  482. width: 100%;
  483. padding: 10px 18px;
  484. }
  485. .prize-img-wrap {
  486. width: 64px;
  487. height: 64px;
  488. border-radius: 50%;
  489. background: #fff;
  490. display: flex;
  491. align-items: center;
  492. justify-content: center;
  493. overflow: hidden;
  494. margin-right: 18px;
  495. border: 2px solid #fff3e0;
  496. }
  497. .prize-img {
  498. width: 60px;
  499. height: 60px;
  500. object-fit: contain;
  501. }
  502. .prize-info {
  503. flex: 1;
  504. display: flex;
  505. flex-direction: column;
  506. justify-content: center;
  507. }
  508. .prize-row {
  509. display: flex;
  510. align-items: center;
  511. background: #ffffff;
  512. border-radius: 93px 93px 93px 93px;
  513. }
  514. .prize-row-top {
  515. margin-bottom: 8px;
  516. border: 1px solid #ea2b0a;
  517. }
  518. .prize-level {
  519. background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%);
  520. color: #fff;
  521. border-radius: 15.71px 15.71px 15.71px 15.71px;
  522. padding: 2px 18px;
  523. font-size: 18px;
  524. font-weight: bold;
  525. margin-right: 12px;
  526. }
  527. .prize-name {
  528. font-size: 18px;
  529. color: #d84315;
  530. font-weight: 500;
  531. }
  532. .prize-row-bottom {
  533. /* margin-bottom: 8px; */
  534. /* border: 1px solid #ea2b0a; */
  535. }
  536. .custom-arrow-icon {
  537. font-size: 24px; /* 图标大小 */
  538. color: #d84315; /* 图标颜色,使用项目主题橙色 */
  539. margin: 5px; /* 外边距 */
  540. cursor: pointer; /* 鼠标悬停样式 */
  541. transition: transform 0.3s ease; /* 过渡动画 */
  542. }
  543. .custom-arrow-icon:hover {
  544. transform: scale(1.1); /* 悬停放大效果 */
  545. }
  546. .prize-count {
  547. font-size: 20px;
  548. font-weight: bold;
  549. }
  550. .prize-divider {
  551. margin: 0 4px;
  552. font-size: 20px;
  553. }
  554. .prize-total {
  555. font-size: 20px;
  556. font-weight: bold;
  557. }
  558. .prize-panel-root {
  559. position: absolute;
  560. top: 20px;
  561. left: 20px;
  562. background: none;
  563. z-index: 10;
  564. min-width: 320px;
  565. max-width: 362px;
  566. display: flex;
  567. flex-direction: column;
  568. }
  569. .prize-panel-footer {
  570. position: relative;
  571. /* width: 100%; */
  572. display: flex;
  573. flex-direction: column;
  574. align-items: center;
  575. z-index: 20;
  576. padding: 10px 0;
  577. border-radius: 0 0 6px 6px;
  578. margin-top: 10px;
  579. }
  580. .arrow-up {
  581. position: relative;
  582. width: 50px;
  583. height: 30px;
  584. margin-bottom: 4px;
  585. cursor: pointer;
  586. background-image: url("../../../assets/展开.png");
  587. background-size: cover;
  588. background-position: center;
  589. transform: rotate(180deg);
  590. }
  591. .arrow-down {
  592. position: fixed;
  593. top: 100px;
  594. left: 150px;
  595. width: 47px;
  596. height: 28px;
  597. margin-bottom: 4px;
  598. cursor: pointer;
  599. background-image: url("../../../assets/展开.png");
  600. background-size: cover;
  601. background-position: center;
  602. }
  603. .winner-btn {
  604. background: rgba(255, 210, 131, 0.8);
  605. color: #d5291f;
  606. border: #fff;
  607. border-radius: 8px;
  608. padding: 15px 79px;
  609. font-size: 20px;
  610. font-weight: bold;
  611. cursor: pointer;
  612. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  613. outline: none;
  614. }
  615. .winner-modal-mask {
  616. position: fixed;
  617. top: 142px;
  618. left: -4px;
  619. width: 100vw;
  620. height: 100vh;
  621. background: rgba(0, 0, 0, 0.01);
  622. z-index: 1000;
  623. display: flex;
  624. align-items: flex-start;
  625. justify-content: center;
  626. }
  627. .winner-modal {
  628. height: 700px;
  629. background: rgba(255, 210, 131, 0.8);
  630. border-radius: 12px;
  631. padding-top: 12px;
  632. padding-left: 25px;
  633. padding-right: 25px;
  634. padding-bottom: 10px;
  635. min-width: 280px;
  636. max-width: 90vw;
  637. box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
  638. position: relative;
  639. margin-left: 10px;
  640. }
  641. .winner-modal-title {
  642. font-size: 22px;
  643. font-weight: bold;
  644. color: #e64f39;
  645. margin-bottom: 5px;
  646. text-align: center;
  647. display: flex;
  648. justify-content: space-between; /* 左右对齐 */
  649. align-items: center; /* 垂直居中对齐 */
  650. /* 可添加padding或margin调整整体间距 */
  651. padding: 5px 0;
  652. }
  653. .winner-modal-close {
  654. position: absolute;
  655. right: 18px;
  656. top: 12px;
  657. font-size: 26px;
  658. color: #888;
  659. cursor: pointer;
  660. }
  661. .winner-list {
  662. height: 580px;
  663. /* background: rgba(255, 210, 131, 0.8);/ */
  664. overflow-y: auto;
  665. padding: 0;
  666. margin: 0;
  667. list-style: none;
  668. /* 隐藏滚动条但保留滚动功能 */
  669. scrollbar-width: none; /* Firefox */
  670. -ms-overflow-style: none; /* IE and Edge */
  671. }
  672. .winner-list::-webkit-scrollbar {
  673. display: none; /* Chrome, Safari and Opera */
  674. }
  675. .winner-list li {
  676. padding: 7px 0;
  677. /* border-bottom: 1px solid #f2f2f2; */
  678. font-size: 17px;
  679. color: #d84315;
  680. display: flex;
  681. gap: 12px;
  682. align-items: center;
  683. justify-content: center;
  684. text-align: center;
  685. }
  686. .progress-bar-bg {
  687. position: relative;
  688. width: 228px;
  689. height: 30px;
  690. background: #e9620e;
  691. border-radius: 16px;
  692. overflow: hidden;
  693. display: flex;
  694. align-items: center;
  695. margin: 0 auto;
  696. border: #e13726;
  697. }
  698. .progress-bar-fill {
  699. position: absolute;
  700. left: 0;
  701. top: 0;
  702. /* width: 100%; */
  703. height: 100%;
  704. /* background: linear-gradient(90deg, #ff9800 0%, #8a3500 100%); */
  705. background: #8a3500;
  706. border-radius: 16px;
  707. transition: width 0.4s;
  708. z-index: 1;
  709. }
  710. .progress-bar-text {
  711. position: relative;
  712. width: 100%;
  713. text-align: center;
  714. color: #ffffff;
  715. font-size: 18px;
  716. font-weight: bold;
  717. z-index: 2;
  718. letter-spacing: 1px;
  719. }
  720. .prize-card-mask {
  721. position: relative;
  722. width: 342px;
  723. height: 88px;
  724. display: flex;
  725. /* align-items: center;
  726. justify-content: center; */
  727. padding: 0;
  728. overflow: hidden;
  729. }
  730. .prize-mask-img {
  731. object-fit: cover;
  732. position: absolute;
  733. width: 100%;
  734. height: 98%;
  735. object-fit: cover;
  736. left: 0;
  737. top: 0;
  738. border-radius: 8px 8px 8px 8px;
  739. }
  740. .prize-panel-item.revealed-highlight {
  741. /* border: 3px solid #ff9800; */
  742. box-shadow: 0 0 16px 4px #ff9800ff, 0 0 20px 6px #ffcc80ff;
  743. transform: scale(1.03);
  744. z-index: 2;
  745. transition: all 0.3s;
  746. /* 确保放大的元素不被遮挡 */
  747. position: relative;
  748. /* margin: 8px 0; */
  749. /* 为放大的元素留出空间 */
  750. transform-origin: center center;
  751. }
  752. .prize-panel-item.disabled {
  753. cursor: not-allowed !important;
  754. position: relative;
  755. }
  756. .prize-panel-item.disabled::after {
  757. content: "请先抽完上一个奖品";
  758. position: absolute;
  759. top: 50%;
  760. left: 50%;
  761. transform: translate(-50%, -50%);
  762. background: rgba(0, 0, 0, 0.8);
  763. color: white;
  764. padding: 8px 12px;
  765. border-radius: 6px;
  766. font-size: 14px;
  767. white-space: nowrap;
  768. z-index: 10;
  769. opacity: 0;
  770. transition: opacity 0.3s;
  771. pointer-events: none;
  772. }
  773. .prize-panel-item.disabled:hover::after {
  774. opacity: 1;
  775. }
  776. /* 分页控件样式 */
  777. .pagination-controls {
  778. display: flex;
  779. justify-content: center;
  780. align-items: center;
  781. gap: 15px;
  782. margin-top: 15px;
  783. padding: 10px 0;
  784. }
  785. .pagination-btn {
  786. background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%);
  787. color: white;
  788. border: none;
  789. border-radius: 50%;
  790. width: 35px;
  791. height: 35px;
  792. font-size: 18px;
  793. font-weight: bold;
  794. cursor: pointer;
  795. display: flex;
  796. align-items: center;
  797. justify-content: center;
  798. transition: all 0.3s ease;
  799. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  800. }
  801. .pagination-btn:hover:not(:disabled) {
  802. transform: scale(1.1);
  803. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  804. }
  805. .pagination-btn:disabled {
  806. background: #ccc;
  807. cursor: not-allowed;
  808. transform: none;
  809. box-shadow: none;
  810. }
  811. .page-info {
  812. font-size: 18px;
  813. font-weight: bold;
  814. color: #d84315;
  815. min-width: 60px;
  816. text-align: center;
  817. }
  818. </style>