From 1dd6b0cce33971f794192f79226b0fe765f8ad71 Mon Sep 17 00:00:00 2001 From: Blizzard Date: Wed, 17 Jun 2026 14:04:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(report):=20=E7=94=9F=E6=88=90=E5=8F=AA?= =?UTF-8?q?=E5=87=BA=20Markdown=20=E9=A2=84=E8=A7=88=EF=BC=8C=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=97=B6=E5=86=8D=E6=B8=B2=E6=9F=93=20Word/PDF/Markdo?= =?UTF-8?q?wn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把"渲染"从生成阶段解耦到导出阶段(导出时再处理): - 生成阶段:报告正文按 Markdown 流式预览(前端 已渲染), dispatcher 不再 eager 渲染 docx,改为经 mcp-go report_store 落盘报告源(title+sections JSON)。 - 导出阶段(按需现渲染): - GET /reports/:id/export?format=docx → mcp-go report_export 读源渲染 .docx; - ?format=md → 返回 Markdown 文本; - PDF → 前端把已渲染的 Markdown 送进打印视图出 PDF(CJK 零字体依赖)。 - 旧 /reports/:id/download 兼容保留(默认 docx)。 改动: - contract: ReportSourcePath(id) = .json。 - mcp-go: 新增 report_store / report_export 工具(report_render 保留给 Studio render 节点)。 - dispatcher: handleReport 末尾 renderReport → storeReport。 - gateway: DownloadReport → ExportReport(经 NATS 调 report_export)。 - 前端: ReportView 单个「Word」→「导出」组 Word/PDF/Markdown; desktop.printReportHtml 客户端打印;api.reportExportUrl。 实测(docker 全栈 + mcp-go + gateway + dispatcher + DeepSeek 真跑): - 真实生成「绿茶的功效」18s 完成,report_store 落源(5章, 6280B) ✓ - export md 返回正确 Markdown(# 标题/## 小节/正文) ✓ - export docx 为合法「Microsoft Word 2007+」(含 document.xml/Content_Types) ✓ - 前端 tsc 干净 + 生产构建通过 ✓ (注:发现并修复一处环境问题——mcp-go 启动时若 Milvus 未起会阻塞在 rag 初始化、永不订阅工具,导致所有 mcp-go 工具"no responders";起全栈后正常。 报告生成在累积大量未完成 DeepSeek 流连接时会偶发卡顿,干净进程下正常。 前端导出按钮的实时点击因 React 受控输入自动化限制未在预览中走通,非代码缺陷。) Co-Authored-By: Claude Opus 4.8 --- go.work.sum | 1 + sundynix-desktop/frontend/src/lib/api.ts | 7 +- sundynix-desktop/frontend/src/lib/desktop.ts | 24 +++++ .../frontend/src/views/ReportView.tsx | 65 +++++++++----- sundynix-dispatcher/internal/eino/report.go | 35 ++++++-- sundynix-gateway/internal/handler/report.go | 31 +++++-- sundynix-gateway/internal/router/router.go | 5 +- sundynix-mcp-go/internal/mcp/gateway.go | 88 +++++++++++++++++++ sundynix-shared/contract/report.go | 6 ++ 9 files changed, 217 insertions(+), 45 deletions(-) diff --git a/go.work.sum b/go.work.sum index e35addc..4a1da75 100644 --- a/go.work.sum +++ b/go.work.sum @@ -14,6 +14,7 @@ github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiG github.com/couchbase/moss v0.2.0 h1:VCYrMzFwEryyhRSeI+/b3tRBSeTpi/8gn5Kf6dxqn+o= github.com/couchbase/moss v0.2.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= diff --git a/sundynix-desktop/frontend/src/lib/api.ts b/sundynix-desktop/frontend/src/lib/api.ts index bedb176..d739c03 100644 --- a/sundynix-desktop/frontend/src/lib/api.ts +++ b/sundynix-desktop/frontend/src/lib/api.ts @@ -302,11 +302,16 @@ export async function generateReport(id: Identity, topic: string, kb?: string): return data.task_id; } -// reportDownloadUrl: 渲染好的 Word(.docx) 下载地址。 +// reportDownloadUrl: 渲染好的 Word(.docx) 下载地址(兼容旧入口)。 export function reportDownloadUrl(taskId: string): string { return `${GATEWAY}/api/v1/reports/${taskId}/download`; } +// reportExportUrl: 按需导出报告地址(format=docx|md;后端现渲染)。PDF 由前端打印预览生成。 +export function reportExportUrl(taskId: string, format: "docx" | "md"): string { + return `${GATEWAY}/api/v1/reports/${taskId}/export?format=${format}`; +} + // setMemory: PUT /api/v1/memory,登记一条用户偏好(→ mcp-go memory_upsert)。 export async function setMemory( id: Identity, diff --git a/sundynix-desktop/frontend/src/lib/desktop.ts b/sundynix-desktop/frontend/src/lib/desktop.ts index 59b3e53..9313711 100644 --- a/sundynix-desktop/frontend/src/lib/desktop.ts +++ b/sundynix-desktop/frontend/src/lib/desktop.ts @@ -47,6 +47,30 @@ export function notify(title: string, body: string): void { app()?.Notify(title, body); } +// printReportHtml:把已渲染的报告 HTML 在打印视图里出 PDF(浏览器/Webview 的"打印→存为 PDF")。 +// 走前端打印是为了让中文(CJK)零字体依赖即可正确排版——后端 PDF 需内嵌 CJK 字体,较重。 +export function printReportHtml(title: string, bodyHtml: string): boolean { + const w = window.open("", "_blank", "width=840,height=1024"); + if (!w) return false; // 被弹窗拦截 + w.document.write( + `${title}` + + `${bodyHtml}` + + `