linxuxiang 6 months ago
parent
commit
eb970b1177

+ 4 - 2
src/App.vue

@@ -5,13 +5,15 @@
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { handWs } from '@/utils/handWs'
+import { useWebSocket } from '@/utils/handWs';  
+const { handWs } = useWebSocket();
+
 const router = useRouter();
 const router = useRouter();
 
 
 /**
 /**
  * 手势
  * 手势
 */
 */
-const getHandWs = () => {
+const getHandWs = async () => {
   //加载手势WS
   //加载手势WS
   handWs((e: any) => {
   handWs((e: any) => {
     // console.log("eeee", e)
     // console.log("eeee", e)

+ 20 - 3
src/store/modules/app.ts

@@ -1,9 +1,10 @@
 export const useAppStore = defineStore('app', () => {
 export const useAppStore = defineStore('app', () => {
   const data = reactive<any>({
   const data = reactive<any>({
     musicList: [],
     musicList: [],
-    classList: []
+    classList: [],
+    socketHand: null
   });
   });
-  const { musicList, classList } = toRefs(data);
+  const { musicList, classList, socketHand } = toRefs(data);
 
 
   /**
   /**
    * 获取音乐
    * 获取音乐
@@ -33,11 +34,27 @@ export const useAppStore = defineStore('app', () => {
     classList.value = data;
     classList.value = data;
   };
   };
 
 
+  /**
+   * 获取手势WS
+   */
+  const getSocketHand = () => {
+    return socketHand.value;
+  };
+
+  /**
+   * 设置手势WS
+   */
+  const setSocketHand = (data: any) => {
+    socketHand.value = data;
+  };
+
   return {
   return {
     getMusic,
     getMusic,
     setMusic,
     setMusic,
     getClass,
     getClass,
-    setClass
+    setClass,
+    getSocketHand,
+    setSocketHand,
   };
   };
 });
 });
 
 

+ 141 - 94
src/utils/handWs.ts

@@ -1,102 +1,149 @@
 import io from 'socket.io-client';
 import io from 'socket.io-client';
-const address: any = import.meta.env.VITE_APP_BASE_API;
-const token: any = localStorage.getItem('token');
-const deviceid: any = localStorage.getItem('deviceid');
-let socketHand: any = {}; //ws实例对象
-let testConnect: any = {}; //接入成功
-socketHand = io(address + '/', {
-  transports: ['websocket', 'polling'],
-  query: {
-    Authorization: 'JWT ' + token,
-  }
-});
+import { ref, onMounted, onUnmounted } from 'vue';
+import useAppStore from '@/store/modules/app';
 
 
-export const handWs = (callback: any) => {
-  callback(testConnect);
-  socketHand.on('connect', (e: any) => {
-    callback(e);
-  });
-  socketHand.on('my_response', (e: any) => {
-    testConnect = e;
-    callback(e);
-  });
-  socketHand.on('device_login_result', (e: any) => {
-    callback(e);
-  });
-  socketHand.on('fe_device_init_result', (e: any) => {
-    callback(e);
-  });
-  socketHand.on('handcontroller_ack', (e: any) => {
-    callback(e);
-  });
-  socketHand.on('handcontroller_result', (e: any) => {
-    callback(e);
-  });
-  socketHand.on('disconnect', (e: any) => {
-    callback(e);
-  });
-};
+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;
 
 
-/**
- * 发送消息
- */
-export const sendMessage = (type: string, data: any, callback?: () => void) => {
-  if (socketHand.connected) {
-    callback = callback || function () {};
-    socketHand.emit(type, data, callback);
+  let socketHand: any = useAppStore().getSocketHand() || null; //ws实例对象
+  if (socketHand == null) {
+    socketHand = io(address + '/', {
+      transports: ['websocket', 'polling'],
+      query: {
+        Authorization: token ? myToken : '',
+      }
+    });
+    useAppStore().setSocketHand(socketHand);
   }
   }
-};
 
 
-/**
- * 开始连接登录
- */
-export const startLogin = (data?: any, callback?: any) => {
-  sendMessage(
-    'fe_get_qrlogin',
-    {
-      deviceid: deviceid ? deviceid : ''
-    },
-    () => {}
-  );
-};
+  // let socketHand: any = null; //ws实例对象
+  //   socketHand = io(address + '/', {
+  //     transports: ['websocket', 'polling'],
+  //     query: {
+  //       Authorization: token ? myToken : '',
+  //     }
+  //   });
 
 
-/**
- * 开始连接设备信息
- */
-export const startDevice = (data?: any, callback?: any) => {
-  sendMessage(
-    'fe_device_init',
-    {
-      data: data
-    },
-    () => {}
-  );
-};
+  function handWs(callback: any) {
+    if(socketHand==null){
+      return false;
+    }
+    callback({
+      wksid:socketHand.id
+    });
+    socketHand.on('connect', (e: any) => {
+      callback(e);
+    });
+    socketHand.on('my_response', (e: any) => {
+      callback(e);
+    });
+    socketHand.on('device_login_result', (e: any) => {
+      callback(e);
+    });
+    socketHand.on('fe_device_init_result', (e: any) => {
+      callback(e);
+    });
+    socketHand.on('handcontroller_ack', (e: any) => {
+      callback(e);
+    });
+    socketHand.on('handcontroller_result', (e: any) => {
+      callback(e);
+    });
+    socketHand.on('disconnect', (e: any) => {
+      callback(e);
+    });
+  };
 
 
-/**
- * 开始连接手势
- */
-export const startHand = (data?: any, callback?: any) => {
-  sendMessage(
-    'handcontroller',
-    {
-      hctrl_name: `handcontroller_${data}`,
-      cmd: 'open_handcontroller'
-    },
-    () => {}
-  );
-};
+  /**
+   * 发送消息
+   */
+  function sendMessage(type: string, data: any, callback?: () => void) {
+    if(socketHand==null){
+      return false;
+    }
+    if (socketHand.connected) {
+      callback = callback || function () { };
+      socketHand.emit(type, data, callback);
+    }
+  };
+
+  /**
+   * 开始连接登录
+   */
+  function startLogin(data?: any, callback?: any) {
+    sendMessage(
+      'fe_get_qrlogin',
+      {
+        deviceid: deviceid ? deviceid : ''
+      },
+      () => { }
+    );
+  };
+
+  /**
+   * 开始连接设备信息
+   */
+  function startDevice(data?: any, callback?: any) {
+    sendMessage(
+      'fe_device_init',
+      {
+        data: data
+      },
+      () => { }
+    );
+  };
+
+  /**
+   * 开始连接手势
+   */
+  function startHand(data?: any, callback?: any) {
+    sendMessage(
+      'handcontroller',
+      {
+        hctrl_name: `handcontroller_${data}`,
+        cmd: 'open_handcontroller'
+      },
+      () => { }
+    );
+  };
+
+  /**
+   * 获取手势状态
+   */
+  function stateHand(data?: any, callback?: any) {
+    sendMessage(
+      'handcontroller',
+      {
+        hctrl_name: `handcontroller_${data}`,
+        cmd: 'get_handcontroller_state'
+      },
+      () => { }
+    );
+  };
+
+  /**
+   * 关闭连接手势
+   */
+  function closeHand(data?: any, callback?: any) {
+    sendMessage(
+      'handcontroller',
+      {
+        hctrl_name: `handcontroller_${data}`,
+        cmd: 'terminate_handcontroller'
+      },
+      () => { }
+    );
+  };
+
+  onUnmounted(() => {
+    if (socketHand) {
+      // socketHand.close();
+      socketHand = null;
+    }
+  });
 
 
-/**
- * 关闭连接手势
- */
-export const closeHand = (data?: any, callback?: any) => {
-  sendMessage(
-    'handcontroller',
-    {
-      hctrl_name: `handcontroller_${data}`,
-      cmd: 'terminate_handcontroller'
-    },
-    () => {}
-  );
-};
+  return { handWs, sendMessage, startLogin, startDevice, startHand, stateHand, closeHand };
+}

+ 530 - 515
src/utils/ws.ts

@@ -1,21 +1,23 @@
 import io from 'socket.io-client';
 import io from 'socket.io-client';
-const address: any = import.meta.env.VITE_APP_BASE_API;
-const token: any = localStorage.getItem('token');
-const myInfo: any = localStorage.getItem('userInfo');
-let socket: any = {}; //ws实例对象
-let timerManager: any = {}; //计时器管理
-let parameter: any = {}; //参数
-let testTime: number = 0; //默认时长
-let userInfo: any = JSON.parse(myInfo); //用户信息
-let beatTime: number = 10000; //心跳频率
-let loading: any = null; //遮罩层
-let version: string = ''; //ws接口版本v2表示单ws多项目
-let examStateList: any = []; //当前状态码
-let testList: any = []; //区列表
-let wkList: any = []; //工作站列表
-let loadingTime: any = null; //记录等待时间
+import { ref, onMounted, onUnmounted } from 'vue';
+
+export function useWs() {
+  const address: any = import.meta.env.VITE_APP_BASE_API;
+  const token: any = localStorage.getItem('token');
+  const myInfo: any = localStorage.getItem('userInfo');
+  let socket: any = null; //ws实例对象
+  let timerManager: any = {}; //计时器管理
+  let parameter: any = {}; //参数
+  let testTime: number = 0; //默认时长
+  let userInfo: any = JSON.parse(myInfo); //用户信息
+  let beatTime: number = 10000; //心跳频率
+  let loading: any = null; //遮罩层
+  let version: string = ''; //ws接口版本v2表示单ws多项目
+  let examStateList: any = []; //当前状态码
+  let testList: any = []; //区列表
+  let wkList: any = []; //工作站列表
+  let loadingTime: any = null; //记录等待时间
 
 
-export const initWs = (data: any, callback: any) => {
   socket = io(address + '/midexam', {
   socket = io(address + '/midexam', {
     transports: ['websocket', 'polling'],
     transports: ['websocket', 'polling'],
     query: {
     query: {
@@ -23,40 +25,56 @@ export const initWs = (data: any, callback: any) => {
       sysuuid: 'JWT ' + token,
       sysuuid: 'JWT ' + token,
     }
     }
   });
   });
-  examStateList = []; //当前状态码
-  testList = []; //区列表
-  wkList = []; //工作站列表
-  loading = ElLoading.service({ text: '正在初始化,请稍候', background: 'rgba(0, 0, 0, 0.8)', customClass: `sports ${data.parameter.project}` });
-  parameter = data.parameter;
-  testTime = data.testTime;
-  version = data.version || '';
-  testList = data.parameter.area.split(',');
-  examStateList = testList.map((item: any) => {
-    let examId = `${parameter.project}_${item}`;
-    let obj = {
-      examState: 0,
-      examId: examId,
-      beatNumber: 0
-    };
-    return obj;
-  });
-  loadingTime = setTimeout(() => {
-    //30秒还在0状态就算超时
-    let list = examStateList.filter((item: any) => {
-      return item.examState == 0;
+
+  function initWs(data: any, callback: any) {
+    examStateList = []; //当前状态码
+    testList = []; //区列表
+    wkList = []; //工作站列表
+    loading = ElLoading.service({ text: '正在初始化,请稍候', background: 'rgba(0, 0, 0, 0.8)', customClass: `sports ${data.parameter.project}` });
+    parameter = data.parameter;
+    testTime = data.testTime;
+    version = data.version || '';
+    testList = data.parameter.area.split(',');
+    examStateList = testList.map((item: any) => {
+      let examId = `${parameter.project}_${item}`;
+      let obj = {
+        examState: 0,
+        examId: examId,
+        beatNumber: 0
+      };
+      return obj;
     });
     });
-    //考虑到多开只有一个在线也有效的
-    if (list.length == testList.length) {
-      clearTimeout(loadingTime);
-      callback({ cmd: 'disconnect_request', data: { message: 'WS连接超时' } });
-    }
-  }, 20000);
-  socket.on('connect', (e: any) => {
-    callback({ cmd: 'mySid', data: { sid: socket.id.replace('/midexam#', '') } });
-    if (testList.length > 1) {
-      //单WS多区
-      testList.forEach((item: any) => {
-        let examId = `${parameter.project}_${item}`;
+    loadingTime = setTimeout(() => {
+      //30秒还在0状态就算超时
+      let list = examStateList.filter((item: any) => {
+        return item.examState == 0;
+      });
+      //考虑到多开只有一个在线也有效的
+      if (list.length == testList.length) {
+        clearTimeout(loadingTime);
+        callback({ cmd: 'disconnect_request', data: { message: 'WS连接超时' } });
+      }
+    }, 20000);
+    socket.on('connect', (e: any) => {
+      callback({ cmd: 'mySid', data: { sid: socket.id.replace('/midexam#', '') } });
+      if (testList.length > 1) {
+        //单WS多区
+        testList.forEach((item: any) => {
+          let examId = `${parameter.project}_${item}`;
+          if (parameter.taskId) {
+            getTaskStarts(examId);
+          } else {
+            getExamStarts(examId);
+          }
+          getNetWork(examId, (e: any) => {
+            if (!e.status) {
+              callback({ cmd: 'disconnect_request', exam_id: examId, data: { message: '工作站未响应' } });
+            }
+          });
+        });
+      } else {
+        //单WS单区
+        let examId = parameter.examId;
         if (parameter.taskId) {
         if (parameter.taskId) {
           getTaskStarts(examId);
           getTaskStarts(examId);
         } else {
         } else {
@@ -67,520 +85,517 @@ export const initWs = (data: any, callback: any) => {
             callback({ cmd: 'disconnect_request', exam_id: examId, data: { message: '工作站未响应' } });
             callback({ cmd: 'disconnect_request', exam_id: examId, data: { message: '工作站未响应' } });
           }
           }
         });
         });
-      });
-    } else {
-      //单WS单区
-      let examId = parameter.examId;
-      if (parameter.taskId) {
-        getTaskStarts(examId);
-      } else {
-        getExamStarts(examId);
       }
       }
-      getNetWork(examId, (e: any) => {
-        if (!e.status) {
-          callback({ cmd: 'disconnect_request', exam_id: examId, data: { message: '工作站未响应' } });
-        }
-      });
-    }
-  });
+    });
 
 
-  socket.on('msg2frontend', (e: any) => {
-    callback(e);
-    //实时状态
-    if (e.cmd === 'exam_status') {
-      let index = examStateList.findIndex((item: any) => {
-        return item.examId == e.exam_id;
-      });
-      if (index != -1) {
-        examStateList[index].examState = e.data;
-        examStateList[index].beatNumber = examStateList[index].beatNumber + 1;
-      }
-    }
-    //工作站状态
-    if (e.cmd === 'init_result') {
-      if (e.status == 666) {
-        let data = {
-          wk_id: e.data.wk_id,
-          examId: e.exam_id
-        };
-        wkList.push(data);
+    socket.on('msg2frontend', (e: any) => {
+      callback(e);
+      //实时状态
+      if (e.cmd === 'exam_status') {
+        let index = examStateList.findIndex((item: any) => {
+          return item.examId == e.exam_id;
+        });
+        if (index != -1) {
+          examStateList[index].examState = e.data;
+          examStateList[index].beatNumber = examStateList[index].beatNumber + 1;
+        }
       }
       }
-    }
-    //测试违规
-    if (e.cmd === 'warning_result') {
-    }
-    //后端播报语音
-    if (e.cmd === 'return_audio_msg') {
-    }
-    //错误提示
-    if (e.cmd === 'info_result') {
-    }
-    //错误提示
-    if (e.cmd === 'error_result') {
-    }
-    //测试中违规提示
-    if (e.cmd === 'warning_notify') {
-    }
-    //断线状态
-    if (e.cmd === 'disconnect_request') {
-      if (loadingTime) {
-        clearTimeout(loadingTime);
+      //工作站状态
+      if (e.cmd === 'init_result') {
+        if (e.status == 666) {
+          let data = {
+            wk_id: e.data.wk_id,
+            examId: e.exam_id
+          };
+          wkList.push(data);
+        }
       }
       }
-      if (testList.length == 1) {
-        getExit();
-        //let examId = e?.exam_id || '';
-        //getExit(examId);
+      //测试违规
+      if (e.cmd === 'warning_result') {
       }
       }
-    }
-    //状态变更
-    if (e.cmd === 'set_exam_state') {
-      let index = examStateList.findIndex((item: any) => {
-        return item.examId == e.exam_id;
-      });
-      if (index != -1) {
-        examStateList[index].examState = e.data;
+      //后端播报语音
+      if (e.cmd === 'return_audio_msg') {
       }
       }
-      if (e.data == 3) {
-        //关闭遮罩层
-        loading?.close();
-        clearTimeout(loadingTime);
+      //错误提示
+      if (e.cmd === 'info_result') {
       }
       }
-    }
-    //新建测试后返回信息,获取result_id
-    if (e.cmd === 'open_one_test_ack') {
-    }
-    //人脸识别状态
-    if (e.cmd === 'face_check_result') {
-    }
-    //测试结束结果
-    if (e.cmd === 'oneresult') {
-    }
-    //结果生成完成(视频图片)
-    if (e.cmd === 'static_urls_finished') {
-    }
-    //选择学生或测试结束后返回的数据
-    if (e.cmd === 'result_info') {
-    }
-  });
-
-  socket.on('disconnect', (e: any) => {
-    callback(e);
-    getExit();
-  });
-};
-
-/**
- * 发送命令
- * @param type发送类型:v2版是单WS多人的项目
- * msgfrom_frontend:测试中命令交互,
- * get_exam_status:心跳,
- * exam_ends:结束测试,
- * fe_reconnect:重连,
- * task_starts:课程开启测试,
- * exam_starts:开启测试,
- * join_exam_room:加入房间,
- * @param data发送数据:
- * msgfrom_frontend发送cmd的参:
- * open_one_test:创建测试将由3转40,
- * start_face_recognition:开始人脸识别将由40转41,
- * stop_face_recognition:停止人脸识别将由41转43,
- * face_confirm_only:人脸确认即将测试,
- * start_one_test:开始测试将由43转42,
- * finish_one_test:正在测试中结束并下一次将由42转6转3,
- * close_one_test:中断任何阶段将由42、43、41、40转3,
- * suspend_face_recognition_channels:工作站识别的短跑,某道识别到了人就停止某道的识别,
- * resume_face_recognition_channels:工作站识别的短跑,重新开启某一道的识别,
- * next_test:,
- * result_info:,
- * @param callback回调函数
- */
-export const sendMessage = (type: string, data: any, callback?: () => void) => {
-  if (socket.connected) {
-    callback = callback || function () {};
-    //版本2就拼接进去
-    if (version == 'v2') {
-      type = type + '_' + version;
-    }
-    socket.emit(type, JSON.stringify(data), callback);
-  }
-};
-
-/**
- * 课程连接成功
- */
-const getTaskStarts = (data?: any) => {
-  let examId = data ? data : parameter.examId;
-  sendMessage(
-    'task_starts',
-    {
-      data: 'start_' + examId,
-      class_id: parameter.classes,
-      exam_type: parameter.standard,
-      task_cate: parameter.taskCate,
-      gesture: parameter.gesture,
-      demo: parameter.demo,
-      test_time: testTime
-    },
-    () => {}
-  );
-};
-
-/**
- * 连接成功
- */
-const getExamStarts = (data?: any) => {
-  let examId = data ? data : parameter.examId;
-  sendMessage(
-    'exam_starts',
-    {
-      data: 'start_' + examId,
-      class_id: parameter.classes,
-      exam_type: parameter.standard,
-      gesture: parameter.gesture,
-      demo: parameter.demo,
-      test_time: testTime
-    },
-    () => {}
-  );
-};
-
-/**
- * 创建测试
- */
-export const openOneTest = (data?: any) => {
-  return new Promise((resolve, reject) => {
-    let examId = data ? data : parameter.examId;
-    let index = examStateList.findIndex((item: any) => {
-      return item.examId == examId;
-    });
-    sendMessage('msgfrom_frontend', {
-      data: {
-        cmd: 'open_one_test',
-        exam_id: examId
+      //错误提示
+      if (e.cmd === 'error_result') {
       }
       }
-    });
-    let timer1 = setInterval(() => {
-      if (examStateList[index].examState == 40) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        resolve({ data: examStateList[index].examState });
+      //测试中违规提示
+      if (e.cmd === 'warning_notify') {
       }
       }
-    }, 250);
-    let timer2 = setTimeout(() => {
-      if (examStateList[index].examState == 3) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:open_one_test' } });
+      //断线状态
+      if (e.cmd === 'disconnect_request') {
+        if (loadingTime) {
+          clearTimeout(loadingTime);
+        }
+        if (testList.length == 1) {
+          getExit();
+          //let examId = e?.exam_id || '';
+          //getExit(examId);
+        }
       }
       }
-    }, 30000);
-  });
-};
-
-/**
- * 开始人脸识别
- */
-export const startFace = (data?: any) => {
-  return new Promise((resolve, reject) => {
-    let examId = data ? data : parameter.examId;
-    let index = examStateList.findIndex((item: any) => {
-      return item.examId == examId;
-    });
-    sendMessage('msgfrom_frontend', {
-      data: {
-        cmd: 'start_face_recognition',
-        exam_id: examId
+      //状态变更
+      if (e.cmd === 'set_exam_state') {
+        let index = examStateList.findIndex((item: any) => {
+          return item.examId == e.exam_id;
+        });
+        if (index != -1) {
+          examStateList[index].examState = e.data;
+        }
+        if (e.data == 3) {
+          //关闭遮罩层
+          loading?.close();
+          clearTimeout(loadingTime);
+        }
       }
       }
-    });
-    let timer1 = setInterval(() => {
-      if (examStateList[index].examState == 41) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        resolve({ data: examStateList[index].examState });
+      //新建测试后返回信息,获取result_id
+      if (e.cmd === 'open_one_test_ack') {
       }
       }
-    }, 250);
-    let timer2 = setTimeout(() => {
-      if (examStateList[index].examState == 40) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:start_face_recognition' } });
+      //人脸识别状态
+      if (e.cmd === 'face_check_result') {
       }
       }
-    }, 30000);
-  });
-};
-
-/**
- * 停止人脸识别
- */
-export const stopFace = (data?: any) => {
-  return new Promise((resolve, reject) => {
-    let examId = data ? data : parameter.examId;
-    let index = examStateList.findIndex((item: any) => {
-      return item.examId == examId;
-    });
-    sendMessage('msgfrom_frontend', {
-      data: {
-        cmd: 'stop_face_recognition',
-        exam_id: examId
+      //测试结束结果
+      if (e.cmd === 'oneresult') {
       }
       }
-    });
-    let timer1 = setInterval(() => {
-      if (examStateList[index].examState == 43) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        resolve({ data: examStateList[index].examState });
+      //结果生成完成(视频图片)
+      if (e.cmd === 'static_urls_finished') {
       }
       }
-    }, 250);
-    let timer2 = setTimeout(() => {
-      if (examStateList[index].examState == 41) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:stop_face_recognition' } });
+      //选择学生或测试结束后返回的数据
+      if (e.cmd === 'result_info') {
       }
       }
-    }, 30000);
-  });
-};
+    });
 
 
-/**
- * 确认并提交人脸
- */
-export const faceConfirmOnly = (data: any, callback?: any) => {
-  let examId = data.exam_id ? data.exam_id : parameter.examId;
-  let myData = null;
-  if (Array.isArray(data)) {
-    //数组类型
-    myData = {
-      cmd: 'face_confirm_only',
-      data
-    };
-  } else {
-    //对象类型
-    myData = {
-      cmd: 'face_confirm_only',
-      exam_id: examId,
-      result_id: data.result_id,
-      student_id: data.student_id,
-      gender: data.gender
-    };
-  }
-  sendMessage(
-    'msgfrom_frontend',
-    {
-      data: myData
-    },
-    () => {
-      callback();
-    }
-  );
-};
+    socket.on('disconnect', (e: any) => {
+      callback(e);
+      getExit();
+    });
+  };
 
 
-/**
- * 开始测试
- */
-export const startOneTest = (data?: any, callback?: any) => {
-  let examId = data ? data : parameter.examId;
-  sendMessage(
-    'msgfrom_frontend',
-    {
-      data: {
-        cmd: 'start_one_test',
-        exam_id: examId
+  /**
+   * 发送命令
+   * @param type发送类型:v2版是单WS多人的项目
+   * msgfrom_frontend:测试中命令交互,
+   * get_exam_status:心跳,
+   * exam_ends:结束测试,
+   * fe_reconnect:重连,
+   * task_starts:课程开启测试,
+   * exam_starts:开启测试,
+   * join_exam_room:加入房间,
+   * @param data发送数据:
+   * msgfrom_frontend发送cmd的参:
+   * open_one_test:创建测试将由3转40,
+   * start_face_recognition:开始人脸识别将由40转41,
+   * stop_face_recognition:停止人脸识别将由41转43,
+   * face_confirm_only:人脸确认即将测试,
+   * start_one_test:开始测试将由43转42,
+   * finish_one_test:正在测试中结束并下一次将由42转6转3,
+   * close_one_test:中断任何阶段将由42、43、41、40转3,
+   * suspend_face_recognition_channels:工作站识别的短跑,某道识别到了人就停止某道的识别,
+   * resume_face_recognition_channels:工作站识别的短跑,重新开启某一道的识别,
+   * next_test:,
+   * result_info:,
+   * @param callback回调函数
+   */
+  function sendMessage(type: string, data: any, callback?: () => void) {
+    if (socket.connected) {
+      callback = callback || function () { };
+      //版本2就拼接进去
+      if (version == 'v2') {
+        type = type + '_' + version;
       }
       }
-    },
-    () => {
-      callback();
+      socket.emit(type, JSON.stringify(data), callback);
     }
     }
-  );
-};
+  };
 
 
-/**
- * 停止测试
- */
-export const finishOneTest = (data?: any) => {
-  return new Promise((resolve, reject) => {
+  /**
+   * 课程连接成功
+   */
+  function getTaskStarts(data?: any) {
     let examId = data ? data : parameter.examId;
     let examId = data ? data : parameter.examId;
-    let index = examStateList.findIndex((item: any) => {
-      return item.examId == examId;
-    });
-    sendMessage('msgfrom_frontend', {
-      data: {
-        cmd: 'finish_one_test',
-        exam_id: examId
-      }
-    });
-    let timer1 = setInterval(() => {
-      if (examStateList[index].examState == 3) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        resolve({ data: examStateList[index].examState });
-      }
-    }, 250);
-    let timer2 = setTimeout(() => {
-      if (examStateList[index].examState == 42) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:finish_one_test' } });
-      }
-    }, 60000);
-  });
-};
+    sendMessage(
+      'task_starts',
+      {
+        data: 'start_' + examId,
+        class_id: parameter.classes,
+        exam_type: parameter.standard,
+        task_cate: parameter.taskCate,
+        gesture: parameter.gesture,
+        demo: parameter.demo,
+        test_time: testTime
+      },
+      () => { }
+    );
+  };
 
 
-/**
- * 关闭测试测试
- */
-export const closeOneTest = (data?: any) => {
-  return new Promise((resolve, reject) => {
+  /**
+   * 连接成功
+   */
+  function getExamStarts(data?: any) {
     let examId = data ? data : parameter.examId;
     let examId = data ? data : parameter.examId;
-    let index = examStateList.findIndex((item: any) => {
-      return item.examId == examId;
+    sendMessage(
+      'exam_starts',
+      {
+        data: 'start_' + examId,
+        class_id: parameter.classes,
+        exam_type: parameter.standard,
+        gesture: parameter.gesture,
+        demo: parameter.demo,
+        test_time: testTime
+      },
+      () => { }
+    );
+  };
+
+  /**
+   * 创建测试
+   */
+  function openOneTest(data?: any) {
+    return new Promise((resolve, reject) => {
+      let examId = data ? data : parameter.examId;
+      let index = examStateList.findIndex((item: any) => {
+        return item.examId == examId;
+      });
+      sendMessage('msgfrom_frontend', {
+        data: {
+          cmd: 'open_one_test',
+          exam_id: examId
+        }
+      });
+      let timer1 = setInterval(() => {
+        if (examStateList[index].examState == 40) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          resolve({ data: examStateList[index].examState });
+        }
+      }, 250);
+      let timer2 = setTimeout(() => {
+        if (examStateList[index].examState == 3) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:open_one_test' } });
+        }
+      }, 30000);
     });
     });
-    sendMessage('msgfrom_frontend', {
-      data: {
-        cmd: 'close_one_test',
-        exam_id: examId
-      }
+  };
+
+  /**
+   * 开始人脸识别
+   */
+  function startFace(data?: any) {
+    return new Promise((resolve, reject) => {
+      let examId = data ? data : parameter.examId;
+      let index = examStateList.findIndex((item: any) => {
+        return item.examId == examId;
+      });
+      sendMessage('msgfrom_frontend', {
+        data: {
+          cmd: 'start_face_recognition',
+          exam_id: examId
+        }
+      });
+      let timer1 = setInterval(() => {
+        if (examStateList[index].examState == 41) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          resolve({ data: examStateList[index].examState });
+        }
+      }, 250);
+      let timer2 = setTimeout(() => {
+        if (examStateList[index].examState == 40) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:start_face_recognition' } });
+        }
+      }, 30000);
     });
     });
