<template>
  <div class="homepage">
    <img src="../../../assets/qilin.webp" alt="麒麟" class="hllogo" />

    <!-- 添加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>

    <div class="leftBar">
      <el-scrollbar id="prizeBar">
        <ul class="prize-list">
          <li
            v-for="item in prizes"
            :key="item.type"
            :id="`prize-item-${item.type}`"
            :class="['prize-item']"
            @click="lookPrize(item)"
          >
            <div
              v-if="item.isLook"
              style="display: flex; width: 100%; height: 100%"
            >
              <span></span><span></span><span></span><span></span>
              <div class="prize-img">
                <img :src="item.imageUrl" :alt="item.title" />
              </div>
              <div class="prize-text">
                <div class="prize-title">
                  <div class="level">
                    {{ item.gradeName }}
                  </div>
                  {{ item.prizeName }}
                </div>
                <div class="prize-count">
                  <div class="progress">
                    <div
                      :id="`prize-bar-${item.type}`"
                      class="progress-bar progress-bar-danger progress-bar-striped active"
                      style="width: 100%"
                    ></div>
                  </div>
                  <div
                    :id="`prize-count-${item.type}`"
                    class="prize-count-left"
                  >
                    {{ item.leftCount }}/{{ item.count }}
                  </div>
                </div>
              </div>
            </div>
            <div v-else style="display: flex; width: 100%; height: 100%">
              <img
                src="../../../assets/img/待揭秘.png"
                alt="待揭秘"
                class="readyLook"
              />
            </div>
          </li>
        </ul>
      </el-scrollbar>
      <div v-if="!isOpen">
        <div class="getPrizeName" @click="openGetPrize()">
          <img src="../../../assets/img/展开.png" alt="展开" class="open" />
          获奖名单
        </div>
      </div>
      <div v-else>
        <div class="dgetPrizeName">
          <img
            src="../../../assets/img/展开.png"
            alt="展开"
            class="close"
            @click="closeGetPrize()"
          />
          <div class="tableHead">
            <div class="tableHead1">HomilyID</div>
            <div class="tableHead2">奖项</div>
            <div class="gradient-line"></div>
          </div>
          <el-scrollbar class="tableBody">
            <div v-for="item in getPrizeUserList" :key="item">
              <div class="tableItem">
                <div class="tableItem1">
                  {{ item.jwcode }}
                </div>
                <div class="tableItem2">
                  {{ item.gradeName }}
                </div>
              </div>
            </div>
          </el-scrollbar>
          <div class="tableFoot">
            <span @click="leftPage()" id="leftPage" class="leftPage"><</span>
            {{ currentPage }}/<span>{{ totalPage }}</span>
            <span @click="rightPage()" id="rightPage" class="rightPage">></span>
          </div>
        </div>
      </div>
    </div>

    <div id="container">
      <div ref="threeContainer" class="three-container"></div>

      <!-- 分页指示器 -->
      <div v-if="pageMaxIndex > 1" class="page-indicator">
        第 {{ pageIndex + 1 }} 页 / 共 {{ pageMaxIndex }} 页
      </div>
    </div>

    <div id="menu">
      <div id="enter" ref="enterRef" @click="enterLottery()" class="btn">
        进入抽奖
      </div>

      <div id="lotteryBar" ref="lotteryBarRef" class="none">
        <div v-if="isBackApi">
          <div class="btn">{{ cjText }}</div>
        </div>
        <div v-else>
          <div
            id="lottery"
            ref="lotteryRef"
            @click="throttledLotteryBtn()"
            class="btn"
          >
            {{ cjText }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive, nextTick } from "vue";
import { useRouter } from "vue-router";
import * as THREE from "three";
import axios from "axios";
import "../../../assets/css/animate.min.css";
import { resetPrize } from "../../../utils/prizeList";
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 _ from "lodash";

import {
  getPrizeListApi,
  getUserListApi,
  getGetPrizeUserListApi,
  startLotteryApi,
} from "../../../api/API";

// 常量
const ROTATE_TIME = 10000; //旋转动画的总时长
const ROTATE_LOOP = 1000;
const BASE_HEIGHT = 1080; //高度

// 按钮控制
const enterRef = ref(null); //进入抽奖按钮
const lotteryBarRef = ref(null); //开始抽奖元素组（显示控制）
const lotteryRef = ref(null); //开始抽奖按钮（文字控制 ）

//3D相关变量
// 当前的比例
let Resolution = 0.9;
//总卡片数
let TOTAL_CARDS;
// 高度卡片数
let ROW_COUNT = 7;
// 宽度卡片数
let COLUMN_COUNT = 21;
// 高亮卡片数组
let HIGHLIGHT_CELL = [];
// 其他变量
let camera,
  scene,
  renderer,
  controls,
  threeDCards = [],
  targets = {
    table: [],
    sphere: [],
  };
// 动画对象
let rotateObj;
// 控制旋转
let rotate = false;

//奖品列表
const prizes = ref([]);
//每个奖品每次抽取的数目
let EACH_COUNT = [];

const users = ref([]);
const getPrizeUsers = ref([]);
//判断是否正在抽奖
let isLotting = false;
const setLotteryStatus = (status = false) => {
  isLotting = status;
};

let selectedCardIndex = [];
let interval;
// 当前抽的奖项，从最低奖开始抽，直到抽到大奖
let currentPrizeIndex;
const currentPrize = ref({});

let currentLuckys = [];
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";

  qipaoText.value = text;
  setTimeout(() => {
    // 设置过渡效果
    qipaoTextRef.value.style.transition = "opacity 0.5s ease-out";
    // 开始渐隐
    qipaoTextRef.value.style.opacity = "0";
    // 动画完成后隐藏元素
    setTimeout(() => {
      qipaoTextRef.value.style.display = "none";
    }, 800);
  }, 1000);
};

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(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) => {
    // console.log("item", item);
    if (item.type != currentPrize.value.type) {
      let box = document.querySelector(`#prize-item-${item.type}`);
      box.style.display = "none";
    }
  });
  let scroll = document.getElementById("prizeBar");
  //   scroll.style.height = "110px";
};

