admincjy 1 месяц назад
Родитель
Сommit
b1ac3e59b3
3 измененных файлов с 193 добавлено и 1 удалено
  1. 103 0
      public/css/style.css
  2. 78 1
      public/js/reader.js
  3. 12 0
      public/reader.html

+ 103 - 0
public/css/style.css

@@ -709,6 +709,80 @@ body {
     border: 0;
 }
 
+/* ==================== 文档导航(上一页/下一页) ==================== */
+.doc-navigation {
+    display: flex;
+    justify-content: space-between;
+    gap: 20px;
+    margin-top: 60px;
+    padding: 40px 0;
+    border-top: 2px solid var(--border-color);
+}
+
+.nav-prev,
+.nav-next {
+    flex: 0 0 calc(50% - 10px);
+    display: flex;
+    flex-direction: column;
+    padding: 20px 24px;
+    background: var(--sidebar-bg);
+    border: 2px solid var(--border-color);
+    border-radius: 12px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    min-height: 100px;
+    justify-content: center;
+}
+
+.nav-prev:hover,
+.nav-next:hover {
+    border-color: var(--primary-color);
+    background: white;
+    transform: translateY(-2px);
+    box-shadow: var(--shadow-lg);
+}
+
+.nav-label {
+    font-size: 0.85rem;
+    color: #656d76;
+    font-weight: 500;
+    margin-bottom: 8px;
+}
+
+.nav-prev .nav-label {
+    text-align: left;
+}
+
+.nav-next .nav-label {
+    text-align: right;
+}
+
+.nav-doc-name {
+    font-size: 1.1rem;
+    font-weight: 600;
+    color: var(--text-color);
+    line-height: 1.4;
+    word-wrap: break-word;
+}
+
+.nav-prev .nav-doc-name {
+    text-align: left;
+}
+
+.nav-next .nav-doc-name {
+    text-align: right;
+}
+
+/* 只有下一页时(首页),下一页按钮固定在右侧 */
+.doc-navigation.has-next-only {
+    justify-content: flex-end;
+}
+
+/* 只有上一页时(末页),上一页按钮固定在左侧 */
+.doc-navigation.has-prev-only {
+    justify-content: flex-start;
+}
+
 /* ==================== 加载和错误状态 ==================== */
 .loading {
     display: flex;
@@ -886,6 +960,35 @@ body {
         padding: 12px;
         font-size: 80%;
     }
+
+    /* 文档导航(上一页/下一页)移动端样式 */
+    .doc-navigation {
+        flex-direction: column;
+        gap: 16px;
+        margin-top: 40px;
+        padding: 30px 0;
+    }
+
+    /* 移动端垂直布局,始终从上到下排列 */
+    .doc-navigation.has-next-only,
+    .doc-navigation.has-prev-only {
+        justify-content: flex-start;
+    }
+
+    .nav-prev,
+    .nav-next {
+        flex: 1 1 auto;
+        min-height: 80px;
+        padding: 16px 20px;
+    }
+
+    .nav-label {
+        font-size: 0.8rem;
+    }
+
+    .nav-doc-name {
+        font-size: 1rem;
+    }
 }
 
 /* 悬浮操作按钮(通用样式) */

+ 78 - 1
public/js/reader.js

@@ -16,7 +16,9 @@ const DOM = {
     editBtn: null,
     editorContainer: null,
     markdownEditor: null,
-    editorDocName: null
+    editorDocName: null,
+    navPrev: null,
+    navNext: null
 };
 
 // 配置 marked
@@ -159,6 +161,9 @@ async function loadDocument(docName, scrollToText = null) {
         // 生成 TOC
         generateTOC();
 
+        // 更新文档导航(上一页/下一页)
+        updateDocNavigation();
+
         // 更新活动文档 - 使用 toggle 优化
         if (DOM.docNav) {
             const navItems = DOM.docNav.querySelectorAll('.nav-item');
@@ -272,6 +277,78 @@ function updateURL(category, doc) {
     window.history.pushState({}, '', url);
 }
 
+// 更新文档导航(上一页/下一页)
+function updateDocNavigation() {
+    // 缓存 DOM 元素
+    if (!DOM.navPrev) DOM.navPrev = document.getElementById('nav-prev');
+    if (!DOM.navNext) DOM.navNext = document.getElementById('nav-next');
+
+    if (!DOM.navPrev || !DOM.navNext || docList.length === 0) return;
+
+    const docNavigation = document.getElementById('doc-navigation');
+    if (!docNavigation) return;
+
+    // 找到当前文档在列表中的索引
+    const currentIndex = docList.findIndex(doc => doc.name === currentDoc);
+
+    if (currentIndex === -1) {
+        DOM.navPrev.style.display = 'none';
+        DOM.navNext.style.display = 'none';
+        docNavigation.className = 'doc-navigation';
+        return;
+    }
+
+    const hasPrev = currentIndex > 0;
+    const hasNext = currentIndex < docList.length - 1;
+
+    // 处理上一页
+    if (hasPrev) {
+        const prevDoc = docList[currentIndex - 1];
+        DOM.navPrev.style.display = 'flex';
+        DOM.navPrev.querySelector('.nav-doc-name').textContent = prevDoc.name;
+        DOM.navPrev.onclick = () => {
+            loadDocument(prevDoc.name);
+            updateURL(currentCategory, prevDoc.name);
+            // 滚动到顶部
+            const contentArea = document.getElementById('content-area');
+            if (contentArea) {
+                contentArea.scrollTo({ top: 0, behavior: 'smooth' });
+            }
+        };
+    } else {
+        DOM.navPrev.style.display = 'none';
+    }
+
+    // 处理下一页
+    if (hasNext) {
+        const nextDoc = docList[currentIndex + 1];
+        DOM.navNext.style.display = 'flex';
+        DOM.navNext.querySelector('.nav-doc-name').textContent = nextDoc.name;
+        DOM.navNext.onclick = () => {
+            loadDocument(nextDoc.name);
+            updateURL(currentCategory, nextDoc.name);
+            // 滚动到顶部
+            const contentArea = document.getElementById('content-area');
+            if (contentArea) {
+                contentArea.scrollTo({ top: 0, behavior: 'smooth' });
+            }
+        };
+    } else {
+        DOM.navNext.style.display = 'none';
+    }
+
+    // 根据导航按钮状态添加类,用于CSS定位
+    if (hasPrev && hasNext) {
+        docNavigation.className = 'doc-navigation has-both';
+    } else if (hasPrev) {
+        docNavigation.className = 'doc-navigation has-prev-only';
+    } else if (hasNext) {
+        docNavigation.className = 'doc-navigation has-next-only';
+    } else {
+        docNavigation.className = 'doc-navigation';
+    }
+}
+
 // 显示错误
 function showError(message) {
     const content = document.getElementById('markdown-content');

+ 12 - 0
public/reader.html

@@ -67,6 +67,18 @@
                 <!-- Markdown 内容将在这里渲染 -->
             </article>
 
+            <!-- 页面导航 -->
+            <footer id="doc-navigation" class="doc-navigation">
+                <div class="nav-prev" id="nav-prev" style="display: none;">
+                    <span class="nav-label">上一页</span>
+                    <div class="nav-doc-name"></div>
+                </div>
+                <div class="nav-next" id="nav-next" style="display: none;">
+                    <span class="nav-label">下一页</span>
+                    <div class="nav-doc-name"></div>
+                </div>
+            </footer>
+
             <!-- 编辑按钮 -->
             <button id="edit-btn" class="floating-action-btn edit-btn" title="编辑文档">
                 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">