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.