From 101d3f9bc9e66daadc985776310fa74060d1303f Mon Sep 17 00:00:00 2001 From: Blizzard Date: Fri, 26 Jun 2026 17:12:48 +0800 Subject: [PATCH] =?UTF-8?q?refactor(desktop):=20=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E9=A1=B5=E6=94=B9=E4=B8=89=E6=A0=8F=20=E2=80=94=E2=80=94=20?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E8=BE=93=E5=87=BA=E5=9B=BA=E5=AE=9A=E5=8F=B3?= =?UTF-8?q?=E4=BE=A7(Markdown)=EF=BC=8C=E4=B8=AD=E9=97=B4=20tab=20?= =?UTF-8?q?=E5=8F=AA=E7=95=99=E8=BD=A8=E8=BF=B9/=E5=B7=A5=E5=85=B7/?= =?UTF-8?q?=E8=AF=84=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按反馈调整运行·观测布局:模型输出不进 tab,恢复成独立右侧面板用 Markdown 渲染(与旧版一致); 中间 tab 切换 执行轨迹/工具调用/评测,标签行右上保留运行状态指示(完成✓/流式中…/出错)。 三栏:运行历史 | tab详情+状态 | 模型输出。 tsc+vite 通过;预览自查布局正确(左历史/中tab+状态/右Markdown输出),wails 重启加载新版。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../frontend/src/views/RunsView.tsx | 67 ++++++++----------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/sundynix-desktop/frontend/src/views/RunsView.tsx b/sundynix-desktop/frontend/src/views/RunsView.tsx index f7ce34b..5a3c7e6 100644 --- a/sundynix-desktop/frontend/src/views/RunsView.tsx +++ b/sundynix-desktop/frontend/src/views/RunsView.tsx @@ -1,13 +1,12 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { Activity, History, Wrench } from "lucide-react"; +import { Activity, FileText, History, Wrench } from "lucide-react"; import { ExecTrace } from "../components/ExecTrace"; -import { ChartView } from "../components/ChartView"; -import { extractChartBlocks, hasChart } from "../lib/chartspec"; +import { Markdown } from "../components/Markdown"; import { deriveNodes, emptyRun, type RunState } from "../lib/run"; import { listRuns, taskEval, streamExec, streamTokens, type RunSummary, type EvalResult } from "../lib/api"; -import { Tabs, Dot, Badge, EmptyState, cn, type TabDef } from "../ui"; +import { Tabs, Panel, Dot, Badge, EmptyState, cn, type TabDef } from "../ui"; -type DetailTab = "trace" | "output" | "tools" | "eval"; +type DetailTab = "trace" | "tools" | "eval"; const STATUS_DOT: Record = { done: "success", failed: "danger", timeout: "danger", rejected: "danger", @@ -23,8 +22,8 @@ function relTime(iso: string): string { return `${Math.floor(d / 86_400_000)} 天前`; } -// 运行 · 观测:左侧运行历史,右侧 tab 切换查看选中运行的 轨迹/输出/工具调用/评测(复盘)。 -// 选中历史运行后从 Redis 回放(exec/token 流对完成任务即回放);「当前运行」置顶沿用实时订阅。 +// 运行 · 观测:左=运行历史,中=tab 切换(轨迹/工具/评测)+状态,右=模型输出(Markdown)。 +// 选中历史运行从 Redis 回放;「当前运行」置顶沿用实时订阅。 export function RunsView({ run }: { run: RunState }) { const [runs, setRuns] = useState([]); const [sel, setSel] = useState(null); // null = 当前实时运行 @@ -53,7 +52,7 @@ export function RunsView({ run }: { run: RunState }) { taskEval(taskId).then(setEvalRes).catch(() => {}); }, [run.taskId]); - // 新的实时运行开始 → 自动切回「当前运行」(若此前选着历史项),并回到轨迹标签。 + // 新实时运行开始 → 切回「当前运行」+ 回到轨迹标签。 useEffect(() => { if (run.taskId) { closeRef.current?.(); setSel(null); setEvalRes(null); setTab("trace"); } }, [run.taskId]); @@ -69,23 +68,28 @@ export function RunsView({ run }: { run: RunState }) { const tools = nodes.filter((n) => n.kind === "tool"); const tabs: TabDef[] = [ { key: "trace", label: "执行轨迹", count: nodes.length }, - { key: "output", label: "模型输出" }, { key: "tools", label: "工具调用", count: tools.length }, { key: "eval", label: "评测" }, ]; const empty = !cur.taskId && cur.exec.length === 0 && !cur.output; + // 运行状态指示(沿用原底部抽屉的「完成 ✓ / 流式中… / 出错」)。 + const statusCls = + cur.phase === "streaming" ? "text-accent-400" : cur.phase === "done" ? "text-success" : cur.phase === "error" ? "text-danger" : "text-slate-500"; + const statusText = + cur.phase === "streaming" ? "流式中…" : cur.phase === "done" ? "完成 ✓" : cur.phase === "error" ? `✗ ${cur.error ?? "出错"}` : cur.phase === "submitting" ? "提交中…" : "就绪"; + return (

运行 · 观测

-

运行历史复盘:选一次运行,切换标签查看节点轨迹、模型输出、工具调用与评测。

+

运行历史复盘:选一次运行,左查轨迹/工具/评测(切换标签),右看模型输出。

{nodes.length} 节点 · {tools.length} 次工具调用
-
+
{/* 运行历史列表 */}
@@ -115,18 +119,17 @@ export function RunsView({ run }: { run: RunState }) {
- {/* 详情:tab 切换 轨迹/输出/工具/评测 */} + {/* 中:tab 切换 轨迹/工具/评测 + 状态指示 */}
-
+
+ {statusText}
{empty ? ( - + ) : tab === "trace" ? ( - ) : tab === "output" ? ( - ) : tab === "tools" ? ( ) : ( @@ -134,30 +137,16 @@ export function RunsView({ run }: { run: RunState }) { )}
-
-
- ); -} -// OutputView:渲染模型输出。含 ```chart 块时分段渲染(文本 + SVG 图表),否则纯文本。 -function OutputView({ output }: { output: string }) { - if (!output) { - return

本次运行暂无输出(或尚未产出 token)。

; - } - if (!hasChart(output)) { - return
{output}
; - } - return ( -
- {extractChartBlocks(output).map((seg, i) => - seg.kind === "chart" ? ( - - ) : ( - seg.text.trim() && ( -
{seg.text}
- ) - ), - )} + {/* 右:模型输出(Markdown,固定面板,与之前一致) */} + + {cur.output ? ( + + ) : ( + + )} + +
); }