(Java项目)用户管理中心

项目地址

前端源代码:gitee
后端源代码:gitee

需求分析

 写一个通用型用户管理中心项目,以后如果写其他项目需要用到用户管理系统,可以直接套用该项目代码。

注意: 由于部分代码过长故而部分代码截图未截全

技术栈

前端:三件套(HTML,CSS,JavaScript),Ant Design + Umi + Ant Design Pro
后端:Java,Spring,SpringMVC,SpringBoot,Mybatis,Mybatis-Plus,Junit,MySQL

项目初始化

- 项目初始化方法
	* Github上搜现成的代码(由于是他人写的代码,直接拿来使用可能会出现未预料的错误,所以不推荐)
	* SpringBoot官方模板生成器(https://start.spring.io/)
	* 使用Idea上面集成的生成器(推荐)

前端初始化

1.浏览器搜索Ant Design Pro,点击开始使用后跳转到该页面
(Java项目)用户管理中心_第1张图片
2.根据教程进行初始化

打开cmd命令行输入
>npm i @ant-design/pro-cli -g
>pro create myapp
来初始化脚手架
	umi版本选择 umi@3
	使用简单的脚手架 simple
在命令行输入
>cd myapp && tyarn
	进入项目并安装依赖,tyarn需要提前安装
安装依赖时可能会发生依赖冲突错误,可尝试降低NodeJs的版本至16.13.0或更低,这里推荐使用NVM来自动管理Node版本,便于满足不同项目对Node版本的不同需求。

3.依赖安装完成后,使用WebStorm打开该文件夹myapp,在WebStorm终端里输入 yarn 来再次安装依赖。
4.在package.json文件中找到start并点击左侧三角启动按钮来启动项目进行测试。
在这里插入图片描述
项目成功启动:
(Java项目)用户管理中心_第2张图片
我们在浏览器打开下方显示的网址(http://localhost:8000 )
出现下面的界面代表项目运行成功!
(Java项目)用户管理中心_第3张图片
5.项目瘦身

  • package.json文件中找到"i18n-remove"并点击左侧的三角启动按钮来移除国际化
    在这里插入图片描述

  • 删除src目录下的locales文件夹(是用来国际化的)
    (Java项目)用户管理中心_第4张图片

  • 删除src目录下的e2e文件夹
    在这里插入图片描述

  • 删除src目录下的services目录下的swagger文件夹
    (Java项目)用户管理中心_第5张图片

  • 删除config目录下的oneapi.json文件
    (Java项目)用户管理中心_第6张图片
    进入config.ts文件,删除里面的“openAPI”部分
    在这里插入图片描述

  • 删除tests文件夹
    在这里插入图片描述

  • 删除jest.config.js文件
    在这里插入图片描述

  • 删除playwright.config.ts文件
    在这里插入图片描述
    前端初始化完毕!

后端初始化

1.Idea新建项目:
(Java项目)用户管理中心_第7张图片
注意SpringBoot版本不要选择3.0及以上!
选择如图六个依赖:

	Lombok
	Spring Boot DevTools
	Spring Configuration Processor
	MySQL Driver
	Spring Web
	MyBatis Framework

(Java项目)用户管理中心_第8张图片2.在pom.xml文件里添加依赖:

  • Mybatis-Plus

      
          com.baomidou
          mybatis-plus-boot-starter
          3.5.2
      
    
  • Junit

      
          junit
          junit
          4.13.2
          test
      
    

注意:添加依赖后需更新maven

3.将application.properties文件名改为application.yml并进行配置(注意将数据库,密码,用户名等改为自己的)

spring:
  application:
    name: user_center
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/user_center
    username: root
    password: 2469
server:
  port: 8080

(Java项目)用户管理中心_第9张图片
4.在com.example目录下添加mappermodel软件包
(Java项目)用户管理中心_第10张图片
后端初始化完毕!

添加后端登录功能

  1. 点击Idea右侧数据库按钮并选择数据源为MySQL
    (Java项目)用户管理中心_第11张图片
    然后链接数据库
    (Java项目)用户管理中心_第12张图片

  2. 使用MySQL数据库建立架构 user_center
    (Java项目)用户管理中心_第13张图片
    (Java项目)用户管理中心_第14张图片

  3. 然后在该架构中创建新表user,建表语句:

     create table user
     (
     id           bigint auto_increment comment 'id'
         primary key,
     username     varchar(256)                       null comment '用户昵称',
     userAccount  varchar(256)                       null comment '用户账号',
     avatarUrl    varchar(1024)                      null comment '用户头像',
     gender       tinyint                            null comment '性别',
     userPassword varchar(512)                       not null comment '密码',
     phone        varchar(128)                       null comment '电话',
     email        varchar(512)                       null comment '邮箱',
     userStatus   int      default 0                 not null comment '状态 0-正常',
     createTime   datetime default CURRENT_TIMESTAMP null comment '创建时间',
     updateTime   datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
     isDelete     tinyint  default 0                 not null comment '是否删除'
     )
     comment '用户表';
    
  4. Idea设置=》插件里搜索并安装MyBatisX插件(安装后需要重启Idea)
    (Java项目)用户管理中心_第15张图片
    在这里插入图片描述
    然后再新建的user表上右键选择MybatisX-Generator
    (Java项目)用户管理中心_第16张图片
    然后如下图填写:
    (Java项目)用户管理中心_第17张图片
    (Java项目)用户管理中心_第18张图片
    点击Finish来自动生成基础文件,然后将生成的文件移动至应属目录下
    domin移至model目录下
    UserMapper移至mapper目录下
    UserService移至service目录下
    UserServiceImpl移至service.impl目录下
    注意更改文件内的相关路径

  5. 在启动类UserCenterApplication里添加注解**@MapperScan(“com.example.mapper”)**
    (Java项目)用户管理中心_第19张图片

  6. pom.xml文件里添加commons-lang3依赖(依赖网站:https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 )

     
         org.apache.commons
         commons-lang3
         3.12.0
     
    
  7. UserService接口里添加接口方法userRegister

     long userRegister(String userAccount,String userPassword,String checkPassword);
    

(Java项目)用户管理中心_第20张图片
并在UserServiceImpl类里实现该方法

@Override
public long userRegister(String userAccount, String userPassword, String checkPassword) {
    // 密码,账号,二次校验密码 不能为空
    if(StringUtils.isAnyBlank(userPassword,userAccount,checkPassword)){
        return -1;
    }
    // 账号长度不小于4
    if(userAccount.length()<4){
        return -1;
    }
    // 密码和二次校验密码 长度不小于8
    if (userPassword.length()<8||checkPassword.length()<8){
        return -1;
    }
    // 账号不能含有特殊字符
    String validPattern="[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、? ]";
    Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
    if (matcher.find()){
        return -1;
    }
    // 密码与二次校验密码需一致
    if (!userPassword.equals(checkPassword)){
        return -1;
    }
    // 账号不可重复
    QueryWrapper queryWrapper=new QueryWrapper<>();
    queryWrapper.eq("userAccount",userAccount);
    long count = this.count(queryWrapper);
    if (count>0){
        return -1;
    }
    // 对密码进行加盐加密(加盐就是让密码加密后更复杂)
    final String SALT="lwy";
    String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
    // 建立用户实体
    User user =new User();
    user.setUserAccount(userAccount);
    user.setUserPassword(encryptPassword);
    // 存储用户信息
    boolean result = this.save(user);
    // 若返回null则不利于后续处理
    if(!result){
        return -1;
    }
    // 用户注册成功
    return 0;
}

(Java项目)用户管理中心_第21张图片

  1. test.java.com.example.service目录下新建UserServiceTest
    (Java项目)用户管理中心_第22张图片
    在类上添加**@SpringBootTest**注解
    在这里插入图片描述
    注入 UserService
    (Java项目)用户管理中心_第23张图片
    编写测试方法 testUserRegister

     @Test
     void testUserRegister(){
         String userAccount = "";
         String userPassword = "12345678";
         String checkPassword= "12345678";
         long result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertEquals(-1, result);
         userAccount="lwy";
         result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertEquals(-1, result);
         userAccount="liwy";
         userPassword="123456";
         result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertEquals(-1, result);
         userAccount="li wy";
         userPassword="12345678";
         checkPassword="12345678";
         result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertEquals(-1, result);
         userAccount="liwy";
         checkPassword="123456789";
         result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertEquals(-1, result);
         userAccount="test";
         checkPassword="12345678";
         result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertEquals(-1, result);
         userAccount="1234";
         result = userService.userRegister(userAccount, userPassword, checkPassword);
         Assertions.assertTrue(result>=0);
     }
    

(Java项目)用户管理中心_第24张图片
测试成功即可

  1. 新增model.domin.request.UserRegisterRequest文件

    /**
     * 用户注册请求体
     *
     * @author lwy
     */
    @Data
    public class UserRegisterRequest implements Serializable {
        private static final long serialVersionUID= 504966900305465423L;
    
        private String userAccount;
    
        private String userPassword;
    
        private String checkPassword;
    }
    

(Java项目)用户管理中心_第25张图片

  1. controller.UserController文件里添加register方法

    @PostMapping("/register")
    public Long register(@RequestBody UserRegisterRequest userRegisterRequest){
        if (userRegisterRequest==null) {
            return null;
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)){
            return null;
        }
        return userService.userRegister(userAccount, userPassword, checkPassword);
    }
    

(Java项目)用户管理中心_第26张图片

在数据库里添加字段

application.yml配置文件里添加逻辑删除配置

  global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

(Java项目)用户管理中心_第27张图片

Idea的数据库里右键点击我们的表user,点击修改表
(Java项目)用户管理中心_第28张图片
新增userRole
(Java项目)用户管理中心_第29张图片
点击确定
再次通过MybatisX-Generator生成文件
在这里插入图片描述
(Java项目)用户管理中心_第30张图片
用新生成的User文件覆盖原本的User文件,并在isDelete字段上添加**@TableLogic**逻辑删除注解
(Java项目)用户管理中心_第31张图片
更改UserMapper.xml文件里的路径引用
(Java项目)用户管理中心_第32张图片
删除其它新生成的文件

完成后端登录功能

  1. 新增model.domin.request.UserLoginRequest文件

     /**
      * 用户登录请求体
      *
      * @author lwy
      */
     @Data
     public class UserLoginRequest implements Serializable {
         private static final long serialVersionUID= -7188479473325271448L;
     
         private String userAccount;
     
         private String userPassword;
     
     }
    

(Java项目)用户管理中心_第33张图片

  1. 新建com.example.content.UserContent文件
    (Java项目)用户管理中心_第34张图片

  2. UserContent文件里添加用户登录状态键:

    String USER_LOGIN_STATE="userLoginState";
    

(Java项目)用户管理中心_第35张图片

  1. 将密码盐提至文件前端以使文件内其它方法可调用
    (Java项目)用户管理中心_第36张图片

  2. userService文件里添加userLogin方法声明

     User userLogin(String userAccount, String userPassword , HttpServletRequest request);
    

(Java项目)用户管理中心_第37张图片

  1. userServiceImpl文件里实现该方法

     @Override
     public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {
     // 密码,账号不能为空
     if(StringUtils.isAnyBlank(userPassword,userAccount)){
         return null;
     }
     // 账号长度不小于4
     if(userAccount.length()<4){
         return null;
     }
     // 密码和二次校验密码 长度不小于8
     if (userPassword.length()<8){
         return null;
     }
     // 账号不能含有特殊字符
     String validPattern="[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”		 “’。,、? ]";
     Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
     if (matcher.find()){
         return null;
     }
     String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
     // 账号不可重复
     QueryWrapper queryWrapper=new QueryWrapper<>();
     queryWrapper.eq("userAccount",userAccount);
     queryWrapper.eq("userPassword",encryptPassword);
     User user = userMapper.selectOne(queryWrapper);
     //用户不存在
     if(user == null){
         log.info("User login failed,userAccount cannot match userPassword");
         return null;
     }
     //用户脱敏
     User safetyUser=getSafetyUser(user);
     //记录用户的登录状态
     request.getSession().setAttribute(USER_LOGIN_STATE,safetyUser);
    
     return safetyUser;
    }
    

(Java项目)用户管理中心_第38张图片

  1. UserService文件里声明getSafetyUser方法

       User getSafetyUser(User originUser);
    

(Java项目)用户管理中心_第39张图片

UserServiceImpl文件里新增getSafetyUser方法

	   /**
     * 用户脱敏
     *
     * @param originUser 脱敏前的用户
     * @return 脱敏后用户信息
     */
   	 @Override
  	 	 public User getSafetyUser(User originUser) {
        User safetyUser=new User();
        safetyUser.setId(originUser.getId());
        safetyUser.setUsername(originUser.getUsername());
        safetyUser.setUserAccount(originUser.getUserAccount());
        safetyUser.setAvatarUrl(originUser.getAvatarUrl());
        safetyUser.setGender(originUser.getGender());
        safetyUser.setPhone(originUser.getPhone());
        safetyUser.setEmail(originUser.getEmail());
        safetyUser.setUserRole(originUser.getUserRole());
        safetyUser.setUserStatus(originUser.getUserStatus());
        safetyUser.setCreateTime(originUser.getCreateTime());
        return safetyUser;
    }	  

(Java项目)用户管理中心_第40张图片

  1. UserController文件里新增login方法

     @PostMapping("/login")
     public User login(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request){
         if (userLoginRequest==null) {
             return null;
         }
         String userAccount = userLoginRequest.getUserAccount();
         String userPassword = userLoginRequest.getUserPassword();
         if (StringUtils.isAnyBlank(userAccount, userPassword)){
             return null;
         }
         return userService.userLogin(userAccount, userPassword,request);
     }
    

(Java项目)用户管理中心_第41张图片

在后端添加查询方法

UserController文件里添加isAdmin方法来判断是否为管理员

 /**
     * 是否为管理员
     *
     * @param request
     * @return 若是管理员则返回true
     */
    private boolean isAdmin(HttpServletRequest request){
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user=(User) userObj;
        return user != null && user.getUserRole() == ADMIN_USER;
    }

(Java项目)用户管理中心_第42张图片

UserController文件里添加searchUsers方法

@GetMapping("/search")
public List searchUsers(String username,HttpServletRequest request){
    if(!isAdmin(request)){
        return new ArrayList<>();
    }
    QueryWrapper queryWrapper=new QueryWrapper<>();
    if (StringUtils.isNotBlank(username)){
        // 模糊查询
        queryWrapper.like("username",username);
    }
    List list = userService.list(queryWrapper);
    return list.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList());
}

(Java项目)用户管理中心_第43张图片

在后端添加删除功能

UserController文件里添加deleteUser方法

@PostMapping("/delete")
public boolean deleteUser(@RequestBody Long id,HttpServletRequest request){
    if (!isAdmin(request)){
        return false;
    }
    if (id<=0){
        return false;
    }
    return userService.removeById(id);
}

(Java项目)用户管理中心_第44张图片

完成前端登录功能

  1. package.json文件里找到start:dev并点击其左侧的三角启动按钮来启动前端项目
    在这里插入图片描述

  2. 找到src.pages.user.Login.index.tsx文件
    (Java项目)用户管理中心_第45张图片

找到**Footer **部分
在这里插入图片描述
按住Ctrl键并鼠标左键点进去
更改登录界面的样式
更改defaultMessageUncommen出品(可自定义修改)
在这里插入图片描述

更改DefaultFooter部分

Uncommon github,
          href: 'https://github.com/15222039615',
          blankTarget: true,
        },
        {
          key: 'gitee',
          title: 'Uncommon gitee',
          href: 'https://gitee.com/Uncommen',
          blankTarget: true,
        },
      ]}
    />

(Java项目)用户管理中心_第46张图片
效果:
在这里插入图片描述
新建src.constants.index.ts文件
(Java项目)用户管理中心_第47张图片
在该文件里添加要用到的常量

