diff --git a/apps/jingrow/frontend/src/app/main.ts b/apps/jingrow/frontend/src/app/main.ts index 1a95c68..309e181 100644 --- a/apps/jingrow/frontend/src/app/main.ts +++ b/apps/jingrow/frontend/src/app/main.ts @@ -29,4 +29,13 @@ import { useAuthStore } from '../shared/stores/auth' const authStore = useAuthStore() authStore.initAuth() +// 初始化动态工具路由 - 使用 router.isReady() 确保路由已完全初始化 +import { useToolsStore } from '../shared/stores/tools' +router.isReady().then(() => { + const toolsStore = useToolsStore() + toolsStore.initToolRoutes(router) +}).catch((error) => { + console.error('Failed to initialize tool routes:', error) +}) + app.mount('#app') diff --git a/apps/jingrow/frontend/src/app/router/index.ts b/apps/jingrow/frontend/src/app/router/index.ts index 0c88a54..e272dc9 100644 --- a/apps/jingrow/frontend/src/app/router/index.ts +++ b/apps/jingrow/frontend/src/app/router/index.ts @@ -12,6 +12,7 @@ const router = createRouter({ }, { path: '/', + name: 'AppLayout', component: () => import('../layouts/AppLayout.vue'), meta: { requiresAuth: true }, children: [ diff --git a/apps/jingrow/frontend/src/shared/stores/tools.ts b/apps/jingrow/frontend/src/shared/stores/tools.ts index 2b6bf83..845d018 100644 --- a/apps/jingrow/frontend/src/shared/stores/tools.ts +++ b/apps/jingrow/frontend/src/shared/stores/tools.ts @@ -1,6 +1,7 @@ import { defineStore } from 'pinia' import { computed, ref } from 'vue' import { t } from '../i18n' +import { registerToolRoute, unregisterToolRoute, syncToolRoutes, registerAllToolRoutes } from '../utils/dynamicRoutes' export interface Tool { id: string @@ -120,7 +121,7 @@ export const useToolsStore = defineStore('tools', () => { }) // 添加用户工具 - function addUserTool(tool: Tool) { + function addUserTool(tool: Tool, router?: any, componentPath?: string) { const defaultToolsCount = getDefaultTools().filter( t => !hiddenDefaultToolIds.value.includes(t.id) ).length @@ -129,6 +130,11 @@ export const useToolsStore = defineStore('tools', () => { tool.isDefault = false userTools.value.push(tool) saveUserTools(userTools.value) + + // 如果是路由类型工具,注册路由(如果提供了 router) + if (tool.type === 'route' && tool.routeName && router) { + registerToolRoute(router, tool, componentPath) + } } // 更新用户工具 @@ -141,7 +147,9 @@ export const useToolsStore = defineStore('tools', () => { } // 删除用户工具 - function deleteUserTool(toolId: string) { + function deleteUserTool(toolId: string, router?: any) { + const tool = userTools.value.find(t => t.id === toolId) + userTools.value = userTools.value.filter(t => t.id !== toolId) // 重新分配 order const defaultToolsCount = getDefaultTools().filter( @@ -151,6 +159,11 @@ export const useToolsStore = defineStore('tools', () => { t.order = defaultToolsCount + index + 1 }) saveUserTools(userTools.value) + + // 如果是路由类型工具,移除路由(如果提供了 router) + if (tool?.type === 'route' && tool.routeName && router) { + unregisterToolRoute(router, tool.routeName) + } } // 隐藏默认工具 @@ -181,6 +194,16 @@ export const useToolsStore = defineStore('tools', () => { saveUserTools(userTools.value) } + // 初始化工具路由(在应用启动时调用) + function initToolRoutes(router: any) { + registerAllToolRoutes(router, userTools.value) + } + + // 同步工具路由(移除不存在的,添加新的) + function syncRoutes(router: any) { + syncToolRoutes(router, userTools.value) + } + return { userTools, hiddenDefaultToolIds, @@ -192,7 +215,9 @@ export const useToolsStore = defineStore('tools', () => { hideDefaultTool, showDefaultTool, updateUserToolsOrder, - getDefaultTools + getDefaultTools, + initToolRoutes, + syncRoutes } }) diff --git a/apps/jingrow/frontend/src/shared/utils/dynamicRoutes.ts b/apps/jingrow/frontend/src/shared/utils/dynamicRoutes.ts new file mode 100644 index 0000000..eb581a5 --- /dev/null +++ b/apps/jingrow/frontend/src/shared/utils/dynamicRoutes.ts @@ -0,0 +1,159 @@ +/** + * 动态路由管理工具 + * 用于动态注册和移除工具路由 + */ + +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 as any).componentPath || + `../../views/tools/${tool.routeName}.vue` + + // 构建路由路径 + // 默认使用 tools/{id},但可以通过 tool.routePath 自定义 + const routePath = (tool as any).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 { + template: '
Failed to load: {{ path }}