Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

InkReader

InkReader 是一款面向本地离线漫画收藏的桌面阅读器。它使用 Tauri 2、Vue 3、TypeScript、Rust 和 SQLite 构建,重点解决本地漫画仓库扫描、书架管理、压缩包阅读、阅读进度、收藏整理、元数据维护和数据备份等日常需求。

项目当前以 Windows 桌面使用为主要目标。应用只索引和读取用户选择的漫画文件,不会修改、移动或删除原始漫画文件。

主要功能

本地仓库

  • 添加本地漫画仓库目录。
  • 扫描仓库下的一层漫画文件夹和一层压缩包。
  • 支持手动重扫和启动后自动扫描。
  • 支持增量扫描,未变化的漫画会跳过深度扫描。
  • 扫描过程中显示进度、扫描阶段和持久化阶段。
  • 保存扫描历史、跳过条目、失败条目和重复漫画诊断。
  • 移除仓库记录时只删除 InkReader 索引,不删除原始漫画文件。

书架与检索

  • 后端分页加载书架,适合较大本地库。
  • 支持搜索标题、按仓库筛选、按作者筛选、按标签筛选、排除标签。
  • 支持阅读状态筛选:全部、未读、阅读中、已读。
  • 支持收藏状态筛选:全部、已收藏、未收藏。
  • 支持元数据缺失筛选:缺少简介、作者、标签、封面、发布时间。
  • 支持按标题、页数、创建时间、最近阅读、发布时间排序。
  • 支持网格、紧凑、列表三种书架布局。
  • 支持封面尺寸、作者显示、标签显示、标题行数和标题字号设置。

收藏与聚合

  • 支持默认收藏和自定义收藏夹。
  • 支持批量加入、移动、移出收藏夹。
  • 支持收藏夹名称、简介和封面维护。
  • 支持作者聚合页和标签聚合页,便于从人物或标签维度浏览漫画。

漫画详情与元数据

  • 显示标题、简介、作者、标签、章节数、页数、阅读进度等信息。
  • 支持自定义漫画标题,并可恢复扫描标题。
  • 支持编辑标题、简介、作者和标签。
  • 支持元数据健康检查,集中查看缺失元数据、缺失封面、无图片条目和重复漫画。

阅读器

  • 支持单页、双页、长条滚动阅读模式。
  • 支持从左到右和从右到左阅读方向。
  • 支持宽度适配、高度适配和原始尺寸。
  • 支持章节切换、页码跳转、上一页/下一页、上一章/下一章。
  • 自动保存阅读进度和最近阅读记录。
  • 支持标记已读、标记未读。
  • 支持书签创建、删除、检查和抽屉式跳转。
  • 支持亮度、对比度、背景色、翻页动画、空格滚动比例、长按空格滚动速度。
  • 支持自动滚动速度、启动延迟和手动滚动停止行为设置。
  • 支持有限图片预加载缓存,降低长章节阅读时的内存风险。

压缩包阅读

  • 支持将 zipcbzrarcbr 作为漫画条目扫描。
  • 支持文件夹漫画中把压缩包作为章节。
  • 支持按需读取压缩包内页面,不需要一次性解压整本漫画。
  • 提供 archive:// 自定义协议读取压缩包内图片。
  • 后端对压缩包页面字节做小型 LRU 缓存,改善连续阅读体验。

缓存、备份与设置

  • 自动生成和复用书架缩略图缓存。
  • 支持查看缩略图缓存统计。
  • 支持清理托管缩略图缓存。
  • 支持重建缺失缩略图。
  • 支持创建 SQLite 数据库备份。
  • 支持从备份恢复数据库,恢复前会生成回滚文件。
  • 支持阅读器设置、书架视图设置和单本阅读器设置。
  • 支持设置导出、设置导入和恢复默认设置。
  • 支持操作日志,记录备份、恢复、缓存维护等高影响操作。

下载

如果只想使用已构建版本,可以从 GitHub Releases 下载 Windows 安装包或便携包:

InkReader Releases

便携包可以直接运行 InkReader.exe。便携包的数据默认保存在可执行文件旁边的 data/ 目录中,适合放在非系统盘或随项目目录迁移。

技术栈

层级技术
桌面框架Tauri 2
前端Vue 3、TypeScript、Vite
UI 组件Naive UI
路由Vue Router hash history
后端Rust
数据库SQLite via rusqlite
压缩包zipunrar-ng
图片处理image
排序自然排序,适配 1.jpg2.jpg10.jpg

环境要求

  • Node.js LTS。
  • pnpm 10+,本项目锁定 pnpm@10.11.0
  • Rust stable,包含 rustccargo
  • Windows WebView2 Runtime。Windows 10/11 通常已自带。
  • Windows 构建 Tauri 时需要可用的 MSVC/Rust Windows 工具链。

检查本地开发环境:

pnpm check:env

快速开始

安装依赖:

