diff --git a/web/static/app.js b/web/static/app.js index c0cda82..66b9181 100644 --- a/web/static/app.js +++ b/web/static/app.js @@ -521,22 +521,26 @@ function routeButtons(routes) { `; } -function searchSteps(steps = []) { +function searchActivity(steps = []) { + const current = + steps.find((step) => step.status === "running") || + [...steps].reverse().find((step) => step.status === "done") || + steps[0] || + {}; + const doneCount = steps.filter((step) => step.status === "done").length; + const currentIndex = Math.min(doneCount + (current.status === "running" ? 1 : 0), steps.length || 1); + const statusLabel = current.status === "running" ? "working" : current.status || "pending"; return ` -
- ${steps - .map( - (step) => ` -
- -
- ${escapeHtml(step.label)} - ${escapeHtml(step.detail || step.status)} -
-
- `, - ) - .join("")} +
+ +
+
+ Search Agent + ${escapeHtml(current.label || "准备搜索")} +
+
${escapeHtml(current.detail || "正在准备检索上下文")}
+
+
${escapeHtml(statusLabel)} · ${currentIndex}/${steps.length || 1}
`; } @@ -596,10 +600,7 @@ function renderSearchRunning(job) { elements.lensTitle.textContent = job?.query || elements.searchInput.value.trim() || "搜索"; elements.lensBody.innerHTML = `
-

Search Agent 正在理解问题、扩展关键词并检索本地论文库。

-
-
- ${searchSteps(job?.steps || [])} + ${searchActivity(job?.steps || [])}
`; } @@ -873,6 +874,7 @@ async function runSearch() { ], }; renderSearchRunning(starter); + scrollLensIntoView(); try { const payload = await api("/api/search/agent", { method: "POST", diff --git a/web/static/index.html b/web/static/index.html index ca86d7f..f572d1f 100644 --- a/web/static/index.html +++ b/web/static/index.html @@ -5,7 +5,7 @@ Agent Knowledge Atlas - +
@@ -79,6 +79,6 @@
- + diff --git a/web/static/styles.css b/web/static/styles.css index 0e5e934..a0450d8 100644 --- a/web/static/styles.css +++ b/web/static/styles.css @@ -521,55 +521,83 @@ button { padding: 3px 6px; } -.agent-steps { +.agent-activity { display: grid; - gap: 10px; + grid-template-columns: auto minmax(0, 1fr) auto; + gap: 12px; + align-items: center; + border: 1px solid var(--line); + border-radius: 8px; + background: #fbfaf6; + padding: 12px; } -.agent-step { - display: grid; - grid-template-columns: 13px 1fr; - gap: 10px; - align-items: start; - color: var(--muted); -} - -.step-dot { - width: 9px; - height: 9px; - margin-top: 6px; - border: 1px solid #aab3ad; +.activity-dot { + width: 12px; + height: 12px; border-radius: 50%; - background: #ffffff; -} - -.agent-step strong { - display: block; - color: #17201d; - font-size: 13px; -} - -.agent-step span:last-child { - display: block; - margin-top: 2px; - font-size: 12px; - line-height: 1.42; -} - -.agent-step.running .step-dot { - border-color: var(--teal); background: var(--teal); - box-shadow: 0 0 0 5px rgba(13, 118, 111, 0.12); + box-shadow: 0 0 0 7px rgba(13, 118, 111, 0.12); } -.agent-step.done .step-dot { - border-color: var(--green); +.agent-activity.running .activity-dot { + animation: activityPulse 1.5s ease-in-out infinite; +} + +.agent-activity.done .activity-dot { background: var(--green); + box-shadow: 0 0 0 7px rgba(82, 127, 70, 0.12); } -.agent-step.error .step-dot { - border-color: var(--coral); +.agent-activity.error .activity-dot { background: var(--coral); + box-shadow: 0 0 0 7px rgba(186, 86, 68, 0.12); +} + +.activity-copy { + min-width: 0; +} + +.activity-title { + display: flex; + flex-wrap: wrap; + gap: 6px; + align-items: baseline; + color: var(--muted); + font-size: 12px; +} + +.activity-title strong { + color: #17201d; + font-size: 14px; +} + +.activity-detail { + margin-top: 3px; + color: #4c5550; + font-size: 13px; + line-height: 1.38; + overflow-wrap: anywhere; +} + +.activity-meta { + color: var(--muted); + font-size: 11px; + font-weight: 760; + white-space: nowrap; +} + +@keyframes activityPulse { + 0%, + 100% { + transform: scale(1); + box-shadow: 0 0 0 7px rgba(13, 118, 111, 0.1); + } + + 50% { + transform: scale(0.82); + box-shadow: 0 0 0 10px rgba(13, 118, 111, 0.18); + } } .search-brief h3 { @@ -885,6 +913,14 @@ button { max-width: 100%; } + .agent-activity { + grid-template-columns: auto minmax(0, 1fr); + } + + .activity-meta { + grid-column: 2; + } + .route-band, .timeline-band { margin-top: 12px;