-    let timer1 = setInterval(() => {
-      if (examStateList[index].examState == 3) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        resolve({ data: examStateList[index].examState });
-      }
-    }, 250);
-    let timer2 = setTimeout(() => {
-      if (examStateList[index].examState != 3) {
-        clearInterval(timer1);
-        clearTimeout(timer2);
-        reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:close_one_test' } });
-      }
-    }, 30000);
-  });
-};
+  };
 
 
-/**
- * 某道识别到了人就停止某道的识别
- */
-export const suspendFaceRecognitionChannels = (data: any) => {
-  let track = data;
-  sendMessage('msgfrom_frontend', {
-    data: {
-      cmd: 'suspend_face_recognition_channels',
-      track: track
-    }
-  });
-};
+  /**
+   * 停止人脸识别
+   */
+  function stopFace(data?: any) {
+    return new Promise((resolve, reject) => {
+      let examId = data ? data : parameter.examId;
+      let index = examStateList.findIndex((item: any) => {
+        return item.examId == examId;
+      });
+      sendMessage('msgfrom_frontend', {
+        data: {
+          cmd: 'stop_face_recognition',
+          exam_id: examId
+        }
+      });
+      let timer1 = setInterval(() => {
+        if (examStateList[index].examState == 43) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          resolve({ data: examStateList[index].examState });
+        }
+      }, 250);
+      let timer2 = setTimeout(() => {
+        if (examStateList[index].examState == 41) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:stop_face_recognition' } });
+        }
+      }, 30000);
+    });
+  };
 
 
-/**
- * 某道重新开始识别
- */
-export const resumeFaceRecognitionChannels = (data: any) => {
-  let track = data;
-  sendMessage('msgfrom_frontend', {
-    data: {
-      cmd: 'resume_face_recognition_channels',
-      track: track
+  /**
+   * 确认并提交人脸
+   */
+  function faceConfirmOnly(data: any, callback?: any) {
+    let examId = data.exam_id ? data.exam_id : parameter.examId;
+    let myData = null;
+    if (Array.isArray(data)) {
+      //数组类型
+      myData = {
+        cmd: 'face_confirm_only',
+        data
+      };
+    } else {
+      //对象类型
+      myData = {
+        cmd: 'face_confirm_only',
+        exam_id: examId,
+        result_id: data.result_id,
+        student_id: data.student_id,
+        gender: data.gender
+      };
     }
     }
-  });
-};
+    sendMessage(
+      'msgfrom_frontend',
+      {
+        data: myData
+      },
+      () => {
+        callback();
+      }
+    );
+  };
 
 
-/**
- * 心跳
- */
-export const getNetWork = (data: any, callback?: any) => {
-  timerManager[data] = setInterval(() => {
-    let obj = wkList.find((item: any) => {
-      return item.examId == data;
-    });
-    if (obj == undefined) {
-      return false;
-    }
-    let wk_id = obj.wk_id;
+  /**
+   * 开始测试
+   */
+  function startOneTest(data?: any, callback?: any) {
     let examId = data ? data : parameter.examId;
     let examId = data ? data : parameter.examId;
     sendMessage(
     sendMessage(
-      'get_exam_status',
+      'msgfrom_frontend',
       {
       {
-        exam_id: examId,
-        wk_id: wk_id,
-        school_id: userInfo.school_id || null
+        data: {
+          cmd: 'start_one_test',
+          exam_id: examId
+        }
       },
       },
       () => {
       () => {
-        //如果心跳停止了就退出去
-        let index = examStateList.findIndex((item: any) => {
-          return item.examId == examId;
-        });
-        if (index == -1) {
-          return false;
-        }
-        let beforBeatNumber = JSON.parse(JSON.stringify(examStateList[index].beatNumber));
-        setTimeout(() => {
-          //5秒后验证是否有变
-          if (beforBeatNumber == examStateList[index].beatNumber) {
-            //异常
-            callback({ status: false });
-          } else {
-            //正常
-            callback({ status: true });
-          }
-        }, 5000);
+        callback();
       }
       }
     );
     );
-  }, beatTime);
-};
+  };
 
 
-/**
- * 关闭项目
- */
-export const examEnds = () => {
-  getExit();
-};
+  /**
+   * 停止测试
+   */
+  function finishOneTest(data?: any) {
+    return new Promise((resolve, reject) => {
+      let examId = data ? data : parameter.examId;
+      let index = examStateList.findIndex((item: any) => {
+        return item.examId == examId;
+      });
+      sendMessage('msgfrom_frontend', {
+        data: {
+          cmd: 'finish_one_test',
+          exam_id: examId
+        }
+      });
+      let timer1 = setInterval(() => {
+        if (examStateList[index].examState == 3) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          resolve({ data: examStateList[index].examState });
+        }
+      }, 250);
+      let timer2 = setTimeout(() => {
+        if (examStateList[index].examState == 42) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:finish_one_test' } });
+        }
+      }, 60000);
+    });
+  };
 
 
-/**
- * 退出
- */
-const getExit = (data?: any) => {
-  //关闭遮罩层
-  loading?.close();
-  //通知工作站关闭
-  if (testList.length > 1 && !data) {
-    //单WS多区
-    examStateList.forEach((item: any) => {
-      let examId = item.examId;
-      sendMessage('exam_ends', {
-        data: 'end_' + examId,
-        class_id: parameter.classes
+  /**
+   * 关闭测试测试
+   */
+  function closeOneTest(data?: any) {
+    return new Promise((resolve, reject) => {
+      let examId = data ? data : parameter.examId;
+      let index = examStateList.findIndex((item: any) => {
+        return item.examId == examId;
+      });
+      sendMessage('msgfrom_frontend', {
+        data: {
+          cmd: 'close_one_test',
+          exam_id: examId
+        }
       });
       });
+      let timer1 = setInterval(() => {
+        if (examStateList[index].examState == 3) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          resolve({ data: examStateList[index].examState });
+        }
+      }, 250);
+      let timer2 = setTimeout(() => {
+        if (examStateList[index].examState != 3) {
+          clearInterval(timer1);
+          clearTimeout(timer2);
+          reject({ cmd: 'disconnect_request', exam_id: examId, data: { message: '超时:close_one_test' } });
+        }
+      }, 30000);
     });
     });
-    //清除计时器
-    getClearTimer();
-    //如果正在连接就关闭
-    if (socket?.connected) {
-      socket?.close();
-    }
-  } else {
-    //单WS单区
-    let examId = data ? data : parameter.examId;
-    sendMessage('exam_ends', {
-      data: 'end_' + examId,
-      class_id: parameter.classes
+  };
+
+  /**
+   * 某道识别到了人就停止某道的识别
+   */
+  function suspendFaceRecognitionChannels(data: any) {
+    let track = data;
+    sendMessage('msgfrom_frontend', {
+      data: {
+        cmd: 'suspend_face_recognition_channels',
+        track: track
+      }
     });
     });
-    if (!data) {
+  };
+
+  /**
+   * 某道重新开始识别
+   */
+  function resumeFaceRecognitionChannels(data: any) {
+    let track = data;
+    sendMessage('msgfrom_frontend', {
+      data: {
+        cmd: 'resume_face_recognition_channels',
+        track: track
+      }
+    });
+  };
+
+  /**
+   * 心跳
+   */
+  function getNetWork(data: any, callback?: any) {
+    timerManager[data] = setInterval(() => {
+      let obj = wkList.find((item: any) => {
+        return item.examId == data;
+      });
+      if (obj == undefined) {
+        return false;
+      }
+      let wk_id = obj.wk_id;
+      let examId = data ? data : parameter.examId;
+      sendMessage(
+        'get_exam_status',
+        {
+          exam_id: examId,
+          wk_id: wk_id,
+          school_id: userInfo.school_id || null
+        },
+        () => {
+          //如果心跳停止了就退出去
+          let index = examStateList.findIndex((item: any) => {
+            return item.examId == examId;
+          });
+          if (index == -1) {
+            return false;
+          }
+          let beforBeatNumber = JSON.parse(JSON.stringify(examStateList[index].beatNumber));
+          setTimeout(() => {
+            //5秒后验证是否有变
+            if (beforBeatNumber == examStateList[index].beatNumber) {
+              //异常
+              callback({ status: false });
+            } else {
+              //正常
+              callback({ status: true });
+            }
+          }, 5000);
+        }
+      );
+    }, beatTime);
+  };
+
+  /**
+   * 关闭项目
+   */
+  function examEnds() {
+    getExit();
+  };
+
+  /**
+   * 退出
+   */
+  function getExit(data?: any) {
+    //关闭遮罩层
+    loading?.close();
+    //通知工作站关闭
+    if (testList.length > 1 && !data) {
+      //单WS多区
+      examStateList.forEach((item: any) => {
+        let examId = item.examId;
+        sendMessage('exam_ends', {
+          data: 'end_' + examId,
+          class_id: parameter.classes
+        });
+      });
       //清除计时器
       //清除计时器
       getClearTimer();
       getClearTimer();
       //如果正在连接就关闭
       //如果正在连接就关闭
       if (socket?.connected) {
       if (socket?.connected) {
         socket?.close();
         socket?.close();
       }
       }
+    } else {
+      //单WS单区
+      let examId = data ? data : parameter.examId;
+      sendMessage('exam_ends', {
+        data: 'end_' + examId,
+        class_id: parameter.classes
+      });
+      if (!data) {
+        //清除计时器
+        getClearTimer();
+        //如果正在连接就关闭
+        if (socket?.connected) {
+          socket?.close();
+        }
+      }
     }
     }
-  }
-};
+  };
 
 
-/**
- * 清空定时任务
- */
-const getClearTimer = () => {
-  for (let key in timerManager) {
-    if (timerManager.hasOwnProperty(key)) {
-      clearInterval(timerManager[key]);
-      timerManager[key] = null;
+  /**
+   * 清空定时任务
+   */
+  function getClearTimer() {
+    for (let key in timerManager) {
+      if (timerManager.hasOwnProperty(key)) {
+        clearInterval(timerManager[key]);
+        timerManager[key] = null;
+      }
+    }
+  };
+
+
+  onUnmounted(() => {
+    if (socket) {
+      socket.close();
+      socket = null;
     }
     }
-  }
-};
+  });
+
+  return { initWs, sendMessage, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels, getNetWork, examEnds };
+}

