<template>
  <div>
    <Header @confirmExit="confirmExit" @setMusic="setMusic"></Header>
    <Transition :enter-active-class="proxy?.animate.dialog.enter" :leave-active-class="proxy?.animate.dialog.leave">
      <div class="time"
        :class="{ 'time1': styleType == 1, 'time2': styleType == 2, 'time3': styleType == 3, 'time4': styleType == 4, }"
        v-show="(needStart && [42].includes(examState)) || (['situp', 'jumprope', 'jumpingjack', 'highknees', 'pullup', 'sidepullup', 'squat', 'jumpleftright', 'crossjump', 'kneeupclap'].includes(parameter.project) && [42].includes(examState))">
        {{
          time.countdownNum
        }}
      </div>
    </Transition>
    <div class="main">
      <div class="testBox"
        :class="{ 'testBox1': styleType == 1, 'testBox2': styleType == 2, 'testBox3': styleType == 3, 'testBox4': styleType == 4 }">
        <div class="ul"
          :class="{ 'overlap': (examState == 43 && time.ready) || [42].includes(examState) || (showTestAgain && ![41].includes(examState)), 'ready': [41].includes(examState), 'hands': parameter.gesture }"
          v-for="(items, indexs) in testListArr" :key="indexs">
          <MultipleItem :ref="(el: any) => { multipleItemRef(el, item.itemNumber, item.area) }"
            v-for="(item, index) in items" :query="parameter" :area="item.area" :key="index" @returnData="returnData"
            @getChooseStudent="getChooseStudent" :examState="examState" :needStart="needStart" :styleType="styleType"
            :parentTrainWsMethod="{ initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels }"
            :parentSpeechMethod="{ initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber }" />
        </div>
      </div>
    </div>
    <div class="footerBtn">
      <template v-if="needStart">
        <div class="btn" @click="getAgain" v-if="examState == 42 || showTestAgain">再测一次</div>
        <div class="btn" @click="getStartFace" v-if="examState < 41">开始识别</div>
        <div class="btn" @click="getStopFace" v-if="examState == 41">停止人脸识别</div>
        <div class="btn startBtn" @click="getReady" v-if="examState == 43">开始测试</div>
        <div class="btn" @click="getAllRetestFace" v-if="examState == 43 || examState == 42">重新识别</div>
      </template>
      <template v-else>
        <template v-if="examState == 43">
          <div class="btn startBtn" @click="getReady"
            v-if="['situp', 'jumprope', 'jumpingjack', 'highknees', 'pullup', 'sidepullup', 'squat', 'jumpleftright', 'crossjump', 'kneeupclap'].includes(parameter.project)">
            开始测试
          </div>
          <div class="btn startBtn" @click="getStartOneTest" v-else>开始测试</div>
        </template>
      </template>
      <div class="btn" :class="{ testRecordBtn: showReportList }" @click="getTestRecord"
        v-if="![43, 42].includes(examState)">
        {{ showReportList ? '关闭记录' : '测试记录' }}
      </div>
      <div class="btn exitBtn" @click="confirmExit">退 出</div>
      <!--测试记录开始-->
      <div class="mask mask2" v-show="showReportList" @click="getTestRecord"></div>
      <Transition :enter-active-class="proxy?.animate.report.enter" :leave-active-class="proxy?.animate.report.leave">
        <div class="main-right" v-show="showReportList">
          <ReportList ref="reportListRef" :parameter="parameter" :showQRCode="true" />
        </div>
      </Transition>
      <!--测试记录结束-->
    </div>
    <!--倒计时开始-->
    <div>
      <Transition :enter-active-class="proxy?.animate.mask.enter" :leave-active-class="proxy?.animate.mask.leave">
        <div class="mask" v-show="examState == 43 && time.ready"></div>
      </Transition>
      <Transition :enter-active-class="proxy?.animate.face.enter" :leave-active-class="proxy?.animate.face.leave">
        <div class="confirmDiaBg" v-show="examState == 43 && time.ready">
          <div class="confirmDiaWindow">
            <div class="readyBox">
              <div class="lable">倒计时</div>
              <div class="value" :class="{ 'transparent': time.ready > 5 }">{{ time.ready }}</div>
              <!-- <div class="lable2">预 备</div> -->
            </div>
          </div>
        </div>
      </Transition>
    </div>
    <!--倒计时结束-->
    <!--选择学生-->
    <ChooseStudent ref="chooseStudentRef" @returnData="returnStudent" />
    <!--十人以内排行榜-->
    <MultipleItemRanking ref="multipleItemRankingRef" :testList="testList"></MultipleItemRanking>
    <!--十人以上排行榜-->
    <MultipleItemAllRanking ref="multipleItemAllRankingRef" :testList="testList"></MultipleItemAllRanking>
  </div>
</template>

<script setup name="Multiple" lang="ts">
import { clearInterval, clearTimeout, setInterval, setTimeout } from 'worker-timers';
import useAppStore from '@/store/modules/app';
import { useWs } from '@/utils/trainWs';
import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech';
import { useWebSocket } from '@/utils/handWs';
const { handWs, startDevice, startHand, stateHand } = useWebSocket();
const {
  initWs,
  examEnds,
  openOneTest,
  startFace,
  stopFace,
  faceConfirmOnly,
  startOneTest,
  finishOneTest,
  closeOneTest,
  suspendFaceRecognitionChannels,
  resumeFaceRecognitionChannels
} = useWs();
const { proxy } = getCurrentInstance() as any;
const router = useRouter();
const route = useRoute();
const reportListRef = ref();
const chooseStudentRef = ref();
const multipleItemRankingRef = ref();
const multipleItemAllRankingRef = ref();

