当前位置: 首页 > news >正文

Umi从零搭建Ant Design Pro项目(2)

文章目录

  • 前言
  • 一、新增登录页面
    • 1.登录页面代码
      • 2.登录处理
    • 3.修改app.tsx
  • 二、说一下逻辑
    • 1. 流程图
    • 2. 注意点
  • 总结


前言

前面写了创建项目及修改一些配置。这一章写写登录页面。


一、新增登录页面

新增登录页面,会涉及Umi的目录结构。先看一下文档再动手。

1.登录页面代码

// src/pages/user/login.tsx
import {
  LockOutlined,
  MobileOutlined,
  UserOutlined,
} from '@ant-design/icons';
import {
  LoginForm,
  ProFormCaptcha,
  ProFormCheckbox,
  ProFormText,
} from '@ant-design/pro-components';
import { Divider, Space, Tabs, message } from 'antd';
import { useState } from 'react';
import { history,useModel } from '@umijs/max';
import { login } from "@/services/demo/UserController"; //该处代码下面见
import { flushSync } from 'react-dom'; //强刷新一下

type LoginType = 'phone' | 'account'; //看字面意思就可以了

export default () => {
  const items = [
    { label: '账户密码登录', key: 'account' },
    { label: '手机号登录', key: 'phone' },
  ];
  const [loginType, setLoginType] = useState<LoginType>('account');
  const { initialState, setInitialState } = useModel('@@initialState'); //注意一下,后面解释

  //写一个获取用户信息的函数
  const fetchUserInfo = async () => {
    const userInfo = await initialState?.fetchUserInfo?.(); //出现initialState了,后面解释
    if (userInfo) {
      flushSync(() => {
        setInitialState((s) => ({
          ...s,
          currentUser: userInfo,
        }));
      });
    }
  };

  const onSubmit = async (formData: API.LoginParams) => {
    try {
      const success = await login({ ...formData });
      if (success) {
        message.success("登录成功");
        await fetchUserInfo(); //调用获取用户信息函数
        history.push('/');
      }else{
        message.error("登录失败");
      }      
    }catch (error:any) {
      if(error.response){
        message.error(error.response.data.message);
      }else{
        message.error("未知错误");
      }
      
    }

  };
  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        height: '100vh',
        overflow: 'auto',
        backgroundImage:
        "url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
        backgroundSize: '100% 100%',
      }}
    >
      <LoginForm
        onFinish={onSubmit}
        title="AntDesgin Pro"
        subTitle="基于Umi从零搭建Ant Desgin Pro"

      >
        <Tabs
          centered
          items={items}
          activeKey={loginType}
          onChange={(activeKey) => setLoginType(activeKey as LoginType)}
        ></Tabs>

        {loginType === 'account' && (
          <>
            <ProFormText
              name="username"
              fieldProps={{
                size: 'large',
                prefix: <UserOutlined className={'prefixIcon'} />,
              }}
              placeholder={'请输入账号/邮箱/电话号码'}
              rules={[
                {
                  required: true,
                  message: '请输入用户名!',
                },
              ]}
            />
            <ProFormText.Password
              name="password"
              fieldProps={{
                size: 'large',
                prefix: <LockOutlined className={'prefixIcon'} />,
              }}
              placeholder={'请输入密码'}
              rules={[
                {
                  required: true,
                  message: '请输入密码!',
                },
              ]}
            />
          </>
        )}
        {loginType === 'phone' && (
          <>
            <ProFormText
              fieldProps={{
                size: 'large',
                prefix: <MobileOutlined className={'prefixIcon'} />,
              }}
              name="mobile"
              placeholder={'手机号'}
              rules={[
                {
                  required: true,
                  message: '请输入手机号!',
                },
                {
                  pattern: /^1\d{10}$/,
                  message: '手机号格式错误!',
                },
              ]}
            />
            <ProFormCaptcha
              fieldProps={{
                size: 'large',
                prefix: <LockOutlined className={'prefixIcon'} />,
              }}
              captchaProps={{
                size: 'large',
              }}
              placeholder={'请输入验证码'}
              captchaTextRender={(timing, count) => {
                if (timing) {
                  return `${count} ${'获取验证码'}`;
                }
                return '获取验证码';
              }}
              name="captcha"
              rules={[
                {
                  required: true,
                  message: '请输入验证码!',
                },
              ]}
              onGetCaptcha={async () => {
                message.success('获取验证码成功!验证码为:1234');
              }}
            />
          </>
        )}
        <div style={{ marginBlockEnd: 24 }}>
          <ProFormCheckbox noStyle name="autoLogin">
            自动登录
          </ProFormCheckbox>
          <a style={{ float: 'right' }}>忘记密码 </a>
        </div>
      </LoginForm>
    </div>
  );
};

