182 lines
5.1 KiB
TypeScript
182 lines
5.1 KiB
TypeScript
import LogoIcon from '@/assets/images/logo.png';
|
|
import { initialPasswordAtom, userAtom } from '@/atoms/user';
|
|
import SealInput from '@/components/seal-form/seal-input';
|
|
import {
|
|
getRememberMe,
|
|
rememberMe,
|
|
removeRememberMe
|
|
} from '@/utils/localstore/index';
|
|
import { GlobalOutlined, LockOutlined, UserOutlined } from '@ant-design/icons';
|
|
import { SelectLang, history, useIntl, useModel } from '@umijs/max';
|
|
import { Button, Checkbox, Form } from 'antd';
|
|
import CryptoJS from 'crypto-js';
|
|
import { useAtom } from 'jotai';
|
|
import { useEffect } from 'react';
|
|
import { flushSync } from 'react-dom';
|
|
import { login } from '../apis';
|
|
|
|
const REMEMBER_ME_KEY = 'r_m';
|
|
const CRYPT_TEXT = 'seal';
|
|
|
|
const renderLogo = () => {
|
|
return (
|
|
<div
|
|
style={{
|
|
width: '400px',
|
|
display: 'flex',
|
|
marginBottom: 24,
|
|
justifyContent: 'center',
|
|
alignItems: 'center'
|
|
}}
|
|
>
|
|
<img src={LogoIcon} alt="logo" style={{ width: '44px' }} />
|
|
<span style={{ fontSize: 34, marginLeft: 12 }}>SEAL</span>
|
|
</div>
|
|
);
|
|
};
|
|
const LoginForm = () => {
|
|
const [userInfo, setUserInfo] = useAtom(userAtom);
|
|
const [initialPassword, setInitialPassword] = useAtom(initialPasswordAtom);
|
|
const { initialState, setInitialState } = useModel('@@initialState');
|
|
const intl = useIntl();
|
|
const [form] = Form.useForm();
|
|
|
|
const gotoDefaultPage = (userInfo: any) => {
|
|
const pathname =
|
|
userInfo && userInfo?.is_admin ? '/dashboard' : '/playground';
|
|
history.push(pathname);
|
|
};
|
|
const fetchUserInfo = async () => {
|
|
const userInfo = await initialState?.fetchUserInfo?.();
|
|
|
|
if (userInfo) {
|
|
flushSync(() => {
|
|
setInitialState((s: any) => ({
|
|
...s,
|
|
currentUser: userInfo
|
|
}));
|
|
});
|
|
}
|
|
return userInfo;
|
|
};
|
|
|
|
const encryptPassword = (password: string) => {
|
|
const psw = CryptoJS.AES?.encrypt?.(password, CRYPT_TEXT).toString();
|
|
return psw;
|
|
};
|
|
const decryptPassword = (password: string) => {
|
|
const bytes = CryptoJS.AES?.decrypt?.(password, CRYPT_TEXT);
|
|
const res = bytes.toString(CryptoJS.enc.Utf8);
|
|
return res;
|
|
};
|
|
|
|
const callRememberMe = async (values: any) => {
|
|
const { autoLogin } = values;
|
|
if (autoLogin) {
|
|
await rememberMe(REMEMBER_ME_KEY, {
|
|
um: encryptPassword(values.username),
|
|
pw: encryptPassword(values.password),
|
|
f: true
|
|
});
|
|
} else {
|
|
await removeRememberMe(REMEMBER_ME_KEY);
|
|
}
|
|
};
|
|
|
|
const callGetRememberMe = async () => {
|
|
const rememberMe = await getRememberMe(REMEMBER_ME_KEY);
|
|
|
|
if (rememberMe?.f) {
|
|
const username = decryptPassword(rememberMe?.um);
|
|
const password = decryptPassword(rememberMe?.pw);
|
|
form.setFieldsValue({ username, password, autoLogin: true });
|
|
}
|
|
};
|
|
|
|
const handleLogin = async (values: any) => {
|
|
try {
|
|
await login({
|
|
username: values.username,
|
|
password: values.password
|
|
});
|
|
const userInfo = await fetchUserInfo();
|
|
setUserInfo(userInfo);
|
|
setInitialPassword(values.password);
|
|
if (values.autoLogin) {
|
|
await callRememberMe(values);
|
|
} else {
|
|
await removeRememberMe(REMEMBER_ME_KEY);
|
|
}
|
|
if (!userInfo?.require_password_change) {
|
|
gotoDefaultPage(userInfo);
|
|
}
|
|
} catch (error) {
|
|
// to do something
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
callGetRememberMe();
|
|
}, []);
|
|
|
|
return (
|
|
<div>
|
|
<div style={{ position: 'fixed', right: 0, top: 0, padding: '0 20px' }}>
|
|
<SelectLang icon={<GlobalOutlined />} reload={false} />
|
|
</div>
|
|
<Form
|
|
form={form}
|
|
style={{ width: '400px', margin: '0 auto', paddingTop: '5%' }}
|
|
onFinish={handleLogin}
|
|
>
|
|
<div>{renderLogo()}</div>
|
|
<Form.Item
|
|
name="username"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: intl.formatMessage(
|
|
{ id: 'common.form.rule.input' },
|
|
{ name: intl.formatMessage({ id: 'common.form.username' }) }
|
|
)
|
|
}
|
|
]}
|
|
>
|
|
<SealInput.Input
|
|
label={intl.formatMessage({ id: 'common.form.username' })}
|
|
prefix={<UserOutlined />}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="password"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: intl.formatMessage(
|
|
{ id: 'common.form.rule.input' },
|
|
{ name: intl.formatMessage({ id: 'common.form.password' }) }
|
|
)
|
|
}
|
|
]}
|
|
>
|
|
<SealInput.Password
|
|
prefix={<LockOutlined />}
|
|
label={intl.formatMessage({ id: 'common.form.password' })}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item name="autoLogin" valuePropName="checked">
|
|
<Checkbox style={{ marginLeft: 10 }}>
|
|
{intl.formatMessage({ id: 'common.login.rember' })}
|
|
</Checkbox>
|
|
</Form.Item>
|
|
<Button htmlType="submit" type="primary" block>
|
|
{intl.formatMessage({ id: 'menu.login' })}
|
|
</Button>
|
|
</Form>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LoginForm;
|