已读完的书挪进「书籍」,抓取上限去掉(8 -> 整架 26 本)
抓取范围 - TOP_N 默认从 8 改成 0=不限制。原来那个 8 是我拍的「最近动过的前 8 本」, 不是接口限制;整架 26 本也就 1+26 个请求,完全够用 - --top N 仍可用,想只抓最近几本时加 分组调整 - 「最近在读」只留 progress < 100 的(20 本),进度条不再出现 100% - 新增「书籍」区底部的「微信读书 · 已读完」分组(6 本),卡片结构与手工 书单一致,左上角带「已读完」徽标;因为微信读书的数据没有书评/简介, 这一组点击直接跳 weread.qq.com,不弹窗 - 这一组带 data-weread-card + data-category="微信读书",所以搜索框和 「领域」筛选同样作用得到;领域筛选里会多出一个「微信读书」选项 - 筛选逻辑把 [data-book-card] 的选择器扩成 [data-book-card], [data-weread-card],分组计数也一并算上 实测数据分布(整架 26 本) - 已读完 6 / 在读中 16(1%-97%)/ 没开始 4(0%) 静态验证(dist/bookshelf/index.html) - 在读区 20 张卡片,进度条 30/0/77/28/13/97/0/5/16/3/10/1/4/13/4/0/1/10/6/0, 区内无「已读完」字样 - 已读完分组 6 张卡片,6 个徽标、6 个微信读书跳转链接,均带 data-weread-card - 手工书单 3 张卡片未受影响;领域筛选新增「微信读书」按钮
This commit is contained in:
@@ -287,7 +287,7 @@ src/data/reading.json
|
|||||||
src/components/bookshelf-content.astro
|
src/components/bookshelf-content.astro
|
||||||
```
|
```
|
||||||
|
|
||||||
- 刷新数据:`pnpm reading`(失败会明确报错并 exit 1);`pnpm reading --top 12` 可改抓取条数(默认 8)
|
- 刷新数据:`pnpm reading`(失败会明确报错并 exit 1)。默认抓**整架**(1 + N 个请求,书架几十本完全够用);想只抓最近动过的几本就 `pnpm reading --top 12`
|
||||||
- **`pnpm build` 会自动先跑一次抓取,但用 `--soft` 模式**:微信读书挂了 / Key 过期 / 断网时,保留上一次的 `reading.json` 继续构建,**不会阻塞部署**
|
- **`pnpm build` 会自动先跑一次抓取,但用 `--soft` 模式**:微信读书挂了 / Key 过期 / 断网时,保留上一次的 `reading.json` 继续构建,**不会阻塞部署**
|
||||||
- `src/data/reading.json` 是数据快照,**要提交进 git**,这样 CI 或新克隆的仓库没 Key 也能构建
|
- `src/data/reading.json` 是数据快照,**要提交进 git**,这样 CI 或新克隆的仓库没 Key 也能构建
|
||||||
- Key 申请:<https://weread.qq.com/r/weread-skills> 扫码,拿到 `wrk-` 开头的串,写进 `.env` 的 `WEREAD_API_KEY`(`.env` 已 gitignore)。**只在本地构建**时用得上 —— `deploy.sh` 是本地构建再 rsync,凭据不会上传服务器;如果另外接了 Vercel / GitHub Actions 构建,要在那边单独配 secret
|
- Key 申请:<https://weread.qq.com/r/weread-skills> 扫码,拿到 `wrk-` 开头的串,写进 `.env` 的 `WEREAD_API_KEY`(`.env` 已 gitignore)。**只在本地构建**时用得上 —— `deploy.sh` 是本地构建再 rsync,凭据不会上传服务器;如果另外接了 Vercel / GitHub Actions 构建,要在那边单独配 secret
|
||||||
@@ -302,7 +302,14 @@ src/components/bookshelf-content.astro
|
|||||||
- `category` 是 `文学-外国文学` 这种「大类-子类」复合串
|
- `category` 是 `文学-外国文学` 这种「大类-子类」复合串
|
||||||
- 时间戳统一按 `YYYY-MM-DD` 展示(官方硬性要求),顺带避开「N 天前」在静态站上会随构建时间变旧
|
- 时间戳统一按 `YYYY-MM-DD` 展示(官方硬性要求),顺带避开「N 天前」在静态站上会随构建时间变旧
|
||||||
|
|
||||||
展示逻辑:过滤掉私密阅读(`secret === 1`)和从没打开过的书;读完的照常显示,标「已读完」;0% 标「还没开始」;有声书不管。
|
展示逻辑:
|
||||||
|
|
||||||
|
| 归到哪 | 条件 |
|
||||||
|
|---|---|
|
||||||
|
| 最近在读 | `progress < 100`(含 0%,标「还没开始」) |
|
||||||
|
| 书籍 → 「微信读书 · 已读完」分组 | `progress === 100` |
|
||||||
|
|
||||||
|
这一组混在「书籍」区的网格里,卡片结构和手工书单一致,但没有书评/简介,所以点击是直接跳微信读书而不是弹窗。它们带 `data-weread-card` 和 `data-category="微信读书"`,所以搜索框和「领域」筛选同样作用得到(领域里会多出一个「微信读书」选项)。过滤掉的:私密阅读(`secret === 1`)、从没打开过的书;有声书不处理。
|
||||||
|
|
||||||
**2. 书籍** —— 来自 `public/data/books.json`,由 `bookshelf-content.astro` 在构建时 import(文件必须存在)。另外两个文件 `papers.json` / `comics.json` 对应的漫画、论文分类已经移除,文件保留但不再被引用。
|
**2. 书籍** —— 来自 `public/data/books.json`,由 `bookshelf-content.astro` 在构建时 import(文件必须存在)。另外两个文件 `papers.json` / `comics.json` 对应的漫画、论文分类已经移除,文件保留但不再被引用。
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -203,7 +203,9 @@ pnpm preview # 本地预览构建产物(搜索功能只有这里才生效
|
|||||||
pnpm reading
|
pnpm reading
|
||||||
```
|
```
|
||||||
|
|
||||||
会打印抓到的每本书和进度。想看更多本就 `pnpm reading --top 12`(默认 8 本)。
|
会打印抓到的每本书和进度。**默认抓整架**;想只抓最近动过的几本就 `pnpm reading --top 12`。
|
||||||
|
|
||||||
|
读完的书会自动出现在「书籍」区底部的「微信读书 · 已读完」分组里,不用手工搬。
|
||||||
|
|
||||||
**平时不用管**:`pnpm build` 和 `./deploy.sh` 都会自动先抓一次。抓不到就沿用上一次的数据,**不会让部署失败**。
|
**平时不用管**:`pnpm build` 和 `./deploy.sh` 都会自动先抓一次。抓不到就沿用上一次的数据,**不会让部署失败**。
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* 用法:
|
* 用法:
|
||||||
* pnpm reading 手动刷新(失败会 exit 1,明确报错)
|
* pnpm reading 手动刷新(失败会 exit 1,明确报错)
|
||||||
* pnpm reading --top 12 抓前 12 本,默认 8
|
* pnpm reading --top 12 只抓最近动过的 12 本;不加则整架都抓(默认不限)
|
||||||
* node scripts/fetch-reading.mjs --soft 失败时保留旧数据并 exit 0(构建流程用)
|
* node scripts/fetch-reading.mjs --soft 失败时保留旧数据并 exit 0(构建流程用)
|
||||||
*
|
*
|
||||||
* 接口是腾讯官方的微信读书 Agent Gateway:
|
* 接口是腾讯官方的微信读书 Agent Gateway:
|
||||||
@@ -25,14 +25,15 @@ const ENDPOINT = "https://i.weread.qq.com/api/agent/gateway"
|
|||||||
/** 与官方 SKILL.md 顶部的 version 保持一致;服务端会用它对版本 */
|
/** 与官方 SKILL.md 顶部的 version 保持一致;服务端会用它对版本 */
|
||||||
const SKILL_VERSION = "1.0.4"
|
const SKILL_VERSION = "1.0.4"
|
||||||
const OUT_FILE = "src/data/reading.json"
|
const OUT_FILE = "src/data/reading.json"
|
||||||
const DEFAULT_TOP = 8
|
/** 0 = 不限制,整架都抓。书架一般也就几十本,1+N 个请求完全够用 */
|
||||||
|
const DEFAULT_TOP = 0
|
||||||
const REQUEST_TIMEOUT_MS = 15_000
|
const REQUEST_TIMEOUT_MS = 15_000
|
||||||
const DELAY_BETWEEN_CALLS_MS = 150
|
const DELAY_BETWEEN_CALLS_MS = 150
|
||||||
|
|
||||||
const args = process.argv.slice(2)
|
const args = process.argv.slice(2)
|
||||||
const SOFT = args.includes("--soft")
|
const SOFT = args.includes("--soft")
|
||||||
const topIndex = args.indexOf("--top")
|
const topIndex = args.indexOf("--top")
|
||||||
const TOP_N = topIndex >= 0 ? Number(args[topIndex + 1]) || DEFAULT_TOP : DEFAULT_TOP
|
const TOP_N = topIndex >= 0 ? Number(args[topIndex + 1]) || DEFAULT_TOP : DEFAULT_TOP // 0 = 不限
|
||||||
|
|
||||||
// .env 已 gitignore;Node 22 自带 loadEnvFile,不需要 dotenv
|
// .env 已 gitignore;Node 22 自带 loadEnvFile,不需要 dotenv
|
||||||
try {
|
try {
|
||||||
@@ -78,13 +79,15 @@ async function call(apiName, params = {}) {
|
|||||||
async function fetchReading() {
|
async function fetchReading() {
|
||||||
const shelf = await call("/shelf/sync")
|
const shelf = await call("/shelf/sync")
|
||||||
|
|
||||||
const candidates = (shelf.books ?? [])
|
const sorted = (shelf.books ?? [])
|
||||||
// 私密阅读(secret=1)不要发到公开网站上
|
// 私密阅读(secret=1)不要发到公开网站上
|
||||||
.filter((book) => book.secret !== 1)
|
.filter((book) => book.secret !== 1)
|
||||||
// readUpdateTime 为 0 表示从没打开过,不算「在读」
|
// readUpdateTime 为 0 表示从没打开过,不算「在读」
|
||||||
.filter((book) => Number(book.readUpdateTime) > 0)
|
.filter((book) => Number(book.readUpdateTime) > 0)
|
||||||
.sort((a, b) => Number(b.readUpdateTime) - Number(a.readUpdateTime))
|
.sort((a, b) => Number(b.readUpdateTime) - Number(a.readUpdateTime))
|
||||||
.slice(0, TOP_N)
|
|
||||||
|
// TOP_N 为 0 时整架都取;页面再按「读完 / 在读」自己分组
|
||||||
|
const candidates = TOP_N > 0 ? sorted.slice(0, TOP_N) : sorted
|
||||||
|
|
||||||
if (candidates.length === 0) {
|
if (candidates.length === 0) {
|
||||||
return { books: [], note: "书架里没有可展示的阅读记录" }
|
return { books: [], note: "书架里没有可展示的阅读记录" }
|
||||||
|
|||||||
@@ -5,10 +5,17 @@ import { cn } from "@/lib/utils"
|
|||||||
import booksData from "../../public/data/books.json"
|
import booksData from "../../public/data/books.json"
|
||||||
import { formatReadingDate, getReadingData } from "@/lib/reading"
|
import { formatReadingDate, getReadingData } from "@/lib/reading"
|
||||||
|
|
||||||
// 微信读书「最近在读」。数据缺失时 reading 为 null,页面退化成空态,不报错。
|
// 微信读书数据。数据缺失时 reading 为 null,页面退化成空态,不报错。
|
||||||
const reading = getReadingData()
|
const reading = getReadingData()
|
||||||
const readingBooks = reading?.books ?? []
|
const readingBooks = reading?.books ?? []
|
||||||
const readingCount = readingBooks.length
|
|
||||||
|
// 读完的挪到「书籍」区,剩下的才留在「最近在读」
|
||||||
|
const inProgressReading = readingBooks.filter((book) => !book.finished)
|
||||||
|
const finishedReading = readingBooks.filter((book) => book.finished)
|
||||||
|
const readingCount = inProgressReading.length
|
||||||
|
|
||||||
|
/** 「书籍」区里给微信读书已读书记一个分类名,同时作为可筛选的领域 */
|
||||||
|
const WEREAD_CATEGORY = "微信读书"
|
||||||
|
|
||||||
// ---- Types
|
// ---- Types
|
||||||
|
|
||||||
@@ -41,7 +48,7 @@ const booksByCategory = allBooks.reduce<Record<string, BookRecord[]>>((acc, book
|
|||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
const bookCategories = ["全部", ...Object.keys(booksByCategory)]
|
const bookCategories = ["全部", ...Object.keys(booksByCategory), ...(finishedReading.length > 0 ? [WEREAD_CATEGORY] : [])]
|
||||||
const bookStatuses = ["全部", "推荐", "中庸", "不行"]
|
const bookStatuses = ["全部", "推荐", "中庸", "不行"]
|
||||||
|
|
||||||
const bookStats = {
|
const bookStats = {
|
||||||
@@ -151,9 +158,9 @@ const recommendBadge = (status?: string) => {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{readingBooks.length > 0 ? (
|
{inProgressReading.length > 0 ? (
|
||||||
<div class="grid gap-4 sm:grid-cols-2">
|
<div class="grid gap-4 sm:grid-cols-2">
|
||||||
{readingBooks.map((book) => (
|
{inProgressReading.map((book) => (
|
||||||
<a
|
<a
|
||||||
href={book.deepLink || undefined}
|
href={book.deepLink || undefined}
|
||||||
target={book.deepLink ? "_blank" : undefined}
|
target={book.deepLink ? "_blank" : undefined}
|
||||||
@@ -352,6 +359,61 @@ const recommendBadge = (status?: string) => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{/* 微信读书里已读完的书,并入「书籍」区。
|
||||||
|
卡片结构和上面的书一样,但没有书评/简介,所以点击直接跳微信读书,不弹窗。
|
||||||
|
data-weread-card 让搜索框和领域/评价筛选同样作用于这一组。 */}
|
||||||
|
{finishedReading.length > 0 && (
|
||||||
|
<section data-books-section={WEREAD_CATEGORY}>
|
||||||
|
<div class="flex items-center gap-3 mb-5">
|
||||||
|
<h3 class="text-base font-semibold text-foreground">微信读书 · 已读完</h3>
|
||||||
|
<span class="text-xs text-muted-foreground" data-books-count>({finishedReading.length})</span>
|
||||||
|
<div class="flex-1 h-px bg-border/60" />
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-5">
|
||||||
|
{finishedReading.map((book) => (
|
||||||
|
<a
|
||||||
|
href={book.deepLink || undefined}
|
||||||
|
target={book.deepLink ? "_blank" : undefined}
|
||||||
|
rel={book.deepLink ? "noopener noreferrer" : undefined}
|
||||||
|
data-weread-card
|
||||||
|
data-category={WEREAD_CATEGORY}
|
||||||
|
data-title={book.title.toLowerCase()}
|
||||||
|
data-authors={book.author.toLowerCase()}
|
||||||
|
class="group block cursor-pointer focus:outline-none"
|
||||||
|
>
|
||||||
|
<div class="relative aspect-[3/4] rounded-lg overflow-hidden mb-3 bg-surface-subtle shadow-sm group-hover:shadow-xl transition-shadow duration-300">
|
||||||
|
{book.cover ? (
|
||||||
|
<img
|
||||||
|
src={book.cover}
|
||||||
|
alt={book.title}
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div class="flex h-full w-full items-center justify-center p-3 bg-gradient-to-br from-primary/30 via-primary/20 to-primary/5">
|
||||||
|
<p class="font-semibold text-xs text-foreground text-center line-clamp-4">{book.title}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<span class="absolute top-2 right-2 text-[10px] px-2 py-0.5 rounded-full bg-status-positive-bg text-status-positive-fg font-medium">
|
||||||
|
已读完
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="min-h-[3.5rem] space-y-1">
|
||||||
|
<h4 class="font-medium text-sm text-foreground line-clamp-2 group-hover:text-primary transition-colors leading-snug">
|
||||||
|
{book.title}
|
||||||
|
</h4>
|
||||||
|
<p class="text-xs text-muted-foreground line-clamp-1">
|
||||||
|
{[book.author, book.category].filter(Boolean).join(" · ")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Empty state (shared, shown when filters return nothing) */}
|
{/* Empty state (shared, shown when filters return nothing) */}
|
||||||
@@ -466,7 +528,7 @@ const recommendBadge = (status?: string) => {
|
|||||||
|
|
||||||
const applyBooks = () => {
|
const applyBooks = () => {
|
||||||
const q = state.query.trim().toLowerCase();
|
const q = state.query.trim().toLowerCase();
|
||||||
const cards = document.querySelectorAll("[data-book-card]");
|
const cards = document.querySelectorAll("[data-book-card], [data-weread-card]");
|
||||||
let totalVisible = 0;
|
let totalVisible = 0;
|
||||||
cards.forEach((card) => {
|
cards.forEach((card) => {
|
||||||
const cat = card.getAttribute("data-category") || "";
|
const cat = card.getAttribute("data-category") || "";
|
||||||
@@ -481,7 +543,7 @@ const recommendBadge = (status?: string) => {
|
|||||||
if (show) totalVisible++;
|
if (show) totalVisible++;
|
||||||
});
|
});
|
||||||
document.querySelectorAll("[data-books-section]").forEach((section) => {
|
document.querySelectorAll("[data-books-section]").forEach((section) => {
|
||||||
const visible = Array.from(section.querySelectorAll("[data-book-card]")).filter((c) => !c.classList.contains("hidden")).length;
|
const visible = Array.from(section.querySelectorAll("[data-book-card], [data-weread-card]")).filter((c) => !c.classList.contains("hidden")).length;
|
||||||
const countEl = section.querySelector("[data-books-count]");
|
const countEl = section.querySelector("[data-books-count]");
|
||||||
if (countEl) countEl.textContent = `(${visible})`;
|
if (countEl) countEl.textContent = `(${visible})`;
|
||||||
section.classList.toggle("hidden", visible === 0);
|
section.classList.toggle("hidden", visible === 0);
|
||||||
|
|||||||
+199
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"updatedAt": "2026-09-15T02:39:58.551Z",
|
"updatedAt": "2026-09-15T02:45:18.862Z",
|
||||||
"source": "weread",
|
"source": "weread",
|
||||||
"books": [
|
"books": [
|
||||||
{
|
{
|
||||||
@@ -89,6 +89,204 @@
|
|||||||
"finished": false,
|
"finished": false,
|
||||||
"lastReadAt": "2026-06-10T16:13:58.000Z",
|
"lastReadAt": "2026-06-10T16:13:58.000Z",
|
||||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=32f329e0813aba1d3g018fee"
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=32f329e0813aba1d3g018fee"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "3300053824",
|
||||||
|
"title": "改变世界的17个方程",
|
||||||
|
"author": "伊恩·斯图尔特",
|
||||||
|
"category": "科学技术-自然科学",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/94/cpplatform_wxkigsn3nwuexqw4pspab6/t6_cpplatform_wxkigsn3nwuexqw4pspab61679905263.jpg",
|
||||||
|
"progress": 100,
|
||||||
|
"finished": true,
|
||||||
|
"lastReadAt": "2026-06-07T10:50:15.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=fb8320d0813ab7b86g01401c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "3300028287",
|
||||||
|
"title": "羊道·深山夏牧场(羊道终章,游牧生活的漫长告别)",
|
||||||
|
"author": "李娟",
|
||||||
|
"category": "精品小说-社会小说",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/82/cpPlatform_kz1K9Wo8Sh3FUsdhx8eckN/t6_cpPlatform_kz1K9Wo8Sh3FUsdhx8eckN.jpg",
|
||||||
|
"progress": 5,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-06-07T05:15:01.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=ec0325c0813ab718cg017a62"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "3300201219",
|
||||||
|
"title": "AI 时代的认知觉醒",
|
||||||
|
"author": "知识重构者",
|
||||||
|
"category": "心理-认知与行为",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/46/cpplatform_t658eoeazmalyo2rw3pskp/t6_cpplatform_t658eoeazmalyo2rw3pskp1776046889.jpg",
|
||||||
|
"progress": 16,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-06-06T18:14:57.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=ec332c80813abb519g019b32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "38894307",
|
||||||
|
"title": "谈美",
|
||||||
|
"author": "朱光潜",
|
||||||
|
"category": "哲学宗教-美学",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/48/YueWen_38894307/t6_YueWen_38894307.jpg",
|
||||||
|
"progress": 3,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-06-01T17:12:29.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=da032ef072517ae3da039f2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "27126747",
|
||||||
|
"title": "杜邦安全管理",
|
||||||
|
"author": "崔政斌 张美元 周礼庆编著",
|
||||||
|
"category": "经济理财-管理",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/98/YueWen_27126747/t6_YueWen_27126747.jpg",
|
||||||
|
"progress": 10,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-05-13T00:11:25.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=a3d32d20719debdba3d5de1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "674073",
|
||||||
|
"title": "沧浪之水",
|
||||||
|
"author": "阎真",
|
||||||
|
"category": "精品小说-影视原著",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/49/yuewen_674073/t6_yuewen_6740731774011595.jpg",
|
||||||
|
"progress": 1,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-04-19T15:00:03.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=7c632ef05a49197c62b53f0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "26943492",
|
||||||
|
"title": "每天5分钟玩转Docker容器技术",
|
||||||
|
"author": "CloudMan",
|
||||||
|
"category": "计算机-计算机综合",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/41/YueWen_26943492/t6_YueWen_26943492.jpg",
|
||||||
|
"progress": 4,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-04-18T15:44:35.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=93d325a0719b200493d5ba9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "40055543",
|
||||||
|
"title": "置身事内:中国政府与经济发展",
|
||||||
|
"author": "兰小欢",
|
||||||
|
"category": "经济理财-财经",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/52/YueWen_40055543/t6_YueWen_40055543.jpg",
|
||||||
|
"progress": 13,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-03-28T10:03:33.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=2a332d10726332f72a34943"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "41100356",
|
||||||
|
"title": "挽救计划(同名电影原著)",
|
||||||
|
"author": "[美]安迪·威尔",
|
||||||
|
"category": "精品小说-科幻小说",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/0/yuewen_41100356/t6_yuewen_411003561772520377.jpg",
|
||||||
|
"progress": 100,
|
||||||
|
"finished": true,
|
||||||
|
"lastReadAt": "2026-03-28T10:01:44.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=6d232640727324446d2e978"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "31515008",
|
||||||
|
"title": "消失的13级台阶",
|
||||||
|
"author": "高野和明",
|
||||||
|
"category": "精品小说-悬疑推理",
|
||||||
|
"cover": "https://wfqqreader-1252317822.image.myqcloud.com/cover/8/31515008/t6_31515008.jpg",
|
||||||
|
"progress": 100,
|
||||||
|
"finished": true,
|
||||||
|
"lastReadAt": "2026-03-25T17:32:16.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=8033247071e0e1808035ab9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "3300175025",
|
||||||
|
"title": "此刻是春天(微信读书特别版)",
|
||||||
|
"author": "卢思浩",
|
||||||
|
"category": "精品小说-治愈小说",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/4/cpplatform_3hsoybvrwapq1efqha1mvz/t6_cpplatform_3hsoybvrwapq1efqha1mvz1762325065.jpg",
|
||||||
|
"progress": 4,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2026-01-11T10:35:21.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=b0b32630813abaadeg0157d1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "39280063",
|
||||||
|
"title": "博弈论:每个人都能成为决策高手(《人民日报》推荐)",
|
||||||
|
"author": "蒋文华",
|
||||||
|
"category": "经济理财-财经",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/77/YueWen_39280063/t6_YueWen_39280063.jpg",
|
||||||
|
"progress": 0,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2025-10-29T00:43:47.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=5d332c2072575dbf5d33fe2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "721367",
|
||||||
|
"title": "白说",
|
||||||
|
"author": "白岩松",
|
||||||
|
"category": "文学-散文杂著",
|
||||||
|
"cover": "https://wfqqreader-1252317822.image.myqcloud.com/cover/367/721367/t6_721367.jpg",
|
||||||
|
"progress": 100,
|
||||||
|
"finished": true,
|
||||||
|
"lastReadAt": "2025-10-29T00:43:35.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=4e3321805b01d74e3fa7481"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "3300024284",
|
||||||
|
"title": "毛泽东选集(全四卷)",
|
||||||
|
"author": "",
|
||||||
|
"category": "政治军事-政治",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/84/3300024284/t6_3300024284.jpg",
|
||||||
|
"progress": 1,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2025-10-18T09:21:26.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=2bb32ff0813ab6ffcg014315"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "3300120749",
|
||||||
|
"title": "不被大风吹倒(莫言陪女儿高考也这样! )",
|
||||||
|
"author": "莫言",
|
||||||
|
"category": "文学-散文杂著",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/60/cpplatform_n3ezmfhymkjcbuuszk8bgy/t6_cpplatform_n3ezmfhymkjcbuuszk8bgy1731488438.jpg",
|
||||||
|
"progress": 10,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2024-12-21T00:51:54.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=2c032e80813ab95aag019524"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "673157",
|
||||||
|
"title": "浴血荣光(同名电视剧原著)",
|
||||||
|
"author": "金一南",
|
||||||
|
"category": "文学-纪实文学",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/25/YueWen_673157/t6_YueWen_673157.jpg",
|
||||||
|
"progress": 6,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2020-04-09T07:29:49.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=814322405a4585814beb03d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "807264",
|
||||||
|
"title": "微纪元",
|
||||||
|
"author": "刘慈欣",
|
||||||
|
"category": "精品小说-科幻小说",
|
||||||
|
"cover": "https://wfqqreader-1252317822.image.myqcloud.com/cover/264/807264/t6_807264.jpg",
|
||||||
|
"progress": 100,
|
||||||
|
"finished": true,
|
||||||
|
"lastReadAt": "2019-10-15T15:30:42.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=770328405c5160770c987ae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bookId": "812443",
|
||||||
|
"title": "白鹿原",
|
||||||
|
"author": "陈忠实",
|
||||||
|
"category": "精品小说-年代小说",
|
||||||
|
"cover": "https://cdn.weread.qq.com/weread/cover/78/YueWen_812443/t6_YueWen_812443.jpg",
|
||||||
|
"progress": 0,
|
||||||
|
"finished": false,
|
||||||
|
"lastReadAt": "2017-05-30T00:49:56.000Z",
|
||||||
|
"deepLink": "https://weread.qq.com/book-detail?type=1&v=47532ac05c659b47554a825"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user