2.登录处理

代码没有做优化,目前代码只是跑通。只为搞明白逻辑关系。

/* eslint-disable */
// src/services/demo/UserController.ts
import { request } from '@umijs/max';

/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
  return request<API.LoginResult>('/api/admin/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    data: body,
    ...(options || {}),
  });
}

/** 获取当前的用户 GET /api/currentUser */
export async function currentUser(options?: { [key: string]: any }) {
  return request<{
    data: API.CurrentUser;
  }>('/api/admin/currentUser', {
    method: 'GET',
    ...(options || {}),
  });
}

3.修改app.tsx

import { currentUser as queryCurrentUser } from './services/demo/UserController';

import { AvatarName }  from '@/components';
// 全局初始化数据配置,用于 Layout 用户信息和权限初始化
// 更多信息见文档:https://umijs.org/docs/api/runtime-config#getinitialstate

const loginPath = '/user/login';
export async function getInitialState(): Promise<{ name: string,currentUser?: API.CurrentUser; fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;}> {
  const fetchUserInfo = async () => {
    try {
      const msg = await queryCurrentUser({
        skipErrorHandler: true,
      });
      return msg.data;
    } catch (error) {
      history.push(loginPath);
    }
    return undefined;
  };

  const { location } = history; 
  if (![loginPath, '/user/register', '/user/register-result'].includes(location.pathname)) {
    const currentUser = await fetchUserInfo();
    return {
      fetchUserInfo,
      currentUser,
      name: '@umijs/max',
    };
  }
  return {
    fetchUserInfo,
    name: '@umijs/max',
  };
}

二、说一下逻辑

1. 流程图

和AntDesign Pro的流程基本一样。

非登录页面流程
登录页面流程
成功
成功
成功
失败
执行完整初始化
自动调用fetchUserInfo
用户信息
获取成功?
更新currentUser状态
渲染目标页面
跳过用户信息初始化
代码中未返回currentUser
当前是登录页面?
显示登录页面
用户提交认证?
调用fetchUserInfo
获取currentUser对象
跳转到首页
访问任何页面
执行应用初始化
getInitialState

2. 注意点

  • Login页面中的fetchUserInfo 调用了InitialState中的fetchUserInfo,并将获取的currentUser初始化,并flushSync了一下。
  • 用户认证与用户信息获取是分开的。
  • 在上一篇Umi从零搭建Ant Design Pro项目(1)中,我已经做了网络拦截,将获取的token进行了处理。就是说包括fetchUserInfo在内的网络请求都会带上token时,后端就会鉴权。

总结

今天就写这么多内容。

相关文章:

  • 每日一题----------文件流(创建文件方式三种)
  • 优化器/模型参数/超参数
  • Python生成requirements.txt的两种方法
  • 【数据分析】数据筛选(布尔索引:多个判断条件)
  • RHCE综合实验
  • LS-NET-004-简单二层环路解决(华为锐捷思科)
  • kotlin @JvmStatic的使用
  • 【C++】STL(1) - 序列容器
  • 在C#的MVC框架framework项目的使用ajax,及源码下载
  • 织梦DedeCMS后台发布文章增加“顶”和“踩”默认随机值,并可后台修改
  • [Windows] OfficeAI 助手 v0.3.20(长期免费,本地支持WPS/Word联动)
  • Java多线程与高并发专题——在 Thread 中多个 ThreadLocal 是怎么存储的?
  • langgraph简单Demo(使用langserve实现外部调用)
  • 解码软件需求的三个维度:从满足基础到创造惊喜
  • UMA架构下的GPU 显存
  • 4、MySQL的存储引擎有哪些?【中高频】
  • 蓝桥杯篇---按键长按与双击
  • 机试准备最后一天
  • electron框架(1.0)认识electron和基础创建
  • Elasticsearch基础教程:从入门到上手
  • 法学联合书单|法庭上的妇女
  • “水运江苏”“航运浙江”,江浙两省为何都在发力内河航运?
  • 俄乌拟在土耳其举行会谈,特朗普:我可能飞过去
  • 男子退机票被收票价90%的手续费,律师:虽然合规,但显失公平
  • 总导演揭秘十五运会闭幕式:赴一场星辰大海之约
  • 中国证监会印发2025年度立法工作计划