Files
Common_Platform/web/src/router/dynamic-routes.ts
T

72 lines
1.9 KiB
TypeScript

import type { Component } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import type { MenuNode } from '@/types/auth'
const viewModules = import.meta.glob('../features/**/index.vue')
const dynamicRouteNames = new Set<string>()
function normalizePath(path: string) {
if (!path.startsWith('/')) return `/${path}`
return path
}
function routeNameByMenu(menu: MenuNode) {
if (menu.name && menu.name.trim().length > 0) {
return menu.name.trim()
}
return `menu-${menu.id}`
}
function resolveViewComponent(componentPath?: string | null): Component {
if (!componentPath) {
return () => import('@/views/errors/NotFoundView.vue')
}
const normalized = componentPath.endsWith('.vue') ? componentPath : `${componentPath}.vue`
const fullPath = `../features/${normalized}`
const component = viewModules[fullPath]
if (!component) {
return () => import('@/views/errors/NotFoundView.vue')
}
return component as unknown as Component
}
function toRoute(menu: MenuNode): RouteRecordRaw | null {
if (menu.type !== 'MENU') return null
if (!menu.path || !menu.component || !menu.visible) return null
const name = routeNameByMenu(menu)
dynamicRouteNames.add(name)
return {
path: normalizePath(menu.path),
name,
component: resolveViewComponent(menu.component),
meta: {
title: menu.title,
permission: menu.permission ?? undefined,
keepAlive: menu.keepAlive,
requiresAuth: true,
dynamic: true
}
}
}
function flattenMenus(menus: MenuNode[]): MenuNode[] {
return menus.flatMap((item) => [item, ...flattenMenus(item.children ?? [])])
}
export function buildDynamicRoutes(menus: MenuNode[]) {
return flattenMenus(menus)
.map(toRoute)
.filter((item): item is RouteRecordRaw => Boolean(item))
}
export function consumeDynamicRouteNames() {
return [...dynamicRouteNames]
}
export function resetDynamicRouteNames() {
dynamicRouteNames.clear()
}