feat(web): kb 查看原件(复用文件预览弹框)+ 预览层级抬到 modal 之上
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
e0aa8130af
commit
0ceb4c5bd9
|
|
@ -1195,13 +1195,15 @@
|
||||||
padding-bottom 让出 chat-form 高度(--preview-bottom-inset 由 JS 按需写),
|
padding-bottom 让出 chat-form 高度(--preview-bottom-inset 由 JS 按需写),
|
||||||
使居中卡片停在输入区之上、不遮挡;输入区本身由 body.fp-open 抬到遮罩之上继续可用。 */
|
使居中卡片停在输入区之上、不遮挡;输入区本身由 body.fp-open 抬到遮罩之上继续可用。 */
|
||||||
#file-preview-modal {
|
#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);
|
padding-bottom: var(--preview-bottom-inset, 0);
|
||||||
}
|
}
|
||||||
|
/* z=114:预览要能从 kb / skills / memory 等 112 层 modal 内打开并盖在其上
|
||||||
|
(kb「查看原件」),同时低于 app-dialog(130,删除确认仍在预览之上)。 */
|
||||||
/* 预览开启时:仅把输入区上浮成遮罩之上的"悬浮活动条"(实底 + 上向阴影),
|
/* 预览开启时:仅把输入区上浮成遮罩之上的"悬浮活动条"(实底 + 上向阴影),
|
||||||
其余底部区域(左栏入口 / 右栏 / 状态)随整屏遮罩统一压暗,不再是一条通亮的带。 */
|
其余底部区域(左栏入口 / 右栏 / 状态)随整屏遮罩统一压暗,不再是一条通亮的带。 */
|
||||||
body.fp-open #chat-form {
|
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);
|
box-shadow: 0 -10px 28px rgba(0,0,0,.22);
|
||||||
}
|
}
|
||||||
#file-preview-modal .card {
|
#file-preview-modal .card {
|
||||||
|
|
@ -1263,7 +1265,7 @@
|
||||||
#file-preview-modal .body .xlsx-sheet td, #file-preview-modal .body .xlsx-sheet th {
|
#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;
|
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 {
|
#mini-preview-modal .card {
|
||||||
width: min(520px, 92vw); height: min(420px, 72vh);
|
width: min(520px, 92vw); height: min(420px, 72vh);
|
||||||
display: flex; flex-direction: column; position: relative;
|
display: flex; flex-direction: column; position: relative;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { escapeHtml } from "./format.js";
|
||||||
import { renderMd, highlightIn } from "./markdown.js";
|
import { renderMd, highlightIn } from "./markdown.js";
|
||||||
import { dialogConfirm, dialogPrompt, message } from "./dialog.js";
|
import { dialogConfirm, dialogPrompt, message } from "./dialog.js";
|
||||||
import { downloadFile } from "./media.js";
|
import { downloadFile } from "./media.js";
|
||||||
|
import { openFilePreview } from "./preview.js";
|
||||||
|
|
||||||
const PLACEHOLDER = '<div class="sk-empty">← 选一个库查看,或「+ 新建库」</div>';
|
const PLACEHOLDER = '<div class="sk-empty">← 选一个库查看,或「+ 新建库」</div>';
|
||||||
const POLL_MS = 3000;
|
const POLL_MS = 3000;
|
||||||
|
|
@ -121,6 +122,7 @@ function renderDetail(d) {
|
||||||
if (pending.length) {
|
if (pending.length) {
|
||||||
html += `<div class="sk-group-title" style="margin-top:10px;">待入库 (${pending.length})</div>`;
|
html += `<div class="sk-group-title" style="margin-top:10px;">待入库 (${pending.length})</div>`;
|
||||||
html += pending.map((n) => `<div class="kb-pending">${escapeHtml(n)}
|
html += pending.map((n) => `<div class="kb-pending">${escapeHtml(n)}
|
||||||
|
<button class="small kb-src-view" data-src="${escapeHtml(n)}" title="查看原件">查看</button>
|
||||||
<button class="small kb-src-dl" data-src="${escapeHtml(n)}" title="下载原件">下载</button></div>`).join("");
|
<button class="small kb-src-dl" data-src="${escapeHtml(n)}" title="下载原件">下载</button></div>`).join("");
|
||||||
if (!ing.running) {
|
if (!ing.running) {
|
||||||
html += `<div style="padding:6px 0;"><button id="kb-reingest" class="small">重试入库</button></div>`;
|
html += `<div style="padding:6px 0;"><button id="kb-reingest" class="small">重试入库</button></div>`;
|
||||||
|
|
@ -138,7 +140,8 @@ function renderDetail(d) {
|
||||||
<div class="sk-name">${escapeHtml(e.title)}</div>
|
<div class="sk-name">${escapeHtml(e.title)}</div>
|
||||||
<div class="sk-desc">${escapeHtml(e.summary)}${e.keywords ? " | " + escapeHtml(e.keywords) : ""}</div>
|
<div class="sk-desc">${escapeHtml(e.summary)}${e.keywords ? " | " + escapeHtml(e.keywords) : ""}</div>
|
||||||
</div>
|
</div>
|
||||||
${src ? `<button class="small kb-src-dl" data-src="${escapeHtml(src)}" title="下载原件">⬇</button>` : ""}
|
${src ? `<button class="small kb-src-view" data-src="${escapeHtml(src)}" title="查看原件">👁</button>
|
||||||
|
<button class="small kb-src-dl" data-src="${escapeHtml(src)}" title="下载原件">⬇</button>` : ""}
|
||||||
<button class="small danger kb-doc-del" data-doc="${escapeHtml(doc)}" title="删除该篇(含原件)">✕</button>
|
<button class="small danger kb-doc-del" data-doc="${escapeHtml(doc)}" title="删除该篇(含原件)">✕</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
}).join("")
|
}).join("")
|
||||||
|
|
@ -162,7 +165,8 @@ async function showDoc(filename) {
|
||||||
`<div class="sk-d-head"><button id="kb-back" class="small">← 返回</button>
|
`<div class="sk-d-head"><button id="kb-back" class="small">← 返回</button>
|
||||||
<span class="sk-d-name">${escapeHtml(filename)}</span>
|
<span class="sk-d-name">${escapeHtml(filename)}</span>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
${src ? `<button id="kb-doc-src-dl" class="small" data-src="${escapeHtml(src)}">下载原件</button>` : ""}
|
${src ? `<button id="kb-doc-src-view" class="small" data-src="${escapeHtml(src)}">查看原件</button>
|
||||||
|
<button id="kb-doc-src-dl" class="small" data-src="${escapeHtml(src)}">下载原件</button>` : ""}
|
||||||
<button id="kb-doc-md-dl" class="small" data-doc="${escapeHtml(filename)}">下载 Markdown</button></div>` +
|
<button id="kb-doc-md-dl" class="small" data-doc="${escapeHtml(filename)}">下载 Markdown</button></div>` +
|
||||||
`<div class="sk-detail-md">${renderMd(data.content)}</div>`;
|
`<div class="sk-detail-md">${renderMd(data.content)}</div>`;
|
||||||
highlightIn(detail);
|
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-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-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; }
|
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");
|
const srcDl = e.target.closest(".kb-src-dl");
|
||||||
if (srcDl) { downloadFile(kbRel("sources/" + srcDl.getAttribute("data-src"))); return; }
|
if (srcDl) { downloadFile(kbRel("sources/" + srcDl.getAttribute("data-src"))); return; }
|
||||||
if (e.target.id === "kb-reingest") {
|
if (e.target.id === "kb-reingest") {
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,10 @@ async function loadVersion() {
|
||||||
// ───── Esc 关弹窗栈(跨模块协调:chpw/选入/文件预览/小预览)─────
|
// ───── Esc 关弹窗栈(跨模块协调:chpw/选入/文件预览/小预览)─────
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
if (e.key !== "Escape") return;
|
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 ($("chpw-modal").classList.contains("show")) { closeChpwModal(); return; }
|
||||||
if ($("skills-modal").classList.contains("show")) { closeSkillsModal(); return; }
|
if ($("skills-modal").classList.contains("show")) { closeSkillsModal(); return; }
|
||||||
if ($("memory-modal").classList.contains("show")) { closeMemoryModal(); 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 ($("crons-modal").classList.contains("show")) { closeCronsModal(); return; }
|
||||||
if ($("wechat-modal").classList.contains("show")) { closeWechatModal(); return; }
|
if ($("wechat-modal").classList.contains("show")) { closeWechatModal(); return; }
|
||||||
if ($("changelog-modal").classList.contains("show")) { closeChangelogModal(); 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 ($("src-picker-modal").classList.contains("show")) { closeSrcPicker(); return; }
|
||||||
if ($("file-preview-modal").classList.contains("show")) { closeFilePreview(); return; }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue