Files

11 KiB
Raw Permalink Blame History

2026-07-17 工作日志

微信读书数据展示网站

  • 使用微信读书 API(weread-skills)拉取用户的阅读数据
  • 数据采集脚本 fetch_data.py:拉取书架(404本)、阅读统计(overall+annually)、笔记本(32本1709条笔记)数据,存入本地 SQLite 数据库 weread.db
  • Flask 后端 app.py(端口 8080),提供 8 个 API 接口:overview, yearly-trend, top-books, categories, authors, time-distribution, shelf, notebooks
  • 前端页面:ECharts 图表(年度趋势柱状图、24h时段折线图、分类饼图、作者排行条形图)、书架网格(分页+筛选)、笔记概览
  • 数据规模:累计阅读 339 小时 57 分钟、304 天阅读、404 本书架藏书、1709 条笔记
  • 技术栈:Python Flask + SQLite + ECharts + 原生 HTML/CSS/JS

功能迭代(第二批)

  • Git 仓库:dev 分支初版提交 + 功能迭代提交,master 分支 --no-ff 合并,遵循 conventional commits 规范
  • 书籍详情弹窗:点击书架书籍实时调 /book/info + /book/getprogress API,展示详细信息+阅读进度,数据入库 book_details/book_progress 表
  • 笔记详情弹窗:点击笔记书籍实时调 /book/bookmarklist + /review/list/mine API,划线按章节分组+想法/点评,数据入库 book_highlights/book_reviews/book_chapters 表
  • 推荐页面:个性化推荐(/book/recommend)+ 关键词搜索(/store/search),数据入库 recommended_books/search_results 表
  • 修复 Flask 中文 URL 参数编码问题(latin-1 -> utf-8 转码)
  • MySQL 版本建表语句 schema_mysql.sql:18 张表完整 DDL,utf8mb4 字符集,含索引和字段注释
  • 新增 7 张按需数据表:book_details, book_progress, book_highlights, book_chapters, book_reviews, recommended_books, search_results

MySQL 迁移

  • 启动本地 MySQL 5.7.31(通过 launchctl load com.oracle.oss.mysql.mysqld.plist)
  • MySQL root 密码:258963
  • 创建数据库 weread_dashboard(utf8mb4),执行 schema_mysql.sql 创建 18 张表
  • 迁移脚本 migrate_to_mysql.py:SQLite -> MySQL 全量迁移,共 862 行数据
  • 时间戳列自动转换(SQLite int -> MySQL TIMESTAMP)
  • 中文内容 utf8mb4 完整保存,数据校验通过
  • Flask 服务暂未切换至 MySQL(用户要求服务不重启)

第三批功能迭代(MySQL 切换 + 文档 + 告警)

  • 数据源切换至 MySQL:app.py 从 SQLite 全面切换到 PyMySQL,所有 API 读取 MySQL weread_dashboard 数据库
  • db_required 装饰器:统一管理数据库连接和异常处理,MySQL 连接失败返回 HTTP 503
  • 健康检查接口:新增 /api/health,前端页面加载时优先检测 MySQL 连接状态
  • 前端告警横幅:MySQL 连接失败时显示黄色告警横幅,阻止后续数据加载
  • 修复 fetched_at 兼容问题:Unix 整数时间戳改为 MySQL TIMESTAMP 格式字符串
  • 代码中文注释:app.py 所有函数/API/工具函数添加完整中文文档注释;fetch_data.py 所有建表语句添加列级中文注释
  • 技术文档 docs/TECHNICAL_DOC.md:项目概述、系统架构图、数据流设计、15 个 API 接口详情、部署指南
  • 元数据文档 docs/METADATA_DOC.md:18 张表完整字段说明、索引设计、表关系 ER 图、数据类型规范
  • Git 提交:dev 分支提交 → master 分支 --no-ff 合并

