Skip to content

登录页 ​

新建一个登录页 ​

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: {},
});