Files
fe_service_ebtp_frontend/src/pages/userformal/login/index.tsx

794 lines
27 KiB
TypeScript
Raw Normal View History

2022-08-17 17:21:01 +08:00
import React, { useEffect, useState, useRef } from 'react';
2022-09-07 16:20:59 +08:00
import { Form, Button, Input, Row, Col, Modal, Spin, message, Tabs } from 'antd';
2022-10-24 17:06:53 +08:00
import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons';
2022-03-10 14:24:13 +08:00
import './style.less';
import { changePass, showFaceTab } from './service';
2022-03-10 14:24:13 +08:00
import logo from '@/images/login/logoPic.png';
2022-09-02 16:10:56 +08:00
import { refreshTokenApi, ZjfakeAccountLogin, ZjfakeFaceLogin } from '@/services/login';
2022-03-10 14:24:13 +08:00
import { history } from 'umi';
import cookie from 'react-cookies';
import moment from 'moment';
2022-08-17 17:21:01 +08:00
import FrameFaceLogin from '../faceLogin/FrameFaceLogin';
2022-10-28 17:23:46 +08:00
import LivingNotIE from './living.min.js';
2022-10-24 17:06:53 +08:00
import { _KJUR } from './jsrsasign-latest-all-min';
import { time } from 'echarts';
import request from '@/utils/request';
2022-03-10 14:24:13 +08:00
const layout = {
labelCol: { span: 7 },
wrapperCol: { span: 13 },
};
2022-09-02 16:10:56 +08:00
export interface RgbParams {
type: string;
image: string;
}
2022-03-10 14:24:13 +08:00
const Index: React.FC<{}> = () => {
const [form] = Form.useForm();
2022-09-07 16:20:59 +08:00
const [form2] = Form.useForm();
2022-03-10 14:24:13 +08:00
const [imgUrl, setImgUrl] = useState<any>('');
const [tmpToken, setTmpToken] = useState<any>('');
const [imgUrlEdit, setImgUrlEdit] = useState<any>('');
2022-03-10 14:24:13 +08:00
const remainingTime = 3 //刷新token的剩余时间单位小时
const [changeForm] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState<boolean>(false)
const [spinning, setSping] = useState<boolean>(false);//加载遮罩
2022-08-17 17:21:01 +08:00
const video = useRef();
const whetherIE = useRef<boolean>(false);
const mediaStreamTrack = useRef<any>();
2022-09-07 16:20:59 +08:00
const { TabPane } = Tabs;
const [submitLoading, setSubmitLoading] = useState<boolean>(false);
2022-12-30 15:27:59 +08:00
const [faceLoginDisable, setFaceLoginDisable] = useState<boolean>(false);
const [faceLoginShow, setFaceLoginShow] = useState<boolean>(false);
2022-10-28 17:23:46 +08:00
const lv = useRef<LivingNotIE>();
2022-10-24 17:06:53 +08:00
const [timerShow, setTimeShow] = useState<boolean>(false);
const [itemShow, setItemShow] = useState<boolean>(false);
const [action, setAction] = useState<number>(1);
const [timer, setTimer] = useState<number>(10000);
const urlRef = useRef<any>("");
2022-10-24 17:06:53 +08:00
/**
* token
*/
2022-12-30 15:27:59 +08:00
const setLiveDetectToken = () => {
let appKey = 'nkYy3g1yT0alE8pF6a1UTC4I'
2022-10-24 17:06:53 +08:00
let appSecrect = 'L30zHpTyAtTlY7tTCpbzdxxKCQgwWIQL'
// Header
var header = {
typ: "JWT", // 声明类型
alg: "HS256" // 声明加密的算法 通常直接使用 HMAC SHA256
};
var payload = {
iss: appKey,
iat: moment().unix(),
exp: moment()
.add(29, "minutes")
.unix()
};
var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(payload);
var sJWT = _KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {
utf8: appSecrect,
});
console.log(sJWT);
return sJWT;
};
/**
*
*/
const liveDetectStart = () => {
liveDetectStop();
2022-12-30 15:27:59 +08:00
let _lv = new LivingNotIE(null, {
2022-10-24 17:06:53 +08:00
timer: 10000,
2022-12-30 15:27:59 +08:00
action: [1, 3, 2],
2022-10-24 17:06:53 +08:00
token: setLiveDetectToken(),
2022-12-30 15:27:59 +08:00
proxy: '/living/api',
getFacePicture: () => {
2022-10-24 17:06:53 +08:00
return getLiveDetectFile()
},
//开始活体检测此时token已鉴权成功
2022-12-30 15:27:59 +08:00
onDetectStart: () => {
2022-10-24 17:06:53 +08:00
setSubmitLoading(true);
},
//每轮检测开始
2022-12-30 15:27:59 +08:00
onDetectActionStart: (action: number) => {
2022-10-24 17:06:53 +08:00
setAction(action);
// this.drawCanvas()
},
//每轮检测计时
2022-12-30 15:27:59 +08:00
onDetectActionProgress: (action: number, timer: number) => {
2022-10-24 17:06:53 +08:00
setTimer(timer);
},
//每轮检测结束
2022-12-30 15:27:59 +08:00
onDetectActionFinish: (action: number, data: any) => {
2022-10-24 17:06:53 +08:00
// this.clearCanvas()
setTimer(10000);
console.log(data)
},
//活体检测完成
2022-12-30 15:27:59 +08:00
onDetectFinish: (data: any) => {
if (data.code == 1) {
2022-10-24 17:06:53 +08:00
setAction(4);
setTimeShow(false);
//人脸比对
hanleFaceSubmit(data.file.file, null);
2022-12-30 15:27:59 +08:00
} else {
2022-10-24 17:06:53 +08:00
message.error('活体检测失败');
setSubmitLoading(false);
}
// data.code === 1? message.success('活体检测通过'):message.error('活体检测失败')
}
});
//开始检测
_lv.start();
lv.current = _lv;
}
/**
*
*/
const liveDetectStop = () => {
lv.current && lv.current.stop();
}
/**
*
* @returns
*/
const getLiveDetectFile = () => {
const canvas = document.createElement('canvas');
canvas.setAttribute('width', '300');
canvas.setAttribute('height', '200');
const context = canvas.getContext('2d');
context.drawImage(video.current, 0, 0, 300, 200);
let _imgURI = canvas.toDataURL("image/jpeg",);
console.log(_imgURI);
let _file = base64ToBlob(_imgURI);
return {
2022-12-30 15:27:59 +08:00
file: _file//传给活体检测服务的文件
2022-10-24 17:06:53 +08:00
}
}
2022-12-30 15:27:59 +08:00
const classColor = (action: any) => {
2022-10-24 17:06:53 +08:00
let color = '';
2022-12-30 15:27:59 +08:00
switch (action) {
2022-10-24 17:06:53 +08:00
case 1:
color = '#409eff';
break;
case 2:
color = '#5daf34';
break;
case 3:
color = 'gold';
break;
case 4:
color = 'grey';
break;
}
return color;
}
2022-12-30 15:27:59 +08:00
const actionText = (action: number, timer: number) => {
2022-10-24 17:06:53 +08:00
let text = '';
2022-12-30 15:27:59 +08:00
switch (action) {
2022-10-24 17:06:53 +08:00
case 1:
2022-12-30 15:27:59 +08:00
text = '对准摄像头眨眨眼(' + timer + 's';
2022-10-24 17:06:53 +08:00
break;
case 2:
2022-12-30 15:27:59 +08:00
text = '对准摄像头张张嘴(' + timer + 's';
2022-10-24 17:06:53 +08:00
break;
case 3:
2022-12-30 15:27:59 +08:00
text = '对准摄像头摇摇头(' + timer + 's';
2022-10-24 17:06:53 +08:00
break;
case 4:
text = '请稍候,正在验证中...';
}
return text;
}
2022-03-10 14:24:13 +08:00
const genRandomString = (len: number) => {
const text = 'abcdefghijklmnopqrstuvwxyz0123456789';
const rdmIndex = (text: string | any[]) => (Math.random() * text.length) | 0;
let rdmString = '';
for (; rdmString.length < len; rdmString += text.charAt(rdmIndex(text)));
return rdmString;
};
const changeCaptcha = () => {
let tmpToken = genRandomString(16);
let url = '/api/auth/captcha?token=' + tmpToken;
setTmpToken(tmpToken);
setImgUrl(url);
};
const changeCaptchaEdit = async () => {//修改密码-获取验证码
let tmpToken = genRandomString(16);
// 获取window的URL对像 并做好浏览器兼容性处理
const windowUrl = window.URL || window.webkitURL
windowUrl.revokeObjectURL(urlRef.current);
// 开始ajax请求
const xhr = new XMLHttpRequest()
// 验证码请求地址
const url = '/api/api/mall-expe/v1/expebaseinfo/getCaptcha?token=' + tmpToken
xhr.open('POST', url, true)
// 设置响应数据的类型 blod是将响应数据转换成二进制数据的Blob对象
xhr.responseType = 'blob'
xhr.onload = function () {
if (this.status === 200) {
const blob = this.response
// 将响应数据转换成url对象 赋值给src变量 传递给img
const blob_url = windowUrl.createObjectURL(blob);
urlRef.current = blob_url;
changeForm.setFieldsValue({ token: tmpToken });
setImgUrlEdit(blob_url);
}
};
xhr.send();
}
2022-03-10 14:24:13 +08:00
//登录刷新Token方法
const refreshToken = async (data: any) => {
const params = {
grant_type: "refresh_token",
refresh_token: data?.refreshToken?.value,
2023-07-27 11:28:54 +08:00
old_token: data?.value,
2022-03-10 14:24:13 +08:00
}
await refreshTokenApi(params).then(res => {
2022-03-10 14:24:13 +08:00
if (res?.success == true) {
sessionStorage.setItem('Authorization', res?.data?.value);
// sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
2022-03-10 14:24:13 +08:00
sessionStorage.setItem('scope', res?.data?.scope);
history.push('/redirect');
}
})
}
const handleSubmit = async (values: any) => {
await ZjfakeAccountLogin({ ...values, tmpToken }).then((res) => {
if (res?.success) {
if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) {
refreshToken(res?.data)
} else {
sessionStorage.setItem('Authorization', res?.data?.value);
// sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
2022-03-10 14:24:13 +08:00
sessionStorage.setItem('scope', res?.data?.scope);
history.push('/redirect');
}
}
changeCaptcha();
});
};
2022-09-07 16:20:59 +08:00
const onChange = (key: string) => {
if (key == '2') {
2022-09-07 16:20:59 +08:00
BrowserType();
InitMedia();
} else {
if (allowedToFaceLogin()) {
if (whetherIE.current) {
2022-09-07 16:20:59 +08:00
releaseCamera('faceLoginFrame');
} else {
2022-09-07 16:20:59 +08:00
mediaStreamTrack.current?.stop();
}
}
}
};
const releaseCamera = (id: string) => {
2022-09-07 16:20:59 +08:00
const childFrameObj = document.getElementById(id);
childFrameObj?.contentWindow?.postMessage('releaseCamera', '*');
2022-09-07 16:20:59 +08:00
}
2022-09-02 16:10:56 +08:00
const hanleFaceSubmit = async (multipartFiles: any, values: any) => {
2022-09-07 16:20:59 +08:00
let userName = form2.getFieldValue('userName');
if (whetherIE.current) {
if (!multipartFiles) {
2022-09-02 16:10:56 +08:00
const childFrameObj = document.getElementById('faceLoginFrame');
childFrameObj.contentWindow.postMessage('capture', '*');
} else {
2022-09-02 16:10:56 +08:00
await ZjfakeFaceLogin({ userName, multipartFiles }).then((res) => {
if (res?.success) {
if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) {
refreshToken(res?.data)
} else {
2022-09-07 16:20:59 +08:00
releaseCamera('faceLoginFrame');
2022-09-02 16:10:56 +08:00
sessionStorage.setItem('Authorization', res?.data?.value);
sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
sessionStorage.setItem('scope', res?.data?.scope);
history.push('/redirect');
}
}
2022-09-07 16:20:59 +08:00
})
.finally(
() => { setSubmitLoading(false); }
);
2022-09-02 16:10:56 +08:00
}
}
else {
if (!multipartFiles) {
2022-09-02 16:10:56 +08:00
const canvas = document.createElement('canvas');
canvas.setAttribute('width', '300');
2022-09-02 16:10:56 +08:00
canvas.setAttribute('height', '200');
2022-10-24 17:06:53 +08:00
document.body.appendChild(canvas);
2022-09-02 16:10:56 +08:00
const context = canvas.getContext('2d');
context.drawImage(video.current, 0, 0, 300, 200);
canvas.toBlob(function (result: any) {
2022-09-02 16:10:56 +08:00
hanleFaceSubmit(result, null);
})
} else {
setSubmitLoading(true);
await ZjfakeFaceLogin({ userName, multipartFiles }).then((res) => {
if (res?.success) {
if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) {
refreshToken(res?.data)
} else {
mediaStreamTrack.current?.stop();
sessionStorage.setItem('Authorization', res?.data?.value);
sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
sessionStorage.setItem('scope', res?.data?.scope);
history.push('/redirect');
2022-09-02 16:10:56 +08:00
}
}
})
2022-09-07 16:20:59 +08:00
.finally(
() => { setSubmitLoading(false); }
2022-09-07 16:20:59 +08:00
);
2022-09-02 16:10:56 +08:00
}
}
2022-09-02 16:10:56 +08:00
}
2022-03-10 14:24:13 +08:00
const handleOk = () => { // 确定修改密码
changeForm.validateFields().then(res => {
if (changeForm.getFieldValue("newPassword") !== changeForm.getFieldValue("newPassword1")) {
message.warn('两次密码输入不一致,请重新输入')
} else {
2022-03-10 14:24:13 +08:00
setSping(true);
const date = changeForm.getFieldsValue();
2022-03-10 14:24:13 +08:00
changePass({ ...date }).then(res => {
if (res.success) {
setIsModalVisible(false);
2022-03-10 14:24:13 +08:00
message.success('修改密码成功');
}
}).finally(() => {
changeCaptchaEdit();
2022-03-10 14:24:13 +08:00
setSping(false);
});
}
})
2022-03-10 14:24:13 +08:00
}
2022-08-17 17:21:01 +08:00
//浏览器类型
const BrowserType = () => {
//取得浏览器的userAgent字符串
var userAgent = navigator.userAgent;
//判断是否IE<11
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1;
//判断是否IE的Edge浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE;
//判断是否IE11
var isIE11 = userAgent.indexOf("Trident") > -1 && userAgent.indexOf("rv:11.0") > -1;
if (isIE) {
var reIE = new RegExp("MSIE(\\d+\\.\\d+);");
reIE.test(userAgent);
var fIEVersion = parseFloat(RegExp["$1"]);
if (fIEVersion == 7) {
return 7;
} else if (fIEVersion == 8) {
return 8;
} else if (fIEVersion == 9) {
return 9;
} else if (fIEVersion == 10) {
return 10;
} else {
//IE版本<=7
return 6;
2022-08-17 17:21:01 +08:00
}
} else if (isEdge) {
return 'edge';
} else if (isIE11) {
//IE11
whetherIE.current = true;
return 11;
} else {
//不是IE浏览器
return -1;
}
2022-08-17 17:21:01 +08:00
}
//初始化video
const InitMedia = () => {
if (!whetherIE.current) {
InitUserMedia({ video: { width: 480, height: 320 } }, success, error);
2022-08-17 17:21:01 +08:00
}
};
//访问用户媒体设备的兼容方法
const InitUserMedia = (constraints: any, success: any, error: any) => {
2022-10-24 17:06:53 +08:00
if (navigator.mediaDevices?.getUserMedia) {
//最新的标准API
2022-10-24 17:06:53 +08:00
navigator.mediaDevices?.getUserMedia(constraints).then(success).catch(error);
2022-08-17 17:21:01 +08:00
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia(constraints, success, error);
2022-08-17 17:21:01 +08:00
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
navigator.mozGetUserMedia(constraints, success, error);
2022-08-17 17:21:01 +08:00
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia(constraints, success, error);
2022-08-17 17:21:01 +08:00
}
}
//调用媒体设备成功回调方法
const success = (stream: any) => {
var result = stream.getVideoTracks().some(function (track: any) {
2022-09-07 16:20:59 +08:00
return track.enabled && track.readyState === 'live';
});
if (result) {
//兼容webkit核心浏览器
const CompatibleURL = window.URL || window.webkitURL;
//将视频流设置为video元素的源
console.log(stream);
//video.src = CompatibleURL.createObjectURL(stream);
video.current.srcObject = stream;
mediaStreamTrack.current = stream.getTracks()[0];
video.current.play();
}
2022-08-17 17:21:01 +08:00
}
//调用媒体设备失败回调方法
const error = (error: any) => {
message.warn('无法获取到摄像头权限,请确认是否存在摄像头及是否授权使用摄像头');
console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
2022-08-17 17:21:01 +08:00
}
2022-09-02 16:10:56 +08:00
2022-08-17 17:21:01 +08:00
//base64转blob
const base64ToBlob = (base64: string) => {
2022-08-17 17:21:01 +08:00
const parts = base64.split(";base64,");
const contentType = parts[0].split(":")[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; i += 1) {
uInt8Array[i] = raw.charCodeAt(i);
2022-08-17 17:21:01 +08:00
}
return new Blob([uInt8Array], { type: contentType });
};
2022-12-30 15:27:59 +08:00
const IELiveDetectFinish2 = async (data: any) => {
2022-10-28 17:23:46 +08:00
console.log(data);
setAction(4);
hanleFaceSubmit(data, null);
}
2022-10-24 17:06:53 +08:00
//IELiveDetectFinish
const IELiveDetectFinish = async (data: any) => {
2022-12-30 15:27:59 +08:00
if (data.code != 0) {
2022-10-28 17:23:46 +08:00
console.log(data);
setAction(4);
hanleFaceSubmit(data.file.file, null);
2022-12-30 15:27:59 +08:00
} else {
2022-10-28 17:23:46 +08:00
message.error('活体检测失败');
setSubmitLoading(false);
}
2022-10-24 17:06:53 +08:00
}
2022-12-30 15:27:59 +08:00
const UpdateDetectStatus = async (action: number, timer: number) => {
2022-10-28 17:23:46 +08:00
setSubmitLoading(true);
2022-10-24 17:06:53 +08:00
setAction(action);
setTimer(timer);
2022-08-17 17:21:01 +08:00
}
2022-09-07 16:20:59 +08:00
//是https或者是本地
const httpsOrLocal = () => {
let protocol = document.location.protocol;
2022-09-08 09:38:55 +08:00
if (protocol == 'https:') {
2022-09-07 16:20:59 +08:00
return true;
} else {
2022-09-07 16:20:59 +08:00
let host = window.location.hostname;
if (host == '127.0.0.1' || host == 'localhost') {
2022-09-07 16:20:59 +08:00
return true;
}
}
return false;
}
//是否允许人脸登录
const allowedToFaceLogin = () => {
let browseType = BrowserType()
if ((browseType == 11 || browseType == -1) && httpsOrLocal()) {
2022-09-07 16:20:59 +08:00
return true;
}
return false;
}
//是否显示人脸登录
const showFaceLogin = async () => {
const res = await showFaceTab();
setFaceLoginShow(res?.data === 1);
}
2022-09-07 16:20:59 +08:00
2022-03-10 14:24:13 +08:00
useEffect(() => {
cookie.remove('mall3_token');
sessionStorage.clear();
changeCaptcha();
if (!allowedToFaceLogin()) {
setFaceLoginDisable(true);
2022-09-07 16:20:59 +08:00
}
showFaceLogin();
2022-03-10 14:24:13 +08:00
}, []);
useEffect(() => {
if (isModalVisible) {
changeForm.resetFields()
changeCaptchaEdit();
}
}, [isModalVisible]);
2022-03-10 14:24:13 +08:00
return (
<Spin spinning={spinning}>
<div className="login-box">
<div className="top">
<img src={logo} />
<h3> | </h3>
<Button className="change" danger style={{ borderColor: '#b30000', color: '#b30000' }} onClick={() => (setIsModalVisible(true))}></Button>
2022-03-10 14:24:13 +08:00
</div>
<div className="main">
<div className="text">
<Tabs defaultActiveKey="1" onChange={onChange} size={'large'}>
2022-09-07 16:20:59 +08:00
<TabPane tab="账号密码登录" key="1">
<Form
name="basic"
className="form-box"
initialValues={{ remember: true }}
form={form}
onFinish={handleSubmit}
// onFinishFailed={onFinishFailed}
>
2022-03-10 14:24:13 +08:00
<Form.Item
label=""
2022-09-07 16:20:59 +08:00
name="userName"
rules={[{ required: true, message: '请输入用户名!' }]}
2022-03-10 14:24:13 +08:00
>
<Input
prefix={
2022-09-07 16:20:59 +08:00
<UserOutlined style={{ fontSize: '18px' }} className="site-form-item-icon" />
2022-03-10 14:24:13 +08:00
}
2022-09-07 16:20:59 +08:00
placeholder="请输入用户名"
2022-03-10 14:24:13 +08:00
/>
</Form.Item>
2022-09-07 16:20:59 +08:00
<Form.Item
label=""
name="password"
rules={[{ required: true, message: '请输入密码!' }]}
>
<Input.Password
prefix={
<LockOutlined style={{ fontSize: '18px' }} className="site-form-item-icon" />
}
placeholder="请输入密码"
/>
</Form.Item>
<Row>
<Col span={14}>
<Form.Item
label=""
name="captcha"
rules={[{ required: true, message: '请输入验证码!' }]}
>
<Input
prefix={
<SafetyCertificateOutlined
style={{ fontSize: '18px' }}
className="site-form-item-icon"
/>
}
placeholder="请输入验证码"
/>
</Form.Item>
</Col>
<Col span={10}>
<img className="verification" onClick={() => changeCaptcha()} src={imgUrl} />
</Col>
</Row>
2022-03-10 14:24:13 +08:00
2022-09-07 16:20:59 +08:00
{/* <Form.Item className="remember" name="remember" valuePropName="checked">
<Checkbox></Checkbox>
</Form.Item> */}
<Form.Item>
<Button type="primary" className="w100" htmlType="submit">
</Button>
2022-09-07 16:20:59 +08:00
</Form.Item>
</Form>
</TabPane>
{faceLoginShow && <>
<TabPane tab="人脸识别登录" key="2" disabled={faceLoginDisable}>
<Form
name="basic2"
className="form-box"
initialValues={{ remember: true }}
form={form2}
// onFinish={hanleFaceSubmit.bind(this, null)}
onFinish={!whetherIE.current ? liveDetectStart : hanleFaceSubmit.bind(this, null)}
// onFinishFailed={onFinishFailed}
2022-09-07 16:20:59 +08:00
>
<Form.Item
label=""
name="userName"
rules={[{ required: true, message: '请输入用户名!' }]}
>
<Input
prefix={
<UserOutlined style={{ fontSize: '18px' }} className="site-form-item-icon" />
}
placeholder="请输入用户名"
/>
</Form.Item>
<Form.Item>
{!whetherIE.current ? (<video ref={video} width="382" height="200"></video>) : (<FrameFaceLogin faceCompareEvent2={IELiveDetectFinish2} faceCompareEvent={IELiveDetectFinish} faceDetectStatusEvent={UpdateDetectStatus} />)}
</Form.Item>
<Form.Item>
<Button type="primary" className="w100" loading={submitLoading} htmlType="submit">
{submitLoading ? actionText(action, Math.round(timer / 1000)) : '登 录'}
</Button>
</Form.Item>
</Form>
</TabPane>
{/* 加载摄像头 */}
<Form.Item hidden={!itemShow}>
<div>
<span style={{ color: classColor(action) }}>{actionText(action)}</span>
<span hidden={!timerShow}>{Math.round(timer / 1000)}</span>
</div>
</Form.Item>
<video ref={video} width="382" height="200"></video>
{/* onClick={() => {hanleFaceSubmit(null, null);}} */}
</>}
2022-09-07 16:20:59 +08:00
</Tabs>
2022-03-10 14:24:13 +08:00
</div>
</div>
<Modal
title="修改密码"
visible={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={[
<Button type='primary' onClick={() => handleOk()} loading={spinning}> </Button>,
2022-03-10 14:24:13 +08:00
<Button onClick={() => setIsModalVisible(false)}> </Button>
]}
width={600}
>
<Spin spinning={spinning}>
<Form
{...layout}
name="basic"
form={changeForm}
>
<Form.Item
label="身份证(用户名)"
name="identityCard"
rules={[
{
required: true,
message: '请输入身份证(用户名)',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="原密码"
name="oldPassword"
rules={[
{
required: true,
message: '请输入原始密码',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="新密码"
name="newPassword"
// rules={[
// {
// required: true,
// validator: (rule, value, callback) => {
// const oNumber = new RegExp(/\d/);
// const oLetter = new RegExp(/[a-zA-Z]/);
// const oSpecial = '.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"';
// if (!value) {
// callback('请输入新密码');
// return;
// }
// if (value.length < 6) {
// callback('密码不能小于六位至少含字母、数字、特殊字符其中的2种');
// return;
// }
// try {
// [...value].forEach(val => {
// if (
// !(
// oNumber.test(val) ||
// oLetter.test(val) ||
// oSpecial.indexOf(val) >= 0
// )
// ) {
// throw new Error();
// }
// });
// } catch (e) {
// callback('密码不能小于六位至少含字母、数字、特殊字符其中的2种');
// }
// const contain: boolean[] = [];
// [...value].forEach(val => {
// if (oNumber.test(val)) {
// contain[0] = true;
// }
// if (oLetter.test(val)) {
// contain[1] = true;
// }
// if (oSpecial.indexOf(val) >= 0) {
// contain[2] = true;
// }
// });
// if (contain.filter(item => item === true).length < 2) {
// callback('密码不能小于六位至少含字母、数字、特殊字符其中的2种');
// return;
// }
// callback();
// }
// }
// ]}
2022-03-10 14:24:13 +08:00
rules={[
{
required: true,
message: '请输入新密码',
}, {
pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[`~!@#$%^&*()\-_=+\\|[{}\];:'",<.>/?])[a-zA-Z0-9`~!@#$%^&*()\-_=+\\|[{}\];:'",<.>/?]{8,20}$/,
message: "密码不符合规则密码长度8-20位必须包含大小写字母、数字和特殊字符",
2022-03-10 14:24:13 +08:00
}
]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="新密码确认"
name="newPassword1"
rules={[
{
required: true,
message: '请再次输入新密码',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item
name="token"
hidden
>
<Input />
</Form.Item>
<Form.Item label="验证码" required>
<Form.Item
noStyle
name="code"
rules={[{ required: true, message: '请输入验证码!' }]}
>
<Input
style={{ width: "calc(60% - 8px)", marginRight: 8 }}
placeholder="请输入验证码"
/>
</Form.Item>
<Form.Item noStyle>
<img className="verification" onClick={() => changeCaptchaEdit()} src={imgUrlEdit} style={{ width: "40%" }} />
</Form.Item>
</Form.Item>
2022-03-10 14:24:13 +08:00
</Form>
</Spin>
</Modal>
</div>
</Spin>
);
};
export default Index;
2022-08-17 17:21:01 +08:00