export const SYSTEM_LOG0 = "https://www.toopic.cn/public/uploads/small/163756299623163756299625.png"

export const CSDN = "https://blog.csdn.net/Uncommen?spm=1010.2135.3001.5343"

在这里插入图片描述

回到src.pages.user.Login.index.tsx文件
添加导入

import {CSDN, SYSTEM_LOG0} from "@/constants";

在这里插入图片描述

找到LoginForm部分,修改Logo信息
(Java项目)用户管理中心_第48张图片
效果:
在这里插入图片描述
删除LoginForm部分的actions(删除其它登录方式)
(Java项目)用户管理中心_第49张图片
删除LoginForm部分的Tabs内的手机号登录
在这里插入图片描述
将下面的LoginMessage改为错误的账号和密码在这里插入图片描述
在该文件内按Ctrl+R键全局替换用户名账号
placeholder改为“请输入账号”
(Java项目)用户管理中心_第50张图片
placeholder改为“请输入密码”
(Java项目)用户管理中心_第51张图片
ProFormText部分的mobile类型删除
(Java项目)用户管理中心_第52张图片
这部分也删除
在这里插入图片描述
更改后面的忘记密码信息
(Java项目)用户管理中心_第53张图片
效果:
(Java项目)用户管理中心_第54张图片
找到src/services/ant-design-pro/typings.d.ts文件,重构LoginParams内的字段usernamepassworduserAccountuserPassword
(Java项目)用户管理中心_第55张图片
(Java项目)用户管理中心_第56张图片
找到src/services/ant-design-pro/api.ts文件,更改其中的登录路径为*/api/user/login*:
(Java项目)用户管理中心_第57张图片
找到src/app.tsx文件,添加请求配置

export const request: RequestConfig = {
  timeout: 10000,
}

(Java项目)用户管理中心_第58张图片
找到config/proxy.ts文件,修改代理为 http://localhost:8080
(Java项目)用户管理中心_第59张图片
在后端application.yml文件里添加配置

  servlet:
    context-path: /api

