import { resolve } from 'path' import qs from 'qs' import type { VabRoute, VabRouteRecord } from '/#/router' import { hasPermission } from '@/utils/permission' import { isExternal } from '@/utils/validate' import { recordRoute } from '@/config' /** * @description all模式渲染后端返回路由,支持包含views路径的所有页面 * @param asyncRoutes * @returns {*} */ export function convertRouter(asyncRoutes: VabRouteRecord[]) { return asyncRoutes.map((route: any) => { if (route.component) { const component = route.component.match(/^@\S+|^Layout$/) if (component) component[0] === 'Layout' ? (route.component = () => import('@vab/layouts/index.vue')) : (route.component = () => import(`@/${component[0].replace(/@\/*/, '')}.vue`)) else throw `后端路由加载失败,请输入'Layout'或以'@/'开头的本地组件地址: ${route.component}` } if (route.children) route.children.length > 0 ? (route.children = convertRouter(route.children)) : delete route.children return route }) } /** * @description 根据roles数组拦截路由 * @param routes 路由 * @param rolesControl 是否进行权限控制 * @param baseUrl 基础路由 * @returns {[]} */ export function filterRoutes( routes: VabRouteRecord[], rolesControl: boolean, baseUrl = '/' ): VabRouteRecord[] { return routes .filter((route: VabRouteRecord) => rolesControl && route.meta.guard ? hasPermission(route.meta.guard) : true ) .flatMap((route: VabRouteRecord) => baseUrl !== '/' && route.children && route.meta.levelHidden ? [...route.children] : route ) .map((route: VabRouteRecord) => { route = { ...route } route.path = route.path !== '*' && !isExternal(route.path) ? resolve(baseUrl, route.path) : route.path if (route.children && route.children.length > 0) { route.children = filterRoutes( route.children, rolesControl, route.path ) if (route.children.length > 0) { route.childrenPathList = route.children.flatMap( (_) => _.childrenPathList ) if (!route.redirect) route.redirect = route.children[0].redirect || route.children[0].path } } else route.childrenPathList = [route.path] return route }) } /** * 根据path路径获取matched * @param routes 菜单routes * @param path 路径 * @returns {*} matched */ export function handleMatched( routes: VabRouteRecord[], path: string ): VabRouteRecord[] { return routes .filter( (route: VabRouteRecord) => (route?.childrenPathList || []).indexOf(path) + 1 ) .flatMap((route: VabRouteRecord) => route.children ? [route, ...handleMatched(route.children, path)] : [route] ) } /** * 生成单个多标签元素,可用于同步/异步添加多标签 * @param tag route页信息 */ export function handleTabs(tag: VabRoute | VabRouteRecord): any { let parentIcon = null if ('matched' in tag) for (let i = tag.matched.length - 2; i >= 0; i--) if (!parentIcon && tag.matched[i].meta.icon) parentIcon = tag.matched[i].meta.icon if (!parentIcon) parentIcon = 'menu-line' const path = handleActivePath(tag, true) if (tag.name && tag.meta.tabHidden !== true) return { path, query: 'query' in tag ? tag.query : {}, params: 'params' in tag ? tag.params : {}, name: tag.name as string, parentIcon, meta: { ...tag.meta }, } } /** * 根据当前route获取激活菜单 * @param route 当前路由 * @param isTab 是否是标签 * @returns {string|*} */ export function handleActivePath(route: VabRoute, isTab = false) { const { meta, path } = route const rawPath = route.matched ? route.matched[route.matched.length - 1].path : path const fullPath = route.query && Object.keys(route.query).length > 0 ? `${route.path}?${qs.stringify(route.query)}` : route.path if (isTab) return meta.dynamicNewTab ? fullPath : rawPath if (meta.activeMenu) return meta.activeMenu return fullPath } /** * 获取当前跳转登录页的Route * @param currentPath 当前页面地址 */ export function toLoginRoute(currentPath: string) { if (recordRoute && currentPath !== '/') return { path: '/login', query: { redirect: currentPath }, replace: true, } else return { path: '/login', replace: true } } /** * 获取路由中所有的Name * @param routes 路由数组 * @returns {*} Name数组 */ export function getNames(routes: VabRouteRecord[]): string[] { return routes.flatMap((route: VabRouteRecord) => { const names = [] if (route.name) names.push(route.name) if (route.children) names.push(...getNames(route.children)) return names }) }