diff --git a/readme.md b/readme.md index cbe9407..fc69533 100644 --- a/readme.md +++ b/readme.md @@ -41,9 +41,33 @@ --- -## 3. 主要数据结构 +## 3. UML 图(Mermaid) -### 3.1 booksnote +> 注:使用 Mermaid 语法,支持在支持渲染的 Markdown 查看。类之间仅展示主要依赖/调用,非完整字段集合。 + +### 3.1 类图(核心模块) +![img](uml/iShot_2025-09-07_12.55.41.png) + +### 3.2 时序图:应用启动 +![img](uml/iShot_2025-09-07_12.56.27.png) + +### 3.3 时序图:选择书籍 + AI 简评 +![img](uml/iShot_2025-09-07_12.56.00.png) + +### 3.4 时序图:导出 Markdown +![img](uml/iShot_2025-09-07_12.57.06.png) + +### 3.5 时序图:已读书籍网格刷新 +![img](uml/iShot_2025-09-07_12.57.19.png) + +### 3.6 时序图:点击已读封面跳转 +![img](uml/iShot_2025-09-07_12.57.28.png) + +--- + +## 4. 主要数据结构 + +### 4.1 booksnote ```python booksnote = { @@ -63,20 +87,20 @@ booksnote = { --- -## 4. 主要流程 +## 5. 主要流程 -### 4.1 数据同步 +### 5.1 数据同步 - 自动将 iBooks 的数据库和 plist 文件复制到本地 `data/` 目录,便于后续处理。 -### 4.2 构建 booksnote +### 5.2 构建 booksnote - 通过 `get_annotations` 解析 SQLite 笔记数据库,获取所有笔记。 - 通过 `parse_books_plist` 解析书籍元数据,获取书名、路径等信息。 - 遍历每本书的所有笔记,结合OPF、NCX文件和HTML 文件,定位章节名。 - 若无法通过目录文件定位章节,则尝试通过笔记选中文本在 HTML 文件中查找章节,否则标记为“未找到章节”。 -### 4.3 交互式选择书籍 +### 5.3 交互式选择书籍 - 读取 Books.plist 获取所有书籍元数据。 - 读取 BKLibrary.sqlite,获取每本书的最近打开时间(last_open,苹果时间戳,基准2001-01-01)。 @@ -84,7 +108,7 @@ booksnote = { - 按 last_open 时间戳降序排列,菜单显示“书名 [时间戳]”,时间戳为 last_open 字段。 - 使用 InquirerPy 提供模糊搜索交互界面,供用户选择要导出的书籍。 -### 4.4 导出 Markdown +### 5.4 导出 Markdown - 仅导出用户选择的书籍。 - Markdown 格式如下: @@ -101,15 +125,15 @@ booksnote = { --- -## 5. 关键函数说明 +## 6. 关键函数说明 -### 5.1 build_booksnote +### 6.1 build_booksnote - 输入:注释数据库路径、书籍 plist 路径 - 输出:结构化的 booksnote 字典 - 逻辑:遍历所有笔记,结合书籍元数据和目录信息,归类到章节下 -### 5.2 export_booksnote_to_md +### 6.2 export_booksnote_to_md - 输入:booksnote、booksinfo、导出路径 - 输出:Markdown 字符串,并写入文件 @@ -117,7 +141,7 @@ booksnote = { --- -## 6. 交互与用户体验 +## 7. 交互与用户体验 - 通过命令行交互,用户可模糊搜索并选择要导出的书籍。 - 若无可导出的笔记,程序自动退出并提示。 @@ -125,9 +149,9 @@ booksnote = { --- -## 7. 代码片段示例 +## 8. 代码片段示例 -### 7.1 书名处理逻辑 +### 8.1 书名处理逻辑 ```python name = info.get('displayname') or info.get('itemname') or assetid @@ -135,7 +159,7 @@ name = info.get('displayname') or info.get('itemname') or assetid if '-' in name: name = name.split('-', 1)[0].strip() ``` -### 7.2 交互式选择与排序 +### 8.2 交互式选择与排序 ```python from booklist_parse import get_books_last_open @@ -156,7 +180,7 @@ answer = inquirer.fuzzy( --- -## 8. 依赖说明 +## 9. 依赖说明 - Python 3 - 主要依赖库:`InquirerPy`, `bs4`, `shutil`, `os`, `datetime`, `sqlite3` @@ -164,7 +188,7 @@ answer = inquirer.fuzzy( --- -## 9. 目录结构 +## 10. 目录结构 - `data/`:存放同步下来的数据库和 plist 文件(含 AEAnnotation.sqlite、Books.plist、BKLibrary.sqlite 等) - `notes/`:导出的 Markdown 文件 @@ -172,9 +196,9 @@ answer = inquirer.fuzzy( --- -## 10. 主要代码文件说明(细化) +## 11. 主要代码文件说明(细化) -### 10.1 exportbooknotes.py +### 11.1 exportbooknotes.py - 采用 OOP 设计,核心类为 `BookNotesExporter`: - `build_booksnote(bookid=None)`:构建结构化笔记数据。 @@ -185,7 +209,7 @@ answer = inquirer.fuzzy( - 只处理用户选中书籍的笔记,按章节分组导出 Markdown。 - 依赖核心解析模块,负责主流程调度。 -### 10.2 annotationdata.py +### 11.2 annotationdata.py - OOP 设计,核心类为 `AnnotationManager`: - `get_annotations(bookid=None)`:返回所有或指定 assetid 的笔记。 @@ -193,7 +217,7 @@ answer = inquirer.fuzzy( - 解析 AEAnnotation.sqlite,提取所有或指定 assetid 的笔记。 - 支持苹果时间戳转换,结构化输出。 -### 10.3 booklist_parse.py +### 11.3 booklist_parse.py - OOP 设计,核心类为 `BookListManager`: - `get_books_info()`:获取书籍元数据。 @@ -201,13 +225,13 @@ answer = inquirer.fuzzy( - 解析 Books.plist,获取书籍元数据(书名、作者、路径、时间等)。 - 解析 BKLibrary.sqlite,获取每本书的最近打开时间。 -### 10.4 opf_parse.py +### 11.4 opf_parse.py - OOP 设计,核心类为 `OPFParser`: - `parse_opf(filepath)`:静态方法,返回 id->href 映射。 - 解析 epub 的 OPF 文件,获取章节与文件映射关系(idref -> href)。 -### 10.5 toc_parse.py +### 11.5 toc_parse.py - OOP 设计,核心类为 `TOCParser`: - `parse_navpoints(navpoints)`:递归解析 navPoint 节点。 @@ -216,13 +240,13 @@ answer = inquirer.fuzzy( - `parse_html_title(html_path)`:解析 html 文件标题。 - 解析 NCX 目录文件,递归构建章节树结构。 -### 10.6 backup/booksnote.py +### 11.6 backup/booksnote.py - 历史/备份脚本,辅助数据迁移或格式转换。 --- -## 11. 扩展与维护建议 +## 12. 扩展与维护建议 - 可扩展支持多本书批量导出 - 可增加导出格式(如 HTML、PDF) @@ -235,9 +259,9 @@ answer = inquirer.fuzzy( --- -## 12. GUI 架构与模块调用关系(2025 拆分后更新) +## 13. GUI 架构与模块调用关系(2025 拆分后更新) -### 12.1 模块职责概览 +### 13.1 模块职责概览 | 模块 | 主要类/函数 | 职责 | 关键依赖 | |------|-------------|------|----------| @@ -252,7 +276,7 @@ answer = inquirer.fuzzy( | `opf_parse.py` | `OPFParser` | 解析 OPF 获取 manifest 映射 | OPF XML | | `charts.py` | 图表组件 | 周 / 月 / 年 / 气泡指标可视化 | `BookListManager` 汇总数据 | -### 12.2 运行时对象关系(简化 UML 文本表示) +### 13.2 运行时对象关系(简化 UML 文本表示) ``` IBookExportApp ├── BookListManager (数据/统计) @@ -268,7 +292,7 @@ IBookExportApp 2. 网格构建 -> `FinishedBooksMixin._populate_finished_books_grid` 3. AI 简评 -> `BookReviewWorker` 发起,完成后回调 `_on_review_finished` -### 12.3 启动序列(Startup Sequence) +### 13.3 启动序列(Startup Sequence) 1. 用户运行 `ibook_export_app.py` → 创建 `QApplication` 2. `IBookExportApp.__init__`: - 加载 `.ui` @@ -281,14 +305,14 @@ IBookExportApp - 安排延迟 `_relayout_finished_grid()` 确保初次布局正确 3. 主窗口显示;用户可交互。 -### 12.4 书籍切换流程(Selecting a Book) +### 13.4 书籍切换流程(Selecting a Book) 1. 用户在列表中选中条目 → `currentRowChanged` → `update_book_info(row)` 2. 刷新右侧三张封面(当前 + 后两本轮播预览) 3. 构建基础信息 `_base_info_cache` 4. 若 `bookintro.json` 已有简评 → 直接渲染;否则启动新 `BookReviewWorker` → 占位“简评获取中...” 5. 线程完成 → 通过信号调用 `_on_review_finished` → 更新 HTML。 -### 12.5 AI 简评线程生命周期 +### 13.5 AI 简评线程生命周期 1. 实例化 `BookReviewWorker(bookname, prompt, json_path)` 2. 连接 `finished` 信号到: - `_on_review_finished` @@ -296,7 +320,7 @@ IBookExportApp 3. `worker.start()` → 线程内部:调用 `DashScopeChatClient.ask()`;写入/更新 `bookintro.json`;发送 `finished` 信号。 4. 主线程根据 `_current_bookname` 校验是否仍是当前书,防止串写。 -### 12.6 已读书籍网格刷新逻辑 +### 13.6 已读书籍网格刷新逻辑 事件触发: 1. 程序启动初次调用 `_populate_finished_books_grid()` 2. Tab 切换到“已读书籍”标签 → `_on_main_tab_changed()` → 若命中,立即 `_relayout_finished_grid()` 并延迟一次;(后续可扩展为定期重新查询) @@ -307,26 +331,26 @@ IBookExportApp - 将 Apple epoch(2001) 秒转为 `datetime`,过滤 `year==当前年` - 返回列表后排序(时间倒序) -### 12.7 封面加载与缩放流程 +### 13.7 封面加载与缩放流程 1. `_load_initial()` / `update_book_info()` 内调用 `find_book_cover()` 获取路径 2. 原图 QPixmap 存入 `_cover_pixmaps_original` 3. `_apply_cover_scale()` 使用当前 `cover_ratio`(默认 1.2)和弹性策略计算目标高度 4. 固定宽 180px,受硬上限 400px 与(可选)文本区 45% 限制 5. 非弹性模式忽略文本高度,仅 ratio + 硬上限。 -### 12.8 导出流程(Export Notes) +### 13.8 导出流程(Export Notes) 1. 用户点击“导出”按钮 → `export_notes()` 2. 取当前行 assetid → `BookNotesExporter.build_booksnote(bookid)` 3. 组装单书字典 → `export_booksnote_to_md()` 输出 Markdown 到 `notes/` 目录 4. 弹窗提示路径。 -### 12.9 统计图表流程 +### 13.9 统计图表流程 1. 启动后调用 `_init_charts()`(懒加载) 2. 获取周 / 月 / 年聚合数据及总指标 3. 构造原生自绘组件 `BarChartWidget` / `ScatterChartWidget` / `BubbleMetricsWidget` 4. 添加到对应 Layout。 -### 12.10 关键调用关系(摘要) +### 13.10 关键调用关系(摘要) ``` update_book_info -> find_book_cover (CoverMixin) update_book_info -> BookReviewWorker.start -> _on_review_finished @@ -336,7 +360,7 @@ export_notes -> BookNotesExporter.build_booksnote -> export_booksnote_to_md _init_charts -> manager.get_total_readtime* 系列函数 ``` -### 12.11 数据流摘要 +### 13.11 数据流摘要 ``` iBooks 原始文件 -> sync_source_files -> data/*.sqlite / Books.plist └─ BookListManager 载入 -> booksinfo / open_times / 阅读统计 @@ -349,7 +373,7 @@ iBooks 原始文件 -> sync_source_files -> data/*.sqlite / Books.plist AI 请求 -> BookReviewWorker -> DashScopeChatClient.ask -> bookintro.json -> _on_review_finished 渲染 ``` -### 12.12 扩展点与建议 +### 13.12 扩展点与建议 1. 已读书籍:增加“显示全部年份 / 仅今年”开关;提供手动“刷新”按钮。 2. 封面缓存:引入 LRU (assetid -> QPixmap) 降低重复磁盘扫描。 3. AI 简评:加速策略(本地缓存 TTL、批量预取前 N 本)。 @@ -361,7 +385,7 @@ AI 请求 -> BookReviewWorker -> DashScopeChatClient.ask -> bookintro.json -> _o 6. 性能:大书量时(>1000)列表初始化可用分页或懒加载。 7. 打包:后续可用 `PyInstaller`,将可执行与资源(icons、ui)整合。 -### 12.13 风险与缓解 +### 13.13 风险与缓解 | 风险 | 描述 | 缓解 | |------|------|------| | 数据不同步 | data/ 下 sqlite 未更新导致已读缺失 | 提供“重新同步”按钮;比对文件修改时间 | @@ -373,32 +397,6 @@ AI 请求 -> BookReviewWorker -> DashScopeChatClient.ask -> bookintro.json -> _o (本节为 2025-09 结构化重构新增) -## 13. UML 图(Mermaid) - -> 注:使用 Mermaid 语法,支持在支持渲染的 Markdown 查看。类之间仅展示主要依赖/调用,非完整字段集合。 - -### 13.1 类图(核心模块) -![img](uml/iShot_2025-09-07_12.55.41.png) - -### 13.2 时序图:应用启动 -![img](uml/iShot_2025-09-07_12.56.27.png) - -### 13.3 时序图:选择书籍 + AI 简评 -![img](uml/iShot_2025-09-07_12.56.00.png) - -### 13.4 时序图:导出 Markdown -![img](uml/iShot_2025-09-07_12.57.06.png) - - -### 13.5 时序图:已读书籍网格刷新 -![img](uml/iShot_2025-09-07_12.57.19.png) - - -### 13.6 时序图:点击已读封面跳转 -![img](uml/iShot_2025-09-07_12.57.28.png) - ---- - ## 14. 书籍阅读时长统计与可视化 ### 14.1 阅读时长统计逻辑 @@ -470,3 +468,5 @@ AI 请求 -> BookReviewWorker -> DashScopeChatClient.ask -> bookintro.json -> _o - 气泡图支持动画过渡或改为雷达/仪表盘形式;“已读”气泡可按年份切换(未来提供年份选择器)。 - 增加刷新按钮与 Esc 退出全屏逻辑。 +--- +