+ 44 - 52
src/views/gesture/index.vue

@@ -3,8 +3,8 @@
     <Header :showTool="false" @confirmExit="getLogout" :key="key"></Header>
     <Header :showTool="false" @confirmExit="getLogout" :key="key"></Header>
     <div class="menu" v-if="projectList.length" :key="projectList.length">
     <div class="menu" v-if="projectList.length" :key="projectList.length">
       <swiper :slides-per-view="5" :space-between="0" :loop="true" :observe-parents="true" :observer="true"
       <swiper :slides-per-view="5" :space-between="0" :loop="true" :observe-parents="true" :observer="true"
-        :centered-slides="true" :initial-slide="2" :dir="projectList.length <= 3 ? 'rtl' : 'ltr'"
-        :modules="[Navigation]" @swiper="onSwiper">
+        :centered-slides="true" :initial-slide="2" :dir="projectList.length <= 3 ? 'rtl' : 'ltr'" :modules="[Navigation]"
+        @swiper="onSwiper">
         <swiper-slide v-for="(item, index) in projectList" :key="index" @click="getOption(item)">
         <swiper-slide v-for="(item, index) in projectList" :key="index" @click="getOption(item)">
           <div class="li">
           <div class="li">
             <div>
             <div>
@@ -25,13 +25,13 @@
 </template>
 </template>
 
 
 <script setup name="Gesture" lang="ts">
 <script setup name="Gesture" lang="ts">
