From 123e5ac13ef36e2f1c0ec1274e6018eba2cfdd34 Mon Sep 17 00:00:00 2001 From: zhangz Date: Wed, 10 Dec 2025 15:43:10 +0800 Subject: [PATCH] 手机端新增人脸登陆; --- src/mobile/login/LoginMobile.js | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/mobile/login/LoginMobile.less | 6 ++++++ 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/mobile/login/LoginMobile.js b/src/mobile/login/LoginMobile.js index d836302..fe6c3c6 100644 --- a/src/mobile/login/LoginMobile.js +++ b/src/mobile/login/LoginMobile.js @@ -13,7 +13,8 @@ import * as commonServices from '../../services/services'; import * as commonFunc from '../../components/Common/commonFunc'; import AppUtil from '../../utils/AppUtil'; import * as commonUtils from '../../utils/utils'; - +// import VConsole from 'vconsole'; +// let vConsole; // eslint-disable-next-line prefer-destructuring const alert = Modal.alert; @@ -124,8 +125,13 @@ class LoginMobile extends React.Component { ); } } + // vConsole = new VConsole(); } + // componentWillUnmount() { + // vConsole.destroy(); + // } + onChange = (name, newValue) => { if (name === 'username') { this.setState({ username: newValue }); @@ -138,7 +144,82 @@ class LoginMobile extends React.Component { loginCompany: value, }); } - handleLogin = async () => { + + takeTenPhotos = () => { + if (!window.plus) { + return Promise.reject(new Error('请在 HBuilder 打包的 App 中运行')); + } + + return new Promise((resolve, reject) => { + // 调用系统相机拍照(尽量指定前置) + plus.camera.getCamera(1).captureImage( + (imagePath) => { + // 直接用 FileReader 读取逻辑路径(如 _doc/...),无需 resolve + const reader = new plus.io.FileReader(); + reader.onload = (e) => { + const img = new Image(); + img.onload = () => { + const canvas = document.createElement('canvas'); + canvas.width = 268; + canvas.height = 214; + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, 268, 214); + // 转为 JPEG,质量 0.85,去掉前缀 + const base64 = canvas.toDataURL('image/jpeg', 0.85).split(',')[1]; + resolve(base64); + }; + img.onerror = () => reject(new Error('图片解析失败')); + + img.src = e.target.result; // Data URL 安全加载 + }; + reader.onerror = (e) => reject(new Error('读取照片失败: ' + e.target.error.message)); + + plus.io.resolveLocalFileSystemURL(imagePath, (entry) => { + entry.file((file) => { + reader.readAsDataURL(file.fullPath); // 关键:直接读逻辑路径 + + }) + }); + }, + (error) => { + reject(new Error('拍照失败: ' + error.message)); + }, + { + filename: `_doc/camera/face_${Date.now()}.jpg`, + format: 'jpg' + } + ); + }); + }; + + handleFaceLogin = () => { + this.takeTenPhotos() + .then(base64List => { + // 这里可以上传到你的 face/detectFaces 接口 + const url = `${commonConfig.face_host}/face/faceSearch`; + commonServices.postValueService(null, [{ + image: base64List, + image_type: "BASE64", + face_field: "age", + option: "COMMON" + }], url).then(({ data: dataReturn }) => { + // console.log('=====dataReturn', dataReturn); + if (dataReturn.code === 1) { + const value = {}; + value.sEmployeeNo = dataReturn.dataset.rows[0].sEmployeeNo; + value.sParentId = dataReturn.dataset.rows[0].sBrandsId; + value.sId = dataReturn.dataset.rows[0].sSubsidiaryId; + this.handleLogin(value); + } else { + Toast.fail(dataReturn.msg); + } + }) + }) + .catch(err => { + console.error('拍摄过程出错:', err); + }); + } + handleLogin = async (valueBase) => { const { dispatch, app } = this.props; const { loginCompany, companys } = this.state; let sParentId = ''; @@ -150,12 +231,16 @@ class LoginMobile extends React.Component { return; } this.props.form.validateFields(async () => { - const value = {}; - value.username = this.state.username; - value.password = this.state.userpwd; - value.sParentId = this.state.sParentId; - // value.company = this.state.loginCompany; - value.sId = this.state.sId; + let value = {}; + if (valueBase) { + value = valueBase; + } else { + value.username = this.state.username; + value.password = this.state.userpwd; + value.sParentId = this.state.sParentId; + // value.company = this.state.loginCompany; + value.sId = this.state.sId; + } const url = `${commonConfig.server_host}userlogin/${sParentId}/${loginCompany}?sLoginType=phoneLogin`; const dataReturn = (await commonServices.postValueService(null, value, url)).data; if (dataReturn.code === 1) { @@ -200,6 +285,7 @@ class LoginMobile extends React.Component { let sLanguage = commonUtils.isNotEmptyArr(companys) ? companys[0].sLanguage : 'sChinese'; const settingTitle = sLanguage === 'sEnglish' ? 'server settings' :'服务器设置'; const loginTitle = sLanguage === 'sEnglish' ? 'Login' :'登录'; + const loginFaceTitle = sLanguage === 'sEnglish' ? 'Face Login' :'人脸登录'; const pleaseInputUser = sLanguage === 'sEnglish' ? 'please Input User' :'请输入用户'; const pleaseInputPassword = sLanguage === 'sEnglish' ? 'please Input Password' :'请输入密码'; @@ -263,6 +349,9 @@ class LoginMobile extends React.Component { + {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}