(Java项目)用户管理中心_第60张图片
在前端src/pages/user/Login/index.tsx文件内全局替换usernameuserAccount
(Java项目)用户管理中心_第61张图片
全局替换passworduserPassword(注意区分大小写)
(Java项目)用户管理中心_第62张图片
ProFormText.Password部分添加密码校验规则
(Java项目)用户管理中心_第63张图片
全局替换msguser
更改登录成功条件 user.status ==== ‘ok’user
(Java项目)用户管理中心_第64张图片

测试登录功能

启动前后端项目
使用真实的数据登录
显示登陆成功(按F12打开开发者工具)
(Java项目)用户管理中心_第65张图片
并且得到后端传回的响应数据
(Java项目)用户管理中心_第66张图片
测试成功!

完成前端注册功能

  1. 进入该文件src/pages/user/Login/index.tsx,新增 新用户注册 选项并添加分隔符:

     
    }> 自动登录 新用户注册 忘记密码

(Java项目)用户管理中心_第67张图片
效果图:
在这里插入图片描述

  1. 复制src/pages/user/Login该文件并粘贴到src/pages/user路径下,注意改名为 Register
    (Java项目)用户管理中心_第68张图片
    删除src/pages/user/Register/index.tsx文件内的:

     const fetchUserInfo = async () => {
       const userInfo = await initialState?.fetchUserInfo?.();
       if (userInfo) {
         await setInitialState((s) => ({
           ...s,
           currentUser: userInfo,
         }));
       }
     };
    

     const { initialState, setInitialState } = useModel('@@initialState');
    

     await fetchUserInfo();
    

     
       自动登录
     
    

     	
    

     const [userLoginState, setUserLoginState] = useState({});
    

     const { status, type: loginType } = userLoginState;
    

     {status === 'error' && loginType === 'account' && (
       
     )}
    

     const LoginMessage: React.FC<{
       content: string;
     }> = ({ content }) => (
       
     );
    

    可以按住 Alt + Ctrl + O 删除所有未使用到的引用

  2. 按住Ctrl + R替换文件内的LoginRegister,注意LoginForm无需更改

  3. LoginForm下添加代码:

     submitter={{
        searchConfig: {
          submitText: '注册'
        }
       }}
    

(Java项目)用户管理中心_第69张图片

  1. 添加 校验密码 代码:

     ,
             }}
             placeholder="请再次输入密码"
             rules={[
               {
                 required: true,
                 message: '确认密码是必填项!',
               },
               {
                 min: 8,
                 type: "string",
                 message: '密码长度不小于 8!',
               },
             ]}
           />
    

(Java项目)用户管理中心_第70张图片

  1. 删除代码:

      
    }> 自动登录 新用户注册 忘记密码

(Java项目)用户管理中心_第71张图片

  1. 进入src/services/ant-design-pro/typings.d.ts文件内,添加注册参数:

      type RegisterParams = {
     userAccount?: string;
     userPassword?: string;
     checkPassword?: string;
     type?: string;
     };
    

在这里插入图片描述

  1. 进入src/services/ant-design-pro/api.ts文件内,添加注册接口代码:

     export async function register(body: API.RegisterParams, options?: { [key: string]: any }) {
       return request('/api/user/register', {
         method: 'POST',
         headers: {
           'Content-Type': 'application/json',
         },
         data: body,
         ...(options || {}),
       });
     }
    

    (Java项目)用户管理中心_第72张图片
    添加搜索用户接口代码:

     export async function searchUsers(options?: { [key: string]: any }) {
       return request('/api/user/search', {
         method: 'GET',
         ...(options || {}),
       });
     }
    

(Java项目)用户管理中心_第73张图片

  1. 添加(更改)注册成功后跳转回登录页面代码:

      const id  = await register(values);
       if (id > 0) {
         const defaultLoginSuccessMessage = '注册成功!';
         message.success(defaultLoginSuccessMessage);
         /** 此方法会跳转到 redirect 参数所在的位置 */
         if (!history) return;
         const { query } = history.location;
         history.push({
           pathname: '/user/login',
           query,
         });
         return;
       } else {
         throw new Error(`redirect error id = ${id}`);
       }
    

(Java项目)用户管理中心_第74张图片

  1. config/routes.ts内添加注册路由:

      {name: '注册', path: '/user/register', component: './user/Register'},
    

