Commit 4bf5b04d542014a49c5a41b20935cef35033a518

Authored by YunaiV
1 parent c5fad966

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

yudao-ui-admin/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;
... ...
yudao-ui-admin/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  
... ...
yudao-ui-admin/src/components/TopNav/index.vue 0 → 100644
  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>
... ...
yudao-ui-admin/src/layout/components/Navbar.vue
... ... @@ -2,12 +2,13 @@
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'">
9 10 <search id="header-search" class="right-menu-item" />
10   -
  11 +
11 12 <el-tooltip content="源码地址" effect="dark" placement="bottom">
12 13 <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
13 14 </el-tooltip>
... ... @@ -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 &#39;@/components/RuoYi/Doc&#39;
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: {
... ...
yudao-ui-admin/src/layout/components/Settings/index.vue
... ... @@ -43,6 +43,11 @@
43 43 <h3 class="drawer-title">系统布局配置</h3>
44 44  
45 45 <div class="drawer-item">
  46 + <span>开启 TopNav</span>
  47 + <el-switch v-model="topNav" class="drawer-switch" />
  48 + </div>
  49 +
  50 + <div class="drawer-item">
46 51 <span>开启 Tags-Views</span>
47 52 <el-switch v-model="tagsView" class="drawer-switch" />
48 53 </div>
... ... @@ -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
... ... @@ -128,70 +147,70 @@ export default {
128 147 </script>
129 148  
130 149 <style lang="scss" scoped>
131   - .setting-drawer-content {
132   - .setting-drawer-title {
133   - margin-bottom: 12px;
134   - color: rgba(0, 0, 0, .85);
135   - font-size: 14px;
136   - line-height: 22px;
137   - font-weight: bold;
138   - }
  150 +.setting-drawer-content {
  151 + .setting-drawer-title {
  152 + margin-bottom: 12px;
  153 + color: rgba(0, 0, 0, .85);
  154 + font-size: 14px;
  155 + line-height: 22px;
  156 + font-weight: bold;
  157 + }
139 158  
140   - .setting-drawer-block-checbox {
141   - display: flex;
142   - justify-content: flex-start;
143   - align-items: center;
144   - margin-top: 10px;
145   - margin-bottom: 20px;
146   -
147   - .setting-drawer-block-checbox-item {
148   - position: relative;
149   - margin-right: 16px;
150   - border-radius: 2px;
151   - cursor: pointer;
152   -
153   - img {
154   - width: 48px;
155   - height: 48px;
156   - }
  159 + .setting-drawer-block-checbox {
  160 + display: flex;
  161 + justify-content: flex-start;
  162 + align-items: center;
  163 + margin-top: 10px;
  164 + margin-bottom: 20px;
  165 +
  166 + .setting-drawer-block-checbox-item {
  167 + position: relative;
  168 + margin-right: 16px;
  169 + border-radius: 2px;
  170 + cursor: pointer;
  171 +
  172 + img {
  173 + width: 48px;
  174 + height: 48px;
  175 + }
157 176  
158   - .setting-drawer-block-checbox-selectIcon {
159   - position: absolute;
160   - top: 0;
161   - right: 0;
162   - width: 100%;
163   - height: 100%;
164   - padding-top: 15px;
165   - padding-left: 24px;
166   - color: #1890ff;
167   - font-weight: 700;
168   - font-size: 14px;
169   - }
  177 + .setting-drawer-block-checbox-selectIcon {
  178 + position: absolute;
  179 + top: 0;
  180 + right: 0;
  181 + width: 100%;
  182 + height: 100%;
  183 + padding-top: 15px;
  184 + padding-left: 24px;
  185 + color: #1890ff;
  186 + font-weight: 700;
  187 + font-size: 14px;
170 188 }
171 189 }
172 190 }
  191 +}
  192 +
  193 +.drawer-container {
  194 + padding: 24px;
  195 + font-size: 14px;
  196 + line-height: 1.5;
  197 + word-wrap: break-word;
173 198  
174   - .drawer-container {
175   - padding: 24px;
  199 + .drawer-title {
  200 + margin-bottom: 12px;
  201 + color: rgba(0, 0, 0, .85);
176 202 font-size: 14px;
177   - line-height: 1.5;
178   - word-wrap: break-word;
179   -
180   - .drawer-title {
181   - margin-bottom: 12px;
182   - color: rgba(0, 0, 0, .85);
183   - font-size: 14px;
184   - line-height: 22px;
185   - }
  203 + line-height: 22px;
  204 + }
186 205  
187   - .drawer-item {
188   - color: rgba(0, 0, 0, .65);
189   - font-size: 14px;
190   - padding: 12px 0;
191   - }
  206 + .drawer-item {
  207 + color: rgba(0, 0, 0, .65);
  208 + font-size: 14px;
  209 + padding: 12px 0;
  210 + }
192 211  
193   - .drawer-switch {
194   - float: right
195   - }
  212 + .drawer-switch {
  213 + float: right
196 214 }
  215 +}
197 216 </style>
... ...
yudao-ui-admin/src/settings.js
1 1 module.exports = {
2   - title: '芋道管理系统',
  2 + title: '若依管理系统',
3 3  
4 4 /**
5 5 * 侧边栏主题 深色主题theme-dark,浅色主题theme-light
... ... @@ -12,6 +12,11 @@ module.exports = {
12 12 showSettings: false,
13 13  
14 14 /**
  15 + * 是否显示顶部导航
  16 + */
  17 + topNav: true,
  18 +
  19 + /**
15 20 * 是否显示 tagsView
16 21 */
17 22 tagsView: true,
... ...
yudao-ui-admin/src/store/getters.js
... ... @@ -12,6 +12,9 @@ const getters = {
12 12 roles: state => state.user.roles,
13 13 permissions: state => state.user.permissions,
14 14 permission_routes: state => state.permission.routes,
  15 + // 工具栏
  16 + topbarRouters:state => state.permission.topbarRouters,
  17 + defaultRoutes:state => state.permission.defaultRoutes,
15 18 sidebarRouters:state => state.permission.sidebarRouters,
16 19 // 数据字典
17 20 dict_datas: state => state.dict.dictDatas
... ...
yudao-ui-admin/src/store/modules/permission.js
... ... @@ -14,8 +14,19 @@ const permission = {
14 14 state.addRoutes = routes
15 15 state.routes = constantRoutes.concat(routes)
16 16 },
17   - SET_SIDEBAR_ROUTERS: (state, routers) => {
18   - state.sidebarRouters = constantRoutes.concat(routers)
  17 + SET_DEFAULT_ROUTES: (state, routes) => {
  18 + state.defaultRoutes = constantRoutes.concat(routes)
  19 + },
  20 + SET_TOPBAR_ROUTES: (state, routes) => {
  21 + // 顶部导航菜单默认添加统计报表栏指向首页
  22 + const index = [{
  23 + path: 'index',
  24 + meta: { title: '统计报表', icon: 'dashboard'}
  25 + }]
  26 + state.topbarRouters = routes.concat(index);
  27 + },
  28 + SET_SIDEBAR_ROUTERS: (state, routes) => {
  29 + state.sidebarRouters = routes
19 30 },
20 31 },
21 32 actions: {
... ... @@ -30,7 +41,9 @@ const permission = {
30 41 const rewriteRoutes = filterAsyncRouter(rdata, false, true)
31 42 rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
32 43 commit('SET_ROUTES', rewriteRoutes)
33   - commit('SET_SIDEBAR_ROUTERS', sidebarRoutes)
  44 + commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
  45 + commit('SET_DEFAULT_ROUTES', sidebarRoutes)
  46 + commit('SET_TOPBAR_ROUTES', sidebarRoutes)
34 47 resolve(rewriteRoutes)
35 48 })
36 49 })
... ...
yudao-ui-admin/src/store/modules/settings.js
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
... ...