最近项目重构,因为之前一直在使用 vue-element-admin 框架,但是该项目的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为该项目集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。
作者这里用的是 vue-element-template 版本,有什么需要都可以去 vue-element-admin 复制。
集成方案:: vue-element-admin.
基础模板:: vue-element-template.

Begin:开启我们的探索旅程吧!!!

1、设置前端反向代理;

项目中 根目录下 .env.developmen 设置 服务端访问路径
在这里插入图片描述
项目中 根目录下 vue.config.js 设置
在这里插入图片描述

2、接口请求地址

项目中 根目录下 src/api/user.js 添加 相应接口
在这里插入图片描述

3、请求头设置

后台接口请求需要前端每次请求时,在请求头中添加 token、ip 等相关数据
项目中 根目录下 src/utils/request.js
在这里插入图片描述

4、状态管理

用户登录后,我们需要存储 登录后, 后端返回给我们的 token 等相关信息。
项目中 根目录下 src/store/modules/user.js
主要用到以下两个方法
在这里插入图片描述

5、相关配置准备完毕后

项目中 根目录下 src/permission.js 根据用户角色 后端接口返回 roles 请求 相对应的角色资源菜单
切记!!!roles 必须是一个 集合
在这里插入图片描述

6、router 路由表相关

项目中 根目录下 src/router/index.js 把不用的静态路由清空;
constantRoutes:静态路由 - 不需要后台动态返回即可访问;
asyncRoutes:动态路由 - 后台动态资源权限菜单;
在这里插入图片描述

7、重要!!!

从 vue-element-admin 中 根目录下 src/store/modules 中 copy 复制一份 premission.js 文件 到项目中。并修改相关代码。

**后台菜单返回 JSON 格式**
{
  "code": "00000",
  "msg": "成功",
  "data": [
    {
      "areaCode": null,
      "id": "5",
      "menuName": "系统管理",
      "menuCode": "SYSTEM",
      "parentId": "0",
      "menuPageUrl": null,
      "menuIcon": "@@@",
      "menuDesc": "系统管理",
      "menuType": "RESOURCE_TYPE_MENU",
      "menuPath": "/system",
      "childrenMenuList": [
        {
          "areaCode": "100010",
          "id": "1",
          "menuName": "资源管理",
          "menuCode": "RESOURCE",
          "parentId": "5",
          "menuPageUrl": "/resource",
          "menuIcon": "***",
          "menuDesc": "资源管理",
          "menuType": "RESOURCE_TYPE_MENU",
          "menuPath": "/resource",
          "childrenMenuList": [
            {
              "areaCode": "100010",
              "id": "3",
              "menuName": "添加",
              "menuCode": "RESOURCE_SAVE",
              "parentId": "1",
              "menuPageUrl": "",
              "menuIcon": "***",
              "menuDesc": "资源管理--添加按钮",
              "menuType": "RESOURCE_TYPE_POWER",
              "menuPath": "/resource_save",
              "childrenMenuList": null
            }
          ]
        },
        {
          "areaCode": "100010",
          "id": "2",
          "menuName": "用户",
          "menuCode": "ADMIN",
          "parentId": "5",
          "menuPageUrl": "/admin",
          "menuIcon": "$$$",
          "menuDesc": "用户管理",
          "menuType": "RESOURCE_TYPE_MENU",
          "menuPath": "/admin",
          "childrenMenuList": [
            {
              "areaCode": "100010",
              "id": "4",
              "menuName": "用户添加",
              "menuCode": "ADMIN_SAVE",
              "parentId": "2",
              "menuPageUrl": "",
              "menuIcon": "***",
              "menuDesc": "用户管理--添加按钮",
              "menuType": "RESOURCE_TYPE_POWER",
              "menuPath": "/admin_save",
              "childrenMenuList": null
            },
            {
              "areaCode": null,
              "id": "6",
              "menuName": "用户列表",
              "menuCode": "ADMIN_LIST",
              "parentId": "2",
              "menuPageUrl": null,
              "menuIcon": "!!!",
              "menuDesc": "用户列表",
              "menuType": "RESOURCE_TYPE_MENU",
              "menuPath": null,
              "childrenMenuList": null
            }
          ]
        }
      ]
    }
  ]
}

