Vue实现动态路由的后端控制
在传统开发后台管理系统时,都会涉及权限控制这一功能需求 即:根据不同登录的角色账号来使用该账号拥有的功能,也就是说系统左边的菜单栏不是固定不变的。
首先是基础路由配置带有component的。
const allRoutes = [
// 基础路由
{
path: '/',
name: 'login',
component: () => import("@/views/LoginView.vue")
},
{
path: '/404',
name: '404',
component: () => import('@/views/Error/404View.vue')
},
// 动态路由容器(登录后内容)
{
path: '/layout',
name: 'layout',
component: () => import('@/Layout/MainLayout.vue'),
children: [
{
path: '/home',
name: '首页',
id: 1,
pid: 0,
// redirect: "/index",//默认重定向的页面
component: () => import('@/views/homeView.vue'),
},{
id: 2,
pid: 0,
redirect: null,
path: '/comp',
name: '门诊',
children: [{
id: 3,
pid: 2,
redirect: null,
component: () => import('@/views/payView.vue'),
path: "/pay",
name: "门诊缴费记录",
},{
id: 4,
pid: 2,
redirect: null,
component: () => import('@/views/reservationView.vue'),
path: "/reservation",
name: "预约记录",
}]
},
{
id: 8,
pid: 0,
path: '/hospital',
name: '住院',
children: [{
id: 9,
pid: 8,
redirect: null,
component: () => import('@/views/hospitalView.vue'),
path: "/hospitalpay",
name: "住院缴费记录",
},{
id: 10,
pid: 8,
redirect: null,
component: () => import('@/views/roomView.vue'),
path: "/room",
name: "房间管理",
},{
id: 11,
pid: 8,
redirect: null,
component: () => import('@/views/inpatientView.vue'),
path: "/inpatient",
name: "住院人",
}]
},]
},
]
然后是后端接口返回的数据,我就先用假数据进行代替了。配置的基础路由和假数据要一致就行。假数据就是动态路由(会发生改变的)
const dynamicRouteConfigs = [
// 动态路由容器(登录后内容)
{
path: '/home',
name: '首页',
id: 1,
pid: 0,
},
{
id: 2,
pid: 0,
redirect: null,
path: '/comp',
name: '门诊',
children: [{
id: 3,
pid: 2,
redirect: null,
path: "/pay",
name: "门诊缴费记录",
},{
id: 4,
pid: 2,
redirect: null,
path: "/reservation",
name: "预约记录",
}]
},
{
id: 8,
pid: 0,
path: '/hospital',
name: '住院',
children: [{
id: 9,
pid: 8,
redirect: null,
path: "/hospitalpay",
name: "住院缴费记录",
},{
id: 10,
pid: 8,
redirect: null,
path: "/room",
name: "房间管理",
},{
id: 11,
pid: 8,
redirect: null,
path: "/inpatient",
name: "住院人",
}]
},
// {
// id: 12,
// pid: 0,
// redirect: null,
// path: '/userinfor',
// name: '用户管理',
// children: [{
// id: 13,
// pid: 12,
// redirect: null,
// path: "/user",
// name: "用户管理",
// },{
// id: 14,
// pid: 12,
// redirect: null,
// path: "/role",
// name: "角色管理",
// },{
// id: 15,
// pid: 12,
// redirect: null,
// path: "/admin",
// name: "管理员管理",
// },{
// id: 27,
// pid: 12,
// redirect: null,
// path: "/visit",
// name: "就诊卡",
// }]
// },
// {
// id: 16,
// pid: 0,
// path: '/department',
// name: '科室管理',
// children: [{
// id: 24,
// pid: 16,
// redirect: null,
// path: "/departments",
// name: "科室管理",
// }]
// },
// {
// id: 17,
// pid: 0,
// path: '/hospitals',
// name: '医院信息',
// redirect: null,
// children: [{
// id: 18,
// pid: 17,
// redirect: null,
// path: "/hospitalList",
// name: "医院信息",
// },{
// id: 19,
// pid: 17,
// redirect: null,
// path: "/doctor",
// name: "医生管理",
// },{
// id: 20,
// pid: 17,
// redirect: null,
// path: "/scheduling",
// name: "医生排班管理",
// },{
// id: 21,
// pid: 17,
// redirect: null,
// path: "/label",
// name: "标签管理",
// },{
// id: 22,
// pid: 17,
// redirect: null,
// path: "/drug",
// name: "药品管理",
// },{
// id: 23,
// pid: 17,
// redirect: null,
// path: "/physical",
// name: "体检管理",
// },{
// id: 26,
// pid: 17,
// redirect: null,
// path: "/trends",
// name: "医院动态",
// }]
// }
];
然后就进行改变判断,通过遍历两个数组,判断两者的name或者path相同的时候将其放入一个新数组中。
然后再声明一个变量等于component,就是添加基础路由的component组件
// 权限过滤方法修正
const filterRoutes = (dynamicRouteConfigs, allRoutes) => {
console.log('动态路由', dynamicRouteConfigs);
console.log('基础路由', allRoutes);
// 递归查找匹配的路由(排除404和首页)
const findMatchedRoute = (routes, target) => {
for (const route of routes) {
// 跳过排除的路由
if (['404', 'home'].includes(route.name)) continue;
// 检查当前路由是否匹配
if (route.name === target.name || route.path === target.path) {
return route; // 返回匹配的路由对象
}
// 递归检查子路由
if (route.children) {
const matchedChild = findMatchedRoute(route.children, target);
if (matchedChild) return matchedChild;
}
}
return null; // 未找到匹配项
};
// 过滤并合并component
return dynamicRouteConfigs
.map(route => {
const matchedRoute = findMatchedRoute(allRoutes, route);
console.log(matchedRoute);
if (matchedRoute) {
// 保留原路由配置,并注入 component
return {
...route,
component: matchedRoute.component // 关键:添加基础路由的组件
};
}
return null; // 未匹配的路由会被过滤
})
.filter(route => route !== null); // 过滤掉未匹配项
};
最后进行动态添加,并且把数据进行存储,在菜单页面进行渲染即可。
// 动态添加路由到layout
const addDynamicRoutes = (roles) => {
// 清空已有动态路由
const layout = router.getRoutes().find(r => r.name === 'layout')
layout.children.forEach(child => {
router.removeRoute(child.name)
})
// 过滤并添加新路由
const allowedRoutes = filterRoutes(dynamicRouteConfigs, allRoutes);
allowedRoutes.forEach(route => { router.addRoute('layout', route); });
console.log(allowedRoutes);
sessionStorage.setItem('menuPath',JSON.stringify(allowedRoutes));//存储的筛选过的动态路由
sessionStorage.setItem('menuName',JSON.stringify(router.getRoutes()));//存储的所有动态路由
// 确保404最后处理
router.addRoute({
path: '/:pathMatch(.*)*',
redirect: '/404'
})
}