import { h } from 'vue' class ComponentLoader { constructor() { this.modules = import.meta.glob('../../views/**/*.vue') this.warmPromises = new Map() } resolveModule(componentPath) { if (!componentPath) { return null } const fullPath = `../../views${componentPath}.vue` const fullPathWithIndex = `../../views${componentPath}/index.vue` return this.modules[fullPath] || this.modules[fullPathWithIndex] || null } /** * 加载组件 */ load(componentPath) { if (!componentPath) { return this.createEmptyComponent() } const module = this.resolveModule(componentPath) if (!module) { const fullPath = `../../views${componentPath}.vue` const fullPathWithIndex = `../../views${componentPath}/index.vue` console.error( `[ComponentLoader] 未找到组件: ${componentPath},尝试过的路径: ${fullPath} 和 ${fullPathWithIndex}` ) return this.createErrorComponent(componentPath) } return module } /** * 预热组件模块,避免首次点击页面时再触发冷加载。 */ warm(componentPath) { const normalizedPath = typeof componentPath === 'string' ? componentPath.trim() : '' if (!normalizedPath) { return Promise.resolve(false) } if (this.warmPromises.has(normalizedPath)) { return this.warmPromises.get(normalizedPath) } const module = this.resolveModule(normalizedPath) if (!module) { return Promise.resolve(false) } const warmTask = module() .then(() => true) .catch((error) => { console.warn(`[ComponentLoader] 组件预热失败: ${normalizedPath}`, error) return false }) this.warmPromises.set(normalizedPath, warmTask) return warmTask } /** * 加载布局组件 */ loadLayout() { return () => import('@/views/index/index.vue') } /** * 加载 iframe 组件 */ loadIframe() { return () => import('@/views/outside/Iframe.vue') } /** * 创建空组件 */ createEmptyComponent() { return () => Promise.resolve({ render() { return h('div', {}) } }) } /** * 创建错误提示组件 */ createErrorComponent(componentPath) { return () => Promise.resolve({ render() { return h('div', { class: 'route-error' }, `组件未找到: ${componentPath}`) } }) } } export { ComponentLoader }