130 lines
4.0 KiB
TypeScript
130 lines
4.0 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { Form, Input, Button, message } from 'antd';
|
||
import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons';
|
||
import { history } from '@umijs/max';
|
||
import './index.less';
|
||
|
||
interface LoginForm {
|
||
username: string;
|
||
password: string;
|
||
}
|
||
|
||
const LoginPage: React.FC = () => {
|
||
const [loading, setLoading] = useState(false);
|
||
|
||
const onFinish = async (values: LoginForm) => {
|
||
setLoading(true);
|
||
try {
|
||
// 模拟登录验证
|
||
if (values.username === 'admin' && values.password === '123456') {
|
||
message.success('登录成功!');
|
||
// 存储登录状态
|
||
localStorage.setItem('isLoggedIn', 'true');
|
||
localStorage.setItem('username', values.username);
|
||
// 跳转到镜像列表页面
|
||
history.push('/images');
|
||
} else {
|
||
message.error('用户名或密码错误!');
|
||
}
|
||
} catch (error) {
|
||
message.error('登录失败,请重试!');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="login-container">
|
||
{/* 左侧品牌区域 */}
|
||
<div className="login-left">
|
||
<div className="brand-content">
|
||
<div className="brand-logo">
|
||
<SafetyCertificateOutlined className="logo-icon" />
|
||
<h1 className="brand-title">紫光汇智</h1>
|
||
</div>
|
||
<div className="brand-subtitle">NNEXSPACE</div>
|
||
<div className="brand-description">
|
||
<p>专业的虚拟桌面基础设施解决方案</p>
|
||
<p>提供安全、高效、灵活的桌面云服务</p>
|
||
</div>
|
||
<div className="brand-features">
|
||
<div className="feature-item">
|
||
<span className="feature-icon">🔒</span>
|
||
<span>安全可靠</span>
|
||
</div>
|
||
<div className="feature-item">
|
||
<span className="feature-icon">⚡</span>
|
||
<span>高效管理</span>
|
||
</div>
|
||
<div className="feature-item">
|
||
<span className="feature-icon">🔄</span>
|
||
<span>灵活部署</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 右侧登录区域 */}
|
||
<div className="login-right">
|
||
<div className="login-form-container">
|
||
<div className="login-header">
|
||
<h2 className="login-title">系统登录</h2>
|
||
<p className="login-subtitle">欢迎使用NEXSPACE</p>
|
||
</div>
|
||
|
||
<Form
|
||
name="login"
|
||
onFinish={onFinish}
|
||
autoComplete="off"
|
||
size="large"
|
||
className="login-form"
|
||
>
|
||
<Form.Item
|
||
name="username"
|
||
rules={[{ required: true, message: '请输入用户名!' }]}
|
||
>
|
||
<Input
|
||
prefix={<UserOutlined className="input-icon" />}
|
||
placeholder="请输入用户名"
|
||
className="login-input"
|
||
/>
|
||
</Form.Item>
|
||
|
||
<Form.Item
|
||
name="password"
|
||
rules={[{ required: true, message: '请输入密码!' }]}
|
||
>
|
||
<Input.Password
|
||
prefix={<LockOutlined className="input-icon" />}
|
||
placeholder="请输入密码"
|
||
className="login-input"
|
||
/>
|
||
</Form.Item>
|
||
|
||
<Form.Item>
|
||
<Button
|
||
type="primary"
|
||
htmlType="submit"
|
||
loading={loading}
|
||
className="login-button"
|
||
block
|
||
>
|
||
{loading ? '登录中...' : '登录'}
|
||
</Button>
|
||
</Form.Item>
|
||
</Form>
|
||
|
||
<div className="login-tips">
|
||
<p>演示账号:admin / 123456</p>
|
||
</div>
|
||
|
||
<div className="login-footer">
|
||
<p>© 2025 紫光汇智科技有限公司 版权所有</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default LoginPage;
|