公司的后台管理系统是基于ant-design-vue的vip收费版搭建的项目。下载地址是https://store.antdv.com/items/admin-pro, 收费版和免费版的区别是收费版用的vue3 ts开发的,而免费版用的是vue2开发的。
项目初始化后是怎么创建页面组件(路由)的,权限控制又是怎么做的?
我们的项目基于pro-vip做了一些改动,但是架子跟pro-vip是基本差不多的。
在router.beforeEach中获取用户信息及权限信息,并将(路由)权限存到userStore里,下次路由跳转判断userStore中有权限信息就不重新获取用户信息及权限信息了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| router.beforeEach(async to => {
if (userStore.allowRouters && userStore.allowRouters.length > 0) { return true; } else { const info = await userStore.GET_INFO(); const allowRouters = await userStore.GENERATE_ROUTES(info); if (allowRouters) { return { ...to, replace: true }; } return false; } });
|
userStore.GENERATE_ROUTES()方法内,调用接口请求用户的菜单权限,拿到值后动态地添加路由,动态添加路由的具体方法为:router.addRoute(route),添加之前router是包含一些如/404、/login等静态路由的路由对象。
要添加的route对象结构如下:
1 2 3 4 5 6 7 8 9 10 11
| { path: '/' redirect: '/home', name: 'index', component: () => import('/src/layouts/index.vue?t=...'), children: [ {path: '/home', name: 'home', component: () => import('/src/views/home/home.vue')}, {} ] }
|
项目中加了顶部切换体系,不同体系展示不同权限菜单的功能
按照需求,我们项目的实现方式如下:
a.后端返回的菜单权限是全部的菜单,树形菜单的每个节点上有体系ID数组,结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [ { name: '采购名录管理', manageSystemIds: [64,3], url: '...', type: 1, children: [ { name: '名录准入管理', manageSystemIds: [64,3], url: '', } ] } ]
|
b.当页面切换体系时,前端对树形菜单进行过滤,返回有该体系有权限的菜单树。
前端要做的事情有两点:
1.根据用户选择的体系id,过滤菜单
由于切换体系的功能是在顶部,是在框架上,而不是某个页面中,故这块dom及逻辑就放在了basic-layout.vue中。
根据id切换过滤菜单的代码略
2.对该体系下没有权限的菜单进行拦截
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
const permitList = ['/404', '/','/a4print','/a5print','/a4printM','/a5printM'];
const filterRouterPath = routes => { routes.forEach(item => { permitList.push(item.path); item.children?.length > 0 ? filterRouterPath(item.children) : ''; }); };
if (userStore.allowRouters && userStore.allowRouters.length > 0) { filterRouterPath(userStore.allowRouters); if (!permitList.includes(route.path)) { setTimeout(() => { router.replace('/404'); }, 300); } }
|
这块是需要重点理解的:打开新页面并访问没权限的菜单时,router.beforeEach()执行两遍,第一遍并不会进入basic-layout页面,第二遍才会进入
根据上面的业务场景及逻辑需要在basic-layout.vue,及router.beforeEach中,写两次。