172 lines
6.2 KiB
TypeScript
172 lines
6.2 KiB
TypeScript
import React, {useEffect, useState} from 'react';
|
|
import {Form, Input, Button, message, Select} from 'antd';
|
|
import {useNavigate} from 'react-router-dom';
|
|
import {useDispatch} from 'react-redux';
|
|
import {login} from './service';
|
|
import {getEnabledTenants} from '@/pages/System/Tenant/service';
|
|
import {setToken, setUserInfo, setMenus} from '../../store/userSlice';
|
|
import {getCurrentUserMenus} from '@/pages/System/Menu/service';
|
|
import type { TenantResponse } from '@/pages/System/Tenant/types';
|
|
import styles from './index.module.css';
|
|
|
|
interface LoginForm {
|
|
tenantId: string;
|
|
username: string;
|
|
password: string;
|
|
}
|
|
|
|
const Login: React.FC = () => {
|
|
const navigate = useNavigate();
|
|
const dispatch = useDispatch();
|
|
const [form] = Form.useForm<LoginForm>();
|
|
const [loading, setLoading] = useState(false);
|
|
const [tenants, setTenants] = useState<TenantResponse[]>([]);
|
|
|
|
useEffect(() => {
|
|
const fetchTenants = async () => {
|
|
try {
|
|
const data = await getEnabledTenants();
|
|
setTenants(data);
|
|
} catch (error) {
|
|
console.error('获取租户列表失败:', error);
|
|
}
|
|
};
|
|
|
|
fetchTenants();
|
|
}, []);
|
|
|
|
// 加载菜单数据
|
|
const loadMenuData = async () => {
|
|
try {
|
|
const menuData = await getCurrentUserMenus();
|
|
if (menuData && menuData.length > 0) {
|
|
dispatch(setMenus(menuData));
|
|
}
|
|
} catch (error) {
|
|
console.error('获取菜单数据失败:', error);
|
|
}
|
|
};
|
|
|
|
const handleFinish = async (values: LoginForm) => {
|
|
setLoading(true);
|
|
try {
|
|
// 1. 登录获取 token 和用户信息
|
|
const loginData = await login(values);
|
|
dispatch(setToken(loginData.token));
|
|
dispatch(setUserInfo({
|
|
id: loginData.id,
|
|
username: loginData.username,
|
|
nickname: loginData.nickname,
|
|
email: loginData.email,
|
|
phone: loginData.phone
|
|
}));
|
|
|
|
// 2. 获取菜单数据
|
|
await loadMenuData();
|
|
|
|
message.success('登录成功');
|
|
navigate('/');
|
|
} catch (error) {
|
|
console.error('登录失败:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={styles.loginContainer}>
|
|
{/* 左侧区域 */}
|
|
<div className={styles.leftSection}>
|
|
<div>
|
|
<h1 className="text-xl font-bold">Deploy Ease Platform</h1>
|
|
</div>
|
|
<div className="space-y-4">
|
|
<blockquote className="text-2xl font-medium">
|
|
"平台帮助我们显著提升了部署效率,让团队可以更专注于业务开发。"
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 右侧登录区域 */}
|
|
<div className={styles.rightSection}>
|
|
<div className={styles.loginBox}>
|
|
<div className={styles.logo}>
|
|
<h1>管理系统</h1>
|
|
<p className="text-gray-500 mt-2">输入您的账号密码登录系统</p>
|
|
</div>
|
|
<Form<LoginForm>
|
|
form={form}
|
|
name="login"
|
|
onFinish={handleFinish}
|
|
autoComplete="off"
|
|
size="large"
|
|
layout="vertical"
|
|
>
|
|
<Form.Item
|
|
name="tenantId"
|
|
rules={[{required: true, message: '请选择租户!'}]}
|
|
>
|
|
<Select
|
|
placeholder="系统管理租户"
|
|
options={tenants.map(tenant => ({
|
|
label: tenant.name,
|
|
value: tenant.code
|
|
}))}
|
|
className={styles.input}
|
|
dropdownStyle={{
|
|
padding: '8px',
|
|
borderRadius: '8px',
|
|
}}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="username"
|
|
rules={[{required: true, message: '请输入用户名!'}]}
|
|
>
|
|
<Input
|
|
placeholder="admin"
|
|
className={styles.input}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="password"
|
|
rules={[{required: true, message: '请输入密码!'}]}
|
|
>
|
|
<Input.Password
|
|
placeholder="········"
|
|
className={styles.input}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item>
|
|
<Button
|
|
type="primary"
|
|
htmlType="submit"
|
|
block
|
|
loading={loading}
|
|
className={styles.loginButton}
|
|
>
|
|
登录
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
|
|
<div className="text-center text-sm text-gray-500 mt-4">
|
|
登录即表示您同意我们的
|
|
<a href="#" className="text-[#2563eb] hover:text-[#1d4ed8] mx-1">
|
|
服务条款
|
|
</a>
|
|
和
|
|
<a href="#" className="text-[#2563eb] hover:text-[#1d4ed8] mx-1">
|
|
隐私政策
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Login;
|