更新: 2 个文件 - 2026-03-21 18:00:07
这个提交包含在:
@@ -63,6 +63,10 @@ const DATA_HUB_ITEMS = [
|
||||
{ title: "entity-completeness.json", href: "/data/entity-completeness.json", description: "实体级 catalog 完整度、版本映射和 workflow 覆盖。", badge: "json" },
|
||||
{ title: "entity-discovery-backlog.json", href: "/data/entity-discovery-backlog.json", description: "发现但尚未正式编目的 repo / 插件 / 包 backlog。", badge: "json" },
|
||||
{ title: "entity-queues.json", href: "/data/entity-queues.json", description: "discovery/history/latest/workflow 四类队列摘要。", badge: "json" },
|
||||
{ title: "version-completeness.json", href: "/data/version-completeness.json", description: "最新版本同步覆盖、安全相关版本历史与 auto-promoted 统计。", badge: "json" },
|
||||
{ title: "version-backlog.json", href: "/data/version-backlog.json", description: "source-gap、未解决版本缺口与 lab pending 队列。", badge: "json" },
|
||||
{ title: "release-index.json", href: "/data/release-index.json", description: "安全相关版本记录索引真值。", badge: "json" },
|
||||
{ title: "lab-enqueue-summary.json", href: "/data/lab-enqueue-summary.json", description: "版本变化触发的 lab 入队与 pending 摘要。", badge: "json" },
|
||||
{ title: "runs.json", href: "/runs.json", description: "最近运行的结构化详情,可用于 UI 和调试。", badge: "json" },
|
||||
{ title: "systems.json", href: "/systems.json", description: "系统级覆盖、分类、更新时间和浏览器证据统计。", badge: "json" },
|
||||
{ title: "entities.json", href: "/entities.json", description: "分层实体索引、实体状态和系统归属。", badge: "json" },
|
||||
@@ -101,6 +105,7 @@ const state = {
|
||||
architecture: null,
|
||||
completeness: null,
|
||||
entityCompleteness: null,
|
||||
versionCompleteness: null,
|
||||
sourceHealth: null,
|
||||
alerts: [],
|
||||
monitorSummary: null,
|
||||
@@ -297,11 +302,14 @@ function familyOptions() {
|
||||
function metricCards() {
|
||||
const completeness = state.completeness || state.summary?.completeness || {};
|
||||
const entityCoverage = state.entityCompleteness || state.summary?.entity_coverage || completeness.entity_coverage || {};
|
||||
const versionCoverage = state.versionCompleteness || state.summary?.version_coverage || completeness.version_coverage || {};
|
||||
const monitoring = state.monitorSummary || state.summary?.monitoring || {};
|
||||
const advisoryTotal = Number(completeness.advisory_total || state.summary?.advisory_count || 0);
|
||||
const advisorySuccess = Number(completeness.verified_real || 0);
|
||||
const catalogedEntities = Number(entityCoverage.cataloged_entity_total || 0);
|
||||
const candidateEntities = Number(entityCoverage.candidate_entity_total || 0);
|
||||
const latestVersionSynced = Number(versionCoverage.latest_version_synced_count || 0);
|
||||
const sourceGapCount = Number(versionCoverage.source_gap_count || 0);
|
||||
const activeSources = Number(monitoring.active_source_count || state.sourceHealth?.active_source_count || 0);
|
||||
const greenSources = Number(monitoring.green_source_count || state.sourceHealth?.green_source_count || 0);
|
||||
const openAlerts = Number(monitoring.open_alert_count || state.sourceHealth?.open_alert_count || 0);
|
||||
@@ -322,6 +330,13 @@ function metricCards() {
|
||||
color: "var(--accent-yellow)",
|
||||
iconName: "systems"
|
||||
},
|
||||
{
|
||||
label: "版本同步",
|
||||
value: latestVersionSynced,
|
||||
note: `source-gap ${sourceGapCount}`,
|
||||
color: "var(--accent-blue)",
|
||||
iconName: "spark"
|
||||
},
|
||||
{
|
||||
label: "active sources",
|
||||
value: activeSources,
|
||||
@@ -602,6 +617,7 @@ function renderSystemCards(items, compact = false) {
|
||||
const verified = Number(system.verified_real || 0) + Number(system.verified_synthetic || 0);
|
||||
const coverage = Math.round((verified / total) * 100);
|
||||
const entitySummary = system.entity_summary || {};
|
||||
const versionSummary = system.version_summary || {};
|
||||
const topEntities = system.top_entities || [];
|
||||
const backlogPreview = system.backlog_preview || [];
|
||||
return `
|
||||
@@ -617,6 +633,8 @@ function renderSystemCards(items, compact = false) {
|
||||
<span class="tag">阻塞 ${escapeHtml(system.blocked || 0)}</span>
|
||||
<span class="tag">实体 ${escapeHtml(entitySummary.cataloged_entity_total || 0)}</span>
|
||||
<span class="tag">backlog ${escapeHtml(entitySummary.candidate_entity_total || 0)}</span>
|
||||
<span class="tag">latest ${escapeHtml(system.latest_version || "-")}</span>
|
||||
<span class="tag">version ${escapeHtml(system.version_sync_status || "-")}</span>
|
||||
</div>
|
||||
<div class="meter"><span style="--fill:${coverage}%"></span></div>
|
||||
${compact ? "" : `
|
||||
@@ -629,6 +647,10 @@ function renderSystemCards(items, compact = false) {
|
||||
<span class="plan-label">队列与缺口</span>
|
||||
<div class="plan-copy">history complete ${escapeHtml(entitySummary.history_full_complete_count || 0)} · latest green ${escapeHtml(entitySummary.latest_green_count || 0)} · version gap ${escapeHtml(entitySummary.version_gap_entity_count || 0)}</div>
|
||||
</article>
|
||||
<article class="plan-card">
|
||||
<span class="plan-label">版本同步</span>
|
||||
<div class="plan-copy">latest synced ${escapeHtml(versionSummary.latest_version_synced_count || 0)} · source-gap ${escapeHtml(versionSummary.source_gap_count || 0)} · security versions ${escapeHtml(system.security_version_count || 0)}</div>
|
||||
</article>
|
||||
</div>
|
||||
${(topEntities.length || backlogPreview.length) ? `
|
||||
<div class="tag-row" style="margin-top:10px;">
|
||||
@@ -816,6 +838,7 @@ function renderPanel(panelKey, title, meta, iconName, content) {
|
||||
function renderCompletenessPanel(panelKey, compact = false) {
|
||||
const completeness = state.completeness || state.summary?.completeness || {};
|
||||
const entityCoverage = state.entityCompleteness || state.summary?.entity_coverage || completeness.entity_coverage || {};
|
||||
const versionCoverage = state.versionCompleteness || state.summary?.version_coverage || completeness.version_coverage || {};
|
||||
const sourceHealth = state.sourceHealth || completeness.source_health || {};
|
||||
const systems = (state.completeness?.systems || []).map((system) => `
|
||||
<article class="plan-card">
|
||||
@@ -874,14 +897,32 @@ function renderCompletenessPanel(panelKey, compact = false) {
|
||||
<strong>version mapped</strong>
|
||||
<span>${escapeHtml(entityCoverage.version_mapped_count || 0)}</span>
|
||||
</article>
|
||||
<article class="detail-stat">
|
||||
<strong>latest version synced</strong>
|
||||
<span>${escapeHtml(versionCoverage.latest_version_synced_count || 0)}</span>
|
||||
</article>
|
||||
<article class="detail-stat">
|
||||
<strong>version source-gap</strong>
|
||||
<span>${escapeHtml(versionCoverage.source_gap_count || 0)}</span>
|
||||
</article>
|
||||
<article class="detail-stat">
|
||||
<strong>security versions</strong>
|
||||
<span>${escapeHtml(versionCoverage.security_version_total || 0)}</span>
|
||||
</article>
|
||||
<article class="detail-stat">
|
||||
<strong>lab enqueued</strong>
|
||||
<span>${escapeHtml(versionCoverage.lab_enqueued_count || 0)}</span>
|
||||
</article>
|
||||
</div>
|
||||
<div class="plan-grid" style="margin-top:16px;">${systems || `<div class="empty-state">暂无系统完整度数据。</div>`}</div>
|
||||
${compact ? "" : `
|
||||
<div class="detail-actions" style="margin-top:16px;">
|
||||
<a class="button button-secondary" href="/docs/testing-completeness-report.html" target="_blank" rel="noreferrer">${icon("docs")}<span>打开中文报告</span></a>
|
||||
<a class="button button-secondary" href="/docs/entity-catalog-report.html" target="_blank" rel="noreferrer">${icon("docs")}<span>打开实体报告</span></a>
|
||||
<a class="button button-secondary" href="/docs/version-sync-report.html" target="_blank" rel="noreferrer">${icon("docs")}<span>打开版本报告</span></a>
|
||||
<a class="button button-secondary" href="/data/completeness.json" target="_blank" rel="noreferrer">${icon("json")}<span>打开 completeness.json</span></a>
|
||||
<a class="button button-secondary" href="/data/entity-completeness.json" target="_blank" rel="noreferrer">${icon("json")}<span>打开 entity-completeness.json</span></a>
|
||||
<a class="button button-secondary" href="/data/version-completeness.json" target="_blank" rel="noreferrer">${icon("json")}<span>打开 version-completeness.json</span></a>
|
||||
<a class="button button-secondary" href="/data/source-health.json" target="_blank" rel="noreferrer">${icon("json")}<span>打开 source-health.json</span></a>
|
||||
</div>
|
||||
${failures.length ? `<div class="callout" style="margin-top:16px;"><strong>Ingest 未清零</strong><div class="plan-copy">${escapeHtml(failures.join(" | "))}</div></div>` : ""}
|
||||
@@ -1634,7 +1675,7 @@ async function loadData(preserveSelection = true) {
|
||||
renderSyncState("loading", "刷新中", `本地时间 ${new Date().toLocaleTimeString("zh-CN", { hour12: false })}`);
|
||||
|
||||
try {
|
||||
const [summary, runs, systems, entities, advisories, profiles, architecture, completeness, entityCompleteness, sourceHealth, alerts, monitorSummary] = await Promise.all([
|
||||
const [summary, runs, systems, entities, advisories, profiles, architecture, completeness, entityCompleteness, versionCompleteness, sourceHealth, alerts, monitorSummary] = await Promise.all([
|
||||
fetchJson("/summary.json"),
|
||||
fetchJson("/runs.json"),
|
||||
fetchJson("/systems.json"),
|
||||
@@ -1644,6 +1685,7 @@ async function loadData(preserveSelection = true) {
|
||||
fetchJson("/architecture.json"),
|
||||
fetchJson("/data/completeness.json"),
|
||||
fetchJson("/data/entity-completeness.json"),
|
||||
fetchJson("/data/version-completeness.json"),
|
||||
fetchJson("/data/source-health.json"),
|
||||
fetchJson("/data/alerts.json"),
|
||||
fetchJson("/data/monitor-summary.json")
|
||||
@@ -1658,6 +1700,7 @@ async function loadData(preserveSelection = true) {
|
||||
state.architecture = architecture;
|
||||
state.completeness = completeness;
|
||||
state.entityCompleteness = entityCompleteness;
|
||||
state.versionCompleteness = versionCompleteness;
|
||||
state.sourceHealth = sourceHealth;
|
||||
state.alerts = alerts;
|
||||
state.monitorSummary = monitorSummary;
|
||||
|
||||
在新工单中引用
屏蔽一个用户