feat
This commit is contained in:
@@ -29,6 +29,7 @@ export interface ServerMenuItem extends TreeNodeBase {
|
||||
// 预定义的视图模块映射(用于 Vite 动态导入)
|
||||
const viewModules = import.meta.glob('@/views/**/*.vue')
|
||||
|
||||
console.log('viewModules', viewModules)
|
||||
/**
|
||||
* 动态加载视图组件
|
||||
* @param componentPath 组件路径,如 'ops/pages/overview' 或 'ops/pages/overview/index'
|
||||
@@ -36,24 +37,33 @@ const viewModules = import.meta.glob('@/views/**/*.vue')
|
||||
*/
|
||||
export function loadViewComponent(componentPath: string) {
|
||||
// 将路径转换为完整的视图路径
|
||||
// 如果路径不以 /index 结尾,自动补全
|
||||
let fullPath = componentPath
|
||||
if (!fullPath.endsWith('/index') && !fullPath.endsWith('.vue')) {
|
||||
fullPath = `${fullPath}/index`
|
||||
// 如果路径不以 /index 结尾且不以 .vue 结尾,自动补全
|
||||
let normalizedPath = componentPath
|
||||
if (!normalizedPath.endsWith('/index') && !normalizedPath.endsWith('.vue')) {
|
||||
normalizedPath = `${normalizedPath}/index`
|
||||
}
|
||||
|
||||
// 构建完整的文件路径
|
||||
const filePath = `/src/views/${fullPath}.vue`
|
||||
const filePath = `/src/views/${normalizedPath}.vue`
|
||||
console.log('filePath', filePath)
|
||||
|
||||
// 从预加载的模块中查找
|
||||
const modulePath = Object.keys(viewModules).find((path) => path.endsWith(filePath) || path === filePath)
|
||||
|
||||
console.log('modulePath', modulePath)
|
||||
if (modulePath && viewModules[modulePath]) {
|
||||
return viewModules[modulePath]
|
||||
}
|
||||
|
||||
// 如果找不到,返回一个默认组件或抛出错误
|
||||
console.warn(`View component not found: ${filePath}`)
|
||||
// 如果找不到,尝试不带 /index 的路径
|
||||
const directFilePath = `/src/views/${componentPath}.vue`
|
||||
const directModulePath = Object.keys(viewModules).find((path) => path.endsWith(directFilePath) || path === directFilePath)
|
||||
|
||||
if (directModulePath && viewModules[directModulePath]) {
|
||||
return viewModules[directModulePath]
|
||||
}
|
||||
|
||||
// 如果都找不到,返回一个默认组件或抛出错误
|
||||
console.warn(`View component not found: ${filePath} or ${directFilePath}`)
|
||||
return () => import('@/views/redirect/index.vue')
|
||||
}
|
||||
|
||||
@@ -70,6 +80,7 @@ export function transformMenuToRoutes(menuItems: ServerMenuItem[]): AppRouteReco
|
||||
path: item.menu_path || '',
|
||||
name: item.title || item.name || `menu_${item.id}`,
|
||||
meta: {
|
||||
// ...item,
|
||||
locale: item.locale || item.title,
|
||||
requiresAuth: item.requiresAuth !== false,
|
||||
icon: item.icon || item?.menu_icon,
|
||||
@@ -87,6 +98,7 @@ export function transformMenuToRoutes(menuItems: ServerMenuItem[]): AppRouteReco
|
||||
// 传递父级的 component 和 path 给子路由处理函数
|
||||
route.children = transformChildRoutes(item.children, item.component, item.menu_path)
|
||||
} else if (item.component) {
|
||||
console.log('menu item component:', item.component)
|
||||
// 一级菜单没有 children 但有 component,创建一个空路径的子路由
|
||||
const routeName = route.name
|
||||
route.children = [
|
||||
@@ -97,7 +109,7 @@ export function transformMenuToRoutes(menuItems: ServerMenuItem[]): AppRouteReco
|
||||
meta: {
|
||||
locale: item.locale || item.title,
|
||||
requiresAuth: item.requiresAuth !== false,
|
||||
isNewTab: item.is_new_tab
|
||||
isNewTab: item.is_new_tab,
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -159,7 +171,7 @@ function transformChildRoutes(
|
||||
return children.map((child) => {
|
||||
// 优先使用子菜单自己的 component,否则继承父级的 component
|
||||
const componentPath = child.component || parentComponent
|
||||
|
||||
console.log('child component:', componentPath)
|
||||
// 计算子路由的相对路径
|
||||
const childFullPath = child.menu_path || child.path || ''
|
||||
const relativePath = extractRelativePath(childFullPath, parentPath || '')
|
||||
@@ -168,6 +180,7 @@ function transformChildRoutes(
|
||||
path: relativePath,
|
||||
name: child.title || child.name || `menu_${child.id}`,
|
||||
meta: {
|
||||
...child,
|
||||
locale: child.locale || child.title,
|
||||
requiresAuth: child.requiresAuth !== false,
|
||||
roles: child.roles,
|
||||
|
||||
@@ -32,6 +32,38 @@ const OPS: AppRouteRecordRaw = {
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'web-test',
|
||||
name: 'WebTest',
|
||||
component: () => import('@/views/ops/pages/help/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.ops.webTest',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
is_web_page: true,
|
||||
web_url: 'https://www.baidu.com'
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'netarch/topo-group',
|
||||
name: 'TopologyGroup',
|
||||
component: () => import('@/views/ops/pages/netarch/topo-group/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.ops.netarch.topoGroup',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'netarch/topo',
|
||||
name: 'Topology',
|
||||
component: () => import('@/views/ops/pages/netarch/topo/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.ops.netarch.topo',
|
||||
requiresAuth: true,
|
||||
roles: ['*'],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
2
src/router/typings.d.ts
vendored
2
src/router/typings.d.ts
vendored
@@ -12,5 +12,7 @@ declare module 'vue-router' {
|
||||
order?: number // Sort routing menu items. If set key, the higher the value, the more forward it is
|
||||
noAffix?: boolean // if set true, the tag will not affix in the tab-bar
|
||||
ignoreCache?: boolean // if set true, the page will not be cached
|
||||
is_web_page?: boolean // If true and web_url exists, display as iframe
|
||||
web_url?: string // The URL to display in iframe when is_web_page is true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user