pnpm install

启动桌面开发模式:

pnpm tauri:dev

也可以使用项目默认启动命令:

pnpm start

只启动 Vite 前端开发服务器:

pnpm dev

前端开发服务器地址由 Tauri 配置为:

http://127.0.0.1:1420

常用命令

pnpm check:env # 检查 Node.js、pnpm、rustc、cargo
pnpm dev # 仅启动 Vite 前端开发服务器
pnpm start # 检查环境并启动 Tauri 开发模式
pnpm tauri:dev # 检查环境并启动 Tauri 开发模式
pnpm typecheck # TypeScript 类型检查
pnpm build # 前端类型检查和 Vite 构建
pnpm tauri:build # 构建 Windows NSIS 安装包
pnpm tauri:build:installer # 构建 Windows NSIS 安装包
pnpm tauri:build:portable # 构建 Windows 便携包和 zip

Rust 常用检查:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

打包输出

构建安装包:

pnpm tauri:build:installer

构建便携包:

pnpm tauri:build:portable

便携包输出位置:

src-tauri/target/release/portable/InkReader-portable-<version>-windows-x64/
InkReader.exe
data/
README-portable.txt

同目录还会生成对应的 .zip 文件。

支持的漫画结构

InkReader 会把仓库目录下的一层文件夹或一层受支持压缩包识别为漫画入口。

多章节文件夹漫画

漫画仓库/
漫画 A/
元数据.json
cover.jpg
第 1 话/
0001.jpg
0002.jpg
第 2 话/
0001.jpg
0002.jpg

单层图片目录

单层图片目录会被识别为一本漫画,并自动生成名为 正文 的章节:

漫画仓库/
漫画 B/
cover.jpg
0001.jpg
0002.jpg
0003.jpg

压缩包漫画

漫画仓库/
漫画 C.cbz
漫画 D.zip
漫画 E.cbr
漫画 F.rar

压缩包章节

文件夹漫画中也可以把压缩包作为章节:

漫画仓库/
漫画 G/
cover.jpg
cbz/
第 1 话.cbz
第 2 话.cbz

扫描规则

  • 仓库只扫描一层文件夹和一层压缩包作为漫画入口。
  • 支持的图片页格式为 jpgjpegpngwebp
  • 支持的压缩包格式为 zipcbzrarcbr
  • 图片和章节使用自然排序。
  • 文件夹漫画优先使用根目录 cover.jpg 作为封面。
  • 没有 cover.jpg 时,使用第一张正文图片作为封面候选。
  • 压缩包漫画优先使用包内 cover.jpg,否则使用包内第一张图片。
  • 漫画目录存在 元数据.json 时,优先使用其中的标题、作者、标签、简介和章节顺序。
  • 单本漫画解析失败不会修改原始文件,错误会记录到扫描诊断中。
  • 重扫会基于路径、修改时间、大小等签名跳过未变化条目,并尽量保留阅读进度、收藏、书签和自定义标题。

元数据格式

元数据.json 使用 camelCase 字段。示例:

{
"id": "comic-001",
"name": "漫画标题",
"addtime": "2026-01-01T00:00:00Z",
"description": "漫画简介",
"author": ["作者 A", "作者 B"],
"tags": ["动作", "冒险"],
"chapterInfos": [
{
"chapterId": "chapter-001",
"chapterTitle": "第 1 话",
"order": 1
}
]
}

字段说明:

  • id:来源 ID,可用于辅助识别来源。
  • name:书架显示标题。
  • addtime:来源发布时间或添加时间,会映射为发布时间。
  • description:漫画简介。
  • author:作者列表。
  • tags:标签列表。
  • chapterInfos[].chapterTitle:章节标题,通常与章节目录名匹配。
  • chapterInfos[].order:章节排序值。

数据存储

InkReader 的运行数据保存在可执行文件所在目录旁边的 data/ 中:

<InkReader.exe 所在目录>/data/inkreader.sqlite3
<InkReader.exe 所在目录>/data/thumbs/

开发模式下,可执行文件通常位于:

src-tauri/target/debug/

因此开发数据通常位于:

src-tauri/target/debug/data/inkreader.sqlite3

注意事项:

  • 应用目录需要可写,否则数据库和缩略图缓存无法创建。
  • 从旧版本升级时,如果新位置没有数据库,应用会尝试从系统应用数据目录迁移旧数据库。
  • 删除仓库记录只删除 InkReader 索引,不删除漫画源文件。
  • 缩略图缓存只保存应用生成的缓存文件,可以通过应用内缓存维护功能重建。

项目结构

