jianzhihuixiang/alacarte-novel-website/chapters.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>