feat: 迭代
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
.login-container {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
background: #0a0e27;
|
||||
}
|
||||
|
||||
/* 左侧装饰区域 - 深色科技风 */
|
||||
.login-left {
|
||||
flex: 1;
|
||||
background: linear-gradient(135deg, #1a1f3a 0%, #0a0e27 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-decoration {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.decoration-circle {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.15) 0%, rgba(118, 75, 162, 0.15) 100%);
|
||||
animation: float 20s infinite ease-in-out;
|
||||
border: 1px solid rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.decoration-circle.circle-1 {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
top: -150px;
|
||||
right: -150px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.decoration-circle.circle-2 {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
bottom: -100px;
|
||||
left: -100px;
|
||||
animation-delay: 5s;
|
||||
}
|
||||
|
||||
.decoration-circle.circle-3 {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
top: 50%;
|
||||
left: 15%;
|
||||
animation-delay: 10s;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0) rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-40px) rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.login-brand {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.brand-icon {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.2) 0%, rgba(118, 75, 162, 0.2) 100%);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 40px;
|
||||
box-shadow: 0 12px 48px rgba(102, 126, 234, 0.3);
|
||||
border: 2px solid rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.brand-title {
|
||||
font-size: 56px;
|
||||
font-weight: 800;
|
||||
margin: 0 0 16px;
|
||||
color: #fff;
|
||||
letter-spacing: 3px;
|
||||
text-shadow: 0 4px 12px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
|
||||
.brand-subtitle {
|
||||
font-size: 22px;
|
||||
margin: 0 0 80px;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
font-weight: 600;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.brand-features {
|
||||
display: flex;
|
||||
gap: 50px;
|
||||
justify-content: center;
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.25) 0%, rgba(118, 75, 162, 0.25) 100%);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
border: 2px solid rgba(102, 126, 234, 0.4);
|
||||
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.feature-text {
|
||||
font-size: 17px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 右侧登录表单 */
|
||||
.login-right {
|
||||
width: 520px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 50px;
|
||||
box-shadow: -8px 0 32px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.login-form-wrapper {
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
.login-header {
|
||||
margin-bottom: 56px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
color: #0a0e27;
|
||||
margin: 0 0 16px;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
font-size: 17px;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.login-input {
|
||||
height: 52px;
|
||||
border-radius: 10px;
|
||||
font-size: 15px;
|
||||
border: 2px solid #e8e8e8;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.login-input:hover {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.login-input:focus,
|
||||
.login-input.ant-input-focused {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.login-input input {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
color: #999;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
height: 52px;
|
||||
border-radius: 10px;
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
||||
transition: all 0.3s;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.login-button:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
|
||||
.login-button:active {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
text-align: center;
|
||||
margin-top: 48px;
|
||||
padding-top: 32px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 1024px) {
|
||||
.login-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.login-right {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.login-right {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.login-form-wrapper {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Form, Input, Button, Card, message } from 'antd';
|
||||
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
||||
import { Form, Input, Button, message } from 'antd';
|
||||
import { UserOutlined, LockOutlined, SafetyOutlined } from '@ant-design/icons';
|
||||
import { loginByPassword } from '@/api/admin';
|
||||
import { useAuthStore } from '@/store/auth';
|
||||
import './Login.css';
|
||||
|
||||
const Login: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -25,22 +26,86 @@ const Login: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#001529' }}>
|
||||
<Card style={{ width: 400 }} title={<div style={{ textAlign: 'center', fontSize: 20, fontWeight: 600, color: '#1890ff' }}>平台管理后台</div>}>
|
||||
<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 className="login-container">
|
||||
{/* 左侧装饰区域 */}
|
||||
<div className="login-left">
|
||||
<div className="login-decoration">
|
||||
<div className="decoration-circle circle-1"></div>
|
||||
<div className="decoration-circle circle-2"></div>
|
||||
<div className="decoration-circle circle-3"></div>
|
||||
</div>
|
||||
<div className="login-brand">
|
||||
<div className="brand-icon">
|
||||
<SafetyOutlined style={{ fontSize: 64, color: '#fff' }} />
|
||||
</div>
|
||||
<h1 className="brand-title">品住会</h1>
|
||||
<p className="brand-subtitle">平台管理后台</p>
|
||||
<div className="brand-features">
|
||||
<div className="feature-item">
|
||||
<div className="feature-icon">✓</div>
|
||||
<div className="feature-text">商家管理</div>
|
||||
</div>
|
||||
<div className="feature-item">
|
||||
<div className="feature-icon">✓</div>
|
||||
<div className="feature-text">订单监控</div>
|
||||
</div>
|
||||
<div className="feature-item">
|
||||
<div className="feature-icon">✓</div>
|
||||
<div className="feature-text">数据分析</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 右侧登录表单 */}
|
||||
<div className="login-right">
|
||||
<div className="login-form-wrapper">
|
||||
<div className="login-header">
|
||||
<h2 className="login-title">欢迎回来</h2>
|
||||
<p className="login-subtitle">请登录您的管理员账号</p>
|
||||
</div>
|
||||
|
||||
<Form onFinish={onFinish} 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}
|
||||
block
|
||||
className="login-button"
|
||||
>
|
||||
登录
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<div className="login-footer">
|
||||
<p className="footer-text">© 2026 品住会. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user