const closeGetPrize = () => {
  isOpen.value = false;
  prizes.value.forEach((item) => {
    // console.log("item", item);
    if (item.type != currentPrize.value.type) {
      let box = document.querySelector(`#prize-item-${item.type}`);
      box.style.display = "flex";
    }
  });
  //   let scroll = document.getElementById("prizeBar");
  //   scroll.style.height = "650px";
};

const leftPage = async (item) => {
  if (currentPage.value == 1) {
    return;
  }
  if (currentPage.value == totalPage.value) {
    const rightPageBtn = document.getElementById("rightPage");
    rightPageBtn.style.cursor = "pointer";
    rightPageBtn.style.setProperty(
      "background",
      "linear-gradient(90deg, #ff9800 0%, #ff5722 100%)",
      "important"
    );
  }
  currentPage.value--;
  pageObj.value.pageNum = currentPage;
  let res = await getGetPrizeUserListApi(pageObj.value);
  getPrizeUserList.value = res.data.list;
  currentPage.value = res.data.pageNum;

  if (currentPage.value == 1) {
    const leftPageBtn = document.getElementById("leftPage");
    leftPageBtn.style.cursor = "not-allowed";
    leftPageBtn.style.background = "#ccc";
  }
};
const rightPage = async (item) => {
  if (currentPage.value == totalPage.value) {
    return;
  }

  if (currentPage.value == 1) {
    const leftPageBtn = document.getElementById("leftPage");
    console.log("leftPageBtn", leftPageBtn);
    leftPageBtn.style.cursor = "pointer";
    leftPageBtn.style.setProperty(
      "background",
      "linear-gradient(90deg, #ff9800 0%, #ff5722 100%)",
      "important"
    );
  }

  currentPage.value++;
  pageObj.value.pageNum = currentPage;
  let res = await getGetPrizeUserListApi(pageObj.value);
  getPrizeUserList.value = res.data.list;
  currentPage.value = res.data.pageNum;

  if (currentPage.value == totalPage.value) {
    const rightPageBtn = document.getElementById("rightPage");
    rightPageBtn.style.cursor = "not-allowed";
    rightPageBtn.style.background = "#ccc";
  }
};

//揭示奖品
const lookPrize = async (item) => {
  // 未进入抽奖禁止揭晓
  if (!joinLottery) {
    addQipao("请先进入抽奖。");
    return;
  }
  // 如果已经揭示，那返回
  if (item.isLook) return;
  //最低级的可以直接揭晓
  if (
    currentPrize.value.type == prizes.value[prizes.value.length - 1].type &&
    item.type == currentPrize.value.type
  ) {
    let currentBox = document.querySelector(`#prize-item-${item.type}`);

    currentBox && currentBox.classList.add("shine");
    //点击揭晓
    item.isLook = true;
  } else if (
    !isLotting && //未在抽奖状态
    currentPrize.value.isLook &&
    currentPrize.value.leftCount == 0 && //当前奖项已抽完
    prizes.value[currentPrizeIndex - 1] == item //点击的奖项是当前奖项的下一个
  ) {
    currentPrize.value = item;
    currentPrizeIndex--;
    let lastIndex = -1;
    for (let i = prizes.value.length - 1; i >= 0; i--) {
      if (prizes.value[i].type == item.type) {
        if (i != prizes.value.length - 1) {
          lastIndex = i + 1;
        }
        break;
      }
    }
    if (lastIndex != -1) {
      let lastPrize = prizes.value[lastIndex];
      //   console.log("lastPrize", lastPrize);
      let lastBox = document.querySelector(`#prize-item-${lastPrize.type}`);
      lastBox.classList.remove("shine");
      lastBox.classList.add("done");

      let currentBox = document.querySelector(`#prize-item-${item.type}`);

      currentBox && currentBox.classList.add("shine");
    }
    //点击揭晓
    item.isLook = true;
  }
  await nextTick();
  setPrizeData(currentPrizeIndex);
};

function setPrizeData(currentPrizeIndex, isInit) {
  //   console.log("prizes", prizes.value);
  //   let currentPrize = prizes.value[currentPrizeIndex];
  let type = currentPrize.value.type;
  let elements = prizeElement[type];

  let count = currentPrize.value.leftCount;
  let totalCount = currentPrize.value.count;

  if (!elements || !elements.bar || !elements.text) {
    elements = {
      box: document.querySelector(`#prize-item-${type}`),
      bar: document.querySelector(`#prize-bar-${type}`),
      text: document.querySelector(`#prize-count-${type}`),
    };
  }

  if (isInit) {
    for (let i = prizes.value.length - 1; i > currentPrizeIndex; i--) {
      let type = prizes.value[i]["type"];
      document.querySelector(`#prize-item-${type}`).className =
        "prize-item done";
      document.querySelector(`#prize-bar-${type}`).style.width = "0";
      document.querySelector(`#prize-count-${type}`).textContent =
        "0" + "/" + prizes.value[i]["count"];
    }
  }

  console.log("count", count);
  console.log("totalCount", totalCount);

  let percent = (count / totalCount).toFixed(2);
  if (elements.bar) {
    elements.bar.style.width = percent * 100 + "%";
  }
}

/**
 * 初始化所有DOM
 */
const pageIndex = ref(0);
const pageMaxIndex = ref(0);
const cardsPerPage = 10; // 每页显示的卡片数量
let isPageTransitioning = false; // 防止页面切换时的重复操作
// 全局变量存储当前选中的卡片索引数组
let globalCardIndexes = [];

