diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts index 2d245f62..0376c08f 100644 --- a/apps/web-antd/src/router/access.ts +++ b/apps/web-antd/src/router/access.ts @@ -94,190 +94,145 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) { }; /** - * 优化后的后台路由转 vben 路由 + * 后台路由转vben路由 * + * todo 需要重构 * @param menuList 后台菜单 * @param parentPath 上级目录 - * @returns vben 路由 + * @returns vben路由 */ function backMenuToVbenMenu( menuList: Menu[], parentPath = '', ): RouteRecordStringComponent[] { const resultList: RouteRecordStringComponent[] = []; - menuList.forEach((menu) => { - // 根目录处理 - if (isRootMenu(menu)) { + // 根目录为菜单形式 + // 固定有一个children children为当前菜单 + if (menu.path === '/' && menu.children && menu.children.length === 1) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion menu.meta = menu.children[0]!.meta; + /** + * todo 先写死 后续再优化 + */ + menu.path = '/root_menu'; menu.component = 'RootMenu'; } - - // 外链处理 - if (isExternalLink(menu)) { + // 外链: http开头 & 组件为Layout || ParentView + // 正则判断是否为http://或者https://开头 + if ( + /^https?:\/\//.test(menu.path) && + (menu.component === 'Layout' || menu.component === 'ParentView') + ) { menu.component = 'Link'; } - - // 内嵌 iframe 处理 - if (isIframe(menu)) { + // 内嵌iframe 组件为InnerLink + if (menu.meta?.link && menu.component === 'InnerLink') { menu.component = 'IFrameView'; } - // 处理路径 - menu.path = formatPath(menu.path, parentPath); + // path + if (parentPath) { + menu.path = `${parentPath}/${menu.path}`; + } - const vbenRoute: RouteRecordStringComponent = createVbenRoute(menu); + const vbenRoute: RouteRecordStringComponent = { + component: menu.component, + meta: { + // 当前路由不在菜单显示 但是可以通过链接访问 + // 不可访问的路由由后端控制隐藏(不返回对应路由) + hideInMenu: menu.hidden, + icon: menu.meta?.icon, + keepAlive: !menu.meta?.noCache, + title: menu.meta?.title, + }, + name: menu.name, + path: menu.path, + }; - // 处理组件类型 - handleComponentType(menu, vbenRoute); + /** + * 处理不同组件 + */ + switch (menu.component) { + case 'Layout': { + vbenRoute.component = 'BasicLayout'; + break; + } + /** + * iframe内嵌 + */ + case 'IFrameView': { + vbenRoute.component = 'IFrameView'; + if (vbenRoute.meta) { + vbenRoute.meta.iframeSrc = menu.meta.link; + } + /** + * 需要判断特殊情况 比如vue的hash是带#的 + * 比如链接 aaa.com/#/bbb path会转换为 aaa/com/#/bbb + * 比如链接 aaa.com/?bbb=xxx + * 需要去除# 否则无法被添加到路由 + */ + /** + * todo 不优雅 考虑别的方案 + */ + if (vbenRoute.path.includes('/#/')) { + vbenRoute.path = vbenRoute.path.replace('/#/', ''); + } + if (vbenRoute.path.includes('#')) { + vbenRoute.path = vbenRoute.path.replace('#', ''); + } + if (vbenRoute.path.includes('?') || vbenRoute.path.includes('&')) { + vbenRoute.path = vbenRoute.path.replace('?', ''); + vbenRoute.path = vbenRoute.path.replace('&', ''); + } + break; + } + /** + * 外链 新窗口打开 + */ + case 'Link': { + if (vbenRoute.meta) { + vbenRoute.meta.link = menu.meta.link; + } + vbenRoute.component = 'BasicLayout'; + break; + } + /** + * 根目录菜单 + */ + case 'RootMenu': { + if (vbenRoute.meta) { + vbenRoute.meta.hideChildrenInMenu = true; + } + vbenRoute.component = 'BasicLayout'; + break; + } + /** + * 不能为layout 会套两层BasicLayout + */ + case 'ParentView': { + vbenRoute.component = ''; + break; + } + /** + * 其他自定义组件 如system/user/index 拼接/ + */ + default: { + vbenRoute.component = `/${menu.component}`; + break; + } + } - // 递归处理子路由 + // children处理 if (menu.children && menu.children.length > 0) { vbenRoute.children = backMenuToVbenMenu(menu.children, menu.path); } resultList.push(vbenRoute); }); - return resultList; } - /** - * 根目录处理 - * @param menu - */ - function isRootMenu(menu: Menu): boolean { - return menu.path === '/' && menu.children && menu.children.length === 1; - } - - /** - * 外链判断 - * @param menu - */ - function isExternalLink(menu: Menu): boolean { - return ( - /^https?:\/\//.test(menu.path) && - (menu.component === 'Layout' || menu.component === 'ParentView') - ); - } - - /** - * 内嵌 iframe 判断 - * @param menu - */ - function isIframe(menu: Menu): boolean { - return !!menu.meta?.link && menu.component === 'InnerLink'; - } - - /** - * 格式化路径 - * @param path - * @param parentPath - */ - function formatPath(path: string, parentPath: string): string { - // 如果父路径是根目录且当前路径不是根目录,避免多余的斜杠 - if (parentPath === '/' && path !== '/') { - return `/${path}`; - } - // 如果当前路径是根目录,直接返回 - if (path === '/') { - return parentPath ? `${parentPath}` : path; - } - // 处理其他正常情况 - return parentPath ? `${parentPath}/${path}` : path; - } - - /** - * 创建 vben 路由 - * @param menu - */ - function createVbenRoute(menu: Menu): RouteRecordStringComponent { - return { - component: menu.component, - meta: { - hideInMenu: menu.hidden, - icon: menu.meta?.icon, - keepAlive: !menu.meta?.noCache, - title: menu.meta?.title, - }, - name: menu.name, - path: menu.path, - }; - } - - /** - * 处理不同组件类型 - * @param menu - * @param vbenRoute - */ - function handleComponentType( - menu: Menu, - vbenRoute: RouteRecordStringComponent, - ) { - switch (menu.component) { - case 'Layout': { - vbenRoute.component = 'BasicLayout'; - break; - } - /** - * iframe内嵌 - */ - case 'IFrameView': { - vbenRoute.component = 'IFrameView'; - handleIframePath(vbenRoute); - break; - } - /** - * 外链 新窗口打开 - */ - case 'Link': { - vbenRoute.component = 'BasicLayout'; - break; - } - /** - * 根目录菜单 - */ - case 'RootMenu': { - if (vbenRoute.meta) { - vbenRoute.meta.hideChildrenInMenu = true; - } - vbenRoute.component = 'BasicLayout'; - break; - } - /** - * 不能为layout 会套两层BasicLayout - */ - case 'ParentView': { - vbenRoute.component = ''; - break; - } - /** - * 其他自定义组件 如system/user/index 拼接/ - */ - default: { - vbenRoute.component = `/${menu.component}`; - } - } - } - - /** - * 处理 iframe 路径中的特殊字符 - * @param vbenRoute - */ - function handleIframePath(vbenRoute: RouteRecordStringComponent) { - if (vbenRoute.meta) { - vbenRoute.meta.iframeSrc = vbenRoute.meta.link; - - const specialChars = ['#', '?', '&']; - specialChars.forEach((char) => { - if (vbenRoute.path.includes(char)) { - vbenRoute.path = vbenRoute.path.replace(char, ''); - } - }); - } - } - return await generateAccessible(preferences.app.accessMode, { ...options, fetchMenuListAsync: async () => { @@ -285,7 +240,6 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) { content: `${$t('common.loadingMenu')}...`, duration: 1, }); - // 后台返回路由/菜单 const backMenuList = await getAllMenusApi(); // 转换为vben能用的路由 @@ -293,7 +247,6 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) { // 特别注意 这里要深拷贝 const menuList = [...cloneDeep(localMenuList), ...vbenMenuList]; console.log('menuList', menuList); - return menuList; }, // 可以指定没有权限跳转403页面 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e52ede4..4097e946 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4210,13 +4210,6 @@ packages: resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} -<<<<<<< HEAD - '@typescript-eslint/scope-manager@8.2.0': - resolution: {integrity: sha512-OFn80B38yD6WwpoHU2Tz/fTz7CgFqInllBoC3WP+/jLbTb4gGPTy9HBSTsbDWkMdN55XlVU0mMDYAtgvlUspGw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/scope-manager@8.3.0': resolution: {integrity: sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4234,13 +4227,6 @@ packages: resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} -<<<<<<< HEAD - '@typescript-eslint/types@8.2.0': - resolution: {integrity: sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/types@8.3.0': resolution: {integrity: sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4254,18 +4240,6 @@ packages: typescript: optional: true -<<<<<<< HEAD - '@typescript-eslint/typescript-estree@8.2.0': - resolution: {integrity: sha512-kiG4EDUT4dImplOsbh47B1QnNmXSoUqOjWDvCJw/o8LgfD0yr7k2uy54D5Wm0j4t71Ge1NkynGhpWdS0dEIAUA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/typescript-estree@8.3.0': resolution: {integrity: sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4281,15 +4255,6 @@ packages: peerDependencies: eslint: ^8.56.0 -<<<<<<< HEAD - '@typescript-eslint/utils@8.2.0': - resolution: {integrity: sha512-O46eaYKDlV3TvAVDNcoDzd5N550ckSe8G4phko++OCSC1dYIb9LTc3HDGYdWqWIAT5qDUKphO6sd9RrpIJJPfg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/utils@8.3.0': resolution: {integrity: sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4300,13 +4265,6 @@ packages: resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} -<<<<<<< HEAD - '@typescript-eslint/visitor-keys@8.2.0': - resolution: {integrity: sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/visitor-keys@8.3.0': resolution: {integrity: sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -13065,11 +13023,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 -<<<<<<< HEAD - '@types/node': 22.5.0 -======= - '@types/node': 18.19.47 ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 + '@types/node': 22.5.1 '@types/hast@3.0.4': dependencies: @@ -13091,11 +13045,7 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: -<<<<<<< HEAD - '@types/node': 22.5.0 -======= '@types/node': 22.5.1 ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@types/jsonwebtoken@9.0.6': dependencies: @@ -13210,14 +13160,6 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 -<<<<<<< HEAD - '@typescript-eslint/scope-manager@8.2.0': - dependencies: - '@typescript-eslint/types': 8.2.0 - '@typescript-eslint/visitor-keys': 8.2.0 - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/scope-manager@8.3.0': dependencies: '@typescript-eslint/types': 8.3.0 @@ -13237,11 +13179,6 @@ snapshots: '@typescript-eslint/types@7.18.0': {} -<<<<<<< HEAD - '@typescript-eslint/types@8.2.0': {} - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/types@8.3.0': {} '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.4)': @@ -13259,24 +13196,6 @@ snapshots: transitivePeerDependencies: - supports-color -<<<<<<< HEAD - '@typescript-eslint/typescript-estree@8.2.0(typescript@5.5.4)': - dependencies: - '@typescript-eslint/types': 8.2.0 - '@typescript-eslint/visitor-keys': 8.2.0 - debug: 4.3.6 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/typescript-estree@8.3.0(typescript@5.5.4)': dependencies: '@typescript-eslint/types': 8.3.0 @@ -13303,20 +13222,6 @@ snapshots: - supports-color - typescript -<<<<<<< HEAD - '@typescript-eslint/utils@8.2.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1(jiti@1.21.6)) - '@typescript-eslint/scope-manager': 8.2.0 - '@typescript-eslint/types': 8.2.0 - '@typescript-eslint/typescript-estree': 8.2.0(typescript@5.5.4) - eslint: 9.9.1(jiti@1.21.6) - transitivePeerDependencies: - - supports-color - - typescript - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/utils@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1(jiti@1.21.6)) @@ -13333,14 +13238,6 @@ snapshots: '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 -<<<<<<< HEAD - '@typescript-eslint/visitor-keys@8.2.0': - dependencies: - '@typescript-eslint/types': 8.2.0 - eslint-visitor-keys: 3.4.3 - -======= ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 '@typescript-eslint/visitor-keys@8.3.0': dependencies: '@typescript-eslint/types': 8.3.0 @@ -15252,13 +15149,8 @@ snapshots: eslint-plugin-perfectionist@3.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)(vue-eslint-parser@9.4.3(eslint@9.9.1(jiti@1.21.6))): dependencies: -<<<<<<< HEAD - '@typescript-eslint/types': 8.2.0 - '@typescript-eslint/utils': 8.2.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) -======= '@typescript-eslint/types': 8.3.0 '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) ->>>>>>> 88a7a9b1ee45901fe61c2fab70c95b50452a1cc5 eslint: 9.9.1(jiti@1.21.6) minimatch: 10.0.1 natural-compare-lite: 1.4.0