Files
invest-mind-store/apps/web/src/pages/LoginPage.tsx
T
2026-01-06 10:49:19 +08:00

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>
);
}