书籍页:手工书单为空时隐藏统计行和搜索/筛选条

books.json 是空的,所以「书籍」页顶上挂着一排
「0 本已读 / 0 本推荐 / 0 个领域」加搜索框、领域和评价筛选 ——
没数据可显示也没东西可筛,纯占地方。

改成 hasManualBooks = allBooks.length > 0 控制:
- 为空时整块(统计行 + 搜索框 + 领域筛选 + 评价筛选)不渲染
- 往 books.json 加了书自动回来,不用改代码
- 顺带补一个兜底空态:手工书单和微信读书都已读完都为空时,
  显示「书架还是空的」并提示两条填充路径

验证(双向都测了)
- books.json 为空时构建:本已读 / data-bookshelf-search /
  data-filter-books-category / data-filter-books-status 在产物里均 0 次;
  已读完分组和 6 张卡片不受影响
- 临时往 books.json 注入 1 本假书再构建:统计行、搜索框、领域筛选、
  评价筛选、手工书卡全部出现(测完已 git checkout 还原)
- 在读页未受影响:20 张卡 / 20 条进度条
This commit is contained in:
dsh
2026-09-15 11:05:39 +08:00
parent 95e5111fd8
commit a88bb536ab
3 changed files with 24 additions and 2 deletions
+21 -1
View File
@@ -63,6 +63,9 @@ const booksByCategory = allBooks.reduce<Record<string, BookRecord[]>>((acc, book
const bookCategories = ["全部", ...Object.keys(booksByCategory), ...(finishedReading.length > 0 ? [WEREAD_CATEGORY] : [])]
const bookStatuses = ["全部", "推荐", "中庸", "不行"]
/** 手工书单为空时,统计行和搜索/筛选条都没有意义,整块隐藏 */
const hasManualBooks = allBooks.length > 0
const bookStats = {
total: allBooks.length,
recommended: allBooks.filter((b) => b.fields.推荐状态 === "推荐").length,
@@ -202,7 +205,11 @@ const recommendBadge = (status?: string) => {
<div class="text-sm italic font-serif text-muted-foreground">博学而笃志,切问而近思</div>
</div>
{/* ---------- Stats ---------- */}
{/* ---------- Stats + Search + filters ----------
只有存在手工书单时才显示。books.json 为空时这三行都是「0 本已读 /
0 本推荐 / 0 个领域」加一排没东西可筛的按钮,纯占地方。 */}
{hasManualBooks && (
<>
<div class="flex flex-wrap gap-x-7 gap-y-2 text-sm text-muted-foreground mb-7">
<span class="flex items-baseline gap-2"><span class="text-primary font-semibold text-base font-serif tabular-nums">{bookStats.total}</span><span>本已读</span></span>
<span class="flex items-baseline gap-2"><span class="text-primary font-semibold text-base font-serif tabular-nums">{bookStats.recommended}</span><span>本推荐</span></span>
@@ -259,6 +266,8 @@ const recommendBadge = (status?: string) => {
</div>
</div>
</>
)}
{/* ========================= Views ========================= */}
@@ -359,6 +368,17 @@ const recommendBadge = (status?: string) => {
)}
</div>
{/* 手工书单和微信读书都已读完都为空时的兜底 */}
{!hasManualBooks && finishedReading.length === 0 && (
<div class="py-16 text-center border border-dashed border-border rounded-xl">
<p class="text-muted-foreground mb-2">书架还是空的。</p>
<p class="text-xs text-muted-foreground/70">
往 <code class="px-1 py-0.5 rounded bg-muted font-mono">public/data/books.json</code> 里加书,
或跑一次 <code class="px-1 py-0.5 rounded bg-muted font-mono">pnpm reading</code> 同步微信读书。
</p>
</div>
)}
{/* Empty state (shared, shown when filters return nothing) */}
<div data-empty-state class="hidden text-center py-16">
<span class="inline-flex h-12 w-12 items-center justify-center text-muted-foreground/30 mx-auto mb-4">
+1 -1
View File
@@ -1,5 +1,5 @@
{
"updatedAt": "2026-09-15T02:58:11.129Z",
"updatedAt": "2026-09-15T03:05:33.930Z",
"source": "weread",
"books": [
{