Browse Source

日常开发

林旭祥 8 months ago
parent
commit
4250e44f0a

+ 27 - 0
src/api/module/common.ts

@@ -65,5 +65,32 @@ export default {
       method: 'get',
       data: data
     });
+  },
+
+  //获取工作站列表
+  allExams: (data: any) => {
+    return req({
+      url: '/school/get_all_exams',
+      method: 'post',
+      data: data
+    });
+  },
+
+  //删除工作站
+  delExamSettings: (data: any) => {
+    return req({
+      url: '/school/del_gpu_exam_setting',
+      method: 'post',
+      data: data
+    });
+  },
+
+  //关闭工作站
+  closeExamForce: (data: any) => {
+    return req({
+      url: '/school/close_exam_force',
+      method: 'post',
+      data: data
+    });
   }
 };

BIN
src/assets/images/common/set1.png


BIN
src/assets/images/common/set2.png


+ 1 - 1
src/components/Header/index.vue

@@ -7,7 +7,7 @@
   </div>
   <div class="logo"> <img src="@/assets/images/logo.png">
     </img>
-    <div class="title"><i></i><span>{{ dic.project[parameter.project] || "" }}</span></div>
+    <div class="title" v-if="parameter.project"><i></i><span>{{ dic.project[parameter.project] || "" }}</span></div>
   </div>
 </template>
 <script setup lang="ts">

+ 2 - 1
src/router/index.ts

@@ -16,7 +16,8 @@ const router = createRouter({
         { path: '/train/test', component: () => import('@/views/train/test.vue') },
         { path: '/train/run', component: () => import('@/views/train/run.vue') },
         { path: '/train/multiple', component: () => import('@/views/train/multiple.vue') },
-        { path: '/set', component: () => import('@/views/set/index.vue') }
+        { path: '/set', component: () => import('@/views/set/index.vue') },
+        { path: '/set/config', component: () => import('@/views/set/config.vue') }
       ]
     }
   ]

+ 11 - 5
src/utils/index.ts