const data = reactive<any>({
  timerManager: {}, //计时器管理
  parameter: {}, //参数
  time: {
    testTime: 60, //时长
    countdownNum: 0, //计时
    ready: 0, //预备
    exit: 0 //退出倒计时
  },
  userInfo: {}, //用户信息
  examState: 0, //当前状态
  needStart: false, //是否需要按钮
  showTestAgain: false, //再测一次按钮
  testList: [], //获取区列表
  multipleItemRefList: [], //获取区列表
  styleType: null, //展示样式1：1-5个，2：6-10个，3：10个以上，4：1-4个，
  showReportList: false, //显示隐藏测试记录
  exitStatus: 0, //退出响应次数
  sid: null, //WS的id
  chooseStudentArea: {}, //弹出手动选择对应的区号
  deviceInfo: {}, //设备信息
  musicList: [] //音乐列表
});
const {
  timerManager,
  parameter,
  time,
  userInfo,
  examState,
  needStart,
  showTestAgain,
  testList,
  multipleItemRefList,
  styleType,
  showReportList,
  exitStatus,
  sid,
  chooseStudentArea,
  deviceInfo,
  musicList
} = toRefs(data);

/**
 * 创建组件实例
 */
const multipleItemRef = (el: any, index: number, area: any) => {
  multipleItemRefList.value[index - 1] = el;
};

/**
 * 开始项目和识别
 */
const getOpenOneTestAndStartFace = () => {
  cleanData();
  examState.value = 40;
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    multipleItemRefList.value[i].getOpenOneTestAndStartFace();
  }
};

/**
 * 开始项目
 */
const getOpenOneTest = () => {
  cleanData();
  examState.value = 40;
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    multipleItemRefList.value[i].getOpenOneTest();
  }
};

/**
 * 开始识别
 */
const getStartFace = () => {
  cleanData();
  examState.value = 41;
  let txt = parameter.value.gesture ? '请举右手看摄像头进行人脸识别' : '请看摄像头进行人脸识别';
  speckText(txt);
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    multipleItemRefList.value[i].getStartFace();
  }
};

/**
 * 停止人脸识别
 */
const getStopFace = async () => {
  let flag = false;
  for (let i = 0; i < testList.value.length; i++) {
    if (testList.value[i] && testList.value[i].faceCheckStu?.student_id) {
      flag = true;
    }
  }
  if (!flag) {
    proxy?.$modal.msgWarning('请选择人员！');
    return false;
  }
  examState.value = 43;
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    multipleItemRefList.value[i].getStopFace();
  }
};

/**
 * 开始测试
 */
const getStartOneTest = () => {
  if (examState.value != 43) {
    return false;
  }
  let flag = false;
  for (let i = 0; i < testList.value.length; i++) {
    if (testList.value[i] && testList.value[i].faceCheckStu?.student_id) {
      flag = true;
    }
  }
  if (!flag) {
    proxy?.$modal.msgWarning('请选择人员！');
    return false;
  }
  getClearTimer('readyTimer');
  time.value.ready = 0;
  examState.value = 42;
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    if (testList.value[i].examState == 41) {
      //正在识别的停止识别
      multipleItemRefList.value[i].getStopFace();
    }
    if (testList.value[i].examState == 43) {
      multipleItemRefList.value[i].getStartOneTest();
    }
  }
  speckText('哨声');
  if (parameter.value.music && musicList.value.length) {
    let obj = musicList.value.find((item: any) => {
      return item.id == parameter.value.music;
    });
    if (obj != undefined) {
      playMusic(obj.url);
    }
  }
  //显示再测一次按钮
  showTestAgain.value = true;
  //时间为0的为正计时，大于0的为倒计时
  if (time.value.testTime == 0) {
    getCounting('+');
  } else {
    getCounting('-');
  }
};

/**
 * 再测一次
 */
const getAgain = async () => {
  let txt = '是否再测一次？';
  await proxy?.$modal.confirm(txt);
  getClearTimer();
  let loading = ElLoading.service({ text: '请稍等...', background: 'rgba(0, 0, 0, 0.8)', customClass: `sports ${parameter.value.project}` });
  cleanData();
  examState.value = 41;
  speckCancel(); //停止播报
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    multipleItemRefList.value[i].getAgain();
  }
  timerManager.value.againTimer = setInterval(() => {
    if (examState.value == 43) {
      getClearTimer('againTimer');
      loading?.close();
    }
  }, 300);
  let loadingTime = setTimeout(() => {
    if (examState.value <= 41) {
      loading?.close();
      clearTimeout(loadingTime);
      getClearTimer('againTimer');
    }
  }, 10000);
};

/**
 * 重新识别
 */
const getAllRetestFace = async () => {
  let loading = ElLoading.service({ text: '请稍等...', background: 'rgba(0, 0, 0, 0.8)', customClass: `sports ${parameter.value.project}` });
  speckCancel(); //停止播报
  showTestAgain.value = false;
  examState.value = 3;
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    multipleItemRefList.value[i].getAllRetestFace();
  }
  timerManager.value.allRetestFaceTimer = setInterval(() => {
    if (examState.value == 41) {
      getClearTimer('allRetestFaceTimer');
      loading?.close();
    }
  }, 300);
  let loadingTime = setTimeout(() => {
    if (examState.value <= 3) {
      loading?.close();
      clearTimeout(loadingTime);
      getClearTimer('allRetestFaceTimer');
    }
  }, 10000);
};

/**
 * 确认退出
 */
const confirmExit = () => {
  let handcontroller_id = parameter.value.handcontroller;
  proxy?.$modal
    .confirm(handcontroller_id ? `请保持两秒确认退出` : `确定退出吗？`)
    .then(() => {
      getExit();
    })
    .finally(() => { });
};

/**
 * 退出
 */
const getExit = () => {
  getClearTimer(); //清除计时器
  examEnds(); //通知工作站关闭
  speckCancel(); //停止播报
  window.onbeforeunload = null; //移除事件处理器
  let handcontroller_id = parameter.value.handcontroller;
  if (handcontroller_id) {
    router.push({ path: '/gesture' });
  } else {
    if (parameter.value.taskId) {
      router.push({ path: '/test' });
    } else {
      router.push({ path: '/train' });
    }
  }
};

/**
 * 清空定时任务
 */
const getClearTimer = (data?: any) => {
  if (data) {
    //清除指定
    clearInterval(timerManager.value[data]);
    timerManager.value[data] = null;
  } else {
    //清除全部
    for (let key in timerManager.value) {
      if (timerManager.value.hasOwnProperty(key)) {
        clearInterval(timerManager.value[key]);
        timerManager.value[key] = null;
      }
    }
  }
};

