jianzhihuixiang/alacarte-novel-website/chapters/chapter-123.html
2026-03-29 13:57:51 +08:00

929 lines
41 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-primary: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
--text-primary: #e0e0e0;
--text-secondary: #888;
--accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--border-color: rgba(255,255,255,0.1);
--btn-bg: rgba(255,255,255,0.1);
--btn-hover: rgba(255,255,255,0.2);
}
[data-theme="light"] {
--bg-primary: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
--text-primary: #333;
--text-secondary: #666;
--border-color: rgba(0,0,0,0.1);
--btn-bg: rgba(0,0,0,0.05);
--btn-hover: rgba(0,0,0,0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Noto Serif SC', serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.8;
min-height: 100vh;
transition: all 0.3s ease;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
padding-bottom: 120px;
}
/* 顶部导航 */
.top-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
background: rgba(0,0,0,0.3);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border-color);
z-index: 1000;
padding: 10px 20px;
}
.top-nav-content {
max-width: 800px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-link {
color: var(--text-primary);
text-decoration: none;
font-family: 'Noto Sans SC', sans-serif;
font-size: 14px;
padding: 8px 16px;
background: var(--btn-bg);
border: 1px solid var(--border-color);
border-radius: 8px;
transition: all 0.3s ease;
}
.nav-link:hover {
background: var(--btn-hover);
}
.chapter-header {
text-align: center;
padding: 80px 0 40px;
border-bottom: 1px solid var(--border-color);
margin-bottom: 40px;
}
.chapter-number {
font-size: 14px;
color: var(--text-secondary);
letter-spacing: 4px;
text-transform: uppercase;
margin-bottom: 10px;
}
.chapter-title {
font-size: 32px;
font-weight: 700;
background: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 20px;
}
.chapter-meta {
font-size: 14px;
color: var(--text-secondary);
}
.chapter-content {
font-size: 18px;
line-height: 2;
text-align: justify;
}
.chapter-content p {
margin-bottom: 1.5em;
text-indent: 2em;
}
.chapter-content p:first-of-type::first-letter {
font-size: 3em;
float: left;
line-height: 1;
margin-right: 8px;
margin-top: -5px;
background: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 700;
}
/* 固定底部导航 */
.fixed-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,0.3);
backdrop-filter: blur(10px);
border-top: 1px solid var(--border-color);
z-index: 1000;
padding: 15px 20px;
}
.fixed-nav-content {
max-width: 800px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-btn {
padding: 12px 24px;
background: var(--btn-bg);
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-primary);
text-decoration: none;
transition: all 0.3s ease;
font-family: 'Noto Sans SC', sans-serif;
font-size: 14px;
cursor: pointer;
}
.nav-btn:hover {
background: var(--btn-hover);
transform: translateY(-2px);
}
.nav-btn.disabled {
opacity: 0.3;
cursor: not-allowed;
pointer-events: none;
}
/* 右侧滚动按钮 */
.scroll-buttons {
position: fixed;
right: 20px;
bottom: 90px;
display: flex;
flex-direction: column;
gap: 10px;
z-index: 1001;
}
.scroll-btn {
width: 40px;
height: 40px;
border-radius: 8px;
background: var(--btn-bg);
border: 1px solid var(--border-color);
color: var(--text-primary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: all 0.3s ease;
font-family: 'Noto Sans SC', sans-serif;
}
.scroll-btn:hover {
background: var(--btn-hover);
}
/* TTS控制面板 */
.tts-panel {
position: fixed;
left: 20px;
bottom: 90px;
display: flex;
flex-direction: column;
gap: 10px;
z-index: 1001;
background: rgba(0,0,0,0.5);
backdrop-filter: blur(10px);
border-radius: 12px;
border: 1px solid var(--border-color);
padding: 15px;
min-width: 180px;
}
.tts-title {
font-size: 12px;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 2px;
margin-bottom: 5px;
}
.tts-controls {
display: flex;
gap: 8px;
margin-bottom: 10px;
}
.tts-btn {
width: 36px;
height: 36px;
border-radius: 8px;
background: var(--btn-bg);
border: 1px solid var(--border-color);
color: var(--text-primary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
transition: all 0.3s ease;
font-family: 'Noto Sans SC', sans-serif;
}
.tts-btn:hover {
background: var(--btn-hover);
}
.tts-btn.active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-color: #667eea;
}
.tts-progress {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}
.tts-progress-bar {
flex: 1;
height: 4px;
background: var(--btn-bg);
border-radius: 2px;
overflow: hidden;
}
.tts-progress-fill {
height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
width: 0%;
transition: width 0.1s ease;
}
.tts-time {
font-size: 12px;
color: var(--text-secondary);
font-family: 'Noto Sans SC', sans-serif;
min-width: 80px;
}
.tts-speed {
display: flex;
align-items: center;
gap: 8px;
}
.tts-speed-label {
font-size: 12px;
color: var(--text-secondary);
font-family: 'Noto Sans SC', sans-serif;
}
.tts-speed-select {
padding: 4px 8px;
background: var(--btn-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
color: var(--text-primary);
font-size: 12px;
cursor: pointer;
font-family: 'Noto Sans SC', sans-serif;
}
@media (max-width: 600px) {
.tts-panel {
left: 10px;
bottom: 80px;
min-width: 150px;
padding: 10px;
}
.tts-btn {
width: 32px;
height: 32px;
font-size: 12px;
}
}
/* 侧边栏 - 标题固定,内容滚动 */
.sidebar {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.5);
backdrop-filter: blur(10px);
border-radius: 12px;
border: 1px solid var(--border-color);
width: 200px;
max-height: 70vh;
z-index: 999;
display: flex;
flex-direction: column;
}
.sidebar-title {
font-size: 14px;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 2px;
padding: 15px 20px;
border-bottom: 1px solid var(--border-color);
flex-shrink: 0;
}
.sidebar-content {
overflow-y: auto;
padding: 10px 20px 20px;
flex: 1;
scrollbar-width: thin;
scrollbar-color: transparent transparent;
transition: scrollbar-color 0.3s ease;
}
.sidebar-content:hover {
scrollbar-color: rgba(255,255,255,0.3) transparent;
}
.sidebar-content::-webkit-scrollbar {
width: 6px;
}
.sidebar-content::-webkit-scrollbar-track {
background: transparent;
}
.sidebar-content::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 3px;
transition: background 0.3s ease;
}
.sidebar-content:hover::-webkit-scrollbar-thumb {
background: rgba(255,255,255,0.3);
}
.sidebar-content:hover::-webkit-scrollbar-thumb:hover {
background: rgba(255,255,255,0.5);
}
[data-theme="light"] .sidebar-content:hover {
scrollbar-color: rgba(0,0,0,0.3) transparent;
}
[data-theme="light"] .sidebar-content:hover::-webkit-scrollbar-thumb {
background: rgba(0,0,0,0.3);
}
[data-theme="light"] .sidebar-content:hover::-webkit-scrollbar-thumb:hover {
background: rgba(0,0,0,0.5);
}
.sidebar-chapter {
display: block;
padding: 8px 0;
color: #aaa;
text-decoration: none;
font-size: 13px;
border-bottom: 1px solid rgba(255,255,255,0.05);
transition: all 0.3s ease;
line-height: 1.5;
}
.sidebar-chapter:hover {
color: #667eea;
}
.sidebar-chapter.current {
color: #667eea;
font-weight: 600;
}
@media (max-width: 1200px) {
.sidebar {
display: none;
}
}
@media (max-width: 600px) {
.chapter-title {
font-size: 24px;
}
.chapter-content {
font-size: 16px;
}
.fixed-nav-content {
gap: 10px;
}
.nav-btn {
padding: 10px 15px;
font-size: 12px;
}
.scroll-buttons {
right: 10px;
bottom: 80px;
}
.scroll-btn {
width: 36px;
height: 36px;
}
}
/* 滚动条样式 */
.sidebar::-webkit-scrollbar {
width: 4px;
}
.sidebar::-webkit-scrollbar-track {
background: transparent;
}
.sidebar::-webkit-scrollbar-thumb {
background: rgba(255,255,255,0.2);
border-radius: 2px;
}
</style>
</head>
<body>
<!-- 顶部导航 -->
<nav class="top-nav">
<div class="top-nav-content">
<a href="../index.html" class="nav-link">返回首页</a>
<button class="nav-link" id="themeToggle">切换主题</button>
</div>
</nav>
<div class="container">
<header class="chapter-header">
<div class="chapter-number">Chapter 123</div>
<h1 class="chapter-title">{{CHAPTER_TITLE}}</h1>
</header>
<article class="chapter-content">
<p>天界,皇都根特的城墙上。</p>
<p>阳光从云层中穿透,洒在这座宏伟的城市上。远处的天空海呈现出淡淡的蓝色,仿佛一幅美丽的画卷。泽丁穿着守备队长的铠甲,站在城墙边缘,望着远处的风景。</p>
<p>她的身姿挺拔而英武,金色的长发在风中飘动。铠甲上刻着天界的徽章,那是她作为守备队长的荣耀。她的腰间挂着长剑,手里握着巡逻的记录簿。</p>
<p>林克走到她身边,两人并肩看着天界的风景。</p>
<p>"好久没来天界了。"林克感慨道。</p>
<p>自从上次卡勒特入侵之后,他已经很久没有回到这里了。那时候的根特满目疮痍,到处都是战火的痕迹。但现在,这座城市已经恢复了往日的繁华。</p>
<p>"嗯。"泽丁点头,"最近皇都恢复了平静,一切都在变好。卡勒特的残党已经被清除,人民的生活也重新稳定下来。"</p>
<p>她转向林克,眼中带着感激:"谢谢你...林克。谢谢你帮助我们。如果不是你,根特可能已经被卡勒特彻底占领了。"</p>
<p>林克摇头:"我只是做了应该做的事。你们才是真正的英雄,在卡勒特的压迫下坚持抵抗,从未放弃。"</p>
<p>泽丁笑了,有些不好意思:"我们只是做了必须做的事。保护家园,保护人民,这是守备队的职责。"</p>
<p>她的目光变得深邃:"但有时候,真的很难坚持下去。看着战友一个个倒下,看着城市被敌人践踏...我曾经一度以为,我们再也夺不回根特了。"</p>
<p>"但你没有放弃。"林克说。</p>
<p>"因为有你。"泽丁认真地看着他,"当你带着冒险家们来到根特的时候,我看到了希望。你让我知道,我们不是孤军奋战,还有人愿意帮助我们。"</p>
<p>她的声音变得轻柔:"是你给了我继续战斗的勇气。"</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p>下午,两人一起巡逻。</p>
<p>泽丁带着林克走过城墙的每一个角落,介绍着皇都的变化。她的讲解详细而认真,每到一个地方都会讲述这里曾经发生的事情,以及现在的修复情况。</p>
<p>"这里是曾经的粮仓。"她指着一座新建的建筑,"卡勒特入侵的时候,他们烧毁了所有的粮食,让人民陷入饥荒。现在,我们已经重新建立了粮仓,储备充足。"</p>
<p>"这里是曾经的医院。"她指着另一座建筑,"那时候伤员太多,医院根本无法容纳。很多战友因为没有及时治疗而牺牲。现在,我们扩建了医院,增加了很多医护人员。"</p>
<p>"这里是..."她停顿了一下,指着一块空地,"曾经是我的队长倒下的地方。"</p>
<p>林克看向她,看到了她眼中的悲伤。</p>
<p>泽丁深吸一口气:"卡勒特入侵的第一天,我的队长就牺牲了。他为了保护我,挡住了敌人的攻击...我看着他倒下,却什么都做不了。"</p>
<p>她的声音变得哽咽:"他最后对我说的是..."泽丁,活下去,保护根特"。"</p>
<p>林克伸手握住她的手,感受到她冰凉的温度。</p>
<p>泽丁看着他,眼中闪过感激:"谢谢你,林克。谢谢你愿意听我说这些。"</p>
<p>"你有权利回忆。"林克说,"那些逝去的战友,应该被记住。"</p>
<p>泽丁点头,深吸一口气,继续说:"后来,我接替了队长的职位,带领守备队继续抵抗。那段时间真的很艰难,我们缺人、缺武器、缺补给...每一天都在生死边缘徘徊。"</p>
<p>她的目光变得坚定:"但我没有放弃,因为我知道,队长在看着我。我不能辜负他的期望,不能辜负根特的人民。"</p>
<p>林克看着她,眼中闪过赞赏:"你很坚强,泽丁。能在这种环境下坚持下来,很不容易。"</p>
<p>泽丁苦笑:"坚强是被逼出来的。如果不够坚强,我早就倒下了。"</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p>巡逻结束后,两人来到了城墙上的一处高点。</p>
<p>这里是根特最高的位置,可以看到整个城市的全景。远处的天空海呈现出淡淡的蓝色,近处的房屋整齐排列,街道上行人来来往往,一片繁荣的景象。</p>
<p>"真美。"林克感慨道。</p>
<p>"嗯。"泽丁点头,"这就是我们守护的城市。每一栋房屋,每一条街道,都是我们的心血。"</p>
<p>她转向林克:"林克,我想问你一个问题。"</p>
<p>"什么?"</p>
<p>泽丁的目光变得认真:"你以后...还会来天界吗?"</p>
<p>林克想了想:"如果有需要的话,我会来的。"</p>
<p>泽丁的眼神有些失落:"只是有需要的时候吗?"</p>
<p>林克看着她,读懂了她眼中的期待。</p>
<p>"泽丁。"他说,"你是想让我经常来吗?"</p>
<p>泽丁低下头,声音变得轻柔:"我...我只是想知道,你会不会想念这里。"</p>
<p>林克走近一步,看着她的眼睛:"我会想念这里的。不只是这座城市,还有...这里的人。"</p>
<p>泽丁抬起头,看着他:"包括我吗?"</p>
<p>林克笑了:"当然包括你。"</p>
<p>泽丁的心跳加速了。她看着林克的眼睛,看到了里面深深的温柔。</p>
<p>"林克。"她轻声说,"我有话想对你说。"</p>
<p>林克静静地看着她,等待着她的下一句话。</p>
<p>泽丁深吸一口气,鼓起勇气说:"我...我喜欢你。"</p>
<p>她的声音很轻,但每一个字都很清晰:"从你来到根特的那天开始,我就把你放在心里了。你是我遇到的第一个真正帮助我们的人,第一个让我看到希望的人,第一个...让我想要依靠的人。"</p>
<p>她的眼睛湿润了:"我知道,你是阿拉德大陆的冒险家,你有很多事情要做,可能不会一直留在天界。但是...我还是想告诉你我的心意。"</p>
<p>她低下头:"至少,让你知道,有人在天界等你。"</p>
<p>林克沉默了片刻。</p>
<p>泽丁紧张地等待着他的回应,心脏跳得很快。她不知道自己为什么会这么紧张,明明已经做好了被拒绝的准备。</p>
<p>然后,她感觉到一只手轻轻握住她的手。</p>
<p>她抬起头,看到林克正温柔地看着她。</p>
<p>"泽丁。"他说,"我也喜欢你。"</p>
<p>泽丁愣住了:"真...真的?"</p>
<p>"真的。"林克点头,"你勇敢、坚强、负责。你为了守护家园付出了那么多,我很敬佩你,也很喜欢你。"</p>
<p>泽丁的眼眶湿润了,眼泪不自觉地滑落。她等这句话等了太久太久。</p>
<p>"林克..."她轻声说,声音带着哽咽。</p>
<p>林克伸手擦去她的眼泪:"傻瓜,哭什么。"</p>
<p>泽丁破涕为笑:"我太开心了嘛..."</p>
<p>然后,她主动凑过去,吻住了他的唇。</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p>这是一个温柔的吻,带着等待已久的深情。</p>
<p>夕阳的余晖洒在两人身上,为这个吻镀上了一层金色的光芒。泽丁的双臂环住林克的脖子,身体紧紧贴着他。她的铠甲发出轻微的碰撞声,但这并不影响这份亲密。</p>
<p>林克的手轻轻搂住她的腰,将她拥入怀中。</p>
<p>吻了很久,两人才分开。泽丁的脸红得像晚霞,眼睛亮晶晶的。</p>
<p>"林克..."她轻声说,声音带着羞涩,"今晚...你可以陪我在这里吗?"</p>
<p>林克看着她,读懂了她眼中的期待。他伸手抚摸着她的脸颊,感受着她微热的温度。</p>
<p>"你想在这里?"他问。</p>
<p>泽丁点头,眼神中带着一丝期待和紧张:"我想和你一起看星星...在这座我守护的城市上..."</p>
<p>她的声音变得轻柔:"这是我第一次...想要和别人分享这份宁静。"</p>
<p>林克没有说话,只是再次吻住了她。这一次的吻更加热烈,更加深入。泽丁发出一声轻哼,紧紧抱住了他。</p>
<p>夕阳慢慢沉入地平线,夜幕开始降临。</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p>夜幕降临,星星出现在天空中。</p>
<p>天界的星空比阿拉德大陆更加明亮,因为这里没有地面的遮挡,可以直接看到整个天穹。无数星星闪烁着,如同钻石洒在黑色的绸缎上。</p>
<p>两人并肩坐在城墙的高点上,看着这美丽的星空。</p>
<p>泽丁的头靠在林克胸口,手指在他的胸口画着圈。她的铠甲已经脱下,只穿着简单的衣物,更显出她的柔美。</p>
<p>"好美。"她感慨道。</p>
<p>"嗯。"林克同意。</p>
<p>"林克。"她轻声说。</p>
<p>"嗯?"</p>
<p>"你知道吗,我曾经以为,自己一辈子都会孤独地守护这座城市。"她的声音带着回忆,"我的队长牺牲了,我的战友越来越少,我看不到希望...我以为,我的命运就是战斗到最后一刻,然后倒在这片土地上。"</p>
<p>林克握住她的手,没有说话,只是静静听着。</p>
<p>泽丁继续说:"但当你出现的时候,一切都变了。你给了我希望,给了我勇气,还给了我...爱情。"</p>
<p>她转向林克,眼中满是温柔:"谢谢你,林克。谢谢你让我知道,守护者也可以被守护。"</p>
<p>林克看着她,眼中闪过心疼:"泽丁,从今以后,我会守护你。"</p>
<p>泽丁的眼眶湿润了:"真的?"</p>
<p>"真的。"林克点头,"无论你在哪里,我都会守护你。"</p>
<p>她笑了,凑过去吻了他。然后,她把头埋进他的胸口,享受着这份宁静和甜蜜。</p>
<p>"林克..."她轻声说,声音带着羞涩。</p>
<p>"嗯?"</p>
<p>"我们可以...再靠近一点吗?"</p>
<p>林克笑了:"你想怎样?"</p>
<p>泽丁的脸红了,但还是勇敢地说:"我想和你...更亲密一点..."</p>
<p>林克没有说话,只是将她拉入怀中,再次吻住了她。这一次的吻更加热烈,更加深入。</p>
<p>泽丁的身体变得柔软,她紧紧抱住林克,感受着他的温度。</p>
<p>月光洒在两人身上,见证着这份新的爱情。</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p>深夜,两人依偎在一起。</p>
<p>泽丁的头靠在林克胸口,听着他的心跳声。她的身体有些疲惫,但心情无比满足。</p>
<p>"林克。"她轻声说。</p>
<p>"嗯?"</p>
<p>"我好幸福。"她的声音带着满足,"这是我第一次觉得,原来守护者也可以有依靠。"</p>
<p>林克搂紧了她:"以后会更好的,泽丁。我会一直在你身边。"</p>
<p>泽丁抬起头,看着他:"你什么时候会再来天界?"</p>
<p>林克想了想:"很快。我会经常来的。"</p>
<p>泽丁开心地笑了:"那我等你。"</p>
<p>她再次把头埋进他的胸口,享受着这份宁静和甜蜜。</p>
<p>星空依旧明亮,见证着这对恋人的甜蜜时光。</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p>第二天清晨,两人并肩离开城墙。</p>
<p>泽丁重新穿上铠甲,恢复了守备队长的威严。但她的脸上带着幸福的笑容,眼神中也多了几分柔和。</p>
<p>"林克。"她说。</p>
<p>"嗯?"</p>
<p>"谢谢你...给我这份回忆。"她的声音很轻,但很真诚。</p>
<p>林克握住她的手:"这只是开始,泽丁。以后我们会有更多的回忆。"</p>
<p>泽丁开心地笑了,紧紧握着他的手。</p>
<p>曾经,她以为自己的命运是孤独地守护这座城市。但现在,她知道,守护者也可以被守护。</p>
<p>根特的城墙依旧坚固,而她的心,也因为爱情而变得更加坚强。</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0;">···</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0; margin-top: 2em;">(第一百二十三章完)</p>
<p style="text-align: center; color: var(--text-secondary); text-indent: 0; margin-top: 2em;">(番外·泽丁篇 完)</p>
</article>
</div>
<!-- 固定底部导航 -->
<nav class="fixed-nav">
<div class="fixed-nav-content">
<a href="chapter-122.html" class="nav-btn ">上一章</a>
<a href="../chapters.html" class="nav-btn">目录</a>
<a href="chapter-124.html" class="nav-btn ">下一章</a>
</div>
</nav>
<!-- 右侧滚动按钮 -->
<div class="scroll-buttons">
<button class="scroll-btn" id="scrollTop" title="回到顶部"></button>
<button class="scroll-btn" id="scrollBottom" title="回到底部"></button>
</div>
<!-- TTS语音朗读面板 -->
<div class="tts-panel" id="ttsPanel">
<div class="tts-title">语音朗读</div>
<div class="tts-controls">
<button class="tts-btn" id="ttsPlay" title="播放"></button>
<button class="tts-btn" id="ttsPause" title="暂停"></button>
<button class="tts-btn" id="ttsStop" title="停止"></button>
</div>
<div class="tts-progress">
<div class="tts-progress-bar">
<div class="tts-progress-fill" id="ttsProgressFill"></div>
</div>
<div class="tts-time" id="ttsTime">0 / 0</div>
</div>
<div class="tts-speed">
<span class="tts-speed-label">速度:</span>
<select class="tts-speed-select" id="ttsSpeed">
<option value="0.5">慢速</option>
<option value="0.75">较慢</option>
<option value="1" selected>正常</option>
<option value="1.25">较快</option>
<option value="1.5">快速</option>
<option value="2">极速</option>
</select>
</div>
</div>
<!-- 侧边栏章节导航 -->
<aside class="sidebar">
<div class="sidebar-title">章节导航</div>
<div class="sidebar-content" id="sidebarContent">
<a href="chapter-93.html" class="sidebar-chapter ">第93章安图恩攻坚战·使徒陨落</a>
<a href="chapter-94.html" class="sidebar-chapter ">第94章克洛诺斯岛·寂静城的召唤</a>
<a href="chapter-95.html" class="sidebar-chapter ">第95章寂静城的秘密</a>
<a href="chapter-96.html" class="sidebar-chapter ">第96章番外·贝奇的献身</a>
<a href="chapter-97.html" class="sidebar-chapter ">第97章光之舞会</a>
<a href="chapter-98.html" class="sidebar-chapter ">第98章钢铁之臂</a>
<a href="chapter-99.html" class="sidebar-chapter ">第99章能源熔炉</a>
<a href="chapter-100.html" class="sidebar-chapter ">第100章王之书库</a>
<a href="chapter-101.html" class="sidebar-chapter ">第101章不灭回廊</a>
<a href="chapter-102.html" class="sidebar-chapter ">第102章机械王座</a>
<a href="chapter-103.html" class="sidebar-chapter ">第103章番外·寂静城的早晨</a>
<a href="chapter-104.html" class="sidebar-chapter ">第104章番外·贝奇与艾泽拉</a>
<a href="chapter-105.html" class="sidebar-chapter ">第105章番外·卢克的嘱托</a>
<a href="chapter-106.html" class="sidebar-chapter ">第106章时空之门的召唤</a>
<a href="chapter-107.html" class="sidebar-chapter ">第107章格兰之火</a>
<a href="chapter-108.html" class="sidebar-chapter ">第108章瘟疫之源</a>
<a href="chapter-109.html" class="sidebar-chapter ">第109章卡勒特之初</a>
<a href="chapter-110.html" class="sidebar-chapter ">第110章无法地带</a>
<a href="chapter-111.html" class="sidebar-chapter ">第111章暗黑圣战</a>
<a href="chapter-112.html" class="sidebar-chapter ">第112章昔日悲鸣</a>
<a href="chapter-113.html" class="sidebar-chapter ">第113章凛冬</a>
<a href="chapter-114.html" class="sidebar-chapter ">第114章迷之觉悟</a>
<a href="chapter-115.html" class="sidebar-chapter ">第115章番外·艾丽丝的抉择</a>
<a href="chapter-116.html" class="sidebar-chapter ">第116章番外·后宫的日常</a>
<a href="chapter-117.html" class="sidebar-chapter ">第117章番外·与赛丽亚的约会</a>
<a href="chapter-118.html" class="sidebar-chapter ">第118章番外·与奥菲利亚的重逢</a>
<a href="chapter-119.html" class="sidebar-chapter ">第119章番外·与敏泰的雪山之行</a>
<a href="chapter-120.html" class="sidebar-chapter ">第120章番外·与莎兰的魔法时光</a>
<a href="chapter-121.html" class="sidebar-chapter ">第121章番外·与帕丽丝的格斗训练</a>
<a href="chapter-122.html" class="sidebar-chapter ">第122章番外·与莫纳亨的念动力</a>
<a href="chapter-123.html" class="sidebar-chapter current">第123章番外·与泽丁的天界巡逻</a>
<a href="chapter-124.html" class="sidebar-chapter ">第124章番外·与马琳的骑士之道</a>
<a href="chapter-125.html" class="sidebar-chapter ">第125章番外·与皇女的皇家约会</a>
<a href="chapter-126.html" class="sidebar-chapter ">第126章番外·与米娅的工坊时光</a>
<a href="chapter-127.html" class="sidebar-chapter ">第127章番外·与贝奇的人造之心</a>
<a href="chapter-128.html" class="sidebar-chapter ">第128章番外·与艾泽拉的守护誓言</a>
<a href="chapter-129.html" class="sidebar-chapter ">第129章魔界的召唤</a>
<a href="chapter-130.html" class="sidebar-chapter ">第130章魔界营地</a>
<a href="chapter-131.html" class="sidebar-chapter ">第131章凯蒂的指引</a>
<a href="chapter-132.html" class="sidebar-chapter ">第132章营地危机</a>
<a href="chapter-133.html" class="sidebar-chapter ">第133章尼梅尔的心意</a>
<a href="chapter-134.html" class="sidebar-chapter ">第134章中央公园</a>
<a href="chapter-135.html" class="sidebar-chapter ">第135章剑圣的试炼</a>
<a href="chapter-136.html" class="sidebar-chapter ">第136章地轨中心</a>
<a href="chapter-137.html" class="sidebar-chapter ">第137章魔剑士阿斯兰</a>
<a href="chapter-138.html" class="sidebar-chapter ">第138章泪目之眼</a>
<a href="chapter-139.html" class="sidebar-chapter ">第139章使徒会晤</a>
<a href="chapter-140.html" class="sidebar-chapter ">第140章复仇之剑</a>
<a href="chapter-141.html" class="sidebar-chapter ">第141章寂静城再访</a>
<a href="chapter-142.html" class="sidebar-chapter ">第142章时间之钥</a>
<a href="chapter-143.html" class="sidebar-chapter ">第143章翡翠梦魇</a>
<a href="chapter-144.html" class="sidebar-chapter ">第144章诅咒的守护者</a>
<a href="chapter-145.html" class="sidebar-chapter ">第145章精灵的誓言</a>
<a href="chapter-146.html" class="sidebar-chapter ">第146章深渊之眼</a>
<a href="chapter-147.html" class="sidebar-chapter ">第147章赫尔德的仪式</a>
<a href="chapter-148.html" class="sidebar-chapter ">第148章战后余晖</a>
<a href="chapter-149.html" class="sidebar-chapter ">第149章泰波尔斯的召唤</a>
<a href="chapter-150.html" class="sidebar-chapter ">第150章天空之城</a>
<a href="chapter-151.html" class="sidebar-chapter ">第151章风暴试炼</a>
<a href="chapter-152.html" class="sidebar-chapter ">第152章光芒与暗影</a>
<a href="chapter-153.html" class="sidebar-chapter ">第153章天空之战</a>
</div>
</aside>
<script>
// 记录阅读进度
let readChapters = JSON.parse(localStorage.getItem('readChapters') || '[]');
if (!readChapters.includes(123)) {
readChapters.push({{CHAPTER_ID}});
localStorage.setItem('readChapters', JSON.stringify(readChapters));
}
// 主题切换
const themeToggle = document.getElementById('themeToggle');
const savedTheme = localStorage.getItem('theme') || 'dark';
document.documentElement.setAttribute('data-theme', savedTheme);
themeToggle.textContent = savedTheme === 'dark' ? '浅色' : '深色';
themeToggle.addEventListener('click', () => {
const currentTheme = document.documentElement.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
themeToggle.textContent = newTheme === 'dark' ? '浅色' : '深色';
});
// 滚动到顶部
document.getElementById('scrollTop').addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// 滚动到底部
document.getElementById('scrollBottom').addEventListener('click', () => {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
});
// 页面加载时,侧边栏自动滚动到当前章节
window.addEventListener('load', () => {
const sidebarContent = document.getElementById('sidebarContent');
const currentChapter = sidebarContent.querySelector('.current');
if (currentChapter) {
currentChapter.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
});
// ========== TTS语音朗读功能 ==========
let ttsSynth = window.speechSynthesis;
let ttsUtterance = null;
let ttsText = '';
let ttsSentences = [];
let ttsCurrentIndex = 0;
let ttsIsPlaying = false;
let ttsIsPaused = false;
let ttsSpeed = 1;
// 初始化:提取章节内容
function initTTS() {
const contentEl = document.querySelector('.chapter-content');
if (!contentEl) return;
// 获取所有段落文本清理HTML标签
ttsText = contentEl.innerText || contentEl.textContent;
// 分割成句子(中文按句号、问号、感叹号分割)
ttsSentences = ttsText.match(/[^。!?\n]+[。!?\n]+|[^。!?\n]+$/g) || [ttsText];
ttsSentences = ttsSentences.filter(s => s.trim().length > 0);
updateTTSProgress();
}
// 更新进度显示
function updateTTSProgress() {
const total = ttsSentences.length;
const current = ttsCurrentIndex;
document.getElementById('ttsTime').textContent = `${current} / ${total}`;
const percent = total > 0 ? (current / total * 100) : 0;
document.getElementById('ttsProgressFill').style.width = `${percent}%`;
}
// 播放当前句子
function playCurrentSentence() {
if (ttsCurrentIndex >= ttsSentences.length) {
stopTTS();
return;
}
const text = ttsSentences[ttsCurrentIndex].trim();
ttsUtterance = new SpeechSynthesisUtterance(text);
ttsUtterance.lang = 'zh-CN';
ttsUtterance.rate = ttsSpeed;
// 尝试选择中文语音
const voices = ttsSynth.getVoices();
const zhVoice = voices.find(v => v.lang.includes('zh') || v.lang.includes('CN'));
if (zhVoice) {
ttsUtterance.voice = zhVoice;
}
ttsUtterance.onend = () => {
if (ttsIsPlaying && !ttsIsPaused) {
ttsCurrentIndex++;
updateTTSProgress();
playCurrentSentence();
}
};
ttsUtterance.onerror = (e) => {
console.error('TTS error:', e);
if (ttsIsPlaying) {
ttsCurrentIndex++;
updateTTSProgress();
playCurrentSentence();
}
};
ttsSynth.speak(ttsUtterance);
}
// 播放
function playTTS() {
if (ttsSentences.length === 0) {
initTTS();
}
if (ttsIsPaused) {
ttsSynth.resume();
ttsIsPaused = false;
} else {
ttsIsPlaying = true;
playCurrentSentence();
}
document.getElementById('ttsPlay').classList.add('active');
document.getElementById('ttsPause').classList.remove('active');
}
// 暂停
function pauseTTS() {
if (ttsIsPlaying) {
ttsSynth.pause();
ttsIsPaused = true;
document.getElementById('ttsPlay').classList.remove('active');
document.getElementById('ttsPause').classList.add('active');
}
}
// 停止
function stopTTS() {
ttsSynth.cancel();
ttsIsPlaying = false;
ttsIsPaused = false;
ttsCurrentIndex = 0;
updateTTSProgress();
document.getElementById('ttsPlay').classList.remove('active');
document.getElementById('ttsPause').classList.remove('active');
}
// 设置速度
function setTTSSpeed(speed) {
ttsSpeed = parseFloat(speed);
// 如果正在播放,需要重新开始当前句子
if (ttsIsPlaying && !ttsIsPaused) {
ttsSynth.cancel();
playCurrentSentence();
}
}
// 绑定事件
document.getElementById('ttsPlay').addEventListener('click', playTTS);
document.getElementById('ttsPause').addEventListener('click', pauseTTS);
document.getElementById('ttsStop').addEventListener('click', stopTTS);
document.getElementById('ttsSpeed').addEventListener('change', (e) => setTTSSpeed(e.target.value));
// 加载语音列表(某些浏览器需要异步加载)
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = initTTS;
}
// 页面加载时初始化
window.addEventListener('load', () => {
initTTS();
});
// 页面离开时停止播放
window.addEventListener('beforeunload', stopTTS);
</script>
</body>
</html>