Files
urbanLifeline/urbanLifelineWeb/temp/routeAdapter.ts

262 lines
8.7 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 { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
import { getDeviceType, DeviceType } from './deviceUtils';
/**
* 路由适配器接口
*/
export interface RouteAdapter {
original: () => Promise<any>; // web桌面端
mobile?: () => Promise<any>; // h5移动端
}
/**
* 移动端路由映射表
*/
export const MOBILE_ROUTES_MAP: Record<string, string> = {
// 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<string, Record<DeviceType, string>> = {
'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<any> {
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<any> {
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<any>) | 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);
};
}