const initAll = async () => {
  const [prizeList, userList] = await Promise.all([
    getPrizeListApi(),
    getUserListApi(),
  ]);
  console.log("hxl-cj调用一次接口", prizeList);
  //   奖品列表
  prizes.value = prizeList.data;
  //   用户列表
  users.value = userList.data;
  prizes.value.forEach((item, index) => {
    item.type = index;
    item.count = item.amount;
    item.leftCount = item.remainNum; //剩余次数（用于计算奖品下方的进度条的百分比）
    item.hasCount = item.amount; //已抽次数（用于计算出奖）
    item.isLook = false; //
    EACH_COUNT.push(item.perWin);
  });
  console.log("prizes", prizes.value);
  console.log("EACH_COUNT", EACH_COUNT);

  HIGHLIGHT_CELL = createHighlight();

  TOTAL_CARDS = ROW_COUNT * COLUMN_COUNT;

  currentPrizeIndex = prizes.value.length - 1;
  currentPrize.value = prizes.value[currentPrizeIndex];

  await nextTick();
  setPrizeData(currentPrizeIndex, true);

  initCards();
  // startMaoPao();
  animate();
  shineCard();
  //   window.AJAX({
  //     url: "/getUsers",
  //     success(data) {},
  //   });
};

const initCards = () => {
  const screenWidth = window.innerWidth;
  const isLaptop = screenWidth < 1600; // 判断
  const baseSpacingX = isLaptop ? 120 : 140;
  const baseSpacingY = isLaptop ? 150 : 180;

  let member = users.value.slice(),
    showCards = [],
    length = member.length;

  let isBold = false;
  let index = 0;
  let totalMember = member.length;
  // let position = {
  //   x: (140 * COLUMN_COUNT - 20) / 2,
  //   y: (180 * ROW_COUNT - 20) / 2,
  // };

  let position = {
    x: (baseSpacingX * COLUMN_COUNT - 20) / 2,
    y: (baseSpacingY * ROW_COUNT - 20) / 2,
  };

  camera = new THREE.PerspectiveCamera(
    40,
    window.innerWidth / window.innerHeight,
    1,
    10000
  );
  camera.position.z = 3500;

  scene = new THREE.Scene();

  for (let i = 0; i < ROW_COUNT; i++) {
    for (let j = 0; j < COLUMN_COUNT; j++) {
      isBold = HIGHLIGHT_CELL.includes(j + "-" + i);
      var element = createCard(member[index % length], isBold, index);

      var object = new CSS3DObject(element);
      object.position.x = Math.random() * 4000 - 2000;
      object.position.y = Math.random() * 4000 - 2000;
      object.position.z = Math.random() * 4000 - 2000;
      scene.add(object);
      threeDCards.push(object);
      //

      // 在initCards函数开始处添加

      const cardSpacingX = isLaptop ? 130 : 155;
      const cardSpacingY = isLaptop ? 160 : 195;

      var object = new THREE.Object3D();
      // object.position.x = j * 155 - position.x;
      // object.position.y = -(i * 195) + position.y;
      // 使用动态间距
      object.position.x = j * cardSpacingX - position.x;
      object.position.y = -(i * cardSpacingY) + position.y;
      targets.table.push(object);
      index++;
    }
  }

  // sphere

  var vector = new THREE.Vector3();

  for (var i = 0, l = threeDCards.length; i < l; i++) {
    var phi = Math.acos(-1 + (2 * i) / l);
    var theta = Math.sqrt(l * Math.PI) * phi;
    var object = new THREE.Object3D();
    object.position.setFromSphericalCoords(800 * Resolution, phi, theta);
    vector.copy(object.position).multiplyScalar(2);
    object.lookAt(vector);
    targets.sphere.push(object);
  }

  renderer = new CSS3DRenderer();
  renderer.setSize(window.innerWidth * 1, window.innerHeight * 0.9);
  renderer.domElement.style.margin = "7% 0 0 1%";
  //   document.getElementById("container").appendChild(renderer.domElement);

  if (threeContainer.value) {
    threeContainer.value.appendChild(renderer.domElement);
  }

  //

  controls = new TrackballControls(camera, renderer.domElement);
  controls.rotateSpeed = 0.5;
  controls.minDistance = 500;
  controls.maxDistance = 6000;
  controls.addEventListener("change", render);

  switchScreen("enter");
};

// 判断是否进入抽奖
let joinLottery = false;
// 进入抽奖
const enterLottery = async () => {
  joinLottery = true;
  removeHighlight();
  await nextTick();
  // rotate = !rotate;
  rotate = true;
  switchScreen("lottery");
};

function switchScreen(type) {
  switch (type) {
    case "enter":
      if (enterRef.value) {
        enterRef.value.classList.remove("none");
      }
      if (lotteryBarRef.value) {
        lotteryBarRef.value.classList.add("none");
      }
      transform(targets.table, 2000);
      break;
    default:
      if (enterRef.value) {
        enterRef.value.classList.add("none");
      }
      if (lotteryBarRef.value) {
        lotteryBarRef.value.classList.remove("none");
      }
      transform(targets.sphere, 2000);
      break;
  }
}

/**
 * 创建元素
 */
const createElement = (css, text) => {
  let dom = document.createElement("div");
  dom.className = css || "";
  dom.innerHTML = text || "";
  return dom;
};

/**
 * 创建名牌
 */
const createCard = (user, isBold, id) => {
  var element = createElement();
  element.id = "card-" + id;
  element.style.display = "flex";
  element.style.alignItems = "center";
  element.style.justifyContent = "center";
  if (isBold) {
    element.className = "element lightitem";
    element.classList.add("highlight");
  } else {
    element.className = "element";
    // element.style.backgroundColor =
    //   "rgba(255,170,22," + (Math.random() * 0.7 + 0.25) + ")";
    element.style.backgroundColor = "rgba(255,170,22,1)";
    element.style.border = "2px solid rgba(255, 255, 255, 1)";
  }

  element.appendChild(createElement("name", user.jwcode));

  return element;
};

const removeHighlight = async () => {
  document.querySelectorAll(".highlight").forEach((node) => {
    console.log(node.id);
    node.className = "";
    node.classList.add("element");
    node.style.backgroundColor = "rgb(255,170,22)";
  });
};