src/ Vue 前端源码
src/api/ Tauri command 调用封装和共享类型
src/components/common/ 应用外壳和通用组件
src/components/library/ 书架列表、卡片和视图设置组件
src/components/reader/ 阅读器工具栏、视口、章节和书签抽屉
src/composables/library/ 书架列表、选择、上下文菜单、缩略图水合逻辑
src/composables/reader/ 阅读器导航、键盘、进度、预加载、缩放、自动滚动逻辑
src/pages/ 页面级组件
src/router/ 前端路由
src/styles/ 全局样式和主题变量
src/utils/ 纯工具函数和默认设置
src-tauri/ Tauri/Rust 工程
src-tauri/src/lib.rs Tauri builder、AppState、archive 协议和 command 注册
src-tauri/src/commands/ Tauri command 入口
src-tauri/src/db/ SQLite 初始化、迁移、查询、备份、缓存维护
src-tauri/src/metadata/ 元数据 JSON 解析
src-tauri/src/models/ Rust 与前端共享的序列化模型
src-tauri/src/scanner/ 仓库、文件夹、压缩包、图片、自然排序扫描逻辑
src-tauri/src/thumbnail.rs 缩略图生成
scripts/ 环境检查和便携包脚本
docs/performance/ 大库和长章节性能基线

前端页面

当前路由:

路径页面
/library书架
/books/:bookId漫画详情
/reader/:bookId阅读器
/favorites收藏
/authors作者聚合
/tags标签聚合
/history阅读记录
/health元数据健康
/repositories仓库管理
/settings设置

后端职责

Rust 后端负责:

  • 本地路径校验。
  • 仓库扫描和增量扫描。
  • 文件夹漫画和压缩包漫画识别。
  • 元数据.json 解析。
  • 图片页过滤、自然排序和 URI 生成。
  • SQLite 迁移、读写、事务和索引维护。
  • 阅读进度、历史、书签、收藏和设置持久化。
  • 缩略图生成、清理和重建。
  • 数据库备份与恢复。
  • archive 协议读取压缩包内图片。

前端负责:

  • 页面展示和用户交互。
  • 调用 src/api/ 中的 Tauri command 封装。
  • 管理页面状态、筛选条件、阅读器设置和本地 UI 偏好。
  • 展示错误、扫描诊断、缓存维护结果和备份恢复结果。

性能基线

项目包含大库和长章节性能基线文档:

docs/performance/large-library-baseline.md

该文档覆盖:

  • 1000 本和 5000 本本地库测试方法。
  • 500 页长章节测试方法。
  • 30 分钟长条滚动稳定性检查。
  • 缩略图水合检查。
  • SQLite 索引盘点和查询计划检查流程。

涉及扫描、书架分页、缩略图、阅读器预加载、SQLite 索引的改动,建议按该文档记录前后数据。

开发约定

  • 前端 Tauri 类型集中在 src/api/tauri.ts
  • 具体 API 模块通过共享 call<T>() 封装调用 Tauri command。
  • Rust 暴露给前端的模型使用 #[serde(rename_all = "camelCase")]
  • 后端列表 API 负责筛选、排序、分页和总数,前端不应自行修正总数。
  • 修改字段名、command 名、设置 key、路由或枚举选项前,先用 rg 搜索镜像位置。
  • 数据库多表写入应通过事务保持一致性。
  • 任何仓库、缓存、备份、恢复功能都必须避免影响用户原始漫画文件。

推荐检查

文档或前端类型改动:

pnpm typecheck

前端构建检查:

pnpm build

Rust 改动:

cargo fmt --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml

完整桌面构建:

pnpm tauri:build:portable

常见问题

启动失败或白屏

先确认环境:

pnpm check:env

然后重新启动:

pnpm tauri:dev

无法创建数据库

确认 InkReader.exe 所在目录可写。便携包建议解压到普通用户目录或非系统盘,不要放在需要管理员权限写入的位置。

仓库扫描不到漫画

检查仓库结构是否满足以下条件之一:

  • 仓库一层子目录中包含图片页或章节目录。
  • 仓库一层存在 zipcbzrarcbr 文件。
  • 图片扩展名是 jpgjpegpngwebp

压缩包无法读取

确认压缩包未损坏、未加密,并且扩展名是 zipcbzrarcbr。如果单个压缩包失败,扫描诊断中会保留失败路径和原因。

缩略图缺失

可以在设置或缓存维护入口中重建缺失缩略图。缩略图缓存缺失不会影响漫画源文件。

想迁移数据

优先使用应用内数据库备份功能创建备份文件,再在目标环境中恢复。便携版也可以整体迁移包含 InkReader.exedata/ 的目录。

贡献

提交改动前建议至少运行与改动范围匹配的检查。涉及界面变化时建议附截图或说明主要交互路径。涉及扫描、阅读器、缓存或数据库性能时,建议补充可复现数据集和性能基线记录。

许可证

本项目基于 MIT License 开源,详见 LICENSE

About

InkReader 是一款基于 Tauri、Vue 和 Rust 构建的本地离线漫画桌面阅读器,支持漫画仓库扫描、压缩包阅读、书签、收藏、元数据编辑和 SQLite 阅读进度管理。

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages