From 0ceb4c5bd98133b5f443f6b2a4552fadf308d512 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 24 Jul 2026 15:38:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20kb=20=E6=9F=A5=E7=9C=8B=E5=8E=9F?= =?UTF-8?q?=E4=BB=B6(=E5=A4=8D=E7=94=A8=E6=96=87=E4=BB=B6=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E5=BC=B9=E6=A1=86)+=20=E9=A2=84=E8=A7=88=E5=B1=82?= =?UTF-8?q?=E7=BA=A7=E6=8A=AC=E5=88=B0=20modal=20=E4=B9=8B=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kb.js: 已入库条目行/单篇页/待入库列表三处加「查看原件」,直接 openFilePreview(.kb 相对路径,与下载同通道 /v1/files/download) - dev.html: file-preview-modal z 90→114(盖过 kb/skills/memory 等 112 层 modal,仍低于 app-dialog 130)、fp-open chat-form 95→115、mini 96→116 - main.js: Esc 关栈顺序同步(小预览→文件预览→各 112 层 modal→选入→新任务) Co-Authored-By: Claude Fable 5 --- web/static/dev.html | 8 +++++--- web/static/js/kb.js | 12 ++++++++++-- web/static/js/main.js | 7 ++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/web/static/dev.html b/web/static/dev.html index d4ca63e..9c7c996 100644 --- a/web/static/dev.html +++ b/web/static/dev.html @@ -1195,13 +1195,15 @@ padding-bottom 让出 chat-form 高度(--preview-bottom-inset 由 JS 按需写), 使居中卡片停在输入区之上、不遮挡;输入区本身由 body.fp-open 抬到遮罩之上继续可用。 */ #file-preview-modal { - background: rgba(0,0,0,0.45); z-index: 90; + background: rgba(0,0,0,0.45); z-index: 114; padding-bottom: var(--preview-bottom-inset, 0); } + /* z=114:预览要能从 kb / skills / memory 等 112 层 modal 内打开并盖在其上 + (kb「查看原件」),同时低于 app-dialog(130,删除确认仍在预览之上)。 */ /* 预览开启时:仅把输入区上浮成遮罩之上的"悬浮活动条"(实底 + 上向阴影), 其余底部区域(左栏入口 / 右栏 / 状态)随整屏遮罩统一压暗,不再是一条通亮的带。 */ body.fp-open #chat-form { - position: relative; z-index: 95; + position: relative; z-index: 115; box-shadow: 0 -10px 28px rgba(0,0,0,.22); } #file-preview-modal .card { @@ -1263,7 +1265,7 @@ #file-preview-modal .body .xlsx-sheet td, #file-preview-modal .body .xlsx-sheet th { border: 1px solid var(--border); padding: 4px 8px; white-space: nowrap; } - #mini-preview-modal { background: rgba(0,0,0,0.18); z-index: 96; align-items: flex-start; justify-content: flex-end; padding: 56px 18px 0 0; } + #mini-preview-modal { background: rgba(0,0,0,0.18); z-index: 116; align-items: flex-start; justify-content: flex-end; padding: 56px 18px 0 0; } #mini-preview-modal .card { width: min(520px, 92vw); height: min(420px, 72vh); display: flex; flex-direction: column; position: relative; diff --git a/web/static/js/kb.js b/web/static/js/kb.js index 82affea..1318f51 100644 --- a/web/static/js/kb.js +++ b/web/static/js/kb.js @@ -9,6 +9,7 @@ import { escapeHtml } from "./format.js"; import { renderMd, highlightIn } from "./markdown.js"; import { dialogConfirm, dialogPrompt, message } from "./dialog.js"; import { downloadFile } from "./media.js"; +import { openFilePreview } from "./preview.js"; const PLACEHOLDER = '
← 选一个库查看,或「+ 新建库」
'; const POLL_MS = 3000; @@ -121,6 +122,7 @@ function renderDetail(d) { if (pending.length) { html += `
待入库 (${pending.length})
`; html += pending.map((n) => `
${escapeHtml(n)} +
`).join(""); if (!ing.running) { html += `
`; @@ -138,7 +140,8 @@ function renderDetail(d) {
${escapeHtml(e.title)}
${escapeHtml(e.summary)}${e.keywords ? " | " + escapeHtml(e.keywords) : ""}
- ${src ? `` : ""} + ${src ? ` + ` : ""} `; }).join("") @@ -162,7 +165,8 @@ async function showDoc(filename) { `
${escapeHtml(filename)} - ${src ? `` : ""} + ${src ? ` + ` : ""}
` + `
${renderMd(data.content)}
`; highlightIn(detail); @@ -214,6 +218,10 @@ $("kb-detail").addEventListener("click", async (e) => { if (e.target.id === "kb-back") { showKb(_current, null); return; } if (e.target.id === "kb-doc-md-dl") { downloadFile(kbRel("docs/" + e.target.getAttribute("data-doc"))); return; } if (e.target.id === "kb-doc-src-dl") { downloadFile(kbRel("sources/" + e.target.getAttribute("data-src"))); return; } + // 查看原件:复用主预览弹框(preview.js,z 114 盖在 kb modal 之上),路径同下载走 .kb 相对路径 + if (e.target.id === "kb-doc-src-view") { openFilePreview(kbRel("sources/" + e.target.getAttribute("data-src"))); return; } + const srcView = e.target.closest(".kb-src-view"); + if (srcView) { openFilePreview(kbRel("sources/" + srcView.getAttribute("data-src"))); return; } const srcDl = e.target.closest(".kb-src-dl"); if (srcDl) { downloadFile(kbRel("sources/" + srcDl.getAttribute("data-src"))); return; } if (e.target.id === "kb-reingest") { diff --git a/web/static/js/main.js b/web/static/js/main.js index b225cb1..ddcb053 100644 --- a/web/static/js/main.js +++ b/web/static/js/main.js @@ -107,7 +107,10 @@ async function loadVersion() { // ───── Esc 关弹窗栈(跨模块协调:chpw/选入/文件预览/小预览)───── document.addEventListener("keydown", (e) => { if (e.key !== "Escape") return; - // 多模态共存:优先关靠前栈顶 — 小预览(z 96)→ 选入(z 95)→ 文件预览(z 90)→ 新任务(z 80) + // 多模态共存:优先关靠前栈顶 — 小预览(z 116)→ 文件预览(z 114,可从 kb 等 + // 112 层 modal 内打开,须先于它们关)→ 各 112 层 modal → 选入(z 95)→ 新任务(z 80) + if ($("mini-preview-modal").classList.contains("show")) { closeMiniPreview(); return; } + if ($("file-preview-modal").classList.contains("show")) { closeFilePreview(); return; } if ($("chpw-modal").classList.contains("show")) { closeChpwModal(); return; } if ($("skills-modal").classList.contains("show")) { closeSkillsModal(); return; } if ($("memory-modal").classList.contains("show")) { closeMemoryModal(); return; } @@ -115,9 +118,7 @@ document.addEventListener("keydown", (e) => { if ($("crons-modal").classList.contains("show")) { closeCronsModal(); return; } if ($("wechat-modal").classList.contains("show")) { closeWechatModal(); return; } if ($("changelog-modal").classList.contains("show")) { closeChangelogModal(); return; } - if ($("mini-preview-modal").classList.contains("show")) { closeMiniPreview(); return; } if ($("src-picker-modal").classList.contains("show")) { closeSrcPicker(); return; } - if ($("file-preview-modal").classList.contains("show")) { closeFilePreview(); return; } });