diff --git a/web/static/css/style.css b/web/static/css/style.css index 6a62dbd9..728aed57 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -8072,6 +8072,47 @@ header { border: 1px solid rgba(0,0,0,0.05); } +.dashboard-section-overview { + background: var(--bg-primary); + border-radius: 16px; + padding: 22px 24px; + box-shadow: 0 2px 12px rgba(0,0,0,0.04); + border: 1px solid rgba(0,0,0,0.05); +} + +.dashboard-overview-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 16px; +} + +.dashboard-overview-item { + padding: 14px 18px; + background: var(--bg-secondary); + border-radius: 12px; + border: 1px solid var(--border-color); + cursor: pointer; + transition: border-color 0.2s, background 0.2s; +} + +.dashboard-overview-item:hover { + border-color: var(--accent-color); + background: rgba(0, 102, 255, 0.04); +} + +.dashboard-overview-label { + display: block; + font-size: 0.8rem; + font-weight: 600; + color: var(--text-secondary); + margin-bottom: 6px; +} + +.dashboard-overview-value { + font-size: 0.9rem; + color: var(--text-primary); +} + .dashboard-section-title { display: flex; align-items: center; diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js index 51f0ef98..d842264e 100644 --- a/web/static/js/dashboard.js +++ b/web/static/js/dashboard.js @@ -1,4 +1,4 @@ -// 仪表盘页面:拉取运行中任务、漏洞统计并渲染 +// 仪表盘页面:拉取运行中任务、漏洞统计、批量任务、工具与 Skills 统计并渲染 async function refreshDashboard() { const runningEl = document.getElementById('dashboard-running-tasks'); @@ -13,17 +13,22 @@ async function refreshDashboard() { const barEl = document.getElementById('dashboard-bar-' + s); if (barEl) barEl.style.width = '0%'; }); + setDashboardOverviewPlaceholder('…'); if (typeof apiFetch === 'undefined') { if (runningEl) runningEl.textContent = '-'; if (vulnTotalEl) vulnTotalEl.textContent = '-'; + setDashboardOverviewPlaceholder('-'); return; } try { - const [tasksRes, vulnRes] = await Promise.all([ + const [tasksRes, vulnRes, batchRes, monitorRes, skillsRes] = await Promise.all([ apiFetch('/api/agent-loop/tasks').then(r => r.ok ? r.json() : null).catch(() => null), - apiFetch('/api/vulnerabilities/stats').then(r => r.ok ? r.json() : null).catch(() => null) + apiFetch('/api/vulnerabilities/stats').then(r => r.ok ? r.json() : null).catch(() => null), + apiFetch('/api/batch-tasks?limit=500&page=1').then(r => r.ok ? r.json() : null).catch(() => null), + apiFetch('/api/monitor/stats').then(r => r.ok ? r.json() : null).catch(() => null), + apiFetch('/api/skills/stats').then(r => r.ok ? r.json() : null).catch(() => null) ]); if (tasksRes && Array.isArray(tasksRes.tasks)) { @@ -50,9 +55,64 @@ async function refreshDashboard() { if (barEl) barEl.style.width = '0%'; }); } + + // 批量任务队列:按状态统计 + if (batchRes && Array.isArray(batchRes.queues)) { + const queues = batchRes.queues; + let pending = 0, running = 0, done = 0; + queues.forEach(q => { + const s = (q.status || '').toLowerCase(); + if (s === 'pending' || s === 'paused') pending++; + else if (s === 'running') running++; + else if (s === 'completed' || s === 'cancelled') done++; + }); + setEl('dashboard-batch-pending', String(pending)); + setEl('dashboard-batch-running', String(running)); + setEl('dashboard-batch-done', String(done)); + } else { + setEl('dashboard-batch-pending', '-'); + setEl('dashboard-batch-running', '-'); + setEl('dashboard-batch-done', '-'); + } + + // 工具调用:monitor/stats 为 { toolName: { TotalCalls, ... } } + if (monitorRes && typeof monitorRes === 'object') { + const names = Object.keys(monitorRes); + let totalCalls = 0; + names.forEach(k => { + const v = monitorRes[k]; + const n = v && (v.totalCalls ?? v.TotalCalls); + if (typeof n === 'number') totalCalls += n; + }); + setEl('dashboard-tools-count', String(names.length)); + setEl('dashboard-tools-calls', String(totalCalls)); + } else { + setEl('dashboard-tools-count', '-'); + setEl('dashboard-tools-calls', '-'); + } + + // Skills:{ total_skills, total_calls, ... } + if (skillsRes && typeof skillsRes === 'object') { + setEl('dashboard-skills-count', String(skillsRes.total_skills ?? '-')); + setEl('dashboard-skills-calls', String(skillsRes.total_calls ?? '-')); + } else { + setEl('dashboard-skills-count', '-'); + setEl('dashboard-skills-calls', '-'); + } } catch (e) { console.warn('仪表盘拉取统计失败', e); if (runningEl) runningEl.textContent = '-'; if (vulnTotalEl) vulnTotalEl.textContent = '-'; + setDashboardOverviewPlaceholder('-'); } } + +function setEl(id, text) { + const el = document.getElementById(id); + if (el) el.textContent = text; +} + +function setDashboardOverviewPlaceholder(t) { + ['dashboard-batch-pending', 'dashboard-batch-running', 'dashboard-batch-done', + 'dashboard-tools-count', 'dashboard-tools-calls', 'dashboard-skills-count', 'dashboard-skills-calls'].forEach(id => setEl(id, t)); +} diff --git a/web/templates/index.html b/web/templates/index.html index a9ba6828..61d5d383 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -267,6 +267,23 @@ +