557 lines
21 KiB
HTML
557 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
|
<meta http-equiv="Pragma" content="no-cache">
|
|
<meta http-equiv="Expires" content="0">
|
|
<title>章节目录 - 阿拉德:剑之回响</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700&family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="css/style.css">
|
|
<style>
|
|
/* 分页控制区域 */
|
|
.pagination-controls {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 15px;
|
|
margin-bottom: 20px;
|
|
padding: 15px 20px;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.page-size-selector {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.page-size-selector label {
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.page-size-selector select {
|
|
padding: 8px 12px;
|
|
background: var(--bg-tertiary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.page-size-selector select:focus {
|
|
outline: none;
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.page-jump {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.page-jump label {
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.page-jump input {
|
|
width: 60px;
|
|
padding: 8px 12px;
|
|
background: var(--bg-tertiary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
text-align: center;
|
|
}
|
|
|
|
.page-jump input:focus {
|
|
outline: none;
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.page-jump button {
|
|
padding: 8px 16px;
|
|
background: var(--primary);
|
|
border: none;
|
|
border-radius: 8px;
|
|
color: white;
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.page-jump button:hover {
|
|
background: var(--primary-light);
|
|
}
|
|
|
|
.page-nav-top {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 15px;
|
|
}
|
|
|
|
.page-nav-top .page-info {
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* 分页导航 */
|
|
.chapters-pagination {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin-top: 30px;
|
|
padding-top: 30px;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.pagination-btn {
|
|
padding: 10px 20px;
|
|
background: var(--bg-tertiary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.pagination-btn:hover:not(:disabled) {
|
|
background: var(--primary);
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.pagination-btn:disabled {
|
|
opacity: 0.4;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.page-numbers {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.page-num {
|
|
min-width: 36px;
|
|
height: 36px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: var(--bg-tertiary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.page-num:hover {
|
|
background: var(--bg-card);
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.page-num.active {
|
|
background: var(--primary);
|
|
border-color: var(--primary);
|
|
color: white;
|
|
}
|
|
|
|
.page-info {
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
padding: 0 10px;
|
|
}
|
|
|
|
/* 响应式 */
|
|
@media (max-width: 600px) {
|
|
.pagination-controls {
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.page-size-selector,
|
|
.page-jump,
|
|
.page-nav-top {
|
|
justify-content: center;
|
|
}
|
|
|
|
.chapters-pagination {
|
|
flex-wrap: wrap;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="chapters-page">
|
|
<!-- 导航栏 -->
|
|
<nav class="navbar">
|
|
<div class="nav-container">
|
|
<a href="index.html" class="logo">
|
|
<span class="logo-icon">⚔️</span>
|
|
<span class="logo-text">阿拉德文库</span>
|
|
</a>
|
|
<div class="nav-links">
|
|
<a href="index.html">首页</a>
|
|
<a href="chapters.html" class="active">目录</a>
|
|
<a href="wiki.html">设定集</a>
|
|
<a href="index.html#about">关于</a>
|
|
</div>
|
|
<div class="nav-actions">
|
|
<button class="theme-toggle" id="themeToggle">
|
|
<span class="theme-icon">🌙</span>
|
|
</button>
|
|
<button class="menu-toggle" id="menuToggle">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- 章节列表头部 -->
|
|
<section class="chapters-header">
|
|
<div class="container">
|
|
<div class="chapters-header-content">
|
|
<div class="book-mini">
|
|
<div class="mini-cover" style="background: url('images/cover.png') center/cover no-repeat;">
|
|
</div>
|
|
</div>
|
|
<div class="chapters-title">
|
|
<h1>阿拉德:剑之回响</h1>
|
|
<p>共 <span id="totalChapters">--</span> 章 · 连载中</p>
|
|
</div>
|
|
</div>
|
|
<div class="reading-progress">
|
|
<div class="progress-bar">
|
|
<div class="progress-fill" id="progressFill"></div>
|
|
</div>
|
|
<span class="progress-text" id="progressText">阅读进度 0%</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 章节列表 -->
|
|
<section class="chapters-list">
|
|
<div class="container">
|
|
<!-- 分页控制 -->
|
|
<div class="pagination-controls">
|
|
<div class="page-size-selector">
|
|
<label>每章显示:</label>
|
|
<select id="pageSizeSelect">
|
|
<option value="20">20 章</option>
|
|
<option value="30">30 章</option>
|
|
<option value="50" selected>50 章</option>
|
|
<option value="100">100 章</option>
|
|
</select>
|
|
</div>
|
|
<div class="page-nav-top">
|
|
<button class="pagination-btn" id="prevPageBtnTop">上一页</button>
|
|
<span class="page-info">第 <span id="currentPageTop">1</span> / <span id="totalPagesTop">--</span> 页</span>
|
|
<button class="pagination-btn" id="nextPageBtnTop">下一页</button>
|
|
</div>
|
|
<div class="page-jump">
|
|
<label>跳转到:</label>
|
|
<input type="number" id="pageJumpInput" min="1" value="1">
|
|
<button id="pageJumpBtn">跳转</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chapters-filter">
|
|
<div class="filter-tabs">
|
|
<button class="filter-tab active" data-filter="all">全部章节</button>
|
|
<button class="filter-tab" data-filter="latest">最近更新</button>
|
|
<button class="filter-tab" data-filter="unread">未读章节</button>
|
|
</div>
|
|
<div class="search-box">
|
|
<input type="text" placeholder="搜索章节..." id="searchInput">
|
|
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="11" cy="11" r="8"/>
|
|
<path d="M21 21l-4.35-4.35"/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chapters-timeline" id="chaptersList">
|
|
<!-- 章节列表将通过JS动态生成 -->
|
|
</div>
|
|
|
|
<!-- 底部分页导航 -->
|
|
<div class="chapters-pagination" id="paginationNav">
|
|
<button class="pagination-btn" id="firstPageBtn">首页</button>
|
|
<button class="pagination-btn" id="prevPageBtn">上一页</button>
|
|
<div class="page-numbers" id="pageNumbers">
|
|
<!-- 页码按钮 -->
|
|
</div>
|
|
<button class="pagination-btn" id="nextPageBtn">下一页</button>
|
|
<button class="pagination-btn" id="lastPageBtn">末页</button>
|
|
<span class="page-info" id="totalPages" style="display:none;"></span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 快速操作浮动按钮 -->
|
|
<div class="fab-container">
|
|
<button class="fab" id="scrollTop" title="回到顶部">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M18 15l-6-6-6 6"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 页脚 -->
|
|
<footer class="footer">
|
|
<div class="container">
|
|
<div class="footer-content">
|
|
<div class="footer-brand">
|
|
<span class="logo-icon">⚔️</span>
|
|
<span class="logo-text">阿拉德文库</span>
|
|
</div>
|
|
<p class="footer-desc">为《阿拉德:剑之回响》打造的专属阅读平台</p>
|
|
<div class="footer-links">
|
|
<a href="index.html">首页</a>
|
|
<a href="chapters.html">目录</a>
|
|
<a href="index.html#about">关于</a>
|
|
</div>
|
|
<p class="footer-copyright">© 2026 阿拉德:剑之回响 · 李策 著</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script src="js/app.js?v=20260329"></script>
|
|
<script>
|
|
// 分页状态
|
|
let currentPage = 1;
|
|
let pageSize = parseInt(localStorage.getItem('chaptersPageSize') || '50');
|
|
let filteredChapters = [];
|
|
|
|
// 页面加载完成后初始化
|
|
document.addEventListener('DOMContentLoaded', async function() {
|
|
// 设置下拉框默认值
|
|
document.getElementById('pageSizeSelect').value = pageSize;
|
|
|
|
// 等待章节数据加载完成
|
|
await loadChaptersData();
|
|
|
|
// 更新总章节数显示
|
|
const totalEl = document.getElementById('totalChapters');
|
|
if (totalEl && window.chaptersData) {
|
|
totalEl.textContent = window.chaptersData.length;
|
|
}
|
|
|
|
// 初始化分页
|
|
initPagination();
|
|
});
|
|
|
|
// 初始化分页功能
|
|
function initPagination() {
|
|
const data = window.chaptersData || [];
|
|
filteredChapters = [...data];
|
|
|
|
// 渲染当前页
|
|
renderCurrentPage();
|
|
|
|
// 绑定事件
|
|
document.getElementById('pageSizeSelect').addEventListener('change', (e) => {
|
|
pageSize = parseInt(e.target.value);
|
|
localStorage.setItem('chaptersPageSize', pageSize);
|
|
currentPage = 1;
|
|
renderCurrentPage();
|
|
});
|
|
|
|
document.getElementById('pageJumpBtn').addEventListener('click', () => {
|
|
const input = document.getElementById('pageJumpInput');
|
|
const totalPages = Math.ceil(filteredChapters.length / pageSize);
|
|
let page = parseInt(input.value);
|
|
if (page < 1) page = 1;
|
|
if (page > totalPages) page = totalPages;
|
|
currentPage = page;
|
|
input.value = page;
|
|
renderCurrentPage();
|
|
});
|
|
|
|
document.getElementById('pageJumpInput').addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') {
|
|
document.getElementById('pageJumpBtn').click();
|
|
}
|
|
});
|
|
|
|
document.getElementById('firstPageBtn').addEventListener('click', () => goToPage(1));
|
|
document.getElementById('prevPageBtn').addEventListener('click', () => goToPage(currentPage - 1));
|
|
document.getElementById('nextPageBtn').addEventListener('click', () => goToPage(currentPage + 1));
|
|
document.getElementById('lastPageBtn').addEventListener('click', () => goToPage(Math.ceil(filteredChapters.length / pageSize)));
|
|
|
|
// 顶部导航按钮
|
|
document.getElementById('prevPageBtnTop').addEventListener('click', () => goToPage(currentPage - 1));
|
|
document.getElementById('nextPageBtnTop').addEventListener('click', () => goToPage(currentPage + 1));
|
|
}
|
|
|
|
// 跳转到指定页
|
|
function goToPage(page) {
|
|
const totalPages = Math.ceil(filteredChapters.length / pageSize);
|
|
if (page < 1) page = 1;
|
|
if (page > totalPages) page = totalPages;
|
|
currentPage = page;
|
|
document.getElementById('pageJumpInput').value = page;
|
|
renderCurrentPage();
|
|
}
|
|
|
|
// 渲染当前页
|
|
function renderCurrentPage() {
|
|
const data = filteredChapters;
|
|
const totalPages = Math.ceil(data.length / pageSize) || 1;
|
|
const start = (currentPage - 1) * pageSize;
|
|
const end = start + pageSize;
|
|
const pageData = data.slice(start, end);
|
|
|
|
// 渲染章节列表
|
|
renderChaptersListPaged(pageData);
|
|
|
|
// 更新页码信息
|
|
document.getElementById('totalPages').textContent = totalPages;
|
|
document.getElementById('totalPagesTop').textContent = totalPages;
|
|
document.getElementById('currentPageTop').textContent = currentPage;
|
|
document.getElementById('pageJumpInput').max = totalPages;
|
|
|
|
// 渲染页码按钮
|
|
renderPageNumbers(totalPages);
|
|
|
|
// 更新底部按钮状态
|
|
document.getElementById('firstPageBtn').disabled = currentPage === 1;
|
|
document.getElementById('prevPageBtn').disabled = currentPage === 1;
|
|
document.getElementById('nextPageBtn').disabled = currentPage === totalPages;
|
|
document.getElementById('lastPageBtn').disabled = currentPage === totalPages;
|
|
|
|
// 更新顶部按钮状态
|
|
document.getElementById('prevPageBtnTop').disabled = currentPage === 1;
|
|
document.getElementById('nextPageBtnTop').disabled = currentPage === totalPages;
|
|
}
|
|
|
|
// 渲染分页后的章节列表
|
|
function renderChaptersListPaged(chapters) {
|
|
const container = document.getElementById('chaptersList');
|
|
|
|
container.innerHTML = chapters.map(chapter => `
|
|
<div class="timeline-item" data-chapter="${chapter.id}">
|
|
<div class="timeline-marker"></div>
|
|
<a href="reader.html?id=${chapter.id}" class="timeline-content">
|
|
<div class="timeline-header">
|
|
<h3>第${chapter.id}章 ${chapter.title}</h3>
|
|
<span class="timeline-date">${chapter.date}</span>
|
|
</div>
|
|
<p class="timeline-subtitle">${chapter.subtitle}</p>
|
|
<p class="timeline-desc">${chapter.desc}</p>
|
|
<div class="chapter-meta">
|
|
<span class="word-count">${chapter.wordCount || 0} 字</span>
|
|
<span class="chapter-status">${chapter.status}</span>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// 渲染页码按钮
|
|
function renderPageNumbers(totalPages) {
|
|
const container = document.getElementById('pageNumbers');
|
|
let html = '';
|
|
|
|
// 显示的页码范围
|
|
let start = Math.max(1, currentPage - 2);
|
|
let end = Math.min(totalPages, currentPage + 2);
|
|
|
|
// 确保至少显示5个页码
|
|
if (end - start < 4) {
|
|
if (start === 1) {
|
|
end = Math.min(totalPages, start + 4);
|
|
} else if (end === totalPages) {
|
|
start = Math.max(1, end - 4);
|
|
}
|
|
}
|
|
|
|
// 第一页
|
|
if (start > 1) {
|
|
html += `<span class="page-num" data-page="1">1</span>`;
|
|
if (start > 2) {
|
|
html += `<span class="page-info">...</span>`;
|
|
}
|
|
}
|
|
|
|
// 中间页码
|
|
for (let i = start; i <= end; i++) {
|
|
html += `<span class="page-num ${i === currentPage ? 'active' : ''}" data-page="${i}">${i}</span>`;
|
|
}
|
|
|
|
// 最后一页
|
|
if (end < totalPages) {
|
|
if (end < totalPages - 1) {
|
|
html += `<span class="page-info">...</span>`;
|
|
}
|
|
html += `<span class="page-num" data-page="${totalPages}">${totalPages}</span>`;
|
|
}
|
|
|
|
container.innerHTML = html;
|
|
|
|
// 绑定页码点击事件
|
|
container.querySelectorAll('.page-num').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
const page = parseInt(btn.dataset.page);
|
|
goToPage(page);
|
|
});
|
|
});
|
|
}
|
|
|
|
// 搜索功能
|
|
document.getElementById('searchInput').addEventListener('input', (e) => {
|
|
const query = e.target.value.toLowerCase();
|
|
const data = window.chaptersData || [];
|
|
|
|
if (query) {
|
|
filteredChapters = data.filter(ch =>
|
|
ch.title.toLowerCase().includes(query) ||
|
|
(ch.desc && ch.desc.toLowerCase().includes(query))
|
|
);
|
|
} else {
|
|
filteredChapters = [...data];
|
|
}
|
|
|
|
currentPage = 1;
|
|
renderCurrentPage();
|
|
});
|
|
|
|
// 筛选功能
|
|
document.querySelectorAll('.filter-tab').forEach(tab => {
|
|
tab.addEventListener('click', () => {
|
|
document.querySelectorAll('.filter-tab').forEach(t => t.classList.remove('active'));
|
|
tab.classList.add('active');
|
|
|
|
const filter = tab.dataset.filter;
|
|
const data = window.chaptersData || [];
|
|
const readChapters = JSON.parse(localStorage.getItem('readChapters') || '[]');
|
|
|
|
if (filter === 'all') {
|
|
filteredChapters = [...data];
|
|
} else if (filter === 'latest') {
|
|
filteredChapters = data.slice(-10).reverse();
|
|
} else if (filter === 'unread') {
|
|
filteredChapters = data.filter(ch => !readChapters.includes(ch.id));
|
|
}
|
|
|
|
currentPage = 1;
|
|
renderCurrentPage();
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |