feat: add evidence search and stabilize pdf previews

- add document evidence parsing/search/open routes, Hermes tool wiring, local index settings/status, and the document-evidence skill plus design notes
- fix PDF resource tabs by rendering PDFs inline with pdf.js canvases instead of iframe preview pages, release PDF documents on close, and document the fourth-PDF stall bug
- keep PDF preview at 2x rendering while removing the previous lazy-load/placeholder direction, and make dev:hot bind loopback defaults externally reachable

Verification:
- node --check rust/crates/mnote-web/browser/document-resource-tab-runtime.js
- node scripts/task-dev-hot-plan-test.js
- cargo test -p mnote-web --manifest-path rust/Cargo.toml pdf_preview_page_does_not_render_visible_toolbar
- cargo test -p mnote-web --manifest-path rust/Cargo.toml document_shell_returns_page_aggregate_snapshot
- cargo build -p mnote-web --manifest-path rust/Cargo.toml
- browser smoke: sequentially opened the four tea_seed_oil_cosmetic PDFs; fourth PDF rendered 15/15 canvases, iframeCount=0, browser errors=0
This commit is contained in:
lix-2026
2026-06-04 18:51:16 +08:00
parent 9f4b5c4d48
commit 627213dc01
51 changed files with 15960 additions and 1844 deletions
+201
View File
@@ -149,6 +149,7 @@ a:hover {
.material-symbols-outlined[data-icon="tag"]::before { content: "#"; }
.material-symbols-outlined[data-icon="edit"]::before { content: "✎"; }
.material-symbols-outlined[data-icon="add"]::before { content: "+"; }
.material-symbols-outlined[data-icon="manage_search"]::before { content: "⌕"; }
.material-symbols-outlined[data-icon="subdirectory_arrow_right"]::before { content: "↳"; }
.material-symbols-filled {
@@ -158,6 +159,7 @@ a:hover {
/* 本地 SVG mask 图标,避免 Google Material Symbols 字体未加载时露出英文图标名。 */
.material-symbols-outlined[data-icon]::before { content: ""; }
.material-symbols-outlined[data-icon="search"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.8 18a7.2 7.2 0 1 1 0-14.4 7.2 7.2 0 0 1 0 14.4Z' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='m16 16 4.2 4.2' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="manage_search"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 17.5a6.5 6.5 0 1 1 0-13 6.5 6.5 0 0 1 0 13Z' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='m15.5 15.5 4 4M8 8.5h5M8 11h5M8 13.5h3' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="account_tree"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 6h4v4H6zM14 4h4v4h-4zM14 16h4v4h-4z' fill='none' stroke='black' stroke-width='1.8'/%3E%3Cpath d='M10 8h2a2 2 0 0 0 2-2M10 8h2a2 2 0 0 1 2 2v8' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="bolt"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13 2 4.5 13h6L9 22l10.5-13h-6z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="help"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='9' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M9.8 9a2.4 2.4 0 0 1 4.6 1.1c0 1.7-1.7 2-2.2 3.1' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Ccircle cx='12' cy='17' r='1.1' fill='black'/%3E%3C/svg%3E"); }
@@ -2909,6 +2911,29 @@ body {
padding: 28px;
}
.mnote-resource-tab-image-shell {
position: relative;
min-height: calc(100vh - 80px);
overflow: auto;
background: #FFF;
}
.mnote-resource-tab-bbox-highlight {
position: absolute;
border: 2px solid rgba(37, 99, 235, 0.9);
background: rgba(37, 99, 235, 0.16);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9);
pointer-events: none;
z-index: 2;
}
.editor-surface .ProseMirror [data-mnote-evidence-text-highlight="true"],
.mnote-resource-tab-text-shell [data-mnote-evidence-text-highlight="true"] {
outline: 2px solid rgba(37, 99, 235, 0.9);
outline-offset: 3px;
background: rgba(37, 99, 235, 0.1);
}
.mnote-resource-tab-text-shell {
padding: 34px 48px;
}
@@ -3546,6 +3571,40 @@ body {
box-shadow: 0 18px 48px rgba(27, 28, 28, 0.12);
}
.mnote-settings-panel-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.mnote-settings-panel-head strong {
color: #1B1C1C;
font-size: 14px;
line-height: 20px;
}
.mnote-settings-panel-close {
width: 28px;
height: 28px;
border: 0;
border-radius: 6px;
background: transparent;
color: #8B8782;
cursor: pointer;
font-size: 18px;
line-height: 1;
}
.mnote-settings-panel-close:hover {
background: #F4F3F3;
color: #1B1C1C;
}
.mnote-local-index-settings-panel {
width: min(386px, calc(100vw - 24px));
}
.wolai-page-settings-tabs {
display: flex;
gap: 6px;
@@ -3609,6 +3668,148 @@ body {
gap: 6px;
}
.wolai-page-settings-index-range-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.wolai-page-settings-index-range-row {
display: grid;
grid-template-columns: 12px minmax(0, 1fr) 28px;
align-items: center;
gap: 8px;
}
.wolai-page-settings-index-status-dot {
width: 9px;
height: 9px;
border-radius: 999px;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9), 0 0 0 3px rgba(27, 28, 28, 0.08);
}
.wolai-page-settings-index-status-dot[data-index-status="indexed"] {
background: #22C55E;
}
.wolai-page-settings-index-status-dot[data-index-status="indexing"] {
background: #F59E0B;
}
.wolai-page-settings-index-status-dot[data-index-status="fault"] {
background: #EF4444;
}
.wolai-page-settings-index-path {
width: 100%;
min-width: 0;
height: 32px;
border: 1px solid #E2DFDA;
border-radius: 6px;
padding: 0 9px;
background: #FFFFFF;
color: #1B1C1C;
font: 12px/18px "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
}
.wolai-page-settings-index-path:disabled {
background: #F7F6F4;
color: #A19D97;
}
.wolai-page-settings-index-remove,
.wolai-page-settings-index-add {
border: 1px solid #D8D4CE;
border-radius: 6px;
background: #FFFFFF;
color: #1B1C1C;
cursor: pointer;
font-size: 12px;
}
.wolai-page-settings-index-remove {
width: 28px;
height: 28px;
padding: 0;
font-size: 16px;
line-height: 1;
}
.wolai-page-settings-index-add {
width: fit-content;
min-height: 30px;
padding: 5px 10px;
}
.wolai-page-settings-index-remove:hover:not(:disabled),
.wolai-page-settings-index-add:hover:not(:disabled) {
background: #F4F3F3;
}
.wolai-page-settings-index-remove:disabled,
.wolai-page-settings-index-add:disabled {
cursor: default;
color: #A19D97;
background: #F7F6F4;
}
.wolai-page-settings-index-schedule {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(96px, .7fr);
gap: 8px;
}
.wolai-page-settings-index-schedule label {
display: flex;
min-width: 0;
flex-direction: column;
gap: 4px;
color: #8B8782;
font-size: 12px;
line-height: 16px;
}
.wolai-page-settings-index-schedule select,
.wolai-page-settings-index-schedule input[type="time"],
.wolai-page-settings-index-schedule input[type="date"] {
width: 100%;
min-height: 30px;
border: 1px solid #E2DFDA;
border-radius: 6px;
padding: 4px 8px;
background: #FFFFFF;
color: #1B1C1C;
font-size: 12px;
}
.wolai-page-settings-index-inline {
grid-column: 1 / -1;
flex-direction: row !important;
align-items: center;
}
.wolai-page-settings-index-inline input {
width: 14px;
height: 14px;
}
.wolai-page-settings-index-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.wolai-page-settings-index-actions button {
min-height: 30px;
border: 1px solid #D8D4CE;
border-radius: 6px;
padding: 5px 10px;
background: #FFFFFF;
color: #1B1C1C;
cursor: pointer;
font-size: 12px;
}
.wolai-page-settings-index-row,
.wolai-page-settings-index-empty {
padding: 8px 10px;