1.需要使用iframe引入二维码
<iframe
className={styles.scanStyle}
scrolling="no"
height="360px"
width="100%"
src={scanUrl}
frameBorder="0"
/>
这里的scanUrl就是二维码链接,是从后端获取的
2.每次进入页面需要获取二维码和验证码,需要对是否超时进行判断,根据后端发送的消息,请求用户信息
const getScanUrl = () => { //获取二维码
dispatch({
type: 'login/getScanUrl',
payload: {},
});
};
const getUserInfo = (code) => { //获取用户信息
dispatch({
type: 'login/loginOn',
payload: { code },
});
};
const isLoginEvent = (e) => { //监听后端信息事件
const code = e.data && e.data.code;
if (code) {
// 根据 code 去获取用户信息
getUserInfo(code);
}
};
const getCode = () => { //获取验证码
let imgUrl = `api/quality/user/getCode?key=${new Date().getTime()}`;
setImgCode(imgUrl);
};
useEffect(() => {
const { overtime } = history.location.query;
overtime ? message.warning('请登录') : '';
getScanUrl();
getCode();
window.addEventListener('message', isLoginEvent);
return () => {
window.removeEventListener('message', isLoginEvent);
};
}, []);
3.监听验证码的键盘事件,表单验证,提交信息
const adminLogin = (params) => { //管理员登录
dispatch({
type: 'login/adminLogin',
payload: { ...params },
});
};
const onPressEnter = (e) => { //键盘回车事件
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
submitForm();
}
};
const submitForm = () => {
form.validateFields().then((res) => { //表单验证后提交
let key = imgCode.split('=')[1];
adminLogin({
...res,
account: rsaEncrypt(res.account), //rsaEncrypt加密
password: rsaEncrypt(res.password),
code: res.code.text,
key,
});
});
};
const validatorCode = (_, value) => { //表单验证
if (value?.text) {
return Promise.resolve();
}
return Promise.reject(new Error('请输入验证码'));
};
useEffect(() => {
document.removeEventListener('keyup', onPressEnter);
if (imgCode) {
document.addEventListener('keyup', onPressEnter);
}
return () => {
document.removeEventListener('keyup', onPressEnter);
};
}, [imgCode]);
4.前端整体结构
const callback = (key) => {
if (key === 'scanCode') {
getScanUrl();
}
setLoginFlag(key);
};
return (
<div className={styles.wrap}>
<div className={styles.login}>
<Tabs
onChange={callback}
accessKey={loginFlag}
>
<TabPane
key="scanCode"
tab={[
<img
key={scanCodeAcive}
src={loginFlag === 'scanCode' ? scanCodeAcive : scanCode}
/>,
<span
style={{ fontSize: 16, marginLeft: 8 }}
key="name1"
className={styles.tabHeader}
>
扫码登陆
</span>,
]}
>
<h3>请用浙政钉扫码登录</h3>
<div className={styles.scanBox}>
<iframe
className={styles.scanStyle}
scrolling="no"
height="360px"
width="100%"
src={scanUrl}
frameBorder="0"
/>
</div>
</TabPane>
<TabPane
key="password"
tab={[
<img
key={loginActive}
src={loginFlag === 'password' ? loginActive : login}
/>,
<span
key="name3"
style={{ fontSize: 16, marginLeft: 8 }}
className={styles.tabHeader}
>
管理员登录
</span>,
]}
>
<h3>请输入超级管理员账号</h3>
<Form
style={{ marginTop: 55 }}
name="login"
autoComplete="off"
form={form}
>
<Form.Item
name="account"
rules={[
{
required: true,
message: '请输入用户名',
},
]}
>
<Input size="large" placeholder="请输入用户名" />
</Form.Item>
<Form.Item
name="password"
rules={[
{
required: true,
message: '请输入密码',
},
]}
>
<Input.Password size="large" placeholder="请输入密码" />
</Form.Item>
<Form.Item
name="code"
rules={[
{
validator: validatorCode,
},
]}
>
<VerificationCode getCode={getCode} imgCode={imgCode} />
</Form.Item>
</Form>
<Button
size="large"
onClick={submitForm}
className={styles.loginBtn}
>
登录
</Button>
</TabPane>
</Tabs>
</div>
</div>
);
5.验证码组件
import { useSelector, useDispatch, history } from 'umi';
import { useEffect, useState } from 'react';
import { Input, Tooltip } from 'antd';
import styles from './index.less';
const VerificationCode = ({ value = {}, onChange, getCode, imgCode }) => {
const dispatch = useDispatch();
const [text, setText] = useState('');
const triggerChange = (changedValue) => {
onChange?.({
text,
...value,
...changedValue,
});
};
const onTextChange = (e) => {
const newText = e.target.value;
setText(newText);
triggerChange({
text: newText,
});
};
return (
<div className={styles.codeStyle}>
<Input
type="text"
value={value.text || text}
onChange={onTextChange}
placeholder="请输入验证码"
size="large"
style={{
width: 200,
}}
/>
<Tooltip
overlayStyle={{ fontSize: '12px' }}
placement="bottom"
title="看不清换一张"
>
<img className={styles.imgStyle} onClick={getCode} src={imgCode} />
</Tooltip>
</div>
);
};
export default VerificationCode;
6.加密规则
export const rsaEncrypt = (password) => {
var encryptor = new JSEncrypt(); // 创建加密对象实例
//之前ssl生成的公钥,复制的时候要小心不要有空格
var pubKey = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwyG0Tp1Wo1nLBqi8wcQYLC6Z4Udjr9rEYmbnb
21CVPaU1UmNXYyU3giV7ck6bhreAjEtwg9NjZ+p2xQL35WAL7ZsyFL0k+CYrRu3VqtFE0qwikyOT
ZjujKOpREqAwzDK4UjzL9hK4ud0GCO9lPfw2ecTJyJ2GTzT0ooPHe5ljAQIDAQAB`;
encryptor.setPublicKey(pubKey); //设置公钥
var rsaPassWord = encryptor.encrypt(password); // 对内容进行加密
return rsaPassWord;
};