function addHighlight() {
  document.querySelectorAll(".lightitem").forEach((node) => {
    node.classList.add("highlight");
  });
}

/**
 * 渲染地球等
 */
function transform(targets, duration) {
  // TWEEN.removeAll();
  for (var i = 0; i < threeDCards.length; i++) {
    var object = threeDCards[i];
    var target = targets[i];

    new TWEEN.Tween(object.position)
      .to(
        {
          x: target.position.x,
          y: target.position.y,
          z: target.position.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();

    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();
  }

  new TWEEN.Tween(this)
    .to({}, duration * 2)
    .onUpdate(render)
    .start();
}

function rotateBall() {
  return new Promise((resolve, reject) => {
    scene.rotation.y = 0;
    rotateObj = new TWEEN.Tween(scene.rotation);
    rotateObj
      .to(
        {
          y: Math.PI * 6 * ROTATE_LOOP,
        },
        ROTATE_TIME * ROTATE_LOOP
      )
      .onUpdate(render)
      // .easing(TWEEN.Easing.Linear)
      .start()
      .onStop(() => {
        scene.rotation.y = 0;
        resolve();
      })
      .onComplete(() => {
        resolve();
      });
  });
}

function animate() {
  // 让场景通过x轴或者y轴旋转
  // rotate && (scene.rotation.y += 0.088);

  requestAnimationFrame(animate);
  TWEEN.update();
  controls.update();

  // 渲染循环
  // render();
}

function render() {
  renderer.render(scene, camera);
}

const threeContainer = ref(null);
function selectCard(duration = 600) {
  return new Promise((resolve) => {
    const width = 160;

    // 计算总页数
    pageMaxIndex.value = Math.ceil(currentLuckys.length / cardsPerPage);
    pageIndex.value = 0;

    // 为每页计算位置信息
    const pageLocates = [];

    for (let page = 0; page < pageMaxIndex.value; page++) {
      const startIndex = page * cardsPerPage;
      const endIndex = Math.min(
        (page + 1) * cardsPerPage,
        currentLuckys.length
      );
      const pageCount = endIndex - startIndex;

      const pageLocate = [];

      // 根据当前页的人数决定排列方式
      if (pageCount > 5) {
        // 大于5个分两排显示（与抽10人时的排列相同）
        const yPosition = [-75, 120];
        const mid = Math.ceil(pageCount / 2);
        let tag = -(mid - 1) / 2;

        for (let i = 0; i < mid; i++) {
          pageLocate.push({
            x: tag * width,
            y: yPosition[0],
          });
          tag++;
        }

        tag = -(pageCount - mid - 1) / 2;
        for (let i = mid; i < pageCount; i++) {
          pageLocate.push({
            x: tag * width,
            y: yPosition[1],
          });
          tag++;
        }
      } else {
        // 小于等于5个一排显示（与抽不足10人时的排列相同）
        let tag = -(pageCount - 1) / 2;
        for (let i = 0; i < pageCount; i++) {
          pageLocate.push({
            x: tag * width,
            y: 0,
          });
          tag++;
        }
      }

      pageLocates.push(pageLocate);
    }

    // console.log("pageLocates calculated:", pageLocates);

    // 初始化所有卡片位置（隐藏超出第一页的卡片）
    selectedCardIndex.forEach((cardIndex, index) => {
      changeSelectedCard(cardIndex, currentLuckys[index]);
      const object = threeDCards[cardIndex];

      // 计算卡片应该在第几页
      const cardPage = Math.floor(index / cardsPerPage);
      const isVisible = cardPage === 0;

      // 计算在当前页中的索引
      const pageNowIndex = index % cardsPerPage;
      const pageLocate = pageLocates[cardPage][pageNowIndex];

      new TWEEN.Tween(object.position)
        .to(
          {
            x: isVisible ? pageLocate.x : pageLocate.x,
            y: isVisible ? pageLocate.y : pageLocate.y + 1000, // 隐藏的卡片移到下方
            z: 2100,
          },
          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");
    });

    // 保存页面位置信息到全局变量，供switchPage使用
    window.pageLocates = pageLocates;

    new TWEEN.Tween({})
      .to({}, duration * 2)
      .onUpdate(() => render())
      .start()
      .onComplete(() => {
        console.log("selectCard animation completed");
        // 如果有多页，添加鼠标滚轮事件监听
        if (pageMaxIndex.value > 1) {
          //   console.log("pageMaxIndex添加滚轮", pageMaxIndex.value);
          // 添加滚轮事件监听
          addWheelListener();
        }

        setLotteryStatus();
        resolve();
      });
  });
}

// 分页切换函数
function switchPage(direction) {
  if (isPageTransitioning || pageMaxIndex.value <= 1) return;

  const newPage =
    direction === "next" ? pageIndex.value + 1 : pageIndex.value - 1;
  if (newPage < 0 || newPage >= pageMaxIndex.value) return;

  isPageTransitioning = true;
  const duration = 800;

  // 使用保存的页面位置信息
  const pageLocates = window.pageLocates;
  if (!pageLocates) {
    console.error("页面位置信息未找到");
    isPageTransitioning = false;
    return;
  }

  // 动画切换卡片位置
  globalCardIndexes.forEach((cardIndex, index) => {
    const object = threeDCards[cardIndex];
    const cardPage = Math.floor(index / cardsPerPage);
    const isVisible = cardPage === newPage;
    const wasVisible = cardPage === pageIndex.value;
    // 计算在当前页中的索引
    const pageNowIndex = index % cardsPerPage;
    const pageLocate = pageLocates[cardPage][pageNowIndex];

    // console.log(
    //   "cardPage",
    //   cardPage,
    //   "pageNowIndex",
    //   pageNowIndex,
    //   "pageLocate",
    //   pageLocate
    // );

    // 根据切换方向决定动画效果
    let targetY;
    if (isVisible) {
      // 当前页要显示的卡片
      if (direction === "next") {
        // 索引增大：从下方飞出
        targetY = pageLocate.y;
      } else {
        // 索引减少：从上方飞出
        targetY = pageLocate.y;
      }
    } else {
      // 当前页要隐藏的卡片
      if (direction === "next") {
        // 索引增大：向上飞走
        targetY = pageLocate.y + 1000;
      } else {
        // 索引减少：向下飞走
        targetY = pageLocate.y - 1000;
      }
    }

    // 设置起始位置
    let startY;
    if (wasVisible) {
      // 当前页的卡片从当前位置开始
      startY = object.position.y;
    } else {
      // 非当前页的卡片从隐藏位置开始
      if (direction === "next") {
        // 索引增大：从下方开始
        startY = pageLocate.y - 1000;
      } else {
        // 索引减少：从上方开始
        startY = pageLocate.y + 1000;
      }
    }

    // 先设置起始位置
    object.position.y = startY;

    new TWEEN.Tween(object.position)
      .to(
        {
          x: pageLocate.x,
          y: targetY,
          z: 2100,
        },
        duration
      )
      .easing(TWEEN.Easing.Cubic.InOut)
      .start();
  });

  new TWEEN.Tween({})
    .to({}, duration)
    .onUpdate(() => render())
    .onComplete(() => {
      pageIndex.value = newPage;
      isPageTransitioning = false;
      console.log(
        `切换到第 ${pageIndex.value + 1} 页，共 ${pageMaxIndex.value} 页`
      );
    })
    .start();
}

// 鼠标滚轮事件处理
function handleWheel(event) {
  if (isPageTransitioning || pageMaxIndex.value <= 1) return;

  event.preventDefault();

  if (event.deltaY > 0) {
    // 向下滚动，显示下一页
    switchPage("next");
  } else if (event.deltaY < 0) {
    // 向上滚动，显示上一页
    switchPage("prev");
  }
}

// 添加鼠标滚轮事件监听器
function addWheelListener() {
  if (threeContainer.value) {
    threeContainer.value.addEventListener("wheel", handleWheel, {
      passive: false,
    });
  }
}

// 移除鼠标滚轮事件监听器
function removeWheelListener() {
  if (threeContainer.value) {
    threeContainer.value.removeEventListener("wheel", handleWheel);
  }
}

/**
 * 重置抽奖牌内容
 */
function resetCard(duration = 500) {
  if (currentLuckys.length === 0) {
    return Promise.resolve();
  }

  globalCardIndexes = [];
  // 移除鼠标滚轮事件监听器
  removeWheelListener();

  // 重置分页状态
  pageIndex.value = 0;
  pageMaxIndex.value = 0;
  isPageTransitioning = false;

  // 清理保存的页面位置信息
  if (window.pageLocates) {
    delete window.pageLocates;
  }

  selectedCardIndex.forEach((index) => {
    let object = threeDCards[index],
      target = targets.sphere[index];

    new TWEEN.Tween(object.position)
      .to(
        {
          x: target.position.x,
          y: target.position.y,
          z: target.position.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();

    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();
  });

  return new Promise((resolve, reject) => {
    new TWEEN.Tween(this)
      .to({}, duration * 2)
      .onUpdate(render)
      .start()
      .onComplete(() => {
        selectedCardIndex.forEach((index) => {
          let object = threeDCards[index];
          object.element.classList.remove("prize");
        });
        resolve();
      });
  });
}

const isBackApi = ref(false);
const cjText = ref("开始抽奖");
// 抽奖
const lotteryBtn = () => {
  //   console.log("isLotting", isLotting);
  //   console.log("currentPrize.value", currentPrize.value);
  if (isLotting) {
    throttledStopLottery();
    return;
  }

  if (!currentPrize.value.isLook) {
    addQipao("请先揭秘礼品。");
    return;
  }
  if (currentPrize.value.leftCount <= 0) {
    addQipao("该礼品已抽取完毕，请揭秘下一个礼品。");
    return;
  }

  // lotteryRef.value.innerHTML = "结束抽奖";
  cjText.value = "结束抽奖";

  isBackApi.value = true;
  // 播放worldcup音频
  playWorldcupAudio();

  getPrizeUsers.value = [];
  let params = {
    gradeId: currentPrize.value.gradeId,
    prizeId: currentPrize.value.prizeId,
    perWin: currentPrize.value.perWin,
    remainNum: currentPrize.value.leftCount,
  };
  // 异步调用API，不阻塞后续代码执行
  startLotteryApi(params)
    .then((res) => {
      // API返回结果时赋值
      getPrizeUsers.value = res.data.data || [];
      isBackApi.value = false;
      console.log("API返回结果:", res.data.data);
    })
    .catch((err) => {
      isBackApi.value = false;
      console.error("API调用失败:", err);
      getPrizeUsers.value = [];
    });

  setLotteryStatus(true);
  //更新剩余抽奖数目的数据显示
  changePrize();
  resetCard().then((res) => {
    // 抽奖
    lottery();
  });

  console.log("currentPrize", currentPrize.value);

  const text = "正在抽取[" + currentPrize.value.prizeName + "],调整好姿势";
  //   addQipao(text);
};

const throttledLotteryBtn = _.throttle(lotteryBtn, 1000, {
  trailing: false,
});

const lottery = () => {
  rotateBall().then(() => {
    // 将之前的记录置空
    currentLuckys = [];
    selectedCardIndex = [];
    // 当前同时抽取的数目,当前奖品抽完还可以继续抽，但是不记录数据

    for (let i = 0; i < getPrizeUsers.value.length; i++) {
      console.log("111", getPrizeUsers.value[i]);
      currentLuckys.push(getPrizeUsers.value[i]);
      currentPrize.value.hasCount--;

      //避免中奖者出现在同一个卡片上
      let cardIndex = random(TOTAL_CARDS);
      while (selectedCardIndex.includes(cardIndex)) {
        cardIndex = random(TOTAL_CARDS);
      }
      selectedCardIndex.push(cardIndex);

      if (currentPrize.value.hasCount === 0) {
        break;
      }
    }

    selectCard(600);
  });
};

const stopLottery = () => {
  // lotteryRef.value.innerHTML = "开始抽奖";
  cjText.value = "开始抽奖";
  rotateObj.stop();

  // 暂停worldcup音频
  pauseWorldcupAudio();
  playDongAudio();
};

const throttledStopLottery = _.throttle(stopLottery, 1000, {
  trailing: false,
});

const changePrize = async () => {
  let type = currentPrize.value.type;

  prizes.value[type].leftCount =
    prizes.value[type].leftCount - EACH_COUNT[type] < 0
      ? 0
      : prizes.value[type].leftCount - EACH_COUNT[type];
  await nextTick();
  // 修改左侧prize的数目和百分比
  setPrizeData(currentPrizeIndex);
};

/**
 * 随机抽奖
 */
function random(num) {
  // Math.floor取到0-num-1之间数字的概率是相等的
  return Math.floor(Math.random() * num);
}

/**
 * 切换名牌人员信息
 */
function changeCard(cardIndex, user) {
  let card = threeDCards[cardIndex].element;
  // console.log("user", user);
  card.innerHTML = `<div class="name">${user.jwcode}</div>`;
}

function changeSelectedCard(cardIndex, user) {
  // 保存到全局变量数组
  if (!globalCardIndexes.includes(cardIndex)) {
    globalCardIndexes.push(cardIndex);
  }

  let card = threeDCards[cardIndex].element;

  card.innerHTML = `<div class="name">${user.jwcode}</div>`;
}
/**
 * 切换名牌背景
 */
const changeBackground = async (cardIndex) => {
  let card = threeDCards[cardIndex].element;
  //   card.style.backgroundColor =
  //     color || "rgba(255,170,22," + (Math.random() * 0.7 + 0.25) + ")";
  card.style.backgroundColor = "rgb(255,170,22) !important";
  card.style.border = "2px solid rgb(255, 255, 255)";

  // await nextTick();
};

/**
 * 随机切换背景和人员信息
 */
function shineCard() {
  let maxCard = 10;
  let maxUser;
  let shineCard = 10 + random(maxCard);

  setInterval(() => {
    // 正在抽奖停止闪烁
    if (isLotting) {
      return;
    }
    maxUser = users.value.length;
    for (let i = 0; i < shineCard; i++) {
      let index = random(maxUser);
      let cardIndex = random(TOTAL_CARDS);
      // 当前显示的已抽中名单不进行随机切换
      if (selectedCardIndex.includes(cardIndex)) {
        continue;
      }

      // changeBackground(cardIndex);
      changeCard(cardIndex, users.value[index]);
    }
  }, 500);
}

const createHighlight = () => {
  let text = "0123";
  let step = 5;
  let xoffset = 1;
  let yoffset = 1;
  let highlight = [];

  text.split("").forEach((n) => {
    highlight = highlight.concat(
      NUMBER_MATRIX[n].map((item) => {
        return `${item[0] + xoffset}-${item[1] + yoffset}`;
      })
    );
    xoffset += step;
  });
  return highlight;
};

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  render();
}

onMounted(async () => {
  initAll();
  window.addEventListener("resize", onWindowResize, false);
});
</script>

<style>
html,
body,
#app {
  height: 100vh;
  width: 100vw;
}

.homepage {
  width: 100%;
  height: 100%;
  display: flex;
  background-image: url("../../../assets/bg@2x.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  justify-content: center;
}

.hllogo {
  position: absolute;
  right: 0;
  bottom: 0;
}

.qipao {
  width: 100%;
  z-index: 100;
  position: absolute;
  top: 27vh;
  left: 50%;
  transform: translateX(-50%);
  color: #db5c58;
  font-weight: bold;
  font-size: 42px;
  width: auto;
  text-align: center;
  display: none;
  white-space: nowrap;
}

a {
  color: #ffffff;
}

.none {
  display: none;
}

#container {
  z-index: 3;
  position: relative;
  overflow: hidden;
}

.three-container {
  width: 100%;
  height: 100%;
}

/* 分页指示器样式 */
.page-indicator {
  position: absolute;
  bottom: 10%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 14px;
  pointer-events: none;
}

.canvas-box {
  /* background-color: rgb(214, 0, 0); */
  position: fixed;
  left: 0;
  top: 0;
  z-index: -1;
}

#info {
  position: absolute;
  width: 100%;
  color: #ffffff;
  padding: 5px;
  font-family: Monospace;
  font-size: 13px;
  font-weight: bold;
  text-align: center;
  z-index: 1;
}

#menu {
  z-index: 4;
  position: absolute;
  bottom: 1vh;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.element {
  width: 7.5vw;
  height: 18.5vh;
  /* box-shadow: 0 0 12px rgba(0, 255, 255, 0.5); */
  border: 1px solid rgba(127, 255, 255, 0.25);
  text-align: center;
  cursor: default;
  transition: background-color 0.3s ease-in;
}

.element:hover {
  box-shadow: 0 0 12px rgba(255, 168, 38, 0.75);
  border: 1px solid rgba(255, 255, 255, 1);
}

.element .name {
  font-size: 2.9vh;
  font-weight: bold;
  color: rgba(255, 255, 255, 1);
  /* text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95); */
}

button {
  border: none;
}

.btn {
  background-image: url("../../../assets/img/抽奖按钮.png");
  background-color: transparent;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  width: 180px;
  height: 70px;
  color: #fff;
  border: 0;
  font-size: 20px;
  font-weight: bold;
  cursor: pointer;
  text-align: center;
  padding-top: 12px;
}

.highlight {
  background: linear-gradient(360deg, #e23d26, #f49c27) !important;
  box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
  border: 2px solid rgba(255, 255, 255, 1);
}

.highlight.element .name {
  text-shadow: 0 0 16px rgba(255, 255, 255, 0.95);
}

.prize.element .name {
  text-shadow: none;
}

.prize.element {
  transition: background-color 1.5s ease-in 0.3s;
  background: linear-gradient(360deg, #e23d26, #f49c27) !important;
  border: 2px solid rgba(255, 255, 255, 1);
}

.prize .company,
.prize .details,
.prize .name,
.highlight .company,
.highlight .name,
.highlight .details {
  color: rgba(255, 255, 255, 0.85);
}

.dan-mu {
  visibility: hidden;
  position: fixed;
  z-index: -1;
  font-size: 12px;
  top: 1vh;
  left: 0;
  padding: 0 1.2vh;
  height: 2.2vh;
  line-height: 2.2vh;
  border-radius: 1vh;
  box-sizing: border-box;
  background-color: rgba(0, 127, 127, 0.37);
  box-shadow: 0 0 4px rgba(0, 255, 255, 0.5);
  border: 1px solid rgba(127, 255, 255, 0.25);
  color: rgba(127, 255, 255, 0.75);
}

.dan-mu.active {
  visibility: visible;
}

.leftBar {
  position: fixed;
  left: 0;
  padding-left: 1.2vh;
  top: 15vh;
  z-index: 100;
}

#prizeBar {
  max-height: 60vh;
  width: 330px;

  overflow-x: hidden;
  overflow-y: auto;

  /* 隐藏滚动条 */
  scrollbar-width: none;
  /* Firefox */
  -ms-overflow-style: none;
  /* IE */
}

#prizeBar::-webkit-scrollbar {
  display: none;
  /* Chrome, Safari */
}

.prize-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.prize-item {
  padding: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;
  /* color: rgba(127, 255, 255, 0.75); */
  width: 30vh;
  height: 9.5vh;
  box-sizing: border-box;
  transition: transform 1s ease-in;
}

.getPrizeName {
  color: #d5291f;
  font-weight: bold;
  font-size: 24px;
  width: 27vh;
  height: 5vh;
  border: 2px solid rgb(255, 255, 255);
  border-radius: 5px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: #ffd283;
  opacity: 0.8;
  margin-left: 2vh;
  margin-top: 3.5vh;
  cursor: pointer;
  position: relative;
}

.dgetPrizeName {
  color: #d5291f;
  font-weight: bold;
  font-size: 24px;
  width: 27vh;
  height: 60vh;
  border: 2px solid rgb(255, 255, 255);
  border-radius: 5px;
  display: flex;
  flex-direction: column;
  /* justify-content: center; */
  align-items: center;
  background-color: #ffd283;
  opacity: 0.8;
  margin-left: 2vh;
  margin-top: 3.5vh;
  position: relative;
}

.open {
  position: absolute;
  top: -42px;
  animation: bounce1 2s ease-in-out infinite;
  transform: rotate(180deg);
}

.close {
  position: absolute;
  top: -32px;
  animation: bounce2 2s ease-in-out infinite;
  cursor: pointer;
}

@keyframes bounce1 {
  0%,
  100% {
    transform: rotate(180deg) translateY(0);
  }

  50% {
    transform: rotate(180deg) translateY(-8px);
  }
}

@keyframes bounce2 {
  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-8px);
  }
}

