本仓库当前不是原 Android 项目的 README 复用版,而是已经重构为前端、桌面壳、独立业务核心和无头服务端分层的实现。
| 形态 | 当前状态 | 入口 |
|---|---|---|
| Windows 桌面端 | 已验证构建和启动,产物为 构建结果/windows/legado-tauri.exe |
pnpm run dev:desktop / pnpm run build:windows:release |
| 浏览器 + headless 后端 | 本机 loopback 已跑通书源、搜索、加书架、目录、正文、进度保存闭环 | pnpm run build + cargo run -p legado-headless -- --dist ./dist |
| Android | 可产出 unsigned APK,真机能力仍在补齐 | pnpm run build:android:release |
| 严格 LAN 部署 | 还需要第二台设备实测 | legado-headless --bind 0.0.0.0 --token <token> |
当前后端已下沉到 crates/reader-core。src-tauri 只做桌面壳、系统能力和命令转发,src-headless 则复用同一个核心提供 HTTP 静态托管和 WebSocket 命令服务。
- 书架管理、阅读进度保存、章节缓存、TXT 导入。
- 滚动、分页、仿真、覆盖等阅读模式,支持阅读设置、字体、背景、段落处理和选中文本扩展。
- 封面缓存已下沉到后端核心,Tauri 与 headless 共用同一套缓存逻辑。
- 支持导入 Legado JSON 书源和本项目 JS 书源。
- 支持在线仓库、
@updateUrl检查与更新、外部书源目录、批量导入。 - 书源列表流式加载,多书源搜索增量返回,搜索 / 目录 / 正文任务支持取消。
- 规则引擎兼容常用 Legado / Rhino /
java.*/source.*能力,并通过书旗、七猫、番茄等真实样本持续回归。
- 前端业务通过统一传输层调用后端,可在 Tauri IPC、Harmony 桥接和 WebSocket 之间切换。
legado-headless可独立运行,托管dist并暴露/ws命令接口和安全的/asset资源接口。- WebDAV 同步、在线仓库、备份数据载荷、封面缓存等能力已经接入 headless 路径。
- 前端插件通过
legado.registerPlugin注册能力。 - 内置阅读器、书架、封面生成、TTS 等示例插件,位于
src/data/pluginExamples/。 - 插件运行在前端页面内,适合做阅读器 UI、文本处理、封面和轻量自动化扩展。
- 本地数据由
reader-core统一管理,主要包含 SQLite、书源文件、章节缓存、配置和书架数据。 - WebDAV 同步已实现凭据、状态、冲突、阅读进度和客户端状态通道。
- 浏览器 / headless 模式使用 data-transfer 形式备份和恢复,不允许服务端随意读写用户本机路径。
src/ Vue 3 前端
composables/useTransport Tauri IPC / Harmony / WebSocket 三模传输层
composables/useInvoke 统一命令调用入口
composables/useEventBus 统一事件入口
features/reader 阅读器业务
crates/reader-core/ Rust 业务核心,无 Tauri 依赖
storage SQLite、文件缓存、数据目录
parser Legado 规则解析、JS 运行时、HTML/JSONPath/XPath
crawler HTTP、DoH、请求配置
service 书源、书架、同步、JSON 文档服务
src-tauri/ Tauri 桌面壳
src/commands Tauri command 注册与转发
src/commands/router.rs WebSocket / IPC 共用命令路由
src/ws_server.rs 桌面壳内本机 WebSocket 服务,默认 127.0.0.1:7688/ws
src-headless/ 独立无头后端
src/main.rs HTTP static + /ws + /asset,直接链接 reader-core
docs/ 架构、命令矩阵、平台和书源兼容文档
scripts/ci/ 契约检查和质量门脚本
WebSocket 协议摘要:
{ "type": "invoke", "id": "uuid", "cmd": "booksource_list", "args": {} }响应:
{ "type": "response", "id": "uuid", "data": [] }事件:
{ "type": "event", "event": "rust:log", "payload": { "message": "..." } }完整约束见 docs/frontend-backend-separation.md。
| 层 | 技术 | 说明 |
|---|---|---|
| 前端 | Vue 3.5 + TypeScript 6 + Vite 8 | Composition API、Pinia、Naive UI、Tailwind CSS 4 |
| 桌面端 | Tauri 2.11 | Windows 桌面壳、系统对话框、文件和深链插件 |
| 后端核心 | Rust 2021 + reader-core |
书源、书架、缓存、同步、备份等业务逻辑 |
| 数据 | SQLite + SQLx + 文件存储 | 数据目录见 docs/data-layout.md |
| JS 运行时 | rquickjs |
执行 JS 书源和 Legado 规则中的脚本能力 |
| 网络 | reqwest + rustls | HTTP、代理、Cookie、压缩、请求超时 |
| 无头服务 | Axum + WebSocket | 静态前端托管、命令分发、资产访问 |
| 工具 | 版本 |
|---|---|
| Node.js | 24 |
| pnpm | 11.5.0,建议使用 corepack |
| Rust | 1.77+ |
| Windows 构建 | MSVC Build Tools + WebView2 |
| Android 构建 | JDK 21 + Android SDK / NDK,见 docs/platform-android.md |
git clone https://github.com/FanhuaAwA/legado.git
cd legado
corepack enable
pnpm install
pnpm run dev:desktoppnpm run build
cargo run -p legado-headless -- --bind 127.0.0.1 --port 7688 --dist ./dist --data ./reader-data打开:
http://127.0.0.1:7688/?ws=ws://127.0.0.1:7688/ws
需要局域网访问时显式绑定并加 token:
cargo run -p legado-headless -- --bind 0.0.0.0 --port 7688 --dist ./dist --data ./reader-data --token <token>客户端地址示例:
http://<host>:7688/?ws=ws://<host>:7688/ws?token=<token>
公网部署必须放在反向代理和 TLS 后面,不要直接裸露明文 WebSocket。
# 前端静态资源
pnpm run build
# Windows release
pnpm run build:windows:release
# Android unsigned APK
pnpm run build:android:release
# 独立无头后端
cargo build -p legado-headless --releasepnpm run lint
node scripts/ci/check-command-contract.mjs --json
cargo check -p legado-tauri
cargo check -p legado-headless
cargo test -p reader-core
cargo test -p legado-headless涉及真实网络书源的测试默认需要手动指定 --ignored,避免 CI 或本机短时间大量请求触发源站限制。
可导入上游 Legado JSON 书源,导入后保存为 .legado.json 并写入 SQLite 索引。兼容状态和真实样本结论见 docs/source-compat-matrix.md。
JS 书源通过注释头声明元数据,并导出约定函数:
// @name 示例书源
// @url https://example.com
// @enabled true
async function search(keyword, page) {
const html = await legado.http.get(
`https://example.com/search?q=${encodeURIComponent(keyword)}&page=${page}`,
);
return [];
}
async function bookInfo(bookUrl) {
return { name: "示例", bookUrl, tocUrl: bookUrl };
}
async function chapterList(tocUrl) {
return [];
}
async function chapterContent(chapterUrl) {
return await legado.http.get(chapterUrl);
}更多模板见 src/composables/useBookSource.ts,公有领域示例见 crates/reader-core/tests/fixtures/book_sources/wikisource_classics.js。
插件示例位于 src/data/pluginExamples/。最小形态:
// @name 示例插件
// @namespace com.legado.example
// @version 1.0.0
// @enabled true
legado.registerPlugin({
id: "com.legado.example",
name: "示例插件",
});- 前端业务代码不要直接调用
@tauri-apps/api,后端命令走useInvoke,事件走useEventBus,本地文件 URL 走useFileSrc,外部链接走useExternalOpen。 - 后端业务逻辑写入
crates/reader-core;src-tauri和src-headless只做平台适配、参数解析和命令分发。 - 新增或修改命令后运行
node scripts/ci/check-command-contract.mjs --json,并同步更新 docs/command-matrix.md。 - WebSocket 服务默认只绑定
127.0.0.1;对外暴露必须显式开启 token,公网部署必须使用 TLS。 js_eval是有意阻断的安全项,不要把它当作缺失命令补回。- 桌面独占功能必须通过
capabilities_get声明,让浏览器 / headless 形态能隐藏或禁用入口。
| 文档 | 内容 |
|---|---|
| docs/frontend-backend-separation.md | 前后端分离、传输层、WS 协议和强制约束 |
| docs/command-matrix.md | 前端 invoke 与后端 command 的契约矩阵 |
| docs/source-compat-matrix.md | 书源兼容状态和真实样本验证 |
| docs/data-layout.md | reader-core 数据目录布局 |
| docs/platform-windows.md | Windows 构建和已知限制 |
| docs/platform-android.md | Android 构建、签名和已知限制 |
| docs/ai-task-status.md | 当前维护状态、质量门和未结工作 |
本项目基于 MIT 许可证 开源。
如果这个项目对你有帮助,欢迎给一个 Star 支持。