-import { handWs, startDevice, stateHand, startHand, closeHand } from '@/utils/handWs'
+import { useWebSocket } from '@/utils/handWs';
 import { Swiper, SwiperSlide } from 'swiper/vue';
 import { Swiper, SwiperSlide } from 'swiper/vue';
 import { Navigation } from 'swiper/modules';
 import { Navigation } from 'swiper/modules';
 import QRCode from "qrcode";
 import QRCode from "qrcode";
 import 'swiper/css';
 import 'swiper/css';
 import 'swiper/scss/navigation';
 import 'swiper/scss/navigation';
-
+const { handWs, startDevice, startHand, stateHand } = useWebSocket();
 const router = useRouter();
 const router = useRouter();
 const route = useRoute();
 const route = useRoute();
 const { proxy } = getCurrentInstance() as any;
 const { proxy } = getCurrentInstance() as any;
@@ -41,12 +41,11 @@ const data = reactive<any>({
   projectList: [],
   projectList: [],
   timerManager: {},
   timerManager: {},
   device_info: {},
   device_info: {},
-  listenWs: false,//是否监听手势
   erweima: '',
   erweima: '',
   sid: '',
   sid: '',
   key: 0,
   key: 0,
 });
 });
-const { mySwiper, projectList, timerManager, device_info, listenWs, erweima, sid, key } = toRefs(data);
+const { mySwiper, projectList, timerManager, device_info, erweima, sid, key } = toRefs(data);
 
 
 /**
 /**
  * 清空定时任务
  * 清空定时任务
@@ -149,7 +148,7 @@ const confirm = (myProject?: any) => {
   console.log("mySwiper.value.realIndex", mySwiper.value.realIndex)
   console.log("mySwiper.value.realIndex", mySwiper.value.realIndex)
   console.log("project", project)
   console.log("project", project)
   if (project == undefined) {
   if (project == undefined) {
-    proxy?.$modal.msgError("获取不到项目信息请刷新重试");
+    proxy?.$modal.msgError("获取不到项目信息");
     return false;
     return false;
   }
   }
   let obj = device_info.value.project_list.find((item: any) => {
   let obj = device_info.value.project_list.find((item: any) => {
@@ -214,13 +213,10 @@ const getLogout = async () => {
  * 提示语
  * 提示语
 */
 */
 const getTips = () => {
 const getTips = () => {
-  if (timerManager.value?.nextItem) {
-    return false
-  }
   let myTime = 7000;
   let myTime = 7000;
   let num = 0;
   let num = 0;
-  timerManager.value.nextItem = setInterval(() => {
-    if (router.currentRoute.value.path == '/gesture') {
+  timerManager.value.tips = setInterval(() => {
+    if (projectList.value.length) {
       if (num % 2 == 0) {
       if (num % 2 == 0) {
         proxy?.$modal.msgWarning({
         proxy?.$modal.msgWarning({
           message: `手向左滑切换项目`,
           message: `手向左滑切换项目`,
@@ -233,8 +229,6 @@ const getTips = () => {
         })
         })
       }
       }
       num++
       num++
-    } else {
-      getClearTimer("nextItem");
     }
     }
   }, myTime)
   }, myTime)
 };
 };
@@ -253,11 +247,30 @@ const getUserInfo = () => {
     if (res.data.length) {
     if (res.data.length) {
       let info = JSON.stringify(res.data[0]);
       let info = JSON.stringify(res.data[0]);
       localStorage.setItem("userInfo", info);
       localStorage.setItem("userInfo", info);
-      key.value = key.value + 1
+      key.value = key.value + 1//更新头部LOGO
     }
     }
   });
   });
 };
 };
 
 
