林旭祥 hace 3 semanas
padre
commit
9e01c3fb45

BIN
src/assets/images/home/course2.png


BIN
src/assets/images/home/query.png


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


+ 89 - 53
src/components/OnlineFaceWindow/index.vue

@@ -1,26 +1,29 @@
 <template>
   <div>
-    <!-- <Transition :enter-active-class="proxy?.animate.mask.enter" :leave-active-class="proxy?.animate.mask.leave">
+    <Transition :enter-active-class="proxy?.animate.mask.enter" :leave-active-class="proxy?.animate.mask.leave">
       <div class="mask" v-show="faceState"></div>
-    </Transition> -->
-    <Transition :enter-active-class="proxy?.animate.face.enter" :leave-active-class="proxy?.animate.face.leave">
+    </Transition>
+    <Transition :enter-active-class="proxy?.animate.rankingWindow.enter"
+      :leave-active-class="proxy?.animate.rankingWindow.leave">
       <div class="confirmDiaBg" v-show="faceState">
-        <div class="confirmDiaWindow">
-          <div class="confirmDiaWindow-con">
-            <div class="pic" :class="{ 'pic2': faceCheckStu.student_id }" v-if="faceCheckStu.student_id"> <img
-                :src="faceCheckStu.student_icon" /></div>
-            <div class="pic" v-else>
-              <div class="shine">
-                <img src="@/assets/images/common/shine.png" />
+        <div>
+          <div class="confirmDiaWindow">
+            <div class="confirmDiaWindow-con">
+              <div class="pic" :class="{ 'pic2': faceCheckStu.student_id }" v-if="faceCheckStu.student_id"> <img
+                  :src="faceCheckStu.student_icon" /></div>
+              <div class="pic" v-else>
+                <div class="shine">
+                  <img src="@/assets/images/common/shine.png" />
+                </div>
+                <img src="@/assets/images/test/profilePicture.png" />
+              </div>
+              <div class="name" :class="{ 'name2': faceCheckStu.student_id }">
+                请看摄像头进行人脸识别
               </div>
-              <img src="@/assets/images/test/profilePicture.png" />
-            </div>
-            <div class="name" :class="{ 'name2': faceCheckStu.student_id }">
-              请看摄像头进行人脸识别
             </div>
           </div>
+          <div @click="getCloseFace" class="close"></div>
         </div>
-        <div @click="getCloseFace">关闭</div>
       </div>
     </Transition>
   </div>
@@ -28,79 +31,108 @@
 </template>
 <script setup lang="ts">
 import { useWebSocket } from '@/utils/faceWs';
-const { faceWs, startDevice, checkFace, openFace, terminateFace, suspendFace, resumeFace, getFace } = useWebSocket();
 const { proxy } = getCurrentInstance() as any;
