108 lines
4.5 KiB
PHP
108 lines
4.5 KiB
PHP
<?php
|
||||
|
|
/**
|
|||
|
|
* 在线阅读(v24 第 14 批 用户第 5 条:「可以点开图书进行查看、阅读」)。
|
|||
|
|
*
|
|||
|
|
* 两种读法,按文件类型分:
|
|||
|
|
* · 解析出正文的(EPUB / TXT)→ 直接把这一章的文本铺在这里(目录在侧栏);
|
|||
|
|
* · PDF(服务端不提取正文)→ 用浏览器自带的 PDF 阅读器内嵌看,排版不会丢。
|
|||
|
|
*
|
|||
|
|
* ⚠️ 翻章就顺手**记进度**(读到第几章):下次点"继续读"直接回到这里。
|
|||
|
|
* 这件事必须自动做 —— 让人手动记"我读到第几章"的阅读器没人会用。
|
|||
|
|
*
|
|||
|
|
* @param array $b 书
|
|||
|
|
* @param array $chapters 目录
|
|||
|
|
* @param array|null $chapter 当前章(含正文)
|
|||
|
|
* @param int $seq 当前章号
|
|||
|
|
*/
|
|||
|
|
$canWrite = \App\Auth::canWrite();
|
|||
|
|
$seq = (int)($seq ?? 1);
|
|||
|
|
$total = count($chapters);
|
|||
|
|
$isPdf = \App\BookParser::inlinable($b['file_format'] ?? '');
|
|||
|
|
$prev = $seq > 1 ? $seq - 1 : 0;
|
|||
|
|
$next = $seq < $total ? $seq + 1 : 0;
|
|||
|
|
?>
|
|||
|
|
<div class="page-head">
|
|||
|
|
<h1><?= e((string)$b['title']) ?></h1>
|
|||
|
|
<span class="sub">
|
|||
|
|
<?= $isPdf ? 'PDF · 浏览器内嵌阅读'
|
|||
|
|
: ('第 ' . $seq . ' / ' . max(1, $total) . ' 章'
|
|||
|
|
. ($chapter ? ' · ' . e((string)$chapter['title']) : '')) ?>
|
|||
|
|
</span>
|
|||
|
|
<div class="actions">
|
|||
|
|
<?php if ($canWrite): ?>
|
|||
|
|
<?php /* 最后一章读完 → 顺手就能标完(这一步做掉了,人才会真的点) */ ?>
|
|||
|
|
<form method="post" action="<?= e(url('books/status')) ?>" class="res-inline">
|
|||
|
|
<?= csrf_field() ?>
|
|||
|
|
<input type="hidden" name="id" value="<?= (int)$b['id'] ?>">
|
|||
|
|
<input type="hidden" name="status" value="done">
|
|||
|
|
<button class="btn<?= (string)$b['status'] === 'done' ? ' btn-ghost' : '' ?>" type="submit">
|
|||
|
|
<?= (string)$b['status'] === 'done' ? '已读完(点这退回在读)' : '读完了' ?>
|
|||
|
|
</button>
|
|||
|
|
</form>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
<a class="btn btn-ghost" href="<?= e(url('books/show', ['id' => (int)$b['id']])) ?>">这本书</a>
|
|||
|
|
<a class="btn btn-ghost" href="<?= e(url('books')) ?>">书架</a>
|
|||
|
|
<?php $bkSetCurrent = 'read'; require __DIR__ . '/_settings_menu.php'; ?>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="book-read">
|
|||
|
|
<?php if (!$isPdf && $total > 0): ?>
|
|||
|
|
<aside class="br-side">
|
|||
|
|
<div class="br-side-h">目录</div>
|
|||
|
|
<ol class="br-toc">
|
|||
|
|
<?php foreach ($chapters as $c): ?>
|
|||
|
|
<li<?= (int)$c['seq'] === $seq ? ' class="is-cur"' : '' ?>>
|
|||
|
|
<a href="<?= e(url('books/read', ['id' => (int)$b['id'], 'seq' => (int)$c['seq']])) ?>">
|
|||
|
|
<?= e((string)$c['title']) ?>
|
|||
|
|
</a>
|
|||
|
|
</li>
|
|||
|
|
<?php endforeach; ?>
|
|||
|
|
</ol>
|
|||
|
|
</aside>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
|
|||
|
|
<div class="br-main">
|
|||
|
|
<?php if ($isPdf): ?>
|
|||
|
|
<?php /* PDF:交给浏览器自己的阅读器。object 比 iframe 兼容性更好,
|
|||
|
|
里面那句提示是"浏览器不支持内嵌"时才显示的兜底。 */ ?>
|
|||
|
|
<div class="br-pdf">
|
|||
|
|
<object data="<?= e(media_url((string)$b['file_key'])) ?>" type="application/pdf">
|
|||
|
|
<p class="empty-hint">
|
|||
|
|
这个浏览器不能直接内嵌看 PDF。
|
|||
|
|
<a href="<?= e(media_url((string)$b['file_key'], ['dl' => 1])) ?>">点这里下载</a>后再看。
|
|||
|
|
</p>
|
|||
|
|
</object>
|
|||
|
|
</div>
|
|||
|
|
<?php elseif (!$chapter): ?>
|
|||
|
|
<p class="empty-hint">
|
|||
|
|
这本书还没有解析出正文。<?php if ($canWrite): ?>
|
|||
|
|
到「编辑」里重新上传一次文件(EPUB / TXT 会自动拆章)。<?php endif; ?>
|
|||
|
|
</p>
|
|||
|
|
<?php else: ?>
|
|||
|
|
<article class="br-text">
|
|||
|
|
<h2 class="br-ch-title"><?= e((string)$chapter['title']) ?></h2>
|
|||
|
|
<?php /* ⚠️ 正文是**纯文本**:nl2br + 转义,绝不 innerHTML ——
|
|||
|
|
书的内容来自用户上传的文件,当成不可信输入处理。 */ ?>
|
|||
|
|
<div class="br-body"><?= nl2br(e((string)$chapter['content'])) ?></div>
|
|||
|
|
</article>
|
|||
|
|
|
|||
|
|
<div class="br-nav">
|
|||
|
|
<?php if ($prev > 0): ?>
|
|||
|
|
<a class="btn btn-ghost" href="<?= e(url('books/read', ['id' => (int)$b['id'], 'seq' => $prev])) ?>">
|
|||
|
|
← 上一章
|
|||
|
|
</a>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
<span class="br-pos small muted"><?= $seq ?> / <?= $total ?></span>
|
|||
|
|
<?php if ($next > 0): ?>
|
|||
|
|
<a class="btn" href="<?= e(url('books/read', ['id' => (int)$b['id'], 'seq' => $next])) ?>">
|
|||
|
|
下一章 →
|
|||
|
|
</a>
|
|||
|
|
<?php else: ?>
|
|||
|
|
<span class="small muted">已经是最后一章了</span>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
</div>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
</div>
|
|||
|
|
</div>
|