Files
FamilyBook/templates/books/form.php
T

214 lines
9.4 KiB
PHP
Raw Normal View History

<?php
/**
* 添加 / 编辑一本书(v24 第 14 批 用户第 5 条)。
*
* 两条进书的路线,**同一张表单**:
* ① 上传文件(EPUB / TXT)→ 服务端解析出书名、作者、简介、封面与**每一章正文**;
* 解析出来的值只填**空着的**字段(用户已经手填的不覆盖)。
* ② 手填一条"想读的书"(还没电子版时先记一笔)。
*
* ⚠️ 文件与封面是两个**不同**的上传位:
* 文件是原书(整存,可能几十 MB),封面是一张图(走裁剪,2:3)。
* 混成一个会让"换封面"变成"重新上传整本书"。
*
* @param array|null $b 编辑时的书;null = 新建
* @param array $people 名册("谁的书")
* @param array $errors 校验错误
*/
$isEdit = !empty($b);
$canWrite = \App\Auth::canWrite();
$people = $people ?? [];
$errors = $errors ?? [];
$cvSlot = \App\ImageSlot::get('bookcover') ?: ['ratio' => '2:3', 'w' => 600, 'h' => 900,
'label' => '封面', 'hint' => ''];
$curCover = $isEdit ? (string)($b['cover_key'] ?? '') : '';
$rate = $isEdit && $b['rating'] !== null ? (int)$b['rating'] : -1;
$ownerSel = $isEdit && (int)($b['owner_id'] ?? 0) > 0 ? [(int)$b['owner_id']] : [];
?>
<div class="page-head">
<h1><?= $isEdit ? '编辑图书' : '添加图书' ?></h1>
<div class="actions">
<a class="btn btn-ghost" href="<?= e($isEdit ? url('books/show', ['id' => (int)$b['id']]) : url('books')) ?>">
<?= $isEdit ? '返回这本书' : '返回书架' ?>
</a>
<?php $bkSetCurrent = 'form'; require __DIR__ . '/_settings_menu.php'; ?>
</div>
</div>
<div class="card card-pad">
<form method="post" enctype="multipart/form-data"
action="<?= e(url($isEdit ? 'books/update' : 'books/create')) ?>">
<?= csrf_field() ?>
<?php if ($isEdit): ?>
<input type="hidden" name="id" value="<?= (int)$b['id'] ?>">
<?php endif; ?>
<?php /* ---- ① 上传图书文件(解析的入口)----
⚠️ 放在最上面:多数人是"先传书、再让系统填好",
把文件框藏在最底下会让人以为只能手填。 */ ?>
<div class="field full">
<label for="bk-file">上传图书(EPUB / TXT / PDF…)</label>
<?php if ($isEdit && !empty($b['file_key'])): ?>
<p class="bk-file-now">
已存文件:<?= e((string)($b['file_name'] ?: $b['file_key'])) ?>
(<?= e(\App\Book::sizeWord($b['file_size'] ?? 0) ?: '大小未知') ?>)
<?php if ((int)($b['chapter_count'] ?? 0) > 0): ?>
· 已解析 <?= (int)$b['chapter_count'] ?> 章
<?php endif; ?>
<br><span class="tip">再选一个文件会替换它,并按新文件重新解析正文。</span>
</p>
<?php endif; ?>
<?php $sdName = 'bookfile'; $sdId = 'bk-file';
$sdAccept = '.epub,.txt,.pdf,.mobi,.azw3,.azw,.doc,.docx,application/epub+zip,text/plain,application/pdf';
$sdMultiple = false;
require __DIR__ . '/../_stage_drop.php'; ?>
<span class="tip">
EPUB 与 TXT 会自动读出书名 / 作者 / 简介 / 封面,并把正文拆成章节(可以直接在线读)。
PDF 只存文件(用浏览器自带的阅读器看)。MOBI / AZW3 存文件、正文解析不了。
</span>
</div>
<div class="form-grid">
<div class="field full">
<label class="is-req" for="bk-title">书名</label>
<input class="input" id="bk-title" name="title" required
value="<?= e(old('title', $b['title'] ?? '')) ?>" placeholder="如:活着">
<?php if (!empty($errors['title'])): ?><span class="err"><?= e($errors['title']) ?></span><?php endif; ?>
</div>
<div class="field">
<label for="bk-sub">副标题</label>
<input class="input" id="bk-sub" name="subtitle"
value="<?= e(old('subtitle', $b['subtitle'] ?? '')) ?>">
</div>
<div class="field">
<label for="bk-author">作者</label>
<input class="input" id="bk-author" name="author"
value="<?= e(old('author', $b['author'] ?? '')) ?>" placeholder="如:余华">
</div>
<div class="field">
<label for="bk-trans">译者</label>
<input class="input" id="bk-trans" name="translator"
value="<?= e(old('translator', $b['translator'] ?? '')) ?>">
</div>
<div class="field">
<label for="bk-pub">出版社</label>
<input class="input" id="bk-pub" name="publisher"
value="<?= e(old('publisher', $b['publisher'] ?? '')) ?>">
</div>
<div class="field">
<label for="bk-date">出版时间</label>
<input class="input" id="bk-date" name="published"
value="<?= e(old('published', $b['published'] ?? '')) ?>" placeholder="如:2012 或 2012-05">
</div>
<div class="field">
<label for="bk-isbn">ISBN</label>
<input class="input" id="bk-isbn" name="isbn" value="<?= e(old('isbn', $b['isbn'] ?? '')) ?>">
</div>
<div class="field">
<label for="bk-lang">语言</label>
<input class="input" id="bk-lang" name="language"
value="<?= e(old('language', $b['language'] ?? '')) ?>" placeholder="如:中文">
</div>
<div class="field">
<label for="bk-cat">分类</label>
<input class="input" id="bk-cat" name="category"
value="<?= e(old('category', $b['category'] ?? '')) ?>" placeholder="如:小说 / 历史 / 技术">
</div>
<div class="field">
<label for="bk-tags">标签(逗号分隔)</label>
<input class="input" id="bk-tags" name="tags" value="<?= e(old('tags', $b['tags'] ?? '')) ?>"
placeholder="如:长篇,当代文学">
</div>
<div class="field">
<label for="bk-status">状态</label>
<select class="select" id="bk-status" name="status">
<?php foreach (\App\Book::STATUS as $sk => $sv): ?>
<option value="<?= e($sk) ?>"
<?= old('status', $b['status'] ?? 'wish') === $sk ? 'selected' : '' ?>><?= e($sv) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="field">
<label for="bk-rate">评分</label>
<select class="select" id="bk-rate" name="rating">
<option value="" <?= $rate < 0 ? 'selected' : '' ?>>还没打分</option>
<?php for ($bi = 0; $bi <= 10; $bi++): ?>
<option value="<?= $bi ?>" <?= $rate === $bi ? 'selected' : '' ?>><?= $bi ?> 分</option>
<?php endfor; ?>
</select>
</div>
<div class="field">
<label for="bk-pages">页数</label>
<input class="input" type="number" min="0" id="bk-pages" name="pages"
value="<?= e((string)old('pages', $b['pages'] ?? '')) ?>" placeholder="有就填,用于统计">
</div>
<div class="field">
<label>谁的书</label>
<?php /* 与全站统一的选人组件(弹窗 + 头像 + 拼音联想);
留「不指定」= 全家共用这一本。 */ ?>
<?php
$ppName = 'owner_id';
$ppPeople = $people;
$ppSelected = $ownerSel;
$ppMode = 'single';
$ppOpenBtn = '选择是谁在读';
$ppTitle = '这本书是谁的';
$ppEmptyText = '全家共用';
$ppAllowEmpty = true;
require __DIR__ . '/../_person_picker.php';
?>
</div>
<div class="field full">
<label for="bk-sum">内容简介</label>
<textarea class="input" id="bk-sum" name="summary" rows="4"><?= e(old('summary', $b['summary'] ?? '')) ?></textarea>
</div>
<?php /* ---- ② 封面(与头像同一套裁剪,2:3)---- */ ?>
<div class="field full">
<label>封面</label>
<div class="cover-picker book-cover-picker">
<?php /* ⚠️ data-pick-input 是 app.js 里的通用"点图选文件"绑定 ——
少了它这块图点下去毫无反应(本批用户报的就是这个)。 */ ?>
<img id="book-cover-preview"
src="<?= e($curCover !== '' ? media_url($curCover) : '') ?>"
alt="" title="点击选封面"
data-pick-input="#bk-cover"
data-has-cover="<?= $curCover !== '' ? '1' : '0' ?>">
<input class="sr-only" id="bk-cover" name="cover" type="file" accept="image/*"
data-crop-ratio="<?= e((string)$cvSlot['ratio']) ?>"
data-crop-w="<?= (int)$cvSlot['w'] ?>"
data-crop-h="<?= (int)$cvSlot['h'] ?>"
data-crop-label="<?= e((string)$cvSlot['label']) ?>"
data-crop-hint="<?= e((string)$cvSlot['hint']) ?>"
data-crop-preview="#book-cover-preview">
<input type="hidden" name="cover_crop" value="">
<span class="avatar-hint small muted">
点左边那块选封面,选完弹裁剪框。<br>
上传 EPUB 时如果书里自带封面,会**自动**用它(你另外选一张就覆盖它)。
</span>
</div>
</div>
</div>
<div class="btn-row">
<button class="btn" type="submit"><?= $isEdit ? '保存' : '加进书架' ?></button>
<a class="btn btn-ghost"
href="<?= e($isEdit ? url('books/show', ['id' => (int)$b['id']]) : url('books')) ?>">取消</a>
</div>
</form>
</div>