通过查看ABP的官方Demo发现,在后台里并没有菜单管理这一概念,而是通过角色权限去控制,通过修改不同角色拥有的权限去限制功能。这里也采用了这一概念,相对来说比较好实现,且大部分情况下菜单并不需要在发布后修改什么东西。

1、权限接口

在上一篇中建立了application-configuration方法,通过返回的数据可以看到当前用户的权限分配在auth=>grantedPolicies中,policies为系统所有权限。

1646354507-image

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表去管理。

文章作者: 不爱思考
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 不爱思考
开发笔记 ABP Vue.js
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