Ant Design Pro V2动态菜单实现

前言

Ant Design Pro是蚂蚁金服团队出品的一款前端框架,安装完毕后可以看到菜单和路由是静态渲染的,在实际的开发过程中,经常需要根据用户名或者权限生成不同的菜单,下面介绍一下具体的实现过程。

开发环境:

  • 后端:Spring 4.2.1
  • 前端:Ant Design Pro V2
  • jdk:1.8

实现效果

使用admin用户登录时,显示管理员菜单项,使用其它用户登录时,显示普通用户菜单项

前端实现过程

官网文档

在官网中https://v2-pro.ant.design/docs/router-and-nav-cn,有这样一句话:
只需在 models/menu 中发起 http 请求,menuData 是一个 json 数组。只需服务器返回类似格式的 json 即可。

[
  {
    
    
    path: '/dashboard',
    name: 'dashboard',
    icon: 'dashboard',
    children: [
      {
    
    
        path: '/dashboard/analysis',
        name: 'analysis',
        exact: true,
      },
      {
    
    
        path: '/dashboard/monitor',
        name: 'monitor',
        exact: true,
      },
      {
    
    
        path: '/dashboard/workplace',
        name: 'workplace',
        exact: true,
      },
    ],
  }
  ...
]

BasicLayout组件中调用model/menu.js

登陆成功后,首先在layouts/BasicLayout.js中通过dva异步调用model/menu.js中的方法获取菜单

class BasicLayout extends React.Component {
    
    
  componentDidMount () {
    
    
    const {
    
    
      dispatch,
      route: {
    
     routes, path, authority },
    } = this.props;
    dispatch({
    
    
      type: 'user/fetchCurrent',
    });
    dispatch({
    
    
      type: 'setting/getSetting',
    });
    dispatch({
    
    
      type: 'menu/getMenuData',  // 异步调用model/menu.js中获取菜单的方法
      payload: {
    
     routes, path, authority },
    });
  }
}

model/menu.js中引入service

在model/menu.js中定义异步方法

  effects: {
    
    
    * getMenuData ({
    
     payload }, {
    
     call, put }) {
    
    
      const {
    
     routes, authority, path } = payload;
      const originalMenuData = memoizeOneFormatter(routes, authority, path);
      // const menuData = filterMenuData(originalMenuData);  //Mock方法
      const menuData = yield call(queryMenus, getUser());  // 后台根据用户名获取自定义菜单
      const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(originalMenuData);
      yield put({
    
    
        type: 'save',
        payload: {
    
     menuData, breadcrumbNameMap, routerData: routes },
      });
    },
  },
  reducers: {
    
    
    save (state, action) {
    
    
      return {
    
      //更新State
        ...state,
        ...action.payload,
      };
    },
  },

service中定义后端API

创建services/menu.js文件,定义后端API

import request from '@/utils/request';

// eslint-disable-next-line import/prefer-default-export
export async function queryMenus(user) {
    
    
  return request(`/api/accounts/${
      
      user}/menus`);
}

后端实现过程

定义菜单类

在这个过程中用到了类的递归,调试过程中发现使用@Data注解给children属性赋值时会报错,所以直接在IDEA中右键-Generate-Getter/Setter-全部选中,生成Setter/Getter方法。

public class MenuData {
    
    
    private String path;
    private String name;
    private String icon;
    private Boolean exact;
    private Set<MenuData> children = new HashSet<>();

    public String getPath() {
    
    
        return path;
    }

    public void setPath(String path) {
    
    
        this.path = path;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public String getIcon() {
    
    
        return icon;
    }

    public void setIcon(String icon) {
    
    
        this.icon = icon;
    }

    public Boolean getExact() {
    
    
        return exact;
    }

    public void setExact(Boolean exact) {
    
    
        this.exact = exact;
    }

    public Set<MenuData> getChildren() {
    
    
        return children;
    }

    public void setChildren(Set<MenuData> children) {
    
    
        this.children = children;
    }
}

定义控制器

定义MenuController.java

  @RequestMapping(value = "/accounts/{user}/menus", method = RequestMethod.GET)
    public ResponseEntity<List<MenuData>> getMenuData(@PathVariable("user") String user) {
    
    
        List<MenuData> menusDataList = new ArrayList<>();

        if (user.equals("admin")) {
    
    
            //父级菜单
            MenuData parent = new MenuData();
            parent.setExact(true);
            parent.setIcon("dashboard");
            parent.setName("管理员-控制面板");
            parent.setPath("/dashboard");
            parent.setChildren(new HashSet<>());

            //子级菜单
            MenuData child1 = new MenuData();
            child1.setExact(true);
            child1.setIcon("analysis");
            child1.setName("管理员-分析");
            child1.setPath("/dashboard/analysis");
            child1.setChildren(new HashSet<>());

            MenuData child2 = new MenuData();
            child2.setExact(true);
            child2.setIcon("monitor");
            child2.setName("管理员-监控");
            child2.setPath("/dashboard/monitor");
            child2.setChildren(new HashSet<>());

            parent.getChildren().add(child1);
            parent.getChildren().add(child2);
            menusDataList.add(parent);
        } else {
    
    
            //父级菜单
            MenuData parent = new MenuData();
            parent.setExact(true);
            parent.setIcon("dashboard");
            parent.setName("普通用户-控制面板");
            parent.setPath("/dashboard");
            parent.setChildren(new HashSet<>());

            //子级菜单
            MenuData child1 = new MenuData();
            child1.setExact(true);
            child1.setIcon("analysis");
            child1.setName("普通用户-分析");
            child1.setPath("/dashboard/analysis");
            child1.setChildren(new HashSet<>());

            MenuData child2 = new MenuData();
            child2.setExact(true);
            child2.setIcon("monitor");
            child2.setName("普通用户-监控");
            child2.setPath("/dashboard/monitor");
            child2.setChildren(new HashSet<>());

            parent.getChildren().add(child1);
            parent.getChildren().add(child2);
            menusDataList.add(parent);
        }
        return new ResponseEntity<>(menusDataList, HttpStatus.OK);
    }

效果验证

后端监测:
在这里插入图片描述

前端监测:
在这里插入图片描述

使用admin用户登录:
在这里插入图片描述

使用user用户登录:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34307801/article/details/103494143