• Vue+abp增加三级菜单



    title: "Vue+abp增加三级菜单"
    publishDate: 2019-12-26 17:28:38 +0800
    date: 2019-12-26 17:28:38 +0800
    categories: Vue+abp增加三级菜单
    position: problem

    原生vue版的abp只支持2级菜单,项目需要增加成3级菜单,一番搜索。成果如下


    增加3级菜单显示

    修改components->shrinkable-menu->components->sidebarMenu文件,增加一级菜单,并增加两个方法hasChildren和getChildren,避免html因为没有children属性报错

    <template>
        <Menu ref="sideMenu" :active-name="$route.name" :open-names="openNames" :theme="menuTheme" width="auto" @on-select="changeMenu">
            <template v-for="item in menuList">
                <MenuItem v-if="item.children.length<=0" :name="item.children[0].name" :key="item.name">
                    <!-- <Icon :type="item.icon" :size="iconSize"></Icon> -->
                    <span class="iconfont">{{item.icon}}</span>
                    <span>{{ itemTitle(item) }}</span>
                </MenuItem>
                <Submenu v-if="item.children.length > 0&&!item.meta.hidden" :name="item.name" :key="item.name">
                    <template slot="title">
                        <i class="iconfont" v-html="item.icon"></i>
                        <span >{{ itemTitle(item) }}</span>
                    </template>
                    <template v-for="child in item.children">
                        <MenuItem v-if="!hasChildren(child)&&!child.meta.hidden" :name="child.name" :key="child.name"> 
                            <i class="iconfont" v-html="child.icon"></i>                       
                            <span> {{L(child.meta.title) }}</span>
                        </MenuItem>
                        <Submenu v-if="hasChildren(child)&&!child.meta.hidden" :name="child.name" :key="child.name">
                            <template slot="title">
                                <i class="iconfont" v-html="child.icon"></i>
                                <span >{{ itemTitle(child) }}</span>
                            </template>
                            <template v-for="ss in child.children">
                                <MenuItem v-if="!hasChildren(ss)&&!ss.meta.hidden" :name="ss.name" :key="ss.name"> 
                                    <i class="iconfont" v-html="ss.icon"></i>                       
                                    <span> {{L(ss.meta.title) }}</span>
                                </MenuItem>
                            </template>
                        </Submenu>
                    </template>
                </Submenu>
            </template>
        </Menu>
    </template>
    <script lang="ts">
        hasChildren(item:any){
            return !!item.children&&item.children.length>0
        }
        getChildren(item:any){
            return item.children;
        }
    </script>
    

    修改显示路由方法

    就是显示图上这个
    显示路由
    这个方法在lib->util.ts文件中,我是抄的Vue iview-admin模板二级菜单改为三级菜单,根据abp做了一些调整,修改setCurrentPath方法如下:

      setCurrentPath(vm: Vue, name?: string) {
        let title = "";
        let isOtherRouter = false;
        vm.$store.state.app.routers.forEach(item => {
          if (item.children.length === 1) {
            if (item.children[0].name === name) {
              title = util.handleTitle(vm, item);
              if (item.name === "otherRouter") {
                isOtherRouter = true;
              }
            }
          } else {
            item.children.forEach(child => {
              if (child.name === name) {
                title = util.handleTitle(vm, child);
                if (item.name === "otherRouter") {
                  isOtherRouter = true;
                }
              }
            });
          }
        });
        let currentPathArr = [];
        //去首页
        if (name === "home_index") {
          currentPathArr = [
            {
              meta: {title: util.handleTitle(
                vm,
                util.getRouterObjByName(vm.$store.state.app.routers, "home_index")
              )},
              path: "",
              name: "home_index"
            }
          ];
        }
        //去导航菜单一级页面或者OtherRouter路由中的页面
        else if (
          (name.indexOf("_index") >= 0 || isOtherRouter) &&
          name !== "home_index"
        ) {
          currentPathArr = [
            {
              meta: {title: util.handleTitle(
                vm,
                util.getRouterObjByName(vm.$store.state.app.routers, "home_index")
              )},
              path: "/home",
              name: "home_index"
            },
            {
              meta: {title: title},
              path: "",
              name: name
            }
          ];
        }
        //去导航菜单二级页面或三级页面
        else {
          let currentPathObj = vm.$store.state.app.routers.filter(item => {
            var hasMenu;
    
            if (item.children.length <= 1) {
              hasMenu = item.children[0].name === name;
              return hasMenu;
            } else {
              let i = 0;
              let childArr = item.children;
              let len = childArr.length;
              while (i < len) {
                //如果是三级页面按钮,则在二级按钮数组中找不到这个按钮名称
                //需要二级页面下可能出现三级子菜单的情况逻辑加入
                if (childArr[i].name === name) {
                  hasMenu = true;
                  return hasMenu;
                }
                i++;
              }
              //如果一级,二级菜单下都没有此按钮名称,则遍历三级菜单
              if (!hasMenu) {
                for (let m = 0; m < childArr.length; m++) {
                  if (!childArr[m].children) continue;
                  let sonArr = childArr[m].children;
                  for (let n = 0; n < sonArr.length; n++) {
                    if (sonArr[n].name === name) {
                      hasMenu = true;
                      return hasMenu;
                    }
                  }
                }
              }
    
              return false;
            }
          })[0];
    
          if (
            currentPathObj.children.length <= 1 &&
            currentPathObj.name === "home"
          ) {
            currentPathArr = [
              {
                    meta: { title: "HomePage" },
                    path: "main/home",
                    name: "home"
              }
            ];
          } else if (
            currentPathObj.children.length <= 1 &&
            currentPathObj.name !== "home"
          ) {
            currentPathArr = [
              {
                    meta: { title: "HomePage" },
                    path: "main/home",
                    name: "home"
              },
              {
                meta: {title: currentPathObj.meta.title},
                path: "",
                name: name
              }
            ];
          } else {
            //如果是三级页面按钮,则在二级按钮数组中找不到这个按钮名称
            //需要二级页面下可能出现三级子菜单的情况逻辑加入
            let childObj = currentPathObj.children.filter(child => {
              return child.name === name;
            })[0];
            //二级页面
            if (childObj) {
              currentPathArr = [
                {
                    meta: { title: "HomePage" },
                    path: "main/home",
                    name: "home"
                },
                {
                  meta: {title: currentPathObj.meta.title},
                  path: "",
                  name: ""
                },
                {
                  meta: {title: childObj.meta.title},
                  path: currentPathObj.path + "/" + childObj.path,
                  name: name
                }
              ];
            }
            //childobj为undefined,再从三级页面中遍历
            else {
              let thirdObj;
              let childObj = currentPathObj.children.filter(child => {
                let hasChildren;
                hasChildren = child.name === name;
                if (hasChildren) return hasChildren;
    
                if (child.children) {
                  let sonArr = child.children;
                  for (let n = 0; n < sonArr.length; n++) {
                    if (sonArr[n].name === name) {
                      thirdObj = sonArr[n];
                      hasChildren = true;
                      return hasChildren;
                    }
                  }
                }
                return hasChildren;
              })[0];
    
              if (thirdObj && childObj) {
                currentPathArr = [
                  {
                    meta: { title: "HomePage" },
                    path: "main/home",
                    name: "home"
                  },
                  {
                    meta: {title: currentPathObj.meta.title},
                    path: "",
                    name: ""
                  },
                  {
                    meta: {title: childObj.meta.title},
                    path: "", //设为空是因为此二级菜单没有实际页面且用于面包屑组件显示,path为空的将不可单击
                    name: ""
                  },
                  {
                    meta: {title: thirdObj.meta.title},
                    path:
                      currentPathObj.path +
                      "/" +
                      childObj.path +
                      "/" +
                      thirdObj.path,
                    name: thirdObj.name
                  }
                ];
              }
            }
          }
        }
        vm.$store.commit("app/setCurrentPath", currentPathArr);
        return currentPathArr;
      }
    

    修改根据菜单权限加载菜单

    如果不修改加载权限,则第三级菜单无法用权限控制,第二级菜单也必须定义权限才能显示。如果第二级菜单只是目录,第三级菜单都没有权限,那么第二级目录是不应该显示出来的。
    在store->modules->app.ts中修改updateMenulist方法如下:

    updateMenulist(state: AppState) {
        let menuList: Array<Router> = [];
        [...appRouters,...organizeRouters,...labRouters,...labcheckRouters,
            ...devRouters,...labreportRouters,...appraiseRouters].forEach((item, index) => {
            if (item.permission !== undefined) {
                Util.addHasPermissionChileMenu(item);
                if(item.children&&item.children.length>0){
                    menuList.push(item);
                }
                // let hasPermissionMenuArr: Array<Router> = [];
                // hasPermissionMenuArr = item.children.filter(child => {
                //     if (child.permission !== undefined) {
                //         if (Util.abp.auth.hasPermission(child.permission)) {
                //             return child;
                //         }
                //     } else {
                //         return child;
                //     }
                // });
                // if (hasPermissionMenuArr.length > 0) {
                //     item.children = hasPermissionMenuArr;
                //     menuList.push(item);
                // }
            } else {
                if (item.children.length === 1) {
                    menuList.push(item);
                } else {
                    let len = menuList.push(item);
                    let childrenArr = [];
                    childrenArr = item.children.filter(child => {
                        return child;
                    });
                    let handledItem = JSON.parse(JSON.stringify(menuList[len - 1]));
                    handledItem.children = childrenArr;
                    menuList.splice(len - 1, 1, handledItem);
                }
            }
        });
        state.menuList = menuList;
    }
    

    在lib->util文件中,增加方法如下:

    addHasPermissionChileMenu(item:any){
        let that=this;
        let hasPermissionMenuArr: Array<Router> = [];
        if(!item.children){
            return;
        }
        hasPermissionMenuArr = item.children.filter(child => {  
            let isFather=!!child.children;
            that.addHasPermissionChileMenu(child);
            let hasChildren=!!child.children
            if (isFather&&!hasChildren) {
                return false;
            }
    
            if (child.permission !== undefined) {
                if (that.abp.auth.hasPermission(child.permission)) {
                    return child;
                }
            } else {
                return child;
            }
        });
        if (hasPermissionMenuArr.length > 0) {
            item.children = hasPermissionMenuArr;
        }else{
            item.children=null;
        }
    }
    

    增加三级菜单路由

    在component目录中增加一个显示三级菜单内容的容器three-leve-container.vue

    <template>
    <div>
      <router-view></router-view>
    </div>
    
    </template>
    
    <script lang="ts">
    import { Component, Vue, Inject } from "vue-property-decorator";
    import ViewUI from "view-design";
    import AbpBase from "../lib/abpbase";
    import util from "../lib/util";
    @Component({
      components: {}
    })
    export default class ThreeLeveContainer extends AbpBase {
          
    }
    </script>
    
    <style>
    </style>
    

    现在可以修改你的菜单定义,在二级菜单下像第一级菜单下增加二级菜单一样增加三级菜单了,二级菜单的权限可以是undefined,二级菜单的component要定义成刚才增加的路由组件,这样不需要在后端定义具体的权限,自动根据三级菜单的权限决定是否显示二级菜单。

      {
        path: "/menu1",
        name: "menu1",
        permission: "",
        meta: { title: "menu1" },
        icon: "&#xe68a;",
        component: main,
        children: [
          {
            path: "menu2",
            permission: undefined,
            meta: { title: "menu2" },
            name: "menu2",
            component:() => import("../components/three-leve-container.vue"),
            children: [
            {
                path: "menu3",
                permission: "menu3",
                meta: { title: "menu3" },
                name: "menu3",
                component: () =>
                import("../views/xxxx.vue")
            }
            ]
          }]
      }
    

    参考资料

  • 相关阅读:
    聊一聊Java泛型的擦除
    微信退款通知信息解密
    Spring Boot 初识
    shiro初识
    Redis 初探
    Java Json库的选取准则
    JAVA 几款Json library的比较
    FUSE简介
    Lab 2 源码分析
    Lab2
  • 原文地址:https://www.cnblogs.com/missile/p/12103875.html
Copyright © 2020-2023  润新知