123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- <template>
- <div class="row" style="margin: 0;">
- <div class="col-md-12 text-center" style="padding:8px;">
- <div style="font-size: 30px;">
- <span>人脸检测</span> <span v-if="showIframe">({{ timeCount }})</span>
- </div>
- <div
- v-if="showIframe"
- class="text-center"
- style="color: red; font-size: 16px;"
- >
- (注意:请点击下方“开始比对”按钮并在60秒内完成人脸检测,超时将退出考试)
- </div>
- </div>
- <div
- id="faceIdDiv"
- style="position: relative;
- height:710px; background-color: #6e6f72 !important;
- background-image: radial-gradient(circle at 50% 0,#a9a9a9,#34363c);"
- >
- <div
- v-show="!showIframe"
- width="100%"
- height="200px"
- style="text-align: center;line-height:100px;margin-top:5px;"
- >
- <div style="color:white;font-weight: bold;font-size:20px;">
- {{ redoBtnMsg }}
- </div>
- <button
- v-if="redoBtnShow"
- type="button"
- class="qm-primary-button"
- :disabled="redoBtnDisabled"
- @click="startFaceVerify"
- >
- 重试
- </button>
- </div>
- <webview
- id="myFrame"
- v-show="showIframe"
- :preload="electronDir + 'manipulateFaceID.js'"
- style="position:absolute;width:100%;height:710px;"
- ></webview>
- <!-- <iframe
- src="https://www.baidu.com"
- preload="./manipulateFaceID.js"
- allow="camera *"
- src="https://www.baidu.com"
- allowusermedia
- id="myFrame"
- scrolling="no"
- width="100%"
- height="710px"
- frameborder="0"
- ></iframe> -->
- <!-- <iframe
- v-show="showIframe"
- allow="camera *"
- allowusermedia
- id="myFrame"
- scrolling="no"
- width="100%"
- height="710px"
- frameborder="0"
- ></iframe> -->
- </div>
- </div>
- </template>
- <script>
- import {
- FACEID_LINENESS_URL,
- VUE_APP_WK_SERVER_SOCKET,
- } from "@/constants/constants.js";
- export default {
- name: "FaceId",
- data() {
- return {
- showIframe: false,
- redoBtnShow: false,
- timeCount: 60,
- redoBtnMsg: "",
- electronDir: "",
- };
- },
- mounted() {
- console.debug("startFaceVerify");
- window._hmt.push(["_trackEvent", "活体检测弹出框", "弹出框"]);
- this.startFaceVerify();
- if (typeof nodeRequire != "undefined") {
- // console.log(nodeRequire("electron").remote.app);
- const app = window.nodeRequire("electron").remote.app;
- this.electronDir = "file://" + app.getAppPath() + "/";
- console.log(this.electronDir);
- }
- },
- beforeDestroy() {
- try {
- if (this.ws && this.ws.readyState === 1) this.ws.close();
- } catch (e) {
- console.log("关闭ws异常。");
- }
- clearTimeout(this.faceIdTime);
- clearInterval(this.timeCountInterval);
- clearTimeout(this.iframeDomReadyTimeout);
- },
- methods: {
- showRedo(redoMsg) {
- this.showIframe = false;
- this.redoBtnDisabled = false;
- this.redoBtnShow = true;
- if (redoMsg) {
- this.redoBtnMsg = redoMsg;
- } else {
- this.redoBtnMsg = "系统繁忙,请手动点击重试";
- }
- },
- updateFaceVerify(errorMsg, redoMsg) {
- this.showRedo(redoMsg);
- this.$http.get(
- "/api/ecs_oe_student/examFaceLivenessVerify/updateFaceLivenessVerify/" +
- this.$route.params.examRecordDataId,
- { params: { errorMsg: errorMsg } }
- );
- },
- // checkIframeOnload() {
- // var iframe = document.getElementById("myFrame");
- // if (!iframe) {
- // return null;
- // }
- // var app = iframe.contentWindow.document.getElementById("app");
- // if (app) {
- // return "success";
- // } else {
- // var preLabel = iframe.contentWindow.document.getElementsByTagName(
- // "pre"
- // )[0];
- // if (
- // preLabel &&
- // preLabel.innerText &&
- // preLabel.innerText.indexOf("error_message") > -1
- // ) {
- // return preLabel.innerText;
- // }
- // }
- // return null;
- // },
- iframeLoadSuccess() {
- window._hmt.push([
- "_trackEvent",
- "活体检测弹出框",
- "FaceID页面iframe加载成功",
- ]);
- // try {
- // var iframe = document.getElementById("myFrame");
- // var app = iframe.contentWindow.document.getElementById("app");
- // app.querySelector(".footer").remove();
- // } catch (err) {
- // console.error(err);
- // }
- const examRecordId = this.$route.params.examRecordDataId;
- this.timeCount = 60; //人脸检测倒计时60秒
- this.timeCountInterval = setInterval(() => {
- --this.timeCount;
- if (this.timeCount === 0) {
- clearInterval(this.timeCountInterval);
- }
- }, 1000);
- //定时事件,如果1分钟内未完成人脸检测,执行内部程序
- this.faceIdTime = setTimeout(() => {
- this.ws.close();
- this.$http
- .get(
- "/api/ecs_oe_student/examFaceLivenessVerify/faceLivenessVerifyTimeOut/" +
- examRecordId
- )
- .then(response => {
- if (response.status == 200) {
- var receivedMsg = response.data;
- this.faceTestEnd(receivedMsg);
- }
- })
- .finally(() => {
- // Chrome 63开始支持。但是vue-cli引入了p-finally,所以已经加在Promise对象中了
- clearInterval(this.timeCountInterval);
- if (!this.faceTestEndCalled) {
- this.$Message.error({
- content: "人脸检测超时,系统退出,请重新登录",
- duration: 30,
- closable: true,
- });
- }
- this.logout(
- "?LogoutReason=" +
- (!this.faceTestEndCalled
- ? "活体检测超时-可续考"
- : "活体检测超时")
- );
- });
- }, 60000); //60000
- /**
- * 人脸检测结果返回后台处理
- */
- this.faceTestEndHandle = result => {
- this.$http
- .get(
- "/api/ecs_oe_student/examFaceLivenessVerify/faceLivenessVerifyEnd/" +
- examRecordId +
- "?result=" +
- result
- )
- .then(() => {
- if (result != "SUCCESS") {
- this.logout("?LogoutReason=活体检测失败");
- window._hmt.push([
- "_trackEvent",
- "活体检测弹出框",
- "活体检测失败",
- ]);
- } else {
- window._hmt.push([
- "_trackEvent",
- "活体检测弹出框",
- "活体检测成功",
- ]);
- }
- })
- .catch(() => {
- this.$Message.error({
- content: "上传人脸检测结果出错!",
- duration: 15,
- closable: true,
- });
- this.logout("?LogoutReason=上传人脸检测结果出错!");
- });
- };
- /**
- * 人脸检测结束
- */
- this.faceTestEnd = receivedMsg => {
- this.faceTestEndCalled = true;
- if (receivedMsg.verifyCount == 1) {
- if (receivedMsg.verifyResult == "TIME_OUT") {
- this.$Message.error({
- content: "第一次人脸检测超时,检测失败,系统退出,请重新登录",
- duration: 30,
- closable: true,
- });
- this.logout(
- "?LogoutReason=第一次活体检测超时,检测失败,系统退出,请重新登录"
- );
- } else if (receivedMsg.verifyResult == "VERIFY_FAILED") {
- this.$Message.error({
- content: "第一次人脸检测失败,系统退出,请重新登录",
- duration: 30,
- closable: true,
- });
- this.logout(
- "?LogoutReason=第一次活体检测失败,系统退出,请重新登录"
- );
- } else if (receivedMsg.verifyResult == "NOT_ONESELF") {
- this.$Message.error({
- content: "人脸检测不合格,结束考试",
- duration: 30,
- closable: true,
- });
- this.faceTestEndHandle("FAILED");
- } else if (receivedMsg.verifyResult == "VERIFY_SUCCESS") {
- this.$Message.info({
- content: "人脸检测成功,请继续完成考试",
- duration: 15,
- closable: true,
- });
- this.faceTestEndHandle("SUCCESS");
- }
- } else if (receivedMsg.verifyCount >= 2) {
- if (receivedMsg.verifyResult == "VERIFY_SUCCESS") {
- this.$Message.info({
- content: "人脸检测成功,请继续完成考试",
- duration: 15,
- closable: true,
- });
- this.faceTestEndHandle("SUCCESS");
- } else {
- this.$Message.error({
- content: "人脸检测不合格,结束考试",
- duration: 30,
- closable: true,
- });
- this.faceTestEndHandle("FAILED");
- }
- }
- };
- // open websocket
- this.ws = new WebSocket(VUE_APP_WK_SERVER_SOCKET + examRecordId);
- this.ws.onopen = function() {
- console.log("websocket已连接");
- };
- this.ws.onmessage = response => {
- if (response.data.indexOf("verifyResult") > -1) {
- var receivedMsg = JSON.parse(response.data);
- this.faceTestEnd(receivedMsg);
- clearTimeout(this.faceIdTime);
- clearInterval(this.timeCountInterval);
- this.$emit("closeFaceId");
- this.ws.close();
- }
- };
- // 重复关闭不会报错
- this.ws.onclose = function() {
- console.log("websocket连接已关闭...");
- };
- },
- async startFaceVerify() {
- this.redoBtnDisabled = true;
- this.redoBtnMsg = "正在进入人脸检测...";
- const examRecordId = this.$route.params.examRecordDataId;
- let response = null;
- try {
- response = await this.$http.get(
- "/api/ecs_oe_student/examFaceLivenessVerify/getFaceLivenessVerifyToken/" +
- examRecordId
- );
- } catch (error) {
- this.$Message.error({
- content: "获取底照token失败,请重新登录!",
- duration: 15,
- closable: true,
- });
- this.logout("?LogoutReason=获取底照token失败,请重新登录!");
- return;
- }
- if (!response.data.success) {
- console.log(response.data.errorMsg);
- this.$Message.error({
- content: "您上传的底照不适合做活体检测,请联系老师!",
- duration: 15,
- closable: true,
- });
- this.logout("?LogoutReason=您上传的底照不适合做活体检测,请联系老师!");
- return;
- }
- this.showIframe = true;
- var iframe = document.getElementById("myFrame");
- try {
- iframe.src = FACEID_LINENESS_URL + response.data.faceLivenessToken;
- } catch (err) {
- console.error(err);
- }
- // var index = 0;
- // var iframeLoadTime = setInterval(() => {
- // var iframeLoadMsg = this.checkIframeOnload();
- // if (!iframeLoadMsg) {
- // index++;
- // if (index == 20) {
- // //检测达到20次
- // clearInterval(iframeLoadTime);
- // this.showRedo("网络异常,请手动点击重试");
- // window._hmt.push(["_trackEvent", "活体检测弹出框", "网络异常"]);
- // }
- // } else if (iframeLoadMsg.indexOf("error_message") > -1) {
- // clearInterval(iframeLoadTime);
- // this.updateFaceVerify(iframeLoadMsg, null);
- // } else if (iframeLoadMsg == "success") {
- // clearInterval(iframeLoadTime);
- // // this.iframeLoadSuccess();
- // setTimeout(() => {
- // this.iframeLoadSuccess();
- // }, 300); // 延迟确保能删除footer
- // }
- // }, 500);
- {
- // iframe 状态管理
- let iframeDomReady = false;
- iframe.addEventListener("did-start-loading", () => {
- console.log("loading faceid iframe");
- });
- iframe.addEventListener("did-fail-load", () => {
- console.log("failed loading faceid iframe");
- });
- iframe.addEventListener("dom-ready", () => {
- iframeDomReady = true;
- console.log("faceid iframe dom ready");
- // iframe.openDevTools();
- });
- iframe.addEventListener("ipc-message", event => {
- // console.log(event.channel);
- clearInterval(this.iframeDomReadyTimeout);
- const iframeLoadMsg = event.channel;
- if (iframeLoadMsg.indexOf("error_message") > -1) {
- this.updateFaceVerify(iframeLoadMsg, null);
- }
- if (iframeLoadMsg === "success") {
- this.iframeLoadSuccess();
- iframe.send("faceid-footer", ".copyright");
- }
- });
- // 网络异常,最后的管理
- this.iframeDomReadyTimeout = setTimeout(() => {
- if (iframeDomReady === false) {
- clearTimeout(this.iframeDomReadyTimeout);
- this.showRedo("网络异常,请手动点击重试");
- window._hmt.push(["_trackEvent", "活体检测弹出框", "网络异常"]);
- }
- }, 60 * 1000);
- }
- },
- },
- };
- </script>
|