数据模型 v2.0 重构(第四批迭代)

  • 官方 API 文档比对:拉取 GitHub 上微信读书官方 8 份 API 文档(book.md, shelf.md, readdata.md, notes.md, discover.md, search.md, review.md, profile.md),逐字段对比发现 12 张缺失表、40+ 缺失字段
  • schema_mysql.sql 重写:从 18 张表扩展到 31 张表,新增 shelf_albums, shelf_meta, prefer_publishers, prefer_cps, prefer_books, read_rank, medals, year_reports, book_best_bookmarks, book_underlines, public_reviews, similar_books, search_sessions
  • 双列时间戳模式:所有 INT UNSIGNED 时间戳字段均伴随 _dt TIMESTAMP 列(如 update_time ↔ update_time_dt)
  • 审计列:每张表统一维护 created_at + updated_at(MySQL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)
  • 索引优化:按实际查询模式设计复合索引、排序索引(如 idx_books_read_update_time DESC, uk_highlights_bookmark)
  • fetch_data.py 重写:SKILL_VERSION 升级至 1.0.4,覆盖全部 31 张表数据采集,新增 ts_to_dt() 辅助函数
  • app.py 适配:移除 ensure_tables(),新增 ts_to_dt_str(),所有 INSERT 语句适配新列名
  • migrate_to_mysql.py 重写:支持 31 张表迁移
  • 数据重建:删除旧 weread.db + DROP MySQL 数据库,重建后采集 685 行数据(404 books, 32 notebooks, 20 publishers, 20 cps, 30 medals, 24 prefer_books 等)
  • 文档更新:TECHNICAL_DOC.md 版本升至 2.0.0,新增数据模型 v2.0 设计规范章节;METADATA_DOC.md 完整重写覆盖全部 31 张表
  • Git 历史:dev 分支两次提交(refactor + docs),master 分支 --no-ff 合并(commit 9c32f69)

前端 UI 增强(第五批迭代)

  • 封面图高清化:新增 hdCover() 函数,将微信读书 CDN 封面 URL 从 t6_(低清150px)升级到 t8_(高清500px),7 处封面图片全部应用,三级回退机制(t8_→t6_→占位图)
  • 阅读排行封面修复:.top-book-cover 从固定 height:200px + object-fit:cover 改为 aspect-ratio:3/4,解决竖版书封面被裁切模糊问题
  • 明亮/黑暗主题切换:
    • CSS 定义 [data-theme="dark"] 变量集(暖色深调,保持文学质感)
    • 导航栏添加太阳/月亮图标切换按钮
    • localStorage 持久化用户选择,首次访问跟随系统 prefers-color-scheme
    • 防闪烁内联脚本在页面渲染前设置主题
    • ECharts 图表通过 getChartColors() 读取 CSS 变量,主题切换时自动重绘
    • 全局 0.3s 平滑过渡(背景、文字、边框、阴影)
  • 整体样式优化:
    • Hero 渐变色从紫色改为暖棕/琥珀色,与全局 accent 色系统一
    • 所有硬编码颜色替换为 CSS 变量(评分标签、徽章、排行标牌等)
    • 推荐区封面改为 aspect-ratio:3/4 竖版展示
    • 页脚数据存储标注从 SQLite 更新为 MySQL
  • Git 提交:commit ae40ed9(master 分支)
  • Bug 修复:想法 star 值溢出:红楼梦书评的 star 字段返回 100(微信读书 API 对书评返回的评分值,非 1-5 范围),导致 "☆".repeat(5-100) 抛出 RangeError: Invalid count value: -95。修复:用 Math.max(0, Math.min(5, parseInt(r.star)||0)) 限制到 0-5 范围。commit 4d8cc2a
  • 前端四大功能增强(commit 7c91814):
    1. 想法详情独立页面:从弹窗改为全页面视图,三类分类(划线/书评/想法),分类筛选标签,视觉标识(badge 颜色区分),章节分组,书评显示 abstract 原文引用
    2. 标签页切换:总览/数据图表/读书排行/书架/笔记/推荐 从纵向滚动改为横向标签页切换,图表懒加载(首次切换到图表页时才初始化 ECharts)
    3. 阅读排行竖向列表:从卡片网格改为横向排列列表,封面缩小至 48x64px 与书架一致,金/银/铜排名徽章
    4. 回到顶部浮动按钮:滚动超过 400px 显示,平滑滚动回顶部
    5. 书籍详情弹窗新增"查看想法"按钮,跳转到想法详情页
  • 搜索封面修复 + 顶部搜索框 + 书架搜索优化(commit 4c916ec):
    1. hdCover() 升级:新增对 s_ 前缀封面 URL 的高清升级(搜索结果用 s_ 前缀,比 t6_ 更模糊)
    2. 顶部常驻搜索框:导航栏下方添加搜索输入框,回车自动切换到推荐页搜索子标签执行搜索
    3. 书架搜索支持书名/作者:/api/shelf 新增 keyword 参数(title LIKE OR author LIKE),原 category 改为精确匹配
    4. 分类标签栏:书架页显示所有分类的可点击标签(pill 样式),点击筛选对应分类
    5. 微信读书 CDN 封面前缀:t6_=低清(~150px), s_=超低清(~90px,搜索结果用), t8_=高清(~500px)

