Kaynağa Gözat

修改菜单栏

lex-xin 4 yıl önce
ebeveyn
işleme
ea998d172c

+ 9 - 0
src/App.vue

@@ -355,6 +355,15 @@ input[type="number"] {
   color: #333;
   opacity: 1;
 }
+
+.horizontal-scrollbar {
+    .el-scrollbar__wrap {
+        overflow-x: hidden;
+        .el-scrollbar__view{
+            white-space: nowrap;
+         }
+    }
+}
 </style>
 <style lang="less">
 .main-dot {

+ 63 - 4
src/layout/components/Navbar.vue

@@ -3,12 +3,21 @@
     <!-- <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> -->
 
     <!-- <breadcrumb class="breadcrumb-container" /> -->
-    <div class="left-menu">
+    <div class="indexlayout-top-menu">
+      <!-- :class="{'active': getTopMenuActive === route.path}" -->
+      <el-scrollbar class="horizontal-scrollbar">
+          <template v-for="route in permission_routes">
+            <app-link v-if="!route.hidden" :to="route.path" :key="route.path" class="indexlayout-top-menu-li" :class="{'active': getTopMenuActive === route.path}">
+                <span>{{ route.meta.title }}</span>
+            </app-link>
+          </template>
+      </el-scrollbar>
+    </div>
+    <!-- <div class="left-menu">
       <i class="el-icon-location-information topIcon"></i>
 
       <el-popover placement="top-start" width="300" trigger="hover">
         <div class="popover-container">
-          <!-- <p style="color: red">{{ organName }}</p> -->
           <el-tag
             class="navbar_tag"
             type="info"
@@ -21,7 +30,7 @@
           organName.length > 10 ? organName.substr(0, 10) + "..." : organName
         }}</span>
       </el-popover>
-    </div>
+    </div> -->
     <div class="right-menu">
       <div class="msginfo" v-permission="'/journals'" @click="gotoRecode">
         <img src="@/assets/images/base/base-bell.svg" />
@@ -140,6 +149,8 @@ import { mapGetters } from "vuex";
 // import Breadcrumb from '@/components/Breadcrumb'
 // import Hamburger from '@/components/Hamburger'
 import { resetPassword } from "@/api/buildTeam";