.tableHead {
  width: 100%;
  display: flex;
  justify-content: center;
  font-size: 18px;
  /* gap: 80px; */
  margin-bottom: 10px;
  position: absolute;
  top: 10px;
}

.tableHead1 {
  width: 50%;
  text-align: center;
}

.tableHead2 {
  width: 50%;
  text-align: center;
}

.gradient-line {
  width: 90%;
  height: 3px;
  border-radius: 150%;
  background: linear-gradient(
    to right,
    transparent 0%,
    #d5291f 45%,
    #d5291f 55%,
    transparent 100%
  );
  position: absolute;
  bottom: -10px;
}

.tableBody {
  display: flex;
  margin-top: 50px;
  width: 100%;
  height: 50vh;
  justify-content: center;
  overflow-y: auto;
  /* 启用垂直滚动 */
  overflow-x: hidden;
  /* 启用垂直滚动 */
  /* 隐藏滚动条 */
  scrollbar-width: none;
  /* Firefox */
  -ms-overflow-style: none;
  /* IE */
}

.tableBody::-webkit-scrollbar {
  display: none;
  /* Chrome, Safari */
}

.tableItem {
  display: flex;
  font-size: 18px;
  width: 27vh;
  margin-bottom: 10px;
  top: 10px;
}

.tableItem1 {
  width: 50%;
  text-align: center;
}

