feat(前端界面): 合并右侧分组,恢复连续滚动
build.yaml / build (push) Successful in 43s

This commit is contained in:
xiaoqidun committed 2026-10-25 22:25:09 +08:00
1 parent 15c64ed6f2
commit 4573cb942b
3 files changed
+130 -183

No files matched your search

+117 -125
View File
@@ -802,150 +802,142 @@
</section> </section>
<aside class="meta-panel" data-empty="true"> <aside class="meta-panel" data-empty="true">
<div id="metaTabs" class="navigation-tabs"> <div id="metaDocumentPanel">
<button id="documentMetaTab" type="button" data-selected="true">文档</button> <div class="panel-row">
<button id="fontsMetaTab" type="button" data-selected="false" tabindex="-1">字体</button> <div class="panel-title compact">文档</div>
<button id="securityMetaTab" type="button" data-selected="false" tabindex="-1">安全</button> <div class="panel-actions">
</div>
<div id="metaContent" class="meta-content">
<div id="metaDocumentPanel">
<div class="panel-actions meta-document-actions">
<button id="resourceManageButton" class="small-button" type="button" disabled>资源</button> <button id="resourceManageButton" class="small-button" type="button" disabled>资源</button>
<button id="settingsButton" class="small-button" type="button" disabled>配置</button> <button id="settingsButton" class="small-button" type="button" disabled>配置</button>
<button id="invoiceButton" class="small-button" type="button" hidden disabled>发票</button> <button id="invoiceButton" class="small-button" type="button" hidden disabled>发票</button>
<button id="documentManageButton" class="small-button" type="button" hidden>管理</button> <button id="documentManageButton" class="small-button" type="button" hidden>管理</button>
<button id="versionManageButton" class="small-button" type="button" hidden>版本</button> <button id="versionManageButton" class="small-button" type="button" hidden>版本</button>
</div> </div>
<div id="editNotice" class="font-permission-hint" hidden></div> </div>
<div id="documentRow" class="document-row" hidden> <div id="editNotice" class="font-permission-hint" hidden></div>
<select id="documentSelect" class="document-select" title="切换文档"></select> <div id="documentRow" class="document-row" hidden>
</div> <select id="documentSelect" class="document-select" title="切换文档"></select>
<div class="document-info"> </div>
<div class="document-info">
<dl class="meta-list">
<div>
<dt>文件名</dt>
<dd id="metaFile">-</dd>
</div>
<div>
<dt>标题</dt>
<dd id="metaTitle">-</dd>
</div>
<div>
<dt>作者</dt>
<dd id="metaAuthor">-</dd>
</div>
<div hidden>
<dt>主题</dt>
<dd id="metaSubject"></dd>
</div>
<div hidden>
<dt>摘要</dt>
<dd id="metaAbstract"></dd>
</div>
<div hidden>
<dt>关键词</dt>
<dd id="metaKeywords"></dd>
</div>
</dl>
<details><summary>文档属性</summary>
<dl class="meta-list"> <dl class="meta-list">
<div> <div hidden>
<dt>文件名</dt> <dt>创建日期</dt>
<dd id="metaFile">-</dd> <dd id="metaCreationDate"></dd>
</div>
<div>
<dt>标题</dt>
<dd id="metaTitle">-</dd>
</div>
<div>
<dt>作者</dt>
<dd id="metaAuthor">-</dd>
</div> </div>
<div hidden> <div hidden>
<dt>主题</dt> <dt>修改日期</dt>
<dd id="metaSubject"></dd> <dd id="metaModDate"></dd>
</div> </div>
<div hidden> <div hidden>
<dt>摘要</dt> <dt>制作软件</dt>
<dd id="metaAbstract"></dd> <dd id="metaCreator"></dd>
</div> </div>
<div hidden> <div hidden>
<dt>关键词</dt> <dt>软件版本</dt>
<dd id="metaKeywords"></dd> <dd id="metaCreatorVersion"></dd>
</div>
<div hidden>
<dt>文档标识</dt>
<dd id="metaDocId"></dd>
</div>
<div hidden>
<dt>文档用途</dt>
<dd id="metaDocUsage"></dd>
</div>
<div hidden>
<dt>封面路径</dt>
<dd id="metaCover"></dd>
</div> </div>
</dl> </dl>
<details><summary>文档属性</summary>
<dl class="meta-list">
<div hidden>
<dt>创建日期</dt>
<dd id="metaCreationDate"></dd>
</div>
<div hidden>
<dt>修改日期</dt>
<dd id="metaModDate"></dd>
</div>
<div hidden>
<dt>制作软件</dt>
<dd id="metaCreator"></dd>
</div>
<div hidden>
<dt>软件版本</dt>
<dd id="metaCreatorVersion"></dd>
</div>
<div hidden>
<dt>文档标识</dt>
<dd id="metaDocId"></dd>
</div>
<div hidden>
<dt>文档用途</dt>
<dd id="metaDocUsage"></dd>
</div>
<div hidden>
<dt>封面路径</dt>
<dd id="metaCover"></dd>
</div>
</dl>
</details>
<details><summary>扩展属性</summary><dl id="metaCustomData" class="meta-list" hidden></dl></details>
<details><summary>格式信息</summary>
<dl class="meta-list">
<div>
<dt>文档类型</dt>
<dd id="metaType">-</dd>
</div>
<div>
<dt>格式版本</dt>
<dd id="metaVersion">-</dd>
</div>
<div>
<dt>签名数量</dt>
<dd id="metaSignatures">0</dd>
</div>
<div>
<dt>字体数量</dt>
<dd id="metaFonts">0</dd>
</div>
</dl>
</details>
</div>
<details id="conversionNotice" class="conversion-notice" hidden>
<summary>提示</summary>
<div id="conversionWarnings" class="panel-detail"></div>
</details> </details>
<section id="structurePanel" class="structure-panel" hidden> <details><summary>扩展属性</summary><dl id="metaCustomData" class="meta-list" hidden></dl></details>
<div class="panel-row"><div id="structurePanelTitle" class="panel-title compact">结构</div><div class="panel-actions"><span id="structureSummary" class="count-pill">0</span><button id="structureManage" class="small-button" type="button" hidden>管理</button></div></div> <details><summary>格式信息</summary>
<div id="structureList" class="structure-list"></div> <dl class="meta-list">
</section> <div>
</div> <dt>文档类型</dt>
<div id="metaFontsPanel" hidden> <dd id="metaType">-</dd>
<section id="docFontPanel" class="doc-font-panel" hidden>
<div class="panel-row">
<div id="docFontPanelTitle" class="panel-title compact">文档字体</div>
<span id="docFontSummary" class="count-pill">0</span>
</div>
<div id="docFontList" class="doc-font-list"></div>
</section>
<section class="font-panel">
<div class="panel-row">
<div id="fontPanelTitle" class="panel-title compact">可用字体</div>
<div class="panel-actions">
<span id="availableFontSummary" class="count-pill">0</span>
<button id="localFontButton" class="small-button" type="button">系统</button>
<button id="fontAddButton" class="small-button" type="button">添加</button>
<button id="fontDirectoryButton" class="small-button" type="button">目录</button>
</div> </div>
</div> <div>
<div id="fontPermissionHint" class="font-permission-hint" hidden>系统字体未授权</div> <dt>格式版本</dt>
<div id="fontList" class="font-list"></div> <dd id="metaVersion">-</dd>
</section> </div>
</div> <div>
<div id="metaSecurityPanel" hidden> <dt>签名数量</dt>
<section id="securityPanel" class="security-panel" hidden> <dd id="metaSignatures">0</dd>
<div class="panel-row"><div id="securityPanelTitle" class="panel-title compact">安全</div><div class="panel-actions"><button id="encryptSaveButton" class="small-button" type="button" disabled>加密</button><button id="signButton" class="small-button" type="button" disabled>签章</button><button id="verifyButton" class="small-button" type="button" disabled>验签</button></div></div> </div>
<dl class="meta-list"><div><dt>加密</dt><dd id="securityEncryption">未加密</dd></div><div id="securitySchemeRow" hidden><dt>方式</dt><dd id="securityScheme"></dd></div><div id="securityMethodRow" hidden><dt>算法</dt><dd id="securityMethod"></dd></div></dl> <div>
</section> <dt>字体数量</dt>
<section id="signaturePanel" class="signature-panel" hidden> <dd id="metaFonts">0</dd>
<div class="panel-row"> </div>
<div id="signaturePanelTitle" class="panel-title compact">签名</div> </dl>
<span id="signatureSummary" class="count-pill">0</span> </details>
</div>
<div id="signatureList" class="signature-list"></div>
</section>
</div> </div>
<details id="conversionNotice" class="conversion-notice" hidden>
<summary>提示</summary>
<div id="conversionWarnings" class="panel-detail"></div>
</details>
<section id="structurePanel" class="structure-panel" hidden>
<div class="panel-row"><div id="structurePanelTitle" class="panel-title compact">结构</div><div class="panel-actions"><span id="structureSummary" class="count-pill">0</span><button id="structureManage" class="small-button" type="button" hidden>管理</button></div></div>
<div id="structureList" class="structure-list"></div>
</section>
</div> </div>
<section id="securityPanel" class="security-panel" hidden>
<div class="panel-row"><div id="securityPanelTitle" class="panel-title compact">安全</div><div class="panel-actions"><button id="encryptSaveButton" class="small-button" type="button" disabled>加密</button><button id="signButton" class="small-button" type="button" disabled>签章</button><button id="verifyButton" class="small-button" type="button" disabled>验签</button></div></div>
<dl class="meta-list"><div><dt>加密</dt><dd id="securityEncryption">未加密</dd></div><div id="securitySchemeRow" hidden><dt>方式</dt><dd id="securityScheme"></dd></div><div id="securityMethodRow" hidden><dt>算法</dt><dd id="securityMethod"></dd></div></dl>
</section>
<section id="signaturePanel" class="signature-panel" hidden>
<div class="panel-row">
<div id="signaturePanelTitle" class="panel-title compact">签名</div>
<span id="signatureSummary" class="count-pill">0</span>
</div>
<div id="signatureList" class="signature-list"></div>
</section>
<section id="docFontPanel" class="doc-font-panel" hidden>
<div class="panel-row">
<div id="docFontPanelTitle" class="panel-title compact">文档字体</div>
<span id="docFontSummary" class="count-pill">0</span>
</div>
<div id="docFontList" class="doc-font-list"></div>
</section>
<section class="font-panel">
<div class="panel-row">
<div id="fontPanelTitle" class="panel-title compact">可用字体</div>
<div class="panel-actions">
<span id="availableFontSummary" class="count-pill">0</span>
<button id="localFontButton" class="small-button" type="button">系统</button>
<button id="fontAddButton" class="small-button" type="button">添加</button>
<button id="fontDirectoryButton" class="small-button" type="button">目录</button>
</div>
</div>
<div id="fontPermissionHint" class="font-permission-hint" hidden>系统字体未授权</div>
<div id="fontList" class="font-list"></div>
</section>
</aside> </aside>
</main> </main>
+6 -16
View File
@@ -1839,7 +1839,7 @@ body[data-hide-meta] .meta-panel {
.search-results, .search-results,
.editor-toolbar, .editor-toolbar,
.document-list, .document-list,
.meta-content { .meta-panel {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: var(--line-strong) transparent; scrollbar-color: var(--line-strong) transparent;
} }
@@ -1855,15 +1855,13 @@ body[data-hide-meta] .meta-panel {
line-height: 1.5; line-height: 1.5;
} }
.page-list-panel, .page-list-panel {
.meta-panel {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
} }
.navigation-content, .navigation-content {
.meta-content {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
overflow: auto; overflow: auto;
@@ -1887,19 +1885,11 @@ body[data-hide-meta] .meta-panel {
border-left: 1px solid var(--line); border-left: 1px solid var(--line);
} }
.meta-document-actions { .meta-panel[data-empty="true"] #metaDocumentPanel {
justify-content: flex-start;
margin-bottom: 12px;
}
.meta-panel[data-empty="true"] #metaDocumentPanel,
.meta-panel[data-empty="true"] #metaSecurityPanel {
display: none; display: none;
} }
#metaFontsPanel > .doc-font-panel, .meta-panel[data-empty="true"] > .font-panel {
#metaFontsPanel > .doc-font-panel[hidden] + .font-panel,
#metaSecurityPanel > .security-panel {
margin-top: 0; margin-top: 0;
padding-top: 0; padding-top: 0;
border-top: 0; border-top: 0;
@@ -4588,7 +4578,7 @@ audio.page-media {
} }
body[data-hide-meta] .meta-panel { body[data-hide-meta] .meta-panel {
display: flex; display: block;
} }
body[data-hide-pages] .page-list-panel { body[data-hide-pages] .page-list-panel {
+7 -42
View File
@@ -183,8 +183,6 @@ function createDocumentState() {
encryptionChanged: false, encryptionChanged: false,
showPages: !COMPACT_LAYOUT.matches, showPages: !COMPACT_LAYOUT.matches,
showMeta: !COMPACT_LAYOUT.matches, showMeta: !COMPACT_LAYOUT.matches,
metaTab: "document",
metaScroll: {document: 0, fonts: 0, security: 0},
}; };
} }
@@ -594,14 +592,6 @@ const el = {
searchNext: document.querySelector("#searchNext"), searchNext: document.querySelector("#searchNext"),
searchResults: document.querySelector("#searchResults"), searchResults: document.querySelector("#searchResults"),
metaPanel: document.querySelector(".meta-panel"), metaPanel: document.querySelector(".meta-panel"),
metaTabs: document.querySelector("#metaTabs"),
metaContent: document.querySelector("#metaContent"),
documentMetaTab: document.querySelector("#documentMetaTab"),
fontsMetaTab: document.querySelector("#fontsMetaTab"),
securityMetaTab: document.querySelector("#securityMetaTab"),
metaDocumentPanel: document.querySelector("#metaDocumentPanel"),
metaFontsPanel: document.querySelector("#metaFontsPanel"),
metaSecurityPanel: document.querySelector("#metaSecurityPanel"),
renderVectorButton: document.querySelector("#renderVectorButton"), renderVectorButton: document.querySelector("#renderVectorButton"),
renderRasterButton: document.querySelector("#renderRasterButton"), renderRasterButton: document.querySelector("#renderRasterButton"),
refreshAppButton: document.querySelector("#refreshAppButton"), refreshAppButton: document.querySelector("#refreshAppButton"),
@@ -1746,23 +1736,17 @@ document.querySelector("#objectActionsButton").addEventListener("click", async (
}); });
el.outlinesTab.addEventListener("click", () => showNavigation(el.outlinesTab)); el.outlinesTab.addEventListener("click", () => showNavigation(el.outlinesTab));
el.searchTab.addEventListener("click", focusSearch); el.searchTab.addEventListener("click", focusSearch);
el.documentMetaTab.addEventListener("click", () => showMetaSection(el.documentMetaTab)); el.navigationTabs.addEventListener("keydown", (event) => {
el.fontsMetaTab.addEventListener("click", () => showMetaSection(el.fontsMetaTab));
el.securityMetaTab.addEventListener("click", () => showMetaSection(el.securityMetaTab));
for (const [container, buttons, show] of [
[el.navigationTabs, [el.pagesTab, el.outlinesTab, el.annotationsTab, el.searchTab], showNavigation],
[el.metaTabs, [el.documentMetaTab, el.fontsMetaTab, el.securityMetaTab], showMetaSection],
]) container.addEventListener("keydown", (event) => {
if (event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { if (event.isComposing || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
return; return;
} }
if (["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) { if (["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) {
event.preventDefault(); event.preventDefault();
const tabs = buttons.filter((tab) => !tab.hidden); const tabs = [el.pagesTab, el.outlinesTab, el.annotationsTab, el.searchTab].filter((tab) => !tab.hidden);
const current = tabs.indexOf(event.target); const current = tabs.indexOf(event.target);
const index = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 const index = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1
: (current + (event.key === "ArrowRight" ? 1 : -1) + tabs.length) % tabs.length; : (current + (event.key === "ArrowRight" ? 1 : -1) + tabs.length) % tabs.length;
show(tabs[index]); showNavigation(tabs[index]);
tabs[index].focus({ preventScroll: true }); tabs[index].focus({ preventScroll: true });
} }
}); });
@@ -2798,9 +2782,8 @@ function detachDocumentView() {
window.clearTimeout(wasmRecoveryTimer); window.clearTimeout(wasmRecoveryTimer);
wasmRecoveryTimer = 0; wasmRecoveryTimer = 0;
const selection = canvasEditor.selected; const selection = canvasEditor.selected;
state.metaScroll[state.metaTab] = el.metaContent.scrollTop;
tab.view = { anchor: state.doc ? scaleAnchor() : null, navigation: el.navigationTabs.querySelector('[data-selected="true"]'), tab.view = { anchor: state.doc ? scaleAnchor() : null, navigation: el.navigationTabs.querySelector('[data-selected="true"]'),
navigationTop: el.navigationContent.scrollTop, tool: canvasEditor.tool, navigationTop: el.navigationContent.scrollTop, metaTop: el.metaPanel.scrollTop, tool: canvasEditor.tool,
selection: selection ? {index: selection.index, ids: (selection.items || [selection]).map(item => item.id)} : canvasEditor.pendingSelection, selection: selection ? {index: selection.index, ids: (selection.items || [selection]).map(item => item.id)} : canvasEditor.pendingSelection,
richClipboard: canvasEditor.richClipboard, search: el.searchInput.value }; richClipboard: canvasEditor.richClipboard, search: el.searchInput.value };
tab.view.searchStatus = state.searchRunning ? "搜索已暂停" : el.searchStatus.textContent; tab.view.searchStatus = state.searchRunning ? "搜索已暂停" : el.searchStatus.textContent;
@@ -2971,7 +2954,7 @@ async function mountDocumentTab(tab) {
} }
renderFontList(); renderFontList();
updateFontSummary(); updateFontSummary();
renderMetaSections(); el.metaPanel.scrollTop = tab.view?.metaTop || 0;
updateControls(); updateControls();
tab.controlsPending = false; tab.controlsPending = false;
setStatus(tab.status); setStatus(tab.status);
@@ -6535,10 +6518,8 @@ async function openDocument(options = {}) {
el.viewerPanel.scrollTop = 0; el.viewerPanel.scrollTop = 0;
el.navigationContent.scrollLeft = 0; el.navigationContent.scrollLeft = 0;
el.navigationContent.scrollTop = 0; el.navigationContent.scrollTop = 0;
state.metaTab = "document"; el.metaPanel.scrollLeft = 0;
state.metaScroll = {document: 0, fonts: 0, security: 0}; el.metaPanel.scrollTop = 0;
el.metaContent.scrollLeft = 0;
renderMetaSections();
} }
applyFit(false); applyFit(false);
if (options.keepPreview) { if (options.keepPreview) {
@@ -11638,22 +11619,6 @@ function focusSearch() {
el.searchInput.select(); el.searchInput.select();
} }
function showMetaSection(selected) {
state.metaScroll[state.metaTab] = el.metaContent.scrollTop;
state.metaTab = selected === el.securityMetaTab ? "security" : selected === el.fontsMetaTab ? "fonts" : "document";
renderMetaSections();
}
function renderMetaSections() {
for (const [tab, panel, name] of [[el.documentMetaTab, el.metaDocumentPanel, "document"], [el.fontsMetaTab, el.metaFontsPanel, "fonts"], [el.securityMetaTab, el.metaSecurityPanel, "security"]]) {
const active = name === state.metaTab;
panel.hidden = !active;
tab.setAttribute("data-selected", String(active));
tab.tabIndex = active ? 0 : -1;
}
el.metaContent.scrollTop = state.metaScroll[state.metaTab];
}
function showNavigation(selected) { function showNavigation(selected) {
const scrollTop = el.navigationContent.scrollTop; const scrollTop = el.navigationContent.scrollTop;
for (const [tab, panel] of [[el.pagesTab, el.pageList], [el.outlinesTab, el.outlineList], [el.annotationsTab, el.annotationsPanel], [el.searchTab, el.searchPanel]]) { for (const [tab, panel] of [[el.pagesTab, el.pageList], [el.outlinesTab, el.outlineList], [el.annotationsTab, el.annotationsPanel], [el.searchTab, el.searchPanel]]) {