已读完的书卡改成和「在读」同一套样式,补开始/读完时间

可行性(先说结论)
- 「开始阅读时间」在官方文档里没列,但 /book/getprogress 的原始回包里有
  book.startReadingTime,6 本已读完的全都有
- 顺带纠正我上一轮的错误结论:真正常为 0 的是 recordReadingTime,
  book.readingTime 是有值的(西线无战事 6190 秒 = 103 分),
  已存进 JSON 的 readingSeconds,卡片暂未展示

抽公共组件
- 新增 src/components/reading-card.astro,在读和已读完共用,样式强制统一:
  横版卡片、封面在左、信息在右
- 两处只在底部两行不同:
    在读   进度条 + 百分比 / 最近阅读 X
    已读完 开始 X / 读完 Y(无进度条)

数据层
- fetch-reading.mjs 每个条目新增 startedAt / finishedAt / readingSeconds
- src/lib/reading.ts 的 ReadingBook 类型同步补上(都可选,老数据不会炸)
- startReadingTime / finishTime 缺失时卡片自动少一行,不会渲染出「开始 —」

时间显示走 Asia/Shanghai。所以西线无战事的 startReadingTime
1786207913(UTC 08-08T15:31Z)在页面上是「开始 2026-08-09」,
这才是本地日期。

静态验证(dist/bookshelf/index.html)
- 在读区 20 张卡 / 20 条进度条 / 20 个「最近阅读」
- 已读完区 6 张卡 / 0 条进度条 / 6 个「开始 X」/ 6 个「读完 X」
- 抽一张:西线无战事(译文经典) 雷马克 · 文学-外国文学
  开始 2026-08-09 读完 2026-09-06,确认不含进度条
- 搜索/领域筛选的 data-weread-card 仍挂在新卡片上,筛选不受影响
This commit is contained in:
dsh
2026-09-15 10:51:50 +08:00
parent 4df235ea21
commit 8a867132de
6 changed files with 208 additions and 98 deletions
+10 -2
View File
@@ -297,7 +297,8 @@ src/components/bookshelf-content.astro
- 请求体里 `skill_version` **必填**,业务参数**平铺在顶层**,不能包进 `params`
- `/shelf/sync` 一次就给全封面/书名/作者/分类/最近阅读时间/跳转链接,**只有阅读进度**要额外调 `/book/getprogress`,所以请求数 = 1 + N
- `book.progress` 是 0–100 的整数,**只有 100 才算读完**
- `book.recordReadingTime` **恒为 0**,所以卡片不做「累计时长」
- `book.recordReadingTime` **恒为 0**(别用它),但 `book.readingTime` 是真数据,累计时长取后者(已存进 JSON 的 `readingSeconds`,卡片暂未展示)
- `book.startReadingTime` **官方文档没列,但回包里确实有**,就是「开始阅读时间」;只有 readUpdateTime 那 26 本里有 8 本没有它(基本都是没怎么打开的书)
- `deepLink` 实测是普通 https(`https://weread.qq.com/book-detail?...`),浏览器能直接打开
- `category` 是 `文学-外国文学` 这种「大类-子类」复合串
- 时间戳统一按 `YYYY-MM-DD` 展示(官方硬性要求),顺带避开「N 天前」在静态站上会随构建时间变旧
@@ -309,7 +310,14 @@ src/components/bookshelf-content.astro
| 最近在读 | `progress < 100`(含 0%,标「还没开始」) |
| 书籍 → 「微信读书 · 已读完」分组 | `progress === 100` |
这一组混在「书籍」区的网格里,卡片结构和手工书单一致,但没有书评/简介,所以点击是直接跳微信读书而不是弹窗。它们带 `data-weread-card` 和 `data-category="微信读书"`,所以搜索框和「领域」筛选同样作用得到(领域里会多出一个「微信读书」选项)。过滤掉的:私密阅读(`secret === 1`)、从没打开过的书;有声书不处理。
**两处用的是同一个组件 `src/components/reading-card.astro`**,保证样式统一 —— 横版卡片、封面在左、信息在右,只有底部两行不同:
| | 第 1 行 | 第 2 行 |
|---|---|---|
| 在读 | 进度条 + 百分比 | 最近阅读 X |
| 已读完 | 开始 X | 读完 Y |
「已读完」那一组混在「书籍」区里,但没有书评/简介,所以点击直接跳微信读书而不是弹窗。它们带 `data-weread-card` 和 `data-category="微信读书"`,所以搜索框和「领域」筛选同样作用得到(领域里会多出一个「微信读书」选项)。过滤掉的:私密阅读(`secret === 1`)、从没打开过的书;有声书不处理。
**2. 书籍** —— 来自 `public/data/books.json`,由 `bookshelf-content.astro` 在构建时 import(文件必须存在)。另外两个文件 `papers.json` / `comics.json` 对应的漫画、论文分类已经移除,文件保留但不再被引用。