154 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 动态路由管理工具
* 用于动态注册和移除工具路由
*/
import type { Router, RouteRecordRaw } from 'vue-router'
import type { Tool } from '../stores/tools'
/**
* 动态注册工具路由
* @param router Vue Router 实例
* @param tool 工具定义
* @param componentPath 组件路径(相对于 src/views
*/
export function registerToolRoute(
router: Router,
tool: Tool,
componentPath?: string
): boolean {
if (tool.type !== 'route' || !tool.routeName) {
return false
}
// 检查路由是否已存在
if (router.hasRoute(tool.routeName)) {
console.warn(`Route ${tool.routeName} already exists, skipping registration`)
return false
}
// 确定组件路径
// 1. 如果提供了 componentPath使用它
// 2. 如果工具有 componentPath 属性,使用它
// 3. 默认使用 tools/{routeName}.vue
const finalComponentPath =
componentPath ||
tool.componentPath ||
`../../views/tools/${tool.routeName}.vue`
// 构建路由路径
// 默认使用 tools/{id},但可以通过 tool.routePath 自定义
const routePath = tool.routePath || `tools/${tool.id}`
// 创建路由配置,添加组件加载错误处理
const route: RouteRecordRaw = {
path: routePath,
name: tool.routeName,
component: () => import(finalComponentPath).catch((error) => {
console.error(`Failed to load tool component: ${finalComponentPath}`, error)
// 返回一个简单的错误组件
return {
name: 'ToolComponentError',
template: '<div style="padding: 20px; text-align: center;"><h3>Component Not Found</h3><p>Failed to load component</p></div>'
}
}),
meta: {
requiresAuth: true,
toolId: tool.id,
toolName: tool.name
}
}
try {
// 将路由添加到 AppLayout 的 children 下
// AppLayout 路由应该在应用启动时已存在
const parentRouteName = router.hasRoute('AppLayout') ? 'AppLayout' : null
if (parentRouteName) {
router.addRoute(parentRouteName, route)
} else {
// 如果 AppLayout 不存在,直接添加到根路由(不应该发生,但作为降级方案)
console.warn('AppLayout route not found, adding tool route to root')
router.addRoute(route)
}
console.log(`Tool route registered: ${tool.routeName} -> ${routePath}`)
return true
} catch (error) {
console.error(`Failed to register tool route ${tool.routeName}:`, error)
return false
}
}
/**
* 移除工具路由
* @param router Vue Router 实例
* @param routeName 路由名称
*/
export function unregisterToolRoute(router: Router, routeName: string): boolean {
if (!router.hasRoute(routeName)) {
return false
}
try {
router.removeRoute(routeName)
console.log(`Tool route removed: ${routeName}`)
return true
} catch (error) {
console.error(`Failed to remove tool route ${routeName}:`, error)
return false
}
}
/**
* 注册所有用户工具的路由
* @param router Vue Router 实例
* @param tools 工具列表
*/
export function registerAllToolRoutes(router: Router, tools: Tool[]): void {
const routeTools = tools.filter(t => t.type === 'route' && t.routeName && !t.isDefault)
routeTools.forEach(tool => {
registerToolRoute(router, tool)
})
console.log(`Registered ${routeTools.length} tool routes`)
}
/**
* 同步工具路由(移除不存在的工具路由,添加新的工具路由)
* @param router Vue Router 实例
* @param currentTools 当前工具列表
*/
export function syncToolRoutes(router: Router, currentTools: Tool[]): void {
// 获取所有已注册的路由
const registeredRoutes = router.getRoutes()
// 找出所有工具路由(通过 meta.toolId 识别)
const toolRoutes = registeredRoutes.filter((route) =>
route.meta?.toolId && !route.meta?.isDefault
)
// 当前应该存在的工具路由名称
const currentRouteNames = new Set(
currentTools
.filter(t => t.type === 'route' && t.routeName && !t.isDefault)
.map(t => t.routeName!)
)
// 移除不再存在的工具路由
toolRoutes.forEach((route) => {
if (route.name && typeof route.name === 'string' && !currentRouteNames.has(route.name)) {
unregisterToolRoute(router, route.name)
}
})
// 添加新的工具路由
currentTools
.filter(t => t.type === 'route' && t.routeName && !t.isDefault)
.forEach(tool => {
if (tool.routeName && !router.hasRoute(tool.routeName)) {
registerToolRoute(router, tool)
}
})
}