HTML5 在线漫画阅读器 (index.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=3,user-scalable=yes">
<title>久保同学不放过我 - 在线漫画阅读器</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{background:#0d0f17;color:#f1f5f9;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;min-height:100vh;display:flex;flex-direction:column}
header{position:sticky;top:0;z-index:50;background:rgba(13,15,23,0.92);backdrop-filter:blur(12px);border-bottom:1px solid rgba(255,255,255,0.09);padding:10px 16px;display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:10px}
.badge{background:linear-gradient(135deg,#ec4899,#8b5cf6);color:#fff;font-size:11px;font-weight:700;padding:3px 8px;border-radius:99px}
.title{font-size:16px;font-weight:700;color:#fff}
.controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
button{background:rgba(255,255,255,0.08);color:#e2e8f0;border:1px solid rgba(255,255,255,0.14);padding:6px 12px;border-radius:8px;font-size:12px;cursor:pointer;transition:.18s}
button:hover,button.active{background:#ec4899;color:#fff;border-color:#ec4899}
.hero{max-width:920px;margin:16px auto;padding:18px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:14px;display:flex;gap:18px;align-items:flex-start}
.hero img{width:120px;height:160px;object-fit:cover;border-radius:10px;flex-shrink:0;box-shadow:0 8px 24px rgba(0,0,0,0.45)}
.hero-meta h1{font-size:20px;margin-bottom:6px}
.hero-meta .sub{font-size:13px;color:#94a3b8;margin-bottom:8px}
.tags{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}
.tag{background:rgba(236,72,153,0.16);color:#f472b6;padding:2px 8px;border-radius:6px;font-size:11px}
.desc{font-size:13px;line-height:1.6;color:#cbd5e1}
.reader-wrap{max-width:860px;width:100%;margin:0 auto 40px;padding:0 8px;flex:1}
.scroll-mode .page-card{margin-bottom:10px;background:#161925;border-radius:8px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,0.4)}
.scroll-mode .page-card img{width:100%;height:auto;display:block}
.page-footer{text-align:center;font-size:11px;color:#64748b;padding:4px 0}
.flip-controls{display:none;justify-content:center;align-items:center;gap:14px;margin:14px 0}
.flip-mode .flip-controls{display:flex}
.drawer{display:none;max-width:920px;margin:0 auto 20px;padding:16px;background:rgba(255,255,255,0.04);border-radius:12px;border:1px solid rgba(255,255,255,0.1)}
.drawer.open{display:block}
.chap-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:8px;margin-top:10px}
.chap-item{padding:8px 10px;background:rgba(255,255,255,0.06);border-radius:8px;font-size:12px;color:#e2e8f0;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chap-item:hover{background:rgba(236,72,153,0.28)}
@media(max-width:600px){.hero{flex-direction:column;align-items:center;text-align:center}.tags{justify-content:center}}
</style>
</head>
<body>
<header>
<div class="brand">
<span class="badge">BILIMANGA · 统一媒体库</span>
<span class="title" id="hdrTitle"></span>
</div>
<div class="controls">
<button id="btnScroll" class="active" onclick="setMode('scroll')">条漫下拉模式</button>
<button id="btnFlip" onclick="setMode('flip')">单页翻页模式</button>
<button onclick="toggleCatalog()">章节目录 (<span id="chapCount">0</span>)</button>
<button onclick="cycleLang()" id="btnLang">繁/簡/EN</button>
</div>
</header>
<section class="hero">
<img id="heroCover" src="" alt="cover">
<div class="hero-meta">
<h1 id="heroTitle"></h1>
<div class="sub" id="heroSub"></div>
<div class="tags" id="heroTags"></div>
<p class="desc" id="heroDesc"></p>
</div>
</section>
<section class="drawer" id="catDrawer">
<h3 style="font-size:14px;margin-bottom:6px">全卷章节目录 (点击切换预览章节)</h3>
<div class="chap-grid" id="chapGrid"></div>
</section>
<div class="reader-wrap scroll-mode" id="readerWrap">
<div class="flip-controls">
<button onclick="stepPage(-1)">◀ 上一页</button>
<span id="pageIndicator" style="font-size:13px;color:#cbd5e1">1 / 1</span>
<button onclick="stepPage(1)">下一页 ▶</button>
</div>
<div id="pagesContainer"></div>
</div>
<script>
const COMIC = {"slug": "bilimanga-325", "mangaid": "325", "zh_title": "久保同学不放过我", "hant_title": "久保同學不放過我", "en_title": "久保同学不放过我 (Bilimanga #325)", "author": "雪森宁々", "tags": ["校园", "日常", "恋爱", "欢乐", "校园青春", "日本漫画", "漫画", "日漫"], "zh_desc": "白石纯太是个存在感极低,就算站在班上同学或老师旁边,也不会被察觉到的「路人」男,然而却有一位同学总是会发现他的存在,并一再捉弄他。这位同学名叫久保渚咲,是位眉清目秀,头脑聪明的「女主角级」美少女。每次久保同学找上白石同学,都让白石同学原本平凡的生活有全新的感受,也让两人对彼此有著距离「恋爱」还差那么一点点的感情…\n\n📚 作品信息:作者 雪森宁々 · 评分 10 · 共收录 12 卷 / 155 话章节目录与高清彩页/条漫预览。", "hant_desc": "白石純太是個存在感極低,就算站在班上同學或老師旁邊,也不會被察覺到的「路人」男,然而卻有一位同學總是會發現他的存在,並一再捉弄他。這位同學名叫久保渚咲,是位眉清目秀,頭腦聰明的「女主角級」美少女。每次久保同學找上白石同學,都讓白石同學原本平凡的生活有全新的感受,也讓兩人對彼此有著距離「戀愛」還差那麼一點點的感情…\n\n📚 作品資訊:作者 雪森寧々 · 評分 10 · 共收錄 12 卷 / 155 話章節目錄與高清彩頁/條漫預覽。", "en_desc": "Popular serialized manga '久保同学不放过我' (久保同學不放過我) by 雪森宁々. Includes 12 volumes and 155 chapters with full online vertical/page-flip web reader.", "pages": ["https://media.huangguodrama.ai/motion/comics/bilimanga-325/page_01.jpg", "https://media.huangguodrama.ai/motion/comics/bilimanga-325/page_02.jpg", "https://media.huangguodrama.ai/motion/comics/bilimanga-325/page_03.jpg", "https://media.huangguodrama.ai/motion/comics/bilimanga-325/page_04.jpg", "https://media.huangguodrama.ai/motion/comics/bilimanga-325/page_05.jpg", "https://media.huangguodrama.ai/motion/comics/bilimanga-325/page_06.jpg"], "volumes": [{"title_hant": "久保同學不放過我 1", "title_zh": "久保同学不放过我 1", "cover_id": 593797, "first_chap_id": 27595, "cover_url": "https://i.motiezw.com/cover/325/593797.jpg"}, {"title_hant": "久保同學不放過我 2", "title_zh": "久保同学不放过我 2", "cover_id": 593963, "first_chap_id": 27609, "cover_url": "https://i.motiezw.com/cover/325/593963.jpg"}, {"title_hant": "久保同學不放過我 3", "title_zh": "久保同学不放过我 3", "cover_id": 594119, "first_chap_id": 27625, "cover_url": "https://i.motiezw.com/cover/325/594119.jpg"}, {"title_hant": "久保同學不放過我 4", "title_zh": "久保同学不放过我 4", "cover_id": 594284, "first_chap_id": 27639, "cover_url": "https://i.motiezw.com/cover/325/594284.jpg"}, {"title_hant": "久保同學不放過我 5", "title_zh": "久保同学不放过我 5", "cover_id": 594449, "first_chap_id": 27653, "cover_url": "https://i.motiezw.com/cover/325/594449.jpg"}, {"title_hant": "久保同學不放過我 6", "title_zh": "久保同学不放过我 6", "cover_id": 594614, "first_chap_id": 27667, "cover_url": "https://i.motiezw.com/cover/325/594614.jpg"}, {"title_hant": "久保同學不放過我 7", "title_zh": "久保同学不放过我 7", "cover_id": 1538063, "first_chap_id": 70817, "cover_url": "https://i.motiezw.com/cover/325/1538063.jpg"}, {"title_hant": "久保同學不放過我 8", "title_zh": "久保同学不放过我 8", "cover_id": 2389479, "first_chap_id": 110559, "cover_url": "https://i.motiezw.com/cover/325/2389479.jpg"}, {"title_hant": "久保同學不放過我 9", "title_zh": "久保同学不放过我 9", "cover_id": 2389647, "first_chap_id": 110573, "cover_url": "https://i.motiezw.com/cover/325/2389647.jpg"}, {"title_hant": "久保同學不放過我 10", "title_zh": "久保同学不放过我 10", "cover_id": 2389798, "first_chap_id": 110586, "cover_url": "https://i.motiezw.com/cover/325/2389798.jpg"}, {"title_hant": "久保同學不放過我 11", "title_zh": "久保同学不放过我 11", "cover_id": 2389963, "first_chap_id": 110600, "cover_url": "https://i.motiezw.com/cover/325/2389963.jpg"}, {"title_hant": "久保同學不放過我 12", "title_zh": "久保同学不放过我 12", "cover_id": 2390138, "first_chap_id": 110615, "cover_url": "https://i.motiezw.com/cover/325/2390138.jpg"}], "chapters": [{"cid": "27595", "title": "episode. 001 N主角與路人男", "title_zh": "episode. 001 N主角与路人男"}, {"cid": "27596", "title": "episode. 002 不開心與膝上", "title_zh": "episode. 002 不开心与膝上"}, {"cid": "27597", "title": "episode. 003 回答權與愛管閒事", "title_zh": "episode. 003 回答权与爱管闲事"}, {"cid": "27598", "title": "episode. 004 隨身面紙與自拍", "title_zh": "episode. 004 随身面纸与自拍"}, {"cid": "27599", "title": "episode. 005 馬尾與止汗濕紙巾", "title_zh": "episode. 005 马尾与止汗湿纸巾"}, {"cid": "27600", "title": "episode. 006 自動門與上學路上", "title_zh": "episode. 006 自动门与上学路上"}, {"cid": "27601", "title": "episode. 007 不幸與家庭訪問", "title_zh": "episode. 007 不幸与家庭访问"}, {"cid": "27602", "title": "episode. 008 出門前的打扮與平凡無奇的一天", "title_zh": "episode. 008 出门前的打扮与平凡无奇的一天"}, {"cid": "27603", "title": "episode. 009 雪與熱可可", "title_zh": "episode. 009 雪与热可可"}, {"cid": "27604", "title": "episode. 010 書店與自卑感", "title_zh": "episode. 010 书店与自卑感"}, {"cid": "27605", "title": "extra episode.打瞌睡", "title_zh": "extra episode.打瞌睡"}, {"cid": "27606", "title": "extra episode.身高差", "title_zh": "extra episode.身高差"}, {"cid": "27607", "title": "special episode.凡人的贈禮", "title_zh": "special episode.凡人的赠礼"}, {"cid": "27609", "title": "episode.011 舊歲與視訊通話", "title_zh": "episode.011 旧岁与视讯通话"}, {"cid": "27610", "title": "episode.012 襪子與不協調感", "title_zh": "episode.012 袜子与不协调感"}, {"cid": "27611", "title": "episode.013 紅S愛心與送禮者", "title_zh": "episode.013 红S爱心与送礼者"}, {"cid": "27612", "title": "episode.014 料理白痴與Q人節前夜", "title_zh": "episode.014 料理白痴与Q人节前夜"}, {"cid": "27613", "title": "episode.015 N孩話題與獨占慾", "title_zh": "episode.015 N孩话题与独占欲"}, {"cid": "27614", "title": "episode.016 初體驗與抹茶拿鐵", "title_zh": "episode.016 初体验与抹茶拿铁"}, {"cid": "27615", "title": "episode.017 早起與耳機孔", "title_zh": "episode.017 早起与耳机孔"}, {"cid": "27616", "title": "episode.018 白SQ人節與感Q的收件者", "title_zh": "episode.018 白SQ人节与感Q的收件者"}, {"cid": "27617", "title": "episode.019 DNA與嚮往", "title_zh": "episode.019 DNA与向往"}, {"cid": "27619", "title": "special episode.你的聲音頻率", "title_zh": "special episode.你的声音频率"}, {"cid": "27620", "title": "extra episode.翹髮", "title_zh": "extra episode.翘发"}, {"cid": "27621", "title": "extra episode.學生手冊", "title_zh": "extra episode.学生手册"}, {"cid": "27622", "title": "extra episode.交換RINE之後-side.白石純太-", "title_zh": "extra episode.交换RINE之后-side.白石纯太-"}, {"cid": "27623", "title": "extra episode.交換RINE之後-side.久保渚浂-", "title_zh": "extra episode.交换RINE之后-side.久保渚浂-"}, {"cid": "27625", "title": "episode.021 病假與誤傳", "title_zh": "episode.021 病假与误传"}, {"cid": "27626", "title": "episode.022 保健室與主角", "title_zh": "episode.022 保健室与主角"}, {"cid": "27627", "title": "episode.023 雨天與回家路上", "title_zh": "episode.023 雨天与回家路上"}, {"cid": "27628", "title": "episode.024 午休與玉子燒", "title_zh": "episode.024 午休与玉子烧"}, {"cid": "27629", "title": "episode.025 評價與感Q要好的定義", "title_zh": "episode.025 评价与感Q要好的定义"}, {"cid": "27630", "title": "episode.026 紅筆與同一款", "title_zh": "episode.026 红笔与同一款"}, {"cid": "27631", "title": "episode.027 過夜會與下一個學年", "title_zh": "episode.027 过夜会与下一个学年"}, {"cid": "27632", "title": "episode.028 隨你裝與邀約", "title_zh": "episode.028 随你装与邀约"}, {"cid": "27633", "title": "episode.029 再挑戰與首次成功", "title_zh": "episode.029 再挑战与首次成功"}, {"cid": "27634", "title": "episode.030 賞花與漢堡排", "title_zh": "episode.030 赏花与汉堡排"}, {"cid": "27635", "title": "episode.031 賞花與心意交錯", "title_zh": "episode.031 赏花与心意交错"}, {"cid": "27636", "title": "episode.032 新學期與重新分班", "title_zh": "episode.032 新学期与重新分班"}, {"cid": "27637", "title": "extra episode.變身!", "title_zh": "extra episode.变身!"}, {"cid": "27639", "title": "episode.033 委員會與花壇", "title_zh": "episode.033 委员会与花坛"}, {"cid": "27640", "title": "episode.034 朋友與疲橋", "title_zh": "episode.034 朋友与疲桥"}, {"cid": "27641", "title": "episode.035 檸檬與青春", "title_zh": "episode.035 柠檬与青春"}, {"cid": "27642", "title": "episode.036 黑板擦與喜歡的髮型", "title_zh": "episode.036 黑板擦与喜欢的发型"}, {"cid": "27644", "title": "episode.038 比身高與壁咚", "title_zh": "episode.038 比身高与壁咚"}, {"cid": "27645", "title": "episode.039 體檢與運動衫", "title_zh": "episode.039 体检与运动衫"}, {"cid": "27646", "title": "episode.040 劇場版與客滿的電車", "title_zh": "episode.040 剧场版与客满的电车"}, {"cid": "27647", "title": "episode.041 搭訕與上映時間", "title_zh": "episode.041 搭讪与上映时间"}, {"cid": "27648", "title": "episode.042 無糖與砂糖", "title_zh": "episode.042 无糖与砂糖"}, {"cid": "27649", "title": "episode.043 電影院與臉部肌禸", "title_zh": "episode.043 电影院与脸部肌禸"}, {"cid": "27650", "title": "episode.044 白石純太", "title_zh": "episode.044 白石纯太"}, {"cid": "27651", "title": "extra episode.大眼瞪小眼", "title_zh": "extra episode.大眼瞪小眼"}, {"cid": "27653", "title": "episode.045 咖啡與從姊姊獨立", "title_zh": "episode.045 咖啡与从姊姊独立"}, {"cid": "27654", "title": "episode.046 心理測驗與深層心理學", "title_zh": "episode.046 心理测验与深层心理学"}, {"cid": "27655", "title": "episode.047 主角與慶生", "title_zh": "episode.047 主角与庆生"}, {"cid": "27656", "title": "episode.048 Q書與挑戰狀", "title_zh": "episode.048 Q书与挑战状"}, {"cid": "27657", "title": "episode.049 NY與挑選顏S", "title_zh": "episode.049 NY与挑选颜S"}, {"cid": "27658", "title": "episode.050 夏季制服與防禦力", "title_zh": "episode.050 夏季制服与防御力"}, {"cid": "27659", "title": "episode.051 止汗劑與相同香氣", "title_zh": "episode.051 止汗剂与相同香气"}, {"cid": "27660", "title": "episode.052 公園與白三葉草", "title_zh": "episode.052 公园与白三叶草"}]};
let lang = 'zh';
let mode = 'scroll';
let curPage = 0;
function renderMeta() {
const t = lang === 'zh' ? COMIC.zh_title : (lang === 'hant' ? COMIC.hant_title : COMIC.en_title);
const d = lang === 'zh' ? COMIC.zh_desc : (lang === 'hant' ? COMIC.hant_desc : COMIC.en_desc);
document.getElementById('hdrTitle').textContent = t;
document.getElementById('heroTitle').textContent = t;
document.getElementById('heroSub').textContent = `${COMIC.author} · 共 ${COMIC.volumes.length} 卷 / ${COMIC.chapters.length} 话`;
document.getElementById('heroDesc').textContent = d;
document.getElementById('heroCover').src = COMIC.pages[0] || '';
document.getElementById('chapCount').textContent = COMIC.chapters.length;
const tg = document.getElementById('heroTags');
tg.innerHTML = '';
(COMIC.tags || []).forEach(x => {
const s = document.createElement('span');
s.className = 'tag';
s.textContent = x;
tg.appendChild(s);
});
}
function renderCatalog() {
const g = document.getElementById('chapGrid');
g.innerHTML = '';
(COMIC.chapters || []).forEach((c, idx) => {
const d = document.createElement('div');
d.className = 'chap-item';
d.textContent = c.title_zh || c.title;
d.onclick = () => {
curPage = idx % COMIC.pages.length;
if (mode === 'flip') renderPages();
else document.querySelectorAll('.page-card')[curPage]?.scrollIntoView({behavior:'smooth'});
document.getElementById('catDrawer').classList.remove('open');
};
g.appendChild(d);
});
}
function renderPages() {
const wrap = document.getElementById('readerWrap');
wrap.className = 'reader-wrap ' + (mode === 'scroll' ? 'scroll-mode' : 'flip-mode');
const box = document.getElementById('pagesContainer');
box.innerHTML = '';
const list = mode === 'scroll' ? COMIC.pages : [COMIC.pages[curPage]];
list.forEach((url, i) => {
const idx = mode === 'scroll' ? i : curPage;
const card = document.createElement('div');
card.className = 'page-card';
card.innerHTML = `<img src="${url}" loading="lazy" alt="Page ${idx+1}"><div class="page-footer">第 ${idx+1} / ${COMIC.pages.length} 页 · ${COMIC.zh_title}</div>`;
if (mode === 'flip') card.onclick = () => stepPage(1);
box.appendChild(card);
});
document.getElementById('pageIndicator').textContent = `${curPage + 1} / ${COMIC.pages.length}`;
}
function setMode(m) {
mode = m;
document.getElementById('btnScroll').classList.toggle('active', m === 'scroll');
document.getElementById('btnFlip').classList.toggle('active', m === 'flip');
renderPages();
}
function stepPage(delta) {
curPage = (curPage + delta + COMIC.pages.length) % COMIC.pages.length;
renderPages();
}
function toggleCatalog() {
document.getElementById('catDrawer').classList.toggle('open');
}
function cycleLang() {
lang = lang === 'zh' ? 'hant' : (lang === 'hant' ? 'en' : 'zh');
renderMeta();
}
renderMeta();
renderCatalog();
renderPages();
</script>
</body>
</html>