+/**
+ * 获取设备项目
+*/
+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();
+    //跳转
+    router.push({ path: '/login/qrcode' });
+  }
+};
+
 /**
 /**
  * 获取二维码
  * 获取二维码
 */
 */
@@ -273,46 +286,25 @@ const getErweima = () => {
 
 
 onBeforeMount(() => {
 onBeforeMount(() => {
   //加载设备WS
   //加载设备WS
-  handWs(async (e: any) => {
-    //发送设备
-    if (e?.wksid) {
-      console.log("e.wksid", e.wksid)
-      sid.value = e.wksid;
-      listenWs.value = true;
-      let deviceid = localStorage.getItem("deviceid") || '';
-      if (deviceid) {
-        startDevice({ deviceid: deviceid })
-        timerManager.value.deviceid = setInterval(() => {
-          if (device_info.value.handcontroller_id == undefined) {
-            //刷新
-            window.location.reload()
-          } else {
-            getClearTimer("deviceid");
-          }
-        }, 10000)
-      } else {
-        proxy?.$modal.msgError(`缺少设备信息请重新登录!`);
-        await proxy?.$http.common.logout({}).then((res: any) => {
-        });
-        proxy?.$modal?.closeLoading()
-        //清空缓存
-        localStorage.clear();
-        //跳转
-        router.push({ path: '/login/qrcode' });
-      }
-    }
-    if (listenWs.value == false) {
+  handWs((e: any) => {
+    if(router.currentRoute.value.path != '/gesture'){
       return false;
       return false;
     }
     }
-    //接收参数
+    console.log("eeeee", e)
+    if (e?.wksid) {
+      //获取设备项目
+      getDevice()
+    }
+    //接收设备信息
     if (e?.device_info) {
     if (e?.device_info) {
-      console.log("222", e)
-      getClearTimer("deviceid");
       device_info.value = e.device_info;
       device_info.value = e.device_info;
+      let handcontroller_id = device_info.value.handcontroller_id;
+      stateHand(handcontroller_id);
+    }
+    //获取手势状态
+    if (e?.cmd == 'get_handcontroller_state' && e?.state == 0) {
       let handcontroller_id = device_info.value.handcontroller_id;
       let handcontroller_id = device_info.value.handcontroller_id;
       startHand(handcontroller_id);
       startHand(handcontroller_id);
-      getInitExam()
-      getTips();
     }
     }
     //左滑动
     //左滑动
     if (e?.data?.result == "next_item") {
     if (e?.data?.result == "next_item") {
@@ -327,19 +319,19 @@ onBeforeMount(() => {
     }
     }
     //退出
     //退出
     if (e?.data?.result == "exit") {
     if (e?.data?.result == "exit") {
-
     }
     }
   });
   });
 })
 })
 onMounted(() => {
 onMounted(() => {
-  // getInitExam();
+  getInitExam();
   getUserInfo();
   getUserInfo();
   //登录码
   //登录码
   getErweima();
   getErweima();
+  //提示语
+  getTips();
 
 
 })
 })
 onBeforeUnmount(() => {
 onBeforeUnmount(() => {
-  listenWs.value = false;
   getClearTimer();
   getClearTimer();
   ElMessage.closeAll();
   ElMessage.closeAll();
 })
 })

+ 8 - 4
src/views/login/qrcode.vue

@@ -39,8 +39,9 @@
 </template>
 </template>
 
 
 <script setup name="QrcodeLogin" lang="ts">
 <script setup name="QrcodeLogin" lang="ts">
+import { useWebSocket } from '@/utils/handWs';
 import QRCode from "qrcode";
 import QRCode from "qrcode";
-import { handWs, startLogin } from '@/utils/handWs'
+const { handWs, startLogin } = useWebSocket();
 const { proxy } = getCurrentInstance() as any;
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 const router = useRouter();
 const route = useRoute();
 const route = useRoute();
@@ -213,13 +214,15 @@ onMounted(() => {
         text-align: center;
         text-align: center;
         height: 4rem;
         height: 4rem;
         line-height: 4rem;
         line-height: 4rem;
+
         .li {
         .li {
           width: 50%;
           width: 50%;
           color: #ffffff;
           color: #ffffff;
           border-bottom: 1px solid #f1f1f1;
           border-bottom: 1px solid #f1f1f1;
           cursor: pointer;
           cursor: pointer;
         }
         }
-        .current{
+
+        .current {
           color: #14F287;
           color: #14F287;
           border-bottom: 1px solid #14F287;
           border-bottom: 1px solid #14F287;
         }
         }
@@ -229,12 +232,14 @@ onMounted(() => {
         width: 13rem;
         width: 13rem;
         height: calc(13rem + 1rem + 2rem);
         height: calc(13rem + 1rem + 2rem);
         padding: 2rem 5rem;
         padding: 2rem 5rem;
+
         .qrcodeBox {
         .qrcodeBox {
           text-align: center;
           text-align: center;
 
 
           .pic {
           .pic {
             width: 100%;
             width: 100%;
             margin-bottom: 1rem;
             margin-bottom: 1rem;
+
             img {
             img {
               width: 100%;
               width: 100%;
             }
             }
@@ -299,5 +304,4 @@ onMounted(() => {
       }
       }
     }
     }
   }
   }
-}
-</style>
+}</style>

+ 6 - 10
src/views/train/multiple.vue

@@ -67,9 +67,11 @@
 </template>
 </template>
 
 
 <script setup name="Multiple" lang="ts">
 <script setup name="Multiple" lang="ts">
+import { useWs } from '@/utils/ws';
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech'
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech'
-import { initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels } from '@/utils/ws'
-import { handWs, startHand, closeHand } from '@/utils/handWs'
+import { useWebSocket } from '@/utils/handWs';  
+const { handWs } = useWebSocket();
+const { initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels } = useWs();
 const { proxy } = getCurrentInstance() as any;
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 const router = useRouter();
 const route = useRoute();
 const route = useRoute();
@@ -94,10 +96,9 @@ const data = reactive<any>({
   showReportList: false,//显示隐藏测试记录
   showReportList: false,//显示隐藏测试记录
   exit: 0,//退出响应次数
   exit: 0,//退出响应次数
   sid: null,//WS的id
   sid: null,//WS的id
-  listenWs: false,//是否监听手势
   chooseStudentArea:'',//弹出手动选择对应的区号
   chooseStudentArea:'',//弹出手动选择对应的区号
 });
 });
-const { timerManager, parameter, time, userInfo, examState, needStart, showTestAgain, testList, multipleItemRefList, styleType, showReportList, exit, sid, listenWs, chooseStudentArea } = toRefs(data);
+const { timerManager, parameter, time, userInfo, examState, needStart, showTestAgain, testList, multipleItemRefList, styleType, showReportList, exit, sid, chooseStudentArea } = toRefs(data);
 
 
 /**
 /**
  * 创建组件实例
  * 创建组件实例
@@ -585,11 +586,7 @@ const getAddTestList = (num: number) => {
 */
 */
 const initHand = () => {
 const initHand = () => {
   handWs((e: any) => {
   handWs((e: any) => {
-    if (e?.wksid) {
-      console.log("e.wksid", e.wksid)
-      listenWs.value = true;
-    }
-    if (listenWs.value == false) {
+    if (router.currentRoute.value.path != '/train/multiple'){
       return false;
       return false;
     }
     }
     //左滑动
     //左滑动
@@ -787,7 +784,6 @@ onMounted(() => {
 })
 })
 
 
 onBeforeUnmount(() => {
 onBeforeUnmount(() => {
-  listenWs.value = false;
   getExit();
   getExit();
 })
 })
 </script>
 </script>

+ 2 - 1
src/views/train/run.vue

@@ -119,14 +119,15 @@
 </template>
 </template>
 
 
 <script setup name="TrainTest" lang="ts">
 <script setup name="TrainTest" lang="ts">
+import { useWs } from '@/utils/ws';
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech'
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech'
-import { initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels } from '@/utils/ws'
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
 import dataDictionary from "@/utils/dataDictionary"
 import dataDictionary from "@/utils/dataDictionary"
 import { Swiper, SwiperSlide } from 'swiper/vue';
 import { Swiper, SwiperSlide } from 'swiper/vue';
 import { Navigation } from 'swiper/modules';
 import { Navigation } from 'swiper/modules';
 import 'swiper/css';
 import 'swiper/css';
 import 'swiper/scss/navigation';
 import 'swiper/scss/navigation';
+const { initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels } = useWs();
 const { proxy } = getCurrentInstance() as any;
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 const router = useRouter();
 const route = useRoute();
 const route = useRoute();

+ 13 - 14
src/views/train/test.vue

@@ -113,11 +113,13 @@
 </template>
 </template>
 
 
 <script setup name="TrainTest" lang="ts">
 <script setup name="TrainTest" lang="ts">
+import { useWs } from '@/utils/ws';
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech'
 import { initSpeech, speckText, playMusic, controlMusic, speckCancel, chineseNumber } from '@/utils/speech'
-import { initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels } from '@/utils/ws'
-import { handWs, startHand, closeHand } from '@/utils/handWs'
+import { useWebSocket } from '@/utils/handWs';  
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
 import dataDictionary from "@/utils/dataDictionary"
 import dataDictionary from "@/utils/dataDictionary"
+const { handWs } = useWebSocket();
+const { initWs, examEnds, openOneTest, startFace, stopFace, faceConfirmOnly, startOneTest, finishOneTest, closeOneTest, suspendFaceRecognitionChannels, resumeFaceRecognitionChannels } = useWs();
 const { proxy } = getCurrentInstance() as any;
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 const router = useRouter();
 const route = useRoute();
 const route = useRoute();
@@ -148,9 +150,8 @@ const data = reactive<any>({
   readyState: true,//倒计时按钮状态
   readyState: true,//倒计时按钮状态
   exit: 0,//退出响应次数
   exit: 0,//退出响应次数
   sid: null,//WS的id
   sid: null,//WS的id
-  listenWs: false,//是否监听手势
 });
 });
-const { timerManager, parameter, time, userInfo, examState, resultId, faceCheckStu, currentResultObj, unit, backReason, backReasonStr, needStart, showTestAgain, readyState, exit, sid, listenWs } = toRefs(data);
+const { timerManager, parameter, time, userInfo, examState, resultId, faceCheckStu, currentResultObj, unit, backReason, backReasonStr, needStart, showTestAgain, readyState, exit, sid } = toRefs(data);
 
 
 /**
 /**
  * 接收消息
  * 接收消息
@@ -545,7 +546,7 @@ const getFaceWindow = (data: boolean, num: number = 0) => {
     }, 3000)
     }, 3000)
   }
   }
   //定时检查如果一直停留在人脸识别就提示
   //定时检查如果一直停留在人脸识别就提示
-  let timeout = 15000;
+  let timeout = 16000;
   timerManager.value.face = setInterval(() => {
   timerManager.value.face = setInterval(() => {
     getClearTimer("face");
     getClearTimer("face");
     if (examState.value == 41 && total < 3) {
     if (examState.value == 41 && total < 3) {
@@ -698,11 +699,7 @@ const getReady = () => {
 */
 */
 const initHand = () => {
 const initHand = () => {
   handWs((e: any) => {
   handWs((e: any) => {
-    if (e?.wksid) {
-      console.log("e.wksid", e.wksid)
-      listenWs.value = true;
-    }
-    if (listenWs.value == false) {
+    if (router.currentRoute.value.path != '/train/test'){
       return false;
       return false;
     }
     }
     //左滑动
     //左滑动
@@ -715,9 +712,9 @@ const initHand = () => {
         getOpenOneTestAndStartFace();
         getOpenOneTestAndStartFace();
       }
       }
       //停止人脸识别
       //停止人脸识别
-      if (needStart.value && examState.value == 41) {
-        getStopFace();
-      }
+      // if (needStart.value && examState.value == 41) {
+      //   getStopFace();
+      // }
       //开始测试
       //开始测试
       if (examState.value == 43) {
       if (examState.value == 43) {
         if (needStart.value) {
         if (needStart.value) {
@@ -810,6 +807,9 @@ watch(() => time.value.countdownNum, (newData) => {
   if (newData <= 5) {
   if (newData <= 5) {
     speckText(newData);
     speckText(newData);
   }
   }
+  if (newData == 0) {
+    speckText("哨声");
+  }
 }, { immediate: true });
 }, { immediate: true });
 
 
 /**
 /**
@@ -889,7 +889,6 @@ onBeforeMount(() => {
 })
 })
 
 
 onBeforeUnmount(() => {
 onBeforeUnmount(() => {
-  listenWs.value = false;
   getExit();
   getExit();
 })
 })
 </script>
 </script>