+const router = useRouter();
+const { faceWs, startDevice, checkFace, openFace, terminateFace, suspendFace, resumeFace, getFaceState } = useWebSocket();
 
 const data = reactive<any>({
-  faceCheckStu: {},
+  faceCheckStu: {},//人脸信息
   faceState: false,//人脸识别窗口状态
   direction: "",//动画方向
   parameter: {},//参数
-  deviceInfo: {},
+  deviceInfo: {},//设备信息
 });
 
 const { faceCheckStu, faceState, direction, parameter, deviceInfo } = toRefs(data);
 
 onBeforeMount(() => {
-  //加载手势WS
+})
+
+onMounted(() => {
+})
+
+/**
+ * 初始化
+ */
+const getInit = async () => {
   faceWs((e: any) => {
     if (e?.wksid) {
       //获取设备信息
       getDevice();
     }
-
-    //接收设备信息
+    //接收设备信息并发送请求
     if (e?.device_info) {
       deviceInfo.value = e.device_info;
+      getCheckFace();
+    }
+    if (e?.cmd == 'check_facecontroller_available') {
+      let handcontroller_id = deviceInfo.value.handcontroller_id;
+      if (e?.code != 0) {
+        proxy?.$modal.msgError(`人脸识别模块不可用`);
+      } else {
+        //查看人脸识别状态,如果不处于关闭就先关闭再重新启动(可能会APP退出然后工作站还在运行的可能性)
+        getFaceState(handcontroller_id);
+      }
+    }
+    if (e?.cmd == 'get_facecontroller_state') {
       let handcontroller_id = deviceInfo.value.handcontroller_id;
-      getCheckGrades();
-      openFace();
+      //state说明: 0:关闭,3:空闲,36:工作中
+      if ([3, 36].includes(e.state)) {
+        terminateFace(handcontroller_id);
+        proxy?.$modal.msgWarning(`请重新人脸识别`);
+      } else {
+        openFace(handcontroller_id);
+      }
+    }
+    if (e?.data) {
+      //返回人脸信息然后跳转
+      let id = e.data.student_id;
+      let name = e.data.student_name;
+      let pic = e.data.student_icon;
+      if (!id) {
+        proxy?.$modal.msgWarning(`缺少参数`);
+        return false;
+      }
+      let obj = { id, name, pic }
+      router.push({ path: '/score', query: 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' });
+  if (!deviceid) {
+    proxy?.$modal.msgError(`请重新登录绑定设备号后使用`);
+    return false;
   }
+  startDevice({ deviceid: deviceid });
 };
 
 /**
  * 查成绩
 */
-const getCheckGrades = () => {
-  const deviceid: any = localStorage.getItem('deviceid');
-  if (!deviceid) {
-    proxy?.$modal.msgWarning('没有设备号,请重新登录');
-    return false;
-  }
+const getCheckFace = () => {
   let handcontroller_id = deviceInfo.value.handcontroller_id;
-  checkFace(handcontroller_id)
+  //检查是否支持人脸识别
+  checkFace(handcontroller_id);
 };
 
-
 /**
  * 关闭人脸识别
 */
 const getCloseFace = () => {
   let handcontroller_id = deviceInfo.value.handcontroller_id;
-  closeFace(handcontroller_id)
+  terminateFace(handcontroller_id);
+  faceState.value = false;
 };
 
+//暴露给父组件用
+defineExpose({
+  getInit
+})
 </script>
 <style lang="scss" scoped>
 .mask {
@@ -109,7 +141,7 @@ const getCloseFace = () => {
   width: 100vw;
   top: 0;
   left: 0;
-  background: rgba(0, 0, 0, 0.3);
+  background: rgba(0, 0, 0, 0.8);
   z-index: 998;
 }
 
@@ -125,8 +157,8 @@ const getCloseFace = () => {
   z-index: 999;
 
   .confirmDiaWindow {
-    width: 23.5%;
-    height: 43.4%;
+    width: 30vh;
+    height: 43vh;
     border-radius: 1.6rem;
     opacity: 1;
     background: radial-gradient(122% 126% at 97% 6%, #35FFC6 0%, #00FFE8 100%);
@@ -134,12 +166,12 @@ const getCloseFace = () => {
     display: flex;
     align-items: center;
     justify-content: center;
-    position: fixed;
+    margin-bottom: 20px;
 
     .confirmDiaWindow-con {
       .pic {
-        width: 22.3vh;
-        height: 22.3vh;
+        width: 25vh;
+        height: 25vh;
         border-radius: 50%;
         display: flex;
         justify-content: center;
@@ -153,7 +185,7 @@ const getCloseFace = () => {
           left: -5vh;
           top: 0;
           width: 5vh;
-          height: 22.3vh;
+          height: 25vh;
           animation: shineani 3s infinite;
           -webkit-animation: shineani 3s infinite;
           z-index: 1;
@@ -177,7 +209,7 @@ const getCloseFace = () => {
       .name {
         width: 100%;
         color: #1A293A;
-        font-size: 1.9rem;
+        font-size: 2.5vh;
       }
 
       .name2 {
@@ -188,6 +220,10 @@ const getCloseFace = () => {
       }
     }
   }
+
+  .close {
+    margin: 0 auto;
+  }
 }
 
 @keyframes shineani {

+ 23 - 22
src/utils/faceWs.ts

@@ -4,25 +4,13 @@ import { ref, onMounted, onUnmounted, onBeforeUnmount } from 'vue';
 export function useWebSocket() {
   const address: any = import.meta.env.VITE_APP_BASE_API;
   const token: any = localStorage.getItem('token');
-  const deviceid: any = localStorage.getItem('deviceid');
   const myToken: any = 'JWT ' + token;
-
   let socketFace: any = null; //ws实例对象
-  socketFace = io(address + '/', {
-    transports: ['websocket', 'polling'],
-    query: {
-      type: 'face',
-      Authorization: token ? myToken : ''
-    }
-  });
 
   function faceWs(callback: any) {
     if (socketFace == null) {
-      return false;
+      socketFace = io(address + '/', {transports: ['websocket', 'polling'],query: {type: 'face',Authorization: token ? myToken : ''}});
     }
-    callback({
-      wksid: socketFace.id
-    });
     socketFace.on('my_response', (e: any) => {
       callback(e);
     });
@@ -30,6 +18,12 @@ export function useWebSocket() {
       callback(e);
     });
     socketFace.on('facecontroller_ack', (e: any) => {
+      if (e?.cmd == 'check_facecontroller_available' && e?.code != 0) {
+        closeWS();
+      }
+      if (e?.cmd == 'get_facecontroller_state' && [3, 36].includes(e.state)) {
+        closeWS();
+      }
       callback(e);
     });
     socketFace.on('disconnect', (e: any) => {
@@ -68,7 +62,7 @@ export function useWebSocket() {
    */
   function checkFace(data?: any, callback?: any) {
     sendMessage(
-      'facecontroller_ack',
+      'facecontroller',
       {
         cmd: 'check_facecontroller_available',
         ctrl_name: `facecontroller_${data}`
@@ -82,7 +76,7 @@ export function useWebSocket() {
    */
   function openFace(data?: any, callback?: any) {
     sendMessage(
-      'facecontroller_ack',
+      'facecontroller',
       {
         cmd: 'open_facecontroller',
         ctrl_name: `facecontroller_${data}`
@@ -96,7 +90,7 @@ export function useWebSocket() {
    */
   function terminateFace(data?: any, callback?: any) {
     sendMessage(
-      'facecontroller_ack',
+      'facecontroller',
       {
         cmd: 'terminate_facecontroller',
         ctrl_name: `facecontroller_${data}`
@@ -110,7 +104,7 @@ export function useWebSocket() {
    */
   function suspendFace(data?: any, callback?: any) {
     sendMessage(
-      'facecontroller_ack',
+      'facecontroller',
       {
         cmd: 'suspend_facecontroller',
         ctrl_name: `facecontroller_${data}`
@@ -124,7 +118,7 @@ export function useWebSocket() {
    */
   function resumeFace(data?: any, callback?: any) {
     sendMessage(
-      'facecontroller_ack',
+      'facecontroller',
       {
         cmd: 'resume_facecontroller',
         ctrl_name: `facecontroller_${data}`
@@ -136,9 +130,9 @@ export function useWebSocket() {
   /**
    * 获取人脸识别模块状态
    */
-  function getFace(data?: any, callback?: any) {
+  function getFaceState(data?: any, callback?: any) {
     sendMessage(
-      'facecontroller_ack',
+      'facecontroller',
       {
         cmd: 'get_facecontroller_state',
         ctrl_name: `facecontroller_${data}`
@@ -147,12 +141,19 @@ export function useWebSocket() {
     );
   }
 
-  onBeforeUnmount(() => {
+  /**
+   * 关闭WS
+   */
+  function closeWS() {
     if (socketFace) {
       socketFace.close();
       socketFace = null;
     }
+  }
+
+  onBeforeUnmount(() => {
+    closeWS();
   });
 
-  return { faceWs,startDevice, sendMessage, checkFace, openFace, terminateFace, suspendFace, resumeFace, getFace };
+  return { faceWs,startDevice, sendMessage, checkFace, openFace, terminateFace, suspendFace, resumeFace, getFaceState };
 }

+ 59 - 14
src/views/home/index.vue

@@ -14,12 +14,22 @@
           <div class="li" @click="getJump('/ranking', '排行榜')"><img src="@/assets/images/home/ranking.png" /></div>
         </div>
         <div class="right-bottom">
-          <div class="li" @click="getJump('/game', '游戏')"><img src="@/assets/images/home/game.png" /></div>
-          <div class="li" @click="getJump('/course', '课程')"><img src="@/assets/images/home/course.png" /></div>
-          <div class="li" @click="getJump('/set', '设置')"><img src="@/assets/images/home/set.png" /></div>
+          <div class="right-bottom-left">
+            <div class="li" @click="getJump('/game', '游戏')"><img src="@/assets/images/home/game.png" /></div>
+          </div>
+          <div class="right-bottom-right">
+            <div class="right-bottom-right-left">
+              <div class="li" @click="getJump('/query', '查询')"><img src="@/assets/images/home/query.png" /></div>
+            </div>
+            <div class="right-bottom-right-right">
+              <div class="li" @click="getJump('/course', '课程')"><img src="@/assets/images/home/course2.png" /></div>
+              <div class="li" @click="getJump('/set', '设置')"><img src="@/assets/images/home/set2.png" /></div>
+            </div>
+          </div>
         </div>
       </div>
     </div>
+    <OnlineFaceWindow ref="onlineFaceRef"></OnlineFaceWindow>
   </div>
 </template>
 
@@ -27,8 +37,11 @@
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech';
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
+const onlineFaceRef = ref();
 
-//跳转
+/**
+* 跳转
+*/
 const getJump = (url: string, name: string) => {
   if (url == undefined || !url) {
     proxy?.$modal.msgWarning(`正在开发,敬请期待!`);
@@ -107,11 +120,21 @@ const getJump = (url: string, name: string) => {
     // } else {
     //   proxy?.$modal.msgWarning('暂不开放使用,敬请期待!');
     // }
-  }
-  else {
+  } else if (url == '/query') {
+    getCheckGrades()
+
+  } else {
     router.push({ path: url });
   }
 };
+
+/**
+* 查成绩
+*/
+const getCheckGrades = () => {
+  onlineFaceRef.value.getInit();
+};
+
 onBeforeMount(() => {
   localStorage.setItem('loginType', "1");
 });
@@ -155,7 +178,7 @@ $waiPadding: 6.51rem;
   }
 
   .left {
-    width: 32.6%;
+    width: 32.65%;
 
     .li {
       width: 100%;
@@ -163,7 +186,7 @@ $waiPadding: 6.51rem;
   }
 
   .right {
-    width: calc(100% - 32.6%);
+    width: calc(100% - 32.65%);
     $myPadding: 1.22rem;
 
     .right-top {
@@ -202,17 +225,39 @@ $waiPadding: 6.51rem;
       justify-content: space-between;
       padding-left: $myPadding;
 
-      .li:nth-child(1) {
+      .right-bottom-left {
         width: calc(50% - $myPadding / 2);
       }
 
-      .li:nth-child(2) {
-        width: calc((50% - $myPadding / 2) / 2 - $myPadding / 2 + 0.05rem);
-      }
+      .right-bottom-right {
+        width: calc(50% - $myPadding / 2);
+        display: flex;
+        justify-content: space-between;
+
+        .right-bottom-right-left {
+          width: calc(50% - $myPadding / 2);
+        }
 
-      .li:nth-child(3) {
-        width: calc((50% - $myPadding / 2) / 2 - $myPadding / 2 - 0.05rem);
+        .right-bottom-right-right {
+          width: calc(50% - $myPadding / 2);
+
+          .li:nth-child(1) {
+            margin-bottom: $myPadding;
+          }
+        }
       }
+
+      // .li:nth-child(1) {
+      //   width: calc(50% - $myPadding / 2);
+      // }
+
+      // .li:nth-child(2) {
+      //   width: calc((50% - $myPadding / 2) / 2 - $myPadding / 2 + 0.05rem);
+      // }
+
+      // .li:nth-child(3) {
+      //   width: calc((50% - $myPadding / 2) / 2 - $myPadding / 2 - 0.05rem);
+      // }
     }
   }
 }

+ 2 - 2
src/views/ranking/index.vue

@@ -91,7 +91,7 @@
                   <div class="studentName">{{ item.student_name }}</div>
                   <div class="scoreBox" v-if="timeProjectList.includes(projectObj.exam_name)">
                     <div class="score">{{
-                      proxy?.$utils.runTime(item.result, true, false) }}</div>
+                      proxy?.$utils.runTime(item.result, false, false) }}</div>
                   </div>
                   <div class="scoreBox" v-else>
                     <div class="score">{{ item.result }}</div>
@@ -118,7 +118,7 @@
                         <i>{{ items.rank }}</i>
                         <div class="studentName">{{ items.student_name }}</div>
                         <div class="right" v-if="timeProjectList.includes(projectObj.exam_name)">
-                          <div class="score">{{ proxy?.$utils.runTime(items.result, true, false) }}
+                          <div class="score">{{ proxy?.$utils.runTime(items.result, false, false) }}
                           </div>
                         </div>
                         <div class="right" v-else>

+ 4 - 6
src/views/score/index.vue

@@ -47,6 +47,7 @@ const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 const route = useRoute();
 const dic: any = dataDictionary;
+const timeProjectList = ['basketballv1','run50','run60','run70','run100','run200','run400','run800','run1000','runa800','runa1000','runwb800','runwb1000'];
 const data = reactive<any>({
   parameter: {
     id: 0,
@@ -60,10 +61,7 @@ const data = reactive<any>({
     size: 30,
     pages: 1,
   },
-  projectList: [{
-    label: "项目",
-    value: null,
-  },],
+  projectList: [],
   project: '',
   date: "",
   debounceTime: '', //防抖状态
@@ -126,7 +124,7 @@ const getReportList = () => {
         } else {
           result = item.result;
         }
-        if (['run50', 'run70', 'run100', 'run200', 'run400', 'run800', 'run1000', 'run15x4', 'run50x8', 'run10x4', 'runwb800', 'runwb1000'].includes(item.exam_name)) {
+        if (timeProjectList.includes(item.exam_name)) {
           item.result = proxy?.$utils.runTime(item.result, false, false);
         } else {
           item.result = result + dic.unit[item.exam_name];
@@ -169,7 +167,7 @@ const getNext = (event?: any) => {
   let scrollTop = obj.scrollTop;
   let clientHeight = obj.clientHeight;
   //提前100高度加载数据
-  if (scrollTop + clientHeight + 150 >= scrollHeight) {
+  if (scrollTop + clientHeight + 200 >= scrollHeight) {
     console.log('到底了!');
     //继续加载下一页
     if (debounceTime.value) {

+ 1 - 16
src/views/set/index.vue

@@ -47,14 +47,6 @@
           </div>
         </div>
       </div>
-      <div class="li" @click="getCheckGrades">
-        <div class="liBox">
-          <div class="pic"></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>
@@ -72,7 +64,6 @@
         </div>
       </div> -->
     </div>
-    <OnlineFaceWindow></OnlineFaceWindow>
   </div>
 </template>
 
@@ -80,6 +71,7 @@
 import Speech from 'speak-tts';
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
+
 const data = reactive<any>({
   vConsoleState: true,
   rankingSwitch1: true,
@@ -229,13 +221,6 @@ const getText = (type: any) => {
   }
 };
 
-/**
- * 查成绩
-*/
-const getCheckGrades = () => {
-
-};
-
 /**
  * 返回
 */