/**
|
* 屏幕管理模块
|
* 负责屏幕显示、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
|