// ========================================================================= // // 全局变量 // // ========================================================================= // /** @type {number | null} 全局自动刷新定时器ID */ let autoRefreshInterval = null; /** @type {StatusGrid | null} API状态分布网格的实例 */ let apiCanvasInstance = null; /** @type {import('chart.js').Chart | null} 全局历史趋势图表实例 */ let historicalChartInstance = null; // 预热关键数据 document.addEventListener('DOMContentLoaded', function() { apiFetch('/admin/dashboard/overview'); apiFetch('/admin/keygroups'); // ... dashboard页面的其他初始化代码 ... }); // ========================================================================= // // 主程序入口 // // ========================================================================= // // 脚本位于
末尾,无需等待DOMContentLoaded,立即执行主程序。 main(); /** * 主执行函数,负责编排核心UI渲染和非核心模块的异步加载。 * [语法修正] 此函数必须是 async,以允许在其中使用 await。 */ async function main() { // 阶段一:立即初始化并渲染所有核心UI initializeStaticFeatures(); await hydrateCoreUIFromPrefetchedData(); // 等待核心UI所需数据加载并渲染完成 // (图表模块),并与之分离 // 这个函数调用本身是同步的,但它内部会启动一个不会阻塞主流程的异步加载过程。 loadChartModulesAndRender(); } // ========================================================================= // // 核心UI功能 // // ========================================================================= // /** * 负责初始化所有静态的、非数据驱动的UI功能。 */ function initializeStaticFeatures() { setupCoreEventListeners(); // [名称修正] 只监听核心UI相关的事件 initializeDropdownMenu(); initializeAutoRefreshControls(); initStatItemAnimations(); } /** * 核心数据“水合”函数。 * 它的使命是使用由 base.html 中的“信使”脚本预取的数据,尽快填充核心UI。 */ async function hydrateCoreUIFromPrefetchedData() { // 初始化Canvas网格实例 if (document.getElementById('poolGridCanvas')) { apiCanvasInstance = new StatusGrid('poolGridCanvas'); apiCanvasInstance.init(); } // 从缓存中等待并获取“概览”数据,然后更新统计卡片 try { const overviewResponse = await apiFetch('/admin/dashboard/overview'); const overviewData = await overviewResponse.json(); updateStatCards(overviewData); } catch (error) { if (error.message !== 'Unauthorized') { console.error('Failed to hydrate overview data:', error); showNotification('渲染总览数据失败。', 'error'); } } // 从缓存中等待并获取“分组”数据,然后填充下拉菜单 try { const keygroupsResponse = await apiFetch('/admin/keygroups'); const keygroupsData = await keygroupsResponse.json(); populateSelectWithOptions(keygroupsData); } catch (error) { if (error.message !== 'Unauthorized') { console.error('Failed to hydrate keygroups data:', error); } } } // ========================================================================= // // 二级火箭:图表模块功能 // // ========================================================================= // /** * 动态加载Chart.js引擎,并在加载成功后,启动图表的渲染流程。 * 这个过程是完全异步的,不会阻塞页面其它部分的交互。 */ function loadChartModulesAndRender() { // 辅助函数:通过动态创建