.tableItem2 {
  width: 50%;
  text-align: center;
}

.tableFoot {
  color: #e64f39;
  display: flex;
  gap: 10px;
}

.leftPage {
  background-color: #ccc;
  color: white;
  cursor: not-allowed;
  /* background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%); */
  border-radius: 50%;
  display: flex;
  width: 35px;
  height: 35px;
  justify-content: center;
  /* align-items: center; */
}

.rightPage {
  color: white;
  cursor: pointer;
  background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%);
  border-radius: 50%;
  display: flex;
  width: 35px;
  height: 35px;
  justify-content: center;
}

.readyLook {
  width: 100%;
  height: 100%;
}

.prize-item .prize-img {
  width: 7.5vh;
  height: 7.5vh;

  margin: auto 10px;
  border-radius: 50%;
  background-color: #fff;
  text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
  overflow: hidden;
}

.prize-img img {
  width: 90%;
  height: 90%;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.prize-text {
  padding: 0 5px;
  width: 100%;
  height: 100%;
  /* margin: auto 0; */
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* gap: 4px; */
}

.prize-title {
  margin: 4px 0;
  font-size: 1.4vh;
  height: 30%;
  border: 1px solid #e13726;
  border-radius: 20px;
  background-color: #ffffff;
  display: flex;
  color: #d5291f;
  font-weight: bold;
  display: flex;
  align-items: center;
}

.level {
  width: 38%;
  height: 100%;
  margin-right: 2%;
  border-radius: 20px;
  background: linear-gradient(360deg, #e23d26, #f49c27) !important;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}

.prize-count {
  padding: 4px 0;
  position: relative;
}

.prize-count .progress {
  height: 1.8vh;
  background: rgba(0, 0, 0, 0.5);
  padding: 1px;
  overflow: visible;
  border-radius: 1vh;
}

.progress .progress-bar {
  border-radius: 1.8vh;
  position: relative;
  animation: animate-positive 2s;
  background-color: #d9534f;
  height: 1.8vh;
  -webkit-transition: width 0.6s ease;
  -o-transition: width 0.6s ease;
  transition: width 0.6s ease;
}

.progress-bar.active {
  animation: reverse progress-bar-stripes 0.4s linear infinite,
    animate-positive 2s;
}

.progress-bar-striped {
  background-image: -webkit-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.15) 25%,
    transparent 25%,
    transparent 50%,
    rgba(255, 255, 255, 0.15) 50%,
    rgba(255, 255, 255, 0.15) 75%,
    transparent 75%,
    transparent
  );
  background-image: -o-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.15) 25%,
    transparent 25%,
    transparent 50%,
    rgba(255, 255, 255, 0.15) 50%,
    rgba(255, 255, 255, 0.15) 75%,
    transparent 75%,
    transparent
  );
  background-image: linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.15) 25%,
    transparent 25%,
    transparent 50%,
    rgba(255, 255, 255, 0.15) 50%,
    rgba(255, 255, 255, 0.15) 75%,
    transparent 75%,
    transparent
  );
  -webkit-background-size: 8px 8px;
  background-size: 8px 8px;
}

