林旭祥 9 hónapja
szülő
commit
55df22194a

+ 10 - 4
src/components/FaceWindow/index.vue

@@ -5,7 +5,7 @@
       <div class="mask" v-show="faceState"></div>
     </transition> -->
     <transition :enter-active-class="proxy?.animate.face.enter"
-      :leave-active-class="faceCheckStu.student_id ? proxy?.animate.face.leave : proxy?.animate.face.leave2">
+      :leave-active-class="direction == 'right' ? proxy?.animate.face.leave3 : faceCheckStu.student_id ? proxy?.animate.face.leave1 : proxy?.animate.face.leave2">
       <div class="confirmDiaBg" v-show="faceState">
         <div class="confirmDiaWindow">
           <div class="confirmDiaWindow-con">
@@ -43,17 +43,23 @@ const props = defineProps({
 
 const data = reactive<any>({
   faceState: false,//人脸识别窗口状态
+  direction: "",//动画方向
 });
 
-const { faceState } = toRefs(data);
+const { faceState, direction } = toRefs(data);
 
 //打开
-const open = (data: any) => {
+const open = (data?: any) => {
+  if (data == "right") {
+    direction.value = data;
+  } else {
+    direction.value = "";
+  }
   faceState.value = true;
 };
 
 //关闭
-const close = () => {
+const close = (type?: any) => {
   faceState.value = false;
 };
 

+ 6 - 1
src/components/OptionWindow/index.vue

@@ -22,7 +22,7 @@
                 </div>
               </div>
               <div @click="getAllArea" class="allBtn" :class="{ 'active': chooseAllState }">{{ chooseAllState ? '重 置' :
-      '全 选' }}</div>
+                '全 选' }}</div>
             </div>
             <div class="standardBox">
               <div class="content-title content-title2">评分标准</div>
@@ -217,6 +217,11 @@ const getClass = () => {
 
 //选择测试区
 const getChooseArea = (data: any) => {
+  if (chooseArea.value.length > 5) {
+    optionForm.value.gesture = false;
+  } else {
+    optionForm.value.gesture = true;
+  }
   let id = data.key;
   let inData = chooseArea.value.includes(id);
   if (inData) {

+ 9 - 2
src/utils/animate.ts

@@ -14,8 +14,9 @@ const dialog = {
 
 const face = {
   enter: animatePrefix + 'animate__fadeIn',
-  leave: animatePrefix + 'animate__zoomOutLeft',
-  leave2: animatePrefix + 'animate__fadeOut'
+  leave1: animatePrefix + 'animate__zoomOutLeft',
+  leave2: animatePrefix + 'animate__fadeOut',
+  leave3: animatePrefix + 'animate__zoomOutRight'
 };
 
 const page = {
@@ -23,6 +24,11 @@ const page = {
   leave: animatePrefix + 'animate__fadeOutLeft'
 };
 
+const foul = {
+  enter: animatePrefix + 'animate__fadeIn',
+  leave: animatePrefix + 'animate__fadeOut'
+};
+
 const error = {
   enter: animatePrefix + 'animate__shakeX'
 };
@@ -32,5 +38,6 @@ export default {
   dialog,
   face,
   page,
+  foul,
   error
 };

+ 226 - 69
src/views/train/test.vue

@@ -10,7 +10,6 @@
     <div class="logo"> <img src="@/assets/images/logo.png">
       </img>
       <div class="title"><i></i><span>{{ dic.project[parameter.project] || "" }}</span></div>
-
     </div>
     <div class="main">
       <div class="main-left">
@@ -28,34 +27,68 @@
             </div>
           </div>
           <div class="top-right">
-            <div class="time" v-if="needStart && [42, 43].includes(examState)">{{
-              time.countdownNum
+            <transition :enter-active-class="proxy?.animate.dialog.enter"
+              :leave-active-class="proxy?.animate.dialog.leave">
+              <div class="time" v-show="needStart && [42].includes(examState)">{{
+                time.countdownNum
               }}</div>
+            </transition>
             <div class="tips" v-if="examState == 41">
               <img v-if="parameter.gesture" src="@/assets/images/test/ready1.png" />
               <img v-if="!parameter.gesture" src="@/assets/images/test/ready2.png" />
             </div>
-            <div class="complete" v-if="faceCheckStu.student_id">
+            <div class="complete" :class="{ 'complete2': needStart && [42].includes(examState) }"
+              v-if="faceCheckStu.student_id && time.ready <= 0 && examState != 43">
               <div class="scoreBox">
-                <div class="score">{{ currentResultObj.count }}</div>
-                <!-- <div class="unit" v-if="currentResultObj.count">{{ unit }}</div> -->
+                <div class="score">{{ currentResultObj.count || 0 }}</div>
+                <div class="unit" v-if="currentResultObj.count && !needStart">{{ unit }}</div>
               </div>
               <div class="fractionViolation">
                 <div class="fraction">
                   <div class="lable">得分:</div>
-                  <div class="value">{{ currentResultObj.score }}</div>
+                  <div class="value">{{ currentResultObj.score || "" }}</div>
                 </div>
                 <div class="violation">
                   <div class="lable">{{ ['jumprope'].includes(parameter.project) ? '中断' : '犯规' }}</div>
-                  <div class="value">{{ currentResultObj.back_num }}</div>
+                  <div class="value">{{ currentResultObj.back_num || 0 }}</div>
                 </div>
               </div>
             </div>
-            <div v-if="examState == 42 && backReason.length">
-              <div>违规项</div>
-              <div v-for="(item, index) in backReason" :key="index">{{ item }}</div>
+
+            <div class="foulBox" v-if="examState == 42 && backReason.length">
+              <div class="foul" v-for="(item, index) in backReason" :key="index">
+                <div class="lable">!</div>
+                <div class="value">{{ item }}</div>
+              </div>
             </div>
-            <div class="btn" @click="getStartOneTest" v-if="needStart && examState == 43">开始测试</div>
+
+            <div v-if="examState == 43 && time.ready">
+              <div class="readyBox">
+                <div class="value">{{ time.ready }}</div>
+                <div class="lable">倒计时</div>
+              </div>
+            </div>
+
+            <div v-if="examState == 43 && !time.ready">
+              <div class="readyBoxBefore">
+                <div class="item" v-if="parameter.gesture">
+                  <div><img src="@/assets/images/test/jushou.png" /></div>
+                  <div class="lable">
+                    <div>请举手开始</div>
+                  </div>
+                </div>
+                <div v-if="!parameter.gesture">
+                  <div class="item"><img src="@/assets/images/test/bujushou.png" /></div>
+                  <div class="lable">
+                    <div>请点击开始</div>
+                  </div>
+                </div>
+              </div>
+            </div>
+
+
+
+            <div class="btn" @click="getReady" v-if="needStart && examState == 43 && !time.ready">开 始</div>
             <!-- <div v-if="needStart"> -->
             <!-- <div class="btn" @click="getOpenOneTestAndStartFace" v-if="examState == 3 || examState == 40">开始识别</div> -->
             <!-- <div class="btn" @click="getStopFace" v-if="examState == 41 && !parameter.gesture">停止人脸识别</div> -->
@@ -124,6 +157,7 @@ const data = reactive<any>({
   time: {
     testTime: 60,//时长
     countdownNum: 0,//计时
+    ready: 0,//预备
   },
   userInfo: {},//用户信息
   examState: 0,//当前状态
@@ -195,7 +229,8 @@ const getMessage = (e: any) => {
 
     }
     if (e.data == 42) {
-
+      getClearTimer("readyTimer");
+      time.value.ready = 0;
     }
   }
   //新建测试后返回信息,获取result_id
@@ -386,11 +421,7 @@ const getClearTimer = (data?: any) => {
 */
 const getChooseStudent = () => {
   if (examState.value < 41) {
-    if (needStart.value) {
-      proxy?.$modal.msgError("请点击开始识别");
-    } else {
-      proxy?.$modal.msgError("请等待");
-    }
+    proxy?.$modal.msgError("请等待");
   }
   if (examState.value == 41) {
     chooseStudentRef.value.open();
@@ -490,7 +521,7 @@ const getFaceWindow = (data: boolean) => {
     faceWindowRef.value.open();
     //然后定时自动关闭
     setTimeout(() => {
-      if (examState.value == 41 && faceWindowRef.value.faceState == true) {
+      if (examState.value == 41 && faceWindowRef.value?.faceState == true) {
         faceWindowRef.value.close();
       }
     }, 3000)
@@ -590,6 +621,7 @@ const getAchievement = (data: any) => {
       }
     }
   }
+  arr.push("哈哈哈哈");
   backReason.value = arr;
   if (data.isfinish) {
     if (['jump'].includes(type) && backReason.value.length) {
@@ -598,6 +630,11 @@ const getAchievement = (data: any) => {
     }
     speckText(faceCheckStu?.value.name + "成绩为" + (chineseNumber(count) || 0) + unit.value + ",请下一位准备!" || "");
     getReportList();
+    faceWindowRef.value.open("right");
+    //然后定时自动关闭
+    setTimeout(() => {
+      faceWindowRef.value.close();
+    }, 1000)
   }
 };
 
@@ -636,6 +673,23 @@ const getFullScreen = () => {
   date.value = proxy?.$utils.fullScreen();
 };
 
+/**
+ * 准备开始
+*/
+const getReady = () => {
+  time.value.ready = 5;
+  speckText(time.value.ready);
+  timerManager.value.readyTimer = setInterval(() => {
+    if (time.value.ready <= 1) {
+      getClearTimer("readyTimer");
+      getStartOneTest();
+    } else {
+      time.value.ready--;
+      speckText(time.value.ready);
+    }
+  }, 1000);
+};
+
 onMounted(() => {
   setDate();
   parameter.value = route.query;
@@ -856,7 +910,7 @@ $waiPadding: 6.51rem;
         display: flex;
         align-items: center;
         justify-content: center;
-        flex-wrap: wrap;
+        flex-direction: column;
         position: relative;
 
         .time {
@@ -890,91 +944,192 @@ $waiPadding: 6.51rem;
         }
 
         .complete {
-          padding-top: 5vh;
-          padding-left: 20%;
           width: 100%;
-        }
-
-        .scoreBox {
-
-          height: 10vh;
-          color: #1A293A;
           display: flex;
-          align-items: center;
-          margin-bottom: 5vh;
+          justify-content: center;
+          flex-direction: column;
+          margin-bottom: 3vh;
 
-          .score {
-            font-size: 7.178rem;
-            font-family: 'Saira-BlackItalic';
+          .scoreBox {
+            height: 10vh;
+            color: #1A293A;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            margin-bottom: 5vh;
 
-          }
+            .score {
+              font-size: 8.5rem;
+              line-height: 8.5rem;
+              font-family: 'Saira-BlackItalic';
+            }
 
-          .unit {
-            font-size: 2rem;
-            margin-left: 10px;
+            .unit {
+              font-size: 2rem;
+              margin-left: 10px;
+            }
           }
-        }
 
-        .fractionViolation {
-          height: 10vh;
-          display: flex;
-          align-items: center;
-          margin-bottom: 5vh;
-
-          .fraction {
-            width: 40%;
-            height: 11vh;
-            line-height: 11vh;
-            border-radius: 5.5vh;
+          .fractionViolation {
+            height: 10vh;
             display: flex;
             align-items: center;
             justify-content: center;
-            background: linear-gradient(138deg, #38536C 21%, #1A293A 75%);
-            box-shadow: inset 0px 1px 13px 0px rgba(255, 255, 255, 0.9452);
 
-            .lable {
-              font-size: 1.93rem;
-              color: #13ED84;
+            .fraction {
+              height: 10vh;
+              line-height: 10vh;
+              border-radius: 5vh;
+              display: flex;
+              align-items: center;
+              padding: 0 6%;
+              background: linear-gradient(138deg, #38536C 21%, #1A293A 75%);
+              box-shadow: inset 0px 1px 13px 0px rgba(255, 255, 255, 0.9452);
+
+              .lable {
+                font-size: 4vh;
+                color: #13ED84;
+              }
+
+              .value {
+                font-size: 7vh;
+                color: #00FFE8;
+                font-family: 'Saira-BlackItalic';
+                min-width: 7vh;
+              }
             }
 
-            .value {
-              font-size: 6.62rem;
-              color: #00FFE8;
-              font-family: 'Saira-BlackItalic';
+            .violation {
+              height: 6.1vh;
+              line-height: 6.1vh;
+              border-radius: 4vh;
+              border: 0.25rem solid #ED7905;
+              display: flex;
+              align-items: center;
+              margin-left: 11px;
+              padding: 3px;
+              box-sizing: content-box;
+
+              .lable {
+                font-size: 1.2rem;
+                color: #ffffff;
+                width: 6.1vh;
+                height: 6.1vh;
+                line-height: 6.1vh;
+                background: #ED7905;
+                border-radius: 50%;
+
+                text-align: center;
+              }
+
+              .value {
+                margin-left: 1.5vh;
+                font-size: 3.2rem;
+                color: #ED7905;
+                font-family: 'Saira-BlackItalic';
+                min-width: 6vh;
+              }
+            }
+          }
+        }
+
+        .complete2 {
+          padding-left: 20%;
+          padding-top: 5vh;
+
+          .scoreBox {
+            margin-bottom: 3vh;
+            justify-content: left;
+          }
 
+          .fractionViolation {
+            justify-content: left;
+
+            .fraction {
+              padding: 0 8%;
             }
           }
+        }
 
-          .violation {
-            height: 8vh;
-            line-height: 8vh;
-            border-radius: 4vh;
-            box-sizing: border-box;
+        .foulBox {
+          height: calc(4.2vh + 0.5rem + 6px);
+          overflow: hidden;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+
+          .foul {
+            height: 4.2vh;
+            line-height: 4.2vh;
+            border-radius: 3vh;
             border: 0.25rem solid #ED7905;
             display: flex;
             align-items: center;
             margin-left: 11px;
+            padding: 3px;
+            box-sizing: content-box;
 
             .lable {
-              font-size: 1.2rem;
+              font-size: 2rem;
               color: #ffffff;
-              width: 6vh;
-              height: 6vh;
-              line-height: 6vh;
+              width: 4.2vh;
+              height: 4.2vh;
+              line-height: 4.2vh;
               background: #ED7905;
               border-radius: 50%;
-              margin: 0 1vh;
               text-align: center;
             }
 
             .value {
-              font-size: 3.2rem;
+              margin-left: 1.5vh;
+              font-size: 2rem;
               color: #ED7905;
               font-family: 'Saira-BlackItalic';
+              min-width: 6vh;
+              padding: 0 10px;
+            }
+          }
+        }
+
+        .readyBoxBefore {
+          display: flex;
+          justify-content: center;
+          font-size: 2.5rem;
+          color: #1A293A;
+          padding-top: 4vh;
+          line-height: 0;
+          margin-bottom: 2vh;
+
+          .item {
+            display: flex;
+            justify-content: center;
+
+            .lable {
+              display: flex;
+              align-items: center;
+              margin-left: 10px;
             }
           }
+
+          img {
+            height: 20vh;
+          }
         }
 
+        .readyBox {
+          text-align: center;
+          color: #1A293A;
+
+          .value {
+            font-size: 8.5rem;
+            line-height: 8.5rem;
+            font-family: 'Saira-BlackItalic';
+          }
+
+          .lable {
+            font-size: 3.5rem;
+          }
+        }
 
         .btn {
           font-size: 2.21rem;
@@ -989,6 +1144,8 @@ $waiPadding: 6.51rem;
           box-shadow: 3px 6px 4px 1px rgba(0, 0, 0, 0.1874), inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
           cursor: pointer;
         }
+
+
       }
 
       i {