Compare commits
5
Commits
daf3b34b8c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff698be696 | ||
|
|
4512d3fb24 | ||
|
|
ddfd0c0402 | ||
|
|
940bac3106 | ||
|
|
2673e236f7 |
@@ -214,6 +214,11 @@ pnpm reading
|
||||
|
||||
读完的书会自动出现在「书籍」区底部的「微信读书 · 已读完」分组里,不用手工搬。
|
||||
|
||||
**有声书(专辑)**:同一次请求里还会抓书架上的专辑,写进 `reading.json` 的 `albums` 字段。
|
||||
「在读」页会自动多出一个「有声书」区块 —— 但没有专辑时整块不显示,所以现在看不到是正常的。
|
||||
专辑没有阅读进度也没有跳转链接(微信读书那边就没给),卡片只显示集数、完结状态和最近收听。
|
||||
`--top` 只作用于书,专辑一次全取;`secret: 1` 的私密收听同样会被过滤掉。
|
||||
|
||||
**平时不用管**:`pnpm build` 和 `./deploy.sh` 都会自动先抓一次。抓不到就沿用上一次的数据,**不会让部署失败**。
|
||||
|
||||
**首次配置**(只做一次):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* 抓取微信读书「最近在读」,写出 src/data/reading.json
|
||||
/* 抓取微信读书「最近在读」与「有声书专辑」,写出 src/data/reading.json
|
||||
*
|
||||
* 用法:
|
||||
* pnpm reading 手动刷新(失败会 exit 1,明确报错)
|
||||
@@ -17,14 +17,24 @@
|
||||
* 只有「阅读进度」要额外调 /book/getprogress,所以请求数 = 1 + N
|
||||
* 2. book.recordReadingTime 恒为 0,但 book.readingTime 是真数据,累计时长取后者
|
||||
* 3. 官方文档没列 book.startReadingTime,但回包里有,是「开始阅读时间」
|
||||
* 4. albums[](专辑/有声书)和 books[] 是平行数组,数据结构也不一样:
|
||||
* 内容包在 albumInfo / albumInfoExtra 两层里,且**没有进度、没有 deepLink**
|
||||
* (至少官方文档没写)。--top 只作用于 books,专辑一次全取。
|
||||
*/
|
||||
|
||||
import fs from "node:fs"
|
||||
import path from "node:path"
|
||||
|
||||
const ENDPOINT = "https://i.weread.qq.com/api/agent/gateway"
|
||||
/** 与官方 SKILL.md 顶部的 version 保持一致;服务端会用它对版本 */
|
||||
const SKILL_VERSION = "1.0.4"
|
||||
/**
|
||||
* 与官方 SKILL.md 顶部的 version 保持一致;服务端会用它对版本。
|
||||
*
|
||||
* 升级就是改这个数字,**不需要**下载官方的 weread-skills.zip:那个包是给 agent 读的
|
||||
* 提示词文档(SKILL.md + shelf.md / book.md 等),本项目一个文件都不消费它;
|
||||
* 网关只拿这里的 skill_version 做比对。2026-10-10 起服务端要求 1.0.5。
|
||||
* 参考:https://cdn.weread.qq.com/skills/weread-skills.zip
|
||||
*/
|
||||
const SKILL_VERSION = "1.0.5"
|
||||
const OUT_FILE = "src/data/reading.json"
|
||||
/** 0 = 不限制,整架都抓。书架一般也就几十本,1+N 个请求完全够用 */
|
||||
const DEFAULT_TOP = 0
|
||||
@@ -47,6 +57,54 @@ const apiKey = process.env.WEREAD_API_KEY
|
||||
|
||||
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
/**
|
||||
* 时间戳转 ISO。
|
||||
*
|
||||
* 微信读书的书架时间戳实测是**秒**;但专辑那边的 lectureReadUpdateTime 官方文档
|
||||
* 没写单位,万一是毫秒(13 位)就会得到公元 5 万年。用位数兜一下,两边都安全。
|
||||
*/
|
||||
function toIso(value) {
|
||||
const n = Number(value)
|
||||
if (!Number.isFinite(n) || n <= 0) return null
|
||||
return new Date(n > 1e12 ? n : n * 1000).toISOString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 专辑/有声书。和 books[] 平行,但结构完全不同:内容在 albumInfo / albumInfoExtra 两层。
|
||||
*
|
||||
* 官方文档给的字段里没有 progress、也没有 deepLink,所以:
|
||||
* - 不伪造进度,前端只展示「集数 / 完结状态 / 最近收听」;
|
||||
* - deepLink 按几个可能的位置兜一下,取不到就是空串(卡片退化成不可点击)。
|
||||
* 私密收听(secret === 1)和书一样必须过滤掉 —— 这是要发到公开网站上的。
|
||||
*/
|
||||
function normalizeAlbums(shelf) {
|
||||
return (shelf.albums ?? [])
|
||||
.filter((album) => album?.albumInfoExtra?.secret !== 1)
|
||||
.map((album) => {
|
||||
const info = album.albumInfo ?? {}
|
||||
const extra = album.albumInfoExtra ?? {}
|
||||
return {
|
||||
albumId: info.albumId ?? "",
|
||||
name: info.name ?? "",
|
||||
/** 演播 / 作者 */
|
||||
author: info.authorName ?? "",
|
||||
cover: info.cover ?? "",
|
||||
trackCount: Number(info.trackCount) || 0,
|
||||
finished: Number(info.finish) === 1,
|
||||
/** 完结状态原文,如「已完结」 */
|
||||
finishStatus: info.finishStatus ?? "",
|
||||
intro: info.intro ?? "",
|
||||
lastListenedAt: toIso(extra.lectureReadUpdateTime),
|
||||
deepLink: info.deepLink ?? album.deepLink ?? "",
|
||||
}
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const at = a.lastListenedAt ? Date.parse(a.lastListenedAt) : 0
|
||||
const bt = b.lastListenedAt ? Date.parse(b.lastListenedAt) : 0
|
||||
return bt - at
|
||||
})
|
||||
}
|
||||
|
||||
async function call(apiName, params = {}) {
|
||||
const res = await fetch(ENDPOINT, {
|
||||
method: "POST",
|
||||
@@ -61,7 +119,22 @@ async function call(apiName, params = {}) {
|
||||
const json = await res.json().catch(() => null)
|
||||
|
||||
if (json?.upgrade_info) {
|
||||
console.warn(`⚠️ 服务端要求升级 Skill:${json.upgrade_info.message ?? "(无说明)"}`)
|
||||
/*
|
||||
* 服务端只拿 skill_version 做版本比对。原来的写法只打了 message,把
|
||||
* current_version / latest_version / upgrade_url 一起丢掉了,于是提示退化成
|
||||
* 一句无解的「请立即升级」—— 而 message 本身是写给 agent 的通用话术
|
||||
* (「必须立即暂停当前操作…不得忽略该字段」),照做就等于让远端文案驱动本地文件。
|
||||
* 这里改成把可执行的信息全打出来:差了多少版、去哪儿看、改哪一行。
|
||||
*/
|
||||
const { current_version, latest_version, upgrade_url, message } = json.upgrade_info
|
||||
console.warn(
|
||||
`⚠️ 微信读书 Skill 版本过期:本地 ${current_version ?? SKILL_VERSION} → 服务端要求 ${latest_version ?? "?"}(接口仍可用,只是提醒)`,
|
||||
)
|
||||
if (message) console.warn(` ${message}`)
|
||||
if (upgrade_url) console.warn(` 升级包(仅供查阅,本项目不消费):${upgrade_url}`)
|
||||
console.warn(
|
||||
` 处理方式:把本文件顶部的 SKILL_VERSION 改成 "${latest_version ?? "最新版本"}",无需下载安装任何文件。`,
|
||||
)
|
||||
}
|
||||
if (res.status === 401 || json?.errcode === -2010) {
|
||||
throw new Error(
|
||||
@@ -80,6 +153,9 @@ async function call(apiName, params = {}) {
|
||||
async function fetchReading() {
|
||||
const shelf = await call("/shelf/sync")
|
||||
|
||||
// 专辑一次全取(--top 只管书),所以先算出来,避免下面提前 return 时把它丢了
|
||||
const albums = normalizeAlbums(shelf)
|
||||
|
||||
const sorted = (shelf.books ?? [])
|
||||
// 私密阅读(secret=1)不要发到公开网站上
|
||||
.filter((book) => book.secret !== 1)
|
||||
@@ -91,7 +167,7 @@ async function fetchReading() {
|
||||
const candidates = TOP_N > 0 ? sorted.slice(0, TOP_N) : sorted
|
||||
|
||||
if (candidates.length === 0) {
|
||||
return { books: [], note: "书架里没有可展示的阅读记录" }
|
||||
return { books: [], albums, note: "书架里没有可展示的阅读记录" }
|
||||
}
|
||||
|
||||
const books = []
|
||||
@@ -140,7 +216,7 @@ async function fetchReading() {
|
||||
await sleep(DELAY_BETWEEN_CALLS_MS)
|
||||
}
|
||||
|
||||
return { books }
|
||||
return { books, albums }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
@@ -151,23 +227,27 @@ async function main() {
|
||||
)
|
||||
}
|
||||
|
||||
const { books, note } = await fetchReading()
|
||||
const { books, albums, note } = await fetchReading()
|
||||
if (note) console.warn(`⚠️ ${note}`)
|
||||
|
||||
const payload = {
|
||||
updatedAt: new Date().toISOString(),
|
||||
source: "weread",
|
||||
books,
|
||||
albums,
|
||||
}
|
||||
|
||||
fs.mkdirSync(path.dirname(OUT_FILE), { recursive: true })
|
||||
fs.writeFileSync(OUT_FILE, `${JSON.stringify(payload, null, 2)}\n`)
|
||||
|
||||
console.log(`✅ 写入 ${books.length} 本到 ${OUT_FILE}`)
|
||||
console.log(`✅ 写入 ${books.length} 本 + ${albums.length} 张有声书专辑到 ${OUT_FILE}`)
|
||||
for (const book of books) {
|
||||
const progress = book.progress === null ? " ?" : `${String(book.progress).padStart(3)}%`
|
||||
console.log(` ${progress} ${book.title}${book.finished ? "(已读完)" : ""}`)
|
||||
}
|
||||
for (const album of albums) {
|
||||
console.log(` 🎧 ${album.name}${album.trackCount ? `(${album.trackCount} 集)` : ""}`)
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
import { formatReadingDate, type ReadingAlbum } from "@/lib/reading"
|
||||
|
||||
/**
|
||||
* 微信读书「专辑 / 有声书」卡片。
|
||||
*
|
||||
* 为什么不复用 ReadingCard:两边能拿到的字段不一样。专辑没有 progress(官方结构里
|
||||
* 就没有),文档也没给 deepLink,还少了分类、开始/读完时间。硬塞进书卡会出现
|
||||
* 「进度条永远是 0%」这种假信息,所以单独一张,底部换成「集数 / 完结状态 / 最近收听」。
|
||||
*
|
||||
* deepLink 拿不到时不渲染成 <a>,只做展示 —— 一个点不动的链接比没有链接更糟。
|
||||
*/
|
||||
interface Props {
|
||||
album: ReadingAlbum
|
||||
}
|
||||
|
||||
const { album } = Astro.props
|
||||
|
||||
const Tag = album.deepLink ? "a" : "div"
|
||||
const linkable = Boolean(album.deepLink)
|
||||
const lastListened = formatReadingDate(album.lastListenedAt)
|
||||
const meta = [album.trackCount > 0 ? `${album.trackCount} 集` : "", album.finishStatus]
|
||||
.filter(Boolean)
|
||||
.join(" · ")
|
||||
---
|
||||
|
||||
<Tag
|
||||
href={linkable ? album.deepLink : undefined}
|
||||
target={linkable ? "_blank" : undefined}
|
||||
rel={linkable ? "noopener noreferrer" : undefined}
|
||||
class:list={[
|
||||
"group flex gap-4 rounded-xl border border-border/50 bg-card p-4",
|
||||
linkable && "transition-shadow duration-300 hover:shadow-lg",
|
||||
]}
|
||||
>
|
||||
<div class="shrink-0 w-20 aspect-square rounded-lg overflow-hidden bg-surface-subtle">
|
||||
{album.cover ? (
|
||||
<img
|
||||
src={album.cover}
|
||||
alt={album.name}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
referrerpolicy="no-referrer"
|
||||
class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
) : (
|
||||
<div class="flex h-full w-full items-center justify-center p-2 bg-gradient-to-br from-primary/30 via-primary/20 to-primary/5">
|
||||
<p class="font-semibold text-[10px] text-foreground text-center line-clamp-4">{album.name}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-w-0 flex flex-col">
|
||||
<h3
|
||||
class:list={[
|
||||
"font-medium text-sm text-foreground line-clamp-2 leading-snug mb-1",
|
||||
linkable && "group-hover:text-primary transition-colors",
|
||||
]}
|
||||
>
|
||||
{album.name}
|
||||
</h3>
|
||||
<p class="text-xs text-muted-foreground line-clamp-1 mb-3">{album.author}</p>
|
||||
|
||||
<div class="mt-auto space-y-1.5">
|
||||
{meta && <p class="text-[11px] text-muted-foreground/80 tabular-nums">{meta}</p>}
|
||||
<p class="text-[11px] text-muted-foreground/80 tabular-nums">
|
||||
{lastListened ? `最近收听 ${lastListened}` : "还没有收听记录"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Tag>
|
||||
@@ -4,6 +4,7 @@ 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 AlbumCard from "@/components/album-card.astro"
|
||||
import { formatReadingDate, getReadingData } from "@/lib/reading"
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,11 @@ const inProgressReading = readingBooks.filter((book) => !book.finished)
|
||||
const finishedReading = readingBooks.filter((book) => book.finished)
|
||||
const readingCount = inProgressReading.length
|
||||
|
||||
// 有声书专辑:与 books[] 平行的另一组数据。
|
||||
// 用 ?? [] 兜住两种情况:老版 reading.json 没有 albums 字段(--soft 回退时),
|
||||
// 以及你根本没听过有声书(服务端返回空数组)。
|
||||
const readingAlbums = reading?.albums ?? []
|
||||
|
||||
/** 「书籍」区里给微信读书已读书记一个分类名,同时作为可筛选的领域 */
|
||||
const WEREAD_CATEGORY = "微信读书"
|
||||
|
||||
@@ -194,6 +200,27 @@ const recommendBadge = (status?: string) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ========================= 有声书(微信读书专辑) =========================
|
||||
与 books[] 平行的一组数据,只有真的听过有声书时服务端才会返回内容。
|
||||
readingAlbums 为空就整块不渲染 —— 所以在你有第一张专辑之前,这个区块
|
||||
既不存在也不占位。数据由 scripts/fetch-reading.mjs 一并抓取。 */}
|
||||
{isReadingView && readingAlbums.length > 0 && (
|
||||
<div id="albums" class="mb-16 scroll-mt-24">
|
||||
<div class="flex flex-wrap items-end justify-between gap-x-6 gap-y-2 mb-6">
|
||||
<div>
|
||||
<div class="text-[11px] text-primary tracking-[0.22em] font-semibold uppercase mb-1.5">Collection · 02</div>
|
||||
<h2 class="text-3xl md:text-4xl font-bold font-serif tracking-tight text-foreground mb-1.5">有声书</h2>
|
||||
<div class="text-sm italic font-serif text-muted-foreground">耳朵也在读书</div>
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground tabular-nums">{readingAlbums.length} 张专辑</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
{readingAlbums.map((album) => <AlbumCard album={album} />)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isReadingView && (
|
||||
<>
|
||||
{/* ---------- Header ---------- */}
|
||||
|
||||
@@ -28,3 +28,6 @@ Halo 用起来和 Vanblog 相比,功能确实很多,但运行起来也相对
|
||||
|
||||
现在我有了自己的这个小站,也可以写自己的一些东西,无论是生活感悟还是技术文章,或者是一些图片之类的,都可以在这个平台上记录,还是那句话,"**现在不缺记录的平台,缺乏记录的热情**。"
|
||||
|
||||
>更新
|
||||
|
||||
今天是2026年10月6日,重新回头思考了一下,我觉得博客或者说自己的小站,更多的是个人的思考展示的一个具体平台。许多自己的想法和认识,用网页的形式公之于众,虽然不会有什么人去看,但是确实有一个独属于自己的赛博空间,用于自己耕耘。
|
||||
@@ -14,18 +14,11 @@ draft: false
|
||||
|
||||
AI 发展越来越快,各式各样的 claw 龙虾层出不穷、日新月异,真的是令人眼花缭乱,AI 工具很多,我们该怎么使用,这是一个新的问题。
|
||||
|
||||
<!-- more -->
|
||||
|
||||

|
||||
|
||||
像我现在使用的 picoclaw,仅仅是部署在我的树莓派上,似乎能完成的工作并不是很多,例如查询树莓派的运行情况,执行一些命令行,还有各种 Skills 没有使用,其应用潜力我只是开发了不到 10%,这是如此的神奇,Impssible😝。
|
||||
|
||||
## 一、智力不再是稀有属性
|
||||
|
||||
像我现在使用的 picoclaw,仅仅是部署在我的树莓派上,似乎能完成的工作并不是很多,例如查询树莓派的运行情况,作为喂奶机器人的提醒等,可以实现很多自动化工作。
|
||||
AI 现在对于我来说,最大的帮助就是能够在陌生领域下,靠提问来参考,完成之前认为比较复杂的问题,极大的降低了学习成本,或者说是入门的门槛。对人的智力解放是极大的,在 openclaw、hermes_Agent 这些工具我还不会使用,当然对词元的消耗也是巨大的。好像又回到了网络初始的年代,高昂的入网费用,多数人将流量用来娱乐而非创造价值。
|
||||
|
||||

|
||||
|
||||
现在似乎对程序员来说影响还是比较大的,AI 能够完成很多工作,似乎已经把人从简单重复的脑力劳动中解放出来。只有最优秀的、最会使用词元 Token 的人,能够将创意灵感迅速变现的人,才能适应这个时代。人的唯一性,灵感、创意、审美这些更重要的品质在智力成本降低的时候更加凸显。
|
||||
|
||||
思考、学习,我们的一直以来成长的途径,在现在这个时代真的要发生巨变了吗?凡事都可以辨证分析,可以说事物的一体两面性的边界并不是很清晰。
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 我的台式机到位了
|
||||
title: 我的台式机组装小记
|
||||
published: 2026-08-22
|
||||
description: 自己动手组装了一台计算机,也是赶在了硬件高价期,吃了一波AI税
|
||||
image: https://cos.tianxuetao.top/IMG_20260915_210045.avif
|
||||
@@ -35,8 +35,23 @@ slug: DIY-computer
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
机箱内部图片还是挺不错的,再加上RGB风扇后,现在一共是6组风扇,下进上出,侧进后出,整个风道还是挺流畅的,就是感觉CPU风冷是不是没有装好,打游戏的时候温度相对来说高一些(能达到70度)
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
现在又买了一块二手硬盘,希捷2TB的叠瓦盘,只花了378元,主要用于存储一些不重要的数》>据,可以多下载一些电影啥的,目前测试还不错没有坏道,可能是商家的擦除技术更加厉害了吧。就这样吧,现在这个情况下二手电子产品还是更具性价比。一块全新的硬盘价格是二手的3倍了(1200元上下),这个时间点真的是很奇怪,从内存条、到显卡、机械硬盘、固态硬盘的价格都是如此的夸张。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
>图一 · 健康度测试
|
||||
|
||||
|
||||

|
||||
>图二 · 硬盘坏块检测
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "执行力的影响"
|
||||
description: 坚定的去完成一件事,而不是消极应付。
|
||||
published: 2026-10-04
|
||||
tags:
|
||||
- "执行力,个人思考"
|
||||
category: "生活"
|
||||
slug: impact-of-execution
|
||||
|
||||
---
|
||||
坚定的执行
|
||||
|
||||
## 执行能力的重要性
|
||||
|
||||
我有时也会思考,人的一生靠什么来驱动。”人活一口气,树活一层皮“,说是人活着要争气,这气是什么,我认为是人的尊严,没有人希望自己如同草芥;其次是对命运的抗争,人生而不平等,出身寒微,但不能消极无为。要想改变这种情况,就需要执行力,坚持去做成一件事情。从学习到工作,都是需要憋着一口气去做。
|
||||
|
||||
|
||||
## 自己干成了的事情
|
||||
|
||||
执行力最终的体现在成事上,有一个结果出来。很多时候我所后悔的往往是因为中途放弃了,而最终没有实现的事情,这么久还是耿耿于怀。
|
||||
就拿五笔打字来说,自己现在还是在用拼音,只不过在AI加持下好像速度还行。但是办公来说还是太慢了,我还是没有练出来。
|
||||
|
||||
对自己的工作还是要上心,自己负责的事情,就要干出个结果来,如果以拖延来逃避,这就是执行力弱化的表现。工作本来就是一个克服阻力的过程,不会顺顺当当的就能完成,大多时候是需要加倍努力的💪,才能出色完成。
|
||||
|
||||
如果干工作一直拖拖拉拉,粗心大意只会让自己越来越差,生活工作一团糟。呈文办事,重在细心,标点符号、基本格式、文字用词如果都容易出现错误的话,确实不应该。有的时候这跟自己的工作态度有关,或者说缺少一种劲头,把工作干好的决心。自己反思了之后,仍然是觉得是主观原因占大多数,许多时候就是这样,个人的主观能动性还是很重要的一环。
|
||||
|
||||
## 知行合一的目标
|
||||
|
||||
**想到和得到之间还有一个做到**
|
||||
|
||||
有的时候我也在想这个问题,**做到**突出的是个人实现的过程,是改变这个物质世界的必然。很多时候,我会选择逃避,便会以拖延的形式出现。干工作没有动力,明明知道这件事情很重要了,但是却一拖再拖。
|
||||
|
||||
内心的驱动力就是这个中间体,映射到行动上就是执行力。自己需要不断提升自己的内驱动力,在自己的精神世界里里面不断建立一个又一个里程碑,完成一个又一个目标形成正反馈,让自己成为一个高执行力的人。
|
||||
很多时候,很多事情是很难看到回报的,或者说没有那么明显的正反馈,就容易懈怠,半途而废。
|
||||
然而每个人之间的差距就会体现在这里。引用一段话:每个人,每个年龄段,每个层次都有不熟悉的领域,不精通的专业。一部分人碍于面子不懂装懂,一部分人放低自己潜心学习。这与你的年龄段,与你的层次没有关系,只与你态度发生转变有关。
|
||||
|
||||
人非生而知之,
|
||||
|
||||
|
||||
现在就是感觉自己很迷茫,不想工作,但又不得不工作。
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
published: 2026-10-04T12:09:10.254Z
|
||||
location: "张掖"
|
||||
tags:
|
||||
- "工作"
|
||||
---
|
||||
忙忙碌碌,却是原地踏步,要明白工作只认可结果,过程中的心酸苦辣无人在意。每个人都在向着更好的方向发展,自己也不能庸人自庸,自我麻痹。
|
||||
@@ -15,3 +15,5 @@ weather: 晴
|
||||
|
||||
## 我必须改变,这需要自己去行动起来
|
||||
|
||||
个人的工作态度直接决定着自己能不能通过工作取得进步,积极向上的态度对工作来说很重要,消极只会带来浑浑噩噩,时间非常宝贵。
|
||||
|
||||
|
||||
+94
-79
@@ -1,35 +1,77 @@
|
||||
{
|
||||
"updatedAt": "2026-09-27T02:29:12.207Z",
|
||||
"updatedAt": "2026-10-11T08:52:01.398Z",
|
||||
"source": "weread",
|
||||
"books": [
|
||||
{
|
||||
"bookId": "3300207468",
|
||||
"title": "快乐的死(果麦经典)",
|
||||
"author": "[法]加缪",
|
||||
"category": "文学-外国文学",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/12/cpplatform_tgx43jt54ezt7bamqcmjbk/t6_cpplatform_tgx43jt54ezt7bamqcmjbk1779878190.jpg",
|
||||
"progress": 5,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-10-08T15:27:08.000Z",
|
||||
"startedAt": null,
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 262,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=66b32530813abb78ag018a22"
|
||||
},
|
||||
{
|
||||
"bookId": "3300086064",
|
||||
"title": "河西走廊",
|
||||
"author": "《河西走廊》摄制组编",
|
||||
"category": "历史-历史地理",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/89/cpplatform_htt13rz3ky797h8pvypqq1/t6_cpplatform_htt13rz3ky797h8pvypqq11707017069.jpg",
|
||||
"progress": 0,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-10-08T12:06:21.000Z",
|
||||
"startedAt": null,
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 0,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=de932a80813ab881eg014870"
|
||||
},
|
||||
{
|
||||
"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-10-08T12:05:30.000Z",
|
||||
"startedAt": "2026-01-11T10:32:09.000Z",
|
||||
"finishedAt": "2026-09-27T16:39:36.000Z",
|
||||
"readingSeconds": 295,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=b0b32630813abaadeg0157d1"
|
||||
},
|
||||
{
|
||||
"bookId": "3300095415",
|
||||
"title": "觉醒年代(全集|同名影视原著)",
|
||||
"author": "龙平平",
|
||||
"category": "历史-历史小说",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/66/cpplatform_4opftuyz4szxsagdfgsn1i/t6_cpplatform_4opftuyz4szxsagdfgsn1i1713258044.jpg",
|
||||
"progress": 0,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-10-08T11:44:34.000Z",
|
||||
"startedAt": null,
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 0,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=e6032ec0813ab8bc5g015fd3"
|
||||
},
|
||||
{
|
||||
"bookId": "182788",
|
||||
"title": "北京法源寺(文学性与思想性相结合的经典作品)",
|
||||
"author": "李敖",
|
||||
"category": "历史-历史小说",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/16/yuewen_182788/t6_yuewen_1827881778320200.jpg",
|
||||
"progress": 4,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-09-27T00:21:57.000Z",
|
||||
"progress": 100,
|
||||
"finished": true,
|
||||
"lastReadAt": "2026-10-08T11:42:40.000Z",
|
||||
"startedAt": "2026-09-21T06:26:14.000Z",
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 451,
|
||||
"finishedAt": "2026-10-08T11:30:06.000Z",
|
||||
"readingSeconds": 11837,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=dcc3296052ca04dccdbef6c"
|
||||
},
|
||||
{
|
||||
"bookId": "23796324",
|
||||
"title": "昨日的世界",
|
||||
"author": "茨威格",
|
||||
"category": "文学-外国文学",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/58/YueWen_23796324/t6_YueWen_23796324.jpg",
|
||||
"progress": 31,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-09-26T16:38:15.000Z",
|
||||
"startedAt": "2026-08-05T16:49:22.000Z",
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 7970,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=80a324f0716b1a6480af682"
|
||||
},
|
||||
{
|
||||
"bookId": "26678299",
|
||||
"title": "大师和玛格丽特(果麦经典)",
|
||||
@@ -38,12 +80,40 @@
|
||||
"cover": "https://wfqqreader-1252317822.image.myqcloud.com/cover/299/26678299/t6_26678299.jpg",
|
||||
"progress": 100,
|
||||
"finished": true,
|
||||
"lastReadAt": "2026-09-25T11:25:17.000Z",
|
||||
"lastReadAt": "2026-09-28T04:46:31.000Z",
|
||||
"startedAt": "2026-09-04T16:07:07.000Z",
|
||||
"finishedAt": "2026-09-22T03:34:52.000Z",
|
||||
"readingSeconds": 14140,
|
||||
"readingSeconds": 14442,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=34c329807197141b34cf1db"
|
||||
},
|
||||
{
|
||||
"bookId": "23914527",
|
||||
"title": "树莓派开始,玩转Linux",
|
||||
"author": "Vamei 周昕梓",
|
||||
"category": "计算机-计算机综合",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/55/YueWen_23914527/t6_YueWen_23914527.jpg",
|
||||
"progress": 100,
|
||||
"finished": true,
|
||||
"lastReadAt": "2026-09-27T16:38:55.000Z",
|
||||
"startedAt": "2026-04-17T15:59:58.000Z",
|
||||
"finishedAt": "2026-09-27T16:37:54.000Z",
|
||||
"readingSeconds": 14629,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=140329d0716ce81f140468e"
|
||||
},
|
||||
{
|
||||
"bookId": "23796324",
|
||||
"title": "昨日的世界",
|
||||
"author": "茨威格",
|
||||
"category": "文学-外国文学",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/58/YueWen_23796324/t6_YueWen_23796324.jpg",
|
||||
"progress": 31,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-09-27T10:00:15.000Z",
|
||||
"startedAt": "2026-08-05T16:49:22.000Z",
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 8117,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=80a324f0716b1a6480af682"
|
||||
},
|
||||
{
|
||||
"bookId": "3300176703",
|
||||
"title": "关于建国以来党的若干历史问题的决议",
|
||||
@@ -72,20 +142,6 @@
|
||||
"readingSeconds": 6214,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=a1932750813ab6e79g017e78"
|
||||
},
|
||||
{
|
||||
"bookId": "3300207468",
|
||||
"title": "快乐的死(果麦经典)",
|
||||
"author": "[法]加缪",
|
||||
"category": "文学-外国文学",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/12/cpplatform_tgx43jt54ezt7bamqcmjbk/t6_cpplatform_tgx43jt54ezt7bamqcmjbk1779878190.jpg",
|
||||
"progress": 0,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-09-22T03:35:33.000Z",
|
||||
"startedAt": null,
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 28,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=66b32530813abb78ag018a22"
|
||||
},
|
||||
{
|
||||
"bookId": "3300048195",
|
||||
"title": "正面管教(修订版)",
|
||||
@@ -114,20 +170,6 @@
|
||||
"readingSeconds": 589,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=b4432330813abb059g01728a"
|
||||
},
|
||||
{
|
||||
"bookId": "23914527",
|
||||
"title": "树莓派开始,玩转Linux",
|
||||
"author": "Vamei 周昕梓",
|
||||
"category": "计算机-计算机综合",
|
||||
"cover": "https://cdn.weread.qq.com/weread/cover/55/YueWen_23914527/t6_YueWen_23914527.jpg",
|
||||
"progress": 97,
|
||||
"finished": false,
|
||||
"lastReadAt": "2026-06-10T16:14:02.000Z",
|
||||
"startedAt": "2026-04-17T15:59:58.000Z",
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 14309,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=140329d0716ce81f140468e"
|
||||
},
|
||||
{
|
||||
"bookId": "3300151878",
|
||||
"title": "从Python开始学编程",
|
||||
@@ -226,20 +268,6 @@
|
||||
"readingSeconds": 291,
|
||||
"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",
|
||||
"startedAt": null,
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 160,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=93d325a0719b200493d5ba9"
|
||||
},
|
||||
{
|
||||
"bookId": "40055543",
|
||||
"title": "置身事内:中国政府与经济发展",
|
||||
@@ -282,20 +310,6 @@
|
||||
"readingSeconds": 4246,
|
||||
"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",
|
||||
"startedAt": null,
|
||||
"finishedAt": null,
|
||||
"readingSeconds": 196,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=b0b32630813abaadeg0157d1"
|
||||
},
|
||||
{
|
||||
"bookId": "39280063",
|
||||
"title": "博弈论:每个人都能成为决策高手(《人民日报》推荐)",
|
||||
@@ -394,5 +408,6 @@
|
||||
"readingSeconds": 137,
|
||||
"deepLink": "https://weread.qq.com/book-detail?type=1&v=47532ac05c659b47554a825"
|
||||
}
|
||||
]
|
||||
],
|
||||
"albums": []
|
||||
}
|
||||
|
||||
@@ -36,6 +36,39 @@ export type ReadingData = {
|
||||
updatedAt: string
|
||||
source: string
|
||||
books: ReadingBook[]
|
||||
/**
|
||||
* 专辑 / 有声书。
|
||||
*
|
||||
* 可选:`--soft` 构建路径下用的可能是更早版本的 reading.json,那时还没有这个字段。
|
||||
* 调用方一律写 `data.albums ?? []`。
|
||||
*/
|
||||
albums?: ReadingAlbum[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 一张有声书专辑。
|
||||
*
|
||||
* 字段刻意比 ReadingBook 少 —— 微信读书给专辑的原始结构里(albumInfo /
|
||||
* albumInfoExtra)**没有阅读进度,也没有 deepLink**,所以这里没有 progress,
|
||||
* 前端也不该伪造一条进度条。哪天官方补了字段,先改 scripts/fetch-reading.mjs。
|
||||
*/
|
||||
export type ReadingAlbum = {
|
||||
albumId: string
|
||||
name: string
|
||||
/** 演播 / 作者 */
|
||||
author: string
|
||||
cover: string
|
||||
/** 音频集数;取不到时为 0 */
|
||||
trackCount: number
|
||||
/** 是否已完结(原始字段 finish === 1) */
|
||||
finished: boolean
|
||||
/** 完结状态原文,如「已完结」 */
|
||||
finishStatus: string
|
||||
intro: string
|
||||
/** 最近收听时间,ISO;从没听过时为 null */
|
||||
lastListenedAt: string | null
|
||||
/** 跳转链接。官方文档未列此字段,实测可能为空串 */
|
||||
deepLink: string
|
||||
}
|
||||
|
||||
const DATA_FILE = path.join(process.cwd(), "src/data/reading.json")
|
||||
|
||||
Reference in New Issue
Block a user