File size: 5,346 Bytes
ceb3821
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
 * 组件加载器 - 用于动态加载 HTML 组件片段
 * Component Loader - For dynamically loading HTML component fragments
 */

// 组件缓存
const componentCache = new Map();

/**
 * 加载单个组件
 * @param {string} componentPath - 组件文件路径
 * @returns {Promise<string>} - 组件 HTML 内容
 */
async function loadComponent(componentPath) {
    // 检查缓存
    if (componentCache.has(componentPath)) {
        return componentCache.get(componentPath);
    }

    try {
        const response = await fetch(componentPath);
        if (!response.ok) {
            throw new Error(`Failed to load component: ${componentPath} (${response.status})`);
        }
        const html = await response.text();
        // 缓存组件
        componentCache.set(componentPath, html);
        return html;
    } catch (error) {
        console.error(`Error loading component ${componentPath}:`, error);
        throw error;
    }
}

/**
 * 将组件插入到指定容器
 * @param {string} componentPath - 组件文件路径
 * @param {string|HTMLElement} container - 容器选择器或元素
 * @param {string} position - 插入位置: 'replace', 'append', 'prepend', 'beforeend', 'afterbegin'
 * @returns {Promise<void>}
 */
async function insertComponent(componentPath, container, position = 'beforeend') {
    const html = await loadComponent(componentPath);
    
    const containerElement = typeof container === 'string' 
        ? document.querySelector(container) 
        : container;
    
    if (!containerElement) {
        throw new Error(`Container not found: ${container}`);
    }

    if (position === 'replace') {
        containerElement.innerHTML = html;
    } else {
        containerElement.insertAdjacentHTML(position, html);
    }
}

/**
 * 批量加载多个组件
 * @param {Array<{path: string, container: string, position?: string}>} components - 组件配置数组
 * @returns {Promise<void>}
 */
async function loadComponents(components) {
    const promises = components.map(({ path, container, position }) => 
        insertComponent(path, container, position)
    );
    await Promise.all(promises);
}

/**
 * 初始化页面组件
 * 加载所有页面组件并插入到相应位置
 * @returns {Promise<void>}
 */
async function initializeComponents() {
    const basePath = 'components/';
    
    // 定义组件配置
    const componentConfigs = [
        { path: `${basePath}header.html`, container: '.container', position: 'afterbegin' },
        { path: `${basePath}sidebar.html`, container: '#sidebar-container', position: 'replace' },
        { path: `${basePath}section-dashboard.html`, container: '#content-container', position: 'beforeend' },
        { path: `${basePath}section-config.html`, container: '#content-container', position: 'beforeend' },
        { path: `${basePath}section-upload-config.html`, container: '#content-container', position: 'beforeend' },
        { path: `${basePath}section-providers.html`, container: '#content-container', position: 'beforeend' },
        { path: `${basePath}section-usage.html`, container: '#content-container', position: 'beforeend' },
        { path: `${basePath}section-logs.html`, container: '#content-container', position: 'beforeend' },
        { path: `${basePath}section-plugins.html`, container: '#content-container', position: 'beforeend' },
    ];

    try {
        // 首先加载 header
        await insertComponent(`${basePath}header.html`, '.container', 'afterbegin');
        
        // 然后加载 sidebar
        await insertComponent(`${basePath}sidebar.html`, '#sidebar-container', 'replace');
        
        // 最后加载所有 section 组件
        const sectionComponents = [
            { path: `${basePath}section-dashboard.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-guide.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-tutorial.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-config.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-upload-config.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-providers.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-usage.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-logs.html`, container: '#content-container', position: 'beforeend' },
            { path: `${basePath}section-plugins.html`, container: '#content-container', position: 'beforeend' },
        ];
        
        await loadComponents(sectionComponents);
        
        console.log('All components loaded successfully');
        // 触发组件加载完成事件
        window.dispatchEvent(new CustomEvent('componentsLoaded'));
        
    } catch (error) {
        console.error('Failed to initialize components:', error);
        throw error;
    }
}

/**
 * 清除组件缓存
 */
function clearComponentCache() {
    componentCache.clear();
}

// 导出函数
export {
    loadComponent,
    insertComponent,
    loadComponents,
    initializeComponents,
    clearComponentCache
};