Просмотр исходного кода

新增菜单导航显示风格TopNav(false为左侧导航菜单,true为顶部导航菜单)

RuoYi лет назад: 5
Родитель
Сommit
1298d02379

+ 6 - 0
ruoyi-ui/src/assets/styles/ruoyi.scss

@@ -176,6 +176,12 @@
176 176
   color: #FFFFFF;
177 177
 }
178 178
 
179
+/* submenu item */
180
+.el-menu--horizontal > .el-submenu .el-submenu__title {
181
+	height: 50px !important;
182
+	line-height: 50px !important;
183
+}
184
+
179 185
 /* text color */
180 186
 .text-navy {
181 187
 	color: #1ab394;

+ 0 - 3
ruoyi-ui/src/assets/styles/sidebar.scss

@@ -135,9 +135,6 @@
135 135
           margin-left: 20px;
136 136
         }
137 137
 
138
-        .el-submenu__icon-arrow {
139
-          display: none;
140
-        }
141 138
       }
142 139
     }
143 140
 

+ 143 - 0
ruoyi-ui/src/components/TopNav/index.vue

@@ -0,0 +1,143 @@
1
+<template>
2
+  <el-menu
3
+    :default-active="activeMenu"
4
+    mode="horizontal"
5
+    @select="handleSelect"
6
+  >
7
+    <template v-for="(item, index) in topMenus">
8
+      <el-menu-item :index="item.path" :key="index" v-if="index < visibleNumber"
9
+        ><svg-icon :icon-class="item.meta.icon" />
10
+        {{ item.meta.title }}</el-menu-item
11
+      >
12
+    </template>
13
+
14
+    <!-- 顶部菜单超出数量折叠 -->
15
+    <el-submenu index="more" v-if="topMenus.length > visibleNumber">
16
+      <template slot="title">更多菜单</template>
17
+      <template v-for="(item, index) in topMenus">
18
+        <el-menu-item
19
+          :index="item.path"
20
+          :key="index"
21
+          v-if="index >= visibleNumber"
22
+          ><svg-icon :icon-class="item.meta.icon" />
23
+          {{ item.meta.title }}</el-menu-item
24
+        >
25
+      </template>
26
+    </el-submenu>
27
+  </el-menu>
28
+</template>
29
+
30
+<script>
31
+import { constantRoutes } from "@/router";
32
+
33
+export default {
34
+  data() {
35
+    return {
36
+      // 顶部栏初始数
37
+      visibleNumber: 5,
38
+      // 是否为首次加载
39
+      isFrist: false,
40
+    };
41
+  },
42
+  computed: {
43
+    // 顶部显示菜单
44
+    topMenus() {
45
+      return this.routers.map((menu) => ({
46
+        ...menu,
47
+        children: undefined,
48
+      }));
49
+    },
50
+    // 所有的路由信息
51
+    routers() {
52
+      return this.$store.state.permission.topbarRouters;
53
+    },
54
+    // 设置子路由
55
+    childrenMenus() {
56
+      var childrenMenus = [];
57
+      this.routers.map((router) => {
58
+        for (var item in router.children) {
59
+          if (router.children[item].parentPath === undefined) {
60
+            router.children[item].path = router.path + "/" + router.children[item].path;
61
+            router.children[item].parentPath = router.path;
62
+          }
63
+          childrenMenus.push(router.children[item]);
64
+        }
65
+      });
66
+      return constantRoutes.concat(childrenMenus);
67
+    },
68
+    // 默认激活的菜单
69
+    activeMenu() {
70
+      const path = this.$route.path;
71
+      let activePath = this.routers[0].path;
72
+      if (path.lastIndexOf("/") > 0) {
73
+        const tmpPath = path.substring(1, path.length);
74
+        activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
75
+      } else if ("/index" == path || "" == path) {
76
+        if (!this.isFrist) {
77
+          this.isFrist = true;
78
+        } else {
79
+          activePath = "index";
80
+        }
81
+      }
82
+      this.activeRoutes(activePath);
83
+      return activePath;
84
+    },
85
+  },
86
+  mounted() {
87
+    this.setVisibleNumber();
88
+  },
89
+  methods: {
90
+    // 根据宽度计算设置显示栏数
91
+    setVisibleNumber() {
92
+      const width = document.body.getBoundingClientRect().width - 200;
93
+      const elWidth = this.$el.getBoundingClientRect().width;
94
+      const menuItemNodes = this.$el.children;
95
+      const menuWidth = Array.from(menuItemNodes).map(
96
+        (i) => i.getBoundingClientRect().width
97
+      );
98
+      this.visibleNumber = (
99
+        parseInt(width - elWidth) / parseInt(menuWidth)
100
+      ).toFixed(0);
101
+    },
102
+    // 菜单选择事件
103
+    handleSelect(key, keyPath) {
104
+      if (key.indexOf("http://") !== -1 || key.indexOf("https://") !== -1) {
105
+        // http(s):// 路径新窗口打开
106
+        window.open(key, "_blank");
107
+      } else {
108
+        this.activeRoutes(key);
109
+      }
110
+    },
111
+    // 当前激活的路由
112
+    activeRoutes(key) {
113
+      var routes = [];
114
+      if (this.childrenMenus && this.childrenMenus.length > 0) {
115
+        this.childrenMenus.map((item) => {
116
+          if (key == item.parentPath || (key == "index" && "" == item.path)) {
117
+            routes.push(item);
118
+          }
119
+        });
120
+      }
121
+      this.$store.commit("SET_SIDEBAR_ROUTERS", routes);
122
+    },
123
+  },
124
+};
125
+</script>
126
+
127
+<style lang="scss" scoped>
128
+.el-menu--horizontal > .el-menu-item {
129
+  float: left;
130
+  height: 50px;
131
+  line-height: 50px;
132
+  margin: 0;
133
+  border-bottom: 3px solid transparent;
134
+  color: #999093;
135
+  padding: 0 5px;
136
+  margin: 0 10px;
137
+}
138
+
139
+.el-menu--horizontal > .el-menu-item.is-active {
140
+  border-bottom: 3px solid #409eff;
141
+  color: #303133;
142
+}
143
+</style>