/**
 * 清除历史记录
 */
const cleanData = () => {
  getClearTimer('countdownTimer');
  time.value.countdownNum = time.value.testTime;
  showTestAgain.value = false;
};

/**
 * 倒计时
 */
const getCounting = (type: string) => {
  timerManager.value.countdownTimer = setInterval(() => {
    //正计时
    if (type == '+') {
      time.value.countdownNum++;
    }
    //倒计时
    if (type == '-') {
      if (time.value.countdownNum <= 0) {
        getClearTimer('countdownTimer');
      } else {
        time.value.countdownNum--;
      }
    }
  }, 1000);
};

/**
 * 子组件选择学生
 */
const getChooseStudent = (data: any) => {
  console.log('data', data);
  chooseStudentArea.value = data;
  chooseStudentRef.value.open();
};

/**
 * 返回被选学生
 */
const returnStudent = (data: any) => {
  console.log('data', data);
  let area = chooseStudentArea.value.area;
  let index = testList.value.findIndex((item: any) => {
    return area == item.area;
  });
  console.log('index', index);
  multipleItemRefList.value[index]?.returnStudent(data);
};

/**
 * 子组件返回数据
 */
const returnData = (data: any) => {
  let index = testList.value.findIndex((item: any) => {
    return item.area == data.area;
  });
  let obj = Object.assign(testList.value[index], data);
  testList.value[index] = JSON.parse(JSON.stringify(obj));
  // console.log('testList.value', testList.value);

  if (examState.value == 0) {
    let flag = false;
    //只监听人脸识别的区
    let newList = testList.value;
    for (let i = 0; i < newList.length; i++) {
      if (newList[i] && newList[i].examState == 3) {
        flag = true;
      }
    }
    if (flag) {
      console.log('变更状态：', 3);
      examState.value = 3;
      speckCancel(); //停止播报
      if (needStart.value) {
        let handcontroller = parameter.value.handcontroller;
        let ctrl = parameter.value.ctrl;
        if (handcontroller && ctrl) {
          speckText(`请${ctrl}区举左手开始识别`);
        } else {
          proxy?.$modal.msgWarning(`请点击右下角的【开始识别】`);
        }
      }
    }
  }

  if (examState.value == 3) {
    let flag = false;
    //只监听人脸识别的区
    let newList = testList.value;
    for (let i = 0; i < newList.length; i++) {
      if (newList[i] && newList[i].examState == 40) {
        flag = true;
      }
    }
    if (flag) {
      console.log('变更状态：', 40);
      examState.value = 40;
    }
  }

  if (examState.value == 40) {
    let flag = false;
    //只监听人脸识别的区
    let newList = testList.value;
    for (let i = 0; i < newList.length; i++) {
      if (newList[i] && newList[i].examState == 41) {
        flag = true;
      }
    }
    if (flag) {
      console.log('变更状态：', 41);
      examState.value = 41;
      let txt = parameter.value.gesture ? '请举右手看摄像头进行人脸识别' : '请看摄像头进行人脸识别';
      speckText(txt);
      //如果过段时候后仍在识别中就提示停止识别
      // setTimeout(() => {
      //   if (examState.value == 41) {
      //     let handcontroller = parameter.value.handcontroller;
      //     let ctrl = parameter.value.ctrl;
      //     if (handcontroller && ctrl) {
      //       speckText(`各就位后请${ctrl}区举左手停止识别`);
      //     } else {
      //       proxy?.$modal.msgWarning(`各就位后请点击右下角的【停止人脸识别】`);
      //     }
      //   }
      // }, 15000)
    }
  }

  if (examState.value == 41) {
    let flag = false;
    //只监听人脸识别的区
    let newList = testList.value.filter((item: any) => {
      return item?.faceCheckStu?.student_id;
    });
    for (let i = 0; i < newList.length; i++) {
      if (newList[i] && newList[i].faceCheckStu?.student_id && newList[i].examState == 43) {
        flag = true;
      }
    }
    if (flag) {
      console.log('变更状态：', 43);
      examState.value = 43;
      cleanData();
      //如果过段时候后仍在识别中就提示停止识别
      // setTimeout(() => {
      //   if (examState.value == 43) {
      //     let handcontroller = parameter.value.handcontroller;
      //     let ctrl = parameter.value.ctrl;
      //     if (handcontroller && ctrl) {
      //       speckText(`请${ctrl}区举左手开始测试`);
      //     } else {
      //       proxy?.$modal.msgWarning(`请点击右下角的【开始测试】`);
      //     }
      //   }
      // }, 10000)
    }
  }

  //测试完成后回退状态
  if (examState.value == 42) {
    let flag = false;
    //只监听人脸识别的区
    let newList = testList.value.filter((item: any) => {
      return item?.faceCheckStu?.student_id;
    });
    for (let i = 0; i < newList.length; i++) {
      if (newList[i] && newList[i].faceCheckStu?.student_id && newList[i].examState == 3) {
        flag = true;
      } else {
        return false;
      }
    }
    if (flag) {
      console.log('变更状态：', 3);
      examState.value = 3;
      speckCancel();//停止播报
      //打开排行榜
      if (testList.value.length >= 10) {
        multipleItemAllRankingRef.value.open();
      } else {
        multipleItemRankingRef.value.open();
      }
    }
  }

  //如果全部状态为0就退出
  if (examState.value >= 0) {
    let flag = false;
    //只监听人脸识别的区
    let newList = testList.value;
    let myList = newList.filter((item: any) => {
      return item.examState == 0;
    });
    if (myList.length == newList.length) {
      examState.value = 0;
      getExit();
    }
  }
};

/**
 * 准备开始
 */
