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")
        }
        ]
      }]
  }

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM