Files
yunhaifinance/company-finance-system/frontend/src/pages/auth/LoginPage.tsx
T

221 lines
7.0 KiB
TypeScript

import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
Card,
Form,
Input,
Button,
Typography,
Space,
Alert,
Flex,
Divider
} from 'antd'
import {
UserOutlined,
LockOutlined,
DashboardOutlined,
DollarOutlined,
ProjectOutlined,
TeamOutlined
} from '@ant-design/icons'
import { useAuthStore } from '../../store/authStore'
import { useLanguageStore } from '../../store/languageStore'
import LanguageSelector from '../../components/common/LanguageSelector'
const { Title, Text } = Typography
const LoginPage: React.FC = () => {
const navigate = useNavigate()
const [form] = Form.useForm()
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const { login } = useAuthStore()
const { t } = useLanguageStore()
const handleSubmit = async (values: { username: string; password: string }) => {
setLoading(true)
setError(null)
try {
await login(values.username, values.password)
navigate('/dashboard')
} catch (err) {
setError(err instanceof Error ? err.message : t('login.loginFailed'))
} finally {
setLoading(false)
}
}
// 测试账户
const testAccounts = [
{ username: 'admin', password: 'X123c321@', role: t('user.admin') },
{ username: 'finance', password: 'X123c321@', role: t('user.finance') },
{ username: 'manager', password: 'X123c321@', role: t('user.manager') },
{ username: 'employee', password: 'X123c321@', role: t('user.employee') }
]
const handleTestLogin = (username: string, password: string) => {
form.setFieldsValue({ username, password })
form.submit()
}
return (
<div style={{
minHeight: '100vh',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '20px'
}}>
<Card
className="login-card"
style={{
width: '100%',
maxWidth: 480,
borderRadius: 16,
boxShadow: '0 20px 60px rgba(0,0,0,0.3)'
}}
styles={{ body: { padding: 40 } }}
>
<Space direction="vertical" size="large" style={{ width: '100%' }}>
{/* 标题 */}
<div style={{ textAlign: 'center' }}>
<Title level={2} style={{ marginBottom: 8 }}>
<DashboardOutlined style={{ marginRight: 12, color: '#1890ff' }} />
{t('login.title')}
</Title>
<Text type="secondary">{t('login.subtitle')}</Text>
</div>
{/* 语言选择器 V2.0 */}
<div style={{
textAlign: 'center',
padding: '12px',
background: '#f0f2f5',
borderRadius: '8px',
border: '2px solid #1890ff'
}}>
<div style={{ marginBottom: 8, color: '#1890ff', fontWeight: 'bold' }}>
🌍 选择语言 / Select Language
</div>
<LanguageSelector size="large" style={{ width: '200px' }} />
</div>
{/* 错误提示 */}
{error && (
<Alert
message={error}
type="error"
showIcon
closable
onClose={() => setError(null)}
/>
)}
{/* 登录表单 */}
<Form
form={form}
layout="vertical"
onFinish={handleSubmit}
autoComplete="off"
>
<Form.Item
name="username"
label={t('login.username')}
rules={[
{ required: true, message: t('login.usernameRequired') },
{ min: 3, message: t('login.usernameMin') }
]}
>
<Input
prefix={<UserOutlined />}
placeholder={t('login.usernamePlaceholder')}
size="large"
/>
</Form.Item>
<Form.Item
name="password"
label={t('login.password')}
rules={[
{ required: true, message: t('login.passwordRequired') },
{ min: 6, message: t('login.passwordMin') }
]}
>
<Input.Password
prefix={<LockOutlined />}
placeholder={t('login.passwordPlaceholder')}
size="large"
/>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
loading={loading}
size="large"
block
>
{t('login.loginButton')}
</Button>
</Form.Item>
</Form>
<Divider>{t('login.testAccounts')}</Divider>
{/* 测试账户 */}
<Space direction="vertical" style={{ width: '100%' }}>
{testAccounts.map((account, index) => (
<Card
key={index}
size="small"
hoverable
onClick={() => handleTestLogin(account.username, account.password)}
style={{ cursor: 'pointer' }}
>
<Flex justify="space-between" align="center">
<Space>
{account.role === t('user.admin') && <DashboardOutlined style={{ color: '#1890ff' }} />}
{account.role === t('user.finance') && <DollarOutlined style={{ color: '#52c41a' }} />}
{account.role === t('user.manager') && <ProjectOutlined style={{ color: '#fa8c16' }} />}
{account.role === t('user.employee') && <TeamOutlined style={{ color: '#722ed1' }} />}
<Text strong>{account.role}</Text>
</Space>
<Text type="secondary">
{t('login.username')}: {account.username} / {t('login.password')}: {account.password}
</Text>
</Flex>
</Card>
))}
</Space>
{/* 功能说明 */}
<Card size="small" type="inner">
<Space direction="vertical" size="small" style={{ width: '100%' }}>
<Text strong>{t('menu.dashboard')}:</Text>
<Text type="secondary"> {t('features.projectManage')}</Text>
<Text type="secondary"> {t('features.advanceManage')}</Text>
<Text type="secondary"> {t('features.reimburseManage')}</Text>
<Text type="secondary"> {t('features.financeReport')}</Text>
<Text type="secondary"> {t('features.mobileSupport')}</Text>
</Space>
</Card>
{/* 技术支持 */}
<div style={{ textAlign: 'center', marginTop: 20 }}>
<Text type="secondary">
{t('login.techSupport')}
</Text>
</div>
</Space>
</Card>
</div>
)
}
export default LoginPage