+ 9 - 1
ruoyi-ui/src/layout/components/Navbar.vue

@@ -2,7 +2,8 @@
2 2
   <div class="navbar">
3 3
     <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
4 4
 
5
-    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
5
+    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
6
+    <top-nav id="topmenu-container" class="breadcrumb-container" v-if="topNav"/>
6 7
 
7 8
     <div class="right-menu">
8 9
       <template v-if="device!=='mobile'">
@@ -48,6 +49,7 @@
48 49
 <script>
49 50
 import { mapGetters } from 'vuex'
50 51
 import Breadcrumb from '@/components/Breadcrumb'
52
+import TopNav from '@/components/TopNav'
51 53
 import Hamburger from '@/components/Hamburger'
52 54
 import Screenfull from '@/components/Screenfull'
53 55
 import SizeSelect from '@/components/SizeSelect'
@@ -58,6 +60,7 @@ import RuoYiDoc from '@/components/RuoYi/Doc'
58 60
 export default {
59 61
   components: {
60 62
     Breadcrumb,
63
+    TopNav,
61 64
     Hamburger,
62 65
     Screenfull,
63 66
     SizeSelect,
@@ -81,6 +84,11 @@ export default {
81 84
           value: val
82 85
         })
83 86
       }
87
+    },
88
+    topNav: {
89
+      get() {
90
+        return this.$store.state.settings.topNav
91
+      }
84 92
     }
85 93
   },
86 94
   methods: {

+ 19 - 0
ruoyi-ui/src/layout/components/Settings/index.vue

@@ -41,6 +41,11 @@
41 41
       <el-divider/>
42 42
 
43 43
       <h3 class="drawer-title">系统布局配置</h3>
44
+      
45
+      <div class="drawer-item">
46
+        <span>开启 TopNav</span>
47
+        <el-switch v-model="topNav" class="drawer-switch" />
48
+      </div>
44 49
 
45 50
       <div class="drawer-item">
46 51
         <span>开启 Tags-Views</span>
@@ -87,6 +92,20 @@ export default {
87 92
         })