@-webkit-keyframes animate-positive {
  0% {
    width: 0;
  }
}

@keyframes animate-positive {
  0% {
    width: 0;
  }
}

@-webkit-keyframes progress-bar-stripes {
  from {
    background-position: 8px 0;
  }

  to {
    background-position: 0 0;
  }
}

@-o-keyframes progress-bar-stripes {
  from {
    background-position: 8px 0;
  }

  to {
    background-position: 0 0;
  }
}

@keyframes progress-bar-stripes {
  from {
    background-position: 8px 0;
  }

  to {
    background-position: 0 0;
  }
}

.prize-count-left {
  position: absolute;
  color: #fff;
  right: 35%;
  font-size: 1.8vh;
  line-height: 1.6vh;
  top: 50%;
  transform: translateY(-50%);
}

.shine {
  background-color: #ffd283;
  border: 1px solid rgba(255, 255, 255, 1);
  border-radius: 5px;
  box-shadow: 0 0 15px 0 #ffd283;
  transform: scale(1.1);
  transform-origin: left center;
  position: relative;
  overflow: hidden;
}

.done {
  position: relative;
}

.done:after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ffd283;
  border: 2px solid rgba(255, 255, 255, 1);
  border-radius: 5px;
  opacity: 0.3;
  cursor: not-allowed;
}

