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; }
});