diff --git a/src/components/ReIcon/index.ts b/src/components/ReIcon/index.ts index 0d2b77091..98615272c 100644 --- a/src/components/ReIcon/index.ts +++ b/src/components/ReIcon/index.ts @@ -13,6 +13,8 @@ export function findIconReg(icon: string) { const faReg = /^FA-/; // iconfont const iFReg = /^IF-/; + // remixicon + const riReg = /^RI-/; // typeof icon === "function" 属于SVG if (faReg.test(icon)) { const text = icon.split(faReg)[1]; @@ -25,12 +27,14 @@ export function findIconReg(icon: string) { return findIcon(icon.split(iFReg)[1], "IF"); } else if (typeof icon === "function") { return findIcon(icon, "SVG"); + } else if (riReg.test(icon)) { + return findIcon(icon.split(riReg)[1], "RI"); } else { return findIcon(icon, "EL"); } } -// 支持fontawesome、iconfont、element-plus/icons、自定义svg +// 支持fontawesome、iconfont、remixicon、element-plus/icons、自定义svg export function findIcon(icon: String, type = "EL", property?: string) { if (type === "FA") { return defineComponent({ @@ -49,6 +53,14 @@ export function findIcon(icon: String, type = "EL", property?: string) { }, template: `` }); + } else if (type === "RI") { + return defineComponent({ + name: "RIIcon", + data() { + return { icon: `ri-${icon}` }; + }, + template: `` + }); } else if (type === "EL") { const components = iconComponents.filter( component => component.name === icon diff --git a/src/plugins/element-plus/index.ts b/src/plugins/element-plus/index.ts index 4c4ac4198..60b3ae3bc 100644 --- a/src/plugins/element-plus/index.ts +++ b/src/plugins/element-plus/index.ts @@ -43,6 +43,7 @@ import { ElEmpty, ElCollapse, ElCollapseItem, + ElTreeV2, // 指令 ElLoading, ElInfiniteScroll @@ -94,7 +95,8 @@ const components = [ ElAvatar, ElEmpty, ElCollapse, - ElCollapseItem + ElCollapseItem, + ElTreeV2 ]; // https://element-plus.org/zh-CN/component/icon.html diff --git a/src/plugins/i18n/config.ts b/src/plugins/i18n/config.ts index 83817a509..604e7d441 100644 --- a/src/plugins/i18n/config.ts +++ b/src/plugins/i18n/config.ts @@ -43,6 +43,7 @@ export const menusConfig = { permissionPage: "页面权限", permissionButton: "按钮权限", hstabs: "标签页操作", + hsMenuTree: "菜单树结构", externalLink: "外链" } }, @@ -80,6 +81,7 @@ export const menusConfig = { permissionPage: "Page Permission", permissionButton: "Button Permission", hstabs: "Tabs Operate", + hsMenuTree: "Menu Tree", externalLink: "External Link" } } diff --git a/src/router/modules/home.ts b/src/router/modules/home.ts index 5dc5b7b3a..bb1ad2ad7 100644 --- a/src/router/modules/home.ts +++ b/src/router/modules/home.ts @@ -7,6 +7,7 @@ const homeRouter = { redirect: "/welcome", meta: { icon: "HomeFilled", + title: "message.hshome", showLink: true, i18n: true, rank: 0 diff --git a/src/router/modules/index.ts b/src/router/modules/index.ts index f3658d47e..2fd1a4f79 100644 --- a/src/router/modules/index.ts +++ b/src/router/modules/index.ts @@ -3,6 +3,7 @@ import homeRouter from "./home"; import errorRouter from "./error"; import editorRouter from "./editor"; import nestedRouter from "./nested"; +import menuTreeRouter from "./menuTree"; import externalLink from "./externalLink"; import flowChartRouter from "./flowchart"; import remainingRouter from "./remaining"; @@ -22,6 +23,7 @@ const routes = [ nestedRouter, externalLink, editorRouter, + menuTreeRouter, flowChartRouter, componentsRouter ]; diff --git a/src/router/modules/menuTree.ts b/src/router/modules/menuTree.ts new file mode 100644 index 000000000..0a16e6329 --- /dev/null +++ b/src/router/modules/menuTree.ts @@ -0,0 +1,29 @@ +import Layout from "/@/layout/index.vue"; + +const menuTreeRouter = { + path: "/menuTree", + name: "reMenuTree", + component: Layout, + redirect: "/menuTree/index", + meta: { + icon: "RI-node-tree", + title: "message.hsMenuTree", + i18n: true, + showLink: true, + rank: 9 + }, + children: [ + { + path: "/menuTree/index", + name: "reMenuTree", + component: () => import("/@/views/menu-tree/index.vue"), + meta: { + title: "message.hsMenuTree", + showLink: true, + i18n: true + } + } + ] +}; + +export default menuTreeRouter; diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts index 608bc30bd..9094edf22 100644 --- a/src/store/modules/permission.ts +++ b/src/store/modules/permission.ts @@ -1,6 +1,7 @@ import { defineStore } from "pinia"; import { store } from "/@/store"; import { cacheType } from "./types"; +import { cloneDeep } from "lodash-es"; import { RouteConfigs } from "/@/layout/types"; import { constantMenus } from "/@/router/modules"; import { ascending, filterTree } from "/@/router/utils"; @@ -12,6 +13,8 @@ export const usePermissionStore = defineStore({ constantMenus, // 整体路由生成的菜单(静态、动态) wholeMenus: [], + // 深拷贝一个菜单树,与导航菜单不突出 + menusTree: [], buttonAuth: [], // 缓存页面keepAlive cachePageList: [] @@ -24,6 +27,10 @@ export const usePermissionStore = defineStore({ ascending(this.constantMenus.concat(routes)) ); + this.menusTree = cloneDeep( + filterTree(ascending(this.constantMenus.concat(routes))) + ); + const getButtonAuth = (arrRoutes: Array) => { if (!arrRoutes || !arrRoutes.length) return; arrRoutes.forEach((v: RouteConfigs) => { diff --git a/src/utils/tree.ts b/src/utils/tree.ts new file mode 100644 index 000000000..58ce86b16 --- /dev/null +++ b/src/utils/tree.ts @@ -0,0 +1,42 @@ +/** + * 提取菜单树中的每一项path + * @param {Object} {menuTree 菜单树} + * @param {return}} expandedPaths 每一项path组成的数组 + */ +const expandedPaths = []; +export function extractPathList(menuTree) { + if (!Array.isArray(menuTree)) { + console.warn("menuTree must be an array"); + return; + } + if (!menuTree || menuTree.length === 0) return; + for (const node of menuTree) { + const hasChildren = node.children && node.children.length > 0; + if (hasChildren) { + extractPathList(node.children); + } + expandedPaths.push(node.path); + } + return expandedPaths; +} + +/** + * 如果父级下children的length为1,删除children + * @param {Object} {menuTree 菜单树} + * @param {return}} + */ +export function deleteChildren(menuTree) { + if (!Array.isArray(menuTree)) { + console.warn("menuTree must be an array"); + return; + } + if (!menuTree || menuTree.length === 0) return; + for (const node of menuTree) { + if (node.children && node.children.length === 1) delete node.children; + const hasChildren = node.children && node.children.length > 0; + if (hasChildren) { + deleteChildren(node.children); + } + } + return menuTree; +} diff --git a/src/views/menu-tree/index.vue b/src/views/menu-tree/index.vue new file mode 100644 index 000000000..b1788ce81 --- /dev/null +++ b/src/views/menu-tree/index.vue @@ -0,0 +1,36 @@ + + + + +