12:27 移除分类排序按钮,默认按分类排序

  • 用户反馈:分类排序不需要前端按钮,默认生效即可
  • 删除 index.html 中的 shelfSortBtn 按钮
  • app.js 中 shelfSortMode 默认值从 "default" 改为 "category"
  • 删除 toggleShelfSort 函数和 .shelf-sort-btn CSS 样式
  • 书架列表始终按分类分组渲染,无需手动切换

12:32 书架恢复横向网格展示,移除分类分组标题

  • 用户反馈:不需要展示分类分组标题(如"历史-历史读物 3本"),恢复简单横向书架
  • 删除 renderBooksGroupedByCategory 函数,loadShelf 始终用简单网格渲染
  • 后端 sort=category 仍生效(按分类排序),但前端不显示分组
  • 分类筛选标签(可折叠层级)保留不变

13:11 添加书架刷新按钮 + 后端服务保活方案

书架刷新按钮

  • 书架筛选栏新增「↻ 刷新」按钮(shelfRefreshBtn)
  • 新增 refreshShelf() 函数:点击后重新调用 loadShelfCategories() + loadShelf(1)
  • 带 loading 状态:按钮禁用 + 文字变为"刷新中..."

后端服务频繁断掉的原因

  • 之前用 Bash 工具 run_in_background 启动的进程,会随工具会话结束被回收
  • nohup 启动的进程在沙箱环境中也可能被清理

保活方案

  1. start_server.sh 脚本:支持 start/daemon/stop/restart/status 五种模式
    • daemon 模式用 nohup 后台运行,记录 PID 到 .server.pid
  2. launchd 服务 (com.weread-dashboard.plist):
    • 路径: ~/Library/LaunchAgents/com.weread-dashboard.plist
    • KeepAlive=true: 崩溃自动重启
    • RunAtLoad=true: 开机自动启动
    • 需要用户在终端手动执行 launchctl load 加载

13:19 刷新按钮支持完整数据同步

问题

  • 之前刷新按钮只从 MySQL 重新读取,数据不会变(用户新增书后看不到变化)
  • 按钮宽度因文字变化抖动

解决方案

  • app.py 新增 /api/sync POST 接口:
    • 运行 fetch_data.py(微信读书API → SQLite)
    • 运行 migrate_to_mysql.py(SQLite → MySQL)
    • 返回每步结果和状态
  • refreshShelf() 改为:先 POST /api/sync → 再 loadShelfCategories + loadShelf
  • 按钮三阶段文案:同步中... → 加载中... → 刷新
  • CSS min-width:96px 防止宽度抖动
  • launchd plist 和 start_server.sh 均注入 WEREAD_API_KEY

数据流

微信读书API → fetch_data.py → weread.db(SQLite) → migrate_to_mysql.py → MySQL → app.py → 前端

测试验证

  • /api/sync 返回 ok:true,406本书同步成功

13:25 Flask 静态文件缓存导致 CSS 不生效

  • 现象:磁盘上 CSS 已更新(width:120px),但服务器仍返回旧版本
  • 原因:Flask 开发服务器缓存静态文件,修改后需重启服务才能生效
  • 解决:pkill + 重启 app.py
  • 提示用户浏览器也要 Cmd+Shift+R 强制刷新清除缓存

13:27 按钮高度抖动根因:↻ 字符渲染异常 + width 限制

  • 截图分析:按钮变成竖长方形,"⟳"和"同步中..."分两行显示
  • 根因:字符 ↻ (U+21BB) 在某些字体下被当成大尺寸字符
    • 配合 width:120px,文字强制换行成两行
    • 高度从 36px 暴涨到 150px+
  • 修复方案:
    • HTML: 拆成 + 两层结构
    • CSS: display:inline-flex + align-items:center + 固定 height:36px
    • 图标字符: ↻ → ⟳ (U+27F3),更稳定
    • JS: 通过 .btn-text 选择器单独更新文字,保留图标 span
  • 关键 CSS: flex-shrink:0 防止被 flex 父容器压缩