/** * 屏幕管理模块 * 负责屏幕显示、UI控制、用户界面管理等功能 */ import dxui from '../dxmodules/dxUi.js' import dxMap from '../dxmodules/dxMap.js' import log from '../dxmodules/dxLogger.js' import net from '../dxmodules/dxNet.js' import viewUtils from './view/viewUtils.js' import i18n from './view/i18n.js' import grainService from './service/grainService.js' import sqliteService from './service/sqliteService.js' import pinyin from './view/pinyin/pinyin.js' import mainView from './view/mainView.js' import idleView from './view/idleView.js' import topView from './view/topView.js' import appView from './view/appView.js' import pwdView from './view/pwdView.js' import emergencyPwdView from './view/emergencyPwdView.js' import newPwdView from './view/config/newPwdView.js' import identityVerificationView from './view/config/identityVerificationView.js' import configView from './view/config/configView.js' import cloudCertView from './view/config/menu/cloudCertView.js' import doorControlView from './view/config/menu/doorControlView.js' import helpView from './view/config/menu/helpView.js' import networkSettingView from './view/config/menu/networkSettingView.js' import systemSettingView from './view/config/menu/systemSettingView.js' import deviceInfoView from './view/config/menu/deviceInfoView.js' import factoryTestView from './view/config/menu/factoryTestView.js' import localUserView from './view/config/menu/localUserView.js' import recordQueryView from './view/config/menu/recordQueryView.js' import voiceBroadcastView from './view/config/menu/voiceBroadcastView.js' import dockingSettingView from './view/config/menu/dockingSetting.js' import localUserAddView from './view/config/menu/localUser/localUserAddView.js' import faceEnterView from './view/config/menu/localUser/faceEnterView.js' import displaySettingView from './view/config/menu/systemSetting/displaySettingView.js' import faceRecognitionSettingView from './view/config/menu/systemSetting/faceRecognitionSettingView.js' import swipeCardRecognitionSettingView from './view/config/menu/systemSetting/swipeCardRecognitionSettingView.js' import passLogSettingView from './view/config/menu/systemSetting/passLogSettingView.js' import passwordOpenDoorSettingView from './view/config/menu/systemSetting/passwordOpenDoorSettingView.js' import passwordManagementView from './view/config/menu/systemSetting/passwordManagementView.js' import timeSettingView from './view/config/menu/systemSetting/timeSettingView.js' import systemInfoView from './view/config/menu/deviceInfo/systemInfoView.js' import dataCapacityInfoView from './view/config/menu/deviceInfo/dataCapacityInfoView.js' import recordQueryDetailView from './view/config/menu/recordQuery/recordQueryDetailView.js' import std from '../dxmodules/dxStd.js' import bus from '../dxmodules/dxEventBus.js' import driver from './driver.js' import config from '../dxmodules/dxConfig.js' import common from '../dxmodules/dxCommon.js' import configService from './service/configService.js' import codeService from './service/codeService.js' import face from '../dxmodules/dxFace.js' import faceService from './service/faceService.js' /** * 屏幕管理对象 */ const screen = {} /** * 屏幕尺寸配置 */ screen.screenSize = { width: 800, height: 1280 } /** * UI上下文 */ const context = {} /** * 初始化屏幕管理模块 * 初始化所有UI组件、设置语言、启动屏保计时器等 * 注意:在main.js中调用,只允许调用一次 */ screen.init = function () { const loadMethod = dxui.loadMain dxui.loadMain = function (view) { if (screen.screenNow && screen.screenNow.id == view.id) { return } screen.screenNow = view pinyin.hide(true) loadMethod.call(dxui, view) } dxui.init({ orientation: 0 }, context); // 初始化所有组件 pinyin.init(800, 400) viewUtils.confirmInit() mainView.init() idleView.init() topView.init() appView.init() pwdView.init() emergencyPwdView.init() newPwdView.init() identityVerificationView.init() configView.init() cloudCertView.init() doorControlView.init() helpView.init() networkSettingView.init() systemSettingView.init() deviceInfoView.init() factoryTestView.init() localUserView.init() recordQueryView.init() voiceBroadcastView.init() dockingSettingView.init() localUserAddView.init() faceEnterView.init() displaySettingView.init() faceRecognitionSettingView.init() swipeCardRecognitionSettingView.init() passLogSettingView.init() passwordOpenDoorSettingView.init() passwordManagementView.init() timeSettingView.init() systemInfoView.init() dataCapacityInfoView.init() recordQueryDetailView.init() // 设置语言 // i18n.setLanguage("en-US") i18n.setLanguage(config.get("base.language")) dxui.loadMain(mainView.screenMain) // dxui.loadMain(networkSettingView.screenMain) // 启动屏保计时器 idleTimerStart() // bus事件 busEvents() // 实时获取点击坐标 getClickPoint() // 隐藏键盘 hidePinyin() // 人脸跟踪框 faceTrackingBox() } /** * 人脸跟踪框处理 * 定期获取人脸跟踪数据并更新跟踪框显示 */ function faceTrackingBox() { std.setInterval(() => { let data = driver.face.getTrackingBox() try { if (data && typeof data === 'string') { // 检查数据是否是有效的JSON字符串 try { data = JSON.parse(data) // 最大10个人 if (data.type == "track" && data.faces && data.faces.length <= 10) { for (let i = 0; i < data.faces.length; i++) { let item = data.faces[i] if (item && item.rect_render && item.rect_render.length === 4) { screen.trackUpdate({ w: item.rect_render[2] - item.rect_render[0], h: item.rect_render[3] - item.rect_render[1], x: item.rect_render[0], y: item.rect_render[1] }, item.id, item.is_living) } } } } catch (parseError) { log.info('screen.faceTrackingBox: 无效的JSON数据:', data); log.error("screen.faceTrackingBox: JSON解析错误:", parseError) } } } catch (error) { log.info('screen.faceTrackingBox:', data); log.error("screen.faceTrackingBox:", error) } }, 110) } /** * 点击坐标变化标记 */ let changedClickPoint /** * 上次点击坐标 */ let lastClickPoint = { x: 0, y: 0 } /** * 当前点击坐标 */ let clickPoint /** * 实时获取点击坐标 * 定期获取用户触摸屏幕的坐标位置 */ function getClickPoint() { const indev = NativeObject.APP.NativeComponents.NativeIndev std.setInterval(() => { clickPoint = { x: Math.abs(800 - indev.lvIndevGetPointVg().x), y: indev.lvIndevGetPointVg().y } if (lastClickPoint.x != clickPoint.x || lastClickPoint.y != clickPoint.y) { changedClickPoint = clickPoint } else { changedClickPoint = null } lastClickPoint = clickPoint }, 5) } /** * 隐藏拼音键盘 * 处理拼音键盘的显示和隐藏逻辑,当用户点击屏幕其他区域时自动隐藏键盘 */ function hidePinyin() { /** * 键盘显示时的点击坐标 */ let showPoint /** * 原始的隐藏方法 */ const hideMethod = pinyin.hide /** * 原始的显示方法 */ const showMethod = pinyin.show /** * 锁定标志,防止重复操作 */ let lock = false // 重写隐藏方法 pinyin.hide = function (isForce) { if (isForce) { hideMethod.call(pinyin) lock = false return } if (lock) { return } lock = true hideMethod.call(pinyin) lock = false } // 重写显示方法 pinyin.show = function (...args) { if (lock) { return } lock = true showMethod.call(pinyin, ...args) showPoint = clickPoint lock = false } // 定期检查是否需要隐藏键盘 std.setInterval(() => { if (showPoint && (Math.abs(showPoint.x - clickPoint.x) > 5 && Math.abs(showPoint.y - clickPoint.y) > 5)) { if (clickPoint.y < (1280 - (pinyin.getMode() == 1 ? 400 + 70 : 400))) { let defocus = dxMap.get("INPUT_KEYBOARD").get("defocus") if (defocus == "defocus") { dxMap.get("INPUT_KEYBOARD").del("defocus") showPoint = null pinyin.hide() } } } }, 5) } /** * 屏幕管理器类 * 负责屏幕状态管理,包括屏保和熄屏功能 */ class ScreenManager { /** * 构造函数 * @param {object} callbacks - 回调函数对象 */ constructor(callbacks = {}) { /** * 定时器对象 */ this.timers = { screenSaver: null, // 屏保定时器 screenOff: null // 熄屏定时器 }; /** * 配置对象 */ this.config = { screenSaverDelay: 0, // 屏保延迟(毫秒) screenOffDelay: 0 // 熄屏延迟(毫秒) }; /** * 回调函数 */ this.callbacks = { onScreenSaverStart: callbacks.onScreenSaverStart || (() => { }), onScreenSaverEnd: callbacks.onScreenSaverEnd || (() => { }), onScreenOff: callbacks.onScreenOff || (() => { }), onScreenOn: callbacks.onScreenOn || (() => { }) }; this.resetTimers = this.resetTimers.bind(this); } /** * 配置时间 * @param {number} screenSaverDelay - 屏保延迟(毫秒) * @param {number} screenOffDelay - 熄屏延迟(毫秒) */ configure({ screenSaverDelay = 0, screenOffDelay = 0 }) { this.config.screenSaverDelay = screenSaverDelay; this.config.screenOffDelay = screenOffDelay; this.resetTimers(); } /** * 重置定时器 * 清除现有定时器并设置新的定时器 */ resetTimers() { // 清除现有定时器 if (this.timers.screenSaver) { std.clearTimeout(this.timers.screenSaver); } if (this.timers.screenOff) { std.clearTimeout(this.timers.screenOff); } // 退出当前状态 this.exitScreenStates(); // 设置新的定时器 if (this.config.screenOffDelay > 0) { this.timers.screenOff = std.setTimeout(() => { this.enterScreenOff(); }, this.config.screenOffDelay); } // 只有当熄屏时间大于屏保时间时才设置屏保定时器 if (this.config.screenSaverDelay > 0 && (this.config.screenSaverDelay < this.config.screenOffDelay || this.config.screenOffDelay == 0)) { this.timers.screenSaver = std.setTimeout(() => { this.enterScreenSaver(); }, this.config.screenSaverDelay); } } /** * 进入屏保状态 */ enterScreenSaver() { const mapUI = dxMap.get("UI") if (!mapUI.get("isScreenOff")) { mapUI.put("isScreenSaver", true) this.callbacks.onScreenSaverStart(); } } /** * 进入熄屏状态 */ enterScreenOff() { const mapUI = dxMap.get("UI") mapUI.put("isScreenOff", true) mapUI.put("isScreenSaver", false) this.callbacks.onScreenOff(); } /** * 退出所有屏幕状态 */ exitScreenStates() { const mapUI = dxMap.get("UI") const previousState = { isScreenOff: mapUI.get("isScreenOff"), isScreenSaver: mapUI.get("isScreenSaver") }; mapUI.put("isScreenOff", false) mapUI.put("isScreenSaver", false) // 如果状态发生改变,触发相应回调 if (previousState.isScreenSaver) { this.callbacks.onScreenSaverEnd(); } if (previousState.isScreenOff) { this.callbacks.onScreenOn(); } } /** * 获取当前状态 * @returns {object} 当前屏幕状态 */ getState() { const mapUI = dxMap.get("UI") return { isScreenOff: mapUI.get("isScreenOff"), isScreenSaver: mapUI.get("isScreenSaver") }; } /** * 清理资源 * 清除所有定时器 */ destroy() { if (this.timers.screenSaver) { std.clearTimeout(this.timers.screenSaver); } if (this.timers.screenOff) { std.clearTimeout(this.timers.screenOff); } } } /** * 屏幕管理器实例 */ let screenManager /** * 启动屏保计时器 * 初始化屏幕管理器,设置屏保和熄屏时间,检测用户触摸 */ function idleTimerStart() { // 创建实例,传入回调函数 screenManager = new ScreenManager({ /** * 屏保开始回调 */ onScreenSaverStart: () => { screen.enterIdle() }, /** * 屏保结束回调 */ onScreenSaverEnd: () => { screen.exitIdle(true) }, /** * 熄屏回调 */ onScreenOff: () => { dxMap.get("screenOff").put("status", 1) // 停止人脸识别 driver.face.status(false) screen.screenNow.hide() topView.screenMain.hide() }, /** * 亮屏回调 */ onScreenOn: () => { screen.exitIdle(true) dxMap.get("screenOff").put("status", 0) // 恢复人脸识别 driver.face.status(true) screen.screenNow.show() topView.screenMain.show() // 退出熄屏时获取并更新气体浓度和状态信息 try { log.info('[screen]: 退出熄屏,获取气体浓度和状态信息') grainService.checkGasConcentration() grainService.checkDevConcentration() } catch (error) { log.error(`[screen]: 获取气体浓度和状态信息错误: ${error.message}`) } } }); // 配置时间(毫秒) screenManager.configure({ // screenSaverDelay: 10000, // 屏保 // screenOffDelay: 5000 // 熄屏 screenSaverDelay: config.get("base.screensaver") * 60 * 1000, // 屏保 screenOffDelay: config.get("base.screenOff") * 60 * 1000 // 熄屏 }); // 检测用户触摸 let touchCount = 0 std.setInterval(() => { let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime() if (count < touchCount) { screenManager.resetTimers(); } touchCount = count }, 100); } /** * 刷新屏幕管理器配置 * 更新屏保和熄屏时间配置 */ screen.screenManagerRefresh = function () { screenManager.configure({ screenSaverDelay: config.get("base.screensaver") * 60 * 1000, // 屏保 screenOffDelay: config.get("base.screenOff") * 60 * 1000 // 熄屏 }); screenManager.resetTimers(); } /** * 进入屏保定时器 */ let enterIdleTimer /** * 进入屏保 * 显示屏保界面 */ screen.enterIdle = function () { // 延迟1秒,防止进入屏保和退出屏保同时触发,1秒内没有触发退出屏保,则认为进入屏保 enterIdleTimer = std.setTimeout(() => { if (idleView.screenMain.isHide()) { viewUtils.confirmClose() dxui.loadMain(mainView.screenMain) idleView.screenMain.show() topView.changeTheme(false) } }, 1000) } /** * 退出屏保 * 隐藏屏保界面 * @param {boolean} isSelf - 是否由系统自身触发 */ screen.exitIdle = function (isSelf) { if (enterIdleTimer) { std.clearTimeout(enterIdleTimer) enterIdleTimer = null } if (!isSelf) { screenManager.resetTimers(); } if (!idleView.screenMain.isHide()) { idleView.screenMain.hide() } } /** * 屏幕循环处理 * 处理UI事件 * @returns {boolean} 处理结果 */ screen.loop = function () { return dxui.handler() } /** * 云证激活 * 激活电子身份证 * @param {string} code - 激活码 * @returns {number} 激活结果,0表示成功,非0表示失败 */ screen.nfcIdentityCardActivation = function (code) { return driver.eid.active(config.get("sys.sn"), config.get("sys.appVersion"), config.get("sys.mac"), code); } /** * 删除人员 * 删除用户信息、权限、凭证和人脸数据 * @param {object} user - 用户对象 * @returns {boolean} 删除结果 */ screen.deleteUser = function (user) { // 删除人员信息 sqliteService.d1_person.deleteByUserId(user.userId) // 删除权限信息 sqliteService.d1_permission.deleteByUserId(user.userId) // 删除凭证信息 sqliteService.d1_voucher.deleteByUserId(user.userId) // 删除人脸数据 let res = driver.face.delete(user.userId) return true } /** * 更新人员信息 * 更新用户信息、密码、卡片和人脸数据 * @param {object} user - 用户对象 * @returns {boolean|string} 更新结果,成功返回true,失败返回错误信息 */ screen.updateUser = function (user) { //修改人员信息 let res = sqliteService.d1_person.updatenameAndExtraByUserId(user.userId, user.name, JSON.stringify({ type: user.type, idCard: user.idCard })) if (res != 0) { return false } //处理凭证 let ret //处理密码凭证 if (user.pwd) { //判断库表是否存在这个凭证 let pwdData = sqliteService.d1_voucher.findByCodeAndType(user.pwd, "400"); if (pwdData.length > 0 && pwdData[0].userId != user.userId) { //存在不能添加返回失败 log.info("密码重复"); return "localUserAddView.failPwdRepeat" } //查询是否有密码凭证有更新没有新增 let countByuserIdAndType = sqliteService.d1_voucher.findByuserIdAndType(user.userId, "400"); if (countByuserIdAndType.length > 0) { ret = sqliteService.d1_voucher.updatecodeByuserIdAndtype(user.userId, "400", user.pwd) if (ret != 0) { return false } } else { //新增一个 ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "400", code: user.pwd, userId: user.userId }) if (ret != 0) { return false } } } else { //没有内容去数据库表删除一下 sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "400") } //处理卡片凭证 if (user.card) { //判断库表是否存在这个凭证 let cardData = sqliteService.d1_voucher.findByCodeAndType(user.card, "200"); if (cardData.length > 0 && cardData[0].userId != user.userId) { //存在不能添加返回失败 log.info("卡重复"); return "localUserAddView.failCardRepeat" } //查询是否有密码凭证有更新没有新增 let countByuserIdAndType = sqliteService.d1_voucher.countByuserIdAndType(user.userId, "200"); if (countByuserIdAndType > 0) { ret = sqliteService.d1_voucher.updatecodeByuserIdAndtype(user.userId, "200", user.card) if (ret != 0) { return false } } else { //新增一个 ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "200", code: user.card, userId: user.userId }) if (ret != 0) { return false } } } else { //没有内容去数据库表删除一下 sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "200") } //处理人脸凭证 if (user.face) { let findByuserIdAndType = sqliteService.d1_voucher.findByuserIdAndType(user.userId, "300"); if (findByuserIdAndType.length <= 0) { let ret = driver.face.registerFaceByPicFile(user.userId, user.face) log.info("2注册人脸,ret:", ret) if (ret != 0) { return faceService.regErrorEnum.picture[ret + ''] } //注册成功后需要吧原来图片移动到 user 对应目录下 let src = "/app/data/user/" + user.userId + "/register.jpg" std.ensurePathExists(src) common.systemBrief('mv ' + user.face + " " + src) //新增一个 ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "300", code: src, userId: user.userId }) if (ret != 0) { return false } } else { //原来有又传入 先删除后新增 if (findByuserIdAndType[0].code != user.face) { //删除老人脸 driver.face.delete(user.userId) //注册新人脸 let res = driver.face.registerFaceByPicFile(user.userId, user.face) log.info("3注册人脸,res:", res) if (res != 0) { return faceService.regErrorEnum.picture[res + ''] } let src = "/app/data/user/" + user.userId + "/register.jpg" std.ensurePathExists(src) //把临时目录人脸移动到 user 对应的文件夹中 common.systemBrief('mv ' + user.face + " " + src) ret = sqliteService.d1_voucher.updatecodeAndExtraByuserIdAndtype(user.userId, "300", src, JSON.stringify({ faceType: 0 })) } } } else { //没有内容去数据库表删除一下 sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "300") driver.face.delete(user.userId) common.systemBrief("rm -rf /app/data/user/" + user.userId) } return true } /** * 新增人员 * 添加新用户信息、密码、卡片和人脸数据 * @param {object} user - 用户对象 * @returns {boolean|string} 添加结果,成功返回true,失败返回错误信息 */ screen.insertUser = async function (user) { /** * 保存凭证 * @param {string} type - 凭证类型 * @param {string} code - 凭证代码 * @returns {boolean|string} 保存结果 */ const saveVoucher = async (type, code) => { // 检查卡片凭证是否重复 if (type == "200") { let cardData = sqliteService.d1_voucher.findByCodeAndType(code, "200"); if (cardData.length > 0 && cardData[0].userId != user.userId) { //存在不能添加返回失败 log.info("卡重复"); return "localUserAddView.failCardRepeat" } } // 当 type 为 "300" 时,首先调用特定方法检查是否可以继续保存凭证 if (type === "300") { let preCheckResult = await preSaveCheck(code); // 假设这是您提到的需要调用的方法 if (preCheckResult !== true) { // 如果预检查不通过,则直接返回 false return preCheckResult; } code = "/app/data/user/" + user.userId + "/register.jpg" } // 检查密码凭证是否重复 if (type == "400") { let pwdData = sqliteService.d1_voucher.findByCodeAndType(code, "400"); if (pwdData.length > 0 && pwdData[0].userId != user.userId) { //存在不能添加返回失败 log.info("密码重复"); return "localUserAddView.failPwdRepeat" } } let keyId = std.genRandomStr(32); let extra = type == 300 ? JSON.stringify({ faceType: 0 }) : JSON.stringify({}) let voucherRet = await sqliteService.d1_voucher.save({ keyId: keyId, type: type, code: code, userId: user.userId, extra: extra }); if (voucherRet != 0) { // 如果凭证保存失败,则删除已保存的用户信息及可能已保存的其他凭证 await sqliteService.d1_person.deleteByUserId(user.userId); await sqliteService.d1_voucher.deleteByUserId(user.userId); return false; } return true; }; /** * 保存前检查 * @param {string} code - 人脸图片路径 * @returns {boolean|string} 检查结果 */ async function preSaveCheck(code) { let ret = driver.face.registerFaceByPicFile(user.userId, code) log.info("1注册人脸,ret:", ret) if (ret != 0) { return faceService.regErrorEnum.picture[ret + ''] } //注册成功后需要吧原来图片移动到 user 对应目录下 let src = "/app/data/user/" + user.userId + "/register.jpg" std.ensurePathExists(src) common.systemBrief('mv ' + code + " " + src) return true; } let success = true; // 保存人脸凭证 if (success === true && user.face && !(success = await saveVoucher("300", user.face))); // 保存密码凭证 if (success === true && user.pwd && !(success = await saveVoucher("400", user.pwd))); // 保存卡片凭证 if (success === true && user.card && !(success = await saveVoucher("200", user.card))); if (success === true) { //{"id":"423","userId":"423","name":"微光互联","idCard":"123","pwd":"251574","card":"123"} //保存人员信息 let personRet = await sqliteService.d1_person.save({ userId: user.userId, name: user.name, extra: JSON.stringify({ type: user.type == 1 ? 1 : 0, idCard: user.idCard }) }); if (personRet != 0) { sqliteService.d1_voucher.deleteByUserId(user.userId); return "localUserAddView.failRepeat" } //新增一条永久权限 sqliteService.d1_permission.save({ permissionId: user.userId, userId: user.userId, timeType: 0 }) } else { await sqliteService.d1_voucher.deleteByUserId(user.userId); } return success; } /** * 获取本地人员信息 * 获取用户的凭证信息,包括身份证、卡片、密码和人脸数据 * @param {string} userId - 用户ID * @returns {object} 用户凭证信息 */ screen.getVoucher = function (userId) { // 获取用户信息 let person = sqliteService.d1_person.find({ userId: userId }); if (person.length < 0) { return } // 获取密码凭证 let pwd_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "400" })[0] || undefined // 获取卡片凭证 let card_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "200" })[0] || undefined // 获取人脸凭证 let face_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "300" })[0] || undefined // 获取身份证信息 let idCard_voucher try { idCard_voucher = JSON.parse(person[0].extra).idCard } catch (error) { } return { id: userId, idCard: idCard_voucher ? idCard_voucher : undefined, card: card_voucher ? card_voucher.code : undefined, pwd: pwd_voucher ? pwd_voucher.code : undefined, face: face_voucher ? face_voucher.code : undefined, type: JSON.parse(person[0].extra).type || 0 } } /** * 获取用户列表 * 根据条件查询用户列表,支持分页和搜索 * @param {number} page - 页码,默认0 * @param {number} size - 每页大小,默认6 * @param {string} userId - 用户ID,用于精确搜索 * @param {string} name - 用户姓名,用于模糊搜索 * @returns {object} 用户列表数据,包含分页信息 */ screen.getUsers = function (page = 0, size = 6, userId, name) { // 按用户ID或姓名搜索 if (userId || name) { // 按用户ID搜索 let user = sqliteService.d1_person.findByUserId(userId)[0] if (user) { user.id = user.userId return { data: [user], totalPage: 1, totalSize: 1, currentPage: 1 } } // 按用户姓名搜索 let users = sqliteService.d1_person.findByName(name) if (users && users.length > 0) { users.map(v => { v.id = v.userId }) /** * 数组分块 * @param {array} arr - 源数组 * @param {number} size - 块大小 * @returns {array} 分块后的数组 */ function chunkArray(arr, size) { // 如果数组为空或者大小为零,返回空数组 if (arr.length === 0 || size <= 0) { return []; } const result = []; // 使用循环遍历数组,并按照大小切割 for (let i = 0; i < arr.length; i += size) { result.push(arr.slice(i, i + size)); // slice 截取指定范围的元素 } return result; } const chunkedArray = chunkArray(users, size); return { data: chunkedArray[page], totalPage: Math.ceil(users.length / size), totalSize: users.length, currentPage: page + 1 } } return { data: [], totalPage: 0, totalSize: 0, currentPage: 1 } } // 获取所有用户 let userCount = sqliteService.d1_person.count() let users = sqliteService.d1_person.findOrderByUserIdAsc({ page, size }) if (users.length > 0) { users.forEach(element => { element.id = element.userId }); } // 总页数 let totalPage = Math.ceil(userCount / size) return { data: users, totalPage: totalPage, totalSize: userCount, currentPage: page + 1 } } /** * 获取通行记录 * 获取用户通行记录,支持分页 * @param {number} page - 页码,默认0 * @param {number} size - 每页大小,默认6 * @returns {object} 通行记录数据,包含分页信息 */ screen.getPassRecord = function (page = 0, size = 6) { let passCount = sqliteService.d1_pass_record.count() let datas = sqliteService.d1_pass_record.findOrderByTimeDesc({ page, size }) // 总页数 let totalPage = Math.ceil(passCount / size) return { data: datas, totalPage: totalPage, totalSize: passCount, currentPage: page + 1 } } /** * 人脸录入开始 * 开始人脸录入,UI控制 * @param {string} userId - 用户ID */ screen.faceEnterStart = function (userId) { dxMap.get("UI").put("faceEnterStart", userId) driver.face.status(1) driver.face.mode(1) } /** * 人脸录入结束 * 结束人脸录入,UI控制 */ screen.faceEnterEnd = function () { dxMap.get("UI").del("faceEnterStart") driver.face.status(0) // driver.face.mode(0) } /** * 获取卡号开始 * 开始获取卡号,UI控制 */ screen.getCardStart = function () { dxMap.get("UI").put("getCardStart", true) } /** * 获取卡号结束 * 结束获取卡号,UI控制 */ screen.endCardEnd = function () { dxMap.get("UI").del("getCardStart") } /** * 开启人脸识别 * 开始人脸识别功能 */ screen.faceRecgStart = function () { driver.face.status(1) driver.face.mode(0) } /** * 人脸识别暂停 * 暂停人脸识别功能 */ screen.faceRecgPause = function () { driver.face.status(0) } /** * 人脸录入结果 * 处理人脸录入结果 * @param {string} facePic - 人脸图片路径 */ screen.faceEnterResult = function (facePic) { if (facePic) { faceEnterView.successFlag = true // 成功,显示人脸照片 localUserAddView.addFace(facePic) dxui.loadMain(localUserAddView.screenMain) faceEnterView.backCb() } else { // 失败,报错 faceEnterView.timeout() } } /** * 非识别页面人脸认证开始 * 开始人脸认证,UI控制 */ screen.faceAuthStart = function () { dxMap.get("UI").put("faceAuthStart", "Y") driver.face.status(1) driver.face.mode(0) } /** * 非识别页面人脸认证结束 * 结束人脸认证,UI控制 */ screen.faceAuthEnd = function () { dxMap.get("UI").del("faceAuthStart") driver.face.status(0) } /** * 非识别页面人脸认证结果 * 处理人脸认证结果 * @param {boolean} bool - 认证结果,true表示成功,false表示失败 */ screen.faceAuthResult = function (bool) { if (bool) { // 成功,进入设置菜单 driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recg_s.wav`) dxui.loadMain(configView.screenMain) } else { // 失败,报错 driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recg_f.wav`) identityVerificationView.statusPanel.fail() } } /** * 保存配置 * 保存系统配置 * @param {object} configAll - 配置对象 * @returns {boolean} 保存结果 */ screen.saveConfig = function (configAll) { // 直接调用配置验证和保存函数 return configService.configVerifyAndSave(configAll) } /** * 获取配置 * 获取系统配置 * @returns {object} 配置对象 */ screen.getConfig = function () { let config1 = config.getAll() return config1 } /** * 密码通行 * 使用密码进行通行验证 * @param {string} pwd - 密码 * @returns {boolean} 验证结果,true表示成功,false表示失败 */ screen.pwdAccess = function (pwd) { // 检查数据库中的应急开仓密码 try { const passwords = sqliteService.d1_emergency_password.findAll({ status: 1 }) for (let i = 0; i < passwords.length; i++) { if (passwords[i].password === pwd) { return true } } } catch (error) { logger.error('检查应急开仓密码失败:', error) } // 其他密码验证逻辑 bus.fire("access", { data: { type: "400", code: pwd } }) return false } /** * 切换网络类型 * 切换网络连接类型 * @param {object} data - 网络类型数据 */ screen.switchNetworkType = function (data) { bus.fire("switchNetworkType", data) } /** * 获取WiFi列表 * 获取可用的WiFi网络列表 */ screen.netGetWifiSsidList = function () { bus.fire("netGetWifiSsidList") } /** * WiFi列表数据 * 处理WiFi列表数据 * @param {array} data - WiFi列表数据 */ screen.netWifiSsidList = function (data) { if (data.length == 0 && config.get("net.type") == 2) { //无线网 std.setTimeout(() => { screen.netGetWifiSsidList() }, 1000) return } networkSettingView.wifiListData = data networkSettingView.wifiList.refresh() } /** * 连接WiFi * 连接到指定的WiFi网络 * @param {string} ssid - WiFi名称 * @param {string} psk - WiFi密码 * @returns {boolean} 连接结果 */ screen.netConnectWifiSsid = function (ssid, psk) { return driver.net.netConnectWifiSsid(ssid, psk) } /** * 获取卡号 * 处理获取到的卡号 * @param {string} card - 卡号 */ screen.getCard = function (card) { localUserAddView.cardBoxInput.text(card) } /** * 事件总线事件处理 * 注册和处理系统事件 */ function busEvents() { // 网络状态 bus.on('netStatus', (data) => { console.log(JSON.stringify(data)); let type = config.get("net.type") if (data.connected) { let ip = net.getModeByCard(type).param.ip mainView.overlayIpLbl.text("IP:" + ip) config.setAndSave("net.ip", ip) config.setAndSave("net.mac", net.getMacaddr(type)) topView.ethConnectState(true, type) networkSettingView.netInfo[10].label.dataI18n = "networkSettingView.networkConnected" } else { topView.ethConnectState(false, type) networkSettingView.netInfo[10].label.dataI18n = "networkSettingView.networkUnconnected" } i18n.refreshObj(networkSettingView.netInfo[10].label) }) // mqtt连接状态 bus.on('mqttStatus', (data) => { if (data == "connected") { topView.mqttConnectState(true) } else { topView.mqttConnectState(false) } }) // 人脸录入开始 bus.on("beginAddFace", screen.beginAddFace) // 人脸录入结果 bus.on("faceEnterResult", screen.faceEnterResult) // 退出屏保 bus.on("exitIdle", screen.exitIdle) // 获取WiFi列表 - 移除事件监听器,避免无限循环 // 获取卡号 bus.on("getCard", screen.getCard) // 人脸认证结果 bus.on("faceAuthResult", screen.faceAuthResult) // 通行结果 bus.on("accessRes", screen.accessRes) // 跟踪更新 // bus.on("trackUpdate", screen.trackUpdate) // 隐藏SN bus.on("hideSn", screen.hideSn) // 切换语言 bus.on("changeLanguage", screen.changeLanguage) // 隐藏IP bus.on("hideIp", screen.hideIp) // 刷新屏幕管理器 bus.on("screenManagerRefresh", screen.screenManagerRefresh) // WiFi列表数据 bus.on("netWifiSsidList", screen.netWifiSsidList) // APP模式 bus.on("appMode", screen.appMode) // 升级 bus.on("upgrade", screen.upgrade) // 卡片重置 // bus.on("cardReset", screen.cardReset) // 跟踪结果 bus.on("trackResult", screen.trackResult) bus.on("showAccessResult", screen.showAccessResult) } /** * 卡片重置定时器 */ let setTimeout /** * 卡片重置 * 处理卡片重置逻辑 * @param {object} msg - 消息对象 */ screen.cardReset = function (msg) { if (msg.type == 2 && msg.status == 3) { setTimeout = std.setTimeout(() => { driver.net.cardReset() }, 30 * 1000); } else { if (setTimeout) { std.clearTimeout(setTimeout) } } } /** * 开始注册人脸 * 处理人脸注册开始逻辑 * @param {object} data - 人脸数据对象 */ screen.beginAddFace = function (data) { log.info('screen.beginAddFace', JSON.stringify(data)); if (!data.fileName) { return screen.faceEnterResult() } driver.alsa.play(`/app/code/resource/${config.get("base.language") == "CN" ? "CN" : "EN"}/wav/recognition_s.wav`) faceEnterView.statusPanel.success("faceEnterView.recogSuccess") // 保存图片到本地 let src = `/app/data/user/register.jpg` common.systemBrief(`mv ${data.fileName} ${src}`) common.systemBrief(`rm -rf /app/data/user/temp/*`) screen.faceEnterResult(src) } /** * 通行结果 * 处理通行成功或失败的结果 * @param {boolean} bool - 通行结果,true表示成功,false表示失败 */ screen.accessRes = function (bool) { if (bool) { if (mainView.smallStatusPanel && mainView.smallStatusPanel.success) { mainView.smallStatusPanel.success() } } else { if (mainView.smallStatusPanel && mainView.smallStatusPanel.fail) { mainView.smallStatusPanel.fail() } } } /** * 切换APP模式 * 切换应用程序显示模式(标准模式或简洁模式) * @param {number} mode - 模式值,0表示标准模式,1表示简洁模式 */ screen.appMode = function (mode) { if (mode == 0) { // 切换到标准模式 } else if (mode == 1) { // 切换到简洁模式 } } /** * 更新人脸跟踪框 * 更新人脸跟踪框的位置和状态 * @param {object} data - 坐标信息 * @param {number} id - face_id,用于关联识别姓名用 * @param {boolean} isLiving - 是否活体 */ screen.trackUpdate = function (data, id, isLiving) { let item = mainView.trackFaces[0] for (let i = 0; i < 10; i++) { let ele = mainView.trackFaces[i] if (ele.face_id == id) { item = ele break } } item.face_id = id if (item && item.timer) { std.clearTimeout(item.timer) item.timer = null } item.timer = std.setTimeout(() => { item.trackFace.hide() // item.trackFaceName.hide() if (item.timer) { std.clearTimeout(item.timer) item.timer = null } }, 300) let edge = data.w > data.h ? data.w : data.h let offset = Math.abs(data.w - data.h) / 2 item.trackFace.show() item.trackFace.setSize(edge, edge) item.trackFace.radius(edge / 2) if (data.w > data.h) { item.trackFace.setPos(data.x, data.y - offset) } else { item.trackFace.setPos(data.x - offset, data.y) } item.trackFaceName.text(" ") if (item.result && item.result.result === true && item.result.id == id) { item.trackFace.setBorderColor(viewUtils.color.success) let user = sqliteService.d1_person.findByUserId(item.result.userId)[0] item.trackFaceName.text(user ? user.name : "") } else if (item.result && item.result.result === false && item.result.id == id) { item.trackFace.setBorderColor(viewUtils.color.fail) } else if (isLiving) { item.trackFace.setBorderColor(0xf3e139) } else { item.trackFace.setBorderColor(0xffffff) } } /** * 认证结果 * 处理人脸识别认证结果 * @param {object} data - 认证结果数据 */ screen.trackResult = function (data) { for (let i = 0; i < 10; i++) { let ele = mainView.trackFaces[i] if (ele.face_id == data.id) { ele.result = data return } } } /** * 隐藏SN按钮 * 控制SN按钮的显示和隐藏 * @param {boolean} bool - 是否显示,true表示显示,false表示隐藏 */ screen.hideSn = function (bool) { if (bool) { mainView.bottomSnBtn.show() } else { mainView.bottomSnBtn.hide() } } /** * 隐藏IP标签 * 控制IP标签的显示和隐藏 * @param {boolean} bool - 是否显示,true表示显示,false表示隐藏 */ screen.hideIp = function (bool) { // 不再需要此函数,因为IP信息现在显示在半透明覆盖图层中 } /** * 隐藏底部框 * 控制底部框的显示和隐藏 * @param {boolean} bool - 是否显示,true表示显示,false表示隐藏 */ screen.hideBottomBox = function (bool) { if (bool) { mainView.bottomBox.hide() } else { mainView.bottomBox.show() } } /** * 切换语言 * 切换系统语言设置 */ screen.changeLanguage = function () { i18n.setLanguage(screen.getConfig()['base.language']) } /** * 升级提示 * 显示系统升级提示信息 * @param {object} data - 升级信息对象,包含title和content */ screen.upgrade = function (data) { const { title, content } = data viewUtils.confirmOpen(title, content) } /** * 显示通行结果弹窗 * @param {object} data - 通行结果数据 * @param {boolean} data.faceAuth - 人脸识别是否通过 * @param {boolean} data.gasConcentration - 气体浓度是否合格 * @param {boolean} data.accessAllowed - 是否允许通行 * @param {string} data.message - 弹窗消息 */ screen.showAccessResult = function (data) { // // 显示状态面板,3秒后自动关闭 // if (data.accessAllowed) { // mainView.statusPanel.success(data.message) // } else { // mainView.statusPanel.fail(data.message) // } // 显示小型状态面板,3秒后自动关闭 if (data.accessAllowed) { mainView.smallStatusPanel.success(data.message) } else { mainView.smallStatusPanel.fail(data.message) } } export default screen