完成登录页面布局
This commit is contained in:
67
src/App.tsx
67
src/App.tsx
@@ -7,6 +7,8 @@ import ECommerce from './pages/Dashboard/ECommerce';
|
||||
import Create from './pages/Create';
|
||||
import Cate from './pages/Cate';
|
||||
import DefaultLayout from './layout/DefaultLayout';
|
||||
import Login from './pages/Login';
|
||||
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
function App() {
|
||||
@@ -21,6 +23,8 @@ function App() {
|
||||
setTimeout(() => setLoading(false), 1000);
|
||||
}, []);
|
||||
|
||||
const isLoginRoute = pathname === '/login';
|
||||
|
||||
return loading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
@@ -33,41 +37,54 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DefaultLayout>
|
||||
{isLoginRoute ? (
|
||||
<Routes>
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<>
|
||||
<PageTitle title="eCommerce Dashboard | TailAdmin - Tailwind CSS Admin Dashboard Template" />
|
||||
<ECommerce />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/create"
|
||||
path="/login"
|
||||
element={
|
||||
<>
|
||||
<PageTitle title="Calendar | TailAdmin - Tailwind CSS Admin Dashboard Template" />
|
||||
<Create />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/cate"
|
||||
element={
|
||||
<>
|
||||
<PageTitle title="Calendar | TailAdmin - Tailwind CSS Admin Dashboard Template" />
|
||||
<Cate />
|
||||
<Login />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</DefaultLayout>
|
||||
</ConfigProvider>
|
||||
) : (
|
||||
<DefaultLayout>
|
||||
<Routes>
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<>
|
||||
<PageTitle title="Thrive - 仪表盘" />
|
||||
<ECommerce />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/create"
|
||||
element={
|
||||
<>
|
||||
<PageTitle title="Thrive - 发挥灵感" />
|
||||
<Create />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/cate"
|
||||
element={
|
||||
<>
|
||||
<PageTitle title="Thrive - 分类管理" />
|
||||
<Cate />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</DefaultLayout>
|
||||
)}
|
||||
</ConfigProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { account, editUser, Login, UserInfo } from '@/types/user'
|
||||
import Request from '@/utils/request'
|
||||
|
||||
// 登录
|
||||
export const loginDataAPI = (data: Login) => Request<account>("POST", "/login", data)
|
||||
export const loginDataAPI = (data: Login) => Request<account>("POST", "/user/login", data)
|
||||
|
||||
// 获取用户信息
|
||||
export const getUserDataAPI = (id?: number) => Request<UserInfo>("GET", `/user/${id}`)
|
||||
|
||||
90
src/pages/Login/index.tsx
Normal file
90
src/pages/Login/index.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useForm } from 'antd/es/form/Form';
|
||||
import { Button, Form, Input, notification } from 'antd';
|
||||
import { UserOutlined, LockOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
||||
import { loginDataAPI } from '@/api/User';
|
||||
import { useUserStore } from '@/stores';
|
||||
|
||||
const LoginForm: React.FC = () => {
|
||||
const [form] = useForm();
|
||||
const [isPassVisible, setIsPassVisible] = useState(false);
|
||||
const store = useUserStore();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const returnUrl = new URLSearchParams(location.search).get('returnUrl') || '/home';
|
||||
|
||||
const onSubmit = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
const { data } = await loginDataAPI(values);
|
||||
store.token = data.token;
|
||||
store.user = data.user;
|
||||
|
||||
notification.success({
|
||||
message: 'success',
|
||||
description: `Hello ${data.user.name} 欢迎回来 🎉`,
|
||||
});
|
||||
|
||||
navigate(returnUrl);
|
||||
} catch (error) {
|
||||
console.error('Failed to login:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-screen h-screen flex justify-center items-center">
|
||||
<div className="overflow-hidden relative w-[400px] h-[380px] rounded-lg bg-white shadow-[4px_6px_200px_200px_rgba(121,122,243,0.1)]">
|
||||
<div className="flex flex-col justify-center items-center h-25 bg-primary text-white">
|
||||
<h3 className="text-3xl">Thrive</h3>
|
||||
<p className="text-gray-300 mt-2">现代化博客管理系统</p>
|
||||
</div>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={onSubmit}
|
||||
className='pt-5 px-10'
|
||||
size='large'
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="账号"
|
||||
rules={[
|
||||
{ required: true, message: '请输入账号' }
|
||||
]}
|
||||
>
|
||||
<Input prefix={<UserOutlined />} placeholder="请输入用户名" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="密码"
|
||||
rules={[
|
||||
{ required: true, message: '请输入密码' }
|
||||
]}
|
||||
>
|
||||
<Input.Password
|
||||
prefix={<LockOutlined />}
|
||||
type={isPassVisible ? 'text' : 'password'}
|
||||
placeholder="请输入密码"
|
||||
iconRender={visible =>
|
||||
visible ? (
|
||||
<EyeOutlined onClick={() => setIsPassVisible(!isPassVisible)} />
|
||||
) : (
|
||||
<EyeInvisibleOutlined onClick={() => setIsPassVisible(!isPassVisible)} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" className="w-full" block>登录</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginForm;
|
||||
Reference in New Issue
Block a user