+import AppLink from './Sidebar/Link';
+import { getBelongTopMenuPath } from '@/utils/permission';
 export default {
   data() {
     return {
@@ -159,11 +170,17 @@ export default {
     };
   },
   components: {
+    AppLink
     // Breadcrumb,
     // Hamburger
   },
   computed: {
-    ...mapGetters(["sidebar", "avatar"]),
+    ...mapGetters(["sidebar", "avatar", "permission_routes"]),
+    getTopMenuActive() {
+      let route = this.$route;
+      // console.log(route, getBelongTopMenuPath(route))
+      return getBelongTopMenuPath(route);
+    }
   },
   mounted() {
     // 手动加入
@@ -262,6 +279,48 @@ export default {
 .navbar_tag {
   margin: 0 5px 8px;
 }
+
+.indexlayout-top-menu{
+  padding-left: 20px;
+  height: 60px;
+  line-height: 60px;
+  flex: 1;
+  display: flex;
+  overflow: hidden;
+  /* overflow-x: auto; */
+  .indexlayout-top-menu-li{
+    display: inline-block;
+    padding: 0 15px;
+    height: 57px;
+    text-decoration: none;
+    color: #000;
+    font-size: 15px;
+    transition: all .3s ease;
+    span {
+      border-bottom: solid 3px transparent;
+      height: 57px;
+      line-height: 57px;
+      display: block;
+    }
+    &:hover,
+    &.active{
+      span {
+        border-bottom-color: #209e91;
+      }
+    }
+    &.active {
+      background-color: #F5F5F5;
+    }
+  }
+  .breadcrumb{
+    line-height: 60px;
+    margin-left: 10px;
+    .el-breadcrumb__item{
+      display: inline-block;
+      float: none;
+    }
+  }
+}
 .popover-container {
   max-height: 350px;
   overflow-y: scroll;

+ 112 - 0
src/layout/components/Sidebar/SidebarMenuItem.vue

@@ -0,0 +1,112 @@
+<template>
+      <div v-if="!routes.hidden" v-show="menuIsShow(routes)">
+        <template v-if="!hasChild(routes.children)">
+            <app-link :to="getResolvePathUrlRoutes">
+                <el-menu-item :index="getResolvePathUrlRoutes">
+                    <menu-title :icon="routes.meta.icon||(routes.meta&&routes.meta.icon)" :title="routes.meta.title" />
+                </el-menu-item>
+            </app-link>
+        </template>
+
+        <el-submenu v-else :index="getResolvePathUrlRoutes" popper-append-to-body>
+            <template slot="title">
+                <menu-title v-if="routes.meta" :icon="routes.meta && routes.meta.icon" :title="routes.meta.title" />
+            </template>
+            <sidebar-menu-item
+                v-for="child in routes.children"
+                :key="getResolvePathUrlRoutes + '/' + child.path"
+                :routes="child"
+                :base-path="getBasePath"
+                :resolve-path="getResolvePathUrlRoutes"
+                :active-top-menu="getActiveTopMenu"
+                class="nest-menu"
+            />
+        </el-submenu>
+    </div>
+</template>
+<script>
+import path from 'path';
+import { isExternal } from "@/utils/validate";
+import { getBelongTopMenuPath } from '@/utils/permission';
+import MenuTitle from './Item';
+import AppLink from './Link';
+export default {
+    name: 'SidebarMenuItem',
+    props: {
+        // route object
+        routes: {
+            type: Object,
+            required: true
+        },
+        // 根路径地址
+        basePath: {
+            type: String,
+            required: true
+        },
+        // 上级路径地址
+        resolvePath: {
+            type: String,
+            default: ''
+        },
+        activeTopMenu: {
+            type: String,
+            default: ''
+        }
+    },
+    components: {
+        MenuTitle,
+        AppLink
+    },
+    computed: {
+        getBasePath: function() {
+            return this.basePath;
+        },
+        getActiveTopMenu: function () {
+            if (this.activeTopMenu !== '') {
+                return this.activeTopMenu;
+            }
+            const route = this.$route;
+            /* 
+            const { meta, path } = route;
+            if (meta.belongTopMenu) {
+                return meta.belongTopMenu;
+            }
+            return '/' + path.split('/')[1];
+            */
+            return getBelongTopMenuPath(route);
+        },
+        getResolvePathUrlRoutes: function() {
+            return this.resolvePathUrl(this.routes.path);
+        }
+    },
+    methods: {
+        menuIsShow(route) {
+            let activeTopMenu = this.getBasePath;
+            const { meta } = route;
+            if (meta.belongTopMenu) {
+                activeTopMenu = meta.belongTopMenu;
+            }
+            return activeTopMenu === this.getActiveTopMenu;
+        },
+        hasChild(children = []) {
+            const showChildren = children.filter(item => {
+                if (item.hidden) {
+                    return false;
+                } else {
+                    return true;
+                }
+            });
+            if (showChildren.length > 0) {
+                return true;
+            }
+            return false;
+        },
+        resolvePathUrl(routePath) {
+            if (isExternal(routePath)) {
+                return routePath;
+            }
+            return path.resolve(this.resolvePath, routePath);
+        }
+    }
+};
+</script>

+ 24 - 4
src/layout/components/Sidebar/index.vue

@@ -12,10 +12,16 @@
                :active-text-color="variables.menuActiveText"
                :collapse-transition="true"
                mode="vertical">
-        <sidebar-item v-for="(route,index) in permission_routes"
+        <template v-for="route in permission_routes">
+          <template v-if="!route.hidden">
+            <!-- <sidebar-item  v-for="route2 in route.children" :key="route.path + '/' + route2.path" :item="route2" :base-path="route.path" :resolve-path="route.path" :active-top-menu="getTopMenuActive" /> -->
+            <sidebar-menu-item v-for="route2 in route.children" :key="route.path + '/' + route2.path" :routes="route2" :base-path="route.path" :resolve-path="route.path" :active-top-menu="getTopMenuActive"/>
+          </template>
+        </template>
+        <!-- <sidebar-item v-for="(route,index) in permission_routes"
                       :key="index"
                       :item="route"
-                      :base-path="route.path" />
+                      :base-path="route.path" /> -->
       </el-menu>
     </el-scrollbar>
   </div>
@@ -24,11 +30,12 @@
 <script>
 import { mapGetters } from 'vuex'
 import Logo from './Logo'
+import SidebarMenuItem from './SidebarMenuItem'
 import SidebarItem from './SidebarItem'
 import variables from '@/styles/variables.scss'
-
+import { getBelongTopMenuPath, getActiveSidebarMenuPath } from '@/utils/permission';
 export default {
-  components: { SidebarItem, Logo },
+  components: { SidebarItem, Logo, SidebarMenuItem },
   // mounted () {
   // },
   computed: {
@@ -59,6 +66,15 @@ export default {
     isCollapse () {
       return false
 
+    },
+    getSidebarMenuActive: function() {
+      const route = this.$route;
+      return getActiveSidebarMenuPath(route);
+    },
+    getTopMenuActive() {
+      let route = this.$route;
+      console.log(getBelongTopMenuPath(route))
+      return getBelongTopMenuPath(route);
     }
   }
 }
@@ -69,4 +85,8 @@ export default {
     padding-bottom: 20px;
   }
 }
+
+/deep/.el-menu-item.is-active {
+    background-color: #13817A !important;
+}
 </style>

+ 2 - 1
src/router/index.js

@@ -96,7 +96,8 @@ export const constantRoutes = [
 
   {
     path: '/',
-    redirect: '/main/main'
+    redirect: '/main/main',
+    hidden: true
   },
   {
     path: '/404',

+ 75 - 4
src/store/modules/permission.js

@@ -46,10 +46,43 @@ const mutations = {
     state.permission = permission
   }
 }
+
+function getFirstMenu(routes) {
+  let firstMenu = null
+  routes.forEach(item => {
+    if(item.children?.length > 0 && !item.hidden) {
+      firstMenu = pathErgodic(item)
+      item.redirect = firstMenu
+    }
+  })
+  return routes
+}
+
+function pathErgodic(item) {
+  let firstMenu = null
+  item.children.forEach(i => {
+    if(!firstMenu && i.children?.length > 0) {
+      firstMenu = pathErgodic(i)
+    } else {
+      if(!firstMenu && checkPathUrl(i.path)) {
+        firstMenu = i.path
+      } else {
+        if(!firstMenu && !i.hidden) {
+          firstMenu = item.path + '/' + i.path
+        }
+      }
+    }
+  })
+  return firstMenu
+}
+// 判断path有没有带/,并且是第一个位置
+function checkPathUrl(path) {
+  return path.indexOf('/') === 0 ? true : false
+}
 // 路由
+
 // 递归遍历数组
 function recursionRouter (arr) {
-
   if (arr.length > 0) {
     let newArr = [];
     for (let i = 0; i < arr.length; i++) {
@@ -66,9 +99,8 @@ function recursionRouter (arr) {
       // }
       arr[i].hid == 0 ? obj.hidden = false : obj.hidden = true
       // console.log('高亮标签'+arr[i].parentPermission,'普通路径'+arr[i].path)
-
       obj.path = arr[i].path;
-      obj.meta = { 'title': arr[i].name, 'icon': arr[i].icon, 'noCache': arr[i].keepAlive, 'activeMenu': arr[i].parentPermission }
+      obj.meta = { 'title': arr[i].name, 'icon': arr[i].icon, 'noCache': arr[i].keepAlive, 'activeMenu': arr[i].parentPermission, 'belongTopMenu': arr[i].belongTopMenu }
       if (arr[i].sysMenus && arr[i].sysMenus.length > 0) {
         obj.children = recursionRouter(arr[i].sysMenus);
       }
@@ -78,6 +110,42 @@ function recursionRouter (arr) {
     return newArr
   }
 }
+
+// 设置 belongTopMenu, 顶部菜单
+function addTopMenu(arr) {
+  if(arr.length > 0) {
+    let newArr = [];
+    for (let i = 0; i < arr.length; i++) {
+      if (arr[i].type == 1) {
+        continue
+      }
+      let obj = arr[i]
+      obj.belongTopMenu = obj.path
+
+      if (arr[i].sysMenus && arr[i].sysMenus.length > 0) {
+        obj.sysMenus = setTopMenu(arr[i].sysMenus, obj);
+      }
+
+      newArr.push(obj)
+    }
+    return newArr
+  }
+}
+
+function setTopMenu(arr, topParentArr) {
+  let newArr = [];
+  for (let i = 0; i < arr.length; i++) {
+    let obj = arr[i]
+    obj.belongTopMenu = topParentArr.path
+    if (arr[i].sysMenus && arr[i].sysMenus.length > 0) {
+      obj.sysMenus = setTopMenu(arr[i].sysMenus, topParentArr);
+    }
+
+    newArr.push(obj)
+  }
+  return newArr
+}
+
 // 权限
 // 递归遍历数组
 let tempArr = []
@@ -95,7 +163,10 @@ const actions = {
       // 获取接口返回的权限菜单
       getSilder().then(res => {
         if (res.code == 200) {
-          let newData = recursionRouter(res.data);
+          let result = addTopMenu(res.data)
+          let newData = recursionRouter(result);
+          newData = getFirstMenu(newData)
+          // console.log((newData))
           recursionPermission(res.data)
           let accessedRoutes
 

+ 32 - 0
src/utils/permission.js

@@ -0,0 +1,32 @@
+/** 
+ * 权限、显示工具
+ * @author LiQingSong
+ */
+
+/**
+ * 获取当前路由对应的顶部菜单path
+ * @param  route 当前路由
+ * @returns String
+ */
+export function getBelongTopMenuPath(route) {
+    // const route = this.$route;
+    const { meta, path } = route;
+    if (meta.belongTopMenu) {
+      return meta.belongTopMenu;
+    }
+    return '/' + path.split('/')[1];
+}
+
+/**
+ * 获取当前路由选中的侧边栏菜单path
+ * @param  route 当前路由
+ * @returns String
+ */
+export function getActiveSidebarMenuPath(route) {
+  // const route = this.$route;
+  const { meta, path } = route;
+  if (meta.activeMenu) {
+    return meta.activeMenu;
+  }
+  return path;
+}

+ 1 - 4
src/utils/validate.js

@@ -1,8 +1,4 @@
 /**
- * Created by PanJiaChen on 16/11/18.
- */
-
-/**
  * @param {string} path
  * @returns {Boolean}
  */
@@ -10,6 +6,7 @@ export function isExternal(path) {
   return /^(https?:|mailto:|tel:)/.test(path)
 }
 
+
 /**
  * @param {string} str
  * @returns {Boolean}