Files
agent/evaluation-site/assets/research.js
T
2026-07-28 00:57:15 +08:00

297 lines
8.9 KiB
JavaScript

(() => {
"use strict";
const evidenceData = window.K1412_EVIDENCE;
const evidenceList = document.querySelector("#evidence-list");
const evidenceCount = document.querySelector("#evidence-count");
const emptyEvidence = document.querySelector("#empty-evidence");
const searchInput = document.querySelector("#evidence-search");
const expandButton = document.querySelector("#expand-evidence");
const depthButtons = [...document.querySelectorAll("[data-depth]")];
const themeButtons = [...document.querySelectorAll("[data-theme]")];
const depthLabels = {
core: "核心证据",
support: "旁证",
context: "历史背景",
};
const themeLabels = {
verification: "完成证明",
protocol: "协议审计",
recovery: "失败恢复",
reliability: "风险可靠性",
context: "历史背景",
};
const state = {
query: "",
depth: "all",
theme: "all",
expanded: false,
};
function normalize(value) {
return String(value || "")
.toLocaleLowerCase("zh-CN")
.replace(/\s+/g, " ")
.trim();
}
function searchableText(record) {
return normalize(
[
record.id,
record.title,
record.depth,
record.theme,
record.evidence,
record.supports,
record.boundary,
].join(" ")
);
}
function filteredRecords() {
if (!evidenceData || !Array.isArray(evidenceData.records)) {
return [];
}
const terms = normalize(state.query).split(" ").filter(Boolean);
return evidenceData.records.filter((record) => {
if (state.depth !== "all" && record.depth !== state.depth) {
return false;
}
if (state.theme !== "all" && record.theme !== state.theme) {
return false;
}
const haystack = searchableText(record);
return terms.every((term) => haystack.includes(term));
});
}
function tag(label, className) {
const element = document.createElement("span");
element.className = `evidence-tag ${className || ""}`.trim();
element.textContent = label;
return element;
}
function detailColumn(title, text, className = "") {
const wrapper = document.createElement("div");
wrapper.className = className;
const heading = document.createElement("h4");
heading.textContent = title;
const paragraph = document.createElement("p");
paragraph.textContent = text || "本轮未将该论文用于直接论证。";
wrapper.append(heading, paragraph);
return wrapper;
}
function evidenceItem(record) {
const details = document.createElement("details");
details.className = "evidence-item";
details.dataset.depth = record.depth;
details.open = state.expanded;
const summary = document.createElement("summary");
const id = document.createElement("span");
id.className = "evidence-id";
id.textContent = record.id;
const heading = document.createElement("div");
heading.className = "evidence-heading";
const title = document.createElement("h3");
title.textContent = record.title;
const tags = document.createElement("div");
tags.className = "evidence-tags";
tags.append(
tag(depthLabels[record.depth] || record.depth, record.depth),
tag(themeLabels[record.theme] || record.theme)
);
heading.append(title, tags);
const openLabel = document.createElement("span");
openLabel.className = "evidence-open";
openLabel.textContent = details.open ? "收起" : "展开";
summary.append(id, heading, openLabel);
details.append(summary);
if (record.depth === "context") {
const detail = document.createElement("div");
detail.className = "evidence-detail context-detail";
detail.append(
detailColumn("本轮位置", record.boundary, "evidence-boundary")
);
details.append(detail);
} else {
const detail = document.createElement("div");
detail.className = "evidence-detail";
detail.append(
detailColumn("核过的直接证据", record.evidence),
detailColumn("可支持的判断", record.supports),
detailColumn("不能外推", record.boundary, "evidence-boundary")
);
details.append(detail);
}
const source = document.createElement("div");
source.className = "evidence-source";
const sourceLink = document.createElement("a");
sourceLink.href = record.url;
sourceLink.target = "_blank";
sourceLink.rel = "noreferrer";
sourceLink.textContent = "打开 arXiv 原文";
source.append(sourceLink);
details.append(source);
details.addEventListener("toggle", () => {
openLabel.textContent = details.open ? "收起" : "展开";
});
return details;
}
function updateFilterButtons(buttons, value, attribute) {
buttons.forEach((button) => {
const active = button.dataset[attribute] === value;
button.classList.toggle("is-active", active);
button.setAttribute("aria-pressed", String(active));
});
}
function renderEvidence() {
if (!evidenceData) {
evidenceCount.textContent = "证据数据未载入。";
emptyEvidence.hidden = false;
return;
}
const records = filteredRecords();
const fragment = document.createDocumentFragment();
records.forEach((record) => fragment.append(evidenceItem(record)));
evidenceList.replaceChildren(fragment);
const counts = evidenceData.counts;
evidenceCount.textContent =
`显示 ${records.length} / ${counts.pool}` +
` · 核心 ${counts.core} · 旁证 ${counts.support} · 背景 ${counts.context}`;
emptyEvidence.hidden = records.length !== 0;
expandButton.disabled = records.length === 0;
expandButton.textContent = state.expanded ? "收起当前结果" : "展开当前结果";
}
depthButtons.forEach((button) => {
button.addEventListener("click", () => {
state.depth = button.dataset.depth;
state.expanded = false;
updateFilterButtons(depthButtons, state.depth, "depth");
renderEvidence();
});
});
themeButtons.forEach((button) => {
button.addEventListener("click", () => {
state.theme = button.dataset.theme;
state.expanded = false;
updateFilterButtons(themeButtons, state.theme, "theme");
renderEvidence();
});
});
searchInput?.addEventListener("input", (event) => {
state.query = event.target.value;
state.expanded = false;
renderEvidence();
});
expandButton?.addEventListener("click", () => {
state.expanded = !state.expanded;
document.querySelectorAll(".evidence-item").forEach((item) => {
item.open = state.expanded;
const label = item.querySelector(".evidence-open");
if (label) {
label.textContent = state.expanded ? "收起" : "展开";
}
});
expandButton.textContent = state.expanded ? "收起当前结果" : "展开当前结果";
});
function updateReadingProgress() {
const documentHeight =
document.documentElement.scrollHeight - window.innerHeight;
const progress = documentHeight > 0 ? window.scrollY / documentHeight : 0;
const bar = document.querySelector("#reading-progress");
if (bar) {
bar.style.width = `${Math.min(1, Math.max(0, progress)) * 100}%`;
}
}
let progressFrame = 0;
window.addEventListener(
"scroll",
() => {
if (progressFrame) {
return;
}
progressFrame = window.requestAnimationFrame(() => {
updateReadingProgress();
progressFrame = 0;
});
},
{ passive: true }
);
updateReadingProgress();
const navAliases = {
conclusions: "overview",
synthesis: "model",
};
const navLinks = [...document.querySelectorAll(".primary-nav a")];
const sections = [...document.querySelectorAll("[data-section]")];
const sectionObserver = new IntersectionObserver(
(entries) => {
const visible = entries
.filter((entry) => entry.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
if (!visible) {
return;
}
const targetId = navAliases[visible.target.id] || visible.target.id;
navLinks.forEach((link) => {
const active = link.getAttribute("href") === `#${targetId}`;
link.classList.toggle("is-active", active);
if (active) {
const nav = link.closest(".primary-nav");
if (nav && nav.scrollWidth > nav.clientWidth) {
nav.scrollTo({
left: Math.max(0, link.offsetLeft - nav.clientWidth / 2),
behavior: "smooth",
});
}
}
});
},
{
rootMargin: "-18% 0px -62% 0px",
threshold: [0, 0.08, 0.2],
}
);
sections.forEach((section) => sectionObserver.observe(section));
renderEvidence();
if (window.location.hash) {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
document.querySelector(window.location.hash)?.scrollIntoView();
});
});
}
})();