(Java项目)用户管理中心_第75张图片

  1. 修改后端 UserServiceImpl 类里的 UserRegister 方法的返回值为 user.getId()
    (Java项目)用户管理中心_第76张图片

  2. 删除并更改src/pages/Admin/UserManage/index.tsx为:

    import React from 'react';
    
    const UserManage: React.FC = () => {
      return (
        
    ); }; export default UserManage;
  3. 在浏览器进入https://procomponents.ant.design/网站,在组件里找到高级表格
    (Java项目)用户管理中心_第77张图片
    展开并复制上图表格的代码:

    import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons';
    import type { ActionType, ProColumns } from '@ant-design/pro-components';
    import { ProTable, TableDropdown } from '@ant-design/pro-components';
    import { Button, Dropdown, Space, Tag } from 'antd';
    import { useRef } from 'react';
    import request from 'umi-request';
    export const waitTimePromise = async (time: number = 100) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(true);
        }, time);
      });
    };
    
    export const waitTime = async (time: number = 100) => {
      await waitTimePromise(time);
    };
    
    type GithubIssueItem = {
      url: string;
      id: number;
      number: number;
      title: string;
      labels: {
        name: string;
        color: string;
      }[];
      state: string;
      comments: number;
      created_at: string;
      updated_at: string;
      closed_at?: string;
    };
    
    const columns: ProColumns[] = [
      {
        dataIndex: 'index',
        valueType: 'indexBorder',
        width: 48,
      },
      {
        title: '标题',
        dataIndex: 'title',
        copyable: true,
        ellipsis: true,
        tip: '标题过长会自动收缩',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
      },
      {
        disable: true,
        title: '状态',
        dataIndex: 'state',
        filters: true,
        onFilter: true,
        ellipsis: true,
        valueType: 'select',
        valueEnum: {
          all: { text: '超长'.repeat(50) },
          open: {
            text: '未解决',
            status: 'Error',
          },
          closed: {
            text: '已解决',
            status: 'Success',
            disabled: true,
          },
          processing: {
            text: '解决中',
            status: 'Processing',
          },
        },
      },
      {
        disable: true,
        title: '标签',
        dataIndex: 'labels',
        search: false,
        renderFormItem: (_, { defaultRender }) => {
          return defaultRender(_);
        },
        render: (_, record) => (
          
            {record.labels.map(({ name, color }) => (
              
                {name}
              
            ))}
          
        ),
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'created_at',
        valueType: 'date',
        sorter: true,
        hideInSearch: true,
      },
      {
        title: '创建时间',
        dataIndex: 'created_at',
        valueType: 'dateRange',
        hideInTable: true,
        search: {
          transform: (value) => {
            return {
              startTime: value[0],
              endTime: value[1],
            };
          },
        },
      },
      {
        title: '操作',
        valueType: 'option',
        key: 'option',
        render: (text, record, _, action) => [
           {
              action?.startEditable?.(record.id);
            }}
          >
            编辑
          ,
          
            查看
          ,
           action?.reload()}
            menus={[
              { key: 'copy', name: '复制' },
              { key: 'delete', name: '删除' },
            ]}
          />,
        ],
      },
    ];
    
    export default () => {
      const actionRef = useRef();
      return (
        
          columns={columns}
          actionRef={actionRef}
          cardBordered
          request={async (params = {}, sort, filter) => {
            console.log(sort, filter);
            await waitTime(2000);
            return request<{
              data: GithubIssueItem[];
            }>('https://proapi.azurewebsites.net/github/issues', {
              params,
            });
          }}
          editable={{
            type: 'multiple',
          }}
          columnsState={{
            persistenceKey: 'pro-table-singe-demos',
            persistenceType: 'localStorage',
            onChange(value) {
              console.log('value: ', value);
            },
          }}
          rowKey="id"
          search={{
            labelWidth: 'auto',
          }}
          options={{
            setting: {
              listsHeight: 400,
            },
          }}
          form={{
            // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
            syncToUrl: (values, type) => {
              if (type === 'get') {
                return {
                  ...values,
                  created_at: [values.startTime, values.endTime],
                };
              }
              return values;
            },
          }}
          pagination={{
            pageSize: 5,
            onChange: (page) => console.log(page),
          }}
          dateFormatter="string"
          headerTitle="高级表格"
          toolBarRender={() => [
            ,
            
              
            ,
          ]}
        />
      );
    };
    
  4. 删除代码:

     {
       disable: true,
    	title: '标签',
       dataIndex: 'labels',
     search: false,
      renderFormItem: (_, { defaultRender }) => {
         return defaultRender(_);
       },
       render: (_, record) => (
         
           {record.labels.map(({ name, color }) => (
             
               {name}
         
           ))}
         
       ),
     },
    

    	disable: true,
    	title: '状态',
    	dataIndex: 'state',
    	filters: true,
    	onFilter: true,
    	ellipsis: true,
    

    	
      
    
    

    toolBarRender={() => [
      ,
    
    ]}
    

    	formItemProps: {
      rules: [
        {
          required: true,
          message: '此项为必填项',
        },
      ],
    },
    

    {
      title: '创建时间',
      key: 'showTime',
      dataIndex: 'created_at',
      valueType: 'date',
      sorter: true,
      hideInSearch: true,
    },
    {
      title: '创建时间',
      dataIndex: 'created_at',
      valueType: 'dateRange',
      hideInTable: true,
      search: {
        transform: (value) => {
          return {
            startTime: value[0],
            endTime: value[1],
          };
        },
      },
    },
    

    	return request<{
      data: CurrentUser[];
    }>('https://proapi.azurewebsites.net/github/issues', {
      params,
    });
    
  5. 改写列信息:

    	  {
        dataIndex: 'id ',
        valueType: 'indexBorder',
        width: 48,
      },
      {
        title: '用户名',
        dataIndex: 'username',
        copyable: true,
      },
      {
        title: '用户账号',
        dataIndex: 'userAccount',
        copyable: true,
      },
      {
        title: '头像',
        dataIndex: 'avatarUrl',
        render: (_, record) => {
          if (record.avatarUrl)
            return 
          return 
        },
        copyable: true,
      },
      {
        title: '性别',
        dataIndex: 'gender',
      },
      {
        title: '电话',
        dataIndex: 'phone',
        copyable: true,
      },
      {
        title: '邮件',
        dataIndex: 'email',
        copyable: true,
      },
      {
        title: '状态',
        dataIndex: 'userStatus',
      },
      {
        title: '角色',
        dataIndex: 'userRole',
        valueType: 'select',
        valueEnum: {
          0: {
            text: '普通用户',
            status: 'Default',
          },
          1: {
            text: '管理员',
            status: 'Success',
          },
        },
      },
      {
        title: '创建时间',
        dataIndex: 'createTime',
        valueType: 'date',
      },
    
  6. 进入src/services/ant-design-pro/api.ts文件内,添加获取当前用户接口:

    	/** 获取当前的用户 GET /api/user/current */
    export async function currentUser(options?: { [key: string]: any }) {
      return request< API.CurrentUser >('/api/user/current', {
        method: 'GET',
        ...(options || {}),
      });
    }
    
  7. 进入src/app.tsx文件内
    添加常量:

    const NO_NEED_WHITE_LIST=['/user/register',loginPath];
    

(Java项目)用户管理中心_第78张图片
这边也要改写一下:
(Java项目)用户管理中心_第79张图片
达到此效果便OK了:
(Java项目)用户管理中心_第80张图片

完成后端基本功能

  1. user表中新增planetCode
    (Java项目)用户管理中心_第81张图片
    再次通过MybatisX-Generator功能生成代码
    在这里插入图片描述
    注意修改src/main/resources/mapper/UserMapper.xml文件内容的路径引用
    (Java项目)用户管理中心_第82张图片
    将新生成的实体类User里的字段复制粘贴到我们自己的User实体类里

      /**
      * 星球编号
      */
     private String planetCode;
    

