基于vue-element-admin的异步权限路由——动态路由(三)

    前面已经实现了用户与角色关联、角色与路由关联,这篇文章主要介绍后端根据用户角色返回角色绑定的路由后,前端如何实现动态生成路由。
    首先我们前端保存了一份全部的异步路由配置表:

export const asyncRoutes = [
    {
        path: '/privilegeManage',
        component: Layout,
        redirect: '/privilegeManage/menuList',
        name: 'privilegeManage',
        alwaysShow: true,
        meta: {
            title: '权限管理',
            icon: 'privilege-manage',
            roles: ['admin', 'seeAdmin']
        },
        children: [
            {
                path: 'menuList',
                component: () => import('@/views/privilegeManage/menuList'),
                name: 'menuList',
                meta: {
                    title: '菜单管理',
                    icon: 'menu',
                    noCache: true
                }
            },
            {
                path: 'createMenu',
                component: () => import('@/views/privilegeManage/createMenu'),
                name: 'createMenu',
                meta: {
                    title: '添加菜单',
                },
                hidden: true
            },
            {
                path: 'editMenu',
                component: () => import('@/views/privilegeManage/editMenu'),
                name: 'editMenu',
                meta: {
                    title: '修改菜单',
                },
                hidden: true
            },
            {
                path: 'roleList',
                component: () => import('@/views/privilegeManage/roleList'),
                name: 'roleList',
                meta: {
                    title: '角色管理',
                    icon: 'role-list',
                    noCache: true
                }
            },
        ]
    },
{
        path: '/accounts',
        component: Layout,
        redirect: '/accounts/list',
        name: 'accountManage',
        alwaysShow: true,
        meta: {
            title: '账单管理',
            icon: 'accounts'
        },
        children: [
            {
                path: 'accountClassify',
                component: () => import('@/views/accounts/accountClassify'),
                name: 'accountClassify',
                meta: {
                    title: '分类管理',
                    icon: 'classify',
                    roles: ['admin', 'seeAdmin']
                }
            },
            {
                path: 'list',
                component: () => import('@/views/accounts/list'),
                name: 'accountsList',
                meta: {
                    title: '账单列表',
                    icon: 'capitallist',
                    noCache: true
                }
            },
            {
                path: 'accountsEdit',
                component: () => import('@/views/accounts/accountsEdit'),
                name: 'accountsEdit',
                meta: {
                    title: '修改账单',
                    activeMenu: '/accounts/list'
                },
                hidden: true
            },
            {
                path: 'accountsAdd',
                component: () => import('@/views/accounts/accountsAdd'),
                name: 'accountsAdd',
                meta: {
                    title: '添加账单',
                    activeMenu: '/accounts/list'
                },
                hidden: true
            }
        ]
    },
 {path: '*', redirect: '/404', hidden: true}
]

    目前就以两个一级菜单为例,为一个角色配置账单管理的权限。后端返回的数据如下:

let userRouter = [
	{
		menuId: 'f95523b631cbb1f9bc7892147f2e441f',
		name: '账单管理',
		pid: '',
		url: '/accounts'
		children: [
			{
				menuId: "8b0e14591bb0964817192401b3bfe934"
				name: "账单列表"
				pid: "f95523b631cbb1f9bc7892147f2e441f"
				url: "list"
			},
			{
				menuId: "aadc11cddff3e18e09d3291c92e17ce8"
				name: "修改账单"
				pid: "f95523b631cbb1f9bc7892147f2e441f"
				url: "accountsEdit"
			},
			{
				menuId: "f8548737bacd227bddbc7315a7f65fd0"
				name: "添加账单"
				pid: "f95523b631cbb1f9bc7892147f2e441f"
				url: "accountsAdd"
			}
		]
	}
]

    一般都是在返回用户信息的接口里面同时返回用户的路由信息,你也可以在获取到用户信息后再获取路由信息也是可以的。
    src/permision.js文件:

router.beforeEach(async (to, from, next) => {
	// 根据token判断用户登录状态(有的项目不是根据token判断登录的,可根据实际情况进行改变)
	const hasToken = getToken();
	if(hasToken) {
		if(to.path === '/login') {
			next({path: '/'})
		} else {
			// 判断用户是否获取到路由信息
			const hasUserRouter = store.state.permission.hasUserRouter;
			if (hasUserRouter) {
				next();
			} else {
				try {
					// 重新获取用户信息并接收信息中的路由信息
					const {routerList} = await stroe.dispatch('user/getInfo');
					// 动态生成可访问的路由
					const recursiveRouter = await store.dispatch('permission/recursiveRouter', routerList);
					router.addRoutes(recursiveRouter);
					next({...to, replace: true})
				} catch (error) {
					Message.error(error || error.message);
                    // 删除token并跳转到登录页重新登录
                    await store.dispatch('user/resetToken')
                    // Message.error(error || '出现一个未知错误')
                    next(`/login?redirect=${to.path}`)
				}
			}
		}
	} else {
		// 没有token
        if (whiteList.indexOf(to.path) !== -1) {
            // 在白名单中,直接进入
            next()
        } else {
            // 其他没有访问权限的页面将重定向到登录页面
            next(`/login?redirect=${to.path}`)
        }
	}
})

    store/modules/permission.js文件:

