From 5163ce51a7c61a8ede1653223882aa905e9bb14b Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Mon, 24 Aug 2026 16:22:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20SSE=20Last-Event-ID=20=E6=96=AD?= =?UTF-8?q?=E7=BA=BF=E9=87=8D=E6=94=BE=20+=20GUI=20=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E9=98=B2=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - webui handler: 新增 sseEventRing 环状缓冲区(200条),断线重连按 Last-Event-ID 重放遗漏事件 - GUI app.js: doRenderAll 检测连接表单打开时改走 refreshDataOnly,修复 15s 定时器擦掉用户输入的 bug - 附带 dashboard.html/index.html 前端调整 + handler_sse_test.go 单测 --- cmd/gui/renderer/app.js | 180 +++++++++++++++++++-- cmd/gui/renderer/index.html | 4 + internal/plugins/webui/dashboard.html | 34 ++-- internal/plugins/webui/handler.go | 75 ++++++++- internal/plugins/webui/handler_sse_test.go | 96 +++++++++++ 5 files changed, 365 insertions(+), 24 deletions(-) create mode 100644 internal/plugins/webui/handler_sse_test.go diff --git a/cmd/gui/renderer/app.js b/cmd/gui/renderer/app.js index c211670..df7f9ef 100644 --- a/cmd/gui/renderer/app.js +++ b/cmd/gui/renderer/app.js @@ -43,6 +43,7 @@ const state = { pendingTools: [], eventSource: null, chatFinalIdx: -1, + sseLastEventID: "", // 最近一次 SSE 事件 id,断线重连时随 Last-Event-ID 头回传 lang: localStorage.getItem("ha-lang") || "zh", connections: [], currentConn: null, @@ -325,6 +326,29 @@ function toggleAppearance() { })(); // ===== Utility ===== +// 安全渲染 markdown:marked 转 HTML 后由 DOMPurify 剥离脚本/事件/危险标签。 +// CDN 加载失败时降级为纯转义文本,绝不把未消毒 HTML 直接写入 innerHTML。 +function renderMd(text) { + if (typeof text !== "string") text = String(text || ""); + var html; + if (typeof marked !== "undefined") { + try { html = marked.parse(text); } + catch (e) { html = escHtml(text); } + } else { + html = "
" + escHtml(text) + "
"; + } + if (typeof DOMPurify !== "undefined" && typeof DOMPurify.sanitize === "function") { + try { return DOMPurify.sanitize(html, { USE_PROFILES: { html: true } }); } + catch (e) {} + } + // 兜底:手动删除 + +