const getReady = () => {
  if (examState.value != 43) {
    return false;
  }
  if (time.value.ready) {
    return false;
  }
  let flag = false;
  for (let i = 0; i < testList.value.length; i++) {
    if (testList.value[i] && testList.value[i].faceCheckStu?.student_id) {
      flag = true;
    }
  }
  if (!flag) {
    proxy?.$modal.msgWarning('请选择人员！');
    return false;
  }
  //停止播报;
  speckCancel();
  //正在识别的停止识别
  for (let i = 0; i < multipleItemRefList.value.length; i++) {
    if (testList.value[i].examState == 41) {
      multipleItemRefList.value[i].getStopFace();
    }
  }
  //speckText("预备3");
  //speckText("各就位！预备！");
  time.value.ready = 6;
  timerManager.value.readyTimer = setInterval(() => {
    time.value.ready--;
    if (time.value.ready <= 0) {
      getClearTimer('readyTimer');
      getStartOneTest();
    } else {
      speckText(time.value.ready);
    }
  }, 1000);
};

/**
 * 成绩列表
 */
const getTestRecord = () => {
  if (showReportList.value) {
    showReportList.value = false;
  } else {
    reportListRef.value.getIniReportList();
    showReportList.value = true;
  }
};

/**
 * 自动填补空缺
 */
const getAddTestList = (num: number) => {
  let list = parameter.value.area.split(',');
  let myLength = num - list.length;
  for (let i = 0; i < myLength; i++) {
    let obj = {
      area: '',
      itemNumber: list.length + (i + 1)
    };
    testList.value.push(obj);
  }
};

/**
 * 获取设备项目
 */
const getDevice = async () => {
  let deviceid = localStorage.getItem('deviceid') || '';
  if (deviceid) {
    startDevice({ deviceid: deviceid });
  } else {
    proxy?.$modal.msgError(`缺少设备信息请重新登录！`);
    await proxy?.$http.common.logout({}).then((res: any) => { });
    proxy?.$modal?.closeLoading();
    //清空缓存
    // localStorage.clear();
    localStorage.removeItem('token');
    localStorage.removeItem('userInfo');
    //跳转
    router.push({ path: '/login/qrcode' });
  }
};

/**
 * 获取音乐
 */
const getMusic = async () => {
  const list: any = useAppStore().getMusic();
  if (list.length) {
    musicList.value = list;
  } else {
    await proxy?.$http.train.musicList().then((res: any) => {
      if (res.data.length > 0) {
        let myList: any = res.data;
        musicList.value = myList;
        useAppStore().setMusic(myList);
      }
    });
  }
};

/**
 * 设置音乐
 */
const setMusic = async (data: any) => {
  //console.log("data",data)
  parameter.value.music = data;
};

/**
 * 加载手势WS
 */
const initHand = () => {
  handWs((e: any) => {
    if (router.currentRoute.value.path != '/train/multiple' || parameter.value.handcontroller == undefined) {
      return false;
    }
    console.log('eeeee', e);
    if (e?.wksid) {
      //获取设备项目
      getDevice();
    }
    //接收设备信息
    if (e?.device_info) {
      deviceInfo.value = e.device_info;
      let handcontroller_id = deviceInfo.value.handcontroller_id;
      //启用才执行命令
      if (deviceInfo.value.status) {
        stateHand(handcontroller_id);
      }
    }
    //获取手势状态
    if (e?.cmd == 'get_handcontroller_state' && e?.state == 0) {
      let handcontroller_id = deviceInfo.value.handcontroller_id;
      startHand(handcontroller_id);
    }
    //刷新
    if (e?.data?.result == 'refresh') {
      getExit();
      //刷新
      window.location.reload();
    }
    //没初始化完成不监听手势动作
    if (examState.value == 0) {
      return false;
    }
    //左滑动
    if (e?.data?.result == 'next_item') {
      // proxy?.$modal.msgSuccess('手势指令：左滑动');
      // if(examState.value == 43 && time.value.ready){
      //   return false;
      // }
      // if (examState.value == 43 || examState.value == 42) {
      //   speckCancel();//停止播报
      //   getAllRetestFace();
      // }
    }
    //举左手
    if (e?.data?.result == 'left_hand') {
      //proxy?.$modal.msgSuccess('手势指令：举左手');
      //举左手确认退出
      // if (exitStatus.value) {
      //   exitStatus.value = 0;
      //   //确认退出
      //   let keyEvent: any = null;
      //   keyEvent = new KeyboardEvent('keydown', {
      //     key: 'Enter', // 键值
      //     code: 'Enter', // 键盘代码
      //     keyCode: 13, // 旧的键盘代码
      //     which: 13, // 新的键盘代码
      //     shiftKey: false, // 是否按下Shift键
      //     ctrlKey: false, // 是否按下Ctrl键
      //     metaKey: false, // 是否按下Meta键（Win键或Command键）
      //     bubbles: true, // 事件是否冒泡
      //     cancelable: true // 是否可以取消事件的默认行为
      //   });
      //   document.activeElement?.dispatchEvent(keyEvent);
      //   return false;
      // }
      //开始识别
      if (needStart.value && examState.value == 40) {
        getStartFace();
        return false;
      }
      //停止人脸识别
      if (needStart.value && examState.value == 41) {
        getStopFace();
        return false;
      }
      //开始测试
      if (examState.value == 43) {
        getReady();
        return false;
      }
    }
    //退出
    if (e?.data?.result == 'exit') {
      proxy?.$modal.msgSuccess('手势指令：交叉手');
      console.log("exitStatus.value", exitStatus.value)
      if (exitStatus.value == 0) {
        speckText("请保持两秒确认退出");
        //第一次才弹出
        confirmExit();
        setTimeout(() => {
          let keyEvent: any = null;
          let myKey = null;
          //如果交叉手两秒后返回超过4次就确认退出
          if (exitStatus.value >= 4) {
            myKey = 'Enter';
          } else {
            myKey = 'Esc';
          }
          if (myKey == 'Esc') {
            keyEvent = new KeyboardEvent('keydown', {
              key: 'Escape', // 键值
              code: 'Escape', // 键盘代码
              keyCode: 27, // 旧的键盘代码
              which: 27, // 新的键盘代码
              shiftKey: false, // 是否按下Shift键
              ctrlKey: false, // 是否按下Ctrl键
              metaKey: false, // 是否按下Meta键（Win键或Command键）
              bubbles: true, // 事件是否冒泡
              cancelable: true // 是否可以取消事件的默认行为
            });
            exitStatus.value = 0;
          }
          if (myKey == 'Enter') {
            keyEvent = new KeyboardEvent('keydown', {
              key: 'Enter', // 键值
              code: 'Enter', // 键盘代码
              keyCode: 13, // 旧的键盘代码
              which: 13, // 新的键盘代码
              shiftKey: false, // 是否按下Shift键
              ctrlKey: false, // 是否按下Ctrl键
              metaKey: false, // 是否按下Meta键（Win键或Command键）
              bubbles: true, // 事件是否冒泡
              cancelable: true // 是否可以取消事件的默认行为
            });
          }
          document.activeElement?.dispatchEvent(keyEvent);
        }, 2500)
      }
      exitStatus.value = exitStatus.value + 1
    }
    // if (e?.data?.result == "exit") {
    //   console.log("exitStatus.value", exitStatus.value)
    //   if (exitStatus.value == 0) {
    //     exitStatus.value = 1
    //     speckText("请5秒内举左手确认退出");
    //     //第一次才弹出
    //     confirmExit();
    //     time.value.exit = 6;
    //     timerManager.value.exitTimer = setInterval(() => {
    //       time.value.exit--;
    //       console.log("取消倒计时", time.value.exit)
    //       proxy?.$modal.msgWarning(`取消倒计时：${time.value.exit}`)
    //       if (time.value.exit == 0) {
    //         exitStatus.value = 0;
    //         getClearTimer("exitTimer");
    //         let keyEvent: any = null;
    //         keyEvent = new KeyboardEvent('keydown', {
    //           key: 'Escape', // 键值
    //           code: 'Escape', // 键盘代码
    //           keyCode: 27, // 旧的键盘代码
    //           which: 27, // 新的键盘代码
    //           shiftKey: false, // 是否按下Shift键
    //           ctrlKey: false, // 是否按下Ctrl键
    //           metaKey: false, // 是否按下Meta键（Win键或Command键）
    //           bubbles: true, // 事件是否冒泡
    //           cancelable: true // 是否可以取消事件的默认行为
    //         });
    //         document.activeElement?.dispatchEvent(keyEvent);
    //       }
    //     }, 1000);
    //   }
    // }
  });
};

