zhou zhou
昨天 5d31cb5f1fb32a478d5b751ebfe97d47db890778
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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 }