diff --git a/README.md b/README.md index b3875f6..a314cfd 100644 --- a/README.md +++ b/README.md @@ -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` 对应的漫画、论文分类已经移除,文件保留但不再被引用。 diff --git a/scripts/fetch-reading.mjs b/scripts/fetch-reading.mjs index 0914ef1..788e129 100644 --- a/scripts/fetch-reading.mjs +++ b/scripts/fetch-reading.mjs @@ -15,7 +15,8 @@ * 两处实测得到的结论,别被直觉带偏: * 1. /shelf/sync 一次就给全了封面/书名/作者/分类/最近阅读时间/跳转链接, * 只有「阅读进度」要额外调 /book/getprogress,所以请求数 = 1 + N - * 2. book.recordReadingTime 恒为 0,拿不到累计时长,所以卡片不做这一项 + * 2. book.recordReadingTime 恒为 0,但 book.readingTime 是真数据,累计时长取后者 + * 3. 官方文档没列 book.startReadingTime,但回包里有,是「开始阅读时间」 */ import fs from "node:fs" @@ -104,6 +105,12 @@ async function fetchReading() { progress: null, finished: false, lastReadAt: new Date(Number(book.readUpdateTime) * 1000).toISOString(), + // 下面三个来自 /book/getprogress。官方文档没列 startReadingTime, + // 但原始回包里确实有(读完的 6 本全都有),是「开始阅读时间」。 + startedAt: null, + finishedAt: null, + /** 累计阅读秒数。注意是 readingTime,不是恒为 0 的 recordReadingTime */ + readingSeconds: null, deepLink: book.deepLink ?? "", } @@ -115,6 +122,15 @@ async function fetchReading() { // progress 是 0-100 的整数,只有正好 100 才算读完 entry.finished = reading.progress === 100 } + if (reading.startReadingTime) { + entry.startedAt = new Date(reading.startReadingTime * 1000).toISOString() + } + if (reading.finishTime) { + entry.finishedAt = new Date(reading.finishTime * 1000).toISOString() + } + if (typeof reading.readingTime === "number") { + entry.readingSeconds = reading.readingTime + } } catch (error) { // 单本节失败不该让整次抓取挂掉,卡片退化成「不显示进度条」 console.warn(` ⚠️ ${book.title}:进度获取失败 — ${error.message}`) diff --git a/src/components/bookshelf-content.astro b/src/components/bookshelf-content.astro index 07bf98e..3355c63 100644 --- a/src/components/bookshelf-content.astro +++ b/src/components/bookshelf-content.astro @@ -3,6 +3,7 @@ import SiteHeader from "@/components/site-header.astro" import Footer from "@/components/footer.astro" import { cn } from "@/lib/utils" import booksData from "../../public/data/books.json" +import ReadingCard from "@/components/reading-card.astro" import { formatReadingDate, getReadingData } from "@/lib/reading" // 微信读书数据。数据缺失时 reading 为 null,页面退化成空态,不报错。 @@ -160,59 +161,7 @@ const recommendBadge = (status?: string) => { {inProgressReading.length > 0 ? (
{book.title}
-- {[book.author, book.category].filter(Boolean).join(" · ")} -
- -- 最近阅读 {formatReadingDate(book.lastReadAt)} -
-{book.title}
-- {[book.author, book.category].filter(Boolean).join(" · ")} -
-{book.title}
++ {[book.author, book.category].filter(Boolean).join(" · ")} +
+ +开始 {startedText}
+ )} ++ 读完 {finishedText || "—"} +
+ > + ) : ( + <> ++ 最近阅读 {formatReadingDate(book.lastReadAt)} +
+ > + )} +