From 010ba1a9e1b42ce7f42cb945c7f76d30b7ece3ac Mon Sep 17 00:00:00 2001 From: xiaoxian521 <1923740402@qq.com> Date: Fri, 21 May 2021 12:55:23 +0800 Subject: [PATCH] feat: add Multi-level menu --- .vscode/vue3.0.code-snippets | 22 ++ src/layout/components/sidebar/SidebarItem.vue | 3 +- src/plugins/element-plus/index.ts | 2 + src/plugins/i18n/config.ts | 16 + src/router/index.ts | 341 +----------------- src/router/modules/components.ts | 108 ++++++ src/router/modules/editor.ts | 27 ++ src/router/modules/error.ts | 36 ++ src/router/modules/flowchart.ts | 27 ++ src/router/modules/home.ts | 27 ++ src/router/modules/nested.ts | 96 +++++ src/router/modules/remaining.ts | 46 +++ src/router/modules/system.ts | 36 ++ src/style/sidebar.scss | 3 + src/views/nested/menu1/index.vue | 12 + src/views/nested/menu1/menu1-1/index.vue | 3 + src/views/nested/menu1/menu1-2/index.vue | 10 + .../nested/menu1/menu1-2/menu1-2-1/index.vue | 3 + .../nested/menu1/menu1-2/menu1-2-2/index.vue | 3 + src/views/nested/menu1/menu1-3/index.vue | 3 + src/views/nested/menu2/index.vue | 3 + 21 files changed, 501 insertions(+), 326 deletions(-) create mode 100644 .vscode/vue3.0.code-snippets create mode 100644 src/router/modules/components.ts create mode 100644 src/router/modules/editor.ts create mode 100644 src/router/modules/error.ts create mode 100644 src/router/modules/flowchart.ts create mode 100644 src/router/modules/home.ts create mode 100644 src/router/modules/nested.ts create mode 100644 src/router/modules/remaining.ts create mode 100644 src/router/modules/system.ts create mode 100644 src/views/nested/menu1/index.vue create mode 100644 src/views/nested/menu1/menu1-1/index.vue create mode 100644 src/views/nested/menu1/menu1-2/index.vue create mode 100644 src/views/nested/menu1/menu1-2/menu1-2-1/index.vue create mode 100644 src/views/nested/menu1/menu1-2/menu1-2-2/index.vue create mode 100644 src/views/nested/menu1/menu1-3/index.vue create mode 100644 src/views/nested/menu2/index.vue diff --git a/.vscode/vue3.0.code-snippets b/.vscode/vue3.0.code-snippets new file mode 100644 index 000000000..fdab05b71 --- /dev/null +++ b/.vscode/vue3.0.code-snippets @@ -0,0 +1,22 @@ +{ + "Vue3.0快速生成模板": { + "prefix": "Vue3.0", + "body": [ + "\n", + "\n", + "", + "$2" + ], + "description": "Vue3.0" + } +} diff --git a/src/layout/components/sidebar/SidebarItem.vue b/src/layout/components/sidebar/SidebarItem.vue index 01f093cdb..869aec2eb 100644 --- a/src/layout/components/sidebar/SidebarItem.vue +++ b/src/layout/components/sidebar/SidebarItem.vue @@ -66,8 +66,9 @@ export default defineComponent({ children: RouteRecordRaw[] = [], parent: RouteRecordRaw ) { - const showingChildren = children.filter(item => { + const showingChildren = children.filter((item: any) => { if (item.hidden) { + // 不显示hidden属性为true的菜单 return false; } else { onlyOneChild.value = item; diff --git a/src/plugins/element-plus/index.ts b/src/plugins/element-plus/index.ts index 5d9268a96..2dd317daa 100644 --- a/src/plugins/element-plus/index.ts +++ b/src/plugins/element-plus/index.ts @@ -28,6 +28,7 @@ import { ElTooltip, ElDrawer, ElPagination, + ElAlert, } from "element-plus"; const components = [ @@ -58,6 +59,7 @@ const components = [ ElTooltip, ElDrawer, ElPagination, + ElAlert, ]; const plugins = [ElLoading]; diff --git a/src/plugins/i18n/config.ts b/src/plugins/i18n/config.ts index 53539c8d1..6e950cfc2 100644 --- a/src/plugins/i18n/config.ts +++ b/src/plugins/i18n/config.ts @@ -30,6 +30,14 @@ export const menusConfig = { hsflowChart: "流程图", hsseamless: "无缝滚动", hscontextmenu: "右键菜单", + hsmenus: "多级菜单", + hsmenu1: "菜单1", + "hsmenu1-1": "菜单1-1", + "hsmenu1-2": "菜单1-2", + "hsmenu1-2-1": "菜单1-2-1", + "hsmenu1-2-2": "菜单1-2-2", + "hsmenu1-3": "菜单1-3", + hsmenu2: "菜单2", }, }, en: { @@ -54,6 +62,14 @@ export const menusConfig = { hsflowChart: "Flow Chart", hsseamless: "Seamless Scroll", hscontextmenu: "Context Menu", + hsmenus: "MultiLevel Menu", + hsmenu1: "Menu1", + "hsmenu1-1": "Menu1-1", + "hsmenu1-2": "Menu1-2", + "hsmenu1-2-1": "Menu1-2-1", + "hsmenu1-2-2": "Menu1-2-2", + "hsmenu1-3": "Menu1-3", + hsmenu2: "Menu2", }, }, }; diff --git a/src/router/index.ts b/src/router/index.ts index 077c93847..f64488a8b 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,335 +1,26 @@ import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"; -import Layout from "../layout/index.vue"; +import homeRouter from "./modules/home"; +import flowChartRouter from "./modules/flowchart"; +import editorRouter from "./modules/editor"; +import componentsRouter from "./modules/components"; +import nestedRouter from "./modules/nested"; +import systemRouter from "./modules/system"; +import errorRouter from "./modules/error"; +import remainingRouter from "./modules/remaining"; import { storageSession } from "../utils/storage"; - import { i18n } from "/@/plugins/i18n/index"; const routes: Array = [ - { - path: "/", - name: "home", - component: Layout, - redirect: "/welcome", - children: [ - { - path: "/welcome", - name: "welcome", - component: () => - import(/* webpackChunkName: "home" */ "../views/welcome.vue"), - meta: { - title: "message.hshome", - showLink: true, - savedPosition: false, - }, - }, - ], - meta: { - icon: "el-icon-s-home", - showLink: true, - savedPosition: false, - }, - }, - { - path: "/components", - name: "components", - component: Layout, - redirect: "/components/split-pane", - children: [ - { - path: "/components/video", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/video/index.vue" - ), - meta: { - title: "message.hsvideo", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/map", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/map/index.vue" - ), - meta: { - title: "message.hsmap", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/draggable", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/draggable/index.vue" - ), - meta: { - title: "message.hsdraggable", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/split-pane", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/split-pane/index.vue" - ), - meta: { - title: "message.hssplitPane", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/button", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/button/index.vue" - ), - meta: { - title: "message.hsbutton", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/cropping", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/cropping/index.vue" - ), - meta: { - title: "message.hscropping", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/countTo", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/count-to/index.vue" - ), - meta: { - title: "message.hscountTo", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/selector", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/selector/index.vue" - ), - meta: { - title: "message.hsselector", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/seamlessScroll", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/seamless-scroll/index.vue" - ), - meta: { - title: "message.hsseamless", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/components/contextmenu", - component: () => - import( - /* webpackChunkName: "components" */ "../views/components/contextmenu/index.vue" - ), - meta: { - title: "message.hscontextmenu", - showLink: false, - savedPosition: true, - }, - }, - ], - meta: { - icon: "el-icon-menu", - title: "message.hscomponents", - showLink: true, - savedPosition: true, - }, - }, - { - path: "/flowChart", - name: "flowChart", - component: Layout, - redirect: "/flowChart/index", - children: [ - { - path: "/flowChart/index", - component: () => - import( - /* webpackChunkName: "user" */ "../views/flow-chart/index.vue" - ), - meta: { - title: "message.hsflowChart", - showLink: false, - savedPosition: true, - }, - }, - ], - meta: { - icon: "el-icon-set-up", - title: "message.hsflowChart", - showLink: true, - savedPosition: true, - }, - }, - { - path: "/editor", - name: "editor", - component: Layout, - redirect: "/editor/index", - children: [ - { - path: "/editor/index", - component: () => - import(/* webpackChunkName: "user" */ "../views/editor/index.vue"), - meta: { - // icon: 'el-icon-edit-outline', - title: "message.hseditor", - showLink: false, - savedPosition: true, - }, - }, - ], - meta: { - icon: "el-icon-edit-outline", - title: "message.hseditor", - showLink: true, - savedPosition: true, - }, - }, - { - path: "/system", - name: "system", - component: Layout, - redirect: "/system/base", - children: [ - { - path: "/system/base", - component: () => - import(/* webpackChunkName: "system" */ "../views/system/user.vue"), - meta: { - // icon: '', - title: "message.hsBaseinfo", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/system/dict", - component: () => - import( - /* webpackChunkName: "system" */ "../views/system/dict/index.vue" - ), - meta: { - // icon: '', - title: "message.hsDict", - showLink: false, - savedPosition: true, - }, - }, - ], - meta: { - icon: "el-icon-setting", - title: "message.hssysManagement", - showLink: true, - savedPosition: true, - }, - }, - { - path: "/error", - name: "error", - component: Layout, - redirect: "/error/401", - children: [ - { - path: "/error/401", - component: () => - import(/* webpackChunkName: "error" */ "../views/error/401.vue"), - meta: { - title: "message.hsfourZeroOne", - showLink: false, - savedPosition: true, - }, - }, - { - path: "/error/404", - component: () => - import(/* webpackChunkName: "error" */ "../views/error/404.vue"), - meta: { - title: "message.hsfourZeroFour", - showLink: false, - savedPosition: true, - }, - }, - ], - meta: { - icon: "el-icon-position", - title: "message.hserror", - showLink: true, - savedPosition: true, - }, - }, - { - path: "/login", - name: "login", - component: () => - import(/* webpackChunkName: "login" */ "../views/login.vue"), - meta: { - title: "message.hslogin", - showLink: false, - }, - }, - { - path: "/register", - name: "register", - component: () => - import(/* webpackChunkName: "register" */ "../views/register.vue"), - meta: { - title: "message.hsregister", - showLink: false, - }, - }, - { - // 找不到路由重定向到404页面 - path: "/:pathMatch(.*)", - component: Layout, - redirect: "/error/404", - meta: { - icon: "el-icon-s-home", - title: "message.hshome", - showLink: false, - savedPosition: false, - }, - }, - { - path: "/redirect", - component: Layout, - children: [ - { - path: "/redirect/:path(.*)", - component: () => import("../views/redirect.vue"), - }, - ], - }, + homeRouter, + flowChartRouter, + editorRouter, + componentsRouter, + nestedRouter, + systemRouter, + errorRouter, + ...remainingRouter, ]; const router = createRouter({ diff --git a/src/router/modules/components.ts b/src/router/modules/components.ts new file mode 100644 index 000000000..dcb96affc --- /dev/null +++ b/src/router/modules/components.ts @@ -0,0 +1,108 @@ +import Layout from "/@/layout/index.vue"; + +const componentsRouter = { + path: "/components", + name: "components", + component: Layout, + redirect: "/components/split-pane", + children: [ + { + path: "/components/video", + component: () => import("/@/views/components/video/index.vue"), + meta: { + title: "message.hsvideo", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/map", + component: () => import("/@/views/components/map/index.vue"), + meta: { + title: "message.hsmap", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/draggable", + component: () => import("/@/views/components/draggable/index.vue"), + meta: { + title: "message.hsdraggable", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/split-pane", + component: () => import("/@/views/components/split-pane/index.vue"), + meta: { + title: "message.hssplitPane", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/button", + component: () => import("/@/views/components/button/index.vue"), + meta: { + title: "message.hsbutton", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/cropping", + component: () => import("/@/views/components/cropping/index.vue"), + meta: { + title: "message.hscropping", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/countTo", + component: () => import("/@/views/components/count-to/index.vue"), + meta: { + title: "message.hscountTo", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/selector", + component: () => import("/@/views/components/selector/index.vue"), + meta: { + title: "message.hsselector", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/seamlessScroll", + component: () => import("/@/views/components/seamless-scroll/index.vue"), + meta: { + title: "message.hsseamless", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/components/contextmenu", + component: () => import("/@/views/components/contextmenu/index.vue"), + meta: { + title: "message.hscontextmenu", + showLink: false, + savedPosition: true, + }, + }, + ], + meta: { + icon: "el-icon-menu", + title: "message.hscomponents", + showLink: true, + savedPosition: true, + }, +}; + +export default componentsRouter; diff --git a/src/router/modules/editor.ts b/src/router/modules/editor.ts new file mode 100644 index 000000000..4a53685e8 --- /dev/null +++ b/src/router/modules/editor.ts @@ -0,0 +1,27 @@ +import Layout from "/@/layout/index.vue"; + +const editorRouter = { + path: "/editor", + name: "editor", + component: Layout, + redirect: "/editor/index", + children: [ + { + path: "/editor/index", + component: () => import("/@/views/editor/index.vue"), + meta: { + title: "message.hseditor", + showLink: false, + savedPosition: true, + }, + }, + ], + meta: { + icon: "el-icon-edit-outline", + title: "message.hseditor", + showLink: true, + savedPosition: true, + }, +}; + +export default editorRouter; diff --git a/src/router/modules/error.ts b/src/router/modules/error.ts new file mode 100644 index 000000000..2e40e4696 --- /dev/null +++ b/src/router/modules/error.ts @@ -0,0 +1,36 @@ +import Layout from "/@/layout/index.vue"; + +const errorRouter = { + path: "/error", + name: "error", + component: Layout, + redirect: "/error/401", + children: [ + { + path: "/error/401", + component: () => import("/@/views/error/401.vue"), + meta: { + title: "message.hsfourZeroOne", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/error/404", + component: () => import("/@/views/error/404.vue"), + meta: { + title: "message.hsfourZeroFour", + showLink: false, + savedPosition: true, + }, + }, + ], + meta: { + icon: "el-icon-position", + title: "message.hserror", + showLink: true, + savedPosition: true, + }, +}; + +export default errorRouter; diff --git a/src/router/modules/flowchart.ts b/src/router/modules/flowchart.ts new file mode 100644 index 000000000..1d08e54c3 --- /dev/null +++ b/src/router/modules/flowchart.ts @@ -0,0 +1,27 @@ +import Layout from "/@/layout/index.vue"; + +const flowChartRouter = { + path: "/flowChart", + name: "flowChart", + component: Layout, + redirect: "/flowChart/index", + children: [ + { + path: "/flowChart/index", + component: () => import("/@/views/flow-chart/index.vue"), + meta: { + title: "message.hsflowChart", + showLink: false, + savedPosition: true, + }, + }, + ], + meta: { + icon: "el-icon-set-up", + title: "message.hsflowChart", + showLink: true, + savedPosition: true, + }, +}; + +export default flowChartRouter; diff --git a/src/router/modules/home.ts b/src/router/modules/home.ts new file mode 100644 index 000000000..acf5076eb --- /dev/null +++ b/src/router/modules/home.ts @@ -0,0 +1,27 @@ +import Layout from "/@/layout/index.vue"; + +const homeRouter = { + path: "/", + name: "home", + component: Layout, + redirect: "/welcome", + children: [ + { + path: "/welcome", + name: "welcome", + component: () => import("/@/views/welcome.vue"), + meta: { + title: "message.hshome", + showLink: true, + savedPosition: false, + }, + }, + ], + meta: { + icon: "el-icon-s-home", + showLink: true, + savedPosition: false, + }, +}; + +export default homeRouter; diff --git a/src/router/modules/nested.ts b/src/router/modules/nested.ts new file mode 100644 index 000000000..3a6be465a --- /dev/null +++ b/src/router/modules/nested.ts @@ -0,0 +1,96 @@ +import Layout from "/@/layout/index.vue"; + +const nestedRouter = { + path: "/nested", + component: Layout, + redirect: "/nested/menu1/menu1-1", + name: "Nested", + meta: { + title: "message.hsmenus", + icon: "el-icon-s-data", + showLink: true, + savedPosition: false, + }, + children: [ + { + path: "menu1", + component: () => import("/@/views/nested/menu1/index.vue"), + name: "Menu1", + meta: { + title: "message.hsmenu1", + showLink: true, + savedPosition: false, + }, + redirect: "/nested/menu1/menu1-1", + children: [ + { + path: "menu1-1", + component: () => import("/@/views/nested/menu1/menu1-1/index.vue"), + name: "Menu1-1", + meta: { + title: "message.hsmenu1-1", + showLink: true, + savedPosition: false, + }, + }, + { + path: "menu1-2", + component: () => import("/@/views/nested/menu1/menu1-2/index.vue"), + name: "Menu1-2", + redirect: "/nested/menu1/menu1-2/menu1-2-1", + meta: { + title: "message.hsmenu1-2", + showLink: true, + savedPosition: false, + }, + children: [ + { + path: "menu1-2-1", + component: () => + import("/@/views/nested/menu1/menu1-2/menu1-2-1/index.vue"), + name: "Menu1-2-1", + meta: { + title: "message.hsmenu1-2-1", + showLink: true, + savedPosition: false, + }, + }, + { + path: "menu1-2-2", + component: () => + import("/@/views/nested/menu1/menu1-2/menu1-2-2/index.vue"), + name: "Menu1-2-2", + meta: { + title: "message.hsmenu1-2-2", + showLink: true, + savedPosition: false, + }, + }, + ], + }, + { + path: "menu1-3", + component: () => import("/@/views/nested/menu1/menu1-3/index.vue"), + name: "Menu1-3", + meta: { + title: "message.hsmenu1-3", + showLink: true, + savedPosition: false, + }, + }, + ], + }, + { + path: "menu2", + name: "Menu2", + component: () => import("/@/views/nested/menu2/index.vue"), + meta: { + title: "message.hsmenu2", + showLink: true, + savedPosition: false, + }, + }, + ], +}; + +export default nestedRouter; diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts new file mode 100644 index 000000000..cce855b0d --- /dev/null +++ b/src/router/modules/remaining.ts @@ -0,0 +1,46 @@ +import Layout from "/@/layout/index.vue"; + +const remainingRouter = [ + { + path: "/login", + name: "login", + component: () => import("/@/views/login.vue"), + meta: { + title: "message.hslogin", + showLink: false, + }, + }, + { + path: "/register", + name: "register", + component: () => import("/@/views/register.vue"), + meta: { + title: "message.hsregister", + showLink: false, + }, + }, + { + // 找不到路由重定向到404页面 + path: "/:pathMatch(.*)", + component: Layout, + redirect: "/error/404", + meta: { + icon: "el-icon-s-home", + title: "message.hshome", + showLink: false, + savedPosition: false, + }, + }, + { + path: "/redirect", + component: Layout, + children: [ + { + path: "/redirect/:path(.*)", + component: () => import("/@/views/redirect.vue"), + }, + ], + }, +]; + +export default remainingRouter; diff --git a/src/router/modules/system.ts b/src/router/modules/system.ts new file mode 100644 index 000000000..cf45ffbdf --- /dev/null +++ b/src/router/modules/system.ts @@ -0,0 +1,36 @@ +import Layout from "/@/layout/index.vue"; + +const systemRouter = { + path: "/system", + name: "system", + component: Layout, + redirect: "/system/base", + children: [ + { + path: "/system/base", + component: () => import("/@/views/system/user.vue"), + meta: { + title: "message.hsBaseinfo", + showLink: false, + savedPosition: true, + }, + }, + { + path: "/system/dict", + component: () => import("/@/views/system/dict/index.vue"), + meta: { + title: "message.hsDict", + showLink: false, + savedPosition: true, + }, + }, + ], + meta: { + icon: "el-icon-setting", + title: "message.hssysManagement", + showLink: true, + savedPosition: true, + }, +}; + +export default systemRouter; diff --git a/src/style/sidebar.scss b/src/style/sidebar.scss index 599666070..b40fa5ff1 100644 --- a/src/style/sidebar.scss +++ b/src/style/sidebar.scss @@ -173,6 +173,9 @@ background-color: $subMenuHover; } } + .el-submenu__title { + color: $menuText; + } } & > .el-menu { i { diff --git a/src/views/nested/menu1/index.vue b/src/views/nested/menu1/index.vue new file mode 100644 index 000000000..1ff56b412 --- /dev/null +++ b/src/views/nested/menu1/index.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/views/nested/menu1/menu1-1/index.vue b/src/views/nested/menu1/menu1-1/index.vue new file mode 100644 index 000000000..dd359a84a --- /dev/null +++ b/src/views/nested/menu1/menu1-1/index.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/nested/menu1/menu1-2/index.vue b/src/views/nested/menu1/menu1-2/index.vue new file mode 100644 index 000000000..bc63d328e --- /dev/null +++ b/src/views/nested/menu1/menu1-2/index.vue @@ -0,0 +1,10 @@ + diff --git a/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue b/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue new file mode 100644 index 000000000..6a8b8db3e --- /dev/null +++ b/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue b/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue new file mode 100644 index 000000000..1efb05549 --- /dev/null +++ b/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/nested/menu1/menu1-3/index.vue b/src/views/nested/menu1/menu1-3/index.vue new file mode 100644 index 000000000..518d5e800 --- /dev/null +++ b/src/views/nested/menu1/menu1-3/index.vue @@ -0,0 +1,3 @@ + diff --git a/src/views/nested/menu2/index.vue b/src/views/nested/menu2/index.vue new file mode 100644 index 000000000..208889e57 --- /dev/null +++ b/src/views/nested/menu2/index.vue @@ -0,0 +1,3 @@ +