/**
 * 权限生成路由模块
 */
import {asyncRoutes, constantRoutes} from "@/router/index";

/**
 * 判断路由路径是否相等
 * @param asyncRouterItem
 * @param userRouteItem
 */
function hasPath(asyncRouterItem, userRouteItem) {
    return asyncRouterItem.path === userRouteItem.path;
}

/**
 * 通过循环递归出符合用户权限的路由表
 * @param asyncRouterList
 * @param userRouterList
 * @returns {*[]}
 */
export function recursiveAsyncRoutes(asyncRouterList, userRouterList) {
    let res = [];
    asyncRouterList.forEach(route => {
        const tmp = {...route};
        if (tmp.path === '*' && !tmp.hasOwnProperty('children')) {
        	// 这一步主要是为了添加404路由
            res.push(tmp)
        } else {
            userRouterList.forEach(uRoute => {
                if (hasPath(tmp, uRoute)) {
                    if (tmp.children && uRoute.children) {
                        tmp.children = recursiveAsyncRoutes(tmp.children, uRoute.children)
                    }
                    res.push(tmp)
                }
            })
        }
    })
    return res;
}
/**
 * 数据
 * @type {{routes: Array, addRoutes: Array}}
 */
const state = {
	hasUserRouter: false,
    routes: [],
    addRoutes: []
}
const mutations = {
    /**
     * 设置路由表
     * @param state 数据
     * @param routes 路由
     * @constructor
     */
    SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
    },
    /**
     * 设置路由状态
     * @param state
     * @param states
     * @constructor
     */
    SET_ROUTER_STATE: (state, states) => {
        state.hasUserRouter = states;
    }
}
const actions = {
    /**
     * 根据用户路由权限递归路由表
     * @param commit
     * @param userRouterList 用户路由权限表
     * @returns {Promise<any>}
     */
    recursiveRouter({commit}, userRouterList) {
        return new Promise(resolve => {
            let accessedRoutes = recursiveAsyncRoutes(asyncRoutes, userRouterList);
            commit('SET_ROUTES', accessedRoutes)
            commit('SET_ROUTER_STATE', true)
            resolve(accessedRoutes)
        })
    },
    removeRouterState({commit}) {
        commit('SET_ROUTER_STATE', false);
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

    这个js文件的主要作用就是把后端返回的路由和前端配置的完整路由进行比较,取相同部分的路由。只拥有账单管理的用户如下图:
在这里插入图片描述    拥有权限管理和账单管理的用户如下图:
在这里插入图片描述
    至此,完成了不同角色用户不同菜单(路由)的功能,我们只需要在后台管理系统给角色分配路由的权限就能实现。

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
如果在 Vue-element-admin 中定义的异步路由 `asyncRoutes` 全部不显示,而动态路由 `dynamicRoutes` 显示了,可能是因为以下原因之一: 1. 用户角色信息获取失败:在 Vue-element-admin 中,用户角色信息是从后端获取的,如果角色信息获取失败或者格式不正确,会导致路由无法正确显示。您可以在浏览器的开发工具中查看控制台输出,检查是否存在角色信息获取失败的错误信息。 2. `asyncRoutes` 路由配置错误:在 Vue-element-admin 中,异步路由 `asyncRoutes` 代表了所有动态生成的路由,如果路由配置错了也会导致路由无法正确显示。您可以检查 `asyncRoutes` 中的每个路由的配置是否正确,例如路由的路径、组件、重定向等。 3. 路由元信息中的 `roles` 属性设置错误:在 Vue-element-admin 中,路由元信息中的 `roles` 属性用于控制该路由的访问权限,如果该属性设置错误,会导致路由无法正确显示。您可以检查 `asyncRoutes` 中的每个路由的元信息,检查是否存在 `roles` 属性设置错误的情况。例如,如果某个路由的访问权限设置为 `admin`,但是用户的角色中并没有 `admin` 角色,该路由就不会显示。 4. 菜单配置错误:在 Vue-element-admin 中,菜单是根据路由自动生成的,如果路由无法正确显示,菜单也会无法正确显示。您可以检查 `src/layout/components/Sidebar/index.vue` 中的菜单配置,检查是否存在菜单配置错误的情况。例如,如果某个路由的 `hidden` 属性设置为 `true`,该路由就不会在菜单中显示。 5. `asyncRoutes` 路由没有添加到 `dynamicRoutes` 中:在 Vue-element-admin 中,动态路由 `dynamicRoutes` 是根据用户角色动态生成的,而异步路由 `asyncRoutes` 是所有可能出现的路由集合。如果您没有将 `asyncRoutes` 中的路由添加到 `dynamicRoutes` 中,那么这些路由就不会被动态生成。您可以检查 `src/store/modules/permission.js` 文件中的 `GenerateRoutes` 方法,检查是否正确地将 `asyncRoutes` 中的路由添加到 `dynamicRoutes` 中。 如果以上方法无法解决问题,建议您提供更详细的错误信息,或者将您的代码上传到 GitHub 等平台上,方便我们查看和调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值