@@ -79,11 +79,11 @@ let utils = {
   /**
    * 跑步成绩格式化
    */
-  runTime: (times: any, noMin = false, isLongRun: boolean) => {
+  runTime: (times: any, noMin = false, type: boolean, lang: any = 0) => {
     if (times != undefined && times.toString().indexOf('.') != -1) {
       times = Math.round((times + Number.EPSILON) * 100) / 100;
     }
-    if (isLongRun) {
+    if (type) {
       if (times <= 0) {
         return '0分0秒';
       }
@@ -161,9 +161,15 @@ let utils = {
           .format('mm′ss″SSS')
           .slice(0, -1);
       } else {
-        return dayjs(+times * 1000)
-          .format('ss″SSS')
-          .slice(0, -1);
+        if (lang == 1) {
+          return dayjs(+times * 1000)
+            .format('ss秒SSS')
+            .slice(0, -1);
+        } else {
+          return dayjs(+times * 1000)
+            .format('ss″SSS')
+            .slice(0, -1);
+        }
       }
     }
   },

+ 263 - 0
src/views/set/config.vue

@@ -0,0 +1,263 @@
+<template>
+  <div class="config">
+    <Header @confirmExit="confirmExit"></Header>
+    <div class="main">
+      <el-table :data="examList" class="table" @row-click="handleSelectionChange" highlight-current-row>
+        <el-table-column prop="0" label="项目" sortable />
+        <el-table-column prop="1" label="状态" />
+        <el-table-column prop="2" label="工作站" :formatter="showWorkers" sortable />
+        <el-table-column fixed="right" label="操作" width="210">
+          <template #default="scope">
+            <el-button @click="chooseItem(scope.row)" size="small" type="primary" plain>部署</el-button>
+            <el-button @click="delExamConf(scope.row)" size="small" type="danger" plain>删除</el-button>
+            <el-button @click="closeExam(scope.row)" size="small" type="warning" plain v-show="scope.row[1] == '已开启'">下课
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="footerBtn">
+      <div class="btn" @click="addGpuExam">添加项目</div>
+      <div class="btn" @click="closeLedScreen">关闭LED屏幕</div>
+      <div class="btn" @click="restartGpu">重启工作站</div>
+      <div class="btn" @click="stopGpu">关闭工作站</div>
+      <div class="btn" @click="getExamList">刷新</div>
+    </div>
+  </div>
+</template>
+
+<script setup name="Login" lang="ts">
+import dataDictionary from "@/utils/dataDictionary"
+const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+const dic: any = dataDictionary;
+
+const data = reactive<any>({
+  examList: [],
+  selectValue: [],
+  loginname: "",
+  workers: {},
+  workerMap: [],
+  oLWorkers: {},
+  examMaxIdxMap: {},
+  existExamIds: {},
+});
+
+const { examList, selectValue, loginname, workers, workerMap, oLWorkers, examMaxIdxMap, existExamIds } = toRefs(data);
+
+//被选行
+const handleSelectionChange = (data: any) => {
+  selectValue.value = data;
+};
+
+//获取列表
+const getExamList = async () => {
+  let myInfo: any = localStorage.getItem("userInfo");
+  let userInfo = JSON.parse(myInfo);
+  let params: any = {
+    school_id: userInfo.school_id
+  };
+  let res = await proxy?.$http.common.allExams(params)
+  workers.value = res.workers
+  Object.keys(res.workers).forEach((item) => {
+    workerMap.value[res.workers[item][0]] = item
+    let wkVal = workers.value[item]
+    if (wkVal[1] === "在线") {
+      oLWorkers.value[item] = wkVal
+    }
+  })
+  loginname.value = res.login_name
+  let list = [];
+  for (let i in res.exams) {
+    if (i.indexOf("skiprope") != 0 && i.indexOf("heartbeat") != 0) {
+      let enIndex = i.split('_')
+      let en = enIndex[0]
+      let eindex = enIndex[1]
+      res.exams[i].worker.forEach((worker: any) => {
+        if (worker in examMaxIdxMap.value) { }
+        else { examMaxIdxMap.value[worker] = {} }
+        if (en in examMaxIdxMap.value[worker]) {
+          if (Number(eindex) > Number(examMaxIdxMap.value[worker][en])) {
+            examMaxIdxMap.value[worker][en] = Number(eindex)
+          }
+        } else {
+          examMaxIdxMap.value[worker][en] = Number(eindex)
+        }
+        if (worker in existExamIds.value) {
+          existExamIds.value[worker].push(i)
+        } else {
+          existExamIds.value[worker] = []
+        }
+      })
+      list.push(
+        [dic.project[en] + "_" + eindex, res.exams[i].isopen,
+        res.exams[i].worker, i])
+    }
+  }
+  examList.value = list;
+};
+
+//转换
+const showWorkers = (row: any) => {
+  return row[2].join(",")
+};
+
+//添加项目
+const addGpuExam = (row: any) => {
+
+};
+
+//关闭LED屏幕
+const closeLedScreen = (row: any) => {
+
+};
+
+//重启工作站
+const restartGpu = (row: any) => {
+
+};
+
+//关闭工作站
+const stopGpu = (row: any) => {
+
+};
+
+const chooseItem = (item: any) => {
+  // let itemName = this.exams[item]
+  let isOn = false
+  item[2].forEach((wkId: any) => {
+    if (workers.value[wkId]) {
+      if (workers.value[wkId][1] == "在线") {
+        isOn = true
+      }
+    }
+  })
+  if (isOn) {
+
+  } else {
+    proxy?.$modal.msgError(`工作站不在线暂不允许配置`);
+  }
+};
+
+const delExamConf = (item: any) => {
+  let conTitle = `是否移除项目-${item[0]}`
+  proxy?.$modal.confirm(conTitle).then(() => {
+    let examId = item[3]
+    let ename = examId.split("_")[0]
+    let eidx = Number(examId.split("_")[1])
+
+    let myInfo: any = localStorage.getItem("userInfo");
+    let userInfo = JSON.parse(myInfo);
+    let params: any = {
+      exam_id: examId,
+      school_id: userInfo.school_id
+    };
+    proxy?.$http.common.delExamSettings(
+      params
+    ).then((res: any) => {
+      if (res.status == 200) {
+        let selWorker: any;
+        let existIdx: any;
+        item[2].forEach((worker: any) => {
+          existIdx = existExamIds.value[worker].indexOf(examId)
+          if (examMaxIdxMap.value[worker][ename] == eidx) {
+            examMaxIdxMap.value[worker][ename] = eidx - 1
+            selWorker = worker
+          } else if (existIdx > -1) {
+            selWorker = worker
+          }
+        })
+        console.log(selWorker, examMaxIdxMap.value, "examMaxIdxMap.value")
+        // let existIdx = existExamIds.value[selWorker].indexOf(examId)
+        let index = examList.value.indexOf(item)
+        if (existIdx > -1) {
+          existExamIds.value[selWorker].splice(existIdx, 1)
+        }
+        if (index > -1) {
+          examList.value.splice(index, 1)
+        }
+        proxy?.$modal.msgSuccess(`删除成功`);
+      } else {
+        proxy?.$modal.msgError(`${res.message}`);
+      }
+
+    })
+  }).catch((err: any) => {
+  });
+};
+
+const closeExam = (item: any) => {
+  let myInfo: any = localStorage.getItem("userInfo");
+  let userInfo = JSON.parse(myInfo);
+  let params: any = {
+    exam_id: item[3],
+    school_id: userInfo.school_id
+  };
+  proxy?.$http.common.closeExamForce(
+    params
+  ).then((res: any) => {
+    if (res.status == 200) {
+      proxy?.$modal.msgSuccess(`下课成功`);
+    }
+    getExamList()
+  })
+};
+
+/**
+ * 返回
+*/
+const confirmExit = () => {
+  router.go(-1);
+};
+
+onMounted(() => {
+  getExamList();
+})
+</script>
+
+<style lang="scss" scoped>
+$topPadding: 5.19rem;
+$waiPadding: 6.51rem;
+
+.main {
+  width: calc(100% - ($waiPadding * 2));
+  padding-top: 10rem;
+  margin: 0 auto;
+  display: flex;
+  justify-content: center;
+  overflow: hidden;
+
+  .table {
+    width: 100%;
+    height: 65vh;
+  }
+}
+
+.footerBtn {
+  width: 100%;
+  padding: 0 calc(13.02rem /2);
+  box-sizing: border-box;
+  position: fixed;
+  bottom: 3vh;
+  display: flex;
+  justify-content: end;
+
+  .btn {
+    width: 11vw;
+    height: 6.1vh;
+    line-height: 6.1vh;
+    font-size: 3vh;
+    color: #1A293A;
+    text-align: center;
+    border-radius: 1vh;
+    cursor: pointer;
+    background: radial-gradient(159% 126% at 5% 93%, #8EFFA9 0%, #07FFE7 100%);
+    box-shadow: 3px 6px 4px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
+    margin-left: 10px;
+
+    &:hover {
+      background: #8EFFA9;
+    }
+  }
+}
+</style>

+ 97 - 6
src/views/set/index.vue

@@ -1,7 +1,25 @@
 <template>
   <div class="set">
-    <div @click="getLogout">退出</div>
-    <div @click="getExit">返回</div>
+    <Header @confirmExit="confirmExit"></Header>
+    <div class="main">
+      <div class="li" @click="getConfig">
+        <div class="liBox">
+          <div class="pic"><img src="@/assets/images/common/set1.png"></div>
+          <div class="name">
+            部署
+          </div>
+        </div>
+
+      </div>
+      <div class="li" @click="getLogout">
+        <div class="liBox">
+          <div class="pic"><img src="@/assets/images/common/set2.png"></div>
+          <div class="name">
+            退出
+          </div>
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
@@ -9,6 +27,11 @@
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 
+//设置
+const getConfig = () => {
+  //跳转
+  router.push({ path: '/set/config' });
+};
 
 // 退出
 const getLogout = () => {
@@ -17,19 +40,19 @@ const getLogout = () => {
     let params = {};
     proxy?.$http.common.logout(params).then((res: any) => {
     });
-  }).finally(() => {
     proxy?.$modal?.closeLoading()
     //清空缓存
     localStorage.clear();
     //跳转
     router.push({ path: '/login' });
+  }).finally(() => {
   });
 };
 
 /**
- * 退出
+ * 返回
 */
-const getExit = () => {
+const confirmExit = () => {
   router.go(-1);
 };
 
@@ -38,4 +61,72 @@ onMounted(() => {
 })
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+$topPadding: 5.19rem;
+$waiPadding: 6.51rem;
+
+.main {
+  width: calc(100% - ($waiPadding * 2));
+  height: 60vh;
+  padding-top: 10rem;
+  margin: 0 auto;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  overflow: hidden;
+
+  .li {
+    width: 13vw;
+    height: 19vw;
+    border-radius: 1.6rem;
+    box-sizing: border-box;
+    box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    text-align: center;
+    cursor: pointer;
+    margin: 0 20px;
+    background: radial-gradient(167% 126% at 97% 6%, #35FFC6 0%, #00FFE8 100%);
+
+    .liBox {
+      .name {
+        width: 100%;
+        font-size: 2.48rem;
+        color: #1A293A;
+        padding: 0.5rem 0;
+      }
+
+
+      .pic {
+        width: 10vw;
+        height: 10vw;
+        border-radius: 50%;
+        background: radial-gradient(78% 78% at 53% 50%, #07121A 0%, #2A4256 49%, #5180A9 100%);
+        box-shadow: 0px 0px 2px 2px #FFFFFF;
+        margin-bottom: 2vh;
+        overflow: hidden;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        flex-shrink: 0;
+
+        img {
+          width: 50%;
+          height: 50%;
+          transition: all 1s;
+        }
+      }
+
+    }
+
+    &:hover {
+      img {
+        transform: translateY(-0.5vw);
+      }
+    }
+
+  }
+
+}
+</style>

+ 1 - 0
src/views/train/multiple.vue

@@ -575,6 +575,7 @@ $waiPadding: 6.51rem;
     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: 3px 6px 4px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
 

+ 175 - 71
src/views/train/run.vue

@@ -4,36 +4,40 @@
     <transition :enter-active-class="proxy?.animate.dialog.enter" :leave-active-class="proxy?.animate.dialog.leave">
       <div class="time" v-show="[42].includes(examState)">{{
         countdownNumFormat
-      }}</div>
+        }}</div>
     </transition>
     <div class="main">
-
       <template v-if="isLongRun">
         <swiper :slides-per-view="2" :space-between="20">
           <swiper-slide v-for="(items, indexs) in testListArr " :key="indexs">
-            <div class="main-left">
+            <div class="main-left main-left2">
               <div class="trackItem">
-                <div v-for="(item, index) in items" :key="index" class="li">
-                  <div class="track">{{ item.track }}</div>
-                  <div class="userInfo" @click="getChooseStudent(item.track)">
-                    <div class="pic pic2" v-if="item.face_pic"> <img :src="item.face_pic" /></div>
-                    <div class="pic" v-else>
-                      <img src="@/assets/images/test/profilePicture.png" />
+                <div v-for="(item, index) in items" :key="item" class="li">
+                  <div class="left">
+                    <div class="track">{{ item.track }}</div>
+                    <div class="userInfo" @click="getChooseStudent(item.track)">
+                      <div class="pic pic2" v-if="item.face_pic"> <img :src="item.face_pic" /></div>
+                      <div class="pic" v-else>
+                        <img src="@/assets/images/test/profilePicture.png" />
+                      </div>
+                      <div class="nameBox">
+                        <div class="name">{{ item.student_name || "未检录" }}</div>
+                      </div>
                     </div>
-                    <div class="name">{{ item.student_name || "未检录" }}</div>
                   </div>
-                  <div>
+                  <div class="scoreBox">
                     <div v-if="item.timeStr" class="score">
                       {{ item.timeStr || "-" }}
                     </div>
-                    <div v-if="isBackRun && item.student_id"> 往返次数:{{ item.turns || "0" }} </div>
+                    <div v-if="isBackRun && item.student_id" class="turns">往返次数:<span><i>{{ item.turns || "0"
+                          }}</i></span>
+                    </div>
+                  </div>
+                  <div class="menuBtn" v-if="examState < 42 && !item.isfinish" @click="getChooseStudent(item.track)">检录
                   </div>
-                  <div class="menuBtn" v-if="isBackRun && item.student_id"> 往返次数:{{ item.turns || "0" }} </div>
-                  <div class="menuBtn" v-if="examState < 42" @click="getChooseStudent(item.track)">检录</div>
-                  <div class="menuBtn" v-if="examState == 43">等待开始测试</div>
-                  <div class="menuBtn" v-if="examState == 42">正在测试</div>
-                  <div class="menuBtn menuBtn"
-                    v-if="examState == 3 && !item.timeStr && item.isfinish && item.student_id">
+                  <div class="menuBtn menuBtn2" v-if="examState == 43 && item.student_id">等待开始测试</div>
+                  <div class="menuBtn menuBtn2" v-if="examState == 42 && item.student_id">正在测试</div>
+                  <div class="menuBtn" v-if="examState == 3 && !item.timeStr && item.isfinish && item.student_id">
                     异常
                   </div>
                 </div>
@@ -45,26 +49,30 @@
       <template v-else>
         <div class="main-left">
           <div class="trackItem">
-            <div v-for="(item, index) in faceStudentList" :key="index" class="li">
-              <div class="track">{{ item.track }}</div>
-              <div class="userInfo" @click="getChooseStudent(item.track)">
-                <div class="pic pic2" v-if="item.face_pic"> <img :src="item.face_pic" /></div>
-                <div class="pic" v-else>
-                  <img src="@/assets/images/test/profilePicture.png" />
+            <div v-for="(item, index) in faceStudentList" :key="item" class="li">
+              <div class="left">
+                <div class="track">{{ item.track }}</div>
+                <div class="userInfo" @click="getChooseStudent(item.track)">
+                  <div class="pic pic2" v-if="item.face_pic"> <img :src="item.face_pic" /></div>
+                  <div class="pic" v-else>
+                    <img src="@/assets/images/test/profilePicture.png" />
+                  </div>
+                  <div class="nameBox">
+                    <div class="name">{{ item.student_name || "未检录" }}</div>
+                  </div>
                 </div>
-                <div class="name">{{ item.student_name || "未检录" }}</div>
               </div>
-              <div>
+              <div class="scoreBox">
                 <div v-if="item.timeStr" class="score">
                   {{ item.timeStr || "-" }}
                 </div>
-                <div v-if="isBackRun && item.student_id"> 往返次数:{{ item.turns || "0" }} </div>
+                <div v-if="isBackRun && item.student_id" class="turns">往返次数:<span><i>{{ item.turns || "0" }}</i></span>
+                </div>
               </div>
-              <div class="menuBtn" v-if="isBackRun && item.student_id"> 往返次数:{{ item.turns || "0" }} </div>
               <div class="menuBtn" v-if="examState < 42" @click="getChooseStudent(item.track)">检录</div>
-              <div class="menuBtn" v-if="examState == 43">等待开始测试</div>
-              <div class="menuBtn" v-if="examState == 42">正在测试</div>
-              <div class="menuBtn menuBtn" v-if="examState == 3 && !item.timeStr && item.isfinish && item.student_id">
+              <div class="menuBtn menuBtn2" v-if="examState == 43 && item.student_id">等待开始测试</div>
+              <div class="menuBtn menuBtn2" v-if="examState == 42 && item.student_id">正在测试</div>
+              <div class="menuBtn" v-if="examState == 3 && !item.timeStr && item.isfinish && item.student_id">
                 异常
               </div>
             </div>
@@ -104,7 +112,8 @@
         <div class="btn startBtn" @click="getStartOneTest" v-if="examState == 43">开始测试</div>
       </template>
       <template v-else> </template>
-      <div class="btn" @click="getAgain" v-if="examState == 42 || showTestAgain">再测一次</div>
+      <div class="btn" @click="getConfirmEnd" v-if="examState == 42">{{ isLongRun ? '结 束' : '下一组' }}</div>
+      <div class="btn" @click="getAgain" v-if="showTestAgain">再测一次</div>
       <div class="btn" @click="getRetestFace" v-if="examState == 43">重新识别</div>
     </div>
     <ChooseStudent ref="chooseStudentRef" @returnData="returnStudent" />
@@ -157,7 +166,7 @@ const getMessage = (e: any) => {
   //工作站状态
   if (e.cmd === 'init_result') {
     if (isLongRun.value) {
-      let num = 70;
+      let num = 80;
       let list: any = [];
       for (let i = 1; i <= num; i++) {
         list.push({ track: i });
@@ -342,6 +351,7 @@ const getStartOneTest = () => {
  * 再测一次
 */
 const getAgain = async () => {
+  let loading = ElLoading.service({ text: '请稍等...', background: 'rgba(0, 0, 0, 0.8)', customClass: `sports ${parameter.value.project}` });
   //预存测试人员
   let student = faceStudentList.value.map((item: any) => {
     let obj = {
@@ -366,6 +376,38 @@ const getAgain = async () => {
   await startFace();
   await stopFace();
   getFaceConfirmOnly(student);
+  loading?.close();
+  let loadingTime = setTimeout(() => {
+    loading?.close();
+    clearTimeout(loadingTime);
+  }, 10000);
+};
+
+/**
+ * 确认退出
+*/
+const getConfirmEnd = async () => {
+  let txt = isLongRun.value ? '是否结束' : '是否开始下一组?'
+  await proxy?.$modal.confirm(txt);
+  let loading = ElLoading.service({ text: '请稍等...', background: 'rgba(0, 0, 0, 0.8)', customClass: `sports ${parameter.value.project}` });
+  //测试中
+  if (examState.value == 42) {
+    await finishOneTest();
+  }
+  //其他状态
+  if (examState.value > 3) {
+    await closeOneTest();
+  }
+  if (!isLongRun.value) {
+    //重新走一次流程
+    await openOneTest();
+    await startFace();
+  }
+  loading?.close();
+  let loadingTime = setTimeout(() => {
+    loading?.close();
+    clearTimeout(loadingTime);
+  }, 10000);
 };
 
 /**
@@ -415,6 +457,10 @@ const getChooseStudent = (track: number) => {
     proxy?.$modal.msgWarning("请点击开始人脸识别");
     return false;
   }
+  if (examState.value == 43) {
+    proxy?.$modal.msgWarning("请点击重新识别");
+    return false;
+  }
   currentTrack.value = track;
   chooseStudentRef.value.open();
 };
@@ -579,7 +625,7 @@ const getReportList = () => {
 */
 const testListArr: any = computed(() => {
   let list: any = [];
-  let num = 7;
+  let num = 8;
   let myLength = Math.ceil(faceStudentList.value.length / num);
   for (let i = 0; i < myLength; i++) {
     list[i] = [];
@@ -692,7 +738,7 @@ $waiPadding: 6.51rem;
   line-height: 20vh;
   border-radius: 50%;
   color: #FF9402;
-  font-size: 8vh;
+  font-size: 7.5vh;
   text-align: center;
   background-image: url("@/assets/images/test/time.png");
   background-position: center;
@@ -714,10 +760,9 @@ $waiPadding: 6.51rem;
   justify-content: space-between;
   overflow: hidden;
 
-
-
   .main-left {
     width: 71.5%;
+    height: 100%;
     display: flex;
     background: linear-gradient(58deg, #092941 -85%, #2A484B 96%);
     box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.4);
@@ -753,63 +798,122 @@ $waiPadding: 6.51rem;
         border-bottom: 1px solid #475557;
         height: calc(100%/8);
         box-sizing: border-box;
+        padding: 0px 20px 0px 50px;
 
-        .track {
-          color: #13ED84;
-          font-size: 2rem;
-          font-family: 'Saira-ExtraBold';
-        }
-
-        .pic {
-          width: 7vh;
-          height: 7vh;
-          border-radius: 50%;
+        .left {
           display: flex;
-          justify-content: center;
           align-items: center;
-          overflow: hidden;
 
-          img {
-            width: 100%;
+          .track {
+            width: 5rem;
+            color: #13ED84;
+            font-size: 2rem;
+            font-family: 'Saira-ExtraBold';
+            margin-right: 1rem
           }
-        }
 
+          .pic {
+            width: 6.7vh;
+            height: 6.7vh;
+            border-radius: 50%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            overflow: hidden;
+            margin-right: 15px;
 
-        .pic2 {
-          box-sizing: border-box;
-          border: 1px solid rgba(255, 255, 255, 0.5);
+            img {
+              width: 100%;
+            }
+          }
+
+
+          .pic2 {
+            box-sizing: border-box;
+            border: 1px solid rgba(255, 255, 255, 0.5);
+          }
+
+          .userInfo {
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+
+            .nameBox {
+              width: 8rem;
+
+              .name {
+                font-size: 1.5rem;
+                color: #ffffff;
+              }
+            }
+
+
+          }
         }
 
-        .userInfo {
+        .scoreBox {
           display: flex;
-          justify-content: flex-start;
           align-items: center;
 
-          .name {
+          .score {
+            color: #ffffff;
             font-size: 2rem;
+            font-family: 'Saira-ExtraBold';
+          }
+
+          .turns {
+            margin-left: 3rem;
             color: #ffffff;
+            display: flex;
+            align-items: center;
+
+            span {
+              font: 1.5rem;
+              margin-left: 5px;
+            }
+
+            i {
+              font-style: normal;
+              font-size: 1.8rem;
+              font-family: 'Saira-ExtraBold';
+            }
           }
         }
 
-        .score {
-          color: #ffffff;
-          font-size: 2rem;
-          font-family: 'Saira-ExtraBold';
-        }
 
         .menuBtn {
           width: auto;
-          padding: 0 1.2rem 0 0.7rem;
-          height: 3rem;
-          line-height: 3rem;
-          border-radius: 1.5rem;
+          padding: 0 1.2rem;
+          height: 2.8rem;
+          line-height: 2.8rem;
+          border-radius: 1.4rem;
           color: #ffffff;
-          font-size: 1.7rem;
-          margin-left: 1rem;
+          font-size: 1.5rem;
           background: linear-gradient(180deg, #FFB200 0%, #ED7905 72%);
           box-shadow: inset 0px 1px 0px 1px rgba(255, 255, 255, 0.5);
           display: flex;
           align-items: center;
+          cursor: pointer;
+        }
+
+        .menuBtn2 {
+          color: #1A293A;
+          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 2px rgba(255, 255, 255, 0.5577);
+        }
+      }
+    }
+  }
+
+  .main-left2 {
+    width: 100%;
+
+    .trackItem {
+      .li {
+        .scoreBox {
+          .score {
+            font-size: 1.8rem;
+          }
         }
       }
     }
@@ -964,7 +1068,7 @@ $waiPadding: 6.51rem;
     margin-left: 20px;
     cursor: pointer;
     background: radial-gradient(159% 126% at 5% 93%, #8EFFA9 0%, #07FFE7 100%);
-    box-shadow: 3px 6px 4px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
+    box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.1874), inset 1px 1px 1px 1px rgba(255, 255, 255, 0.5577);
 
     &:hover {
       background: #8EFFA9;
@@ -974,7 +1078,7 @@ $waiPadding: 6.51rem;
   .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.5577);
+    box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.1874), inset 1px 1px 1px 1px rgba(255, 255, 255, 0.5577);
 
     &:hover {
       background: #F99F02;

+ 22 - 5
src/views/train/test.vue

@@ -21,7 +21,7 @@
               :leave-active-class="proxy?.animate.dialog.leave">
               <div class="time" v-show="needStart && [42].includes(examState)">{{
                 time.countdownNum
-                }}</div>
+              }}</div>
             </transition>
             <div class="tips" v-if="examState == 41">
               <img v-if="parameter.gesture" src="@/assets/images/test/ready1.png" />
@@ -29,7 +29,11 @@
             </div>
             <div class="complete" :class="{ 'complete2': needStart && [42].includes(examState) }"
               v-if="faceCheckStu.student_id && time.ready <= 0 && examState != 43">
-              <div class="scoreBox">
+
+              <div class="scoreBox" v-if="['basketballv1'].includes(parameter.project)">
+                <div class="score">{{ currentResultObj.count || 0 }}</div>
+              </div>
+              <div class="scoreBox" v-else>
                 <div class="score">{{ currentResultObj.count || 0 }}</div>
                 <div class="unit" v-if="currentResultObj.count && !needStart">{{ unit }}</div>
               </div>
@@ -113,7 +117,11 @@
                 </div>
               </div>
             </div>
-            <div class="right">
+            <div class="right" v-if="['basketballv1'].includes(parameter.project)">
+              <div class="score">{{ proxy?.$utils.runTime(item.result, true, 1) }}
+              </div>
+            </div>
+            <div class="right" v-else>
               <div class="score">{{ item.result }}
               </div>
               <div class="unit">{{ unit }}</div>
@@ -543,6 +551,9 @@ const getAchievement = (data: any) => {
       data?.[dic.typeResultKey[type]]?.toFixed(2);
     count = Math.round(count) / 100;
   }
+  if (["basketballv1"].includes(type)) {
+    count = proxy?.$utils.runTime(data?.[dic.typeResultKey[type]], true, 1)
+  }
   data.count = count || "0";
   data.score = data.score || "0";
   currentResultObj.value = data;
@@ -622,7 +633,13 @@ const getAchievement = (data: any) => {
       speckText("请重新测试");
       return false;
     }
-    speckText(faceCheckStu?.value.name + "成绩为" + (chineseNumber(count) || 0) + unit.value + ",请下一位准备!" || "");
+    if (["basketballv1"].includes(type)) {
+      speckText(faceCheckStu?.value.name + "成绩为" + (chineseNumber(proxy?.$utils.runTime(count, false, 0,
+        1)) || 0) + ",请下一位准备!" || "");
+    } else {
+      speckText(faceCheckStu?.value.name + "成绩为" + (chineseNumber(count) || 0) + unit.value + ",请下一位准备!" || "");
+    }
+
     getReportList();
     faceWindowRef.value.open("right");
     //然后定时自动关闭
@@ -695,7 +712,7 @@ onBeforeMount(() => {
     parameter.value.gesture = false
   }
   //需要开始按钮的项目
-  if (["jumprope", "skiprope", "jumpingjack", "situp"].includes(project)) {
+  if (["jumprope", "skiprope", "jumpingjack", "situp", "basketballv1"].includes(project)) {
     needStart.value = true;
   }
   //加载WS