登录页
新建一个登录页
tsx
import { LockOutlined, UserOutlined } from "@ant-design/icons";
import { LoginForm, ProFormText } from "@ant-design/pro-components";
import { history } from "@umijs/max";
import { App } from "antd";
import styles from "./index.less";
type LoginParams = {
username: string;
password: string;
};
const LoginPage: React.FC = () => {
const { message } = App.useApp();
const handleSubmit = async (values: LoginParams) => {
// 模拟登录:成功后把 token 写入 localStorage
const token = `mock-token-${Date.now()}`;
localStorage.setItem("token", token);
message.success("登录成功");
history.push("/home");
};
return (
<div className={styles.container}>
<div className={styles.content}>
<LoginForm title="demo2" subTitle="用户登录" onFinish={handleSubmit}>
<ProFormText
name="username"
fieldProps={{
size: "large",
prefix: <UserOutlined />,
}}
placeholder="用户名"
rules={[
{
required: true,
message: "请输入用户名",
},
]}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: "large",
prefix: <LockOutlined />,
}}
placeholder="密码"
rules={[
{
required: true,
message: "请输入密码",
},
]}
/>
</LoginForm>
</div>
</div>
);
};
export default LoginPage;- 样式
less
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(135deg, #1677ff 0%, #0958d9 100%);
}
.content {
width: 100%;
max-width: 580px;
padding: 32px;
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
}新建拦截组件
- src/wrappers/auth.tsx
tsx
import { Navigate, Outlet } from "@umijs/max";
// 路由拦截:有 token 放行,没有则跳转到登录页
export default function AuthWrapper() {
const token = localStorage.getItem("token");
if (!token) {
return <Navigate to="/login" replace />;
}
return <Outlet />;
}修改 .umirc.ts
ts
import { defineConfig } from "@umijs/max";
export default defineConfig({
antd: {
appConfig: {
message: {
maxCount: 1,
},
},
},
access: {},
model: {},
initialState: {},
request: {},
layout: {
title: "@umijs/max",
},
routes: [
{
path: "/login",
component: "./Login",
layout: false,
},
{
path: "/",
redirect: "/home",
},
{
name: "首页",
path: "/home",
component: "./Home",
wrappers: ["@/wrappers/auth"],
},
{
name: "权限演示",
path: "/access",
component: "./Access",
wrappers: ["@/wrappers/auth"],
},
{
name: " CRUD 示例",
path: "/table",
component: "./Table",
wrappers: ["@/wrappers/auth"],
},
],
npmClient: "pnpm",
utoopack: {},
});