You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.8 KiB
TypeScript

import type { RouteRecordNormalized, RouteRecordRaw } from 'vue-router'
import { pathToRegexp } from 'path-to-regexp'
import { cloneDeep, findParentPath, isUrl, mapTree } from '~/utils'
export function getAllParentPath<T = Recordable<any>>(
treeData: T[],
path: string,
) {
const menuList = findParentPath(treeData, n => n.path === path) as unknown as Menu[]
return (menuList || []).map(item => item.path)
}
export function hideFilter(menu: Menu) {
// console.log('hideFilter', menu, !(menu.meta?.hideInMenu || menu.hideInMenu))
return !menu.hideInMenu
}
export function basicFilter(routes: RouteRecordNormalized[]) {
return (menu: Menu) => {
const matchRoute = routes.find((route) => {
if (isUrl(menu.path))
return true
if (route.meta?.carryParam)
return pathToRegexp(route.path).test(menu.path)
const isSame = route.path === menu.path
if (!isSame)
return false
if (route.meta?.ignoreAuth)
return true
return isSame || pathToRegexp(route.path).test(menu.path)
})
if (!matchRoute)
return false
menu.icon = (menu.icon || matchRoute.meta.icon) as string
menu.meta = matchRoute.meta
return true
}
}
function joinParentPath(menus: Menu[], parentPath = '') {
for (let index = 0; index < menus.length; index++) {
const menu = menus[index]
// https://next.router.vuejs.org/guide/essentials/nested-routes.html
// Note that nested paths that start with / will be treated as a root path.
// This allows you to leverage the component nesting without having to use a nested URL.
if (!(menu.path.startsWith('/') || isUrl(menu.path))) {
// path doesn't start with /, nor is it a url, join parent path
menu.path = `${parentPath}/${menu.path}`
}
if (menu?.children?.length) {
joinParentPath(
menu.children,
menu.meta?.hidePathForChildren ? parentPath : menu.path,
)
}
}
}
export function transformRouteToMenu(routes: RouteRecordRaw[], routerMapping: boolean = false): Menu[] {
const cloneRouteList = cloneDeep(routes)
const routeList: RouteRecordRaw[] = []
cloneRouteList.forEach((item) => {
if (routerMapping && item.meta?.hideChildrenInMenu && typeof item.redirect === 'string') {
item.path = item.redirect
}
routeList.push(item)
})
// 筛选隐藏子菜单
routeList.forEach((v) => {
if (v.meta?.hideChildrenInMenu) {
delete v.children
}
})
const list = mapTree(routeList, {
conversion: (node: RouteRecordRaw): Menu => {
const { meta: { hideInMenu = false } = {} } = node
return {
...(node.meta || {}),
meta: node.meta,
name: node.name as string,
hideInMenu,
path: node.path,
...(node.redirect ? { redirect: node.redirect } : {}),
}
},
})
joinParentPath(list)
return cloneDeep(list) as Menu[]
}