249 lines
7.4 KiB
JavaScript
249 lines
7.4 KiB
JavaScript
import React, { useContext, useEffect, useState } from 'react';
|
||
import {
|
||
Button,
|
||
Divider,
|
||
Form,
|
||
Grid,
|
||
Header,
|
||
Image,
|
||
Message,
|
||
Modal,
|
||
Segment,
|
||
Card,
|
||
} from 'semantic-ui-react';
|
||
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
|
||
import { UserContext } from '../context/User';
|
||
import { API, getLogo, showError, showSuccess, showWarning } from '../helpers';
|
||
import { onGitHubOAuthClicked, onLarkOAuthClicked } from './utils';
|
||
import larkIcon from '../images/lark.svg';
|
||
|
||
const LoginForm = () => {
|
||
const [inputs, setInputs] = useState({
|
||
username: '',
|
||
password: '',
|
||
wechat_verification_code: '',
|
||
});
|
||
const [searchParams, setSearchParams] = useSearchParams();
|
||
const [submitted, setSubmitted] = useState(false);
|
||
const { username, password } = inputs;
|
||
const [userState, userDispatch] = useContext(UserContext);
|
||
let navigate = useNavigate();
|
||
const [status, setStatus] = useState({});
|
||
const logo = getLogo();
|
||
|
||
useEffect(() => {
|
||
if (searchParams.get('expired')) {
|
||
showError('未登录或登录已过期,请重新登录!');
|
||
}
|
||
let status = localStorage.getItem('status');
|
||
if (status) {
|
||
status = JSON.parse(status);
|
||
setStatus(status);
|
||
}
|
||
}, []);
|
||
|
||
const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false);
|
||
|
||
const onWeChatLoginClicked = () => {
|
||
setShowWeChatLoginModal(true);
|
||
};
|
||
|
||
const onSubmitWeChatVerificationCode = async () => {
|
||
const res = await API.get(
|
||
`/api/oauth/wechat?code=${inputs.wechat_verification_code}`
|
||
);
|
||
const { success, message, data } = res.data;
|
||
if (success) {
|
||
userDispatch({ type: 'login', payload: data });
|
||
localStorage.setItem('user', JSON.stringify(data));
|
||
navigate('/');
|
||
showSuccess('登录成功!');
|
||
setShowWeChatLoginModal(false);
|
||
} else {
|
||
showError(message);
|
||
}
|
||
};
|
||
|
||
function handleChange(e) {
|
||
const { name, value } = e.target;
|
||
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||
}
|
||
|
||
async function handleSubmit(e) {
|
||
setSubmitted(true);
|
||
if (username && password) {
|
||
const res = await API.post(`/api/user/login`, {
|
||
username,
|
||
password,
|
||
});
|
||
const { success, message, data } = res.data;
|
||
if (success) {
|
||
userDispatch({ type: 'login', payload: data });
|
||
localStorage.setItem('user', JSON.stringify(data));
|
||
if (username === 'root' && password === '123456') {
|
||
navigate('/user/edit');
|
||
showSuccess('登录成功!');
|
||
showWarning('请立刻修改默认密码!');
|
||
} else {
|
||
navigate('/token');
|
||
showSuccess('登录成功!');
|
||
}
|
||
} else {
|
||
showError(message);
|
||
}
|
||
}
|
||
}
|
||
|
||
return (
|
||
<Grid textAlign='center' style={{ marginTop: '48px' }}>
|
||
<Grid.Column style={{ maxWidth: 450 }}>
|
||
<Card
|
||
fluid
|
||
className='chart-card'
|
||
style={{ boxShadow: '0 1px 3px rgba(0,0,0,0.12)' }}
|
||
>
|
||
<Card.Content>
|
||
<Card.Header>
|
||
<Header
|
||
as='h2'
|
||
textAlign='center'
|
||
style={{ marginBottom: '1.5em' }}
|
||
>
|
||
<Image src={logo} style={{ marginBottom: '10px' }} />
|
||
<Header.Content>用户登录</Header.Content>
|
||
</Header>
|
||
</Card.Header>
|
||
<Form size='large'>
|
||
<Form.Input
|
||
fluid
|
||
icon='user'
|
||
iconPosition='left'
|
||
placeholder='用户名 / 邮箱地址'
|
||
name='username'
|
||
value={username}
|
||
onChange={handleChange}
|
||
style={{ marginBottom: '1em' }}
|
||
/>
|
||
<Form.Input
|
||
fluid
|
||
icon='lock'
|
||
iconPosition='left'
|
||
placeholder='密码'
|
||
name='password'
|
||
type='password'
|
||
value={password}
|
||
onChange={handleChange}
|
||
style={{ marginBottom: '1.5em' }}
|
||
/>
|
||
<Button
|
||
fluid
|
||
size='large'
|
||
style={{
|
||
background: '#2F73FF', // 使用更现代的蓝色
|
||
color: 'white',
|
||
marginBottom: '1.5em',
|
||
}}
|
||
onClick={handleSubmit}
|
||
>
|
||
登录
|
||
</Button>
|
||
</Form>
|
||
|
||
<Divider />
|
||
<Message style={{ background: 'transparent', boxShadow: 'none' }}>
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
fontSize: '0.9em',
|
||
color: '#666',
|
||
}}
|
||
>
|
||
<div>
|
||
忘记密码?
|
||
<Link to='/reset' style={{ color: '#2185d0' }}>
|
||
点击重置
|
||
</Link>
|
||
</div>
|
||
<div>
|
||
没有账户?
|
||
<Link to='/register' style={{ color: '#2185d0' }}>
|
||
点击注册
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</Message>
|
||
|
||
{(status.github_oauth ||
|
||
status.wechat_login ||
|
||
status.lark_client_id) && (
|
||
<>
|
||
<Divider
|
||
horizontal
|
||
style={{ color: '#666', fontSize: '0.9em' }}
|
||
>
|
||
使用其他方式登录
|
||
</Divider>
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
justifyContent: 'center',
|
||
gap: '1em',
|
||
marginTop: '1em',
|
||
}}
|
||
>
|
||
{status.github_oauth && (
|
||
<Button
|
||
circular
|
||
color='black'
|
||
icon='github'
|
||
onClick={() =>
|
||
onGitHubOAuthClicked(status.github_client_id)
|
||
}
|
||
/>
|
||
)}
|
||
{status.wechat_login && (
|
||
<Button
|
||
circular
|
||
color='green'
|
||
icon='wechat'
|
||
onClick={onWeChatLoginClicked}
|
||
/>
|
||
)}
|
||
{status.lark_client_id && (
|
||
<div
|
||
style={{
|
||
background:
|
||
'radial-gradient(circle, #FFFFFF, #FFFFFF, #FFFFFF, #FFFFFF, #FFFFFF)',
|
||
width: '36px',
|
||
height: '36px',
|
||
borderRadius: '10em',
|
||
display: 'flex',
|
||
cursor: 'pointer',
|
||
}}
|
||
onClick={() => onLarkOAuthClicked(status.lark_client_id)}
|
||
>
|
||
<Image
|
||
src={larkIcon}
|
||
avatar
|
||
style={{
|
||
width: '36px',
|
||
height: '36px',
|
||
cursor: 'pointer',
|
||
margin: 'auto',
|
||
}}
|
||
/>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</>
|
||
)}
|
||
</Card.Content>
|
||
</Card>
|
||
</Grid.Column>
|
||
</Grid>
|
||
);
|
||
};
|
||
|
||
export default LoginForm;
|