diff --git a/src/interface/common/route.ts b/src/interface/common/route.ts index 3491aed9..906c1e17 100644 --- a/src/interface/common/route.ts +++ b/src/interface/common/route.ts @@ -1,7 +1,7 @@ import type { RouteRecordRaw } from 'vue-router'; /** 路由描述 */ -interface RouteMeta { +export interface CustomRouteMeta { /** 路由名称 */ title?: string; /** 缓存页面 */ @@ -12,12 +12,15 @@ interface RouteMeta { isNotMenu?: boolean; /** 菜单和面包屑对应的图标 */ icon?: string; - /** 路由作为菜单时的排序 */ + /** 导入的路由模块排序,可用于菜单的排序 */ order?: number; } /** 路由配置 */ -export type CustomRoute = RouteRecordRaw & { meta: RouteMeta }; +export type CustomRoute = RouteRecordRaw & { meta: CustomRouteMeta }; + +/** 导入的路由模块 */ +export type ImportedRouteModules = Record; /** 路由声明的key */ export type RouteKey = diff --git a/src/router/const/index.ts b/src/router/const/index.ts deleted file mode 100644 index 21e65850..00000000 --- a/src/router/const/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { RouteKey } from '@/interface'; - -interface RouteConst { - /** 路由名称 */ - name: RouteKey; - /** 路由路径 */ - path: string; - /** 路由标题 */ - title: string; -} - -/** 声明的路由名称、路径和标题 */ -const routeConstMap = new Map([ - ['root', { name: 'root', path: '/', title: 'Root' }], - ['login', { name: 'login', path: '/login', title: '登录' }], - ['no-permission', { name: 'no-permission', path: '/403', title: '无权限' }], - ['not-found', { name: 'not-found', path: '/404', title: '未找到' }], - ['service-error', { name: 'service-error', path: '/500', title: '服务器错误' }], - ['dashboard', { name: 'dashboard', path: '/dashboard', title: '仪表盘' }], - ['dashboard_analysis', { name: 'dashboard_analysis', path: '/dashboard/analysis', title: '分析页' }], - ['dashboard_workbench', { name: 'dashboard_workbench', path: '/dashboard/workbench', title: '工作台' }], - ['document', { name: 'document', path: '/document', title: '文档' }], - ['document_vue', { name: 'document_vue', path: '/document/vue', title: 'vue文档' }], - ['document_vite', { name: 'document_vite', path: '/document/vite', title: 'vite文档' }], - ['document_naive', { name: 'document_naive', path: '/document/naive', title: 'naive文档' }], - ['component', { name: 'component', path: '/component', title: '组件插件' }], - ['component_map', { name: 'component_map', path: '/component/map', title: '地图插件' }], - ['component_video', { name: 'component_video', path: '/component/video', title: '视频插件' }], - ['component_editor', { name: 'component_editor', path: '/component/editor', title: '编辑器' }], - [ - 'component_editor_quill', - { name: 'component_editor_quill', path: '/component/editor/quill', title: '富文本编辑器' } - ], - [ - 'component_editor_markdown', - { name: 'component_editor_markdown', path: '/component/editor/markdown', title: 'markdown编辑器' } - ], - ['component_swiper', { name: 'component_swiper', path: '/component/swiper', title: 'Swiper插件' }], - ['feat', { name: 'feat', path: '/feat', title: '功能示例' }], - ['feat_copy', { name: 'feat_copy', path: '/feat/copy', title: '剪贴板' }], - ['feat_icon', { name: 'feat_icon', path: '/feat/icon', title: '图标' }], - ['feat_print', { name: 'feat_print', path: '/feat/print', title: '打印' }], - ['multi-menu', { name: 'multi-menu', path: '/multi-menu', title: '多级菜单' }], - ['multi-menu_first', { name: 'multi-menu_first', path: '/multi-menu/first', title: '一级菜单' }], - ['multi-menu_first_second', { name: 'multi-menu_first_second', path: '/multi-menu/first/second', title: '二级菜单' }], - ['exception', { name: 'exception', path: '/exception', title: '异常页' }], - ['exception_403', { name: 'exception_403', path: '/exception/403', title: '异常页-403' }], - ['exception_404', { name: 'exception_404', path: '/exception/404', title: '异常页-404' }], - ['exception_500', { name: 'exception_500', path: '/exception/500', title: '异常页-500' }], - ['about', { name: 'about', path: '/about', title: '关于' }] -]); - -/** 获取路由的声明(name、path、title) */ -export function getRouteConst(key: RouteKey) { - return routeConstMap.get(key)!; -} -/** 路由名称 */ -export function routeName(key: RouteKey) { - return routeConstMap.get(key)!.name; -} -/** 路由路径 */ -export function routePath(key: RouteKey) { - return routeConstMap.get(key)!.path; -} -/** 路由标题 */ -export function routeTitle(key: RouteKey) { - return routeConstMap.get(key)!.title; -} diff --git a/src/router/constant/index.ts b/src/router/constant/index.ts new file mode 100644 index 00000000..9de8cff7 --- /dev/null +++ b/src/router/constant/index.ts @@ -0,0 +1,279 @@ +import type { RouteKey } from '@/interface'; + +interface RouteConst { + /** 路由名称 */ + name: RouteKey; + /** 路由路径 */ + path: string; + /** 路由标题 */ + title: string; +} + +/** 声明的路由名称、路径和标题 */ +const routeConstMap = new Map([ + [ + 'root', + { + name: 'root', + path: '/', + title: 'Root' + } + ], + [ + 'login', + { + name: 'login', + path: '/login', + title: '登录' + } + ], + [ + 'no-permission', + { + name: 'no-permission', + path: '/403', + title: '无权限' + } + ], + [ + 'not-found', + { + name: 'not-found', + path: '/404', + title: '未找到' + } + ], + [ + 'service-error', + { + name: 'service-error', + path: '/500', + title: '服务器错误' + } + ], + [ + 'dashboard', + { + name: 'dashboard', + path: '/dashboard', + title: '仪表盘' + } + ], + [ + 'dashboard_analysis', + { + name: 'dashboard_analysis', + path: '/dashboard/analysis', + title: '分析页' + } + ], + [ + 'dashboard_workbench', + { + name: 'dashboard_workbench', + path: '/dashboard/workbench', + title: '工作台' + } + ], + [ + 'document', + { + name: 'document', + path: '/document', + title: '文档' + } + ], + [ + 'document_vue', + { + name: 'document_vue', + path: '/document/vue', + title: 'vue文档' + } + ], + [ + 'document_vite', + { + name: 'document_vite', + path: '/document/vite', + title: 'vite文档' + } + ], + [ + 'document_naive', + { + name: 'document_naive', + path: '/document/naive', + title: 'naive文档' + } + ], + [ + 'component', + { + name: 'component', + path: '/component', + title: '组件插件' + } + ], + [ + 'component_map', + { + name: 'component_map', + path: '/component/map', + title: '地图插件' + } + ], + [ + 'component_video', + { + name: 'component_video', + path: '/component/video', + title: '视频插件' + } + ], + [ + 'component_editor', + { + name: 'component_editor', + path: '/component/editor', + title: '编辑器' + } + ], + [ + 'component_editor_quill', + { + name: 'component_editor_quill', + path: '/component/editor/quill', + title: '富文本编辑器' + } + ], + [ + 'component_editor_markdown', + { + name: 'component_editor_markdown', + path: '/component/editor/markdown', + title: 'markdown编辑器' + } + ], + [ + 'component_swiper', + { + name: 'component_swiper', + path: '/component/swiper', + title: 'Swiper插件' + } + ], + [ + 'feat', + { + name: 'feat', + path: '/feat', + title: '功能示例' + } + ], + [ + 'feat_copy', + { + name: 'feat_copy', + path: '/feat/copy', + title: '剪贴板' + } + ], + [ + 'feat_icon', + { + name: 'feat_icon', + path: '/feat/icon', + title: '图标' + } + ], + [ + 'feat_print', + { + name: 'feat_print', + path: '/feat/print', + title: '打印' + } + ], + [ + 'multi-menu', + { + name: 'multi-menu', + path: '/multi-menu', + title: '多级菜单' + } + ], + [ + 'multi-menu_first', + { + name: 'multi-menu_first', + path: '/multi-menu/first', + title: '一级菜单' + } + ], + [ + 'multi-menu_first_second', + { + name: 'multi-menu_first_second', + path: '/multi-menu/first/second', + title: '二级菜单' + } + ], + [ + 'exception', + { + name: 'exception', + path: '/exception', + title: '异常页' + } + ], + [ + 'exception_403', + { + name: 'exception_403', + path: '/exception/403', + title: '异常页-403' + } + ], + [ + 'exception_404', + { + name: 'exception_404', + path: '/exception/404', + title: '异常页-404' + } + ], + [ + 'exception_500', + { + name: 'exception_500', + path: '/exception/500', + title: '异常页-500' + } + ], + [ + 'about', + { + name: 'about', + path: '/about', + title: '关于' + } + ] +]); + +/** 获取路由的声明(name、path、title) */ +export function getRouteConst(key: RouteKey) { + return routeConstMap.get(key)!; +} +/** 路由名称 */ +export function routeName(key: RouteKey) { + return routeConstMap.get(key)!.name; +} +/** 路由路径 */ +export function routePath(key: RouteKey) { + return routeConstMap.get(key)!.path; +} +/** 路由标题 */ +export function routeTitle(key: RouteKey) { + return routeConstMap.get(key)!.title; +} diff --git a/src/router/guide/index.ts b/src/router/guard/index.ts similarity index 100% rename from src/router/guide/index.ts rename to src/router/guard/index.ts diff --git a/src/router/guide/permission.ts b/src/router/guard/permission.ts similarity index 92% rename from src/router/guide/permission.ts rename to src/router/guard/permission.ts index 252de0a5..9f6a2ca2 100644 --- a/src/router/guide/permission.ts +++ b/src/router/guard/permission.ts @@ -1,5 +1,5 @@ import type { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'; -import { routeName } from '@/router'; +import { router, routeName } from '@/router'; import { getToken, getLoginRedirectUrl } from '@/utils'; type RouterAction = [boolean, () => void]; @@ -33,7 +33,7 @@ export function handlePagePermission( [ !isLogin && needLogin, () => { - const redirectUrl = getLoginRedirectUrl(); + const redirectUrl = getLoginRedirectUrl(router); next({ name: routeName('login'), query: { redirectUrl } }); } ], diff --git a/src/router/index.ts b/src/router/index.ts index f9b8362b..acc35ae8 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,3 +1,3 @@ -export * from './const'; +export * from './constant'; export * from './routes'; export * from './setup'; diff --git a/src/router/modules/about.ts b/src/router/modules/about.ts index 067933ff..ceb48ad0 100644 --- a/src/router/modules/about.ts +++ b/src/router/modules/about.ts @@ -1,21 +1,27 @@ import type { CustomRoute } from '@/interface'; -import { setRouterCacheName, setSingleRoute } from '@/utils'; +import { setSingleRoute } from '@/utils'; import { BasicLayout } from '@/layouts'; import About from '@/views/about/index.vue'; -import { getRouteConst } from '../const'; +import { getRouteConst, routeName } from '../constant'; const { name, path, title } = getRouteConst('about'); -setRouterCacheName(About, name); -const ABOUT: CustomRoute = setSingleRoute(BasicLayout, { - name, - path, - component: About, +const ABOUT: CustomRoute = setSingleRoute({ + route: { + name, + path, + component: About, + meta: { + requiresAuth: true, + title, + icon: 'fluent:book-information-24-regular' + } + }, + container: BasicLayout, meta: { - requiresAuth: true, - title, - icon: 'fluent:book-information-24-regular' - } + order: 7 + }, + notFoundName: routeName('not-found') }); export default ABOUT; diff --git a/src/router/modules/component.ts b/src/router/modules/component.ts index 5a75979c..cda3eef5 100644 --- a/src/router/modules/component.ts +++ b/src/router/modules/component.ts @@ -1,18 +1,11 @@ import type { CustomRoute } from '@/interface'; import { BasicLayout, RouterViewLayout } from '@/layouts'; -import { setRouterCacheName } from '@/utils'; import ComponentMap from '@/views/component/map/index.vue'; import ComponentVideo from '@/views/component/video/index.vue'; import EditorQuill from '@/views/component/editor/quill/index.vue'; import EditorMarkdown from '@/views/component/editor/markdown/index.vue'; import ComponentSwiper from '@/views/component/swiper/index.vue'; -import { routeName, routePath, routeTitle } from '../const'; - -setRouterCacheName(ComponentMap, routeName('component_map')); -setRouterCacheName(ComponentVideo, routeName('component_video')); -setRouterCacheName(EditorQuill, routeName('component_editor_quill')); -setRouterCacheName(EditorMarkdown, routeName('component_editor_markdown')); -setRouterCacheName(ComponentSwiper, routeName('component_swiper')); +import { routeName, routePath, routeTitle } from '../constant'; const COMPONENT: CustomRoute = { name: routeName('component'), @@ -22,7 +15,8 @@ const COMPONENT: CustomRoute = { meta: { requiresAuth: true, title: routeTitle('component'), - icon: 'fluent:app-store-24-regular' + icon: 'fluent:app-store-24-regular', + order: 3 }, children: [ { diff --git a/src/router/modules/dashboard.ts b/src/router/modules/dashboard.ts index 416d5512..4f537643 100644 --- a/src/router/modules/dashboard.ts +++ b/src/router/modules/dashboard.ts @@ -1,11 +1,8 @@ import type { CustomRoute } from '@/interface'; import { BasicLayout } from '@/layouts'; -import { setRouterCacheName } from '@/utils'; +import DashboardAnalysis from '@/views/dashboard/analysis/index.vue'; import DashboardWorkbench from '@/views/dashboard/workbench/index.vue'; -import { ROUTE_HOME } from '../routes'; -import { routeName, routePath, routeTitle } from '../const'; - -setRouterCacheName(DashboardWorkbench, routeName('dashboard_workbench')); +import { routeName, routePath, routeTitle } from '../constant'; const DASHBOARD: CustomRoute = { name: routeName('dashboard'), @@ -14,10 +11,20 @@ const DASHBOARD: CustomRoute = { redirect: { name: routeName('dashboard_analysis') }, meta: { title: routeTitle('dashboard'), - icon: 'carbon:dashboard' + icon: 'carbon:dashboard', + order: 1 }, children: [ - ROUTE_HOME, + { + name: routeName('dashboard_analysis'), + path: routePath('dashboard_analysis'), + component: DashboardAnalysis, + meta: { + keepAlive: true, + requiresAuth: true, + title: routeTitle('dashboard_analysis') + } + }, { name: routeName('dashboard_workbench'), path: routePath('dashboard_workbench'), diff --git a/src/router/modules/document.ts b/src/router/modules/document.ts index 994cf43c..4c652eb1 100644 --- a/src/router/modules/document.ts +++ b/src/router/modules/document.ts @@ -1,14 +1,9 @@ import type { CustomRoute } from '@/interface'; import { BasicLayout } from '@/layouts'; -import { setRouterCacheName } from '@/utils'; import DocumentVue from '@/views/document/vue/index.vue'; import DocumentVite from '@/views/document/vite/index.vue'; import DocumentNaive from '@/views/document/naive/index.vue'; -import { routeName, routePath, routeTitle } from '../const'; - -setRouterCacheName(DocumentVue, routeName('document_vue')); -setRouterCacheName(DocumentVite, routeName('document_vite')); -setRouterCacheName(DocumentNaive, routeName('document_naive')); +import { routeName, routePath, routeTitle } from '../constant'; const DOCUMENT: CustomRoute = { name: routeName('document'), @@ -18,7 +13,8 @@ const DOCUMENT: CustomRoute = { meta: { requiresAuth: true, title: routeTitle('document'), - icon: 'carbon:document' + icon: 'carbon:document', + order: 2 }, children: [ { diff --git a/src/router/modules/exception.ts b/src/router/modules/exception.ts index 9adb94da..2574e228 100644 --- a/src/router/modules/exception.ts +++ b/src/router/modules/exception.ts @@ -1,14 +1,9 @@ import type { CustomRoute } from '@/interface'; import { BasicLayout } from '@/layouts'; -import { setRouterCacheName } from '@/utils'; import Exception403 from '@/views/system/exception/403.vue'; import Exception404 from '@/views/system/exception/404.vue'; import Exception500 from '@/views/system/exception/500.vue'; -import { routeName, routePath, routeTitle } from '../const'; - -setRouterCacheName(Exception404, routeName('exception_404')); -setRouterCacheName(Exception403, routeName('exception_403')); -setRouterCacheName(Exception500, routeName('exception_500')); +import { routeName, routePath, routeTitle } from '../constant'; const EXCEPTION: CustomRoute = { name: routeName('exception'), @@ -18,7 +13,8 @@ const EXCEPTION: CustomRoute = { meta: { requiresAuth: true, title: routeTitle('exception'), - icon: 'ant-design:exception-outlined' + icon: 'ant-design:exception-outlined', + order: 5 }, children: [ { diff --git a/src/router/modules/feat.ts b/src/router/modules/feat.ts index 676e353c..3b5fc836 100644 --- a/src/router/modules/feat.ts +++ b/src/router/modules/feat.ts @@ -1,14 +1,9 @@ import type { CustomRoute } from '@/interface'; import { BasicLayout } from '@/layouts'; -import { setRouterCacheName } from '@/utils'; import FeatCopy from '@/views/feat/copy/index.vue'; import FeatIcon from '@/views/feat/icon/index.vue'; import FeatPrint from '@/views/feat/print/index.vue'; -import { routeName, routePath, routeTitle } from '../const'; - -setRouterCacheName(FeatCopy, routeName('feat_copy')); -setRouterCacheName(FeatIcon, routeName('feat_icon')); -setRouterCacheName(FeatPrint, routeName('feat_print')); +import { routeName, routePath, routeTitle } from '../constant'; const FEAT: CustomRoute = { name: routeName('feat'), @@ -18,7 +13,8 @@ const FEAT: CustomRoute = { meta: { requiresAuth: true, title: routeTitle('feat'), - icon: 'ic:round-repeat' + icon: 'ic:round-repeat', + order: 4 }, children: [ { diff --git a/src/router/modules/index.ts b/src/router/modules/index.ts index 3bcf8565..49b246eb 100644 --- a/src/router/modules/index.ts +++ b/src/router/modules/index.ts @@ -1,10 +1,8 @@ -import ROOT from './root'; -import DASHBOARD from './dashboard'; -import DOCUMENT from './document'; -import COMPONENT from './component'; -import FEAT from './feat'; -import EXCEPTION from './exception'; -import MULTI_MENU from './multi-menu'; -import ABOUT from './about'; +import { transformRouteModules } from '@/utils'; +import type { ImportedRouteModules } from '@/interface'; -export default [ROOT, DASHBOARD, DOCUMENT, COMPONENT, FEAT, EXCEPTION, MULTI_MENU, ABOUT]; +const modules = import.meta.globEager('./*.ts') as ImportedRouteModules; + +const customRoutes = transformRouteModules(modules); + +export default customRoutes; diff --git a/src/router/modules/multi-menu.ts b/src/router/modules/multi-menu.ts index ea18e816..86f6dfb6 100644 --- a/src/router/modules/multi-menu.ts +++ b/src/router/modules/multi-menu.ts @@ -1,10 +1,7 @@ import type { CustomRoute } from '@/interface'; import { BasicLayout, RouterViewLayout } from '@/layouts'; -import { setRouterCacheName } from '@/utils'; import MultiMenuFirstSecond from '@/views/multi-menu/first/second/index.vue'; -import { routeName, routePath, routeTitle } from '../const'; - -setRouterCacheName(MultiMenuFirstSecond, routeName('multi-menu_first_second')); +import { routeName, routePath, routeTitle } from '../constant'; const MULTI_MENU: CustomRoute = { name: routeName('multi-menu'), @@ -13,7 +10,8 @@ const MULTI_MENU: CustomRoute = { redirect: { name: routeName('multi-menu_first') }, meta: { title: routeTitle('multi-menu'), - icon: 'carbon:menu' + icon: 'carbon:menu', + order: 6 }, children: [ { diff --git a/src/router/modules/root.ts b/src/router/modules/root.ts deleted file mode 100644 index 6c5993c1..00000000 --- a/src/router/modules/root.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { CustomRoute } from '@/interface'; -import { routeName, routePath } from '../const'; -import { ROUTE_HOME } from '../routes'; - -const ROOT: CustomRoute = { - name: routeName('root'), - path: routePath('root'), - redirect: { name: ROUTE_HOME.name }, - meta: { - isNotMenu: true - } -}; - -export default ROOT; diff --git a/src/router/routes/constant.ts b/src/router/routes/constant-routes.ts similarity index 82% rename from src/router/routes/constant.ts rename to src/router/routes/constant-routes.ts index d2286e00..6df201e9 100644 --- a/src/router/routes/constant.ts +++ b/src/router/routes/constant-routes.ts @@ -5,7 +5,8 @@ import Login from '@/views/system/login/index.vue'; import NoPermission from '@/views/system/exception/403.vue'; import NotFound from '@/views/system/exception/404.vue'; import ServiceError from '@/views/system/exception/500.vue'; -import { routeName, routePath, routeTitle } from '../const'; +import { routeName, routePath, routeTitle } from '../constant'; +import { ROUTE_HOME_NAME } from './route-home'; /** * 固定不变的路由 @@ -13,8 +14,14 @@ import { routeName, routePath, routeTitle } from '../const'; */ const constantRoutes: RouteRecordRaw[] = [ { - name: 'single_', - path: '/single_', + name: routeName('root'), + path: routePath('root'), + redirect: { name: ROUTE_HOME_NAME } + }, + { + // 名称、路由随意,不在路由声明里面,只是为各个页面充当传递BlankLayout的桥梁,因此访问该路由时重定向到404 + name: 'constant-single_', + path: '/constant-single_', component: BlankLayout, redirect: { name: routeName('not-found') }, meta: { diff --git a/src/router/routes/index.ts b/src/router/routes/index.ts index b12c1e3a..c9bf8f63 100644 --- a/src/router/routes/index.ts +++ b/src/router/routes/index.ts @@ -1,9 +1,8 @@ import type { RouteRecordRaw } from 'vue-router'; -import ROUTE_HOME from './routeHome'; import customRoutes from '../modules'; -import constantRoutes from './constant'; +import constantRoutes from './constant-routes'; /** 所有路由 */ export const routes: RouteRecordRaw[] = [...customRoutes, ...constantRoutes]; -export { ROUTE_HOME, customRoutes }; +export { ROUTE_HOME } from './route-home'; diff --git a/src/router/routes/route-home.ts b/src/router/routes/route-home.ts new file mode 100644 index 00000000..de71fae6 --- /dev/null +++ b/src/router/routes/route-home.ts @@ -0,0 +1,9 @@ +import { getRouteHome } from '@/utils'; +import { routeName } from '../constant'; +import customRoutes from '../modules'; + +/** 路由首页的名字 */ +export const ROUTE_HOME_NAME = routeName('dashboard_analysis'); + +/** 路由首页 */ +export const ROUTE_HOME = getRouteHome(customRoutes, ROUTE_HOME_NAME); diff --git a/src/router/routes/routeHome.ts b/src/router/routes/routeHome.ts deleted file mode 100644 index 722fa047..00000000 --- a/src/router/routes/routeHome.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { CustomRoute } from '@/interface'; -import { setRouterCacheName } from '@/utils'; -import DashboardAnalysis from '@/views/dashboard/analysis/index.vue'; -import { getRouteConst } from '../const'; - -const { name, path, title } = getRouteConst('dashboard_analysis'); - -setRouterCacheName(DashboardAnalysis, name); - -/** 路由首页 */ -const ROUTE_HOME: CustomRoute = { - name, - path, - component: DashboardAnalysis, - meta: { - requiresAuth: true, - title - } -}; - -export default ROUTE_HOME; diff --git a/src/router/setup/cache.ts b/src/router/setup/cache.ts new file mode 100644 index 00000000..d47a5b0f --- /dev/null +++ b/src/router/setup/cache.ts @@ -0,0 +1,7 @@ +import { getCacheRoutes } from '@/utils'; +import { routes } from '../routes'; + +/** 缓存的路由对应vue页面的名称 */ +const cacheRoutes = getCacheRoutes(routes); + +export default cacheRoutes; diff --git a/src/router/setup/index.ts b/src/router/setup/index.ts index b17cb273..5d1e4855 100644 --- a/src/router/setup/index.ts +++ b/src/router/setup/index.ts @@ -1,8 +1,7 @@ import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'; import type { App } from 'vue'; -import { getCacheRoutes, transformRouteToMenu } from '@/utils'; -import { routes, customRoutes } from '../routes'; -import { createRouterGuide } from '../guide'; +import { routes } from '../routes'; +import { createRouterGuide } from '../guard'; /** 用于部署vercel托管服务 */ const isStaging = import.meta.env.VITE_HTTP_ENV === 'STAGING'; @@ -18,8 +17,5 @@ export async function setupRouter(app: App) { await router.isReady(); } -/** 缓存的路由对应vue页面的名称 */ -export const cacheRoutes = getCacheRoutes(routes); - -/** 菜单 */ -export const menus = transformRouteToMenu(customRoutes); +export { default as cacheRoutes } from './cache'; +export { default as menus } from './menus'; diff --git a/src/router/setup/menus.ts b/src/router/setup/menus.ts new file mode 100644 index 00000000..7815598e --- /dev/null +++ b/src/router/setup/menus.ts @@ -0,0 +1,7 @@ +import { transformRouteToMenu } from '@/utils'; +import customRoutes from '../modules'; + +/** 菜单 */ +const menus = transformRouteToMenu(customRoutes); + +export default menus; diff --git a/src/utils/router/cache.ts b/src/utils/router/cache.ts index 462b064c..e384018d 100644 --- a/src/utils/router/cache.ts +++ b/src/utils/router/cache.ts @@ -1,3 +1,4 @@ +import type { Component } from 'vue'; import type { RouteRecordRaw } from 'vue-router'; function getCacheName(route: RouteRecordRaw, isCache: boolean) { @@ -5,6 +6,7 @@ function getCacheName(route: RouteRecordRaw, isCache: boolean) { const hasChild = hasChildren(route); if (isCache && !hasChild) { const name = route.name as string; + setComponentName(route.component, name); cacheNames.push(name); } if (hasChild) { @@ -24,6 +26,13 @@ function hasChildren(route: RouteRecordRaw) { return Boolean(route.children && route.children.length); } +/** 给需要缓存的页面组件设置名称 */ +export function setComponentName(component?: Component, name?: string) { + if (component && name) { + Object.assign(component, { name }); + } +} + /** 获取被缓存的路由 */ export function getCacheRoutes(routes: RouteRecordRaw[]) { const cacheNames: string[] = []; diff --git a/src/utils/router/helpers.ts b/src/utils/router/helpers.ts index 4a5c4571..aa0338dc 100644 --- a/src/utils/router/helpers.ts +++ b/src/utils/router/helpers.ts @@ -1,34 +1,74 @@ import type { Component } from 'vue'; -import type { CustomRoute } from '@/interface'; -import { router } from '@/router'; +import type { Router } from 'vue-router'; +import type { CustomRoute, ImportedRouteModules, CustomRouteMeta } from '@/interface'; -/** 给需要缓存的页面组件设置名称 */ -export function setRouterCacheName(component: Component, name?: string) { - if (name) { - Object.assign(component, { name }); +/** 处理导入的路由模块 */ +export function transformRouteModules(routeModules: ImportedRouteModules) { + const modules = Object.keys(routeModules).map(key => { + return routeModules[key].default; + }); + const constantRoutes: CustomRoute[] = modules.sort((next, pre) => Number(next.meta.order) - Number(pre.meta.order)); + return constantRoutes; +} + +/** + * 获取路由的首页 + * @param routes - 路由 + * @param routeHomeName - 路由首页名称 + */ +export function getRouteHome(routes: CustomRoute[], routeHomeName: string) { + let routeHome: CustomRoute; + function hasChildren(route: CustomRoute) { + return Boolean(route.children && route.children.length); } + function getRouteHomeByRoute(route: CustomRoute) { + if (routeHome) return; + const hasChild = hasChildren(route); + if (!hasChild) { + if (route.name === routeHomeName) { + routeHome = route; + } + } else { + getRouteHomeByRoutes(route.children as CustomRoute[]); + } + } + function getRouteHomeByRoutes(_routes: CustomRoute[]) { + _routes.some(item => { + getRouteHomeByRoute(item as CustomRoute); + return routeHome !== undefined; + }); + } + getRouteHomeByRoutes(routes); + return routeHome!; } /** 获取登录后的重定向地址 */ -export function getLoginRedirectUrl() { +export function getLoginRedirectUrl(router: Router) { const path = router.currentRoute.value.fullPath as string; const redirectUrl = path === '/' ? undefined : path; return redirectUrl; } -/** - * 设置单个路由 - * @param route - 路由 - * @param notFoundName - 404未找到的路由名称 - * @param container - 路由容器 - */ -export function setSingleRoute(container: Component, route: CustomRoute, notFoundName = 'not-found') { +interface SingleRouteConfig { + /** 路由 */ + route: CustomRoute; + /** 路由容器 */ + container: Component; + /** 路由容器的描述 */ + meta: CustomRouteMeta; + /** 404路由的名称 */ + notFoundName: string; +} +/** * 设置单个路由 */ +export function setSingleRoute(config: SingleRouteConfig) { + const { route, container, meta, notFoundName } = config; const routeItem: CustomRoute = { name: `${route.name as string}_`, path: `${route.path}_`, component: container, redirect: { name: notFoundName }, meta: { + ...meta, isNotMenu: true }, children: [route] diff --git a/src/utils/router/menus.ts b/src/utils/router/menus.ts index d9149d28..cedd3b0d 100644 --- a/src/utils/router/menus.ts +++ b/src/utils/router/menus.ts @@ -1,5 +1,5 @@ import type { CustomRoute, GlobalMenuOption } from '@/interface'; -import { iconifyRender } from '@/utils'; +import { iconifyRender } from '../common'; /** 判断路由是否作为菜单 */ function asMenu(route: CustomRoute) {