81 lines
2.8 KiB
TypeScript
81 lines
2.8 KiB
TypeScript
import { useState } from 'react';
|
|
import { Card, Form, Input, Button, message, Typography } from 'antd';
|
|
import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { authApi } from '../api/modules';
|
|
import { setAuth, type AuthUser } from '../store/auth';
|
|
import { getErrorMessage } from '../utils/error';
|
|
import { useTheme } from '../store/useTheme';
|
|
import { useAppInfo } from '../hooks/useAppInfo';
|
|
|
|
const { Title, Text } = Typography;
|
|
|
|
export default function LoginPage({ onLogin }: { onLogin?: () => void }) {
|
|
const [loading, setLoading] = useState(false);
|
|
const navigate = useNavigate();
|
|
const { isDark } = useTheme();
|
|
const appInfo = useAppInfo();
|
|
const versionText = appInfo?.version ? `v${appInfo.version}` : 'v--';
|
|
|
|
const onFinish = async (values: { username: string; password: string }) => {
|
|
setLoading(true);
|
|
try {
|
|
const result = await authApi.login(values.username, values.password);
|
|
const user: AuthUser = {
|
|
id: 0,
|
|
username: result.username,
|
|
role: result.role,
|
|
permissions: result.permissions,
|
|
};
|
|
setAuth(user);
|
|
message.success('登录成功');
|
|
onLogin?.(); // 触发 App 重渲染
|
|
navigate('/', { replace: true });
|
|
} catch (e: unknown) {
|
|
message.error(getErrorMessage(e) || '登录失败');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div style={{
|
|
minHeight: '100vh',
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
background: isDark
|
|
? 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)'
|
|
: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
}}>
|
|
<Card style={{ width: 380, boxShadow: isDark ? '0 8px 24px rgba(0,0,0,0.4)' : '0 8px 24px rgba(0,0,0,0.15)' }}>
|
|
<Title level={3} style={{ textAlign: 'center', marginBottom: 32 }}>
|
|
直播运营后台
|
|
</Title>
|
|
<Text type="secondary" style={{
|
|
display: 'block',
|
|
textAlign: 'center',
|
|
marginTop: -20,
|
|
marginBottom: 24,
|
|
fontSize: 12,
|
|
}}>
|
|
当前版本 {versionText}
|
|
</Text>
|
|
<Form onFinish={onFinish} size="large">
|
|
<Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]}>
|
|
<Input prefix={<UserOutlined />} placeholder="用户名" />
|
|
</Form.Item>
|
|
<Form.Item name="password" rules={[{ required: true, message: '请输入密码' }]}>
|
|
<Input.Password prefix={<LockOutlined />} placeholder="密码" />
|
|
</Form.Item>
|
|
<Form.Item>
|
|
<Button type="primary" htmlType="submit" loading={loading} block>
|
|
登录
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|