7.1、重要三点 - 1

后台查询返回的菜单数据拼装成我们前端的路由格式数据
在这里插入图片描述

/**
 * 后台查询的菜单数据拼装成路由格式的数据
 * @param routes
 */
export function generaMenu(routes, data) {
    data.forEach(item => {
        const menu = {
            path: item.menuPath === '#' ? item.id + '_key' : item.menuPath,
            component: Layout,
            hidden: false,
            redirect: 'noRedirect',
            children: [],
            meta: {
                title: item.menuDesc,
                icon: "nested"
            },
            name: 'menu_' + item.id
        }

        if (item.childrenMenuList) {
            getChildrenMenu(menu.children ,item.childrenMenuList);
        }

        routes.push(menu)

    });
  }

7.2、重要三点 - 2

判断是否有子级菜单,做相应多级菜单数据
在这里插入图片描述

/**
 * 判断是否还有子级菜单
 */
function getChildrenMenu(routes, children) {
    if (children) {
        children.forEach(element => {
            if (element.menuType == 'RESOURCE_TYPE_MENU') {
                const childrenMenuObj = {
                    path: element.menuPath === null ? '/' : element.menuPath.replace("/", ""),
                    name: element.menuPath === null ? '/' : element.menuPath.replace("/", ""),
                    meta: { title: element.menuDesc, icon: "nested" },
                    component: element.menuPageUrl === "" ? '/' : () => import("@/views/dashboard/index"),
                    children: []
                }
                if(element.childrenMenuList) {
                    getChildrenMenu(childrenMenuObj.children, element.childrenMenuList);
                }
                routes.push(childrenMenuObj)
            }
        });
    }
}

7.3、重要三点 - 3

请求后台接口
在这里插入图片描述

generateRoutes({ commit }, roles) {
        return new Promise(resolve => {
            const loadMenuData = [];

            getAuthMenu().then(response => {
                let data = response.data;
                
                Object.assign(loadMenuData, data);
                const tempAsyncRoutes = Object.assign([], asyncRoutes);

                generaMenu(tempAsyncRoutes, loadMenuData);

                let accessedRoutes;

                if (roles.includes("admin")) {
                    accessedRoutes = tempAsyncRoutes || [];
                } else {
                    accessedRoutes = filterAsyncRoutes(tempAsyncRoutes, roles);
                }

                commit("SET_ROUTES", accessedRoutes);

                resolve(accessedRoutes);

            });

        });
    }

8、 重要!!!重要!!!重要!!!(被这个坑了好久,添加新文件,忘了 import 引入)

项目中 根目录下 src/store/index.js
记得把新加入的 permission.js 文件 在 index.js 中 import permission form “./modules/permission.js”
或者 从 vue-element-admin 中复制这个文件,替换掉。。。

9、项目中 根目录下 src/store/getter.js 添加 permission_routers

const getters = {
    sidebar: state => state.app.sidebar,
    device: state => state.app.device,
    token: state => state.user.token,
    refreshToken: state => state.user.refreshToken,
    avatar: state => state.user.avatar,
    name: state => state.user.name,
    roles: state => state.user.roles,
    permission_routes: state => state.permission.routes
};
export default getters;

10、最后,项目中 根目录下 src/layout/components/sidebar/index.vue

在这里插入图片描述

效果展示

在这里插入图片描述
至此,我们的整个动态资源菜单就可以展示出来了。如有不对的地方,还望各位道友 多多指出,共同完善本博。

End:都是坑啊!!! F**K

Logo

前往低代码交流专区

更多推荐