PageSourceSearch

https://hhdcz04-python2.hf.space/app/app.js

js hhdcz04-python2.hf.space collected 2026-10-03 16:55:51 UTC 8,747 bytes, 303 lines download raw bytes

1// 主应用入口文件 - 模块化版本
2
3// 导入所有模块
4import {
5    providerStats,
6    REFRESH_INTERVALS
7} from './constants.js';
8
9import {
10    showToast,
11    getProviderStats
12} from './utils.js';
13
14import { t } from './i18n.js';
15
16import {
17    initFileUpload,
18    fileUploadHandler
19} from './file-upload.js';
20
21import { 
22    initNavigation,
23    setSectionLoaders
24} from './navigation.js';
25
26import {
27    initEventListeners,
28    setDataLoaders,
29    setReloadConfig
30} from './event-handlers.js';
31
32import {
33    initEventStream,
34    setProviderLoaders,
35    setConfigLoaders
36} from './event-stream.js';
37
38import {
39    loadSystemInfo,
40    updateTimeDisplay,
41    loadProviders,
42    loadProvidersPageData,
43    openProviderManager,
44    showAuthModal,
45    executeGenerateAuthUrl,
46    handleGenerateAuthUrl,
47    showAddProviderGroupModal
48} from './provider-manager.js';
49
50import {
51    loadConfiguration,
52    saveConfiguration,
53    generateApiKey
54} from './config-manager.js';
55
56import {
57    showProviderManagerModal,
58    refreshProviderConfig
59} from './modal.js';
60
61import {
62    initRoutingExamples
63} from './routing-examples.js';
64
65import {
66    initAccessManager,
67    loadAccessInfo
68} from './access-manager.js';
69
70import {
71    initUploadConfigManager,
72    loadConfigList,
73    viewConfig,
74    deleteConfig,
75    closeConfigModal,
76    copyConfigContent,
77    reloadConfig
78} from './upload-config-manager.js';
79
80import {
81    initUsageManager,
82    loadUsagePageData,
83    refreshUsage
84} from './usage-manager.js';
85
86import {
87    initImageZoom
88} from './image-zoom.js';
89
90import {
91    initPluginManager,
92    loadPlugins,
93    togglePlugin
94} from './plugin-manager.js';
95
96import {
97    initTutorialManager
98} from './tutorial-manager.js';
99
100import {
101    CustomModelsManager
102} from './custom-models-manager.js';
103
104import {
105    initPlaygroundManager,
106    loadPlaygroundData
107} from './playground-manager.js';
108
109let isAppInitialized = false;
110
111/**
112 * 加载初始数据
113 */
114async function loadInitialData() {
115    await Promise.all([
116        loadSystemInfo(),
117        loadProviders()
118    ]);
119}
120
121/**
122 * 初始化应用
123 */
124async function initApp() {
125    if (isAppInitialized) {
126        return;
127    }
128    isAppInitialized = true;
129
130    // 设置数据加载器
131    setDataLoaders(loadInitialData, saveConfiguration);
132    
133    // 设置reloadConfig函数
134    setReloadConfig(reloadConfig);
135    
136    // 设置提供商加载器
137    setProviderLoaders(loadProviders, refreshProviderConfig);
138    
139    // 设置配置加载器
140    setConfigLoaders(loadConfigList);
141
142    setSectionLoaders({
143        access: loadAccessInfo,
144        config: loadConfiguration,
145        providers: loadProvidersPageData,
146        'custom-models': () => window.customModelsManager?.load(),
147        'upload-config': loadConfigList,
148        usage: loadUsagePageData,
149        plugins: loadPlugins,
150        playground: loadPlaygroundData
151    });
152    
153    // 导出全局函数供其他模块使用
154    window.loadProviders = loadProviders;
155    window.openProviderManager = openProviderManager;
156    window.showProviderManagerModal = showProviderManagerModal;
157    window.refreshProviderConfig = refreshProviderConfig;
158    window.fileUploadHandler = fileUploadHandler;
159    window.showAuthModal = showAuthModal;
160    window.executeGenerateAuthUrl = executeGenerateAuthUrl;
161    window.handleGenerateAuthUrl = handleGenerateAuthUrl;
162    window.showAddProviderGroupModal = showAddProviderGroupModal;
163
164    // 配置管理相关全局函数
165    window.viewConfig = viewConfig;
166    window.deleteConfig = deleteConfig;
167    window.loadConfigList = loadConfigList;
168    window.closeConfigModal = closeConfigModal;
169    window.copyConfigContent = copyConfigContent;
170    window.reloadConfig = reloadConfig;
171    window.generateApiKey = generateApiKey;
172    window.loadAccessInfo = loadAccessInfo;
173
174    // 用量管理相关全局函数
175    window.refreshUsage = refreshUsage;
176
177    // 插件管理相关全局函数
178    window.togglePlugin = togglePlugin;
179
180    // 初始化自定义模型管理
181    window.customModelsManager = new CustomModelsManager();
182
183    // 初始化各个模块
184    initEventListeners();
185    initEventStream();
186    initFileUpload(); // 初始化文件上传功能
187    initAccessManager(); // 初始化快速接入页面
188    initUploadConfigManager(); // 初始化配置管理功能
189    initUsageManager(); // 初始化用量管理功能
190    initImageZoom(); // 初始化图片放大功能
191    initPluginManager(); // 初始化插件管理功能
192    initTutorialManager(); // 初始化教程管理功能
193    initPlaygroundManager(); // 初始化 Playground
194    initMobileMenu(); // 初始化移动端菜单
195    
196    // 加载初始数据 (确保在导航初始化前加载,因为导航可能触发页面数据加载)
197    await loadInitialData();
198    
199    // 初始化导航功能,触发初始页面的激活
200    initNavigation();
201    
202    // 显示欢迎消息
203    showToast(t('common.success'), t('common.welcome'), 'success');
204    
205    // 每5秒更新服务器时间和运行时间显示
206    setInterval(() => {
207        updateTimeDisplay();
208    }, 5000);
209    
210    // 定期刷新系统信息
211    setInterval(() => {
212        loadProviders();
213
214        if (providerStats.activeProviders > 0) {
215            const stats = getProviderStats(providerStats);
216            console.log('=== 提供商统计报告 ===');
217            console.log(`活跃提供商: ${stats.activeProviders}`);
218            console.log(`健康提供商: ${stats.healthyProviders} (${stats.healthRatio})`);
219            console.log(`总账户数: ${stats.totalAccounts}`);
220            console.log(`总请求数: ${stats.totalRequests}`);
221            console.log(`总错误数: ${stats.totalErrors}`);
222            console.log(`成功率: ${stats.successRate}`);
223            console.log(`平均每提供商请求数: ${stats.avgUsagePerProvider}`);
224            console.log('========================');
225        }
226    }, REFRESH_INTERVALS.SYSTEM_INFO);
227
228}
229
230/**
231 * 初始化移动端菜单
232 */
233function initMobileMenu() {
234    const mobileMenuToggle = document.getElementById('mobileMenuToggle');
235    const headerControls = document.getElementById('headerControls');
236    
237    if (!mobileMenuToggle || !headerControls) {
238        console.log('Mobile menu elements not found');
239        return;
240    }
241    
242    // 默认隐藏header-controls
243    headerControls.style.display = 'none';
244    
245    let isMenuOpen = false;
246    
247    mobileMenuToggle.addEventListener('click', (e) => {
248        e.preventDefault();
249        e.stopPropagation();
250        
251        console.log('Mobile menu toggle clicked, current state:', isMenuOpen);
252        
253        isMenuOpen = !isMenuOpen;
254        
255        if (isMenuOpen) {
256            headerControls.style.display = 'flex';
257            mobileMenuToggle.innerHTML = '<i class="fas fa-times"></i>';
258            console.log('Menu opened');
259        } else {
260            headerControls.style.display = 'none';
261            mobileMenuToggle.innerHTML = '<i class="fas fa-bars"></i>';
262            console.log('Menu closed');
263        }
264    });
265    
266    // 点击页面其他地方关闭菜单
267    document.addEventListener('click', (e) => {
268        if (isMenuOpen && !mobileMenuToggle.contains(e.target) && !headerControls.contains(e.target)) {
269            isMenuOpen = false;
270            headerControls.style.display = 'none';
271            mobileMenuToggle.innerHTML = '<i class="fas fa-bars"></i>';
272            console.log('Menu closed by clicking outside');
273        }
274    });
275}
276
277// 等待组件加载完成后初始化应用
278// 组件加载器会在所有组件加载完成后触发 'componentsLoaded' 事件
279window.addEventListener('componentsLoaded', initApp);
280
281// 如果组件已经加载完成(例如页面刷新后),也需要初始化
282// 检查是否有组件已经存在
283document.addEventListener('DOMContentLoaded', () => {
284    // 如果 sidebar 和 content 已经有内容,说明组件已加载
285    const sidebarContainer = document.getElementById('sidebar-container');
286    const contentContainer = document.getElementById('content-container');
287    
288    // 如果容器不存在或为空,说明使用的是组件加载方式,等待 componentsLoaded 事件
289    // 如果容器已有内容,说明是静态 HTML,直接初始化
290    if (sidebarContainer && contentContainer) {
291        const hasContent = sidebarContainer.children.length > 0 || contentContainer.children.length > 0;
292        if (hasContent) {
293            // 静态 HTML 方式,直接初始化
294            initApp();
295        }
296        // 否则等待 componentsLoaded 事件
297    }
298});
299
300// 导出调试函数
301window.getProviderStats = () => getProviderStats(providerStats);
302
303console.log('AIClient2API 管理控制台已加载 - 模块化版本');

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.