(Java项目)用户管理中心_第83张图片
删除新生成的generator文件包
在文件src/main/java/com/example/model/domain/request/UserRegisterRequest.java里添加字段planetCode
(Java项目)用户管理中心_第84张图片
注意在src/test/java/com/example/service/UserServiceTest.java测试类里添加planetCode相关字段内容:
(Java项目)用户管理中心_第85张图片

  1. 新增src/main/java/com/example/common/ErrorCode.java错误码枚举类

     package com.example.common;
     
     /**
      * 错误码
      *
      * @author Uncommon
      */
     public enum ErrorCode {
         SUCCESS(0,"OK",""),
         PARAMS_ERROR(40000,"请求参数错误",""),
         NULL_ERROR(40001,"请求参数为空",""),
         NOT_LOGIN(40100,"未登录",""),
         NO_AUTH(40101,"无权限",""),
         SYSTEM_ERROR(50000,"系统内部异常","");
         private final int code;
     
         // 状态码信息
         private final String message;
     
         // 状态码详情
         private final String description;
     
         ErrorCode(int code, String message, String description) {
             this.code = code;
             this.message = message;
             this.description = description;
         }
     
         public int getCode() {
             return code;
         }
     
         public String getMessage() {
             return message;
         }
     
         public String getDescription() {
             return description;
         }
     }
    

(Java项目)用户管理中心_第86张图片

  1. 新增src/main/java/com/example/common/BaseResponse.java通用返回类

     package com.example.common;
     
     import lombok.Data;
     
     import java.io.Serializable;
     
     /**
      * 通用返回类
      *
      * @param 
      * @author Uncommon
      */
     @Data
     public class BaseResponse implements Serializable {
         // 返回码
         private int code;
     
         // 返回值信息
         private String message;
     
         // 返回值数据
         private T data;
     
         // 返回值描述
         private String description;
     
         public BaseResponse(int code, T data, String message,String description) {
             this.code = code;
             this.message = message;
             this.data = data;
             this.description = description;
         }
         public BaseResponse(int code, T data,String message){
             this(code, data,message,"");
         }
         public BaseResponse(int code, T data){
             this(code, data,"","");
         }
         public BaseResponse(ErrorCode errorCode){
             this(errorCode.getCode(),null,errorCode.getMessage(),errorCode.getDescription());
         }
     
     }
    

(Java项目)用户管理中心_第87张图片

  1. 新增src/main/java/com/example/common/ResultUtils.java工具类:

     package com.example.common;
     
     /**
      *  统一返回工具类
      *
      * @author Uncommon
      */
     public class ResultUtils {
     
         /**
          * 成功
          *
          * @param data
          * @return
          * @param 
          */
         public static  BaseResponse success(T data) {
             return new BaseResponse<>(0,data,"OK");
         }
     
         /**
          * 失败
          *
          * @param errorCode
          * @return
          * @param 
          */
         public static  BaseResponse error(ErrorCode errorCode) {
             return new BaseResponse<>(errorCode);
         }
     
         /**
          * 失败
          *
          * @param errorCode
          * @param message
          * @param description
          * @return
          */
         public static BaseResponse error(ErrorCode errorCode, String message,String description) {
             return new BaseResponse(errorCode.getCode(),null,message,description);
         }
     
         /**
          * 失败
          *
          * @param errorCode
          * @param description
          * @return
          */
         public static BaseResponse error(ErrorCode errorCode,String description) {
             return new BaseResponse(errorCode.getCode(),null,errorCode.getMessage(),description);
         }
     
         /**
          * 失败
          *
          * @param code
          * @param message
          * @param description
          * @return
          */
         public static BaseResponse error(int code, String message,String description) {
             return new BaseResponse(code,null,message,description);
         }
     }
    

(Java项目)用户管理中心_第88张图片

  1. 新增src/main/java/com/example/exception/BusinessException.java异常类:

     package com.example.exception;
     
     import com.example.common.ErrorCode;
     
     /**
      *  自定义异常类
      *
      * @author Uncommon
      */
     public class BusinessException extends RuntimeException{
         private final int code;
     
         private final String description;
     
         public BusinessException(int code,String message ,String description) {
             super(message);
             this.code = code;
             this.description = description;
         }
         public BusinessException(ErrorCode errorCode) {
             super(errorCode.getMessage());
             this.code = errorCode.getCode();
             this.description = errorCode.getDescription();
         }
         public BusinessException(ErrorCode errorCode,String description) {
             super(errorCode.getMessage());
             this.code = errorCode.getCode();
             this.description = description;
         }
     
         public int getCode() {
             return code;
         }
     
         public String getDescription() {
             return description;
         }
     }
    

(Java项目)用户管理中心_第89张图片

  1. 新增src/main/java/com/example/exception/GlobalExceptionHandler.java全局异常处理器:
package com.example.exception;

import com.example.common.BaseResponse;
import com.example.common.ErrorCode;
import com.example.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器
 *
 * @author Uncommon
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(BusinessException.class)
    public BaseResponse businessExceptionHandler(BusinessException e){
        log.error("businessException: "+e.getMessage(),e);
        return ResultUtils.error(e.getCode(),e.getMessage(),e.getDescription());
    }

    @ExceptionHandler(RuntimeException.class)
    public BaseResponse runtimeExceptionHandler(RuntimeException e){
        log.error("runtimeException: ",e);
        return ResultUtils.error(ErrorCode.SYSTEM_ERROR,e.getMessage(),"");
    }
}

(Java项目)用户管理中心_第90张图片

  1. 更改src/main/java/com/example/service/impl/UserServiceImpl.java类的异常返回(注意接口UserService内的相应参数也要改)
package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.ErrorCode;
import com.example.common.ResultUtils;
import com.example.exception.BusinessException;
import com.example.mapper.UserMapper;
import com.example.model.domain.User;
import com.example.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.example.content.UserContent.USER_LOGIN_STATE;

/**
 * 用户服务实现类
 *
* @author lwy
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;
    /**
     * 对密码进行加盐加密(加盐就是让密码加密后更复杂)
     */
    private static final String SALT="lwy";


    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword,String planetCode) {
        // 密码,账号,二次校验密码 不能为空
        if(StringUtils.isAnyBlank(userPassword,userAccount,checkPassword,planetCode)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }
        // 账号长度不小于4
        if(userAccount.length()<4){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号过短");
        }
        // 密码和二次校验密码 长度不小于8
        if (userPassword.length()<8||checkPassword.length()<8){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码过短");
        }
        // 星球编号长度不能大于5
        if (planetCode.length() > 5){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"星球编号过长");
        }
        // 账号不能含有特殊字符
        String validPattern="[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、? ]";
        Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号不合法");
        }
        // 密码与二次校验密码需一致
        if (!userPassword.equals(checkPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不一致");
        }
        // 账号不可重复
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("userAccount",userAccount);
        long count = this.count(queryWrapper);
        if (count>0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号重复");
        }
        // 星球编号不可重复
        queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("planetCode",planetCode);
        count = this.count(queryWrapper);
        if (count>0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"新球编号重复");
        }
        // 加密密码
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        // 建立用户实体
        User user =new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setPlanetCode(planetCode);
        // 存储用户信息
        boolean result = this.save(user);
        // 若返回null则不利于后续处理
        if(!result){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"注册失败");
        }
        // 用户注册成功
        return user.getId();
    }

    @Override
    public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        // 密码,账号不能为空
        if(StringUtils.isAnyBlank(userPassword,userAccount)){
            throw new BusinessException(ErrorCode.NULL_ERROR,"账号或密码不能为空");
        }
        // 账号长度不小于4
        if(userAccount.length()<4){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号过短");
        }
        // 密码和二次校验密码 长度不小于8
        if (userPassword.length()<8){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码过短");
        }
        // 账号不能含有特殊字符
        String validPattern="[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、? ]";
        Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号不合法");
        }
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        // 账号不可重复
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("userAccount",userAccount);
        queryWrapper.eq("userPassword",encryptPassword);
        User user = userMapper.selectOne(queryWrapper);
        //用户不存在
        if(user == null){
            log.info("User login failed,userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户不存在");
        }
        //用户脱敏
        User safetyUser=getSafetyUser(user);
        //记录用户的登录状态
        request.getSession().setAttribute(USER_LOGIN_STATE,safetyUser);

        return safetyUser;
    }

    @Override
    public int userLogout(HttpServletRequest request) {
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return 1;
    }

    /**
     * 用户脱敏
     *
     * @param originUser 脱敏前的用户
     * @return 脱敏后用户信息
     */
    @Override
    public User getSafetyUser(User originUser) {
        if (originUser == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户为空");
        }
        User safetyUser=new User();
        safetyUser.setId(originUser.getId());
        safetyUser.setUsername(originUser.getUsername());
        safetyUser.setUserAccount(originUser.getUserAccount());
        safetyUser.setAvatarUrl(originUser.getAvatarUrl());
        safetyUser.setGender(originUser.getGender());
        safetyUser.setPhone(originUser.getPhone());
        safetyUser.setEmail(originUser.getEmail());
        safetyUser.setUserRole(originUser.getUserRole());
        safetyUser.setPlanetCode(originUser.getPlanetCode());
        safetyUser.setUserStatus(originUser.getUserStatus());
        safetyUser.setCreateTime(originUser.getCreateTime());
        return safetyUser;
    }
}
  1. 更改src/main/java/com/example/controller/UserController.java控制类里的异常返回值:
package com.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.common.BaseResponse;
import com.example.common.ErrorCode;
import com.example.common.ResultUtils;
import com.example.exception.BusinessException;
import com.example.model.domain.User;
import com.example.model.domain.request.UserLoginRequest;
import com.example.model.domain.request.UserRegisterRequest;
import com.example.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

import static com.example.content.UserContent.ADMIN_USER;
import static com.example.content.UserContent.USER_LOGIN_STATE;

/**
 * 用户服务控制类
 *
 * @author lwy
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    UserService userService;

    @PostMapping("/register")
    public BaseResponse<Long> register(@RequestBody UserRegisterRequest userRegisterRequest){
        if (userRegisterRequest==null) {
            throw new BusinessException(ErrorCode.NULL_ERROR,"参数为空");
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        String planetCode = userRegisterRequest.getPlanetCode();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword,planetCode)){
            throw new BusinessException(ErrorCode.NULL_ERROR,"参数为空");
        }
        Long result= userService.userRegister(userAccount, userPassword, checkPassword,planetCode);
        return ResultUtils.success(result);
    }
    @PostMapping("/login")
    public BaseResponse<User> login(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request){
        if (userLoginRequest==null) {
            throw new BusinessException(ErrorCode.NULL_ERROR,"参数为空");
        }
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword)){
            throw new BusinessException(ErrorCode.NULL_ERROR,"账号或密码为空");
        }
        User user = userService.userLogin(userAccount, userPassword, request);
        return ResultUtils.success(user);
    }

    @PostMapping("/logout")
    public BaseResponse<Integer> logout(HttpServletRequest request){
        if (request==null) {
            throw new BusinessException(ErrorCode.NULL_ERROR,"参数为空");
        }
        int result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    @GetMapping("/current")
    public BaseResponse<User> getCurrentUser(HttpServletRequest request){
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User currentUser = (User) userObj;
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN,"用户未登录");
        }
        Long userId = currentUser.getId();
        User user = userService.getById(userId);
        User safetyUser = userService.getSafetyUser(user);
        return ResultUtils.success(safetyUser);
    }

    @GetMapping("/search")
    public BaseResponse<List<User>> searchUsers(String username,HttpServletRequest request){
        if(!isAdmin(request)){
            throw new BusinessException(ErrorCode.NO_AUTH,"用户不是管理员");
        }
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        if (StringUtils.isNotBlank(username)){
            // 模糊查询
            queryWrapper.like("username",username);
        }
        List<User> list = userService.list(queryWrapper);
        List<User> collect = list.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList());
        return ResultUtils.success(collect);
    }

    @PostMapping("/delete")
    public BaseResponse<Boolean> deleteUser(@RequestBody Long id,HttpServletRequest request){
        if (!isAdmin(request)){
            throw new BusinessException(ErrorCode.NO_AUTH,"用户不是管理员");
        }
        if (id<=0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数错误");
        }
        boolean result = userService.removeById(id);
        return ResultUtils.success(result);
    }

    /**
     * 是否为管理员
     *
     * @param request
     * @return 若是管理员则返回true
     */
    private boolean isAdmin(HttpServletRequest request){
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user=(User) userObj;
        return user != null && user.getUserRole() == ADMIN_USER;
    }
}