88 93
       }
89 94
     },
95
+    topNav: {
96
+      get() {
97
+        return this.$store.state.settings.topNav
98
+      },
99
+      set(val) {
100
+        this.$store.dispatch('settings/changeSetting', {
101
+          key: 'topNav',
102
+          value: val
103
+        })
104
+        if (!val) {
105
+          this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes);
106
+        }
107
+      }
108
+    },
90 109
     tagsView: {
91 110
       get() {
92 111
         return this.$store.state.settings.tagsView

+ 5 - 0
ruoyi-ui/src/settings.js

@@ -12,6 +12,11 @@ module.exports = {
12 12
   showSettings: false,
13 13
 
14 14
   /**
15
+   * 是否显示顶部导航
16
+   */
17
+  topNav: false,
18
+
19
+  /**
15 20
    * 是否显示 tagsView
16 21
    */
17 22
   tagsView: true,

+ 2 - 0
ruoyi-ui/src/store/getters.js

@@ -11,6 +11,8 @@ const getters = {
11 11
   roles: state => state.user.roles,
12 12
   permissions: state => state.user.permissions,
13 13
   permission_routes: state => state.permission.routes,
14
+  topbarRouters:state => state.permission.topbarRouters,
15
+  defaultRoutes:state => state.permission.defaultRoutes,
14 16
   sidebarRouters:state => state.permission.sidebarRouters,
15 17
 }
16 18
 export default getters

+ 18 - 3
ruoyi-ui/src/store/modules/permission.js

@@ -7,6 +7,8 @@ const permission = {
7 7
   state: {
8 8
     routes: [],
9 9
     addRoutes: [],
10
+    defaultRoutes: [],
11
+    topbarRouters: [],
10 12
     sidebarRouters: []
11 13
   },
12 14
   mutations: {
@@ -14,8 +16,19 @@ const permission = {
14 16
       state.addRoutes = routes
15 17
       state.routes = constantRoutes.concat(routes)
16 18
     },
17
-    SET_SIDEBAR_ROUTERS: (state, routers) => {
18
-      state.sidebarRouters = constantRoutes.concat(routers)
19
+    SET_DEFAULT_ROUTES: (state, routes) => {
20
+      state.defaultRoutes = constantRoutes.concat(routes)
21
+    },
22
+    SET_TOPBAR_ROUTES: (state, routes) => {
23
+      // 顶部导航菜单默认添加统计报表栏指向首页
24
+      const index = [{
25
+        path: 'index',
26
+        meta: { title: '统计报表', icon: 'dashboard'}
27
+      }]
28
+      state.topbarRouters = routes.concat(index);
29
+    },
30
+    SET_SIDEBAR_ROUTERS: (state, routes) => {
31
+      state.sidebarRouters = routes
19 32
     },
20 33
   },
21 34
   actions: {
@@ -30,7 +43,9 @@ const permission = {
30 43
           const rewriteRoutes = filterAsyncRouter(rdata, false, true)
31 44
           rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
32 45
           commit('SET_ROUTES', rewriteRoutes)
33
-          commit('SET_SIDEBAR_ROUTERS', sidebarRoutes)
46
+          commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
47
+          commit('SET_DEFAULT_ROUTES', sidebarRoutes)
48
+          commit('SET_TOPBAR_ROUTES', sidebarRoutes)
34 49
           resolve(rewriteRoutes)
35 50
         })
36 51
       })

+ 2 - 1
ruoyi-ui/src/store/modules/settings.js

@@ -1,12 +1,13 @@
1 1
 import variables from '@/assets/styles/element-variables.scss'
2 2
 import defaultSettings from '@/settings'
3 3
 
4
-const { sideTheme, showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings
4
+const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo } = defaultSettings
5 5
 
6 6
 const state = {
7 7
   theme: variables.theme,
8 8
   sideTheme: sideTheme,
9 9
   showSettings: showSettings,
10
+  topNav: topNav,
10 11
   tagsView: tagsView,
11 12
   fixedHeader: fixedHeader,
12 13
   sidebarLogo: sidebarLogo