/**
 * 播报时间
 */
watch(
  () => time.value.countdownNum,
  (newData) => {
    if (examState.value != 42) {
      return false;
    }
    if (newData >= 30 && newData < time.value.testTime) {
      if (newData % 30 == 0) {
        speckText(`还有${newData}秒`);
      }
    }
    if (newData == 10) {
      speckText('还有10秒');
    }
    if (newData <= 5) {
      speckText(newData);
    }
    if (newData == 0) {
      speckText('哨声');
    }
  },
  { immediate: true }
);

/**
 * 将测试列表转为多行
 */
const testListArr = computed(() => {
  let list: any = [];
  let num = 0;
  if (styleType.value == 1) {
    num = 3;
  }
  if (styleType.value == 2) {
    num = 5;
  }
  if (styleType.value == 3) {
    num = 10;
  }
  if (styleType.value == 4) {
    num = 4;
  }
  let myLength = Math.ceil(testList.value.length / num);
  for (let i = 0; i < myLength; i++) {
    list[i] = [];
    for (let j = 0; j < testList.value.length; j++) {
      if (j >= i * num && j < (i + 1) * num) {
        list[i].push(testList.value[j]);
      }
    }
  }
  // console.log('list', list);
  return list;
});

/**
 * 时间转换
 */
// const countdownNumFormat = computed(() => {
//   return time.value.countdownNum;
//   //return proxy?.$utils.timeFormat(time.value.countdownNum);
// });

onBeforeMount(() => {
  parameter.value = route.query;
  let project = parameter.value.project;
  let area = parameter.value.area;
  parameter.value.examId = `${project}_${area}`; //项目+区
  if (parameter.value.time) {
    time.value.testTime = parameter.value.time;
  }
  time.value.countdownNum = time.value.testTime;
  let myInfo: any = localStorage.getItem('userInfo');
  userInfo.value = JSON.parse(myInfo);
  if (parameter.value.gesture == 'true') {
    parameter.value.gesture = true;
  } else {
    parameter.value.gesture = false;
  }
  let list = parameter.value.area.split(',');
  testList.value = list.map((item: any, index: number) => {
    let obj = {
      area: item,
      itemNumber: index + 1
    };
    return obj;
  });

  //展示样式控制
  if (testList.value.length == 5) {
    styleType.value = 1;
    //填补空缺
    getAddTestList(5);
  }
  if (testList.value.length > 5 && testList.value.length <= 10) {
    styleType.value = 2;
    //填补空缺
    getAddTestList(10);
  }
  if (testList.value.length > 10) {
    styleType.value = 3;
  }
  if (testList.value.length < 5) {
    styleType.value = 4;
  }
  //需要开始按钮的项目
  let myList = ['situp', 'jumprope', 'jumpingjack', 'highknees', 'pullup', 'sidepullup', 'squat', 'jumpleftright', 'crossjump', 'kneeupclap'];
  if (myList.includes(project) && [2, 3].includes(styleType.value)) {
    needStart.value = true;
  }
  //加载音乐
  getMusic();
});

onMounted(() => {
  //加载WS
  let project = parameter.value.project;
  initWs({ parameter: parameter.value, testTime: time.value.testTime, version: 'v2' }, (data: any) => {
    //获取sid
    if (data.cmd === 'mySid') {
      console.log('data.data.sid', data.data.sid);
      sid.value = data.data.sid;
    }
    let index = testList.value.findIndex((item: any) => {
      let examId = `${project}_${item.area}`;
      return examId == data.exam_id;
    });
    multipleItemRefList.value[index]?.getMessage(data);
  });
  //初始化语音
  initSpeech();
  //初始化手势
  initHand();
  //刷新关闭
  window.onbeforeunload = function (e) {
    var confirmationMessage = '刷新/关闭页面将会关闭页面,是否确认退出页面?';
    (e || window.event).returnValue = confirmationMessage; // 兼容 Gecko + IE

    testList.value.forEach((item: any) => {
      let examId = item.exam_id;
      let bUrl = import.meta.env.VITE_APP_BASE_API;
      let classId = parameter.value.classes;
      let mySid = sid.value;
      let token: any = localStorage.getItem('token');
      let formData = new FormData();
      formData.append('exam_id', examId);
      formData.append('class_id', classId);
      formData.append('token', token);
      formData.append('sid', mySid);
      navigator.sendBeacon(bUrl + '/exam/close_exam', formData);
    });
    return confirmationMessage; // 兼容 Gecko + Webkit, Safari, Chrome
  };
});