.shine span {
  position: absolute;
  display: block;
}

.shine span:nth-child(1) {
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, transparent, #f46303);
  animation: animate1 1s linear infinite;
}

@keyframes animate1 {
  0% {
    left: -100%;
  }

  50%,
  100% {
    left: 100%;
  }
}

.shine span:nth-child(2) {
  top: -100%;
  right: 0;
  width: 2px;
  height: 100%;
  background: linear-gradient(180deg, transparent, #f46303);
  animation: animate2 1s linear infinite;
  animation-delay: 0.25s;
}

@keyframes animate2 {
  0% {
    top: -100%;
  }

  50%,
  100% {
    top: 100%;
  }
}

.shine span:nth-child(3) {
  bottom: 0;
  right: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(270deg, transparent, #f46303);
  animation: animate3 1s linear infinite;
  animation-delay: 0.5s;
}

@keyframes animate3 {
  0% {
    right: -100%;
  }

  50%,
  100% {
    right: 100%;
  }
}

.shine span:nth-child(4) {
  bottom: -100%;
  left: 0;
  width: 2px;
  height: 100%;
  background: linear-gradient(360deg, transparent, #f46303);
  animation: animate4 1s linear infinite;
  animation-delay: 0.75s;
}

@keyframes animate4 {
  0% {
    bottom: -100%;
  }

  50%,
  100% {
    bottom: 100%;
  }
}

.shine.prize-item {
  /* width: 24vh; */
  margin: 1.2vh 0;
}

.prize-mess {
  color: #fff;
  line-height: 5vh;
  font-size: 1.6vh;
  margin: 2.4vh 0;
}

.music {
  position: fixed;
  top: 3vh;
  right: 4vh;
  z-index: 5;
}

.music-item {
  display: block !important;
  opacity: 0;
}

.music-box {
  width: 5vh;
  height: 5vh;
  border-radius: 50%;
  text-align: center;
  line-height: 5vh;
  font-size: 1.4vh;
  color: #fff;
  cursor: pointer;
  background-color: rgba(253, 105, 0, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.5);
}

.rotate-active {
  animation: rotate 4s linear infinite;
}

@keyframes rotate {
  from {
    transform: rotate(0);
  }

  to {
    transform: rotate(360deg);
  }
}

.margin-l-40 {
  margin-left: 40px;
}

.fixed-bar {
  position: fixed;
  bottom: 20px;
  right: 20px;
}

.fixed-btn {
  margin: 20px 0 0;
  width: 200px;
  text-align: center;
  display: block;
}

#lottery {
  animation: breath 1.6s linear infinite;
  /* box-shadow: 0px 0px 15px rgb(127 255 255 / 75%); */
}

@keyframes breath {
  0% {
    transform: scale(1);
    opacity: 0.8;
  }

  25% {
    transform: scale(1.1);
    opacity: 1;
  }

  50% {
    transform: scale(1);
    opacity: 1;
  }

  75% {
    transform: scale(0.9);
    opacity: 1;
  }

  100% {
    transform: scale(1);
    opacity: 0.8;
  }
}
</style>
