From 1c15e46ad6f059f48fdf35dbf88082448edbfe7b Mon Sep 17 00:00:00 2001 From: nanhaoluo <3075912108@qq.com> Date: Sun, 25 Jan 2026 01:53:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20Mermaid=20?= =?UTF-8?q?=E5=85=A8=E5=B1=8F=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在工具栏添加全屏按钮(⛶ 图标) - 实现全屏模式进入和退出功能 - 全屏模式下保持缩放和拖拽功能可用 - 支持 ESC 键退出全屏 - 退出全屏时恢复图表原始状态(缩放级别和滚动位置) - 全屏模式下禁用页面滚动 - 添加全屏按钮激活状态样式 - 在清理函数中添加全屏事件监听器清理 - 全屏模式下工具栏始终可见,背景更明显 - 全屏容器占满整个视口,居中显示图表 需求:14.1, 14.2, 14.3, 14.4, 14.5 --- .kiro/specs/pjax-lazyload-fix/tasks.md | 8 +- argontheme.js | 119 +++++++++++++++++++++++++ style.css | 55 ++++++++++++ 3 files changed, 178 insertions(+), 4 deletions(-) diff --git a/.kiro/specs/pjax-lazyload-fix/tasks.md b/.kiro/specs/pjax-lazyload-fix/tasks.md index 90b3209..0ff937d 100644 --- a/.kiro/specs/pjax-lazyload-fix/tasks.md +++ b/.kiro/specs/pjax-lazyload-fix/tasks.md @@ -54,10 +54,10 @@ ### 阶段 3: Mermaid 高级功能 -- [ ] 8. 实现 Mermaid 全屏模式 - - [ ] 8.1 添加全屏按钮 _需求:14.1_ - - [ ] 8.2 全屏模式功能保持 _需求:14.2, 14.3_ - - [ ] 8.3 全屏模式退出(ESC 键) _需求:14.4, 14.5_ +- [x] 8. 实现 Mermaid 全屏模式 + - [x] 8.1 添加全屏按钮 _需求:14.1_ + - [x] 8.2 全屏模式功能保持 _需求:14.2, 14.3_ + - [x] 8.3 全屏模式退出(ESC 键) _需求:14.4, 14.5_ - [ ] 9. 实现 Mermaid 导出功能 - [ ] 9.1 添加导出按钮和菜单 _需求:15.1_ diff --git a/argontheme.js b/argontheme.js index 01ce2c6..4dca0d7 100644 --- a/argontheme.js +++ b/argontheme.js @@ -2900,6 +2900,11 @@ function cleanupMermaidInstances() { const newToolbar = toolbar.cloneNode(true); toolbar.parentNode.replaceChild(newToolbar, toolbar); } + + // 清理全屏模式 + if (container._fullscreenCleanup) { + container._fullscreenCleanup(); + } }); ArgonDebug.log('Mermaid 实例已清理'); @@ -5682,6 +5687,7 @@ void 0; inner.appendChild(svg); // 创建缩放控制 + // 需求 14.1: 添加全屏按钮 const controls = document.createElement('div'); controls.className = 'mermaid-zoom-controls'; controls.innerHTML = ` @@ -5689,6 +5695,7 @@ void 0; 100% + `; container.appendChild(controls); @@ -5754,6 +5761,7 @@ void 0; }; // 绑定按钮事件 + // 需求 14.1, 14.2, 14.3: 全屏按钮功能 controls.addEventListener('click', (e) => { const btn = e.target.closest('.mermaid-zoom-btn'); if (!btn || btn.disabled) return; // 忽略禁用的按钮 @@ -5769,6 +5777,9 @@ void 0; } else if (action === 'zoom-reset') { scale = 1; updateZoom(true); // 重置使用平滑过渡 + } else if (action === 'fullscreen') { + // 需求 14.1: 点击全屏按钮 + toggleFullscreen(); } }); @@ -5932,6 +5943,114 @@ void 0; }, 50); }); + // ========================================================================== + // 需求 14: Mermaid 全屏模式 + // ========================================================================== + + // 全屏状态 + let isFullscreen = false; + let savedScale = 1; + let savedScrollLeft = 0; + let savedScrollTop = 0; + + /** + * 切换全屏模式 + * 需求 14.1: 点击全屏按钮将图表全屏显示 + * 需求 14.2, 14.3: 全屏模式下保持缩放和拖拽功能可用 + * 需求 14.5: 退出全屏恢复图表原始状态 + */ + const toggleFullscreen = () => { + if (!isFullscreen) { + // 进入全屏 + enterFullscreen(); + } else { + // 退出全屏 + exitFullscreen(); + } + }; + + /** + * 进入全屏模式 + */ + const enterFullscreen = () => { + // 保存当前状态 + savedScale = scale; + savedScrollLeft = container.scrollLeft; + savedScrollTop = container.scrollTop; + + // 添加全屏类 + container.classList.add('mermaid-fullscreen'); + isFullscreen = true; + + // 更新全屏按钮 + const fullscreenBtn = controls.querySelector('[data-action="fullscreen"]'); + if (fullscreenBtn) { + fullscreenBtn.textContent = '⛶'; + fullscreenBtn.title = '退出全屏'; + fullscreenBtn.classList.add('active'); + } + + // 需求 14.3: 全屏模式下显示退出全屏按钮(已在工具栏中) + // 工具栏在全屏模式下仍然可见 + + // 禁用页面滚动 + document.body.style.overflow = 'hidden'; + + this.logDebug('进入全屏模式'); + }; + + /** + * 退出全屏模式 + * 需求 14.5: 恢复图表原始状态(缩放级别和位置) + */ + const exitFullscreen = () => { + // 移除全屏类 + container.classList.remove('mermaid-fullscreen'); + isFullscreen = false; + + // 更新全屏按钮 + const fullscreenBtn = controls.querySelector('[data-action="fullscreen"]'); + if (fullscreenBtn) { + fullscreenBtn.textContent = '⛶'; + fullscreenBtn.title = '全屏'; + fullscreenBtn.classList.remove('active'); + } + + // 恢复原始状态 + scale = savedScale; + updateZoom(false); + + // 恢复滚动位置 + setTimeout(() => { + container.scrollLeft = savedScrollLeft; + container.scrollTop = savedScrollTop; + }, 50); + + // 恢复页面滚动 + document.body.style.overflow = ''; + + this.logDebug('退出全屏模式'); + }; + + // 需求 14.4: 按 ESC 键退出全屏模式 + const handleEscKey = (e) => { + if (e.key === 'Escape' && isFullscreen) { + exitFullscreen(); + } + }; + + // 绑定 ESC 键事件 + document.addEventListener('keydown', handleEscKey); + + // 清理函数(在容器销毁时调用) + container.dataset.cleanupFullscreen = 'registered'; + container._fullscreenCleanup = () => { + document.removeEventListener('keydown', handleEscKey); + if (isFullscreen) { + exitFullscreen(); + } + }; + // ========================================================================== // 需求 16.2-16.4: 移动端触摸手势支持 // ========================================================================== diff --git a/style.css b/style.css index 8c5a80e..87401db 100644 --- a/style.css +++ b/style.css @@ -1135,6 +1135,61 @@ html.darkmode .mermaid-hint { -ms-user-select: none; } +/* 需求 14: Mermaid 全屏模式样式 */ +.mermaid-fullscreen { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + width: 100vw !important; + height: 100vh !important; + margin: 0 !important; + padding: 20px !important; + z-index: 99999 !important; + background: var(--color-foreground) !important; + border-radius: 0 !important; + box-shadow: none !important; + overflow: auto !important; +} + +html.darkmode .mermaid-fullscreen { + background: var(--color-widgets) !important; +} + +/* 全屏模式下的工具栏 */ +.mermaid-fullscreen .mermaid-zoom-controls { + opacity: 1; + transform: translateY(0); + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15); +} + +html.darkmode .mermaid-fullscreen .mermaid-zoom-controls { + background: rgba(30, 30, 30, 0.95); + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5); +} + +/* 全屏按钮激活状态 */ +.mermaid-zoom-btn[data-action="fullscreen"].active { + background: rgba(94, 114, 228, 0.2); + color: var(--themecolor); +} + +/* 全屏模式下的内部容器 */ +.mermaid-fullscreen .mermaid-container-inner { + max-height: calc(100vh - 100px); + display: flex; + align-items: center; + justify-content: center; +} + +/* 全屏模式下的提示文本 */ +.mermaid-fullscreen .mermaid-hint { + opacity: 1; + bottom: 20px; +} + /* Mermaid 淡入动画 */ @keyframes mermaidFadeIn { from {