onBeforeUnmount(() => {
  getExit();
});
</script>

<style scoped lang="scss">
$waiPadding: 6.51rem;

.time {
  width: 20vh;
  height: 20vh;
  line-height: 20vh;
  border-radius: 50%;
  color: #ff9402;
  font-size: 8vh;
  text-align: center;
  background-image: url('@/assets/images/test/time.png');
  background-position: center;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  position: absolute;
  right: 50%;
  top: -4vh;
  margin-right: -10vh;
  font-family: 'Saira-BlackItalic';
}

.time1,
.time4 {
  width: 26vh;
  height: 26vh;
  line-height: 26vh;
  font-size: 10.3vh;
  right: auto;
  left: 50%;
  top: 0vh;
  margin-left: 8vw;
  margin-right: auto;
}

.main {
  width: calc(100% - ($waiPadding * 2));
  height: 78vh;
  padding-top: 10rem;
  margin: 0 auto;
  display: flex;
  overflow: hidden;
  flex-direction: column;
}

.mask {
  position: fixed;
  height: 100vh;
  width: 100vw;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.3);
  z-index: 998;
}

.mask2 {
  background: rgba(0, 0, 0, 0.68);
}

.confirmDiaBg {
  width: 100%;
  height: 100vh;
  position: fixed;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 999;

  .confirmDiaWindow {
    width: 40%;
    height: 43.4%;
    border-radius: 1.6rem;
    opacity: 1;
    box-sizing: border-box;
    border: 0.55rem solid #13ed84;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);

    .readyBox {
      text-align: center;
      color: #1a293a;

      .lable {
        font-size: 4.3rem;
        line-height: 1;
        margin-bottom: 1.5rem;
      }

      .value {
        font-size: 10rem;
        line-height: 1;
        font-family: 'Saira-BlackItalic';
      }

      .transparent {
        opacity: 0;
      }

      .lable2 {
        font-size: 4.5rem;
      }
    }
  }
}

.footerBtn {
  width: 100%;
  padding: 0 calc(13.02rem / 2);
  box-sizing: border-box;
  position: fixed;
  bottom: 3vh;
  display: flex;
  justify-content: flex-end;

  .btn {
    width: 13vw;
    height: 6.1vh;
    line-height: 6.1vh;
    font-size: 3vh;
    color: #1a293a;
    text-align: center;
    border-radius: 1vh;
    cursor: pointer;
    margin-left: 10px;
    background: radial-gradient(159% 126% at 5% 93%, #8effa9 0%, #07ffe7 100%);
    box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 1px rgba(255, 255, 255, 0.3);

    &:hover {
      background: #8effa9;
    }
  }

  .startBtn {
    color: #ffffff;
    background: radial-gradient(159% 126% at 5% 93%, #f99f02 0%, #ed7905 100%);
    box-shadow: 3px 6px 4px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 2px rgba(255, 255, 255, 0.3);

    &:hover {
      background: #f99f02;
    }
  }

  .exitBtn {
    color: #ffffff;
    background: radial-gradient(159% 126% at 5% 93%, #931b1b 0%, #ec5624 0%, #ff6860 76%);
    box-shadow: 3px 6px 4px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);

    &:hover {
      background: #ec5624;
    }
  }

  .testRecordBtn {
    position: relative;
    z-index: 999;
  }
}

.main-right {
  width: 22.7%;
  height: 80vh;
  border-radius: 1.6rem;
  // background: linear-gradient(29deg, #092941 -82%, #2A484B 94%);
  background-color: rgba(9, 41, 65, 0.8);
  box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.4);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: absolute;
  z-index: 999;
  bottom: 6.5vh;
  right: calc(13.02rem / 2);
}

//列表样式写在此父组件里，子组件尽量减少个性化class和style，多样性以父组件控制类型
::v-deep(.testBox1) {
  $listMargin: 10vw;
  $listWidth: calc((100vw - ($waiPadding * 2) - $listMargin) / 5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;

  .ul {
    width: 100%;
    height: 36vh;
    display: flex;

    .li {
      width: $listWidth;
      position: relative;

      .ready {
        position: absolute;
        height: 100%;
        width: 100%;
        display: flex;
        align-items: center;
        justify-items: center;

        img {
          width: 100%;
        }
      }

      .userInfo {
        width: 100%;
        height: 100%;
        border-radius: 1.6rem;
        background: radial-gradient(122% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        margin-bottom: 3px;

        .userInfo-center {
          .pic {
            width: calc(36vh * 0.62);
            height: calc(36vh * 0.62);
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            margin: 0 auto 2vh auto;
            position: relative;

            .area {
              position: absolute;
              top: calc(36vh * 0.18);
              color: #203c52;
              font-size: 5vh;
              line-height: 1;
              font-family: 'Saira-ExtraBold';
              text-align: center;
            }

            img {
              width: 100%;
            }
          }

          .pic2 {
            box-sizing: border-box;
            border: 0.44rem solid rgba(26, 41, 58, 0.6315);
          }

          .name {
            width: 100%;
            color: #1a293a;
            font-size: 2.21rem;
          }

          .name2 {
            box-sizing: border-box;
            padding: 0.1rem 0.4rem;
            border-radius: 1.1rem;
            background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
            box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
          }

          .ctrlBox {
            position: absolute;
            left: 0;
            top: 0;
            border: 5px solid #ffffff;
            display: flex;
            flex-direction: column;
            align-items: center;
            background: rgba(0, 0, 0, 0.8);
            z-index: 2;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            border-radius: 1.6rem;

            img {
              max-width: 100%;
              max-height: 70%;
              margin: 10% 0 5% 0;
            }

            .lable {
              text-align: center;
              font-size: 2rem;
              color: #ffffff;
            }
          }
        }
      }

      .score {
        height: 18vh;
        line-height: 18vh;
        font-size: 12vh;
        font-family: 'Saira-BlackItalic';
        border: 0.55rem solid #13ed84;
        text-align: center;
        border-radius: 1.6rem;
        box-sizing: content-box;
        color: #1a293a;
        position: relative;
        background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
        display: none;

        &::before {
          content: '';
          width: 2vw;
          height: 2vw;
          display: block;
          position: absolute;
          top: -1.5vw;
          left: 50%;
          margin-left: -1vw;
          background-image: url('@/assets/images/test/yuan.png');
          background-position: center;
          background-repeat: no-repeat;
          background-size: 100% 100%;
          border-radius: 50%;
          flex-shrink: 0;
          transition: all 0.5s;
        }
      }
    }

    .disable {

      .userInfo,
      .score {
        opacity: 0.5;
      }
    }

    .wait {

      .userInfo,
      .score {
        opacity: 0.5;
      }
    }

    &:nth-child(1) {
      justify-content: space-between;
    }

    &:nth-child(2) {
      justify-content: space-evenly;

      .li {
        margin-left: calc($listMargin/4);
        margin-right: calc($listMargin/4);
      }
    }
  }

  .ready.ul {
    &:nth-child(1) {
      .li:nth-child(2) {
        &::after {
          content: '';
          position: absolute;
          height: 100%;
          width: 100%;
          display: block;
          background-image: url('@/assets/images/test/ready3.png');
          background-position: center center;
          background-repeat: no-repeat;
          background-size: 100%;
        }
      }
    }

    &:nth-child(2) {
      .li {
        &::after {
          content: '';
          position: absolute;
          height: 100%;
          width: 100%;
          display: block;
          background-image: url('@/assets/images/test/ready3.png');
          background-position: center center;
          background-repeat: no-repeat;
          background-size: 100%;
          top: -100%;
        }
      }
    }
  }

  .hands.ul {
    &:nth-child(1) {
      .li:nth-child(2) {
        &::after {
          background-image: url('@/assets/images/test/ready4.png');
        }
      }
    }

    &:nth-child(2) {
      .li {
        &::after {
          background-image: url('@/assets/images/test/ready4.png');
        }
      }
    }
  }

  .overlap.ul {
    transition: all 0.5s;

    .li {
      .score {
        display: block;
      }
    }

    &:nth-child(1) {
      margin-top: 5vh;

      .li {
        &::before {
          display: none;
        }

        &::after {
          display: none;
        }
      }
    }

    &:nth-child(2) {
      margin-top: -20vh;

      .li {
        &::before {
          display: none;
        }

        &::after {
          display: none;
        }
      }
    }
  }
}

::v-deep(.testBox2) {
  $listMargin: 10vw;
  $listWidth: calc((100% - $listMargin) / 5);

  .ul {
    width: 100%;
    height: 34vh;
    display: flex;
    justify-content: space-between;
    margin-bottom: 4vh;

    .li {
      width: $listWidth;
      position: relative;
      height: 100%;
      border-radius: 3vh;
      padding: 0.6vw;
      background: radial-gradient(122% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      box-sizing: border-box;

      .userInfo {
        width: 100%;
        height: 100%;
        border-radius: 1.6rem;
        background: radial-gradient(122% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        position: relative;

        .userInfo-center {
          .pic {
            width: calc(36vh * 0.62);
            height: calc(36vh * 0.62);
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            margin: 0 auto 2vh auto;
            position: relative;

            .area {
              position: absolute;
              top: calc(36vh * 0.18);
              color: #203c52;
              font-size: 5vh;
              line-height: 1;
              font-family: 'Saira-ExtraBold';
              text-align: center;
            }

            img {
              width: 100%;
            }
          }

          .pic2 {
            box-sizing: border-box;
            border: 0.44rem solid rgba(26, 41, 58, 0.6315);
          }

          .name {
            width: 100%;
            color: #1a293a;
            font-size: 2.21rem;
          }

          .ctrlBox {
            position: absolute;
            left: 0;
            top: 0;
            border: 5px solid #ffffff;
            display: flex;
            flex-direction: column;
            align-items: center;
            background: rgba(0, 0, 0, 0.8);
            z-index: 2;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            border-radius: 1.6rem;

            img {
              max-width: 100%;
              max-height: 70%;
              margin: 10% 0 5% 0;
            }

            .lable {
              text-align: center;
              font-size: 2rem;
              color: #ffffff;
            }
          }
        }
      }

      .score {
        height: 14vh;
        line-height: 14vh;
        font-size: 9vh;
        font-family: 'Saira-BlackItalic';
        background: #ffffff;
        box-sizing: border-box;
        border: 0.55rem solid #13ed84;
        text-align: center;
        border-radius: 1.6rem;
        box-sizing: content-box;
        color: #1a293a;
        position: relative;
        display: none;

        &::before {
          content: '';
          width: 2vw;
          height: 2vw;
          display: block;
          position: absolute;
          top: -1.3vw;
          left: 50%;
          margin-left: -1vw;
          background-image: url('@/assets/images/test/yuan.png');
          background-position: center;
          background-repeat: no-repeat;
          background-size: 100% 100%;
          border-radius: 50%;
          flex-shrink: 0;
          transition: all 0.5s;
        }
      }
    }

    .disable {
      opacity: 0.5;
    }

    .wait {
      opacity: 0.5;
    }
  }

  .overlap {
    .li {
      .userInfo {
        height: 6.2vw;

        .userInfo-center {
          width: 100%;
          text-align: center;
          display: flex;
          align-items: center;
          cursor: pointer;

          .pic {
            width: 6.2vw;
            height: 6.2vw;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            position: relative;
            flex-shrink: 0;
            margin: 0;

            .area {
              position: absolute;
              top: 0;
              left: 0;
              width: 100%;
              height: 100%;
              line-height: 6.2vw;
              color: #ffffff;
              font-size: 2.5vw;
              font-family: 'Saira-ExtraBold';
              text-align: center;
              background: rgba(#000000, 0.4);
            }

            img {
              width: 100%;
            }
          }

          .pic2 {
            box-sizing: border-box;
            border: 2px solid rgba(26, 41, 58, 0.6315);
          }

          .name {
            width: 100%;
            color: #1a293a;
            font-size: 1.8rem;
            border-radius: 2vw;
            padding: 0.5rem 0;
            background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
            box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
          }
        }
      }

      .score {
        display: block;
      }
    }
  }
}

::v-deep(.testBox3) {
  $listMargin: 5vw;
  $listWidth: calc((100% - $listMargin) / 10);

  .ul {
    width: 100%;
    height: 14vh;
    display: flex;
    justify-content: space-around;
    margin-bottom: calc($listMargin / 10);

    .li {
      width: $listWidth;
      position: relative;
      height: 100%;
      border-radius: 5vh;
      background: radial-gradient(122% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);

      .userInfo {
        padding: 2vh 0.6vw 0 0.6vw;
        margin-bottom: 0.8vh;

        .userInfo-center {
          text-align: center;
          display: flex;
          align-items: center;
          cursor: pointer;
          border-radius: 1.3vw;
          height: 2.6vw;
          background: linear-gradient(180deg, #ffffff 0%, rgba(255, 255, 255, 0.6571) 100%);
          border: 1px solid #ffffff;

          .pic {
            width: 2.6vw;
            height: 2.6vw;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            position: relative;
            flex-shrink: 0;

            .area {
              position: absolute;
              top: 0;
              left: 0;
              width: 100%;
              height: 100%;
              line-height: 2.6vw;
              color: #ffffff;
              font-size: 1.4vw;
              font-family: 'Saira-ExtraBold';
              text-align: center;
              background: rgba(#000000, 0.4);
            }

            img {
              width: 100%;
            }
          }

          .pic2 {
            box-sizing: border-box;
            border: 2px solid rgba(26, 41, 58, 0.6315);
          }

          .name {
            color: #1a293a;
            font-size: 1rem;
            margin-left: 0.5vw;
          }

          .ctrlBox {
            position: absolute;
            left: 0;
            top: 0;
            border: 5px solid #ffffff;
            display: flex;
            flex-direction: column;
            align-items: center;
            background: rgba(0, 0, 0, 0.8);
            z-index: 2;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            border-radius: 5vh;

            img {
              max-width: 100%;
              max-height: 60%;
              margin: 5% 0 5% 0;
            }

            .lable {
              text-align: center;
              font-size: 1rem;
              color: #ffffff;
            }
          }
        }
      }

      .score {
        font-size: 3rem;
        font-family: 'Saira-BlackItalic';
        text-align: center;
        color: #1a293a;
        line-height: 1;
      }
    }

    .disable {
      opacity: 0.5;
    }

    .wait {
      opacity: 0.75;
    }

    .startedAlready {
      background: #15ef96;
    }
  }
}

::v-deep(.testBox4) {
  $listMargin: 10vw;
  $listWidth: calc((100vw - ($waiPadding * 2) - $listMargin) / 5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  height: 100%;

  .ul {
    width: 100%;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
    height: 36vh;

    .li {
      width: $listWidth;
      height: 100%;
      position: relative;

      .ready {
        position: absolute;
        height: 100%;
        width: 100%;
        display: flex;
        align-items: center;
        justify-items: center;

        img {
          width: 100%;
        }
      }

      .userInfo {
        width: 100%;
        height: 100%;
        border-radius: 1.6rem;
        background: radial-gradient(122% 126% at 97% 6%, #35ffc6 0%, #00ffe8 100%);
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        margin-bottom: 3px;

        .userInfo-center {
          .pic {
            width: calc(36vh * 0.62);
            height: calc(36vh * 0.62);
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            margin: 0 auto 2vh auto;
            position: relative;

            .area {
              position: absolute;
              top: calc(36vh * 0.18);
              color: #203c52;
              font-size: 5vh;
              line-height: 1;
              font-family: 'Saira-ExtraBold';
              text-align: center;
            }

            img {
              width: 100%;
            }
          }

          .pic2 {
            box-sizing: border-box;
            border: 0.44rem solid rgba(26, 41, 58, 0.6315);
          }

          .name {
            width: 100%;
            color: #1a293a;
            font-size: 2.21rem;
          }

          .name2 {
            box-sizing: border-box;
            padding: 0.1rem 0.4rem;
            border-radius: 1.1rem;
            background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
            box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
          }

          .ctrlBox {
            position: absolute;
            left: 0;
            top: 0;
            border: 5px solid #ffffff;
            display: flex;
            flex-direction: column;
            align-items: center;
            background: rgba(0, 0, 0, 0.8);
            z-index: 2;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            border-radius: 1.6rem;

            img {
              max-width: 100%;
              max-height: 70%;
              margin: 10% 0 5% 0;
            }

            .lable {
              text-align: center;
              font-size: 2rem;
              color: #ffffff;
            }
          }
        }
      }

      .score {
        height: 18vh;
        line-height: 18vh;
        font-size: 12vh;
        font-family: 'Saira-BlackItalic';
        border: 0.55rem solid #13ed84;
        text-align: center;
        border-radius: 1.6rem;
        box-sizing: content-box;
        color: #1a293a;
        position: relative;
        background: radial-gradient(96% 96% at 2% 32%, #ffffff 0%, #fcfdfd 54%, #e1e4e7 100%);
        display: none;

        &::before {
          content: '';
          width: 2vw;
          height: 2vw;
          display: block;
          position: absolute;
          top: -1.5vw;
          left: 50%;
          margin-left: -1vw;
          background-image: url('@/assets/images/test/yuan.png');
          background-position: center;
          background-repeat: no-repeat;
          background-size: 100% 100%;
          border-radius: 50%;
          flex-shrink: 0;
          transition: all 0.5s;
        }
      }
    }

    .disable {

      .userInfo,
      .score {
        opacity: 0.5;
      }
    }

    .wait {

      .userInfo,
      .score {
        opacity: 0.5;
      }
    }
  }

  .overlap.ul {
    transition: all 0.5s;
    margin-top: -15vh;

    .li {
      .score {
        display: block;
      }
    }
  }
}
</style>
