From e491cdb48129752324c4e3764f99bd9203c56dec Mon Sep 17 00:00:00 2001
From: lgq <1015864684@qq.com>
Date: 星期二, 31 三月 2026 09:48:44 +0800
Subject: [PATCH] 1.新增VF205门禁机代码
---
vf205_access/src/service/faceService.js | 447 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 447 insertions(+), 0 deletions(-)
diff --git a/vf205_access/src/service/faceService.js b/vf205_access/src/service/faceService.js
new file mode 100644
index 0000000..a84aab1
--- /dev/null
+++ b/vf205_access/src/service/faceService.js
@@ -0,0 +1,447 @@
+/**
+ * 浜鸿劯璇嗗埆鏈嶅姟妯″潡
+ * 澶勭悊浜鸿劯璇嗗埆鐩稿叧鐨勪笟鍔¢�昏緫锛屽寘鎷汉鑴告敞鍐屽拰浜鸿劯姣斿
+ */
+import logger from "../../dxmodules/dxLogger.js";
+import dxCommon from "../../dxmodules/dxCommon.js";
+import bus from "../../dxmodules/dxEventBus.js";
+import dxMap from "../../dxmodules/dxMap.js";
+import driver from "../driver.js";
+import config from "../../dxmodules/dxConfig.js";
+import sqliteService from "./sqliteService.js";
+import std from "../../dxmodules/dxStd.js";
+import pool from "../../dxmodules/dxWorkerPool.js";
+
+let map = dxMap.get("LOGIN")
+const faceService = {}
+
+// 璇煶鎾斁闃叉姈鎺у埗
+let lastPlayTime = 0
+const PLAY_DELAY = 2000 // 2绉掑唴涓嶉噸澶嶆挱鏀剧浉鍚岃闊�
+
+/**
+ * 璇煶鎾斁闃叉姈鍑芥暟
+ * @param {function} playFunction - 鎾斁鍑芥暟
+ * @returns {boolean} 鏄惁鎵ц浜嗘挱鏀�
+ */
+function debouncePlay(playFunction) {
+ const now = Date.now()
+ if (now - lastPlayTime > PLAY_DELAY) {
+ lastPlayTime = now
+ playFunction()
+ return true
+ }
+ return false
+}
+
+// 鍙屼汉璁よ瘉鐘舵�佺鐞�
+let dualAuthState = {
+ firstUserId: null, // 绗竴涓敤鎴稩D
+ firstUserName: null, // 绗竴涓敤鎴峰鍚�
+ firstUserFileName: null, // 绗竴涓敤鎴蜂汉鑴稿浘鐗囨枃浠惰矾寰�
+ firstUserIdCard: null, // 绗竴涓敤鎴疯韩浠借瘉鍙�
+ firstUserType: null, // 绗竴涓敤鎴疯韩浠界被鍨�
+ secondUserId: null, // 绗簩涓敤鎴稩D
+ secondUserName: null, // 绗簩涓敤鎴峰鍚�
+ secondUserIdCard: null, // 绗簩涓敤鎴疯韩浠借瘉鍙�
+ secondUserType: null, // 绗簩涓敤鎴疯韩浠界被鍨�
+ startTime: 0, // 寮�濮嬫椂闂�
+ timeout: null, // 瀹氭椂鍣�
+ authComplete: false // 璁よ瘉鏄惁瀹屾垚
+}
+
+/**
+ * 鎺ユ敹浜鸿劯璇嗗埆娑堟伅骞跺鐞�
+ * @param {object} data - 浜鸿劯璇嗗埆鏁版嵁
+ */
+faceService.receiveMsg = function (data) {
+ logger.info('[faceService] receiveMsg :' + JSON.stringify(data))
+ // 瑙﹀彂閫�鍑虹┖闂茬姸鎬佷簨浠讹紙閿佸睆鍜屾伅灞忥級
+ bus.fire("exitIdle")
+
+ switch (data.type) {
+ case "register":
+ // 娉ㄥ唽浜鸿劯澶勭悊
+ for (let i = 0; i < data.faces.length; i++) {
+ const element = data.faces[i];
+ bus.fire("beginAddFace", element)
+ }
+ break;
+ case "compare":
+ // 浜鸿劯姣斿澶勭悊
+ // 鏄剧ず濮撳悕锛屼唬琛ㄦ湁娉ㄥ唽杩囦汉鑴革紝浣嗘槸鏉冮檺涓嶄竴瀹氭湁鏁堬紝闇�瑕佽繘涓�姝ヨ璇�
+ for (let i = 0; i < data.faces.length; i++) {
+ const element = data.faces[i];
+
+ // 鍙湁鍦ㄨ璇佹湭瀹屾垚鏃舵墠瑙﹀彂trackResult浜嬩欢
+ if (!dualAuthState.authComplete) {
+ // 鍒ゆ柇褰撳墠鏄鍑犱釜鐢ㄦ埛锛堢敤浜庡弻浜鸿璇侊級
+ let userIndex = 1 // 0琛ㄧず鏈煡锛�1琛ㄧず绗竴涓敤鎴凤紝2琛ㄧず绗簩涓敤鎴�
+ if (!dualAuthState.firstUserId) {
+ // 绗竴涓敤鎴疯繕鏈缃紝褰撳墠鐢ㄦ埛灏辨槸绗竴涓敤鎴�
+ userIndex = 1
+ } else if (element.userId === dualAuthState.firstUserId) {
+ userIndex = 1
+ } else if (element.userId !== dualAuthState.firstUserId) {
+ userIndex = 2
+ }
+
+ logger.info('[faceService]: 鍑嗗瑙﹀彂trackResult浜嬩欢, userIndex=' + userIndex + ', result=' + element.result + ', userId=' + element.userId + ', authComplete=' + dualAuthState.authComplete + ', fileName=' + element.fileName)
+
+ // 鐩存帴浣跨敤bus.fire瑙﹀彂trackResult浜嬩欢
+ bus.fire("trackResult", { id: element.id, result: element.result, userId: element.userId, userIndex: userIndex, fileName: element.fileName })
+ }
+
+ if (element.result) {
+ // 浜鸿劯鐩镐技搴﹂獙璇侀�氳繃
+ let ret = sqliteService.d1_person.find({ userId: element.userId })
+
+ if (dxMap.get("UI").get("faceAuthStart") == "Y") {
+ // 姝e湪浜鸿劯鐧诲綍
+ if (JSON.parse(ret[0].extra).type != 0) {
+ bus.fire("faceAuthResult", true)
+ } else {
+ bus.fire("faceAuthResult", false)
+ }
+ return
+ }
+
+ // 妫�鏌ョ敤鎴风被鍨嬶紙绠$悊鍛樼骇鍒級
+ let userType = 0
+ try {
+ userType = JSON.parse(ret[0].extra).type || 0
+ } catch (error) {
+ logger.error("瑙f瀽鐢ㄦ埛绫诲瀷澶辫触")
+ }
+
+ // 绠$悊鍛樼骇鍒敤鎴凤紙type != 0锛夌洿鎺ヨ璇侀�氳繃
+ if (userType != 0) {
+ // 娓呴櫎鍙屼汉璁よ瘉鐘舵��
+ clearDualAuthState()
+
+ // 鏍规嵁璇煶妯″紡鎾斁鐩稿簲鐨勮闊�
+ switch (config.get("face.voiceMode")) {
+ case 0:
+ // 鏃犺闊�
+ break;
+ case 1:
+ // 鎾斁鍚嶅瓧
+ driver.alsa.ttsPlay(ret[0].name)
+ break;
+ case 2:
+ // 鎾斁闂�欒
+ driver.alsa.ttsPlay(config.get("face.voiceModeDate") ? config.get("face.voiceModeDate") : "娆㈣繋鍏変复")
+ break;
+ default:
+ break;
+ }
+
+ // 閫氳璁よ瘉澶勭悊
+ bus.fire("access", { data: { type: "300", code: element.userId }, fileName: element.fileName })
+ } else {
+ // 闈炵鐞嗗憳绾у埆鐢ㄦ埛锛岄渶瑕佸弻浜鸿璇�
+ handleDualAuth(element.userId, ret[0].name, element.fileName)
+ }
+ } else {
+ // 浜鸿劯鐩镐技搴﹂獙璇佸け璐�
+ if (dxMap.get("UI").get("faceAuthStart") == "Y") {
+ // 浜鸿劯鐧诲綍澶辫触
+ bus.fire("faceAuthResult", false)
+ } else {
+ // 闄岀敓浜哄鐞�
+ switch (config.get("face.stranger")) {
+ case 0:
+ // 鏃犺闊�
+ break;
+ case 1:
+ // 鎾斁璇峰厛娉ㄥ唽锛堥槻鎶栨帶鍒讹級
+ debouncePlay(() => {
+ driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/register.wav`)
+ })
+ break;
+ case 2:
+ // 鎾斁闄岀敓浜轰綘濂斤紙闃叉姈鎺у埗锛�
+ debouncePlay(() => {
+ driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/stranger.wav`)
+ })
+ break;
+ default:
+ break;
+ }
+ // 閫氳璁よ瘉澶勭悊锛堢浉浼煎害楠岃瘉澶辫触锛�
+ bus.fire("access", { data: { type: "300", code: element.userId }, fileName: element.fileName, similarity: false })
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// 鐩戝惉閫氳瑙i攣瀹屾垚浜嬩欢锛岄噸缃弻浜鸿璇佺姸鎬�
+bus.on('accessUnlockComplete', () => {
+ logger.info('[faceService]: accessUnlockComplete浜嬩欢瑙﹀彂锛岄噸缃弻浜鸿璇佺姸鎬�')
+ clearDualAuthState()
+})
+
+/**
+ * 娓呴櫎鍙屼汉璁よ瘉鐘舵��
+ */
+function clearDualAuthState() {
+ dualAuthState.firstUserId = null
+ dualAuthState.firstUserName = null
+ dualAuthState.firstUserFileName = null
+ dualAuthState.firstUserIdCard = null
+ dualAuthState.firstUserType = null
+ dualAuthState.secondUserId = null
+ dualAuthState.secondUserName = null
+ dualAuthState.secondUserIdCard = null
+ dualAuthState.secondUserType = null
+ dualAuthState.startTime = 0
+ dualAuthState.authComplete = false // 閲嶇疆璁よ瘉瀹屾垚鏍囧織
+ if (dualAuthState.timeout) {
+ std.clearTimeout(dualAuthState.timeout)
+ dualAuthState.timeout = null
+ }
+}
+
+/**
+ * 澶勭悊鍙屼汉璁よ瘉瓒呮椂
+ */
+function handleDualAuthTimeout() {
+ try {
+ // 淇濆瓨璁よ瘉璁板綍
+ if (dualAuthState.firstUserId && !dualAuthState.authComplete) {
+ // 鏌ヨ绗竴鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤绫诲瀷
+ let firstUserType = dualAuthState.firstUserType || 0
+ if (!firstUserType) {
+ let res = sqliteService.d1_person.findByUserId(dualAuthState.firstUserId)
+ if (res.length > 0) {
+ try {
+ firstUserType = JSON.parse(res[0].extra).type || 0
+ } catch (error) {
+ logger.error("鏃犵涓�鐢ㄦ埛绫诲瀷")
+ }
+ }
+ }
+
+ // 鏌ヨ绗簩鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤绫诲瀷
+ let secondUserType = dualAuthState.secondUserType || 0
+ if (dualAuthState.secondUserId && !secondUserType) {
+ let res = sqliteService.d1_person.findByUserId(dualAuthState.secondUserId)
+ if (res.length > 0) {
+ try {
+ secondUserType = JSON.parse(res[0].extra).type || 0
+ } catch (error) {
+ logger.error("鏃犵浜岀敤鎴风被鍨�")
+ }
+ }
+ }
+
+ // 鍒涘缓璁よ瘉璁板綍
+ const record = {
+ id: std.genRandomStr(16),
+ userId: dualAuthState.firstUserId,
+ userId2: dualAuthState.secondUserId || "",
+ type: "300", // 浜鸿劯璁よ瘉锛堝瓧绗︿覆鏍煎紡锛�
+ code: dualAuthState.firstUserFileName, // 浜鸿劯鎶撴媿鍥剧墖璺緞
+ result: 1, // 璁よ瘉澶辫触锛�0鎴愬姛锛�1澶辫触锛�
+ time: Math.floor(Date.now() / 1000), // 鏃堕棿鎴筹紙绉掞級
+ message: "鍙屼汉璁よ瘉瓒呮椂",
+ extra: JSON.stringify({ name: dualAuthState.firstUserName, idCard: dualAuthState.firstUserIdCard, type: firstUserType }),
+ extra2: dualAuthState.secondUserId ? JSON.stringify({ name: dualAuthState.secondUserName || "", idCard: dualAuthState.secondUserIdCard || "", type: secondUserType }) : "",
+ permissionId: firstUserType.toString(),
+ permissionId2: dualAuthState.secondUserId ? secondUserType.toString() : ""
+ }
+
+ // 淇濆瓨鍒版暟鎹簱
+ sqliteService.d1_pass_record.save(record)
+ logger.info(`[faceService]: 淇濆瓨鍙屼汉璁よ瘉瓒呮椂璁板綍: ${JSON.stringify(record)}`)
+ }
+
+ // 娓呴櫎璁よ瘉鐘舵��
+ clearDualAuthState()
+
+ // 鎾斁澶辫触鎻愮ず闊�
+ driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/verify_300_f.wav`)
+
+ // 璇煶鎻愮ず璁よ瘉澶辫触
+ // driver.alsa.ttsPlay("鍙屼汉璁よ瘉瓒呮椂锛岃璇佸け璐�")
+
+ // 瑙﹀彂璁よ瘉澶辫触浜嬩欢
+ bus.fire("showAccessResult", {
+ faceAuth: false,
+ gasConcentration: true,
+ accessAllowed: false,
+ message: "*鍙屼汉璁よ瘉瓒呮椂锛岃璇佸け璐�*"
+ })
+
+ // 瑙﹀彂閫氳澶辫触浜嬩欢锛岄�氱煡UI閲嶇疆
+ bus.fire("accessRes", false)
+
+
+ } catch (error) {
+ logger.error(`[faceService]: 澶勭悊鍙屼汉璁よ瘉瓒呮椂閿欒: ${error.message}`)
+ }
+}
+
+/**
+ * 澶勭悊鍙屼汉璁よ瘉閫昏緫
+ * @param {string} userId - 褰撳墠鐢ㄦ埛ID
+ * @param {string} userName - 褰撳墠鐢ㄦ埛濮撳悕
+ * @param {string} fileName - 浜鸿劯鍥剧墖鏂囦欢璺緞
+ */
+function handleDualAuth(userId, userName, fileName) {
+ try {
+ if (!dualAuthState.firstUserId) {
+ // 绗竴娆¤璇�
+ dualAuthState.firstUserId = userId
+ dualAuthState.firstUserName = userName
+ dualAuthState.firstUserFileName = fileName
+
+ // 鏌ヨ绗竴鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤璇佸彿鍜岃韩浠界被鍨�
+ let res = sqliteService.d1_person.findByUserId(userId)
+ if (res.length > 0) {
+ let idCard
+ let userType = 0
+ try {
+ idCard = JSON.parse(res[0].extra).idCard
+ userType = JSON.parse(res[0].extra).type || 0
+ } catch (error) {
+ logger.error("鏃犵涓�鐢ㄦ埛韬唤璇佸彿鎴栫被鍨�")
+ }
+ dualAuthState.firstUserIdCard = idCard
+ dualAuthState.firstUserType = userType
+ }
+
+ dualAuthState.startTime = Date.now()
+
+ // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+ if (dualAuthState.timeout) {
+ std.clearTimeout(dualAuthState.timeout)
+ }
+
+ // 璁剧疆1鍒嗛挓瓒呮椂
+ dualAuthState.timeout = std.setTimeout(() => {
+ // 瓒呮椂澶勭悊锛岃涓鸿璇佸け璐�
+ handleDualAuthTimeout()
+ }, 60000)
+
+ // 璇煶鎻愮ず-璇风浜岀敤鎴疯繘琛岃璇�
+ driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/user2.wav`)
+ } else {
+ // 绗簩娆¤璇�
+ if (userId !== dualAuthState.firstUserId) {
+ // 涓嶅悓鐢ㄦ埛锛岃璇侀�氳繃
+ // 鏌ヨ绗簩鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤璇佸彿鍜岃韩浠界被鍨�
+ let secondUserIdCard = ""
+ let secondUserType = 0
+ let res = sqliteService.d1_person.findByUserId(userId)
+ if (res.length > 0) {
+ try {
+ secondUserIdCard = JSON.parse(res[0].extra).idCard
+ secondUserType = JSON.parse(res[0].extra).type || 0
+ } catch (error) {
+ logger.error("鏃犵浜岀敤鎴疯韩浠借瘉鍙锋垨绫诲瀷")
+ }
+ }
+
+ // 淇濆瓨鍙屼汉璁よ瘉鐘舵�佷俊鎭紝鐢ㄤ簬UI鏇存柊
+ let dualAuthInfo = {
+ firstUserId: dualAuthState.firstUserId,
+ firstUserName: dualAuthState.firstUserName,
+ secondUserId: userId,
+ secondUserName: userName,
+ secondUserIdCard: secondUserIdCard,
+ secondUserType: secondUserType
+ }
+ // 淇濆瓨绗竴鐢ㄦ埛鐨勪汉鑴稿浘鐗囪矾寰�
+ let firstUserFileName = dualAuthState.firstUserFileName
+ // 璁剧疆璁よ瘉瀹屾垚鏍囧織
+ dualAuthState.authComplete = true
+ clearDualAuthState()
+
+ // 璇煶鎻愮ず-鍙屼汉璁よ瘉閫氳繃
+ driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/user2_s.wav`)
+
+ // 閫氳璁よ瘉澶勭悊锛屼紶閫掑弻浜鸿璇佷俊鎭�
+ bus.fire("access", { data: { type: "300", code: userId, dualAuthInfo: dualAuthInfo, authComplete: true, firstUserFileName: firstUserFileName }, fileName: fileName })
+ } else {
+ // 鍚屼竴鐢ㄦ埛锛岄噸鏂板紑濮�
+ dualAuthState.firstUserId = userId
+ dualAuthState.firstUserName = userName
+
+ // 鏌ヨ鐢ㄦ埛鐨勮缁嗕俊鎭紝鑾峰彇韬唤璇佸彿鍜岃韩浠界被鍨�
+ let idCard
+ let userType = 0
+ let res = sqliteService.d1_person.findByUserId(userId)
+ if (res.length > 0) {
+ try {
+ idCard = JSON.parse(res[0].extra).idCard
+ userType = JSON.parse(res[0].extra).type || 0
+ } catch (error) {
+ logger.error("鏃犵敤鎴疯韩浠借瘉鍙锋垨绫诲瀷")
+ }
+ dualAuthState.firstUserIdCard = idCard
+ dualAuthState.firstUserType = userType
+ }
+
+ dualAuthState.startTime = Date.now()
+
+ // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+ if (dualAuthState.timeout) {
+ std.clearTimeout(dualAuthState.timeout)
+ }
+
+ // 閲嶆柊璁剧疆1鍒嗛挓瓒呮椂
+ dualAuthState.timeout = std.setTimeout(() => {
+ // 瓒呮椂澶勭悊锛岃涓鸿璇佸け璐�
+ handleDualAuthTimeout()
+ }, 60000)
+
+ // 璇煶鎻愮ず-璇风浜岀敤鎴疯繘琛岃璇�
+ driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/user2.wav`)
+ }
+ }
+ } catch (error) {
+ logger.error(`[faceService]: 澶勭悊鍙屼汉璁よ瘉閿欒: ${error.message}`)
+ // 娓呴櫎璁よ瘉鐘舵��
+ clearDualAuthState()
+ }
+}
+/**
+ * 浜鸿劯娉ㄥ唽閿欒鏋氫妇
+ * 鍖呭惈鍚勭娉ㄥ唽澶辫触鐨勯敊璇爜鍜屽搴旂殑閿欒淇℃伅
+ */
+faceService.regErrorEnum = {
+ "callback": {
+ title: "娉ㄥ唽鍥炶皟鐘舵�佹灇涓�",
+ "-1": "faceService.contrastFailure", // 瀵规瘮澶辫触
+ "-2": "faceService.scalingFailure", // 缂╂斁澶辫触
+ "-3": "faceService.failedToSavePicture", // 淇濆瓨鍥剧墖澶辫触
+ "-4": "faceService.convertToBase64Fail", // 杞崲涓篵ase64澶辫触
+ },
+ "feature": {
+ title: "鐗瑰緛鍊兼敞鍐岀姸鎬佹灇涓�",
+ "-1": "faceService.base64DecodingFail", // base64瑙g爜澶辫触
+ "-10": "faceService.contrastFailure", // 瀵规瘮澶辫触
+ "-11": "faceService.similarityOverheight", // 鐩镐技搴﹁繃楂�
+ },
+ "picture": {
+ title: "鍥剧墖娉ㄥ唽鐘舵�佹灇涓�",
+ "-1": "faceService.fileDoesNotExist", // 鏂囦欢涓嶅瓨鍦�
+ "-2": "faceService.theImageFormatIsNotSupported", // 鍥剧墖鏍煎紡涓嶆敮鎸�
+ "-3": "faceService.pictureReadFailure", // 鍥剧墖璇诲彇澶辫触
+ "-4": "faceService.thePictureSizeDoesNotMatch", // 鍥剧墖灏哄涓嶅尮閰�
+ "-5": "faceService.imageParsingFailure", // 鍥剧墖瑙f瀽澶辫触
+ "-6": "faceService.imageYUVProcessingFailed", // 鍥剧墖YUV澶勭悊澶辫触
+ "-7": "faceService.failedToConvertJpegToImage", // JPEG杞崲涓哄浘鐗囧け璐�
+ "-8": "faceService.faceInformationExtractionFailed", // 浜鸿劯淇℃伅鎻愬彇澶辫触
+ "-9": "faceService.theFaceIsNotUnique", // 浜鸿劯涓嶅敮涓�
+ "-10": "faceService.contrastFailure", // 瀵规瘮澶辫触
+ "-11": "faceService.similarityOverheight", // 鐩镐技搴﹁繃楂�
+ }
+}
+
+export default faceService
\ No newline at end of file
--
Gitblit v1.9.3