fix(desktop): 补回报告页剥离时漏搬的 PDF 导出与完成系统通知
759483b 把报告页剥成纯启动器时,Word/Markdown 导出搬去了运行页,但漏了两个:
printReportHtml(前端打印出 PDF,CJK 零字体依赖)和 notify(完成弹系统通知)
外部调用点归零,成了被孤立的活功能。
- 运行页报告正文面板补 PDF 按钮:previewRef 抓已渲染 DOM 送打印视图,
与剥离前同一条路径。
- 完成通知挪进 attachRun 的 token 流 done 回调并加 label 参数:原先只有
报告会通知,但「跑几分钟、人早切走了」对编排任务一样成立,且 attachRun
是所有运行的唯一汇合点,放这儿不会再漂移。恢复的待审任务也带主题。
验证:tsc 干净、68 个 vitest 全过、两函数调用点恢复非零。
⚠️ 未实机点验(需登录态):PDF 按钮实际点击出打印视图、通知实际弹出,
下次起服务后补验。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { Activity, FileText, FileType2, FileCode, History, Users, Wrench } from "lucide-react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Activity, FileText, FileType2, FileCode, Printer, History, Users, Wrench } from "lucide-react";
|
||||
import { ExecTrace } from "../components/ExecTrace";
|
||||
import { TeamView } from "../components/TeamView";
|
||||
import { OfficeView } from "../components/OfficeView";
|
||||
@@ -9,7 +9,7 @@ import { extractChartBlocks, hasChart } from "../lib/chartspec";
|
||||
import { deriveNodes, isMultiAgent, isReportRun, emptyRun, type RunState } from "../lib/run";
|
||||
import { listRuns, taskEval, runReplay, reportExportUrl, reportFilename, type RunSummary, type EvalResult } from "../lib/api";
|
||||
import { Tabs, Panel, Dot, Badge, Button, EmptyState, useToast, cn, type TabDef } from "../ui";
|
||||
import { saveReportAs } from "../lib/desktop";
|
||||
import { saveReportAs, printReportHtml } from "../lib/desktop";
|
||||
|
||||
type DetailTab = "trace" | "team" | "tools" | "eval";
|
||||
|
||||
@@ -37,6 +37,7 @@ export function RunsView({ run, focusTaskId }: { run: RunState; focusTaskId?: st
|
||||
const [evalRes, setEvalRes] = useState<EvalResult | null>(null);
|
||||
const [tab, setTab] = useState<DetailTab>("trace");
|
||||
const [teamSkin, setTeamSkin] = useState<"office" | "board">("office"); // 团队视图皮肤:卡通办公室 / 卡片看板
|
||||
const previewRef = useRef<HTMLDivElement>(null); // 导出 PDF 要拿已渲染的正文 DOM
|
||||
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
@@ -88,6 +89,17 @@ export function RunsView({ run, focusTaskId }: { run: RunState; focusTaskId?: st
|
||||
toast.push("error", (e as Error).message);
|
||||
}
|
||||
};
|
||||
// 导出 PDF:把预览到的正文(已渲染 HTML)送进打印视图(CJK 零字体依赖,故走前端打印而非后端渲染)。
|
||||
const exportPdf = () => {
|
||||
const html = previewRef.current?.innerHTML;
|
||||
if (!html) {
|
||||
toast.push("error", "暂无报告正文可导出");
|
||||
return;
|
||||
}
|
||||
if (!printReportHtml(curTopic || curId, html)) {
|
||||
toast.push("error", "打印窗口被拦截,请允许弹出窗口后重试");
|
||||
}
|
||||
};
|
||||
const nodes = deriveNodes(cur.exec);
|
||||
// 工具调用面板纳入专家派发:MCP 工具(kind=tool)与多智能体协调里的子智能体派发(kind=agent)都是「调用」。
|
||||
const calls = nodes.filter((n) => n.kind === "tool" || n.kind === "agent");
|
||||
@@ -201,6 +213,9 @@ export function RunsView({ run, focusTaskId }: { run: RunState; focusTaskId?: st
|
||||
<Button icon={FileType2} onClick={() => exportReport("docx")}>
|
||||
Word
|
||||
</Button>
|
||||
<Button variant="ghost" icon={Printer} onClick={exportPdf}>
|
||||
PDF
|
||||
</Button>
|
||||
<Button variant="ghost" icon={FileCode} onClick={() => exportReport("md")}>
|
||||
Markdown
|
||||
</Button>
|
||||
@@ -209,7 +224,9 @@ export function RunsView({ run, focusTaskId }: { run: RunState; focusTaskId?: st
|
||||
}
|
||||
>
|
||||
{cur.output ? (
|
||||
<OutputView output={cur.output} />
|
||||
<div ref={previewRef}>
|
||||
<OutputView output={cur.output} />
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState icon={Activity} title="尚无输出" desc="选择一次运行查看结果;或发起新运行,回复会在这里逐字呈现。" />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user