mirror of
https://github.com/KingHWJ/WeReadBoard.git
synced 2026-11-03 18:24:58 +08:00
11 KiB
11 KiB
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 范围。commit4d8cc2a - 前端四大功能增强(commit 7c91814):
- 想法详情独立页面:从弹窗改为全页面视图,三类分类(划线/书评/想法),分类筛选标签,视觉标识(badge 颜色区分),章节分组,书评显示 abstract 原文引用
- 标签页切换:总览/数据图表/读书排行/书架/笔记/推荐 从纵向滚动改为横向标签页切换,图表懒加载(首次切换到图表页时才初始化 ECharts)
- 阅读排行竖向列表:从卡片网格改为横向排列列表,封面缩小至 48x64px 与书架一致,金/银/铜排名徽章
- 回到顶部浮动按钮:滚动超过 400px 显示,平滑滚动回顶部
- 书籍详情弹窗新增"查看想法"按钮,跳转到想法详情页
- 搜索封面修复 + 顶部搜索框 + 书架搜索优化(commit 4c916ec):
- hdCover() 升级:新增对
s_前缀封面 URL 的高清升级(搜索结果用 s_ 前缀,比 t6_ 更模糊) - 顶部常驻搜索框:导航栏下方添加搜索输入框,回车自动切换到推荐页搜索子标签执行搜索
- 书架搜索支持书名/作者:/api/shelf 新增 keyword 参数(title LIKE OR author LIKE),原 category 改为精确匹配
- 分类标签栏:书架页显示所有分类的可点击标签(pill 样式),点击筛选对应分类
- 微信读书 CDN 封面前缀:t6_=低清(~150px), s_=超低清(~90px,搜索结果用), t8_=高清(~500px)
- hdCover() 升级:新增对
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 启动的进程在沙箱环境中也可能被清理
保活方案
- start_server.sh 脚本:支持 start/daemon/stop/restart/status 五种模式
- daemon 模式用 nohup 后台运行,记录 PID 到 .server.pid
- launchd 服务 (com.weread-dashboard.plist):
- 路径: ~/Library/LaunchAgents/com.weread-dashboard.plist
- KeepAlive=true: 崩溃自动重启
- RunAtLoad=true: 开机自动启动
- 需要用户在终端手动执行 launchctl load 加载
13:19 刷新按钮支持完整数据同步
问题
- 之前刷新按钮只从 MySQL 重新读取,数据不会变(用户新增书后看不到变化)
- 按钮宽度因文字变化抖动
解决方案
- app.py 新增
/api/syncPOST 接口:- 运行 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 父容器压缩