import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router'; import { getDeviceType, DeviceType } from './deviceUtils'; /** * 路由适配器接口 */ export interface RouteAdapter { original: () => Promise; // web桌面端 mobile?: () => Promise; // h5移动端 } /** * 移动端路由映射表 */ export const MOBILE_ROUTES_MAP: Record = { // User Views '/home': '@/views/user/home/HomeView.mobile.vue', '/resource-center': '@/views/user/resource-center/ResourceCenterView.mobile.vue', '/resource-hot': '@/views/user/resource-center/HotResourceView.mobile.vue', '/search': '@/views/user/resource-center/SearchView.mobile.vue', '/course-center': '@/views/user/study-plan/CourseCenterView.mobile.vue', '/course-detail': '@/views/user/study-plan/CourseDetailView.mobile.vue', '/course-study': '@/views/user/study-plan/CourseStudyView.mobile.vue', '/study-tasks': '@/views/user/study-plan/StudyTasksView.mobile.vue', '/learning-task-detail': '@/views/user/study-plan/LearningTaskDetailView.mobile.vue', '/user-center': '@/views/user/user-center/UserCenterLayout.mobile.vue', '/personal-info': '@/views/user/user-center/profile/PersonalInfoView.mobile.vue', '/account-settings': '@/views/user/user-center/profile/AccountSettingsView.mobile.vue', '/my-achievements': '@/views/user/user-center/MyAchievementsView.mobile.vue', '/my-favorites': '@/views/user/user-center/MyFavoritesView.mobile.vue', '/learning-records': '@/views/user/user-center/LearningRecordsView.mobile.vue', '/my-messages': '@/views/user/message/MyMessageListView.mobile.vue', '/message-detail': '@/views/user/message/MyMessageDetailView.mobile.vue', // Public Views '/login': '@/views/public/login/Login.mobile.vue', '/register': '@/views/public/login/Register.mobile.vue', '/forgot-password': '@/views/public/login/ForgotPassword.mobile.vue', '/article-show': '@/views/public/article/ArticleShowView.mobile.vue', '/article-add': '@/views/public/article/ArticleAddView.mobile.vue' }; /** * Layout映射表 */ export const LAYOUT_MAP: Record> = { 'NavigationLayout': { [DeviceType.MOBILE]: '@/layouts/MobileLayout.vue', // h5移动端 [DeviceType.DESKTOP]: '@/layouts/NavigationLayout.vue' // web桌面端 }, 'SidebarLayout': { [DeviceType.MOBILE]: '@/layouts/MobileLayout.vue', // h5移动端 [DeviceType.DESKTOP]: '@/layouts/SidebarLayout.vue' // web桌面端 }, 'BasicLayout': { [DeviceType.MOBILE]: '@/layouts/MobileLayout.vue', // h5移动端 [DeviceType.DESKTOP]: '@/layouts/BasicLayout.vue' // web桌面端 }, 'BlankLayout': { [DeviceType.MOBILE]: '@/layouts/BlankLayout.vue', // h5移动端 [DeviceType.DESKTOP]: '@/layouts/BlankLayout.vue' // web桌面端 }, 'PageLayout': { [DeviceType.MOBILE]: '@/layouts/MobileLayout.vue', // h5移动端 [DeviceType.DESKTOP]: '@/layouts/PageLayout.vue' // web桌面端 } }; /** * 创建响应式路由组件 */ export function createResponsiveRoute(adapter: RouteAdapter): () => Promise { return async () => { const deviceType = getDeviceType(); try { // 尝试加载设备特定的组件 if (deviceType === DeviceType.MOBILE && adapter.mobile) { return await adapter.mobile(); } } catch (error) { console.warn(`Failed to load device-specific component for ${deviceType}, falling back to original:`, error); } // 回退到原始组件(桌面端/web) return await adapter.original(); }; } /** * 获取响应式Layout组件 */ export function getResponsiveLayout(layoutName: string): () => Promise { const deviceType = getDeviceType(); const layoutMap = LAYOUT_MAP[layoutName]; if (!layoutMap) { console.warn(`Unknown layout: ${layoutName}, using original`); // 使用具体的导入路径 switch (layoutName) { case 'BlankLayout': return () => import('@/layouts/BlankLayout.vue'); case 'NavigationLayout': return () => import('@/layouts/NavigationLayout.vue'); case 'SidebarLayout': return () => import('@/layouts/SidebarLayout.vue'); case 'BasicLayout': return () => import('@/layouts/BasicLayout.vue'); case 'PageLayout': return () => import('@/layouts/PageLayout.vue'); default: throw new Error(`Unknown layout: ${layoutName}`); } } const targetLayout = layoutMap[deviceType]; return async () => { try { // 使用具体的导入路径而不是动态路径 switch (targetLayout) { case '@/layouts/BlankLayout.vue': return await import('@/layouts/BlankLayout.vue'); case '@/layouts/NavigationLayout.vue': return await import('@/layouts/NavigationLayout.vue'); case '@/layouts/SidebarLayout.vue': return await import('@/layouts/SidebarLayout.vue'); case '@/layouts/BasicLayout.vue': return await import('@/layouts/BasicLayout.vue'); case '@/layouts/MobileLayout.vue': return await import('@/layouts/MobileLayout.vue'); case '@/layouts/PageLayout.vue': return await import('@/layouts/PageLayout.vue'); default: throw new Error(`Unknown layout path: ${targetLayout}`); } } catch (error) { console.warn(`Failed to load responsive layout ${targetLayout}, falling back to original:`, error); // 回退到原始layout switch (layoutName) { case 'BlankLayout': return await import('@/layouts/BlankLayout.vue'); case 'NavigationLayout': return await import('@/layouts/NavigationLayout.vue'); case 'SidebarLayout': return await import('@/layouts/SidebarLayout.vue'); case 'BasicLayout': return await import('@/layouts/BasicLayout.vue'); case 'PageLayout': return await import('@/layouts/PageLayout.vue'); default: throw new Error(`Unknown layout: ${layoutName}`); } } }; } /** * 创建自适应路由配置 */ export function createAdaptiveRoute( path: string, originalComponent: string, layoutName?: string, meta?: any ): RouteRecordRaw { // 创建具体的导入函数而不是使用动态路径 const getOriginalComponent = () => { switch (originalComponent) { case '@/views/public/login/Login.vue': return import('@/views/public/login/Login.vue'); case '@/views/public/login/Register.vue': return import('@/views/public/login/Register.vue'); case '@/views/public/login/ForgotPassword.vue': return import('@/views/public/login/ForgotPassword.vue'); default: throw new Error(`Unknown component: ${originalComponent}`); } }; const getMobileComponent = (): (() => Promise) | null => { const mobilePath = MOBILE_ROUTES_MAP[path]; if (!mobilePath) return null; switch (mobilePath) { case '@/views/public/login/Login.mobile.vue': return () => import('@/views/public/login/Login.mobile.vue'); case '@/views/public/login/Register.mobile.vue': return () => import('@/views/public/login/Register.mobile.vue'); case '@/views/public/login/ForgotPassword.mobile.vue': return () => import('@/views/public/login/ForgotPassword.mobile.vue'); default: return null; } }; const adapter: RouteAdapter = { original: getOriginalComponent }; // 检查是否有移动端版本 const mobileImportFunction = getMobileComponent(); if (mobileImportFunction) { adapter.mobile = mobileImportFunction; } // 如果指定了Layout,应用响应式Layout if (layoutName) { const route: RouteRecordRaw = { path, component: getResponsiveLayout(layoutName), children: [ { path: '', component: createResponsiveRoute(adapter), meta } ], meta }; return route; } const route: RouteRecordRaw = { path, component: createResponsiveRoute(adapter), meta }; return route; } /** * 监听屏幕尺寸变化,重新加载路由 */ export function setupRouteWatcher(router: any) { let currentDeviceType = getDeviceType(); const handleResize = () => { const newDeviceType = getDeviceType(); if (newDeviceType !== currentDeviceType) { currentDeviceType = newDeviceType; // 重新加载当前路由以应用新的组件 const currentRoute = router.currentRoute.value; router.replace({ ...currentRoute, query: { ...currentRoute.query, _refresh: Date.now() // 强制重新加载 } }); } }; window.addEventListener('resize', handleResize); // 返回清理函数 return () => { window.removeEventListener('resize', handleResize); }; }