后端优化完成!

完成前端基本功能

  1. 在文件src/pages/user/Register/index.tsx内添加planetCode输入框:
 <ProFormText
                name="planetCode"
                fieldProps={{
                  size: 'large',
                  prefix: <UserOutlined className={styles.prefixIcon}/>,
                }}
                placeholder="请输入星球编号"
                rules={[
                  {
                    required: true,
                    message: '星球编号是必填项!',
                  },
                ]}
              />

(Java项目)用户管理中心_第91张图片

  1. 修改 注册成功 相应逻辑:
try {
      // 注册
      const id = await register(values);
      // @ts-ignore
      // 忽略res.data可能未定义的报错
      if (id) {
        const defaultLoginSuccessMessage = '注册成功!';
        message.success(defaultLoginSuccessMessage);
        /** 此方法会跳转到 redirect 参数所在的位置 */
        if (!history) return;
        const {query} = history.location;
        history.push({
          pathname: '/user/login',
          query,
        });
        return;
      }
    } catch (error: any) {
      const defaultLoginFailureMessage = '注册失败,请重试!';
      message.error(defaultLoginFailureMessage);
    }

(Java项目)用户管理中心_第92张图片

  1. src/services/ant-design-pro/typings.d.ts文件内修改注册参数:
  //注册参数
  type RegisterParams = {
    userAccount?: string;
    userPassword?: string;
    checkPassword?: string;
    planetCode?: string;
    type?: string;
  };

添加通用返回参数:

 /**
   * 通用返回参数
   */
  type BaseResponse<T> = {
    code?: number;
    data?: T;
    message?: string;
    description?: string;
  }

(Java项目)用户管理中心_第93张图片

  1. 修改src/services/ant-design-pro/api.ts文件内的各接口返回值:
// @ts-ignore
/* eslint-disable */
import request from '@/plugins/globalRequest';

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

/** 退出登录接口 POST /api/user/logout */
export async function outLogin(options?: { [key: string]: any }) {
  return request<API.BaseResponse<number>>('/api/user/logout', {
    method: 'POST',
    ...(options || {}),
  });
}

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

/** 注册接口 POST /api/user/register */
export async function register(body: API.RegisterParams, options?: { [key: string]: any }) {
  return request<API.BaseResponse<API.RegisterResult>>('/api/user/register', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    data: body,
    ...(options || {}),
  });
}

/** 搜索用户 GET /api/user/search */
export async function searchUsers(options?: { [key: string]: any }) {
  return request<API.BaseResponse<API.CurrentUser[]>>('/api/user/search', {
    method: 'GET',
    ...(options || {}),
  });
}

/** 此处后端没有提供注释 GET /api/notices */
export async function getNotices(options?: { [key: string]: any }) {
  return request<API.NoticeIconList>('/api/notices', {
    method: 'GET',
    ...(options || {}),
  });
}

/** 获取规则列表 GET /api/rule */
export async function rule(
  params: {
    // query
    /** 当前的页码 */
    current?: number;
    /** 页面的容量 */
    pageSize?: number;
  },
  options?: { [key: string]: any },
) {
  return request<API.RuleList>('/api/rule', {
    method: 'GET',
    params: {
      ...params,
    },
    ...(options || {}),
  });
}

/** 新建规则 PUT /api/rule */
export async function updateRule(options?: { [key: string]: any }) {
  return request<API.RuleListItem>('/api/rule', {
    method: 'PUT',
    ...(options || {}),
  });
}

/** 新建规则 POST /api/rule */
export async function addRule(options?: { [key: string]: any }) {
  return request<API.RuleListItem>('/api/rule', {
    method: 'POST',
    ...(options || {}),
  });
}

/** 删除规则 DELETE /api/rule */
export async function removeRule(options?: { [key: string]: any }) {
  return request<Record<string, any>>('/api/rule', {
    method: 'DELETE',
    ...(options || {}),
  });
}

  1. 新增src/plugins/globalRequest.ts全局请求拦截器:
import {extend} from 'umi-request';
import {message} from "antd";
import {history} from "@@/core/history";
import {stringify} from "querystring";

/**
 * 配置request请求时的默认参数
 */
const request = extend({
  credentials: 'include', // 默认请求是否带上cookie
  // requestType: 'form',
});

/**
 * 所以请求拦截器
 */
request.interceptors.request.use((url, options): any => {
  console.log(`do request url = ${url}`)

  return {
    url,
    options: {
      ...options,
      headers: {},
    },
  };
});

/**
 * 所有响应拦截器
 */
request.interceptors.response.use(async (response, options): Promise<any> => {

  const res = await response.clone().json();
  if (res.code === 0) {
    return res.data;
  }
  if (res.code === 40100) {
    message.error("请先登录");
    history.replace({
      pathname: '/user/login',
      search: stringify({
        redirect: location.pathname,
      }),
    });
  } else {
    message.error(res.description);
  }
  return res.data;
});

export default request;

(Java项目)用户管理中心_第94张图片

  1. 在文件src/components/RightContent/AvatarDropdown.tsx内添加退出登录相关代码:
    (Java项目)用户管理中心_第95张图片
    前端优化完成!

你可能感兴趣的:(java,开发语言,笔记,课程设计,开源)