96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router';
|
|
import { Button, Form, Input, message } from 'antd';
|
|
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
|
import { authService } from '../services/auth';
|
|
import type { LoginRequest } from '@/types/user';
|
|
import './LoginPage.css';
|
|
|
|
export default function LoginPage() {
|
|
const navigate = useNavigate();
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
// 如果已登录,重定向到首页
|
|
useEffect(() => {
|
|
if (authService.isAuthenticated()) {
|
|
navigate('/', { replace: true });
|
|
}
|
|
}, [navigate]);
|
|
|
|
const onFinish = async (values: LoginRequest) => {
|
|
setLoading(true);
|
|
try {
|
|
await authService.login(values);
|
|
message.success('登录成功');
|
|
navigate('/', { replace: true });
|
|
} catch (error: any) {
|
|
message.error(error.message || '登录失败,请检查用户名和密码');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="login-container">
|
|
<div className="login-box">
|
|
<div className="login-header">
|
|
<h1>投小记</h1>
|
|
<p>投资决策与复盘工具</p>
|
|
</div>
|
|
|
|
<Form
|
|
name="login"
|
|
onFinish={onFinish}
|
|
autoComplete="off"
|
|
size="large"
|
|
className="login-form"
|
|
>
|
|
<Form.Item
|
|
name="usernameOrEmail"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: '请输入用户名或邮箱',
|
|
},
|
|
{
|
|
min: 3,
|
|
message: '用户名或邮箱至少3个字符',
|
|
},
|
|
]}
|
|
>
|
|
<Input prefix={<UserOutlined />} placeholder="用户名或邮箱" />
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="password"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: '请输入密码',
|
|
},
|
|
{
|
|
min: 6,
|
|
message: '密码至少6个字符',
|
|
},
|
|
]}
|
|
>
|
|
<Input.Password prefix={<LockOutlined />} placeholder="密码" />
|
|
</Form.Item>
|
|
|
|
<Form.Item>
|
|
<Button
|
|
type="primary"
|
|
htmlType="submit"
|
|
loading={loading}
|
|
block
|
|
className="login-button"
|
|
>
|
|
登录
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|