通过查看ABP的官方Demo发现,在后台里并没有菜单管理这一概念,而是通过角色权限去控制,通过修改不同角色拥有的权限去限制功能。这里也采用了这一概念,相对来说比较好实现,且大部分情况下菜单并不需要在发布后修改什么东西。
1、权限接口
在上一篇中建立了application-configuration方法,通过返回的数据可以看到当前用户的权限分配在auth=>grantedPolicies中,policies为系统所有权限。

2、Vue菜单权限设置
打开types/vue-router.d.ts,在RouteMeta里新增一个字段grantedPolicy?: string;
,然后在需要权限控制的菜单里的meta添加grantedPolicy:"AbpIdentity.Roles",值为返回的auth.grantedPolicies。
store/modules/user.ts
新增grantedPolicies:string[]
,并添加对应的get/set方法,在getUserInfoAction方法中set返回的grantedPolicies值。
setGrantedPolicies(codes: { [key: string]: boolean }) { const policies: string[] = []; for (const key in codes) { if (codes[key]) { policies.push(key); } } this.grantedPolicies = policies; // GRANTED_POLICIES_KEY需自行添加,也可直接使用"GRANTED_POLICY_KEY__" setAuthCache(GRANTED_POLICIES_KEY, policies); },
store/modules/permission.ts
async buildRoutesAction(): Promise<AppRouteRecordRaw[]> { const { t } = useI18n(); const userStore = useUserStore(); const appStore = useAppStoreWithOut(); let routes: AppRouteRecordRaw[] = []; const roleList = toRaw(userStore.getRoleList) || []; const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig; const routeFilter = (route: AppRouteRecordRaw) => { const { meta } = route; const { roles } = meta || {}; if (!roles) return true; return roleList.some((role) => roles.includes(role)); }; // add const grantedPolicies = userStore.getGrantedPolicies; const routerGrantedPolicyFilter = (route: AppRouteRecordRaw) => { const { meta } = route; const { grantedPolicy } = meta || {}; if (!grantedPolicy) return true; return grantedPolicies.some((policy) => policy == grantedPolicy); }; // const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { const { meta } = route; const { ignoreRoute } = meta || {}; return !ignoreRoute; }; /** * @description 根据设置的首页path,修正routes中的affix标记(固定首页) * */ const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { if (!routes || routes.length === 0) return; let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; function patcher(routes: AppRouteRecordRaw[], parentPath = '') { if (parentPath) parentPath = parentPath + '/'; routes.forEach((route: AppRouteRecordRaw) => { const { path, children, redirect } = route; const currentPath = path.startsWith('/') ? path : parentPath + path; if (currentPath === homePath) { if (redirect) { homePath = route.redirect! as string; } else { route.meta = Object.assign({}, route.meta, { affix: true }); throw new Error('end'); } } children && children.length > 0 && patcher(children, currentPath); }); } try { patcher(routes); } catch (e) { // 已处理完毕跳出循环 } return; }; switch (permissionMode) { case PermissionModeEnum.ROLE: routes = filter(asyncRoutes, routeFilter); routes = routes.filter(routeFilter); //add routes = filter(routes, routerGrantedPolicyFilter); routes = routes.filter(routerGrantedPolicyFilter); // // Convert multi-level routing to level 2 routing routes = flatMultiLevelRoutes(routes); break; case PermissionModeEnum.ROUTE_MAPPING: routes = filter(asyncRoutes, routeFilter); routes = routes.filter(routeFilter); // add routes = filter(routes, routerGrantedPolicyFilter); routes = routes.filter(routerGrantedPolicyFilter); // const menuList = transformRouteToMenu(routes, true); routes = filter(routes, routeRemoveIgnoreFilter); routes = routes.filter(routeRemoveIgnoreFilter); menuList.sort((a, b) => { return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0); }); this.setFrontMenuList(menuList); // Convert multi-level routing to level 2 routing routes = flatMultiLevelRoutes(routes); break; // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below //case PermissionModeEnum.BACK: // ...... }
这里使用的为前端权限的ROUTE_MAPPING、ROLE,并未采用后端权限方式。这种方法改造起来最为简单,且利用好了abp自身提供的方法,无需另建menu表去管理。