From 65cb5beec4cc472bbf4c27a907c238b2b5aeceec Mon Sep 17 00:00:00 2001 From: catlog22 Date: Mon, 12 Jan 2026 21:57:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E7=AE=A1=E7=90=86=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BB=8E=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E8=AF=BB=E5=8F=96=20CLI=20=E7=8A=B6=E6=80=81=E5=92=8C?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard-js/components/cli-status.js | 101 ++++++++++++++---- ccw/src/templates/dashboard-js/main.js | 18 +++- .../dashboard-js/views/codexlens-manager.js | 17 ++- 3 files changed, 107 insertions(+), 29 deletions(-) diff --git a/ccw/src/templates/dashboard-js/components/cli-status.js b/ccw/src/templates/dashboard-js/components/cli-status.js index 1c7e032f..549db6ee 100644 --- a/ccw/src/templates/dashboard-js/components/cli-status.js +++ b/ccw/src/templates/dashboard-js/components/cli-status.js @@ -78,14 +78,31 @@ async function loadAllStatusesFallback() { /** * Legacy: Load CLI tool status individually + * 优先从缓存读取,如果缓存有效则直接使用 */ async function loadCliToolStatus() { + // 尝试从缓存获取 + if (window.cacheManager) { + const cached = window.cacheManager.get('cli-status'); + if (cached) { + cliToolStatus = cached; + updateCliBadge(); + console.log('[CLI Status] Loaded from cache'); + return cached; + } + } + try { const response = await fetch('/api/cli/status'); if (!response.ok) throw new Error('Failed to load CLI status'); const data = await response.json(); cliToolStatus = data; + // 存入缓存 + if (window.cacheManager) { + window.cacheManager.set('cli-status', data, 300000); // 5分钟 + } + // Update badge updateCliBadge(); @@ -135,36 +152,31 @@ async function loadCodexLensStatus() { /** * Load CodexLens dashboard data using aggregated endpoint (single API call) * This is optimized for the CodexLens Manager page initialization + * 优先从缓存读取,如果缓存有效则直接使用 * @returns {Promise} Dashboard init data or null on error */ async function loadCodexLensDashboardInit() { + // 尝试从缓存获取 + if (window.cacheManager) { + const cached = window.cacheManager.get('dashboard-init'); + if (cached) { + applyDashboardInitData(cached); + console.log('[CLI Status] CodexLens dashboard init loaded from cache'); + return cached; + } + } + try { const response = await fetch('/api/codexlens/dashboard-init'); if (!response.ok) throw new Error('Failed to load CodexLens dashboard init'); const data = await response.json(); - // Update status variables from aggregated response - codexLensStatus = data.status || { ready: false }; - semanticStatus = data.semantic || { available: false }; + applyDashboardInitData(data); - // Expose to window for other modules - if (!window.cliToolsStatus) { - window.cliToolsStatus = {}; + // 存入缓存 + if (window.cacheManager) { + window.cacheManager.set('dashboard-init', data, 300000); // 5分钟 } - window.cliToolsStatus.codexlens = { - installed: data.installed || false, - version: data.status?.version || null, - installedModels: [], - config: data.config || {}, - semantic: data.semantic || {} - }; - - // Store config globally for easy access - window.codexLensConfig = data.config || {}; - window.codexLensStatusData = data.statusData || {}; - - // Update badges - updateCodexLensBadge(); console.log('[CLI Status] CodexLens dashboard init loaded:', { installed: data.installed, @@ -180,6 +192,35 @@ async function loadCodexLensDashboardInit() { } } +/** + * 应用 dashboard-init 数据到状态变量 + * @param {object} data - dashboard init 响应数据 + */ +function applyDashboardInitData(data) { + // Update status variables from aggregated response + codexLensStatus = data.status || { ready: false }; + semanticStatus = data.semantic || { available: false }; + + // Expose to window for other modules + if (!window.cliToolsStatus) { + window.cliToolsStatus = {}; + } + window.cliToolsStatus.codexlens = { + installed: data.installed || false, + version: data.status?.version || null, + installedModels: [], + config: data.config || {}, + semantic: data.semantic || {} + }; + + // Store config globally for easy access + window.codexLensConfig = data.config || {}; + window.codexLensStatusData = data.statusData || {}; + + // Update badges + updateCodexLensBadge(); +} + /** * Legacy: Load semantic status individually */ @@ -229,8 +270,23 @@ async function loadInstalledModels() { /** * Load CLI tools config from .claude/cli-tools.json (project or global fallback) + * 优先从缓存读取,如果缓存有效则直接使用 */ async function loadCliToolsConfig() { + // 尝试从缓存获取 + if (window.cacheManager) { + const cached = window.cacheManager.get('cli-tools-config'); + if (cached) { + cliToolsConfig = cached.tools?.tools || {}; + window.claudeCliToolsConfig = cached; + if (cached.defaultTool) { + defaultCliTool = cached.defaultTool; + } + console.log('[CLI Tools Config] Loaded from cache'); + return cached; + } + } + try { const response = await fetch('/api/cli/tools-config'); if (!response.ok) return null; @@ -244,6 +300,11 @@ async function loadCliToolsConfig() { defaultCliTool = data.defaultTool; } + // 存入缓存 + if (window.cacheManager) { + window.cacheManager.set('cli-tools-config', data, 300000); // 5分钟 + } + console.log('[CLI Config] Loaded from:', data._configInfo?.source || 'unknown', '| Default:', data.defaultTool); return data; } catch (err) { diff --git a/ccw/src/templates/dashboard-js/main.js b/ccw/src/templates/dashboard-js/main.js index cbe6c478..b830714a 100644 --- a/ccw/src/templates/dashboard-js/main.js +++ b/ccw/src/templates/dashboard-js/main.js @@ -118,22 +118,30 @@ function initPreloadServices() { { isHighPriority: true, ttl: 120000 } // 2分钟 ); + // CLI 状态 - 高优先级 window.preloadService.register('cli-status', () => fetch('/api/cli/status').then(r => r.ok ? r.json() : Promise.reject(r)), { isHighPriority: true, ttl: 300000 } // 5分钟 ); + // CLI 工具配置 - /api/cli/config(cli-manager.js 使用) + window.preloadService.register('cli-config', + () => fetch('/api/cli/config').then(r => r.ok ? r.json() : Promise.reject(r)), + { isHighPriority: true, ttl: 300000 } // 5分钟 + ); + + // CLI 工具列表配置 - /api/cli/tools-config(cli-status.js 使用) + window.preloadService.register('cli-tools-config', + () => fetch('/api/cli/tools-config').then(r => r.ok ? r.json() : Promise.reject(r)), + { isHighPriority: true, ttl: 300000 } // 5分钟 + ); + // 注册中优先级数据源 window.preloadService.register('codexlens-models', () => fetch('/api/codexlens/models').then(r => r.ok ? r.json() : Promise.reject(r)), { isHighPriority: false, ttl: 600000 } // 10分钟 ); - window.preloadService.register('cli-config', - () => fetch('/api/cli/config').then(r => r.ok ? r.json() : Promise.reject(r)), - { isHighPriority: false, ttl: 300000 } // 5分钟 - ); - // 立即触发高优先级预加载(静默后台执行) window.preloadService.runInitialPreload(); diff --git a/ccw/src/templates/dashboard-js/views/codexlens-manager.js b/ccw/src/templates/dashboard-js/views/codexlens-manager.js index 90d11962..a0697db5 100644 --- a/ccw/src/templates/dashboard-js/views/codexlens-manager.js +++ b/ccw/src/templates/dashboard-js/views/codexlens-manager.js @@ -1,6 +1,11 @@ // CodexLens Manager - Configuration, Model Management, and Semantic Dependencies // Extracted from cli-manager.js for better maintainability +// ============================================================ +// EVENT HANDLERS - 用于防止内存泄漏的处理器引用 +// ============================================================ +var _workspaceStatusHandler = null; + // ============================================================ // CACHE BRIDGE - 使用全局 PreloadService // ============================================================ @@ -156,13 +161,17 @@ async function refreshWorkspaceIndexStatus(forceRefresh) { if (window.lucide) lucide.createIcons(); } - // 2. Listen for data update events + // 2. Listen for data update events (防止内存泄漏:先移除旧监听器) if (window.eventManager) { - var handleUpdate = function(data) { + // 移除之前的监听器(如果存在) + if (_workspaceStatusHandler) { + window.eventManager.off('data:updated:workspace-status', _workspaceStatusHandler); + } + // 创建新的监听器并保存引用 + _workspaceStatusHandler = function(data) { render(data); }; - // Use one-time listener or remove at appropriate time - window.eventManager.on('data:updated:workspace-status', handleUpdate); + window.eventManager.on('data:updated:workspace-status', _workspaceStatusHandler); } // 3. Trigger background loading