From dec8ec8c447abe3c96cbaf854ad8730867d7ba20 Mon Sep 17 00:00:00 2001 From: hectorqin Date: Mon, 28 Sep 2026 10:32:52 +0800 Subject: [PATCH] docs: document media features and remove remote source plugin guides --- README.en.md | 60 +- README.md | 61 +- docs/README.md | 13 +- docs/api.md | 273 +-- docs/architecture.md | 4 +- docs/backup.zh-CN.md | 6 +- docs/closed-issues-2026-09-23/issues.md | 1877 --------------------- docs/closed-issues-analysis-2026-09-23.md | 179 -- docs/configuration.en.md | 31 +- docs/configuration.zh-CN.md | 31 +- docs/development.en.md | 10 +- docs/development.zh-CN.md | 10 +- docs/ecosystem-roadmap.zh-CN.md | 41 +- docs/getting-started.en.md | 32 +- docs/getting-started.zh-CN.md | 32 +- docs/opds-webdav.zh-CN.md | 2 +- docs/p0-progress-2026-09-23.md | 6 +- docs/p1-progress-2026-09-23.md | 6 +- docs/p2-progress-2026-09-24.md | 50 - docs/plugin-extensions.md | 63 - docs/source-login.zh-CN.md | 12 - docs/source-plugins.md | 499 ------ docs/ui-review/collections-ux.md | 4 +- docs/ui-review/source-search.md | 9 - docs/ui-review/sources-ux.md | 27 - docs/ui.md | 2 +- docs/user-guide.zh-CN.md | 25 +- 27 files changed, 258 insertions(+), 3107 deletions(-) delete mode 100644 docs/closed-issues-2026-09-23/issues.md delete mode 100644 docs/closed-issues-analysis-2026-09-23.md delete mode 100644 docs/p2-progress-2026-09-24.md delete mode 100644 docs/plugin-extensions.md delete mode 100644 docs/source-login.zh-CN.md delete mode 100644 docs/source-plugins.md delete mode 100644 docs/ui-review/source-search.md delete mode 100644 docs/ui-review/sources-ux.md diff --git a/README.en.md b/README.en.md index 5b029e5..f0c8d4f 100644 --- a/README.en.md +++ b/README.en.md @@ -1,60 +1,66 @@ # reader -**One reading space for your local books, OPDS catalogs, and remote book sources.** +**One home for your books, movies, series, music, and audiobooks.** -A self-hosted library and reader for browsers and Android, with EPUB typography, comic reading, per-user sync, and extensible sources. +A self-hosted reading and media library for browsers and Android, with EPUB typography, comic reading, media playback, and per-user progress sync. [简体中文](README.md) · **English** -[Get started](docs/getting-started.en.md) · [User guide (中文)](docs/user-guide.zh-CN.md) · [Configuration](docs/configuration.en.md) · [Documentation](docs/README.md) +[Get started](docs/getting-started.en.md) · [Reading guide (中文)](docs/user-guide.zh-CN.md) · [Media guide (中文)](docs/media-user-guide.zh-CN.md) · [Configuration](docs/configuration.en.md) · [Documentation](docs/README.md) ## Why reader -- **Your own library**: mount an existing book directory without reorganizing it first. Covers, indexes, and server state live in a separate data directory. -- **Built for reading**: preserve publisher styles in EPUBs and detect encodings and chapters in TXT files. Choose paged or scrolling reading, themes, fonts, and text-to-speech. -- **Multiple sources**: local libraries and OPDS are built in; independent plugins add remote book sources. -- **Continue across devices**: each account has its own shelf, progress, notes, and highlights. Browsers and Android connect to the same server. -- **Simple hosting**: one Docker container serves both the backend and Web UI. Mount your books read-only or writable according to your needs. +- **Your own libraries**: mount existing directories, connect OPDS book catalogs, or add OpenList media directories. Books and media are organized separately; indexes, covers, and user state live in the data directory. +- **Built for reading**: preserve EPUB publisher styles, detect TXT encodings and chapters, and enjoy comics, paged or scrolling reading, themes, fonts, and text-to-speech. +- **Media browsing**: browse movies and series, artists and albums, or audiobooks and narrators. Filter by library, search, save favorites, and manage playback history and queues. +- **Metadata and organization**: read local tags, NFO, artwork, lyrics, and subtitles. Configure TMDB and MusicBrainz for online matching, review candidates, or edit metadata and editions manually. +- **Continue across devices**: accounts have independent shelves, notes, reading and playback progress. Web video uses Plyr; audio includes lyrics, speed controls, and a sleep timer. Android supports native background playback. +- **Simple hosting**: one Docker container serves the backend and Web UI. Media scanning only reads source files, with separate databases and service threads for reading and media. -## Books and sources +## Supported content | Type | Support | | --- | --- | -| EPUB | Publisher styles, embedded fonts, table of contents, footnotes, and inline images | -| TXT | Encoding detection, inferred chapters, adjustable font size and line spacing | +| EPUB / TXT | Publisher typography, contents, footnotes; TXT encoding detection and inferred chapters | | CBZ / ZIP / image directories | Natural page ordering, comic paging, and volumes | -| PDF | Basic viewing through the browser or device viewer, without reflow | -| OPDS | Browsing, search, pagination, and book acquisition | -| Remote source plugins | Multi-source search, chapter reading, rich text and images, catalog refresh, and automatic update tracking | - +| PDF | Basic browser or device viewing without reflow | +| OPDS | Browse, search, and acquire books; publish a read-only catalog to external readers | +| Movies / series | Artwork, metadata, seasons, episodes, editions, subtitles, and progress | +| Music | Artists, albums, tracks, lyrics, queues, and continuous playback | +| Audiobooks | Narrators, descriptions, chapters, playback speed, and sleep timers | +| OpenList | Scan remote media and sidecar metadata, then play through Reader's authorized streaming API | ## Get started -Prepare Docker, Docker Compose, and a directory of books. After starting the service, open `http://:5888`. The first registered account becomes the administrator. +Prepare Docker, Docker Compose, a book directory, and a separate data directory. Open `http://:5888` after starting the service. The first registered account becomes the administrator. Follow the [getting started guide](docs/getting-started.en.md). -**[Open the getting started guide →](docs/getting-started.en.md)** +Reader opens on the bookshelf by default. Use the media entry to browse your media; on mobile, tap the channel title to switch between video, music, audiobooks, and reading. Media settings include multiple themes; reading controls and bookshelf settings remain separate. -The guide covers Compose setup, first login, adding books, read-only and writable mounts, and upgrades. The database, caches, and upload staging live in `DATA_DIR`, which must be outside `BOOKS_DIR` and must not be the same directory. +In media settings, administrators can add a server directory or OpenList library. Mount local media into Docker first and enter its container path. Library creation starts a scan. See the [media guide (中文)](docs/media-user-guide.zh-CN.md) and [OpenList setup (中文)](docs/media-openlist.md). ## Documentation | I want to… | Start here | | --- | --- | -| Install reader and open my first book | [Getting started](docs/getting-started.en.md) | -| Use shelves, the reader, sources, and text-to-speech | [User guide (中文)](docs/user-guide.zh-CN.md) | -| Configure environment variables, HTTPS, TTS, or troubleshoot deployment | [Configuration](docs/configuration.en.md) | -| Run from source, test changes, or build Android | [Development](docs/development.en.md) | -| Build a source plugin or use the API | [Documentation index](docs/README.md) | +| Deploy reader and add books or media | [Getting started](docs/getting-started.en.md) | +| Use shelves, reading, OPDS, and text-to-speech | [Reading guide (中文)](docs/user-guide.zh-CN.md) | +| Manage media, match metadata, and play content | [Media guide (中文)](docs/media-user-guide.zh-CN.md) | +| Connect OpenList / NAS / cloud storage mounts | [OpenList setup (中文)](docs/media-openlist.md) | +| Configure HTTPS, metadata tools, or TTS | [Configuration](docs/configuration.en.md) | +| Back up accounts, reading, and media state | [Backup and restore (中文)](docs/backup.zh-CN.md) | +| Develop, test, or build Android | [Development](docs/development.en.md), [media validation (中文)](docs/media-validation.md) | ## Current limits -- PDF support is basic viewing; `.rar/.cbr` and general format conversion are not supported. -- Offline access depends on cached content. Whole-book prefetch and cache quotas for remote chapters are not implemented. -- Clients are available for Web and Android. There are no standalone iOS or desktop clients; desktop users can use a browser. +- No audio/video transcoding. Playback depends on the browser or device's container and codec support. +- OpenList supports sidecar NFO, artwork, lyrics, and subtitles; remote embedded tags, artwork, and chapters are not read. Some drivers require OpenList Web proxy and correct Range support. +- No TVBox/JAR, media offline downloads, or direct cloud account login. OpenList manages cloud storage mounts. +- PDF viewing is basic; `.rar/.cbr` and general book conversion are unsupported. Offline reading depends on content cached on the current device. +- Web and Android clients are available. There are no standalone iOS or desktop clients; use a browser on desktop. ## Contributing -Bug reports, documentation improvements, and code contributions are welcome. Include reproduction steps, your environment, and redacted logs. See the [development guide](docs/development.en.md) for the workflow and checks. +Bug reports, documentation improvements, and code contributions are welcome. Include reproduction steps, your environment, and redacted logs. See the [development guide](docs/development.en.md). ## License diff --git a/README.md b/README.md index edf2ed1..c20f86c 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,66 @@ # reader -**把本地书、OPDS 书库和远程书源,放进自己的阅读空间。** +**把书籍、电影、剧集、音乐和有声书,放进自己的阅读与影音空间。** -支持浏览器与 Android 的自部署书库阅读器,提供 EPUB 排版、漫画阅读、多用户同步和可扩展书源。 +支持浏览器与 Android 的自部署书库和媒体库,提供 EPUB 排版、漫画阅读、影音播放和多用户进度同步。 **简体中文** · [English](README.en.md) -[开始使用](docs/getting-started.zh-CN.md) · [使用手册](docs/user-guide.zh-CN.md) · [部署配置](docs/configuration.zh-CN.md) · [文档中心](docs/README.md) +[开始使用](docs/getting-started.zh-CN.md) · [阅读手册](docs/user-guide.zh-CN.md) · [影音手册](docs/media-user-guide.zh-CN.md) · [部署配置](docs/configuration.zh-CN.md) · [文档中心](docs/README.md) ## 为什么使用 reader -- **自己的书库**:挂载现有书籍目录,无需先把文件搬进另一套目录结构。封面、索引和服务端状态单独保存在数据目录。 -- **专注阅读**:EPUB 保留出版方样式,TXT 支持编码识别与章节切分;支持分页、滚动、主题、字体设置和朗读。 -- **多种来源**:内置本地书库和 OPDS,通过独立插件接入远程书源。 -- **跨设备继续**:每个账号拥有独立书架、阅读进度、笔记和高亮;浏览器与 Android 连接同一服务。 -- **随读随记**:选中文字即可复制、高亮、批注或添加书签,点击高亮查看批注;在线书内搜索由服务端执行,离线仅搜索已缓存内容。 -- **适合自部署**:一个 Docker 容器包含服务端和 Web 界面,书库可按需要选择只读或可写挂载。 +- **自己的书库与媒体库**:挂载现有目录,或连接 OPDS 书库、OpenList 媒体目录。书籍与影音分别管理,索引、封面和用户状态保存在数据目录。 +- **专注阅读**:EPUB 保留出版方样式,TXT 支持编码识别与章节切分;支持漫画、分页、滚动、主题、字体和朗读。 +- **完整的影音浏览**:电影与剧集、歌手与专辑、有声书与演播者分别组织,支持媒体库筛选、搜索、收藏、历史记录和播放队列。 +- **资料与刮削**:读取本地标签、NFO、封面、歌词和字幕;可配置 TMDB 与 MusicBrainz 补全资料,确认匹配后保存,也可手工整理作品与版本。 +- **跨设备继续**:账号独立保存书架、阅读进度、笔记及播放进度。Web 视频采用 Plyr;音频支持歌词、倍速和睡眠定时,Android 支持原生后台播放。 +- **适合自部署**:一个 Docker 容器提供服务端与 Web 界面;影音源文件只读扫描,阅读与影音使用独立数据库及服务线程。 -## 书籍与来源 +## 支持内容 | 类型 | 支持情况 | | --- | --- | -| EPUB | 出版方样式、嵌入字体、目录、脚注、图文混排 | -| TXT | 编码识别、章节推断、字号与行距调整 | +| EPUB / TXT | 出版方排版、目录、脚注;TXT 编码识别和章节推断 | | CBZ / ZIP / 图片目录 | 自然页序、漫画分页和卷目录 | -| PDF | 基础查看,能力取决于浏览器或设备查看器,不重排 | -| OPDS | 浏览、搜索、分页和获取书籍 | -| 远程书源插件 | 多源搜索、章节阅读、富文本与图片、刷新目录和自动追更 | - +| PDF | 浏览器或设备基础查看,不重排 | +| OPDS | 浏览、搜索和获取书籍;也可向外部阅读器提供只读目录 | +| 电影 / 剧集 | 海报与资料、季和单集、版本选择、字幕与播放进度 | +| 音乐 | 歌手、专辑、曲目、歌词、队列与连续播放 | +| 有声书 | 演播者、内容简介、章节、倍速与睡眠定时 | +| OpenList | 接入远端媒体目录,扫描外置资料,通过 Reader 授权接口播放 | ## 开始使用 -准备 Docker、Docker Compose 和一个书籍目录,即可部署。服务启动后访问 `http://<你的主机>:5888`,首个注册账号成为管理员。 +准备 Docker、Docker Compose、书籍目录和独立数据目录。启动后访问 `http://<你的主机>:5888`,首个注册账号成为管理员。部署步骤见[入门指南](docs/getting-started.zh-CN.md)。 -**[打开入门指南 →](docs/getting-started.zh-CN.md)** +默认进入书架,从「影音」入口打开媒体模块。手机点击顶部频道名称切换影视、音乐、有声书,选择「阅读」返回书架;影音设置内置多种主题,阅读界面与书架设置保持独立。 -指南包含 Compose 配置、首次登录、添加书籍、只读/可写挂载和更新流程。数据库、缓存和上传暂存均写入 `DATA_DIR`;该目录不能与 `BOOKS_DIR` 相同或位于其内部。 +管理员在「影音设置 → 媒体库管理」添加服务器目录或 OpenList。Docker 本地媒体目录需先挂载,再填写容器内路径;创建后自动扫描。详细步骤见[影音手册](docs/media-user-guide.zh-CN.md)和 [OpenList 接入](docs/media-openlist.md)。 ## 文档 | 我想要…… | 从这里开始 | | --- | --- | -| 安装并读到第一本书 | [入门指南](docs/getting-started.zh-CN.md) | -| 使用书架、阅读器、书源和朗读 | [使用手册](docs/user-guide.zh-CN.md) | -| 设置环境变量、HTTPS、TTS 或排查部署问题 | [部署配置](docs/configuration.zh-CN.md) | -| 从源码运行、测试或构建 Android | [开发指南](docs/development.zh-CN.md) | -| 开发来源插件或调用 API | [文档中心](docs/README.md) | +| 部署服务、添加书籍与媒体 | [入门指南](docs/getting-started.zh-CN.md) | +| 使用书架、阅读器、OPDS 和朗读 | [阅读手册](docs/user-guide.zh-CN.md) | +| 建媒体库、刮削、看视频或听音乐与有声书 | [影音手册](docs/media-user-guide.zh-CN.md) | +| 对接 OpenList / NAS / 网盘挂载 | [OpenList 接入](docs/media-openlist.md) | +| 配置环境变量、HTTPS、媒体探测或 TTS | [部署配置](docs/configuration.zh-CN.md) | +| 备份账号、阅读与影音数据 | [备份恢复](docs/backup.zh-CN.md) | +| 开发、测试或构建 Android | [开发指南](docs/development.zh-CN.md)、[影音验证](docs/media-validation.md) | ## 当前边界 -- PDF 提供基础查看;不支持 `.rar/.cbr` 或通用格式转换。 -- 离线能力取决于已缓存内容;远程章节整书预下载与缓存配额尚未实现。 -- 当前客户端为 Web 和 Android,没有独立 iOS 或桌面客户端;电脑端可使用浏览器。 +- 视频与音频不提供转码,实际播放能力取决于浏览器或设备支持的容器和编码。 +- OpenList 支持外置 NFO、封面、歌词和字幕,暂不读取远端内嵌标签、封面和章节;部分驱动需开启 OpenList Web 代理并正确支持 Range。 +- 影音暂不支持 TVBox/JAR、离线下载或直接登录网盘;网盘挂载由 OpenList 管理。 +- PDF 为基础查看;不支持 `.rar/.cbr` 或通用书籍格式转换。阅读离线能力取决于当前设备已缓存内容。 +- 提供 Web 和 Android 客户端,没有独立 iOS 或桌面客户端;电脑端使用浏览器。 ## 参与贡献 -欢迎提交问题、改进文档或贡献代码。请附上复现步骤、运行环境和脱敏日志;开发与验证流程见[开发指南](docs/development.zh-CN.md)。 +欢迎提交问题、改进文档或贡献代码。请附上复现步骤、运行环境和脱敏日志,开发流程见[开发指南](docs/development.zh-CN.md)。 ## 许可证 diff --git a/docs/README.md b/docs/README.md index 25da5d5..407d2dd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,7 @@ [项目首页](../README.md) · [English overview](../README.en.md) -项目首页介绍用途与能力;安装、日常使用、运维和开发步骤分别放在下面的指南中。 +项目首页介绍阅读与影音能力;安装、日常使用、运维和开发步骤分别放在下面的指南中。 The project README introduces reader. Use the guides below for installation, everyday use, operations, and development. ## 使用与部署 · Using and deploying reader @@ -11,6 +11,8 @@ The project README introduces reader. Use the guides below for installation, eve | --- | --- | --- | | 安装、首次登录、添加书籍、更新 / Installation and first steps | [入门指南](getting-started.zh-CN.md) | [Getting started](getting-started.en.md) | | 书架、阅读、朗读、来源和离线 / Shelves, reading, TTS, sources, offline | [使用手册](user-guide.zh-CN.md) | Chinese only | +| 电影、剧集、音乐与有声书 / Movies, series, music and audiobooks | [影音手册](media-user-guide.zh-CN.md) | Chinese only | +| 远端媒体目录 / Remote media directories | [OpenList 接入](media-openlist.md) | Chinese only | | 安装到桌面、离线启动和版本更新 / PWA installation, offline startup and updates | [PWA 指南](pwa.zh-CN.md) | Chinese only | | 环境变量、目录权限、HTTPS、排错 / Settings, permissions, HTTPS, troubleshooting | [部署配置](configuration.zh-CN.md) | [Configuration](configuration.en.md) | | 数据备份、校验与恢复 / Data backup, verification and restore | [备份恢复](backup.zh-CN.md) | Chinese only | @@ -23,9 +25,7 @@ The project README introduces reader. Use the guides below for installation, eve | 文档 / Document | 内容 / Contents | | --- | --- | | [架构与数据边界 / Architecture](architecture.md) | 数据目录、身份、同步和客户端架构 / Data boundaries, identity, sync, client architecture | -| [API](api.md) | 鉴权、书籍、资源、进度、文件管理、来源 / Auth, books, resources, progress, file management, sources | -| [来源插件系统 / Source plugins](source-plugins.md) | 契约、宿主职责及实施状态 / Contracts, host responsibilities, implementation status | -| [通用插件扩展 / Plugin extensions](plugin-extensions.md) | 配置页面、任务、搜索、换源 / Configuration pages, tasks, search, source switching | +| [API](api.md) | 鉴权、书籍、资源、进度、文件管理、OPDS 与影音 / Auth, books, resources, progress, file management, OPDS and media | | [界面规范 / UI guidelines](ui.md) | 布局、交互、可访问性 / Layout, interaction, accessibility | ## 验证记录 · Review records @@ -34,14 +34,11 @@ The project README introduces reader. Use the guides below for installation, eve These records describe checks at specific delivery points. Use tests and CI for the current commit's results. - [UI 评审工具 / UI review tooling](ui-review/README.md) -- [书源界面 / Source UI](ui-review/sources-ux.md) - [书库与阅读界面 / Library and reader UI](ui-review/collections-ux.md) -- [书源搜索 / Source search](ui-review/source-search.md) - [P1 阅读工具实施与验证](p1-progress-2026-09-23.md) -- [P2 交付与验证记录](p2-progress-2026-09-24.md) -- [生态互通与客户端覆盖方案](ecosystem-roadmap.zh-CN.md) +- [互通与客户端覆盖](ecosystem-roadmap.zh-CN.md) - [OPDS 服务端接入与 WebDAV 备份上传](opds-webdav.zh-CN.md) diff --git a/docs/api.md b/docs/api.md index 4e0eadb..a347e13 100644 --- a/docs/api.md +++ b/docs/api.md @@ -44,7 +44,7 @@ ### `GET /books/:id/search?q=关键词&cursor=上一页游标` -仅允许搜索当前用户书架中的书籍,支持 TXT、EPUB 和远程章节。关键词去除首尾空白后搜索,原始长度限 1–200 个字符。响应不缓存。 +仅允许搜索当前用户书架中的书籍,支持 TXT 和 EPUB。关键词去除首尾空白后搜索,原始长度限 1–200 个字符。响应不缓存。 ```json { @@ -59,7 +59,7 @@ 服务端按需扫描正文,每页本地最多 8 章、远程最多 1 章,每页最多返回 200 条匹配;`limited` 表示达到匹配上限。客户端连续请求 `nextCursor`,最多展示 200 条。游标绑定书籍目录、版本、关键词和个人整理版本,条件变化需重新搜索。此接口不是预建全文索引。 -单章限制 8 MiB,远程章节有 12 秒超时;失败章节在 `failures` 中返回 `{title, code}`,保留其他章节结果。客户端停止请求会取消后续扫描。返回定位包含当前用户的个人纠错。 +单章限制 8 MiB;失败章节在 `failures` 中返回 `{title, code}`,保留其他章节结果。客户端停止请求会取消后续扫描。返回定位包含当前用户的个人纠错。 使用自定义 TXT 标题规则时返回 `400 SEARCH_LOCAL_LAYOUT`,客户端使用本地目录和缓存搜索并明确提示。断网时同样仅搜索已缓存内容,缓存不完整时提示结果可能不完整,不下载整书到浏览器搜索。 @@ -138,7 +138,7 @@ "total": 1, "page": 1, "pageSize": 50 } ``` -只看得到可用文件书、当前用户已获取的下载书和章节出版物。本地文件被删的书不会留在书架上;插件禁用不会隐藏已经获取的章节书。 +只返回当前账号可访问的书籍;本地文件被删的书不会留在书架上。 `path` 是对 `book_files.rel_path` 的**前缀匹配**,带上分隔符:`path=科幻` 匹配 `科幻/…`,不会匹配到旁边的 `科幻小说`。`%` 和 `_` 在文件名里合法、在 `LIKE` 里是通配符, @@ -215,7 +215,6 @@ `?group=N` 会把 `items` 收窄到第 N 组,`groups` 仍然完整——这样打开一本 40 卷的漫画 只传一卷的条目。目录客户端用 `/toc`,不要自己拼 `groups` 的标题。 -`format=chapters` 是远程章节出版物,没有整书文件,`files` 为 `[]`。它的 manifest 始终返回完整目录快照,即使传入 `group` 也不分窗,`content.revision` 标识快照版本。`items[].href` 是稳定定位引用,`items[].resourceRef` 是带 revision 的正文引用;用前者保存进度,用后者请求 `/assets`。阅读器应从这同一份快照构建目录,避免并发刷新时把两份目录混合。 ### `GET /books/:id/items?group=N` @@ -286,22 +285,6 @@ pdf / 单图没有独立目录,回落到 items。 响应带 `Cache-Control: private, max-age=31536000, immutable`:文件资源由内容身份寻址;章节资源引用同时包含目录 revision,所以同一个资源 URL 的内容保持不变。 -章节资源按 manifest 的 `mediaType` 返回 `text/plain; charset=utf-8` 或清洗后的 `text/html; charset=utf-8`,带 `nosniff` 和 `default-src 'none'; img-src data:; sandbox` CSP。纯文本必须转义排版;HTML 只保留白名单标签,图片经插件通道获取、校验 PNG/JPEG/GIF/WebP 签名并转为 data URL。脚本、样式、表单、外部链接、SVG 和任意网络图片被移除。正文读取后持久缓存,来源禁用或插件卸载不影响缓存命中;旧 revision 已缓存正文可读,未缓存正文返回 `409 CHAPTER_SNAPSHOT_EXPIRED`。 - -### `POST /books/:id/refresh` - -为当前用户已获取的章节书拉取并原子提交新目录,响应是完整内容 manifest(不含外层 `book`): - -```json -{ "kind": "text", "revision": "", "total": 1, - "groups": [{ "id": "chapters", "seq": 0, "title": "章节", "count": 1, "offset": 0 }], - "items": [{ "id": "", "seq": 0, "title": "第一章", "kind": "chapter", - "href": "chapter:", - "resourceRef": "chapter-resource::", - "mediaType": "text/plain; charset=utf-8", "format": "html" }] } -``` - -`format: "html"` 表示客户端将纯文本排版为 HTML,不表示资源含 HTML;富文本条目省略 `format`、声明 `mediaType: text/html`,目录 `kind` 为 `reflowable`。该接口无需请求体;文件书返回 `400 SOURCE_UNSUPPORTED`,其他用户章节书返回 404。刷新失败保留旧目录;同一目录保持 revision 不变;正文变化时插件须更新 `ManifestSnapshot.version`。进度和笔记不重写,插章后以稳定 href 定位。手动刷新会更新检查时间和新增章计数,但不会自动开启订阅或预下载正文。 ### 文件资源的流式与子资源行为 @@ -825,184 +808,71 @@ manifest 的每个条目还带 `ref`,即这个文件对应的**资源引用** --- -## 来源与插件 +## 本地与 OPDS 来源 -来源接口把本地书、OPDS 和外部章节插件统一成同一组发现与获取操作。来源实例由管理员创建;来源配置在实例级共享,登录凭据通过用户级凭据接口保存。插件运行在独立的受信任 Node 进程中,安装前必须确认它拥有服务端操作系统权限。 +以下接口需账号令牌。内置类型为 reader.local 和 reader.opds;管理员配置来源,用户浏览、搜索和获取书籍。 -### `GET /sources/types` +| 接口 | 用途 | +| --- | --- | +| GET /sources/types | 查询内置来源类型及能力 | +| GET /sources | 查询来源实例;普通用户不返回管理配置 | +| POST /sources | 管理员创建来源 | +| PATCH /sources/:id | 管理员修改名称、配置、启停或默认搜索来源 | +| GET /sources/:id/browse | 浏览目录 | +| POST /sources/:id/search | 搜索书籍 | +| GET /sources/:id/entries?ref=条目引用 | 查询条目详情 | +| POST /sources/:id/acquire | 获取条目并加入当前账号书架 | -返回当前已注册的内置和外部来源类型: +创建 OPDS 示例: ```json -{ - "types": [ - { "id": "local", "pluginId": "reader.local", "builtin": true, "label": "本地书库", "version": "1.0.0", "capabilities": ["browse", "search", "detail"] }, - { "id": "opds", "pluginId": "reader.opds", "builtin": true, "label": "OPDS", "version": "1.0.0", "capabilities": ["browse", "search", "detail", "acquire.file"] } - ] -} -``` - -### `GET /sources` - -登录用户可以看到来源实例,响应为 `{ "sources": [...] }`;每项有 `id/pluginId/sourceType/name/enabled/isDefault/descriptor`,只有管理员返回 `config`。服务端启动时自动创建 `local` 实例。 - -管理员可发送 `PATCH /api/v1/sources/:id`,请求体为 `{ "isDefault": true }`,将已启用且支持搜索的来源设为全站默认书源。服务端最多保留一个默认来源,并持久保存;`false` 取消默认,暂停或删除来源也会清除其默认状态。进入搜书页时自动选中可用的默认来源,用户仍可手动选择其它来源;插件不可用时跳过默认选择。 - -### `POST /sources` — 管理员 - -创建来源: - -```http -POST /api/v1/sources -Authorization: Bearer -Content-Type: application/json - {"pluginId":"reader.opds","sourceType":"opds","name":"家庭 OPDS","config":{"url":"https://books.example.test/opds","username":"reader"}} ``` -返回 `201 { "source": {...} }`。可指定 `id`(2~80 位字母、数字、下划线或短横线),省略则自动生成。`sourceType` 和 `pluginId` 从 `/sources/types` 读取。`local` 仅接受空配置,使用宿主 `BOOKS_DIR`。 +pluginId 是接口兼容字段。创建返回 201 与 source 对象。本地来源使用 BOOKS_DIR;OPDS 文件下载到 DATA_DIR/acquired。来源浏览、搜索和详情的游标及条目引用以响应为准,不应从外部 URL 自行拼接。 -`config` 不能包含密码。OPDS 的 `url` 必须是 HTTP(S) 地址;Feed 和下载链接默认限制在该 origin。跨 origin 获取文件须配置 `allowedOrigins`;Basic 凭据不转发到附加 origin。管理员可 `PATCH /sources/:id` 更新 `name/config/enabled/isDefault`,配置仍由提供者校验,修改 config 会清除该来源所有用户的凭据,防止向新地址发送旧凭据;来源有在途调用时修改 config 返回 `409 SOURCE_BUSY`。`DELETE /sources/:id` 只允许删除没有已获取内容的非内置来源,否则返回 `409 SOURCE_IN_USE`。Web 的 `#/sources` 提供对应表单。 +搜索请求 body 包含 query 和 sessionId,响应以 text/event-stream 返回 results、done 或 error;获取请求 body 使用 entryRef。 -### 来源浏览、搜索和详情 +当前账号可使用 PUT /sources/:id/credentials/password,body 为 {"value":"密码"},保存自己的 OPDS 密码;凭据不会通过普通来源列表回显。暂停来源不删除已获取的文件书。 -```text -GET /api/v1/sources/:id/browse?ref=&cursor=&limit=<1..200> -POST /api/v1/sources/:id/search -GET /api/v1/sources/:id/entries?ref= +Reader 对外提供的只读 OPDS 服务与 WebDAV 备份上传见[接入指南](opds-webdav.zh-CN.md)。 + +## 影音 + +接口前缀为 /api/v1/media,沿用账号令牌。用户只能访问已授权媒体库;建库、权限、扫描、刮削和人工资料编辑需要管理员权限。准备中返回 MEDIA_STARTING,启动失败返回 MEDIA_UNAVAILABLE。阅读健康检查不能替代影音就绪检查。 + +| 接口(省略 /api/v1/media) | 用途 | +| --- | --- | +| GET /libraries | 当前账号可访问的媒体库 | +| POST /libraries | 创建本地或 OpenList 媒体库 | +| GET /libraries/:id/configuration | 管理员查看连接配置摘要,不回传凭据原值 | +| PATCH /libraries/:id | 修改名称或 OpenList 凭据 | +| PUT /libraries/:id/access | 设置访问范围与用户列表 | +| POST /libraries/:id/scan | 提交扫描任务 | +| GET /libraries/:id/jobs、GET /jobs/:id | 查看任务状态 | +| GET /browse、GET /libraries/:id/items | 按频道、分类或库浏览 | +| GET /items/:id | 作品、版本与章节详情 | +| GET /search、GET /favorites、GET /history、GET /queue | 搜索及当前账号收藏、历史与队列 | +| PUT /items/:id/favorite | 设置收藏,body 为 {"favorite":true} 或 {"favorite":false} | +| PATCH /items/:id/metadata | 管理员保存人工资料 | +| GET /metadata/providers | 可用在线资料提供者 | +| POST /items/:id/matches、PUT /items/:id/match | 搜索候选、确认资料匹配 | +| POST /playback | 根据 partId 创建播放会话 | +| POST /playback/:id/renew | 续期播放会话 | +| GET /parts/:id/progress、PUT /playback/:id/progress | 读取与保存播放进度 | +| GET /streams/:id | 授权资源流,支持有效的字节 Range | + +本地建库请求示例: + +```json +{"name":"家庭电影","kind":"video","storage":"local","root":"/media/video","access":"restricted"} ``` -浏览仍返回普通 JSON 目录响应。搜索使用 Streamable HTTP:请求体为 `{ "query": "...", "sessionId": "...", "cursor": "...", "filters": {}, "resultLimit": 10000 }`,响应为 `text/event-stream`,持续发送 `results`、最终 `done` 或 `error` 事件。`results.data` 是 CatalogPage,客户端边收边合并;断开连接会取消在途搜索。`ref` 和 `cursor` 是来源拥有的不透明值,客户端只保存并原样回传。条目返回 `ref`、标题、作者、封面和 `options`;不要从 `ref` 推断 URL 或拼接下一页地址。引用和查询参数必须为非空字符串且不超过 16,384 字符;路径中的 `publicationRef` 需要 URL 编码,路由允许最大 16,384 字符的参数。 +kind 为 video、music 或 audiobook;OpenList 建库和凭据更新见[OpenList API](media-openlist.md#api)。媒体路径属于服务端或容器,不是浏览器所在设备的路径。 -搜索请求必须携带 Bearer 凭据。`sessionId` 必填,由 16–80 个字母、数字、`_` 或 `-` 组成;继续同一次搜索时保留该值并回传最后收到的 `nextCursor`,新关键词或筛选条件使用新的值。可选 `limit` 为每页 1–200 条,`resultLimit` 为 1–10000 条,默认上限 10000 条。旧 GET 搜索接口已移除。 +播放会话使用具体 partId,不以作品名称或文件路径代替。流地址、有效期及进度并发字段以服务端响应为准;客户端不持久保存临时下载链接。权限撤销和资源失效需重新处理,不能绕过鉴权重用旧链接。后台专用授权见[后台播放](media-background-auth.md)。 -```text -event: results -data: {"items":[{"ref":"book-1","title":"示例书籍"}],"nextCursor":"opaque-cursor","batch":{"completed":1,"total":2}} - -event: results -data: {"items":[],"batch":{"completed":2,"total":2}} - -event: done -data: {"reason":"complete"} - -``` - -服务端在同一响应中自动消费后续分页。`done.reason` 为 `complete` 或 `limit`;错误事件形如 `{"code":"SEARCH_FAILED","message":"搜索中断,已保留收到的结果。","status":500}`。响应开始前的鉴权或参数错误使用普通 HTTP 错误响应,响应开始后的错误通过 `error` 事件返回。没有收到 `done` 或 `error` 就结束连接属于异常中断,客户端保留已收到的结果,不自动重放搜索。Web 停止搜索只中止结果流,不再额外发送 HTTP 取消请求;服务端在断开后取消在途 RPC 并调用插件会话停止接口。继续同一会话前,服务端等待旧连接清理完成,防止旧清理停止新搜索。`POST /api/v1/sources/:id/search/cancel`(body 为 `{"sessionId":"..."}`)仍供其它调用方显式停止会话。 - -搜索期间可查看已返回书籍的详情或加入书架。停止或中断后,搜索框旁的主按钮为“继续搜索”,沿用会话与最后收到的游标并保留结果;下拉菜单中的“重新搜索”使用新会话并清空结果。修改关键词或筛选条件后使用新搜索,会话过期时也需重新搜索。能否从中断处继续由来源的游标/会话能力决定。 - -### 凭据与来源启停 - -```http -PUT /api/v1/sources/:id/credentials/password -Authorization: Bearer -Content-Type: application/json - -{"value":"用户自己的 OPDS 密码"} -``` - -返回 `{ "ok": true }`。`value` 必须为字符串,允许空密码,最大 16,384 字符。密码按 `(sourceId, userId, key)` 隔离并以 AES-256-GCM 加密保存,普通来源列表不会回显。管理员可用 `PATCH /api/v1/sources/:id` 携带 `{ "enabled": false }` 暂停来源;已获取到 `DATA_DIR/acquired` 的书不会被删除。 - -### 获取内容、目录和章节资源 - -```http -POST /api/v1/sources/:id/acquire -Authorization: Bearer -Content-Type: application/json - -{"entryRef":"","optionId":""} -``` - -内置 `local` 直接返回已有书的 `publicationId`。OPDS 文件会同步下载,成功响应为 `{ "kind":"ready", "publicationId":"" }`;单文件上限 256 MiB,下载完成后计算真实 SHA-256,写入 `DATA_DIR/acquired`,复用现有格式解析和阅读端点,并将书加入当前用户书架。取消、超限或解析失败不会留下临时文件。 - -章节插件在 RPC 中返回 `{ "kind":"chapters", "publicationRef":"..." }`。宿主随后获取并持久化目录,建立当前用户专属的 `format=chapters` 出版物并加入书架;HTTP 同样返回 `{ "kind":"ready", "publicationId":"" }`。反复获取沿用 book ID,已隐藏的书重新上架;不同用户获取同一条目会得到不同出版物和正文缓存。此后通过 `/books/:id/manifest|items|toc|assets` 阅读,使用 `/books/:id/refresh` 手动更新目录。章节书没有整书文件,调用 `/books/:id/content` 返回 `400 CHAPTER_BOOK`。 - -来源级开发预览仍保留: - -```text -GET /api/v1/sources/:id/publications/:publicationRef/manifest -GET /api/v1/sources/:id/publications/:publicationRef/resource?ref= -``` - -上述来源级资源接口只返回 JSON:文本用 `text`,二进制资源用 `base64`。入库阅读接受 UTF-8 `text/plain`、`text/html`、`application/xhtml+xml`;目录最多 10,000 项及 2 MiB,原始正文最多 2 MiB。HTML 插图仅接受 `src="reader-res:<插件资源引用>"`,由同一来源的 `readResource` 返回图片;每章最多 32 个不同图片,单图 2 MiB,清洗与内嵌后的章节总计不超过 8 MiB,整章加载限时 60 秒。所有插件响应仍受单条 RPC 2 MiB 上限约束(含 base64)。 - -服务端和设备分别缓存已读正文(含已内嵌图片)。Web 按服务器、账号及 resourceRef 隔离;断网或 5xx 时目录可回退本账号缓存,授权失败或资源不存在时不回退。没有整书预下载和缓存总配额。后台目录检查由下面的订阅接口控制。 - -### 自动追更订阅 - -`GET /subscriptions` 返回 `{ "subscriptions": [...] }`,只列当前用户书架中的章节书:`bookId/title/enabled/intervalMinutes/nextCheckAt/lastCheckAt/lastSuccessAt/lastError/failures/newChapters`,时间为毫秒,未检查时间为 null。默认关闭、间隔 60 分钟。 - -`PATCH /books/:id/subscription` 接受 `{ "enabled": true, "intervalMinutes": 60 }` 或 `{ "acknowledge": true }`。间隔为 15~10080 分钟的整数;`acknowledge` 只清除新增章提示。管理员不能操作他人的章节书。 - -单实例服务每分钟扫描一次,每轮最多顺序处理 20 本;开始时写入 5 分钟执行租约,崩溃重启后到期重试。暂停来源、禁用账号或隐藏书籍时跳过。失败按订阅间隔和指数退避的较大值重试,保留旧目录及上次成功时间;不预下载正文,不发外部通知。状态中的错误是代码,不包含上游消息。浏览器关闭不影响调度;阅读中不会自动替换当前目录,用户刷新或重开时采用新版本。 - -插件类型可声明 `credentialKeys: [{ "key": "access-token", "label": "访问令牌" }]`;同时声明 `permissions.credentials: true` 后,宿主仅将该类型声明的当前用户键值放进 RPC `context.credentials`。凭据不出现在来源列表或普通 config 中。`AUTH_REQUIRED` 表示来源凭据问题,客户端不应退出 reader 账号。 - -### 插件管理(管理员) - -管理员可以直接安装 npm 包或上传 `.tgz`,成功后自动启用。npm 包名支持作用域与可选版本/标签,拒绝 URL、本地路径、别名及安装参数。服务端使用 npm 安装,禁用生命周期脚本;每次安装有独立依赖目录,失败清理本次目录,不修改已有插件。重复插件 ID 返回 409,内置插件不能覆盖。 - -```http -POST /api/v1/plugins -Authorization: Bearer -Content-Type: application/json - -{"package":"reader-source-example@1.0.0","trusted":true} -``` - -上传接口:`POST /api/v1/plugins/upload`,使用 `multipart/form-data`,字段 `trusted=true` 和单个 `file`(`.tgz`,最大 100 MiB)。字段顺序不限。包应由 `npm pack` 生成,包含 `package.json`、`plugin.json` 和已构建的入口文件。上传包未包含的依赖仍会从 npm 仓库下载。来源类型、配置与扩展入口由插件清单声明。 - -原目录加载接口仍可使用 `{"folder":"demo-chapters","trusted":true}`,或 `{"folder":"npm:reader-source-example","trusted":true}` 加载预部署在 `DATA_DIR/plugins` 或其 `node_modules` 下的包。新安装的 `folder` 是服务端生成的存储标识,客户端不应自行构造。 - -启停和卸载: - -```text -GET /api/v1/plugins -PATCH /api/v1/plugins/:id body: {"enabled":true|false} -DELETE /api/v1/plugins/:id 保留来源实例、已获取书和数据 -``` - -安装返回 `201 { "plugin": {...} }`,列表返回 `{ "plugins": [...] }`,启停返回 `{ "plugin": {...} }`,卸载返回 `{ "ok": true }`。插件状态包含 `pluginId/builtin/enabled/sourceTypes/runtime`,外部插件还带 `folder/name/version`,加载失败时有 `error`。卸载会移除注册和安装记录,保留包文件、来源实例、凭据和书籍数据。 - -禁用或插件进程故障不会删除已下载文件、章节目录及已缓存正文。npm 安装和上传包遇到相同插件 ID、不同版本时,会先在独立目录安装、校验已有来源能力和配置,再切换并启用;配置、凭据、订阅、插件数据目录和书架记录均保留。成功响应的 `plugin` 附带 `updated:true` 和可用的 `previousVersion`,相同版本返回 `409 PLUGIN_ALREADY_INSTALLED`。新版缺少已有实例能力返回 `409 PLUGIN_UPDATE_INCOMPATIBLE`,旧插件仍有在途操作返回 `409 PLUGIN_BUSY`。校验或切换失败保留旧安装记录和提供者;不自动回滚插件自行修改的数据。预部署目录加载不自动覆盖,一键版本回滚尚未提供。 - -内置 `reader.local` 和 `reader.opds` 不可卸载、禁用或替换。已安装插件失败后可用 `PATCH ... {"enabled":true}` 重新加载。同一服务实例同时只处理一次安装,冲突返回 `409 PLUGIN_INSTALL_BUSY`;npm 下载限时 5 分钟,失败返回 `502 PLUGIN_INSTALL_FAILED`,缺失 npm 返回 `503 NPM_UNAVAILABLE`。 - -### 可运行示例:demo-chapters - -仓库中的 [`examples/plugins/demo-chapters`](../examples/plugins/demo-chapters) 是一个不联网的静态章节插件。按以下步骤验证完整调用链(服务端已启动且已有管理员令牌): - -```powershell -# 在仓库根目录执行;改为服务端实际使用的 DATA_DIR 和管理员令牌。 -$readerDataDir = 'D:\reader-data' -$readerApi = 'http://localhost:5888/api/v1' -$readerHeaders = @{ Authorization = 'Bearer ' } -New-Item -ItemType Directory -Force (Join-Path $readerDataDir 'plugins') -Copy-Item -Recurse examples/plugins/demo-chapters (Join-Path $readerDataDir 'plugins/demo-chapters') - -Invoke-RestMethod -Method Post -Uri "$readerApi/plugins" -Headers $readerHeaders ` - -ContentType 'application/json' -Body '{"folder":"demo-chapters","trusted":true}' -$createdSource = Invoke-RestMethod -Method Post -Uri "$readerApi/sources" -Headers $readerHeaders ` - -ContentType 'application/json' -Body '{"pluginId":"reader.source.demo","sourceType":"demo-chapters","name":"Demo chapters","config":{}}' -$readerSourceId = $createdSource.source.id - -Invoke-RestMethod -Uri "$readerApi/sources/$readerSourceId/browse" -Headers $readerHeaders -Invoke-RestMethod -Uri "$readerApi/sources/$readerSourceId/entries?ref=demo-book" -Headers $readerHeaders -$acquiredBook = Invoke-RestMethod -Method Post -Uri "$readerApi/sources/$readerSourceId/acquire" -Headers $readerHeaders ` - -ContentType 'application/json' -Body '{"entryRef":"demo-book"}' -$readerBookId = $acquiredBook.publicationId -$readerManifest = Invoke-RestMethod -Uri "$readerApi/books/$readerBookId/manifest" -Headers $readerHeaders -$readerResourceRef = [Uri]::EscapeDataString($readerManifest.items[0].resourceRef) -Invoke-RestMethod -Uri "$readerApi/books/$readerBookId/assets?ref=$readerResourceRef" -Headers $readerHeaders -Invoke-RestMethod -Method Post -Uri "$readerApi/books/$readerBookId/refresh" -Headers $readerHeaders -``` - -资源正文应包含“这是通过独立 Node 进程提供的示例章节”,书籍同时出现在当前用户书架。普通成员也可使用自己的令牌获取、阅读及手动刷新;只有安装插件、创建和启停来源需要管理员。 - -宿主来源调用预算为 60 秒,同一来源实例最多 2 个并发调用,宿主总计最多 8 个,超限立即返回 `429 RATE_LIMITED`。插件每次 RPC 预算 30 秒、单条 JSON 消息上限 2 MiB(包含 base64 开销)。超时或取消只结束对应请求,向插件发送 `$/cancelRequest` 并忽略迟到响应,不终止其它在途请求或阻止后续调用;`searchCancel` 控制请求超时只结束等待,允许插件继续清理会话。插件应协作中断对应任务,宿主不会自动重试操作。协议错误、超长响应、管道故障或进程退出仍会使整个插件失败,需管理员重新启用。外部进程暂不支持 `acquire.file`,大文件获取由内置 OPDS 提供。 - ---- +完整请求 schema 及响应以[当前路由](../server/src/http/routes/media.ts)为准,使用流程见[影音手册](media-user-guide.zh-CN.md),数据隔离见[影音架构](media-implementation.md)。 ## 管理员 @@ -1046,7 +916,7 @@ GET 返回 `{ "mode": "closed", "invites": [...] }`;PATCH 接受 `{ "mode": "c → `{ "providers": [ { "id": "none", "displayName": "...", "enabled": true } ] }` -第一版只有 `none`。此处是元数据补全 provider,与 `/sources` 内容来源独立;安装书源插件不会改变该列表。 +本地书籍元数据提供者目前只有 `none`;影音的在线资料提供者使用 `/media/metadata/providers`。 --- @@ -1105,17 +975,7 @@ GET 返回 `{ "mode": "closed", "invites": [...] }`;PATCH 接受 `{ "mode": "c | `MANIFEST_TOO_LARGE` | 413 | 章节目录超过 10,000 项或 2 MiB | | `INVALID_MANIFEST` | 400 | 章节目录版本字段不合法 | | `INVALID_RESOURCE` | 400 | 获取内容为空、媒体类型不匹配或解析失败 | -| `PLUGIN_TRUST_REQUIRED` | 400 | 安装受信任进程插件时未显式确认权限 | -| `PLUGIN_UNAVAILABLE` | 404 / 503 | 来源插件未注册,或进程不可用 | | `RATE_LIMITED` | 429 | 上游限流或宿主来源并发达到上限 | -| `PLUGIN_TIMEOUT` | 504 | 插件单次 RPC 超过 30 秒 | -| `PLUGIN_PROTOCOL_ERROR` | 502 | 插件返回了不符合协议的 JSON | -| `PLUGIN_INCOMPATIBLE` | 400 | 安装包的 API 版本或运行时不受支持 | -| `PLUGIN_PACKAGE_NOT_FOUND` | 404 | 插件目录、清单或入口文件不存在 | -| `PLUGIN_INVALID_MANIFEST` | 400 | 插件清单 JSON 或字段不合法 | -| `PLUGIN_PATH_ESCAPE` | 400 | 插件目录不在 `DATA_DIR/plugins` 内 | -| `PLUGIN_ALREADY_INSTALLED` | 409 | 插件 ID 或目录已安装 | -| `BUILTIN_PLUGIN_IMMUTABLE` | 400 | 内置来源不能停用、卸载或替换 | | `SOURCE_TIMEOUT` | 504 | 宿主来源调用超过 60 秒 | | `SOURCE_CANCELLED` | 499 | 客户端断开或主动取消来源调用 | | `INTERNAL` | 500 | 服务端错误 | @@ -1138,21 +998,6 @@ GET 返回 `{ "mode": "closed", "invites": [...] }`;PATCH 接受 `{ "mode": "c 改个文件名时踢下线,顺手把他存的令牌也删了。按 `error.code` 判断,不要只看状态码。 -### 插件扩展与换源 - -- 管理员 `GET /api/v1/sources/:id/pages/:pageId`:来源实例的声明页面,返回 `title/description/notice/forms/sections/tabs/activeTab`。 -- 管理员 `POST /api/v1/sources/:id/pages/:pageId`:`{action,values}`,操作当前实例并返回页面;入口来自 sourceType 的 `extensions.pages`。暂停来源仍可管理,插件停用后不可访问。 -- 管理员 `GET /api/v1/plugins/:id/pages/:pageId`:已声明配置页,返回通用 title/description/forms/sections。 -- 管理员 `POST /api/v1/plugins/:id/pages/:pageId`:`{action,values}`,返回更新后的页面。插件清单顶层 extensions.pages 提供全局入口。 -- `GET /api/v1/sources/:id/search-filters`:插件声明的选择字段;搜索接口接受 JSON 编码的 `filters` 查询参数,值为字符串映射。 -- `GET /api/v1/books/:id/source-options`:`{canSwitch}`,限本人有权限的书籍。 -- `POST /api/v1/books/:id/alternatives`:请求 `{sessionId,cursor?,resultLimit?}`,以 `text/event-stream` 返回 `results`(CatalogPage)、`done`、`error`,与搜索使用相同的 Streamable HTTP 协议。断开连接取消换源搜索。 -- `POST /api/v1/books/:id/refresh-chapter`:请求 `{ref}`(当前 manifest 的 `resourceRef`),强制重新读取当前修订的章节,返回正文二进制响应;失败保留原缓存,旧修订返回 `CHAPTER_SNAPSHOT_EXPIRED`。 -- `POST /api/v1/books/:id/switch-preview`:`{entryRef}` → `{chapters:[{id,title}]}`。 -- `POST /api/v1/books/:id/switch-source`:`{entryRef,chapterId,revision}` → `{content,href}`;所选正文验证成功后事务切换,保留 bookId。目录变更返回冲突,客户端刷新再选择。 - -后台任务 RPC、持久化及限制见[插件扩展设计](plugin-extensions.md)。页面只接受声明式数据,不执行插件提供的浏览器脚本。 - ## Personal reading overrides and TTS diagnostics All endpoints require the account access token in the Authorization header. Reading overrides additionally check book access. @@ -1161,13 +1006,3 @@ All endpoints require the account access token in the Authorization header. Read - PUT /api/v1/books/:id/reading-overrides accepts the same object. A correction contains id, anchor (sectionId, start, end, quote, prefix, suffix), and replacement. The submitted version must match the latest version; stale writes return 409. Up to 500 corrections are allowed, with each quote/replacement at most 4,000 characters. headingPrefix is a literal prefix of at most 60 characters. - POST /api/v1/books/:id/reading-overrides/undo accepts { version } and saves the preceding snapshot as a new version. History is scoped to account/book and stored in DATA_DIR/reader.db; it never rewrites library files. - POST /api/v1/tts/test accepts { voice?, speed? }, synthesizes a fixed sample and returns { bytes, contentType, elapsedMs, cached }. Failure codes include TTS_DISABLED, TTS_AUTH, TTS_TIMEOUT, TTS_CONTENT, TTS_EMPTY and TTS_UPSTREAM. It does not accept an upstream URL. Audio playback remains GET /api/v1/tts. - -### 章节质量和个人凭据状态(P2) - -- `POST /api/v1/books/:id/switch-quality`:已登录且拥有该书,body 为 `{ entryRef, chapterId }`。沿当前来源插件获取候选正文,返回 `{ chapterId, title, latestChapter, characters, images, bytes, elapsedMs }`;不写入书架、绑定或正文缓存。耗时包含目录、正文、内嵌图片处理,不含前置 acquire 和网络往返。 -- `switch-preview` 额外返回 `latestChapter`。质量检测按需执行;确认换源时重新获取并验证正文。空白或清洗后为空的正文返回 `EMPTY_CHAPTER`,不覆盖旧缓存/绑定。图片章可通过,字符统计不包含空白与 HTML 标签。 -- `GET /api/v1/sources/:id/credentials`:仅当前账号的 `{ state, checkedAt, available, fields: [{ key, label, configured }] }`,不包含凭据值。state 为 unknown / reachable / auth-required / verification-required。checkedAt 是毫秒时间戳或 null;仅代表最近观察。 -- `DELETE /api/v1/sources/:id/credentials/:key`:只删除当前账号该项。原 PUT 保存空字符串也会删除;保存/删除后访问状态回到 unknown。修改连接配置会清除该来源所有个人凭据并重置状态。 -- 插件抛出 `AUTH_REQUIRED`、`AUTH_EXPIRED` 或 `VERIFICATION_REQUIRED` 时记录访问状态;它们不使 Reader 账号退出。部分搜索错误中出现同类码也会记录;多个站点共用一个实例时只表示其中有站点需要处理。普通网络失败不推断为凭据失效。 - -- [OPDS 服务端接入与 WebDAV 备份上传](opds-webdav.zh-CN.md) diff --git a/docs/architecture.md b/docs/architecture.md index a261fc3..22d13e8 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -3,7 +3,7 @@ 本文记录**为什么这样设计**,尤其是那些一旦写错就很难回头的决策。 早期产品设计中的约束在这里落成了实现,逐条对应;当前行为以代码和 API 文档为准。 -来源扩展与插件系统的设计、接口及实施状态见 [来源插件系统设计](source-plugins.md)。该文档区分目标架构和当前开发切片,本页现有本地书籍身份及兼容约束继续适用。 +影音采用独立数据库和服务线程,详见[影音架构](media-implementation.md)及[写入隔离](media-write-isolation.md)。 --- @@ -12,7 +12,7 @@ | 位置 | 内容 | 读写 | | --- | --- | --- | | `BOOKS_DIR` (`/books`) | 用户自己的电子书;管理员可执行文件管理操作 | 按挂载权限读写 | -| `DATA_DIR` (`/data`) | SQLite、封面缓存、扫描记录、上传暂存、令牌密钥和插件数据 | 读写 | +| `DATA_DIR` (`/data`) | SQLite、封面缓存、扫描记录、上传暂存、令牌密钥和影音数据 | 读写 | | 客户端本地 | 离线书文件缓存、本地进度 | 读写 | 服务端是唯一真相源。客户端只承担「渲染 + 缓存」。 diff --git a/docs/backup.zh-CN.md b/docs/backup.zh-CN.md index 1fbfb76..0b54b53 100644 --- a/docs/backup.zh-CN.md +++ b/docs/backup.zh-CN.md @@ -1,8 +1,8 @@ # 数据备份与恢复 -维护命令随服务端构建发布,覆盖整个 `DATA_DIR`:SQLite(含 WAL)、账号、书架、进度、笔记、签名密钥、插件包/状态、下载与缓存。SQLite 的共享内存文件会重新生成,不计入备份。**`BOOKS_DIR` 原书、Compose 配置和环境变量需另行备份。** 如果签名密钥由环境变量提供,也需保留原配置。 +维护命令随服务端构建发布,覆盖整个 `DATA_DIR`:SQLite(含 WAL)、账号、书架、进度、笔记、签名密钥、影音资料、收藏与播放记录、下载与缓存。SQLite 的共享内存文件会重新生成,不计入备份。**`BOOKS_DIR` 原书、原始媒体文件、OpenList 挂载配置、Compose 配置和环境变量需另行备份。** 如果签名密钥由环境变量提供,也需保留原配置。 -这是离线维护工具。运行 backup/restore 前停止所有使用该数据目录的服务和插件;`--server-stopped` 是操作者确认,不会自动检测或停止服务。校验和能发现意外损坏,不证明备份来自可信来源。 +这是离线维护工具。运行 backup/restore 前停止所有使用该数据目录的服务进程;`--server-stopped` 是操作者确认,不会自动检测或停止服务。校验和能发现意外损坏,不证明备份来自可信来源。 ## 独立影音数据库 @@ -77,6 +77,6 @@ docker run --rm --user 0:0 --entrypoint chown \ - 仅支持当前 Node 版 reader 数据库;不转换旧 Java 版 `/storage` 数据。 - 保留目录内部的相对符号链接;拒绝绝对链接、外部链接和特殊设备文件。Windows 创建符号链接可能需要开发者模式或相应权限。 - 本工具不保证在服务运行中复制的一致性;停机是使用前提。书籍多时备份可能较大,请确保目标空间充足。 -- 备份含账号及插件凭据,应使用受限权限存放。 +- 备份含账号及来源和 OpenList 凭据,应使用受限权限存放。 - [OPDS 服务端接入与 WebDAV 备份上传](opds-webdav.zh-CN.md) diff --git a/docs/closed-issues-2026-09-23/issues.md b/docs/closed-issues-2026-09-23/issues.md deleted file mode 100644 index 409eb93..0000000 --- a/docs/closed-issues-2026-09-23/issues.md +++ /dev/null @@ -1,1877 +0,0 @@ -# 最近两天关闭的 Issue 原文存档 - -抓取日期:2026-09-23。共 101 条;按关闭时间筛选,包含历史创建的 issue。正文原样保留;图片和附件未下载。评论仅包含 2026-09-21 起更新的相关评论,不代表完整讨论。 - -## 索引 - -- [#718 会考虑增加书源登陆的功能吗?](https://github.com/hectorqin/reader/issues/718) — 2026/9/23 9:25:14,not_planned -- [#717 希望可以配置导出epub在nas里也存一份,并且可以设置自定义保存目录,另外希望能支持opds](https://github.com/hectorqin/reader/issues/717) — 2026/9/23 9:25:13,not_planned -- [#716 【功能请求】:内容相似度显示](https://github.com/hectorqin/reader/issues/716) — 2026/9/23 9:25:13,not_planned -- [#712 (建议)对于arm版Windows的构建](https://github.com/hectorqin/reader/issues/712) — 2026/9/23 9:25:12,not_planned -- [#714 Docker上用什么字段来修改默认书源上限?](https://github.com/hectorqin/reader/issues/714) — 2026/9/23 9:25:12,not_planned -- [#711 【功能建议】可以自定义网页标题](https://github.com/hectorqin/reader/issues/711) — 2026/9/23 9:25:11,not_planned -- [#710 【功能建议】多级目录](https://github.com/hectorqin/reader/issues/710) — 2026/9/23 9:25:11,not_planned -- [#709 【功能申请】内容划线与注释](https://github.com/hectorqin/reader/issues/709) — 2026/9/23 9:25:10,not_planned -- [#707 会创造大量docker日志,填满磁盘](https://github.com/hectorqin/reader/issues/707) — 2026/9/23 9:25:10,not_planned -- [#706 com.jayway.jsonpath.PathNotFoundException: No results for path: $['data']](https://github.com/hectorqin/reader/issues/706) — 2026/9/23 9:25:09,not_planned -- [#703 能否集成cloudscraper 实现自动过cf盾?](https://github.com/hectorqin/reader/issues/703) — 2026/9/23 9:25:09,not_planned -- [#704 浏览书仓,是否可以搜索子目录?](https://github.com/hectorqin/reader/issues/704) — 2026/9/23 9:25:09,not_planned -- [#702 能够自动加载下一章,每次都得手动点击下一章,特别影响阅读体验](https://github.com/hectorqin/reader/issues/702) — 2026/9/23 9:25:08,not_planned -- [#700 能否适配阅读客户端的webdav同步逻辑](https://github.com/hectorqin/reader/issues/700) — 2026/9/23 9:25:08,not_planned -- [#699 有办法把其他平台的评论抓过来吗](https://github.com/hectorqin/reader/issues/699) — 2026/9/23 9:25:07,not_planned -- [#698 能自动下一章吗?](https://github.com/hectorqin/reader/issues/698) — 2026/9/23 9:25:07,not_planned -- [#696 跳段很影响观感](https://github.com/hectorqin/reader/issues/696) — 2026/9/23 9:25:06,not_planned -- [#697 导入书源过多,直接崩溃,重新打开,书架的书,一直显示报错](https://github.com/hectorqin/reader/issues/697) — 2026/9/23 9:25:06,not_planned -- [#694 【功能建议】建议增加AI速读功能](https://github.com/hectorqin/reader/issues/694) — 2026/9/23 9:25:05,not_planned -- [#695 依赖出现了CVE,建议升级下对应依赖版本](https://github.com/hectorqin/reader/issues/695) — 2026/9/23 9:25:05,not_planned -- [#693 请教如何把reader3服务器做成书源导入阅读apk?](https://github.com/hectorqin/reader/issues/693) — 2026/9/23 9:25:05,not_planned -- [#692 书籍内搜索无法定位](https://github.com/hectorqin/reader/issues/692) — 2026/9/23 9:25:04,not_planned -- [#691 【功能申请】能否在不同的客户端能使用不同的主题?](https://github.com/hectorqin/reader/issues/691) — 2026/9/23 9:25:04,not_planned -- [#690 [web] 朗读功能失效](https://github.com/hectorqin/reader/issues/690) — 2026/9/23 9:25:03,not_planned -- [#689 听书想用第三方的语音要怎么配置啊?](https://github.com/hectorqin/reader/issues/689) — 2026/9/23 9:25:02,not_planned -- [#688 希望修改文章内容是在原txt修改而非重新生成](https://github.com/hectorqin/reader/issues/688) — 2026/9/23 9:17:36,not_planned -- [#684 希望可以锁定横向滑动,添加全屏](https://github.com/hectorqin/reader/issues/684) — 2026/9/23 9:17:35,not_planned -- [#687 docker compose 部署](https://github.com/hectorqin/reader/issues/687) — 2026/9/23 9:17:35,not_planned -- [#677 书海数据响应问题](https://github.com/hectorqin/reader/issues/677) — 2026/9/23 9:17:34,not_planned -- [#679 可以新增功能支持opds协议,来连接自己的书库吗,比如calibre-web?](https://github.com/hectorqin/reader/issues/679) — 2026/9/23 9:17:34,not_planned -- [#674 突然无法打开书架和添加本地书籍,原账号可以登录成功,但原书架数据全都丢失?](https://github.com/hectorqin/reader/issues/674) — 2026/9/23 9:17:33,not_planned -- [#676 [Web] 3.2.14 版本中 “关闭书架虚拟列表优化” 也无法将单列目录还原,且关闭后当书架书籍数量不足时,会拉伸书籍div高度来自适应书架高度,造成界面排版异常](https://github.com/hectorqin/reader/issues/676) — 2026/9/23 9:17:33,not_planned -- [#672 同样的书源手机客户端能搜到书籍,服务器版搜索不到](https://github.com/hectorqin/reader/issues/672) — 2026/9/23 9:17:32,not_planned -- [#673 opds support](https://github.com/hectorqin/reader/issues/673) — 2026/9/23 9:17:32,not_planned -- [#669 求教服务器版本如何看漫画](https://github.com/hectorqin/reader/issues/669) — 2026/9/23 9:17:31,not_planned -- [#670 [web/server] docker compose部署 out of memory](https://github.com/hectorqin/reader/issues/670) — 2026/9/23 9:17:31,not_planned -- [#665 [web/server] claw cloud run 和Railway 部署都失败](https://github.com/hectorqin/reader/issues/665) — 2026/9/23 9:17:30,not_planned -- [#666 部署那个就可以吗](https://github.com/hectorqin/reader/issues/666) — 2026/9/23 9:17:30,not_planned -- [#664 电脑上3.2.14书架和目录的排列](https://github.com/hectorqin/reader/issues/664) — 2026/9/23 9:17:30,not_planned -- [#659 使用自定义目录规则会导致无法调整左右间距(手机模式)](https://github.com/hectorqin/reader/issues/659) — 2026/9/23 9:17:29,not_planned -- [#663 [web/server]:阅读了几章后,点击顶部首页按钮返回书架页后,阅读进度没有刷新,还是显示之前阅读进度,点击进入后也会回到之前的阅读进度](https://github.com/hectorqin/reader/issues/663) — 2026/9/23 9:17:29,not_planned -- [#658 提供 t2s 等新版开源阅读js命令](https://github.com/hectorqin/reader/issues/658) — 2026/9/23 9:17:28,not_planned -- [#657 原先导入的小说,突然在页面中不显示了](https://github.com/hectorqin/reader/issues/657) — 2026/9/23 9:17:28,not_planned -- [#656 [server]macOS下的safari导出书籍时,文件名乱码](https://github.com/hectorqin/reader/issues/656) — 2026/9/23 9:17:27,not_planned -- [#654 目录规则:添加自定义规则以及设置默认规则](https://github.com/hectorqin/reader/issues/654) — 2026/9/23 9:17:27,not_planned -- [#655 服务器版本老是跳,有时候跳段落,有时候跳章节](https://github.com/hectorqin/reader/issues/655) — 2026/9/23 9:17:27,not_planned -- [#651 调试源结果正常,但是在阅读UI界面添加书籍,反应找不到书,怎么回事?](https://github.com/hectorqin/reader/issues/651) — 2026/9/23 9:17:26,not_planned -- [#652 移动端浏览器进度异常跳跃问题【尝试解决中】](https://github.com/hectorqin/reader/issues/652) — 2026/9/23 9:17:26,not_planned -- [#650 请求支持startBrowserAwait去除人机验证](https://github.com/hectorqin/reader/issues/650) — 2026/9/23 9:17:25,not_planned -- [#649 求助:目录能否自动刷新](https://github.com/hectorqin/reader/issues/649) — 2026/9/23 9:17:25,not_planned -- [#647 大佬求助:字符集错误导致文本无法正常显示](https://github.com/hectorqin/reader/issues/647) — 2026/9/23 9:16:52,not_planned -- [#645 [server]翻页模式bug](https://github.com/hectorqin/reader/issues/645) — 2026/9/23 9:16:52,not_planned -- [#644 docker版目录](https://github.com/hectorqin/reader/issues/644) — 2026/9/23 9:16:51,not_planned -- [#642 每次升级版本就会把之前上传的小说重置](https://github.com/hectorqin/reader/issues/642) — 2026/9/23 9:16:51,not_planned -- [#643 过滤规则:是否能够将文本替换为换行](https://github.com/hectorqin/reader/issues/643) — 2026/9/23 9:16:51,not_planned -- [#638 web/server 书架过大的时候会出现超时](https://github.com/hectorqin/reader/issues/638) — 2026/9/23 9:16:50,not_planned -- [#641 [server] 关于自动同步配置造成的问题](https://github.com/hectorqin/reader/issues/641) — 2026/9/23 9:16:50,not_planned -- [#637 每过一段时间,都会自动删除我使用的账号](https://github.com/hectorqin/reader/issues/637) — 2026/9/23 9:16:49,not_planned -- [#636 阅读epub时,iframe和解析模式的bug](https://github.com/hectorqin/reader/issues/636) — 2026/9/23 9:16:49,not_planned -- [#635 在Arc浏览器使用reader的朗读功能,跳到下一章的时候,总是从文章的中间开始。](https://github.com/hectorqin/reader/issues/635) — 2026/9/23 9:16:48,not_planned -- [#632 当使用mongo数据库时,依然会丢失书源](https://github.com/hectorqin/reader/issues/632) — 2026/9/23 9:16:48,not_planned -- [#634 [web/simple]:kindle 的simple-waeb翻页闪屏](https://github.com/hectorqin/reader/issues/634) — 2026/9/23 9:16:48,not_planned -- [#630 从书仓导入PDF文件,大部分页面变成空白](https://github.com/hectorqin/reader/issues/630) — 2026/9/23 9:16:47,not_planned -- [#626 希望把java端整合在setup](https://github.com/hectorqin/reader/issues/626) — 2026/9/23 9:16:47,not_planned -- [#624 翻页。。。在平板上不行啊,上下页不衔接](https://github.com/hectorqin/reader/issues/624) — 2026/9/23 9:16:46,not_planned -- [#622 可以隐藏任务栏吗](https://github.com/hectorqin/reader/issues/622) — 2026/9/23 9:16:46,not_planned -- [#623 [web]:IOS设备使用safari等webkit内核浏览器在最新版本系统中无法使用大声朗读\httpTTS的tts](https://github.com/hectorqin/reader/issues/623) — 2026/9/23 9:16:46,not_planned -- [#618 删除书籍后,assets目录下的export与cover未删除](https://github.com/hectorqin/reader/issues/618) — 2026/9/23 9:16:45,not_planned -- [#616 大声朗读局域网IP可以使用,使用花生壳域名访问无法使用 DMZ主机是开着的](https://github.com/hectorqin/reader/issues/616) — 2026/9/23 9:16:45,not_planned -- [#613 分享一个自定义Docker TTS 语音项目 可配 web TTS 朗读](https://github.com/hectorqin/reader/issues/613) — 2026/9/23 9:16:44,not_planned -- [#614 数据库+redis方案](https://github.com/hectorqin/reader/issues/614) — 2026/9/23 9:16:44,not_planned -- [#608 服务器版手机 edge 浏览器自带大声朗读无法播放](https://github.com/hectorqin/reader/issues/608) — 2026/9/23 9:16:43,not_planned -- [#601 添加本地书籍报错 获取章节内容失败! 章节文件不存在](https://github.com/hectorqin/reader/issues/601) — 2026/9/23 9:16:43,not_planned -- [#596 页面显示的章节与打开书籍后显示的章节不一致](https://github.com/hectorqin/reader/issues/596) — 2026/9/23 9:16:43,not_planned -- [#594 【建议】希望编辑后可以永久生效,而不是刷新后就会失效](https://github.com/hectorqin/reader/issues/594) — 2026/9/23 9:16:42,not_planned -- [#590 请教下各位书友httptts 怎么配置](https://github.com/hectorqin/reader/issues/590) — 2026/9/23 9:15:23,not_planned -- [#585 是否能修改下翻页的一个问题,章尾最后一页的排版,最后一行字始终是在页面最底部](https://github.com/hectorqin/reader/issues/585) — 2026/9/23 9:15:22,not_planned -- [#588 windows桌面版和安卓app版怎么和服务端连接](https://github.com/hectorqin/reader/issues/588) — 2026/9/23 9:15:22,not_planned -- [#584 建议增加标题的替换功能](https://github.com/hectorqin/reader/issues/584) — 2026/9/23 9:15:21,not_planned -- [#580 v3.2.10版本问题汇总](https://github.com/hectorqin/reader/issues/580) — 2026/9/23 9:15:21,not_planned -- [#573 [web]:切换书源界面功能强化-章节关键字搜索以及显示字数](https://github.com/hectorqin/reader/issues/573) — 2026/9/23 9:15:21,not_planned -- [#539 希望优化翻页方式(滚动)](https://github.com/hectorqin/reader/issues/539) — 2026/9/23 9:15:20,not_planned -- [#536 希望优化翻页](https://github.com/hectorqin/reader/issues/536) — 2026/9/23 9:15:20,not_planned -- [#523 Kindle的浏览器打不开](https://github.com/hectorqin/reader/issues/523) — 2026/9/23 9:15:19,not_planned -- [#529 [web/server]: “上下滚动”的翻页方式会导致切换书的时候页面空白](https://github.com/hectorqin/reader/issues/529) — 2026/9/23 9:15:19,not_planned -- [#519 使用nginx反向代理的redaer自带webdav作为阅读3.0的备份服务器,在阅读3.0导入远程书籍时显示超时](https://github.com/hectorqin/reader/issues/519) — 2026/9/23 9:15:19,not_planned -- [#513 书源失效时服务器缓存不起作用](https://github.com/hectorqin/reader/issues/513) — 2026/9/23 9:15:18,not_planned -- [#512 竖排书籍无法正常翻页](https://github.com/hectorqin/reader/issues/512) — 2026/9/23 9:15:18,not_planned -- [#498 书籍目录无法获取完整](https://github.com/hectorqin/reader/issues/498) — 2026/9/23 9:15:17,not_planned -- [#491 请问怎么设置单次搜索次数?现在需要一直点击加载更多](https://github.com/hectorqin/reader/issues/491) — 2026/9/23 9:15:17,not_planned -- [#486 [server]:有充足内存的情况下报错OutOfMemoryError ](https://github.com/hectorqin/reader/issues/486) — 2026/9/23 9:15:16,not_planned -- [#484 书籍列表分页的问题](https://github.com/hectorqin/reader/issues/484) — 2026/9/23 9:15:16,not_planned -- [#482 IOS, web端, 使用翻页的时候, 下一章的内容会跳转到最后,而不是最前,且语音听书的时候经常会有卡住的情况](https://github.com/hectorqin/reader/issues/482) — 2026/9/23 9:15:15,not_planned -- [#475 RSS Feed Bug](https://github.com/hectorqin/reader/issues/475) — 2026/9/23 9:15:14,not_planned -- [#463 本地书籍整理功能支持](https://github.com/hectorqin/reader/issues/463) — 2026/9/23 9:15:14,not_planned -- [#454 可不可以加入背景透明化](https://github.com/hectorqin/reader/issues/454) — 2026/9/23 9:15:14,not_planned -- [#453 发一下windows Java安装教程](https://github.com/hectorqin/reader/issues/453) — 2026/9/23 9:15:13,not_planned -- [#353 WebDAV的疑问](https://github.com/hectorqin/reader/issues/353) — 2026/9/23 9:14:41,completed -- [#339 为用jb的IDE的程序员们开发了个reader的阅读插件](https://github.com/hectorqin/reader/issues/339) — 2026/9/23 9:14:25,completed -- [#720 书源功能建议](https://github.com/hectorqin/reader/issues/720) — 2026/9/23 7:14:13,completed -- [#719 新版本安装问题及书源导入方法](https://github.com/hectorqin/reader/issues/719) — 2026/9/22 8:26:51,completed - -## #718 会考虑增加书源登陆的功能吗? - -原始链接:https://github.com/hectorqin/reader/issues/718 -创建:2026/6/6 13:42:08;关闭:2026/9/23 9:25:14;原因:not_planned;历史评论总数:0。时间为 UTC。 - -现在好的书源都要会员和登陆才行。 - -## #717 希望可以配置导出epub在nas里也存一份,并且可以设置自定义保存目录,另外希望能支持opds - -原始链接:https://github.com/hectorqin/reader/issues/717 -创建:2026/5/27 15:37:20;关闭:2026/9/23 9:25:13;原因:not_planned;历史评论总数:0。时间为 UTC。 - -(无正文) - -## #716 【功能请求】:内容相似度显示 - -原始链接:https://github.com/hectorqin/reader/issues/716 -创建:2026/5/19 2:06:39;关闭:2026/9/23 9:25:13;原因:not_planned;历史评论总数:0。时间为 UTC。 - -大佬好,请问能否出一个功能,当切换书源的时候,在书源每行的延迟时间旁边添加两个内容,一个是该书源在本章的字数,另一个是该书源在和本书源在本章节的相似度(可以直接借用notepad++的compare功能)。 -这样如果在读书的时候,这个书源的内容被修改了,可以快速的找到正确的书源内容,不用再一个一个更换了 - -## #712 (建议)对于arm版Windows的构建 - -原始链接:https://github.com/hectorqin/reader/issues/712 -创建:2026/2/2 14:50:50;关闭:2026/9/23 9:25:12;原因:not_planned;历史评论总数:0。时间为 UTC。 - -希望可以构建Windows的arm版本 - - - -## #714 Docker上用什么字段来修改默认书源上限? - -原始链接:https://github.com/hectorqin/reader/issues/714 -创建:2026/4/20 1:50:37;关闭:2026/9/23 9:25:12;原因:not_planned;历史评论总数:1。时间为 UTC。 - -defaultUserBookSourceLimit修改到2000是无效的,最高100。用什么字段来修改默认书源上限? - -## #711 【功能建议】可以自定义网页标题 - -原始链接:https://github.com/hectorqin/reader/issues/711 -创建:2026/1/10 1:04:00;关闭:2026/9/23 9:25:11;原因:not_planned;历史评论总数:1。时间为 UTC。 - -希望可以自定义网页标题,现在默认是小说名字+章节,如果能自定义就能更隐蔽的阅读。 - -## #710 【功能建议】多级目录 - -原始链接:https://github.com/hectorqin/reader/issues/710 -创建:2026/1/6 16:23:25;关闭:2026/9/23 9:25:11;原因:not_planned;历史评论总数:0。时间为 UTC。 - -想要多级目录 - -## #709 【功能申请】内容划线与注释 - -原始链接:https://github.com/hectorqin/reader/issues/709 -创建:2026/1/6 15:33:57;关闭:2026/9/23 9:25:10;原因:not_planned;历史评论总数:0。时间为 UTC。 - -想要这个功能,可能对文字内容进行划线,并可以选择对其进行文字注释。用的 docker 版本,没找到这种操作,不知道桌面端有没有 - -## #707 会创造大量docker日志,填满磁盘 - -原始链接:https://github.com/hectorqin/reader/issues/707 -创建:2025/12/26 6:31:58;关闭:2026/9/23 9:25:10;原因:not_planned;历史评论总数:1。时间为 UTC。 - -每天都会创建大量日志,导致磁盘被空间 - -## #706 com.jayway.jsonpath.PathNotFoundException: No results for path: $['data'] - -原始链接:https://github.com/hectorqin/reader/issues/706 -创建:2025/12/25 16:43:35;关闭:2026/9/23 9:25:09;原因:not_planned;历史评论总数:0。时间为 UTC。 - -不管什么书源加入书全是这个报错 -com.jayway.jsonpath.PathNotFoundException: No results for path: $['data'] - -## #703 能否集成cloudscraper 实现自动过cf盾? - -原始链接:https://github.com/hectorqin/reader/issues/703 -创建:2025/12/8 13:11:57;关闭:2026/9/23 9:25:09;原因:not_planned;历史评论总数:0。时间为 UTC。 - -能否集成 https://github.com/VeNoMouS/cloudscraper ,实现自动过书源站点的cf盾,例如https://www.69shuba.com/ 这种优质书源站点挂了cf盾,不能自动过盾的话,就没法搜索阅读。 -谢谢! - -## #704 浏览书仓,是否可以搜索子目录? - -原始链接:https://github.com/hectorqin/reader/issues/704 -创建:2025/12/16 13:47:58;关闭:2026/9/23 9:25:09;原因:not_planned;历史评论总数:0。时间为 UTC。 - -我的本地书仓按照书籍类型有几个子目录,导入本地书仓时,搜索功能无法搜索子目录 - -## #702 能够自动加载下一章,每次都得手动点击下一章,特别影响阅读体验 - -原始链接:https://github.com/hectorqin/reader/issues/702 -创建:2025/12/8 1:14:22;关闭:2026/9/23 9:25:08;原因:not_planned;历史评论总数:3。时间为 UTC。 - -我是nas部署的,然后用手机浏览器阅读,每次音量键翻页到章节末页都得手动点击下一章,特别影响阅读体验 - -## #700 能否适配阅读客户端的webdav同步逻辑 - -原始链接:https://github.com/hectorqin/reader/issues/700 -创建:2025/11/15 5:03:21;关闭:2026/9/23 9:25:08;原因:not_planned;历史评论总数:0。时间为 UTC。 - -实现自动同步,而非需要手动点击还原 - -## #699 有办法把其他平台的评论抓过来吗 - -原始链接:https://github.com/hectorqin/reader/issues/699 -创建:2025/11/8 9:48:14;关闭:2026/9/23 9:25:07;原因:not_planned;历史评论总数:0。时间为 UTC。 - -如题 - -## #698 能自动下一章吗? - -原始链接:https://github.com/hectorqin/reader/issues/698 -创建:2025/11/6 11:29:25;关闭:2026/9/23 9:25:07;原因:not_planned;历史评论总数:0。时间为 UTC。 - -每一章读到最后,能自动加载下一章吗?不需要手动点击才能下一章。 - -## #696 跳段很影响观感 - -原始链接:https://github.com/hectorqin/reader/issues/696 -创建:2025/10/17 10:18:49;关闭:2026/9/23 9:25:06;原因:not_planned;历史评论总数:0。时间为 UTC。 - -把跳段修修吧,求你了很影响看书 - -## #697 导入书源过多,直接崩溃,重新打开,书架的书,一直显示报错 - -原始链接:https://github.com/hectorqin/reader/issues/697 -创建:2025/11/3 3:01:47;关闭:2026/9/23 9:25:06;原因:not_planned;历史评论总数:1。时间为 UTC。 - -一直出现下面的报错,io.vertx.core.json.DecodeException: Failed to decode:No content to map due to end-of-input at [Source: (String)""; line: 1, column: 0] - -## #694 【功能建议】建议增加AI速读功能 - -原始链接:https://github.com/hectorqin/reader/issues/694 -创建:2025/9/11 14:02:44;关闭:2026/9/23 9:25:05;原因:not_planned;历史评论总数:0。时间为 UTC。 - -建议增加AI总结功能,可通过大模型API对每章内容进行总结提炼,帮助快速阅读 - -## #695 依赖出现了CVE,建议升级下对应依赖版本 - -原始链接:https://github.com/hectorqin/reader/issues/695 -创建:2025/10/14 19:02:18;关闭:2026/9/23 9:25:05;原因:not_planned;历史评论总数:0。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -FasterXML jackson-databind远程代码执行漏洞(CVE-2019-17531) -在3.2.14 jar包中扫描出了有问题版本的依赖,建议升级下依赖版本。 - - -## #693 请教如何把reader3服务器做成书源导入阅读apk? - -原始链接:https://github.com/hectorqin/reader/issues/693 -创建:2025/8/28 11:36:02;关闭:2026/9/23 9:25:05;原因:not_planned;历史评论总数:7。时间为 UTC。 - -如标题所述,起因需求是reader3服务器能正常访问海外,而手机毕竟无法长期上T,如果能把服务器做成书源导入手机阅读apk,那不就方便了么? -请高手指点一下如何操作? - -## #692 书籍内搜索无法定位 - -原始链接:https://github.com/hectorqin/reader/issues/692 -创建:2025/8/24 8:22:09;关闭:2026/9/23 9:25:04;原因:not_planned;历史评论总数:0。时间为 UTC。 - -作者您好,我在使用这个软件阅读时,我在书籍内搜索关键字,会列出所有结果,我点击一个结果,然后只会跳转到结果所在的那一章的开头而不是到这个结果的具体位置。我尝试了使用单页模式(切换成手机模式再用左右翻面)还是一样的情况。是我没有设置对还是这是一个bug? - -## #691 【功能申请】能否在不同的客户端能使用不同的主题? - -原始链接:https://github.com/hectorqin/reader/issues/691 -创建:2025/8/23 8:42:14;关闭:2026/9/23 9:25:04;原因:not_planned;历史评论总数:0。时间为 UTC。 - -不同的设备要使用不同的主题,电脑,手机,电纸书(还分彩色和黑白)等等要使用不同的主题才更适合。 - -客户端做本地标识,然后再后台列表记录一下应该就可以了。或者直接把主题选择存在本地更简单。 - - - -另外,还有个问题,打开页面时读书籍列表很废时,体验不好,能不能在本地缓存之前的,打开时先显示缓存,更新后再前台刷新,这样体验应该会更好。 - -## #690 [web] 朗读功能失效 - -原始链接:https://github.com/hectorqin/reader/issues/690 -创建:2025/8/20 4:59:48;关闭:2026/9/23 9:25:03;原因:not_planned;历史评论总数:4。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -朗读功能突然失效, 包含`浏览器`和 `大声朗读` - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. 打开小说 -2. 点开朗读功能 -3. 任意朗读服务 -4. 点击播放 - -**Expected behavior 期待修复的效果** -播放朗读 - -**Screenshots 如有必要,可以截图说明** -- - -**版本说明** - - OS: 树莓pi 4, ubuntu - - docker 部署 - - hectorqin/reader:openj9-latest - - chrome 浏览器(桌面端 & 手机端) - -**Additional context 其他说明** -检查 api 返回内容, 并没有资料, 返回内容如下: -```json -{"isSuccess":true,"errorMsg":"","data":""} -``` - - -## #689 听书想用第三方的语音要怎么配置啊? - -原始链接:https://github.com/hectorqin/reader/issues/689 -创建:2025/8/19 11:52:39;关闭:2026/9/23 9:25:02;原因:not_planned;历史评论总数:4。时间为 UTC。 - -我想用听书功能,但默认的语音太难听了,想自己配置第三方语音但不知道怎么配,这个HttpTTS是用来配置第三方的吗?文档里也没有说明。 - -Image - -## #688 希望修改文章内容是在原txt修改而非重新生成 - -原始链接:https://github.com/hectorqin/reader/issues/688 -创建:2025/8/13 9:18:59;关闭:2026/9/23 9:17:36;原因:not_planned;历史评论总数:1。时间为 UTC。 - - 目前编辑文章内容是重新生成一份新的txt,包括从书仓导入的,这样导致编辑的内容只是在前端web显示,书仓的原书籍依然是不变的。 - 并且一旦刷新更改的内容就全部消失,但是后端新建的txt又还在,这样的操作逻辑比较奇怪。 - 不清楚实现这样的功能是否过于复杂,如果难以实现的话也只能通过手动修改书仓内txt进行变更,就是比较麻烦,主要是因为部分文章存在缺文少字的情况,难免会有需要手动更改,但是目前的修改功能感觉并不能很好的支撑这一需求。 - -Image - -## #684 希望可以锁定横向滑动,添加全屏 - -原始链接:https://github.com/hectorqin/reader/issues/684 -创建:2025/8/5 7:42:55;关闭:2026/9/23 9:17:35;原因:not_planned;历史评论总数:0。时间为 UTC。 - -1. 我在使用触控板进行滑动阅读的时候,有时候会略微偏斜导致先横向滑动,后竖向滚动,发生页面晃动,影响阅读体验。我试了一下各个浏览器,发现似乎只有谷歌浏览器是横向滑动的时候页面不动,希望可以锁定横向滑动。 - -2. 希望添加类似浏览器f11的全屏功能 - - -## #687 docker compose 部署 - -原始链接:https://github.com/hectorqin/reader/issues/687 -创建:2025/8/12 9:27:10;关闭:2026/9/23 9:17:35;原因:not_planned;历史评论总数:3。时间为 UTC。 - -每次都是从第一章开始,没有获取阅读进度 - - -## #677 书海数据响应问题 - -原始链接:https://github.com/hectorqin/reader/issues/677 -创建:2025/6/30 2:18:46;关闭:2026/9/23 9:17:34;原因:not_planned;历史评论总数:0。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -A clear and concise description of what the bug is. 简洁有效的说明。 -书海哪里点击响应问题 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. Go to '...' -2. - -![Image](https://github.com/user-attachments/assets/c3bbb451-fef5-434e-8daa-9077790a67cc) -点击了 但是没有数据请求 -3. Click on '....' -4. 点击下一个选项有了上一个的数据请求并响应回来 - -![Image](https://github.com/user-attachments/assets/424f299c-70aa-4e0e-bec5-841cba1ac9b5) - -5. Scroll down to '....' -6. See error**Expected behavior 期待修复的效果** -A clear and concise description of what you expected to happen. 简单描述。 - -**Screenshots 如有必要,可以截图说明** -If applicable, add screenshots to help explain your problem. - -**版本说明** - - OS: [e.g. win] win - - Deploy Method web版 - - Program Version 3.2.14 - - Browser [e.g. chrome, safari] edge - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #679 可以新增功能支持opds协议,来连接自己的书库吗,比如calibre-web? - -原始链接:https://github.com/hectorqin/reader/issues/679 -创建:2025/7/4 4:08:51;关闭:2026/9/23 9:17:34;原因:not_planned;历史评论总数:1。时间为 UTC。 - -目前自己同时也部署了一套calibre-web,希望可以通过reader3来连接calibre-web来阅读自己本地的书籍,reader3本身自带的本地书仓不太好用,默认只能放到localstorage下,挂载了其他目录也访问不到。 - -## #674 突然无法打开书架和添加本地书籍,原账号可以登录成功,但原书架数据全都丢失? - -原始链接:https://github.com/hectorqin/reader/issues/674 -创建:2025/6/18 8:27:17;关闭:2026/9/23 9:17:33;原因:not_planned;历史评论总数:0。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -A clear and concise description of what the bug is. 简洁有效的说明。 -1、我是在群晖上用docker架设的阅读服务器(多用户模式),长期使用域名访问看书起码半年多了。今天群晖突然故障重启,然后阅读服务器下我个人常用的账号书架书籍全消失了,浏览书仓功能可以进入,但要重新添加书仓内的本地txt小说却会失败,会提示:“io.vertx.core,json.DecodeException: Failed to decode:No content to map due to end-of input at [Source: ($tring)"; line: 1, column: 0]”;该账号登录是会有提示“io.vertx.corejson.DecodeException: Failed to decode:No content to map due to end-of-input at [Source:(String)"; line: 1, column: 0]”两次及提示“没有备份文件”。如图所示。 -奇怪的是,用其他账号登录,书架也在,添加书籍操作也在。 -2、我访问服务用的是网页版,但是在PC端chrome浏览器下访问,关键词搜索新书籍时会搜不到书,要在手机端chrome浏览器下就可以搜索到到书籍,明明是同样的书源。 -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior 期待修复的效果** -A clear and concise description of what you expected to happen. 简单描述。 -希望咨询账号数据恢复的手段。 -**Screenshots 如有必要,可以截图说明** -If applicable, add screenshots to help explain your problem. - -![Image](https://github.com/user-attachments/assets/79959a1c-5fd1-49b4-9557-a818e0d80a60) - -![Image](https://github.com/user-attachments/assets/396ecdfc-e582-4f9e-a36c-c8536077eb92) - -**版本说明** - - OS: 群晖DSM - - Deploy Method docker部署 - - Program Version最新的3.2.14 - - Browser [e.g. chrome, safari] chrome浏览器,PC端 - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #676 [Web] 3.2.14 版本中 “关闭书架虚拟列表优化” 也无法将单列目录还原,且关闭后当书架书籍数量不足时,会拉伸书籍div高度来自适应书架高度,造成界面排版异常 - -原始链接:https://github.com/hectorqin/reader/issues/676 -创建:2025/6/28 3:14:32;关闭:2026/9/23 9:17:33;原因:not_planned;历史评论总数:13。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -1、更新 `3.2.14` 版本 [reader-pro-3.2.14.jar](https://github.com/hectorqin/reader/releases/download/v3.2.14/reader-pro-3.2.14.jar) 并重新启动后,默认启用了 `书架虚拟列表优化` ,界面显示单列但无异常; -2、在左侧 `书架设置` --> `列表优化` 中选择 `不启用优化` 后保存,因为曾经为之前的版本为书籍的 info div 块添加了 `height: auto;min-height: 112px;`,因此发现在更新错误分组中书籍高度显示异常,经检查发现即使去掉了添加的 css 样式,凡是分组中书籍数量过少的界面,书籍的 div 块高度都会默认拉伸铺满分组书架界面; -3、即使在 “关闭书架虚拟列表优化” 后,进入书籍,目录列表显示也是单列,没有找到可以调整的设置,无法调整。试过重置后重新查看、备份后重新查看均无效。 - -**Expected behavior 期待修复的效果** -希望书籍目录列表可以正常切换单列和多列;书籍少的分组界面显示优化。 - -**Screenshots 如有必要,可以截图说明** -1、`启用虚拟列表优化` 时界面显示 -Image -2、`不启用优化` 时书架分组界面显示 -【添加 css 样式】 -Image -【去除 css 样式】 -Image -3、`不启用优化` 时书籍列表界面显示 -Image - -**版本说明** - - OS: Windows 11 - - Deploy Method: [reader-pro-3.2.14.jar](https://github.com/hectorqin/reader/releases/download/v3.2.14/reader-pro-3.2.14.jar) - - Program Version: 3.2.14 - - Browser: edge 浏览器 - - -## #672 同样的书源手机客户端能搜到书籍,服务器版搜索不到 - -原始链接:https://github.com/hectorqin/reader/issues/672 -创建:2025/6/17 1:55:40;关闭:2026/9/23 9:17:32;原因:not_planned;历史评论总数:5。时间为 UTC。 - -手机上用的阅读3客户端,在云服务器上也部署了3.2.14版本。手机和服务器上的书源是同一套,但是同样的小说在阅读3上能搜到,在服务器版上可能就搜不到。而且搜索结果的数量也是少很多。我会调的只有并发线程,把线程调高了也没什么用。 - -## #673 opds support - -原始链接:https://github.com/hectorqin/reader/issues/673 -创建:2025/6/17 11:27:19;关闭:2026/9/23 9:17:32;原因:not_planned;历史评论总数:1。时间为 UTC。 - -大佬目前版本支持opds么 - -## #669 求教服务器版本如何看漫画 - -原始链接:https://github.com/hectorqin/reader/issues/669 -创建:2025/6/4 16:53:49;关闭:2026/9/23 9:17:31;原因:not_planned;历史评论总数:2。时间为 UTC。 - -提示不支持webview或者显示空白 - -![Image](https://github.com/user-attachments/assets/a2ac2179-90c3-4493-8991-2f572dfc7170) - - - -## #670 [web/server] docker compose部署 out of memory - -原始链接:https://github.com/hectorqin/reader/issues/670 -创建:2025/6/5 4:00:30;关闭:2026/9/23 9:17:31;原因:not_planned;历史评论总数:1。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** - docker compose部署 docker启动时报错 -``` -library initialization failed - unable to allocate file descriptor table - out of memory11:49:36.914 [main] INFO com.htmake.reader.ReaderApplication - Starting application with args: [] -``` - 机器内存16G -``` -dnine7@dnine7-GL63-8RE:~/reader$ free -h - total used free shared buff/cache available -内存: 14Gi 4.9Gi 9.3Gi 265Mi 1.3Gi 10Gi -交换: 4.0Gi 0B 4.0Gi -``` - -**版本说明** - - OS: [e.g. win] 说明操作系统 ubuntu 24.10 - - Deploy Method 说明软件部署方式 docker compose - - Program Version 说明软件版本 3.2.14 - -**docker-compose-yaml** -``` -version: '3.1' -services: -# reader 在线阅读 -# 公开服务器(服务器位于日本):[https://reader.nxnow.top](https://reader.nxnow.top) 测试账号/密码分别为guest/guest123,也可自行创建账号添加书源,不定期删除长期未登录账号(2周) -# 书源集合 : [https://legado.aoaostar.com/](https://legado.aoaostar.com/) 点击打开连接,添加远程书源即可 -# 公众号汇总 : [https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MjM5MzMyMDgyMA==&action=getalbum&album_id=2397535253763801090#wechat_redirect](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MjM5MzMyMDgyMA==&action=getalbum&album_id=2397535253763801090#wechat_redirect) -# 手动更新方式 : docker-compose pull && docker-compose up -d - reader: - image: hectorqin/reader:latest - #image: hectorqin/reader:openj9-latest #docker镜像,arm64架构或小内存机器优先使用此镜像.启用需删除上一行 - container_name: reader #容器名 可自行修改 - restart: always - ports: - - 9970:8080 #4396端口映射可自行修改 - networks: - - share_net - volumes: - - /home/dnine7/reader/logs:/logs #log映射目录 /home/reader/logs 映射目录可自行修改 - - /home/dnine7/reader/storage:/storage #数据映射目录 /home/reader/storage 映射目录可自行修改 - environment: - - SPRING_PROFILES_ACTIVE=prod - - READER_APP_USERLIMIT=999999 #用户上限,默认50 - - READER_APP_USERBOOKLIMIT=99999 #用户书籍上限,默认200 - - READER_APP_CACHECHAPTERCONTENT=true #开启缓存章节内容 V2.0 - # 如果启用远程webview,需要取消注释下面的 remote-webview 服务 - # - READER_APP_REMOTEWEBVIEWAPI=http://remote-webview:8050 #开启远程webview - # 下面都是多用户模式配置 - - READER_APP_SECURE=true #开启登录鉴权,开启后将支持多用户模式 - - READER_APP_SECUREKEY=xzq521xzq #管理员密码 建议修改 - - READER_APP_INVITECODE=Dnine7 #注册邀请码 建议修改,如不需要可注释或删除 - # remote-webview: - # image: hectorqin/remote-webview - # container_name: remote-webview #容器名 可自行修改 - # restart: always - # ports: - # - 8050:8050 - # networks: - # - share_net -# 自动更新docker镜像 - watchtower: - image: containrrr/watchtower - container_name: watchtower - restart: always - # 环境变量,设置为上海时区 - environment: - - TZ=Asia/Shanghai - volumes: - - /var/run/docker.sock:/var/run/docker.sock - command: reader watchtower --cleanup --schedule "0 0 4 * * *" - networks: - - share_net - # 仅更新reader与watchtower容器,如需其他自行添加 '容器名' ,如:reader watchtower nginx - # --cleanup 更新后清理旧版本镜像 - # --schedule 自动检测更新 crontab定时(限定6位crontab) 此处代表凌晨4点整 -networks: - share_net: - driver: bridge -``` - - -## #665 [web/server] claw cloud run 和Railway 部署都失败 - -原始链接:https://github.com/hectorqin/reader/issues/665 -创建:2025/5/30 13:35:48;关闭:2026/9/23 9:17:30;原因:not_planned;历史评论总数:1。时间为 UTC。 - -![Image](https://github.com/user-attachments/assets/3df583a0-cdec-4d39-a5e6-187048f60d00) - -![Image](https://github.com/user-attachments/assets/3eb8f049-5c62-4c81-827e-f90c3c940ae7) - -![Image](https://github.com/user-attachments/assets/bac806fb-762c-4ffe-86be-2e0e97034ec8) - -部署方式:https://mp.weixin.qq.com/s/TCL6i_7Zrgf2okJG-BF07Q -如果有成功的大佬请帮帮忙看一下,是怎么回事?要怎么处理,还是说当前的这个版本是不能部署的?能部署的是哪个版本,有没有对应的链接, - -感谢各位大佬!!! - -## #666 部署那个就可以吗 - -原始链接:https://github.com/hectorqin/reader/issues/666 -创建:2025/5/30 14:02:54;关闭:2026/9/23 9:17:30;原因:not_planned;历史评论总数:0。时间为 UTC。 - -> Reader 完整源码仅开放到 v2.5.4,新版本当前仅开放部分开源源码,见 https://github.com/hectorqin/reader-legado. -> -> -> -> @jueinin -> -> 早就是闭源的了 - - _Originally posted by @rolay in [#498](https://github.com/hectorqin/reader/issues/498#issuecomment-2313894063)_ - -那意思是部署上面的这个就行吗? https://github.com/hectorqin/reader-legado. - -## #664 电脑上3.2.14书架和目录的排列 - -原始链接:https://github.com/hectorqin/reader/issues/664 -创建:2025/5/29 23:47:13;关闭:2026/9/23 9:17:30;原因:not_planned;历史评论总数:2。时间为 UTC。 - -电脑上3.2.14书架和目录的排列都是类似手机的单列竖排,没有哪里可以设置成跟以前一样的吗 - -书架左边栏找到了书架设置,目录没找到。 - -但是书架,如果设置成网格显示,就只显示封面,不显示已读和最新章节,且无论点击还是长按都是直接点进小说里,右键无效,也就是无法像列表模式点击封面那样出现编辑,移出书架,封面设置等选项。 -像保留这些选项就只能设置成单列的列表模式,希望可以保留跟以前的书架一样的多列列表的模式。另外就是目录的多列显示哪里设置 - -## #659 使用自定义目录规则会导致无法调整左右间距(手机模式) - -原始链接:https://github.com/hectorqin/reader/issues/659 -创建:2025/5/14 17:59:39;关闭:2026/9/23 9:17:29;原因:not_planned;历史评论总数:0。时间为 UTC。 - -使用自定义目录规则会导致部分小说无法调整左右间距 - -小说来源:本地txt - -版本:reader-pro-3.2.13.jar - -问题出现在web手机模式。 - -使用的规则是自定义的冒号分割 - -正则表达式:`.*(?<=:)\s([\u4e00-\u9fa5a-zA-Z0-9]{1,7})[^\n]{1,35}(|\n)` - - -> 以下是使用自定义的目录规则,无法设置左右间距 - -![Image](https://github.com/user-attachments/assets/38d5f327-eaad-4105-aae7-52cf32cdcb94) - -> 以下是使用自带的目录规则,可以正常设置左右间距 - -![Image](https://github.com/user-attachments/assets/ee94fbb3-382c-443d-a454-834225c84d55) - -## #663 [web/server]:阅读了几章后,点击顶部首页按钮返回书架页后,阅读进度没有刷新,还是显示之前阅读进度,点击进入后也会回到之前的阅读进度 - -原始链接:https://github.com/hectorqin/reader/issues/663 -创建:2025/5/28 23:24:28;关闭:2026/9/23 9:17:29;原因:not_planned;历史评论总数:4。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -A clear and concise description of what the bug is. 简洁有效的说明。 - -阅读小说中点击首页按钮,书籍进度不会刷新 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. Go to 小说阅读界面,阅读几章之后 -2. Click on '首页' -3. 可以看到书架上刚刚阅读的书,进度并没有更新,点进去也会回到之前的章节。除非点首页返回后,再次下拉刷新后,书架上的进度才会更新 - -**Expected behavior 期待修复的效果** -A clear and concise description of what you expected to happen. 简单描述。 - -点首页返回后,能正确刷新进度 - -**Screenshots 如有必要,可以截图说明** -If applicable, add screenshots to help explain your problem. - -**版本说明** - - OS: [e.g. win] unraid - - Deploy Method docker compose - - Program Version v3.2.14-05250935 - - Browser [e.g. chrome, safari] win edge, android edge - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #658 提供 t2s 等新版开源阅读js命令 - -原始链接:https://github.com/hectorqin/reader/issues/658 -创建:2025/5/13 11:07:33;关闭:2026/9/23 9:17:28;原因:not_planned;历史评论总数:0。时间为 UTC。 - -如题 - -## #657 原先导入的小说,突然在页面中不显示了 - -原始链接:https://github.com/hectorqin/reader/issues/657 -创建:2025/5/5 3:59:23;关闭:2026/9/23 9:17:28;原因:not_planned;历史评论总数:1。时间为 UTC。 - -Docker部署的,书源能正常显示,但是小说却不显示了。并且我去容器内看了,小说数据其实都还是在的,只是不知道为什么页面不显示了【难道小说的展示与否并不是根据存储目录中是否有这本小说,而是有一个专门的[配置文件]记录每次导入的新小说,然后页面展示小说就是根据这个[配置文件]来展示?然后莫名其妙这个[配置文件]消失了,所以原先导入的小说都不展示了?然后我重新导入了一本新的,于是这个[配置文件]重建了,所以才会只显示导入的这一本小说?】 - -![Image](https://github.com/user-attachments/assets/bf81474e-2796-443d-b027-ce2e36ed2828) - -![Image](https://github.com/user-attachments/assets/ea4e4964-b177-491c-b515-e4c0573b6d8c) - -## #656 [server]macOS下的safari导出书籍时,文件名乱码 - -原始链接:https://github.com/hectorqin/reader/issues/656 -创建:2025/4/18 15:13:33;关闭:2026/9/23 9:17:27;原因:not_planned;历史评论总数:0。时间为 UTC。 - -如题,文件名中的中文变成URL编码。 - -**To Reproduce 如何重现问题** -只要导出书籍必定会出现。 - -**版本说明** - - OS: [e.g. win] macOS15.4.1 - - Deploy Method 说明软件部署方式 群晖Docker - -**Additional context 其他说明** -AI说是部分服务器未遵循标准,在返回文件时未正确设置 Content-Disposition 头部的 filename* 参数(用于 UTF-8 编码),导致 Safari 无法自动解码文件名。Safari 对非 ASCII 字符(如中文、日文、特殊符号)的处理较严格,若服务器未明确指定 UTF-8 编码,Safari 会直接保留 URL 编码格式,而非尝试解码。 - - -## #654 目录规则:添加自定义规则以及设置默认规则 - -原始链接:https://github.com/hectorqin/reader/issues/654 -创建:2025/4/15 4:26:39;关闭:2026/9/23 9:17:27;原因:not_planned;历史评论总数:1。时间为 UTC。 - -关于目录规则的两个建议: -1、添加自定义规则(目前只有内置的一些规则,添加完书籍后,然后在阅读界面可重选以及修改规则,但是下次再添加书籍时要用相同规则需要重新加一遍) -2、设置某个规则为默认规则(目前是内置规则) -![Image](https://github.com/user-attachments/assets/15385785-340f-4db1-8647-613582d5b346) - -## #655 服务器版本老是跳,有时候跳段落,有时候跳章节 - -原始链接:https://github.com/hectorqin/reader/issues/655 -创建:2025/4/15 15:48:40;关闭:2026/9/23 9:17:27;原因:not_planned;历史评论总数:3。时间为 UTC。 - -![Image](https://github.com/user-attachments/assets/1d72e022-360f-41f3-bad0-09c24a9ac282) - -这样设置有问题吗 - -## #651 调试源结果正常,但是在阅读UI界面添加书籍,反应找不到书,怎么回事? - -原始链接:https://github.com/hectorqin/reader/issues/651 -创建:2025/4/12 4:33:06;关闭:2026/9/23 9:17:26;原因:not_planned;历史评论总数:0。时间为 UTC。 - -阅读docker版本 v3.2.12-12171550。系统ubuntu 24.04.2。浏览器firefox,版本137.0。 -写了一个书源,书源内容见以下。 -``` -{ - "bookSourceUrl": "https://www.xiguasuwu.com/", - "bookSourceType": 0, - "bookSourceName": "西瓜书屋", - "bookSourceGroup": "自编", - "bookSourceComment": "", - "loginUrl": "", - "loginUi": "", - "loginCheckJs": "", - "concurrentRate": "", - "header": " {\n'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56',\n'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',\n'Accept-Encoding': 'gzip, deflate, br',\n'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6'\n}", - "bookUrlPattern": "", - "searchUrl": "https://www.xiguasuwu.com/search,{'method':'POST','body':'searchkey={{key}}'}", - "exploreUrl": "", - "enabled": true, - "enabledExplore": true, - "weight": 0, - "customOrder": 0, - "lastUpdateTime": 1744422386179, - "ruleSearch": { - "bookList": "class.panel-body@class.book-coverlist", - "name": "class.fs-16@tag.a@text", - "author": "class.fs-14@text", - "intro": "class.fs-12@text", - "bookUrl": "class.fs-16@tag.a@href" - }, - "ruleExplore": {}, - "ruleBookInfo": { - "name": "class.bookTitle@text", - "author": "class.glyphicon-user@text", - "kind": "class.breadcrumb@tag.li1@text", - "wordCount": "class.glyphicon-font@text", - "lastChapter": "class.text-danger@text", - "intro": "id.bookIntro@text", - "coverUrl": "class.img-thumbnail@data-original", - "tocUrl": "class.btn-success@href" - }, - "ruleToc": { - "chapterList": "id.newlist@tag.dd", - "chapterName": "class.col-sm-4@tag.a@text", - "chapterUrl": "class.col-sm-4@tag.a@href", - "nextTocUrl": "class.right@tag.a@href!class.before" - }, - "ruleContent": { - "content": "id.booktxt@text", - "nextContentUrl": "id.linkNext@href" - } -} -``` - -调试源,可以得到正文页解析完成。调试回报见以下附件。 -[阅读调试log.txt](https://github.com/user-attachments/files/19717654/log.txt) -然后将书源保存,确认阅读UI界面里有该书源。然后只用该源分类,搜索书籍,反馈找不到书。书名为“绿龙筑巢记”,即是调试源时用的搜索书名。不知道是什么原因,有朋友知道什么原因,或者怎么检查? -[reader-2025-04-12.log](https://github.com/user-attachments/files/19716378/reader-2025-04-12.log) -阅读的日志文件,隐去个人网址。 - -## #652 移动端浏览器进度异常跳跃问题【尝试解决中】 - -原始链接:https://github.com/hectorqin/reader/issues/652 -创建:2025/4/12 5:29:04;关闭:2026/9/23 9:17:26;原因:not_planned;历史评论总数:16。时间为 UTC。 - -1、屏幕触控、滑动经常乱跳乱翻页 -2、浏览器界面不能全屏,建议去komga漫画应用学习一下 - -## #650 请求支持startBrowserAwait去除人机验证 - -原始链接:https://github.com/hectorqin/reader/issues/650 -创建:2025/4/10 12:03:07;关闭:2026/9/23 9:17:25;原因:not_planned;历史评论总数:1。时间为 UTC。 - -现在大部分的网站都启用了人机验证,大部分的书源通过以下方案去除人机验证: - -if(result.match(/Just a moment/)){ -cookie.removeCookie(source.bookSourceUrl) -var x=baseUrl; -var s=java.startBrowserAwait(x,"验证").body() -result=s; - }else{ - result=result; - } -result - - -reader3服务器版目前还不支持,使用时时会报错 -Error: org.mozilla.javascript.EcmaError: TypeError: Cannot find function startBrowserAwait in object io.legado.app.model.analyzeRule.AnalyzeRule@1baa25b8 -请问大佬是否可以支持,谢谢 - -## #649 求助:目录能否自动刷新 - -原始链接:https://github.com/hectorqin/reader/issues/649 -创建:2025/4/10 7:44:39;关闭:2026/9/23 9:17:25;原因:not_planned;历史评论总数:1。时间为 UTC。 - -docker部署的阅读服务端。 -使用本地txt作为书籍来源,作为来源的本地txt内容会自动更新。 -但本地更新后在阅读web界面书本不会自动更新内容,需要在书本详情里点击目录-刷新,才能更新章节及内容。 -想请问大佬有没有解决方法或者是能够调用的章节刷新接口,谢谢! - -## #647 大佬求助:字符集错误导致文本无法正常显示 - -原始链接:https://github.com/hectorqin/reader/issues/647 -创建:2025/4/9 5:17:35;关闭:2026/9/23 9:16:52;原因:not_planned;历史评论总数:1。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -书源可以缓存,但由于字符集不匹配无法正常显示 -可以正常缓存,获取封面,获取目录 -在reader安卓原版客户端上使用正常 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. 添加“速读谷”书源 https://www.yckceo.com/yuedu/shuyuan/json/id/5862.json -2. 随便添加一本书到书架,我添加的是“夜无疆” -3. 打开书籍 -4. 随便选中间的一个章节加载(这里很奇怪,第一次用这个书源的时候前两个章节都可以正常加载,后面突然不行了) -5. 页面显示java字符集报错 - -![Image](https://github.com/user-attachments/assets/efa13e74-c9cb-44e4-8099-fc8cb3f540d5) - -对应log -``` -[f26ccad3] [DefaultDispatcher-worker-2] 12:50:59.249 ERROR YueduApi - onHandlerError: -java.nio.charset.IllegalCharsetNameException: initial-scale=1.0, maximum-scale=1.0, user-scalable=no, width=device-width - at java.nio.charset.Charset.checkName(Charset.java:315) - at java.nio.charset.Charset.lookup2(Charset.java:484) - at java.nio.charset.Charset.lookup(Charset.java:464) - at java.nio.charset.Charset.forName(Charset.java:528) - at io.legado.app.help.http.OkHttpUtilsKt.text(OkHttpUtils.kt:117) - at io.legado.app.help.http.OkHttpUtilsKt.text$default(OkHttpUtils.kt:102) - at io.legado.app.help.http.OkHttpUtilsKt.newCallStrResponse(OkHttpUtils.kt:78) - at io.legado.app.help.http.OkHttpUtilsKt$newCallStrResponse$1.invokeSuspend(OkHttpUtils.kt) - at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) - at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) - at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571) - at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750) - at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678) - at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665) -``` - -**Expected behavior 期待修复的效果** -可以正常显示章节文本 - -**Screenshots 如有必要,可以截图说明** - - -**版本说明** - - OS: [e.g. win] Linux - - Deploy Method Docker - - Program Version 3.2.13 - - Browser [e.g. chrome, safari] Chrome - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #645 [server]翻页模式bug - -原始链接:https://github.com/hectorqin/reader/issues/645 -创建:2025/4/7 16:48:19;关闭:2026/9/23 9:16:52;原因:not_planned;历史评论总数:3。时间为 UTC。 - -“上下滑动”翻页模式在章末会有大片的空白。 - -版本说明 - - - OS: [iOS] - - Deploy Method docker - - Program Version v3.2.13 - - Browser [safari] - -## #644 docker版目录 - -原始链接:https://github.com/hectorqin/reader/issues/644 -创建:2025/4/7 5:21:03;关闭:2026/9/23 9:16:51;原因:not_planned;历史评论总数:4。时间为 UTC。 - -大佬你好,请问能否重置或指定nas里的目录,而不是root里面,就是扫描nas本地目录,从而添加书籍 - -## #642 每次升级版本就会把之前上传的小说重置 - -原始链接:https://github.com/hectorqin/reader/issues/642 -创建:2025/4/6 1:39:55;关闭:2026/9/23 9:16:51;原因:not_planned;历史评论总数:1。时间为 UTC。 - -我用docker安装的,每次升级版本就会把之前上传的小说重置 - -![Image](https://github.com/user-attachments/assets/91522c5e-2f84-4542-8fd5-a24374d109fd) - -## #643 过滤规则:是否能够将文本替换为换行 - -原始链接:https://github.com/hectorqin/reader/issues/643 -创建:2025/4/6 5:27:27;关闭:2026/9/23 9:16:51;原因:not_planned;历史评论总数:0。时间为 UTC。 - -我要将两个空格替换为换行,我在过滤规则中使用了/n , /r, /r/n,启动或是关闭“使用正则表达式”,都不成功,都是直接将两个空格替换为了/n , /r, /r/n的文本,请问过滤规则能够实现将文本替换为换行吗 - -## #638 web/server 书架过大的时候会出现超时 - -原始链接:https://github.com/hectorqin/reader/issues/638 -创建:2025/3/20 12:30:45;关闭:2026/9/23 9:16:50;原因:not_planned;历史评论总数:1。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -无法加载书架数据,导致无法查看书籍 - -2025-03-20 20:14:11 [09201f70] [DefaultDispatcher-worker-4] INFO c.h.r.api.controller.BaseController - Loop: 3681 concurrentCount: 16 lastIndex: 58910 endIndex: 58917 costTime: 37853 ms deferredList size: 0 -2025-03-20 20:14:11 [09201f70] [DefaultDispatcher-worker-4] INFO c.h.r.api.controller.BaseController - Loop: 3682 concurrentCount: 6 lastIndex: 58916 endIndex: 58917 costTime: 37863 ms deferredList size: 0 -2025-03-20 20:14:12 [09201f70] [DefaultDispatcher-worker-4] INFO i.v.e.w.h.impl.LoggerHandlerImpl - 10.0.3.1 - - [Thu, 20 Mar 2025 12:13:32 GMT] "GET /reader3/getBookshelf?refresh=0&v=1742472812088 HTTP/1.1" 200 40385249 "https://公网IP/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" -2025-03-20 20:14:12 [1e01fe14] [vert.x-eventloop-thread-0] INFO c.h.reader.verticle.RestVerticle - 客户端已断开链接,终止运行 - -![Image](https://github.com/user-attachments/assets/ceb65b7c-21d0-48a0-81e8-36327dff856b) -超时后,后端设定会报红 - -![Image](https://github.com/user-attachments/assets/e1df17c3-76bb-4427-99a9-5d729379c8c8) -我的书架文件bookshelf大概有60M - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -进入页面开始加载书架就会出现,完全无法加载书籍 - -**Expected behavior 期待修复的效果** -希望书架信息可以在项目启动时预加载到缓存中,更新数据的时候,对缓存也进行更新删除操作 - -**版本说明** - - OS: [e.g. win] 说明操作系统 - - linux - - Deploy Method 说明软件部署方式 - - docker - - Program Version 说明软件版本 - - 3.2.12 - - Browser [e.g. chrome, safari] 说明终端、浏览器型号 - - chrome - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #641 [server] 关于自动同步配置造成的问题 - -原始链接:https://github.com/hectorqin/reader/issues/641 -创建:2025/4/5 16:16:26;关闭:2026/9/23 9:16:50;原因:not_planned;历史评论总数:0。时间为 UTC。 - -在同时打开“自动同步”和配置方案“自动切换”时,自动切换日/夜模式会失效。 - -表现为在冷启动时,先获取了系统的深色模式,再触发了自动同步,同步后把在系统获取到的深色模式覆盖掉了。 - - -**版本说明** - - OS: [iOS] - - Deploy Method docker - - Program Version v3.2.13 - - Browser [safari] - -## #637 每过一段时间,都会自动删除我使用的账号 - -原始链接:https://github.com/hectorqin/reader/issues/637 -创建:2025/3/15 9:08:22;关闭:2026/9/23 9:16:49;原因:not_planned;历史评论总数:6。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -1.每过一段时间没登录,都会自动删除我使用的账号,登录提示账号未注册 -2.重新注册同名账号后,所有数据都在,仅仅是账号莫名其妙消失了 -3.大概每过1个月左右?如果没登录的话,账号就不见了,并且我并未设置多少天未登录自动删除账号这个环境变量 - -**To Reproduce 如何重现问题** -1.重现过两次,每次都是长时间未登录,然后账号消失,但账号的数据却又都在 - -**Expected behavior 期待修复的效果** -1.希望能找到账号被删除的原因,毕竟我并未设置“**天未登录就自动删除”的环境变量,还是说docker在未设置环境变量的情况下,本身就默认自带“30天未登录就删除账号”这个环境变量?我用了几年了,记得以前不会的,不知道从去年哪个版本开始就开始会删账号了 - -**版本说明** -UNRAID系统下,docker部署 - - - - -## #636 阅读epub时,iframe和解析模式的bug - -原始链接:https://github.com/hectorqin/reader/issues/636 -创建:2025/3/12 4:43:30;关闭:2026/9/23 9:16:49;原因:not_planned;历史评论总数:0。时间为 UTC。 - - -**Describe the bug 描述你遇到的问题** -阅读epub时,iframe和解析模式的bug - -**To Reproduce 如何重现问题** -1. 将epub解析设置成iframe模式 -2. 显示为这样(标题和图片重叠,字体样式有问题) -![Image](https://github.com/user-attachments/assets/f684880c-f806-4b9a-9c65-d622a1224447) -3.shitf+f5忽略缓存刷新后,将epub解析设置为解析模式 -4.显示正常 -![Image](https://github.com/user-attachments/assets/9b06e98c-fccb-4c12-ad88-5d037d8c963c) -5.点击下一章或者刷新页面后,格式错乱(之后无论怎么刷新或者切换解析模式都是错乱的) -![Image](https://github.com/user-attachments/assets/d7db2f09-558a-4244-938c-7cfb00b95726) -6.将epub解析再次设置为iframe模式,shitf+f5忽略缓存刷新,之后再将epub解析设置为解析模式。显示正常 -但是点击下一章或者刷新页面后还是格式错乱 -结论:只有将epub解析设置成iframe模式后shitf+f5忽略缓存刷新,再设置成解析模式,才能出现一次正常显示的页面,之后无论点击下一章还是刷新页面都是错乱的,需要重复此步骤才能再次正常显示 - - -**Expected behavior 期待修复的效果** -设置成解析模式时无论点击下一章还是刷新页面都正常显示 - -**版本说明** - - OS: LINUX - - Deploy Method: docker - - Program Version : v3.2.12 - - Browser : chrome浏览器(https访问) - -**Additional context 其他说明** -epub文件(下载后解压): -[epub文件.zip](https://github.com/user-attachments/files/19202858/epub.zip) - -## #635 在Arc浏览器使用reader的朗读功能,跳到下一章的时候,总是从文章的中间开始。 - -原始链接:https://github.com/hectorqin/reader/issues/635 -创建:2025/3/10 2:07:11;关闭:2026/9/23 9:16:48;原因:not_planned;历史评论总数:3。时间为 UTC。 - -在Arc浏览器使用reader的朗读功能,跳到下一章的时候,总是从文章的中间开始,~~但是使用chrome并没有这个问题~~(听了一上午的chrome,也发现存在这个问题),可以随意复现。 - -**版本说明** - - macos Sonoma 14.0 - - docker本地部署 - - 软件版本:V3.2.12-12171550 - - arc版本:版本1.85.0 (59596) - - 内核:Chromium Engine Version 134.0.6998.45 - - -## #632 当使用mongo数据库时,依然会丢失书源 - -原始链接:https://github.com/hectorqin/reader/issues/632 -创建:2025/3/5 7:05:09;关闭:2026/9/23 9:16:48;原因:not_planned;历史评论总数:1。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -A clear and concise description of what the bug is. 简洁有效的说明。 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior 期待修复的效果** -A clear and concise description of what you expected to happen. 简单描述。 - -**Screenshots 如有必要,可以截图说明** -If applicable, add screenshots to help explain your problem. - -**版本说明** - - OS: [e.g. win] 说明操作系统 - - Deploy Method 说明软件部署方式 - - Program Version 说明软件版本 - - Browser [e.g. chrome, safari] 说明终端、浏览器型号 - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #634 [web/simple]:kindle 的simple-waeb翻页闪屏 - -原始链接:https://github.com/hectorqin/reader/issues/634 -创建:2025/3/7 16:21:34;关闭:2026/9/23 9:16:48;原因:not_planned;历史评论总数:1。时间为 UTC。 - -kindle在使用simple-web版的网页翻页时会出现闪屏(全屏刷新)问题,但使用正常版网页,并不会出现闪屏。在正常版的网页使用时,将动画时长设定为0,动画速度设定为1000,无闪屏,且使用体验还可以。但是正常版的内存占用太大,使用卡顿。能否增加一个类似的翻页效果,来解决全屏刷新的问题。 - - -**版本说明** - - OS: kindle - - Deploy Method kindle 浏览器 - - Program Version 3.2.12 - - Browser kindle withe paper 5 ,内置浏览器 - -**Additional context 其他说明** -kpw 5有水波纹刷新,也许增加一个类似的动画。 - -## #630 从书仓导入PDF文件,大部分页面变成空白 - -原始链接:https://github.com/hectorqin/reader/issues/630 -创建:2025/3/1 3:32:22;关闭:2026/9/23 9:16:47;原因:not_planned;历史评论总数:0。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -从书仓导入PDF文件,大部分页面变成空白。 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior 期待修复的效果** -A clear and concise description of what you expected to happen. 简单描述。 - -**Screenshots 如有必要,可以截图说明** -If applicable, add screenshots to help explain your problem. - -**版本说明** - - OS: [e.g. win] MacOS 15.3.1 - - Deploy Method 群晖docker - - Program Version v3.2.12-12171550 - - Browser [e.g. chrome, safari] safari - -Image - -Image - -Image - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #626 希望把java端整合在setup - -原始链接:https://github.com/hectorqin/reader/issues/626 -创建:2025/2/8 8:42:02;关闭:2026/9/23 9:16:47;原因:not_planned;历史评论总数:0。时间为 UTC。 - -希望把java端整合在setup,不是每个人都需要java,只是为了方便使用reader,而单独去安装一个java,没必要。这里指win端 ,web端还好,可以用apt,yum等直接安装,而且作者给的123盘的java链接已经失效 - -## #624 翻页。。。在平板上不行啊,上下页不衔接 - -原始链接:https://github.com/hectorqin/reader/issues/624 -创建:2025/1/28 2:31:18;关闭:2026/9/23 9:16:46;原因:not_planned;历史评论总数:2。时间为 UTC。 - -翻页。。。在平板上不行啊,上下页不衔接 - -## #622 可以隐藏任务栏吗 - -原始链接:https://github.com/hectorqin/reader/issues/622 -创建:2025/1/13 1:29:58;关闭:2026/9/23 9:16:46;原因:not_planned;历史评论总数:0。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 -2. 你确定已有的issue不能解决你的问题 -3. 你确定issue的title按照格式如下:[web/simple-web/server]:description - -**Describe the bug 描述你遇到的问题** -A clear and concise description of what the bug is. 简洁有效的说明。 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior 期待修复的效果** -A clear and concise description of what you expected to happen. 简单描述。 - -**Screenshots 如有必要,可以截图说明** -If applicable, add screenshots to help explain your problem. - -**版本说明** - - OS: [e.g. win] 说明操作系统 - - Deploy Method 说明软件部署方式 - - Program Version 说明软件版本 - - Browser [e.g. chrome, safari] 说明终端、浏览器型号 - -**Additional context 其他说明** -Add any other context about the problem here. 添加你认为有必要的内容,否则不写。 - - -## #623 [web]:IOS设备使用safari等webkit内核浏览器在最新版本系统中无法使用大声朗读\httpTTS的tts - -原始链接:https://github.com/hectorqin/reader/issues/623 -创建:2025/1/18 15:57:29;关闭:2026/9/23 9:16:46;原因:not_planned;历史评论总数:4。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -IOS设备使用safari等webkit内核浏览器在最新版本系统中无法使用大声朗读\HTTPTTS的tts - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. 打开任意文字内容 -2. 打开TTS版面 -3. 朗读方式选取大声朗读或者httpTTS(已经配置好AZURE TTS) -4. 点击开始按钮,按钮没有变成暂停键,同时文字TTS部分被标红,就没有任何反应了 - -**Screenshots 如有必要,可以截图说明** - -![Image](https://github.com/user-attachments/assets/7ae699e4-4387-4804-bd85-13bbd39f9391) - -![Image](https://github.com/user-attachments/assets/b33fbf53-fb13-4927-82b8-e3920335d696) - -**版本说明** - - OS:iPhone/iPad iOS18.2 - - Deploy Method :Docker In DSM7.2.2 - - Program Version :3.2.12 - - Browser :iOS浏览器:safari,firefox,chrome,edge - -**Additional context 其他说明** -经过穷举法,目前测试出只有夸克可以正常播放(见下图),理论上应该也是Webkit内核才对,原因不明 -其他所有设备都能正常播放。 - -![Image](https://github.com/user-attachments/assets/8e3a8172-d011-4dd3-acef-1d7c0e479d18) - -## #618 删除书籍后,assets目录下的export与cover未删除 - -原始链接:https://github.com/hectorqin/reader/issues/618 -创建:2024/12/17 0:30:16;关闭:2026/9/23 9:16:45;原因:not_planned;历史评论总数:0。时间为 UTC。 - -点击导入书籍,上传txt格式的书,设置了封面,然后导出epub,之后删除这本书,发现`assets/用户/export `里面曾经导出过的epub文件还残留, `assets/用户/cover`里面曾经上传的封面图片还在,书多了以后,这些残留资源该如何清理? - -## #616 大声朗读局域网IP可以使用,使用花生壳域名访问无法使用 DMZ主机是开着的 - -原始链接:https://github.com/hectorqin/reader/issues/616 -创建:2024/12/16 7:19:44;关闭:2026/9/23 9:16:45;原因:not_planned;历史评论总数:8。时间为 UTC。 - -能不能让大声朗读不要用梯子也可以使用 - -## #613 分享一个自定义Docker TTS 语音项目 可配 web TTS 朗读 - -原始链接:https://github.com/hectorqin/reader/issues/613 -创建:2024/12/7 15:44:54;关闭:2026/9/23 9:16:44;原因:not_planned;历史评论总数:15。时间为 UTC。 - -项目 https://github.com/zuoban/tts?tab=readme-ov-file - -使用方法 -1、自行配置上述Docker -2、打开本项目reader的web页面,随便点开一部小说,然后点朗读图标 -3、点击HttpTTS添加,弹出的默认示例中名字可以自己定义,其他不需要输入,url输入这个 -`http://192.168.1.X:8080/tts?t={{java.encodeURI(speakText)}}&v=zh-CN-YunxiNeural&r={{java.encodeURI(speakSpeed)}}*4&p=0&o=audio-24khz-48kbitrate-mono-mp3` - -``` -参数列表: -1. t: 文本内容 (必填) -2. v: 语音名称 (可选), 默认为 zh-CN-XiaoxiaoMultilingualNeural -3. r: 语速 (可选), 默认为 0 -4. p: 语调 (可选), 默认为 0 -5. o: 输出格式 (可选), 默认为audio-24khz-48kbitrate-mono-mp3 -``` - - -## #614 数据库+redis方案 - -原始链接:https://github.com/hectorqin/reader/issues/614 -创建:2024/12/11 2:44:22;关闭:2026/9/23 9:16:44;原因:not_planned;历史评论总数:1。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -自部署版本在导入书源、校验书源等步骤时运行卡顿,且消耗内存过大 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. 导入书源 -2. 选择本地书源文件导入(json格式) - -或 - -1. 失效书源 -2. 检测书源 - -**Expected behavior 期待修复的效果** -1. 在检测书源是否失效页面增加 `停止` 、`取消` 按钮,点击取消能取消全部操作,点击停止能停止校验(已校验过的结果保留) -![image](https://github.com/user-attachments/assets/9c3e0c70-2ca9-4e51-b042-184aa1601ce8) - -2. 新增连接外置数据库方法及说明,如MySQL、Postgres、Mongo、Sqllite等 - -3. 新增连接外置redis加快缓存速度 - -**版本说明** - - OS: 群晖Synology - - Deploy Method :Docker - - Program Version :3.2.11 - - Browser :Chrome - -**Additional context 其他说明** -1. 建议隐藏 `后端设定` 选项,改错了前端容易崩溃 -![image](https://github.com/user-attachments/assets/aa2afbb4-d0da-43a6-a6e4-f229ed749047) -2. `WdbDav` 增加 `坚果云` 等第三方远程连接方式,以便和手机端通过第三方同步 -3. `其它` 改为 `关于` 并排版到最下面(与Github链接合并) -![image](https://github.com/user-attachments/assets/5697a718-8ba0-4239-941b-7980caf21c6d) - - -## #608 服务器版手机 edge 浏览器自带大声朗读无法播放 - -原始链接:https://github.com/hectorqin/reader/issues/608 -创建:2024/11/11 13:21:53;关闭:2026/9/23 9:16:43;原因:not_planned;历史评论总数:1。时间为 UTC。 - -服务器版手机端用 edge 浏览器自带大声朗读无法播放,不是项目自带的阅读功能,电脑上面没问题![Screenshot_2024-11-11-21-13-32-293_com.microsoft.emmx.jpg](https://github.com/user-attachments/assets/647576fc-05b2-408a-8ac2-ef560e3857dc) - -用 legado 的 app web 服务来链接到 reader3 上就没问题![IMG_20241111_213707.jpg](https://github.com/user-attachments/assets/072a5414-fd4e-453e-9a84-50a081404130) - -![Screenshot_2024-11-11-21-34-24-932_com.microsoft.emmx.jpg](https://github.com/user-attachments/assets/52d881e5-fdfc-48bb-8374-9c35df9914a6) - - -还有目录加载速度很慢 - -## #601 添加本地书籍报错 获取章节内容失败! 章节文件不存在 - -原始链接:https://github.com/hectorqin/reader/issues/601 -创建:2024/10/30 20:45:25;关闭:2026/9/23 9:16:43;原因:not_planned;历史评论总数:3。时间为 UTC。 - - -![image](https://github.com/user-attachments/assets/f9aa7db0-553d-4c83-9c26-c6fde4eba7fe) - - -## #596 页面显示的章节与打开书籍后显示的章节不一致 - -原始链接:https://github.com/hectorqin/reader/issues/596 -创建:2024/10/22 11:50:07;关闭:2026/9/23 9:16:43;原因:not_planned;历史评论总数:0。时间为 UTC。 - -1.问题描述 -页面显示的章节与打开书籍后显示的章节不一致 - -2.问题发生的位置 -安卓APP和本项目网页端 - -3.问题的详细描述 -手机端阅读APP设置webdav同步,安卓APP和网页端均能正常同步章节。但是在点击进入书籍后,打开的章节与显示的不一致。 - -4.问题复现 -手机端阅读APP阅读至543章,点开网页发现能正常同步进度 -1 - -但是点开书籍后显示的章节却是536章 -2 -注:手机端安卓APP和网页端均存在该问题。 - - - - -**版本说明** -安卓阅读APP 3.23.031210 -本项目的版本 v3.2.10-07270648 -浏览器 火狐、Safari -部署方式docker - - - - -## #594 【建议】希望编辑后可以永久生效,而不是刷新后就会失效 - -原始链接:https://github.com/hectorqin/reader/issues/594 -创建:2024/10/13 4:20:05;关闭:2026/9/23 9:16:42;原因:not_planned;历史评论总数:0。时间为 UTC。 - -![1728792866759](https://github.com/user-attachments/assets/ed88e1dc-cef0-4b0f-99e3-47d95f02fac6) -![1728792885992](https://github.com/user-attachments/assets/3c7c4e71-8687-49a3-bc17-df3920183667) -因为小说内容可能会有错别字或者乱码之类的,我看到了就想手动改掉或者删除,但是现在这个编辑功能就有点鸡肋,没什么实际效果【感觉只是改了HTML,变更的内容并没有真的保存起来】,刷新页面又出来了 - -## #590 请教下各位书友httptts 怎么配置 - -原始链接:https://github.com/hectorqin/reader/issues/590 -创建:2024/9/24 6:30:13;关闭:2026/9/23 9:15:23;原因:not_planned;历史评论总数:1。时间为 UTC。 - -(无正文) - -## #585 是否能修改下翻页的一个问题,章尾最后一页的排版,最后一行字始终是在页面最底部 - -原始链接:https://github.com/hectorqin/reader/issues/585 -创建:2024/8/30 13:01:21;关闭:2026/9/23 9:15:22;原因:not_planned;历史评论总数:0。时间为 UTC。 - -当阅读到章尾时,最后一页的最后一行字始终是在页面最底部,而不是依据上一页最后内容来排版 -这样每次到章尾时,眼睛都要上下扫扫,才能找刚才看到哪了 - -图一为 上一页最后内容 -![1](https://github.com/user-attachments/assets/7fd97a48-ee0b-42b9-ab42-55aa21d7927a) - -图二为 最后一页排版 -![2](https://github.com/user-attachments/assets/be94b45a-3862-4c20-a923-e288599d46eb) - -图三 希望能把上一页已阅读的内容隐藏了 -![3](https://github.com/user-attachments/assets/05f27315-f1ef-4c91-99a3-e3f58e11f1ed) - - -## #588 windows桌面版和安卓app版怎么和服务端连接 - -原始链接:https://github.com/hectorqin/reader/issues/588 -创建:2024/9/8 16:49:23;关闭:2026/9/23 9:15:22;原因:not_planned;历史评论总数:6。时间为 UTC。 - -windows桌面版和安卓app版怎么和服务端连接呢,想要app或者桌面上看服务端上本地传了书 - -## #584 建议增加标题的替换功能 - -原始链接:https://github.com/hectorqin/reader/issues/584 -创建:2024/8/29 2:30:02;关闭:2026/9/23 9:15:21;原因:not_planned;历史评论总数:0。时间为 UTC。 - -建议增加标题的替换功能,方便正则去除求月票、求订阅、XX加更之类的内容 - -## #580 v3.2.10版本问题汇总 - -原始链接:https://github.com/hectorqin/reader/issues/580 -创建:2024/8/15 13:43:35;关闭:2026/9/23 9:15:21;原因:not_planned;历史评论总数:5。时间为 UTC。 - -1.键盘->下一章出现跳章问题,目前最大跳四章; -2.朗读时候最小化状态切换下一章不是从章头开始朗读(历史版本一直存在此问题); - -## #573 [web]:切换书源界面功能强化-章节关键字搜索以及显示字数 - -原始链接:https://github.com/hectorqin/reader/issues/573 -创建:2024/8/2 9:28:42;关闭:2026/9/23 9:15:21;原因:not_planned;历史评论总数:2。时间为 UTC。 - - -**Describe the bug 描述你遇到的问题** -希望可以象Legado 阅读一样,在切换书源时,可以直接搜索关键字(这样可以搜出已经更新出最新章节的源)并显示章节字数(这样可以知道哪些源是真正更新了该章内容的,那种只有几十个字百来个字的显然不合格) - -以下是Legado阅读和reader相关界面的对比: -![tempImageDPoIDx](https://github.com/user-attachments/assets/6e145a83-0d4e-4d24-890f-1c8ab41ba55a) -![Longshot-20240802172024](https://github.com/user-attachments/assets/4c7289b9-e007-4b27-b8b0-418d1e3436b5) - -**版本说明** - - OS: [e.g. win] MacOS最新 - - Deploy Method: Docker - - Program Version:最新 - - Browser [e.g. chrome, safari] MacBook Pro, Safari - - - -## #539 希望优化翻页方式(滚动) - -原始链接:https://github.com/hectorqin/reader/issues/539 -创建:2024/6/4 10:26:30;关闭:2026/9/23 9:15:20;原因:not_planned;历史评论总数:4。时间为 UTC。 - - -翻页方式-滚动翻页,全屏点击-不翻页后。手机触摸滚动屏幕时候偶尔还是会触发整页翻动。希望优化成手机触摸滚动屏幕不要触发页面跳转。 - -## #536 希望优化翻页 - -原始链接:https://github.com/hectorqin/reader/issues/536 -创建:2024/6/1 8:30:38;关闭:2026/9/23 9:15:20;原因:not_planned;历史评论总数:4。时间为 UTC。 - -翻页功能能否自定义,不要一点击屏幕就自动跳转翻页。手机使用经常不小心点击到就跳转了其他内容 - -## #523 Kindle的浏览器打不开 - -原始链接:https://github.com/hectorqin/reader/issues/523 -创建:2024/5/8 6:01:02;关闭:2026/9/23 9:15:19;原因:not_planned;历史评论总数:5。时间为 UTC。 - -如题 -然后在reader里点7天试用,邮箱填了收不到验证码邮件 - -## #529 [web/server]: “上下滚动”的翻页方式会导致切换书的时候页面空白 - -原始链接:https://github.com/hectorqin/reader/issues/529 -创建:2024/5/26 20:13:27;关闭:2026/9/23 9:15:19;原因:not_planned;历史评论总数:3。时间为 UTC。 - -使用 “上下滚动”的翻页方式切换书的时候,必然出现三种情况中一种: -1. 点进去的时候当前章节内容部分会变成空白,需要手动在章节列表点击具体章节,或用快捷键切换到下一章才能正常显示。 -2. 点进去的时候当前章节内容部分先是依然是上本书的章节内容,卡顿几秒后跳转到新书的某个章节,该章节可能是上上次阅读到的位置,或别的设备阅读到的位置,而不是书架中显示的最新的阅读进度(书架中显示的最新的阅读进度是正确的)。随后书架中显示的最新的阅读进度也变成了这个随机章节。 -3. 当前章节内容部分能正常显示,但是章节列表变成空白,也无法用快捷键切换到下一章,需要手动刷新章节列表。 - -书均为来自本地书仓的txt文件。 - -当选择“上下滑动”翻页方式的时候,则没有任何问题。 - -**版本说明** - - OS: 群晖 - - Deploy Method: Docker - - Program Version: 3.2.8 - - Browser: Safari, macOS - - -## #519 使用nginx反向代理的redaer自带webdav作为阅读3.0的备份服务器,在阅读3.0导入远程书籍时显示超时 - -原始链接:https://github.com/hectorqin/reader/issues/519 -创建:2024/4/30 16:23:36;关闭:2026/9/23 9:15:19;原因:not_planned;历史评论总数:5。时间为 UTC。 - -### 确认 / Assignments - -- [X] 搜索现有issues,不存在相似或相关的issue / No similar or related issues -- [X] 最新[测试版](https://github.com/gedoor/legado/actions/workflows/test.yml)依然存在此问题 / Latest beta app does not work -- [X] 此问题和Xposed、Lsposed、Magisk、手机主题、浏览器插件等无关 / Make sure your machine is not touched by hook frameworks, plugins etc - -### 问题描述 / Describe Bugs - -自己使用docker搭建的reader服务器,使用其自带的webdav作为书库。经过nginx反向代理为子目录访问,访问链接为https://test.com:1122/dav/。可以正常备份和恢复,本地书籍或缓存好的书籍可以正常导入至webdav。在远程书籍中也能够看到目录下的书籍,但是从远程书籍导入时失败,日志显示导入出错,timeout。查看nginx日志,access.log中只有一条记录"PROPFIND /dav/reader3/webdav/legado/books HTTP/1.1" 207 22862 "-" "Chrome/119.0.0.0 Safari/537.36 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"。error.log中无任何记录。当代理为location /{}时情况一样。 - - -我的nginx设置为: -server { - #添加加ssl和http2协议的要求。 - listen 11loca22 ssl ; #ipv4 - #修改为自己申请的域名 - server_name test.com; - ###添加秘钥 - # Mozilla Intermediate configuration - ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; - #以下协议需要确认硬件是否支持,如果不支持或者不确定可以直接去除 - ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; - #以下修改为自己申请的域名公钥和私钥文件地址 - ssl_certificate ; - ssl_certificate_key ; - ############## - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 10m; - if ($server_port !~ 1122){ - rewrite ^(/.*)$ https://$host$1 permanent; - } - error_page 497 https://$host$request_uri; - -location / { - -} - - location /dav/ { -##### - gzip on; #开启gzip压缩 - gzip_min_length 1k; #设置对数据启用压缩的最少字节数 - gzip_buffers 4 16k; - gzip_http_version 1.0; - gzip_comp_level 6; #设置数据的压缩等级,等级为1-9,压缩比从小到大 - gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; #设置需要压缩的数据格式 - gzip_vary on; - client_max_body_size 50m; #允许上传50MB文件,上传本地书籍需要修改此项大小.如nginx主配置文件已添加,删除此行并修改主配置即可 -#修改为自己需要代理的局域网ip和端口号 - proxy_pass http://112.128.1.21:1122/; #阅读 - proxy_http_version 1.1; - proxy_cache_bypass $http_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Port $server_port; - } - - access_log /var/log/nginx/access.log; #; - error_log /var/log/nginx/error.log; # ; -} - - - - - -### 复现步骤 / How to reproduce - -每次使用都是如此 - -### 确认 / Assignment - -- [X] 已经提交复现所需要的附加资料 / Submit additions related with bugs - -### 其他信息 / Additions - -_No response_ - -### 日志提交 / Relevant log output - -_No response_ - -### 阅读版本 / Legado version - -3.23.110211 - -### Android版本 / Android version - -HarmonyOS 4.0.0 - -### 机型 / Model - -HUAWEI Mate 40 - -## #513 书源失效时服务器缓存不起作用 - -原始链接:https://github.com/hectorqin/reader/issues/513 -创建:2024/4/5 15:38:10;关闭:2026/9/23 9:15:18;原因:not_planned;历史评论总数:1。时间为 UTC。 - -发现书源失效的时候之前浏览过的小说就看不了了, -即使在内容已经缓存在服务器的情况下 -![屏幕截图 2024-04-05 233558](https://github.com/hectorqin/reader/assets/31752207/5a2037ae-b60d-4ba6-b44e-92988278e2a0) -在缓存文件夹有内容的情况下,无法设置启用缓存数据代替书源数据 - -## #512 竖排书籍无法正常翻页 - -原始链接:https://github.com/hectorqin/reader/issues/512 -创建:2024/4/3 14:01:34;关闭:2026/9/23 9:15:18;原因:not_planned;历史评论总数:1。时间为 UTC。 - -竖排书籍无法正常翻页,只能左右滑动,导致无法存储位置。 -点击翻页区域,直接跳到上一章或者下一章。 - -以下为提供的竖排epub书籍: - -[越女剑.epub](https://alist.toyqiu.cc:999/d/nas/eBooks/CalibreWeb/Jin%20Yong/Yue%20Nu%20Jian%20(1005)/Yue%20Nu%20Jian%20-%20Jin%20Yong.epub?sign=UPpc4qt_BHHbDRf7MrN1fxDYQQL9EpN5JuR4Ycirf_I=:0) - -[かばん屋の相続.epub](https://alist.toyqiu.cc:999/d/nas/eBooks/CalibreWeb/Chi%20Jing%20Hu%20Run/kabanWu%20noXiang%20Sok%20(1189)/kabanWu%20noXiang%20Sok%20-%20Chi%20Jing%20Hu%20Run.epub?sign=0G2nvkOdPz-yNCGUNCrXiwBo3ZMcrRzv5S4zrlf7IVM=:0) - -## #498 书籍目录无法获取完整 - -原始链接:https://github.com/hectorqin/reader/issues/498 -创建:2024/2/29 12:35:23;关闭:2026/9/23 9:15:17;原因:not_planned;历史评论总数:11。时间为 UTC。 - -**为避免无效问题和冗余问题,提问前请确认** -1. 你确定Google不能解决你的问题 是 -2. 你确定已有的issue不能解决你的问题 是 - -**Describe the bug 描述你遇到的问题** - -- **部分epub书籍的目录在sigil,calibre-web中可以正常识别目录结构,但是这里并不能完整提取** - -![Snipaste_2024-02-29_20-31-20](https://github.com/hectorqin/reader/assets/52244378/452d28f7-5b87-4f74-8377-a18b1ac4e53e) -![Snipaste_2024-02-29_20-26-53](https://github.com/hectorqin/reader/assets/52244378/b3c5e92d-ae48-402a-a98a-f57199a0c346) -![Snipaste_2024-02-29_20-25-27](https://github.com/hectorqin/reader/assets/52244378/c3974a5f-6e97-404f-b036-972b80c7bcc2) - -**版本说明** - - OS: [e.g. win] 说明操作系统:ubuntu 22.04 - - Deploy Method 说明软件部署方式: docker compose - - Program Version 说明软件版本:v3.2.7-01010833 - - -## #491 请问怎么设置单次搜索次数?现在需要一直点击加载更多 - -原始链接:https://github.com/hectorqin/reader/issues/491 -创建:2024/2/6 10:39:25;关闭:2026/9/23 9:15:17;原因:not_planned;历史评论总数:2。时间为 UTC。 - -找了下文档和docker的yaml没看到描述此类的配置项,有些书书源多点方便换源,感觉服务器这块,直接检索完全部书源也不是不可以,是否有这个功能呢,有的话在哪里配置呢 - -## #486 [server]:有充足内存的情况下报错OutOfMemoryError - -原始链接:https://github.com/hectorqin/reader/issues/486 -创建:2024/1/24 13:09:41;关闭:2026/9/23 9:15:16;原因:not_planned;历史评论总数:4。时间为 UTC。 - -**Describe the bug 描述你遇到的问题** -有充足内存的情况下报错OutOfMemoryError ,类似于 #429 ,但明确并非真的发生了内存不足 - -**To Reproduce 如何重现问题** -Steps to reproduce the behavior: 把你遇到的问题的发生步骤替换掉下面的内容: -1. 使用docker运行[reader](https://github.com/hectorqin/reader),并限制内存为2G -2. 对内存占用进行监测 -3. 使用10并发进行书源检测 -4. 大量请求无返回,达到超时请求后失败;查看日志发现大量报错OutOfMemoryError,但此时仍有充足内存供使用。 -log如:Exception in thread "DefaultDispatcher-worker-xx" java.lang.OutOfMemoryError: Java heap space - -**Expected behavior 期待修复的效果** -在用完或接近用完时再报错OutOfMemoryError,方案为增加自定义堆内存大小,如允许在JVM启动时指定参数且不会被脚本覆盖 -`-Xmx2048m`,如在下面这行就会和手动设置的内存数冲突。 - -https://github.com/hectorqin/reader/blob/b3f580f49385376b88f92818b5a9dfa874e1f80f/server/bin/startup.sh#L96 - -**Screenshots 如有必要,可以截图说明** -容器内存情况 -![image](https://github.com/hectorqin/reader/assets/44089074/9adbb302-5bc5-4672-9cc1-9bbb1e748acb) -宿主机内存情况 -![image](https://github.com/hectorqin/reader/assets/44089074/be0427bf-20d3-4878-b7ac-e3bf8dde8a6b) -日志 -![image](https://github.com/hectorqin/reader/assets/44089074/b2df2c30-e64a-4035-8612-544bfb71f11b) - - -**版本说明** - - OS: Ubuntu 22.04 - - Deploy Method: Docker - - Program Version: `v3.2.7-01010833` - - Browser: Google Chrome v120 - - -## #484 书籍列表分页的问题 - -原始链接:https://github.com/hectorqin/reader/issues/484 -创建:2024/1/18 3:25:31;关闭:2026/9/23 9:15:16;原因:not_planned;历史评论总数:5。时间为 UTC。 - -我采用了reader的docker last版本,然后导入了本地9000多本书籍 -当我进入书籍页面后发现,加载书籍列表需要非常长的时间(测试估计在30秒左右) -然后我看了一下请求,发现 getbookshelf接口的确没有进行分页,而是将所有的书籍返回 - -是否有计划下一步进行更新? - -![image](https://github.com/hectorqin/reader/assets/8120401/27901d59-1577-413f-8015-9d80ee78844d) - -![image](https://github.com/hectorqin/reader/assets/8120401/0cbb4687-629f-445d-8c74-9cde7a41fb58) - - -## #482 IOS, web端, 使用翻页的时候, 下一章的内容会跳转到最后,而不是最前,且语音听书的时候经常会有卡住的情况 - -原始链接:https://github.com/hectorqin/reader/issues/482 -创建:2024/1/17 2:01:59;关闭:2026/9/23 9:15:15;原因:not_planned;历史评论总数:2。时间为 UTC。 - -IOS, web端。 -1、使用翻页的时候, 偶尔会出现下一章的内容会跳转到最后,而不是最前。 -2、语音听书的时候经常会有卡住的情况,需要重新刷新页面才行。 -3、web端上下滑动、上下滚动、翻页的时候会存在翻多页的情况,体验不加。 -4、IOS使用网页浏览,内置的主题切换会导致页面展示出现问题,比如白天我看到第七页换成夜晚就变成了第2页这种。 - -## #475 RSS Feed Bug - -原始链接:https://github.com/hectorqin/reader/issues/475 -创建:2024/1/3 7:47:17;关闭:2026/9/23 9:15:14;原因:not_planned;历史评论总数:1。时间为 UTC。 - -RSS Feed报错: -org.xmlpull.v1.XmlPullParserException: No valid parser classes found in parameter classNames to newInstance() that contained ' org.kxml2.io.KXmlParser org.kxml2.io.KXmlSerializer ' - - -## #463 本地书籍整理功能支持 - -原始链接:https://github.com/hectorqin/reader/issues/463 -创建:2023/11/25 2:46:01;关闭:2026/9/23 9:15:14;原因:not_planned;历史评论总数:1。时间为 UTC。 - -你好,我有1.8G本地书需要整理 -Q1:如果在文件夹里多个txt分别为第一章第二章第三章,必须手动合并到一个txt才能识别?能否能增加功能支持 - -Q2:本地一个分组就有上百本书籍,能否增加本地搜索支持 - -Q3:本地txt添加不同分组导入后,发现他存到了reader\storage\data\default文件夹,但是我本地有1.8G的TXT,也按照分类分好文件夹了,能否出个调用本地文件夹的功能,这样数据就不用再存到reader文件夹下,如果必须存,能否将default文件夹内加上分组文件夹,这样我就把本地txt删了 - -## #454 可不可以加入背景透明化 - -原始链接:https://github.com/hectorqin/reader/issues/454 -创建:2023/11/6 6:53:57;关闭:2026/9/23 9:15:14;原因:not_planned;历史评论总数:1。时间为 UTC。 - -类似于这位开发的背景虚化功能 -https://github.com/binbyu/Reader/blob/master/README.md - -## #453 发一下windows Java安装教程 - -原始链接:https://github.com/hectorqin/reader/issues/453 -创建:2023/11/6 1:12:22;关闭:2026/9/23 9:15:13;原因:not_planned;历史评论总数:0。时间为 UTC。 - -我是小白,之前没接触过需要安装Java的项目,因为安装成功,分享我的步骤。 - -1、下载 Java 8 安装包。可以从 Oracle 官网 https://www.java.com/download/ie_manual.jsp 下载。 - -2、安装 Java 8。安装过程非常简单,只需要按照屏幕上的提示操作即可。 - -3、配置 Java 环境变量。在 Windows 系统中,可以通过以下步骤来配置 Java 环境变量: - -打开控制面板,然后单击“系统”。 -在“系统”窗口中,单击“高级系统设置”。 -在“高级”选项卡中,单击“环境变量”。 -在“系统变量”列表中,单击“新建”。 -在“变量名”框中键入“JAVA_HOME”,在“变量值”框中键入 Java 安装目录的路径。例如,如果 Java 安装目录为 C:\Program Files\Java\jdk1.8.0_271,则变量值为 C:\Program Files\Java\jdk1.8.0_271。 -单击“确定”。 -在“系统变量”列表中,单击“Path”。 -在“变量值”框的末尾添加 %JAVA_HOME%\bin。 -单击“确定”。 -验证 Java 环境是否安装成功。在命令提示符中输入以下命令: - -java -version -如果显示 Java 版本信息,则表示 Java 环境安装成功。 - -需要特别注意的是,在Reader设置,Java路径应当具体到exe文件。列如X:\Java\bin\java.exe - -## #353 WebDAV的疑问 - -原始链接:https://github.com/hectorqin/reader/issues/353 -创建:2023/4/13 14:20:44;关闭:2026/9/23 9:14:41;原因:completed;历史评论总数:27。时间为 UTC。 - -1、阅读APP上WebDAV设置里有个子文件夹,修改这个子文件夹我APP端点备份后会在这个文件夹里生成一个带设备名称的压缩包。而且阅读服务器端点WebDAV保存备份是生成在legado内不带设备名称的压缩包。那服务器端和阅读APP的书籍进度不是存在一个目录内的吗?服务器端好像没有可用修改子文件夹的地方。 -2、阅读APP上有个远程书籍,目录是WebDAV内的books文件夹。我在阅读服务器端上把文件上传到这个目录然后加入书架,但阅读APP上充远程书籍上放入书籍一直提示导入出错这是为什么?有什么方法可以把本地书籍放在WebDAV上然后服务器和APP端都能同步进度的吗? -其次必须阅读APP子文件夹目录修改成默认的legado书架才能同步吗? - -## #339 为用jb的IDE的程序员们开发了个reader的阅读插件 - -原始链接:https://github.com/hectorqin/reader/issues/339 -创建:2023/3/22 15:39:56;关闭:2026/9/23 9:14:25;原因:completed;历史评论总数:5。时间为 UTC。 - -## 在IDE中随时随地阅读,提升编码效率。 -### 同时支持`开源阅读app`和`服务器版阅读` - -都是为了我们程序员能够随时阅读书籍,提升自我 -### 点击链接开始阅读:https://github.com/nancheung/legado-reader - -![image](https://user-images.githubusercontent.com/34061813/226959469-82b4485b-ed3c-4db8-95d1-6f215712abbf.png) - -![image](https://user-images.githubusercontent.com/34061813/226958375-7b44e1e3-52ec-48be-ba8e-a3e89b2e27e9.png) - - -## #720 书源功能建议 - -原始链接:https://github.com/hectorqin/reader/issues/720 -创建:2026/9/22 11:36:32;关闭:2026/9/23 7:14:13;原因:completed;历史评论总数:1。时间为 UTC。 - -之前一直使用旧版本reader,在安装了新版本reader 后,书源的使用遇到困难。 -希望出个书源导入的教程。 - -另外,按照README 来安装,需要修改一下,默认命令无法拉取镜像: -docker run -d --name reader \ - -p 8080:8080 \ - -v /path/to/your/books:/books:ro \ - -v ./data:/data \ - cnb.cool/hectorqin/reader:**main** - -### 近期评论:hectorqin,2026/9/23 7:14:13 -https://github.com/hectorqin/reader/issues/720#issuecomment-5790657565 - -目前还在开发中,未发布镜像,而且目前只聚焦本地书库,是不支持legado书源的。 - -## #719 新版本安装问题及书源导入方法 - -原始链接:https://github.com/hectorqin/reader/issues/719 -创建:2026/9/22 7:34:42;关闭:2026/9/22 8:26:51;原因:completed;历史评论总数:2。时间为 UTC。 - -使用更新后的readme来安装,docker安装时有个问题:拉取不到镜像。使用如下的方式可以拉取 -docker run -d --name reader \ - -p 8080:8080 \ - -v /path/to/your/books:/books:ro \ - -v ./data:/data \ - cnb.cool/hectorqin/reader:_main_ - -另外有个疑问或者说建议: -老版本的书源导入方式,复制链接后就可以自动同步。 -新版本还不知道怎么导入书源。 - -### 近期评论:eking929,2026/9/22 7:35:24 -https://github.com/hectorqin/reader/issues/719#issuecomment-5772817643 - -谢谢你的来信,看到后我会尽快回复! - -### 近期评论:hectorqin,2026/9/22 8:26:51 -https://github.com/hectorqin/reader/issues/719#issuecomment-5773422708 - -新版本目前聚焦本地书库,暂时不考虑支持远程书源相关功能 diff --git a/docs/closed-issues-analysis-2026-09-23.md b/docs/closed-issues-analysis-2026-09-23.md deleted file mode 100644 index f563452..0000000 --- a/docs/closed-issues-analysis-2026-09-23.md +++ /dev/null @@ -1,179 +0,0 @@ -# 最近两天关闭 Issue 的需求方向分析 - -分析日期:2026-09-23(北京时间)。对象:hectorqin/reader 的关闭 issue,以及当前本地工作区代码。 - -## 结论 - -建议以“可靠的个人书库阅读器”为主线:优先保证进度、阅读和数据不会出错,再补齐书内检索、批注、多级目录、缓存管理等日常能力。远程来源继续沿用插件架构,避免把旧版 Legado 的全部兼容性负担重新放回核心。 - -建议顺序:**发布与接入说明 → 阅读/进度可靠性与数据恢复 → 书内搜索、批注和目录 → 朗读与离线体验 → 书源质量与生态互通。** - -下文优先级是根据影响范围、当前基础和产品定位给出的建议,不是维护者已承诺的排期。 - -## 1. 抓取范围与解释 - -- GitHub REST Search:`repo:hectorqin/reader is:issue is:closed closed:>=2026-09-21`,分页抓取 101 条,再核对关闭时间。 -- 以 2026-09-23 17:31 北京时间为分析截止,最近 48 小时内共 101 条;按北京时间 9 月 22—23 日统计结果相同。9 月 22 日 1 条,9 月 23 日 100 条。 -- `state_reason`:97 条 `not_planned`,4 条 `completed`(#339、#353、#719、#720)。旧问题在数分钟内密集关闭,与批量清理历史 backlog 的特征一致;不能解释为两天新增的需求,更不能解释为全部已修复。 -- 完整抓取全部标题、正文、创建/关闭时间、标签和评论数量;另抓取 9 月 21 日起更新的仓库 issue 评论,相关评论为 #719 的 2 条和 #720 的 1 条。**没有抓取全部历史评论,也没有逐一检查图片和附件。** -- 当前能力通过 README、使用手册、架构文档及关键源码交叉核对。没有启动应用执行兼容性测试,因此“已有实现”不等于“已验证旧问题全部消失”。 -- 完整正文和索引见 [issue 存档](closed-issues-2026-09-23/issues.md),结构化数据见 [issues.json](closed-issues-2026-09-23/issues.json)。 - -### 发布口径与工作区能力存在差异 - -[维护者在 #719 的回复](https://github.com/hectorqin/reader/issues/719#issuecomment-5773422708)表示“新版本目前聚焦本地书库,暂时不考虑支持远程书源相关功能”;[在 #720 的回复](https://github.com/hectorqin/reader/issues/720#issuecomment-5790657565)表示“目前还在开发中,未发布镜像……不支持 legado 书源”。 - -本地工作区已包含 local、OPDS、通用进程插件、远程章节、换源和追更。这说明本地开发能力与对外口径需要同步,但不能据此推断公开镜像已经提供这些功能。通用插件能力也不等于原生支持 Legado JSON 书源。 - -## 2. 需求方向与当前差距 - -### A. 安装、迁移和来源接入:P0 - -**依据:** [#719](https://github.com/hectorqin/reader/issues/719)、[#720](https://github.com/hectorqin/reader/issues/720)、#714、#666、#588。 - -**用户目标:** 部署成功后知道如何读到第一本书,旧用户知道哪些数据和书源可以继续使用。 - -**当前基础:** 已有 Docker 入门文档、插件管理 UI、npm/.tgz 安装和来源实例管理。入门文档仍展示 `cnb.cool/hectorqin/reader:latest`,但上述回复称尚未发布镜像;本次未核验镜像仓库标签。 - -**建议需求:** - -1. 明确稳定版、开发版、旧版的入口、镜像标签、能力范围和数据目录,发布前核验文档命令可用。 -2. 首次使用提供本地目录、OPDS、插件三种接入路径,并显示是否配置成功。 -3. Legado JSON/订阅链接导入时给出明确兼容性说明;若由独立插件支持,提供具体插件及安装步骤,不能只提示“添加书源”。 -4. 旧版迁移先明确账号、书架、进度、书源的可迁移范围,再设计预检查和迁移摘要;不能把旧 `/storage` 直接当新 `/data`。 - -**验收:** 新用户按发布文档部署并读到一本书;旧用户能在导入前知道兼容范围;不兼容输入显示可操作的解释。 - -### B. 阅读与进度可靠性:P0 - -**依据:** #702、#698、#696、#692、#687、#663、#655、[#652](https://github.com/hectorqin/reader/issues/652)、#645、#624、#596、#585、#580、#539、#536、#529、#512、#482。 - -**用户目标:** 不跳章、不漏段,换设备或重新打开仍在刚才的位置。 - -**当前基础:** 已有分页/滚动、手势和定位器、跨窗口加载、离线 outbox、按账号同步、按设备保存显示设置。它们是完善和回归的基础,不应重做一套阅读器。 - -**建议需求:** - -1. 将“打开位置正确、翻页连续、退出前保存”作为版本验收门槛,覆盖 iOS Safari、Android WebView 和桌面浏览器。 -2. 明确滚动到章末、点击翻页、键盘和音量键的跨章行为;手势一次只触发一个动作。 -3. 字号、主题、旋转屏幕、工具栏显隐后保留正文锚点,不能靠旧页码恢复位置。 -4. 显示同步状态和失败重试入口;提供进度历史/恢复能力,处理多设备离线后回传旧位置的情况。 - -**验收:** 连续读过章节边界后退出重进,正文位置与书架进度一致;A/B 两设备交替阅读及断网重连不发生无提示回退;切换排版不丢当前段落。 - -### C. 数据保护与大书库:P0/P1 - -**依据:** [#674](https://github.com/hectorqin/reader/issues/674)、#657、#642、#637、#632、#638、[#484](https://github.com/hectorqin/reader/issues/484)、#463、#644、#704、#697、#707、#618、#614。 - -**当前基础:** SQLite、独立 DATA_DIR、直接扫描 BOOKS_DIR、稳定内容身份、元数据覆盖、分页和目录递归筛选已有实现。书架服务默认每页 50、最多 200;不能再把“新增分页”作为空白功能立项。现有备份文档要求停机后复制完整数据目录。 - -**建议需求:** - -1. 提供备份/恢复的产品入口或可靠管理命令,包含账号、进度、笔记、插件配置及一致性校验;恢复前可预览。 -2. 把“文件暂时离线”“索引失效”“账号书架隐藏”“数据损坏”区分显示,提供重扫或恢复路径。 -3. 验证 1 万本及更大书库下首屏、查询、增量扫描和同步性能;前端也要避免一次性载入全部数据。 -4. 增加存储用量、封面/章节/下载缓存分类、日志轮转部署示例与可预览清理。 -5. 本地 TXT 追加更新应考虑版本关系和进度继承。当前内容哈希参与身份,文件内容变化可能成为新副本;“自动重扫”并不自动保证追更连续性。 - -**验收:** 升级、重启和移动文件不丢阅读记录;备份恢复后账号和进度可用;缓存清理不删原书;大书库结果按页展示。 - -### D. 书内搜索、批注与内容整理:P1 - -**依据:** [#692](https://github.com/hectorqin/reader/issues/692)、[#709](https://github.com/hectorqin/reader/issues/709)、#710、#498、#654、#659、#688、#594、#643、#584。 - -**当前差距:** - -- 书架/书库的书名、作者搜索已存在;没有找到完整的书内全文搜索入口和命中段落定位流程。 -- 笔记、高亮、书签的数据类型、API 和离线同步已存在;没有找到阅读 UI 中创建、编辑、列表和定位的完整操作链。因此应归为“补齐产品交互”,不宜直接写成已完成。 -- Web EPUB nav 解析将条目设为 `depth: 0`,章节匹配去掉 fragment;NCX 使用正则提取嵌套结构。服务端也主要提取章节标题。真实多级目录和章内锚点需要专项补齐。 -- 元数据编辑已持久化,但不代表正文纠错、标题替换或 TXT 目录规则已支持。 - -**建议需求:** - -1. 书内全文检索:结果摘要、命中高亮、跳到具体段落,保留返回原阅读位置的入口。 -2. 选区高亮 → 添加批注 → 笔记列表 → 点击回正文,复用现有同步与墓碑删除机制。 -3. 正确保留 EPUB nav/NCX 层级和 fragment,支持折叠、多级定位;TXT 增加可复用的章节规则及预览。 -4. 正文纠错和过滤规则先采用可撤销的覆盖层,保存于 DATA_DIR;刷新不丢,规则更新可回退。只有用户明确选择且书库可写时才考虑写回原文件。 - -**验收:** 同一章多个搜索命中定位不同段落;批注跨设备恢复;三级目录不丢节点;刷新后纠错仍在且可撤销。 - -### E. 朗读体验与配置诊断:P1 - -**依据:** #690、[#689](https://github.com/hectorqin/reader/issues/689)、#635、#623、#616、#613、#608、#590、#580、#482。 - -**当前基础:** 已有浏览器、Android 原生及 HTTP 三类引擎,语音选择、逐句高亮、自动续章、服务端代理及 TTS 缓存上限。 - -**建议需求:** 增加配置检测与试听;区分无语音、鉴权失败、上游超时和浏览器播放限制;验证 HTTPS/反代/iOS 下播放、后台返回和续章定位;失败可重试或切换引擎。 - -**验收:** 管理员可用一次试听确认配置;续章从章首开始;失败有具体原因,不返回空成功;停止后没有残留音频继续播放。 - -### F. 离线缓存与书源质量:P1/P2 - -**依据:** [#513](https://github.com/hectorqin/reader/issues/513)、#717、#718、#716、#573、#672、#706、#703、#650、#658、#647、#491、#697。 - -**当前基础:** 已读章节优先使用服务端缓存,来源失效前已缓存的内容有继续读取的基础;搜索可流式展示和取消;已有同一来源实例内的换源和个人凭据接口。凭据接口不等于支持任意网站的交互登录,通用插件不等于兼容全部 Legado JS。 - -**建议需求:** - -1. P1:整书/章节范围预下载、暂停/继续/取消、离线可读状态、按用户/书籍的配额和清理。明确“服务端缓存”与“设备断网可读”两个层次。 -2. P2:换源候选显示当前章字数、最新章节、响应时间和获取错误;先解决明显空章,再考虑相似度,避免把相似度当内容正确性的证明。 -3. P2:插件能力兼容表、登录状态/过期提示与必要的人工验证流程;解析和网站适配留在插件侧。 -4. EPUB 导出和 NAS 保存作为独立能力评估,需要版本、保存位置、失败重试及存储边界。它与 OPDS 浏览是不同需求。 - -**验收:** 预下载后断网可读指定范围;来源停用不损坏已有书架和缓存;任务可取消且配额可见;换源失败仍保留原内容和进度。 - -### G. 生态互通和客户端覆盖:P2 - -**依据:** [#679](https://github.com/hectorqin/reader/issues/679)、#673、#717、#700、#353、#519、#693、#588、#712、#523、#634。 - -**当前基础:** 已有 OPDS 客户端获取能力和 Web/Android;当前检查范围内没有找到 OPDS 服务端目录发布和 Legado WebDAV 同步路由。 - -**建议:** - -- 连接 Calibre 等 OPDS 书库归为已有功能的易用性完善。 -- “把 reader 书库供其他客户端使用”需要 OPDS 服务端能力,另行立项,不能与 OPDS 客户端混为一谈。 -- WebDAV 文件备份、账号数据备份、第三方阅读进度互通是三种问题。若做 Legado 兼容,单独定义书籍身份与定位映射适配器。 -- 先明确支持的浏览器版本和电纸书低动画方案;独立 iOS/Windows ARM 客户端按需求规模另评估。 - -### H. 可选增强:P3 - -**依据:** #694 AI 章节总结、#699 外部评论、#711 自定义标题、#454 背景透明化、#475 RSS。 - -AI 速读适合在书内定位、内容访问和插件边界稳定后评估,需包含章节来源定位、调用成本和用户配置。网页标题隐私选项成本可能较低,可穿插实现。外部评论和 RSS 会扩展产品范围,建议暂缓。 - -旧 Java 安装、JVM 内存参数、Jackson CVE 等(#453、#626、#486、#670、#695)不应直接转为当前 Node 服务端的对应修改;应保留其“易部署、受限资源运行、依赖维护”的目标。#339、#613 属于生态分享,不直接按缺陷计数。 - -## 3. 当前已覆盖、应转为验收的能力 - -| 历史诉求 | 当前证据 | 后续动作 | -| --- | --- | --- | -| 本地目录挂载、减少复制、子目录搜索 | `ShelfService.list`、扫描器、文件管理 | 做数据规模与权限场景验收 | -| 大书架分页 | `server/src/services/shelf.ts` 的 page/pageSize | 检查前端、同步和首屏是否仍全量加载 | -| OPDS 接入 | `server/src/sources/opds.ts` | 完善添加与鉴权体验;勿宣称已有 OPDS 服务端 | -| 不同设备独立主题 | `web/src/store/settings.ts` 按设备持久化 | 验证账号同步不覆盖显示设置 | -| 自动追更和换源 | `chapter-updates.ts`、`source-host.ts` | 验证插件能力声明、换源落点与失败回滚 | -| 失效源已有章节可读 | `ChapterPublications.asset` 在取源前返回已存正文 | 验证目录与设备缓存;补整书预下载 | -| TTS 引擎与续章 | `web/src/render/speech.ts`、`server/src/services/tts.ts` | 补配置诊断与平台验收 | -| 笔记/高亮同步 | `SyncService`、`OfflineStore` 和 notes API | 补阅读器完整交互,不作为已完成产品功能 | - -## 4. 建议下一批需求拆分 - -| 顺序 | 交付切片 | 可评审成果 | -| --- | --- | --- | -| 1 | 新旧版与来源接入说明 | 已核验部署命令、发布能力表、首次接入流程 | -| 2 | 进度可靠性 | 跨设备/离线/重排场景验收、同步状态、进度恢复方案 | -| 3 | 数据恢复 | 一致性备份、恢复校验、升级与目录变化验证 | -| 4 | 书内检索和目录 | 段落命中定位、三级目录、fragment 保留 | -| 5 | 笔记操作闭环 | 选区批注、笔记列表、回跳和跨设备同步 | -| 6 | 离线及听书 | 下载任务、缓存管理、TTS 试听和异常提示 | -| 7 | 插件生态增强 | 登录能力声明、换源质量、兼容矩阵和互通方案 | - -优先级不按关闭时间或关闭原因机械排序;这批数据混有多年旧版本反馈、使用问题和生态分享。建议在立项时对各切片补充新版本真实用户验证,而非直接复刻旧版功能集合。 - -## 5. 源码与文档核对入口 - -- [使用手册](user-guide.zh-CN.md)、[架构](architecture.md)、[来源插件](source-plugins.md)、[插件扩展](plugin-extensions.md)。 -- [书架分页与递归筛选](../server/src/services/shelf.ts)、[同步服务](../server/src/services/sync.ts)、[客户端同步](../web/src/core/sync.ts)。 -- [设备设置](../web/src/store/settings.ts)、[阅读器交互](../web/src/ui/reader-screen.tsx)、[阅读工具栏](../web/src/ui/reader-chrome.tsx)。 -- [Web EPUB 目录解析](../web/src/formats/epub.ts)、[服务端 EPUB 解析](../server/src/indexer/formats/epub.ts)。 -- [章节缓存](../server/src/publications/chapters.ts)、[来源 API](../server/src/http/routes/sources.ts)、[TTS 服务](../server/src/services/tts.ts)。 diff --git a/docs/configuration.en.md b/docs/configuration.en.md index 85ea6fd..8d199ee 100644 --- a/docs/configuration.en.md +++ b/docs/configuration.en.md @@ -7,7 +7,7 @@ For a first installation, follow [getting started](getting-started.en.md). This ## Directories and permissions - `BOOKS_DIR` contains your books. Use `:ro` for read-only access, or `:rw` plus filesystem write permissions for administrator file management. -- `DATA_DIR` stores SQLite, accounts, reading records, keys, covers, scan state, upload staging, remote downloads, and plugin data. It must always be writable. +- `DATA_DIR` stores SQLite, accounts, reading records, keys, covers, scan state, upload staging, downloaded files, and media metadata. It must always be writable. - `DATA_DIR` must not be the same directory as, or a child of, `BOOKS_DIR`. Startup rejects that configuration. - The image entrypoint attempts to fix ownership of the data directory itself, then runs as the `reader` user. It does not change book-directory ownership or recursively repair existing data-file permissions. @@ -22,7 +22,7 @@ These are defaults when running the server directly. The Docker image additional | `BOOKS_DIR` | `/books` | Book directory | | `DATA_DIR` | `data` under the current working directory | Server state and caches | | `HOST` | `0.0.0.0` | Listen address | -| `PORT` | `8080` | Listen port | +| `PORT` | `5888` | Listen port | | `PUBLIC_URL` | Empty | Public-facing URL; set when using a reverse proxy | | `SCAN_INTERVAL` | `1800` | Scheduled scan interval in seconds; `0` disables it | | `WATCH_INTERVAL` | `60` | Change-check interval in seconds; `0` disables it | @@ -31,6 +31,11 @@ These are defaults when running the server directly. The Docker image additional | `REFRESH_TOKEN_TTL` | `31536000` | Refresh-token lifetime in seconds | | `READER_TOKEN_SECRET` | Generated | Signing secret, at least 16 characters; otherwise stored in `DATA_DIR/token.secret` | | `LOG_LEVEL` | `info` | Logging level | +| `MEDIA_FFPROBE_PATH` | `ffprobe` | Local media probe executable | +| `MEDIA_FFMPEG_PATH` | `ffmpeg` | Embedded artwork and subtitle extraction | +| `MEDIA_TMDB_TOKEN` | Empty | TMDB read token; preferred when both credentials are configured | +| `MEDIA_TMDB_API_KEY` | Empty | TMDB API key; no online matching unless token or key is set | +| `MEDIA_MUSICBRAINZ_USER_AGENT` | Empty | MusicBrainz application/version/contact identifier; empty disables matching | | `CORS_ORIGINS` | Empty | Comma-separated browser origins; empty reflects the requesting origin | | `WEB_DIR` | `web` under the current working directory | Built Web client directory | | `TTS_URL` | Empty | HTTP speech upstream; empty disables HTTP speech | @@ -43,13 +48,13 @@ Run `docker compose up -d` after changing environment variables. Keep the signin ## HTTPS and reverse proxies -Use `http://:8080` on your LAN. Use HTTPS for public access to protect login credentials and access tokens. +Use `http://:5888` on your LAN. Use HTTPS for public access to protect login credentials and access tokens. For Caddy running on the same host as reader: ```caddyfile reader.example.com { - reverse_proxy 127.0.0.1:8080 + reverse_proxy 127.0.0.1:5888 } ``` @@ -92,6 +97,20 @@ Check whether the mount uses `:ro`. After switching to `:rw` and recreating the Check that the mounted files are readable and supported, then wait for scanning or trigger a scan as an administrator. The scanner skips directories such as `.git`, `@eaDir`, and `#recycle` and does not follow symlinks. Use the library file page to inspect the actual directory. -### Remote source searches fail +## Media libraries -Check the source address, current account credentials and the error details shown next to the search results. Verify that the source and its plugin are enabled. Runtime dependencies and provider-specific configuration are documented by the plugin author. +Mount local movie, series, music, and audiobook directories separately (read-only is recommended), then enter their container paths in media settings. For a native server, use absolute local paths. Do not use DATA_DIR as a media root. Users see authorized libraries; administrators manage scans, matching, and metadata. + +The official image includes ffprobe and ffmpeg. For native runs, put them on PATH or set MEDIA_FFPROBE_PATH / MEDIA_FFMPEG_PATH to executable paths. They probe metadata and extract embedded resources; they do not enable transcoding. + +Set MEDIA_TMDB_TOKEN or MEDIA_TMDB_API_KEY for online video matching, and MEDIA_MUSICBRAINZ_USER_AGENT for music metadata. Keep credentials in the host environment or an untracked .env, and pass them through Compose environment entries. A .env entry alone does not inject the value into the container. Local tags and NFO work without online credentials. + +Configure OpenList in the library creation form; no local mount is needed. Reader must reach OpenList and its download upstreams. Remote embedded metadata is not read, and some drivers require OpenList Web proxy. See [OpenList setup (中文)](media-openlist.md). + +Media uses media.db; reading and accounts use reader.db. Back up the complete DATA_DIR and restore both together. See [backup and restore (中文)](backup.zh-CN.md). + +### Media unavailable or playback fails + +A healthy reading endpoint does not imply media readiness. Retry MEDIA_STARTING after initialization; inspect server logs and data storage for MEDIA_UNAVAILABLE. For scan failures, inspect task errors and fix paths, permissions, or OpenList connectivity before rescanning. + +If metadata appears but playback fails, check browser codec/container support, upstream connectivity, and Range responses. Transcoding is not provided. Drivers requiring special download headers may need OpenList Web proxy. Do not delete media.db as a recovery step. diff --git a/docs/configuration.zh-CN.md b/docs/configuration.zh-CN.md index 9df4081..45011b6 100644 --- a/docs/configuration.zh-CN.md +++ b/docs/configuration.zh-CN.md @@ -7,8 +7,7 @@ ## 目录与权限 - `BOOKS_DIR` 是用户书籍目录。`:ro` 用于只读部署;`:rw` 配合文件系统写权限启用管理员文件管理。 -- `DATA_DIR` 保存 SQLite、账号、阅读记录、密钥、封面、扫描状态、上传暂存、远程下载与插件数据,必须始终可写。 -- Web 插件安装需要服务端可执行 npm(官方容器已包含)。可通过服务端 npm 配置设置 registry;下载、依赖和缓存都放在 `DATA_DIR/plugins` 的独立安装目录,成功后清理临时包和下载缓存。安装最长等待 5 分钟,禁用 npm 生命周期脚本;需要编译或额外运行环境的插件应由发布者提供构建产物与部署说明。 +- `DATA_DIR` 保存 SQLite、账号、阅读记录、密钥、封面、扫描状态、上传暂存、下载文件与影音资料,必须始终可写。 - `DATA_DIR` 不能与 `BOOKS_DIR` 相同或位于其内部,启动时会拒绝该配置。 - 镜像入口脚本尝试修正数据目录本身的属主,再以 `reader` 用户运行。它不会替你修改书籍目录的属主,也不会递归修复已有数据文件的权限。 @@ -23,7 +22,7 @@ | `BOOKS_DIR` | `/books` | 书籍目录 | | `DATA_DIR` | 当前工作目录下的 `data` | 服务端状态和缓存目录 | | `HOST` | `0.0.0.0` | 监听地址 | -| `PORT` | `8080` | 监听端口 | +| `PORT` | `5888` | 监听端口 | | `PUBLIC_URL` | 空 | 对外访问地址,反向代理后设置 | | `SCAN_INTERVAL` | `1800` | 定时扫描间隔,秒;`0` 关闭 | | `WATCH_INTERVAL` | `60` | 变化检查间隔,秒;`0` 关闭 | @@ -33,7 +32,9 @@ | `READER_TOKEN_SECRET` | 自动生成 | 至少 16 字符的签名密钥;默认保存在 `DATA_DIR/token.secret` | | `LOG_LEVEL` | `info` | 日志级别 | | `MEDIA_FFPROBE_PATH` | `ffprobe` | 影音技术信息读取程序;缺失时仍可扫描入库,时长、标签及章节信息可能不完整 | -| `MEDIA_TMDB_TOKEN` | 空 | TMDB API Read Access Token;空值禁用 TMDB 在线匹配,不影响本地扫描 | +| `MEDIA_TMDB_TOKEN` | 空 | TMDB 读取令牌;与 API Key 同时配置时优先使用 | +| `MEDIA_TMDB_API_KEY` | 空 | TMDB API Key;令牌与 Key 均为空时关闭在线影视匹配 | +| `MEDIA_FFMPEG_PATH` | `ffmpeg` | 内嵌封面与字幕提取程序,不提供转码 | | `MEDIA_MUSICBRAINZ_USER_AGENT` | 空 | MusicBrainz 请求标识,填写应用名称、版本及有效联系地址,例如 `Reader/0.1 (mailto:admin@example.com)`;空值禁用 MusicBrainz 在线匹配 | | `CORS_ORIGINS` | 空 | 允许的浏览器来源,逗号分隔;空值反射请求来源 | | `WEB_DIR` | 当前工作目录下的 `web` | 已构建 Web 客户端目录 | @@ -47,13 +48,13 @@ ## HTTPS 与反向代理 -局域网可直接访问 `http://<服务器IP>:8080`。对公网提供服务时使用 HTTPS,保护登录凭据和访问令牌。 +局域网可直接访问 `http://<服务器IP>:5888`。对公网提供服务时使用 HTTPS,保护登录凭据和访问令牌。 例如 Caddy 与 reader 运行在同一台主机上时: ```caddyfile reader.example.com { - reverse_proxy 127.0.0.1:8080 + reverse_proxy 127.0.0.1:5888 } ``` @@ -96,6 +97,20 @@ reader 代理语音请求,不内置合成模型。上游接口需兼容项目 确认挂载目录中的文件对服务进程可读,格式受支持,并等待扫描完成或由管理员手动扫描。扫描器跳过 `.git`、`@eaDir`、`#recycle` 等目录,不跟随符号链接;可在书库文件页核对实际目录。 -### 远程书源搜索失败 +## 影音媒体库 -检查来源地址、当前账号凭据和搜索结果中的错误详情,确认来源与插件已启用。插件额外的运行依赖和配置要求,以插件作者提供的文档为准。 +本地电影、剧集、音乐和有声书目录单独挂载到容器(建议只读),在「影音设置 → 媒体库管理」中填写容器路径。直接运行服务端时填写本机绝对路径;媒体根目录不要使用 DATA_DIR。普通用户只可访问已授权的库,扫描、刮削与资料编辑由管理员操作。 + +官方镜像包含 ffprobe 和 ffmpeg。本机启动时将二者加入 PATH,或设置 MEDIA_FFPROBE_PATH / MEDIA_FFMPEG_PATH 为可执行文件路径。ffprobe 用于时长、编码、标签和章节,ffmpeg 用于内嵌资源提取,均不提供转码。 + +在线匹配可配置 MEDIA_TMDB_TOKEN 或 MEDIA_TMDB_API_KEY,音乐资料可配置 MEDIA_MUSICBRAINZ_USER_AGENT。仅在宿主环境或未提交的 .env 中保存凭据,并在 Compose 的 environment 中传入;只有 .env 值、未声明 environment 时不会自动传进容器。本地 NFO 和标签读取不依赖在线凭据。 + +OpenList 连接信息在建库界面设置,无需本地挂载;服务端必须能访问 OpenList 和其下载源。远端内嵌资料暂不读取,某些驱动需要 OpenList Web 代理。配置与限制见 [OpenList 接入](media-openlist.md)。 + +影音使用独立 media.db;阅读与账号使用 reader.db。备份整个 DATA_DIR,成对恢复,见[备份指南](backup.zh-CN.md)。 + +### 影音不可用或无法播放 + +阅读健康检查成功不代表影音已就绪。MEDIA_STARTING 表示正在准备,稍后重试;MEDIA_UNAVAILABLE 需检查服务日志与数据目录。扫描失败时查看任务错误,检查路径、权限或 OpenList 连接后重新扫描。 + +能显示资料但无法播放时,检查浏览器对媒体容器及编码的支持、下载源连通性和 Range 响应。当前没有转码;OpenList 驱动特定请求头问题可按其配置启用 Web 代理。不要删除 media.db 作为修复方式。 diff --git a/docs/development.en.md b/docs/development.en.md index da10690..3ea14f7 100644 --- a/docs/development.en.md +++ b/docs/development.en.md @@ -53,7 +53,7 @@ In the second terminal: npm run dev --prefix web ``` -Open `http://localhost:5174`. Vite proxies `/api` to `http://127.0.0.1:8080` by default. Set `READER_SERVER` to change the proxy target. +Open `http://localhost:5174`. Vite proxies `/api` to `http://127.0.0.1:5888` by default. Set `READER_SERVER` to change the proxy target. ## Checks and tests @@ -103,7 +103,7 @@ cd android ./gradlew :app:assembleDebug ``` -Use `gradlew.bat` from a native Windows terminal. The output is `android/app/build/outputs/apk/debug/app-debug.apk`. Add `-PdefaultServerUrl=http://nas.local:8080` to preset the server address; otherwise users enter it and sign in. Building an APK does not validate reading on a physical device. +Use `gradlew.bat` from a native Windows terminal. The output is `android/app/build/outputs/apk/debug/app-debug.apk`. Add `-PdefaultServerUrl=http://nas.local:5888` to preset the server address; otherwise users enter it and sign in. Building an APK does not validate reading on a physical device. ## Code map @@ -112,7 +112,9 @@ Use `gradlew.bat` from a native Windows terminal. The output is `android/app/bui | `server/src/config`, `db` | Runtime configuration, SQLite schema and access | | `server/src/indexer` | File formats, scanning, identity, and metadata | | `server/src/services`, `http` | Business services, API, authentication, and resources | -| `server/src/sources` | Built-in sources and generic plugin contracts | +| `server/src/media` | Media catalog, scans, metadata, and playback | +| `web/src/media` | Media pages, routes, themes, and players | +| `server/src/sources` | Local library and OPDS integration | | `web/src/formats` | EPUB, TXT, comics, and other format handling | | `web/src/ui`, `styles` | Preact UI, reading stage, and styles | | `web/src/core`, `store` | Platform capabilities, synchronization, and offline storage | @@ -127,4 +129,4 @@ Preact manages UI state; the reading stage handles content layout and measuremen 3. Add appropriate regression checks for behavior changes. Documentation-only changes need link, command, and example checks. 4. Describe the changes, validation, and known limitations when submitting. -For integrations, see the [API reference (中文)](api.md), [source architecture (中文)](source-plugins.md), and [extension protocol (中文)](plugin-extensions.md). +See the [API reference (中文)](api.md), [media architecture (中文)](media-implementation.md), and [media validation (中文)](media-validation.md). diff --git a/docs/development.zh-CN.md b/docs/development.zh-CN.md index 8de4cba..214bc79 100644 --- a/docs/development.zh-CN.md +++ b/docs/development.zh-CN.md @@ -53,7 +53,7 @@ npm run dev --prefix server npm run dev --prefix web ``` -访问 `http://localhost:5174`。Vite 默认把 `/api` 代理到 `http://127.0.0.1:8080`;通过 `READER_SERVER` 环境变量可调整代理目标。 +访问 `http://localhost:5174`。Vite 默认把 `/api` 代理到 `http://127.0.0.1:5888`;通过 `READER_SERVER` 环境变量可调整代理目标。 ## 检查与测试 @@ -103,7 +103,7 @@ cd android ./gradlew :app:assembleDebug ``` -Windows 原生终端使用 `gradlew.bat`。产物为 `android/app/build/outputs/apk/debug/app-debug.apk`。可通过 `-PdefaultServerUrl=http://nas.local:8080` 预设地址;未预设时由用户填写服务地址并登录。编译 APK 不等于完成真机阅读验证。 +Windows 原生终端使用 `gradlew.bat`。产物为 `android/app/build/outputs/apk/debug/app-debug.apk`。可通过 `-PdefaultServerUrl=http://nas.local:5888` 预设地址;未预设时由用户填写服务地址并登录。编译 APK 不等于完成真机阅读验证。 ## 代码导览 @@ -112,7 +112,9 @@ Windows 原生终端使用 `gradlew.bat`。产物为 `android/app/build/outputs/ | `server/src/config`、`db` | 运行时配置、SQLite schema 和访问层 | | `server/src/indexer` | 文件格式、扫描、身份与元数据 | | `server/src/services`、`http` | 业务服务、API、鉴权和资源交付 | -| `server/src/sources` | 内置来源和通用插件契约 | +| `server/src/media` | 影音目录、扫描、资料与播放服务 | +| `web/src/media` | 影音页面、路由、主题与播放器 | +| `server/src/sources` | 本地书库与 OPDS 接入 | | `web/src/formats` | EPUB、TXT、漫画等格式处理 | | `web/src/ui`、`styles` | Preact 界面、阅读舞台和样式 | | `web/src/core`、`store` | 平台能力、同步、离线存储 | @@ -127,4 +129,4 @@ Windows 原生终端使用 `gradlew.bat`。产物为 `android/app/build/outputs/ 3. 为行为变更补充适当的回归验证;纯文档修改检查链接、命令和示例即可。 4. 提交变更时说明改动、验证方式和已知限制。 -API 详见 [API 文档](api.md),插件开发见[来源架构](source-plugins.md)与[扩展协议](plugin-extensions.md)。 +API 详见 [API 文档](api.md);影音边界见[模块架构](media-implementation.md),验证入口见[影音验证](media-validation.md)。 diff --git a/docs/ecosystem-roadmap.zh-CN.md b/docs/ecosystem-roadmap.zh-CN.md index e4f53d2..d6013ca 100644 --- a/docs/ecosystem-roadmap.zh-CN.md +++ b/docs/ecosystem-roadmap.zh-CN.md @@ -1,37 +1,16 @@ -# P2 生态互通与客户端覆盖方案 +# 互通与客户端覆盖 -日期:2026-09-24。依据:[关闭 issue 分析](closed-issues-analysis-2026-09-23.md) F、G。 +## 当前互通能力 -## 当前可使用的能力 +- OPDS 客户端可浏览、搜索并获取外部目录中的文件书。 +- OPDS 服务端向外部阅读器提供只读文件书籍目录;访问使用专用凭据。 +- WebDAV 可上传已完成的离线备份包,不同步运行中的数据库,见[接入指南](opds-webdav.zh-CN.md)。 +- OpenList 可接入电影、剧集、音乐与有声书目录,由 Reader 扫描外置资料并代理授权播放,见[OpenList 接入](media-openlist.md)。 -- Reader 的 OPDS **客户端**可连接 Calibre 等外部目录,浏览、搜索并获取文件;具体搜索、分页、下载和鉴权取决于目录服务。 -- 来源页可查看插件声明的能力。个人凭据仅显示是否配置,以及当前账号最近一次访问的结果;不代表网站会话持续有效。 -- 章节换源可按所选章节检测正文、查看最新章节和耗时。字符数和可读性不能证明章节完整、内容正确或站点授权。 -- 阅读设置提供电纸书预设:浅色、分页、无翻页动画。设备自行管理刷新率、残影与全刷;这不是原生电纸书客户端。 +跨应用阅读进度互通、通用书籍格式转换和影音转码尚未提供。Reader 账号内的阅读及播放进度可在连接同一服务的客户端间继续。 -## 独立交付项目 +## 客户端与验证范围 -| 项目 | 首版建议边界 | 关键决策及验收 | -| --- | --- | --- | -| OPDS 服务端 | 只读发布当前账号有权访问的文件书籍;分页、搜索、封面和原文件下载 | 使用可撤销的客户端凭据;不向外泄露文件路径;两个账号互不可见;停用凭据后不能继续获取资源;用 Calibre/至少一个移动客户端验收。章节书暂不发布,待有可下载出版物再接入。 | -| WebDAV 文件备份 | 上传已完成并校验的一致性备份包,复用 P0 备份/恢复流程 | 不直接同步运行中的 SQLite;临时上传后完成发布;断网重试、配额、保留策略、凭据加密;下载后校验并在独立目录恢复。与书籍文件保存任务分离。 | -| Legado 进度互通 | 独立适配器,明确对方版本、备份格式、书籍身份及定位映射 | 先只读导入并预览冲突;书名作者相同不能直接判为同一本;来源变化、缺章、多设备冲突、时间差均有明确策略;无法映射的记录必须可解释且不覆盖本地。 | -| 章节 EPUB 导出 | 将用户有权获取的指定章节快照导出为一个任务产物 | 固定目录版本,包含图片与目录,记录缺章;取消、配额、重复请求与失败重试可控;通过 EPUB 检验工具并在外部阅读器打开。不能用导出来绕过站点访问限制。 | -| NAS 保存 | 为导出产物选择管理员允许的根目录,保存完成后再扫描入库 | 默认不覆盖同名文件;路径限制、空间不足、写入中断清理、并发导出和原子完成;数据库与书籍文件备份分别说明。 | +Web 可用于桌面及移动浏览器,Android 提供应用外壳与原生媒体播放。浏览器排版、离线存储、编解码和后台行为均依赖运行环境。Chromium 自动化检查不等同于 Firefox、Safari、iOS 或电纸书实机认证;Android 构建也不能替代真机播放验收。 -2026-09-24 续批已实现 OPDS 服务端只读文件书籍及备份包 WebDAV 上传,使用边界见 [接入指南](opds-webdav.zh-CN.md)。进度互通、章节导出与 NAS 保存仍为独立方案,尚未实现。 - -## 浏览器验收范围 - -构建目标 `es2020` 仅描述语法,不保证浏览器具备所需 Web API。当前桌面验收使用 Playwright Chromium,具体版本及结果见 [P2 记录](p2-progress-2026-09-24.md)。 - -| 客户端 | 支持目标 / 验收要求 | 当前证据 | -| --- | --- | --- | -| Chrome / Edge | 当前稳定版与上一稳定版;阅读、登录、换源、下载和 IndexedDB | 自动化 Chromium 验收,不等同于全部 Chrome/Edge 版本实测 | -| Firefox | 当前稳定版与 ESR;特别检查排版、弹窗和离线存储 | 本轮未实机验收 | -| Safari / iOS | 当前与上一主版本;检查后台冻结、存储回收、语音和安全区域 | 本轮未实机验收,暂不承诺具体最低版本 | -| Android WebView | 当前稳定版;应用桥接、文件访问和生命周期另验收 | 本轮未设备验收 | -| 电纸书内置浏览器 | 必须先验证 JS、IndexedDB、Fetch/流、AbortController 与 dialog;使用电纸书预设 | 无实机证据,旧内核可能无法使用 | -| iOS 原生 / Windows ARM 原生 | 根据用户规模另评估;优先验证现有 Web 使用路径 | 未作为本轮开发项目 | - -离线应用安装和更新的环境要求参见 [PWA 指南](pwa.zh-CN.md)。设备低动画预设只关闭阅读翻页动画;其他界面动画可配合系统减少动态效果设置,无法代替硬件刷新控制。 +阅读的电纸书预设调整主题、分页及动画,不控制硬件刷新。PWA 安装与缓存要求见 [PWA 指南](pwa.zh-CN.md),影音测试及真机边界见[影音验证](media-validation.md)。 diff --git a/docs/getting-started.en.md b/docs/getting-started.en.md index 98ab07b..02b8556 100644 --- a/docs/getting-started.en.md +++ b/docs/getting-started.en.md @@ -4,13 +4,13 @@ This guide takes you through Docker deployment, account registration, and opening your first book. To run from source, use the [development guide](development.en.md). -This guide describes the current Node implementation. CI publishes `main` (development) and short commit tags, not `latest`; availability depends on a successful build. Pin a published commit tag for repeatable deployments. Legacy Java images, `/storage` data and Legado JSON sources are not directly compatible with this version. +This guide describes the current Node implementation. CI publishes `main` (development) and short commit tags, not `latest`; availability depends on a successful build. Pin a published commit tag for repeatable deployments. Legacy Java images and `/storage` data are not directly compatible with this version. ## 1. Prepare your environment - Install Docker Engine or Docker Desktop and the Docker Compose plugin. - Prepare a book directory and a separate data directory. -- Make port `8080` available, or change the host port in Compose, for example to `8090:8080`. +- Make port `5888` available, or change the host port in Compose, for example to `5890:5888`. The container serves both the API and Web UI. No separate frontend deployment is needed. Run the following commands from the repository root. @@ -34,7 +34,7 @@ For example, use `/srv/books:/books:ro` on Linux, or `"D:/books:/books:ro"` with | Directory | Purpose | | --- | --- | | `/books` (`BOOKS_DIR`) | Your existing book files | -| `/data` (`DATA_DIR`) | Database, accounts, reading records, covers, upload staging, downloaded files, and plugin data | +| `/data` (`DATA_DIR`) | Database, accounts, reading records, covers, upload staging, downloaded files, and media state | `DATA_DIR` must be outside `BOOKS_DIR` and must not be the same directory. Startup checks this constraint. Metadata stays in the data directory; reader does not create cover files or `.calibre` metadata beside your books. @@ -53,7 +53,7 @@ docker compose ps docker compose logs --tail=100 reader ``` -Open `http://localhost:8080`, or `http://:8080` from another device. +Open `http://localhost:5888`, or `http://:5888` from another device. 1. Register the first account. It automatically becomes the administrator. 2. Wait for the initial scan, then open a book from the shelf or library. @@ -78,7 +78,7 @@ On Linux/macOS with a POSIX shell, you can also run the container using absolute ```sh mkdir -p ./data docker run -d --name reader --restart unless-stopped \ - -p 8080:8080 \ + -p 5888:5888 \ -v /path/to/your/books:/books:ro \ -v "$(pwd)/data:/data" \ cnb.cool/hectorqin/reader:main @@ -98,17 +98,25 @@ The shelf contains readable books; the library lets you browse the disk director As an administrator, add an OPDS source under Sources (书源) and configure its server URL. If authentication is required, set credentials for your current account. Open the source to browse or search its catalog and acquire books for your shelf. -### External source plugins +## 5. Add media libraries -The generic plugin host does not parse Legado JSON. Do not enter a legacy JSON file or subscription URL as an npm package. Compatibility requires a separate plugin that explicitly supports that format; otherwise use local books or OPDS. +Mount local media separately by adding the directories you need to Compose volumes: -In Sources → Plugin management, administrators can confirm that they trust the plugin, then enter an npm package name (optionally with a version or tag) or upload a `.tgz` archive produced by `npm pack` (up to 100 MiB). Successful installations are enabled automatically; no manual deployment is needed. Add a source instance using the plugin’s source type and configure it from that instance’s management entry. One plugin can provide several independent instances. Capabilities and runtime dependencies are defined by each plugin. +```yaml + - /path/to/your/videos:/media/video:ro + - /path/to/your/music:/media/music:ro + - /path/to/your/audiobooks:/media/audiobook:ro +``` -Plugins run with server process privileges. Only install trusted code. The server needs Node.js and npm, plus network access for npm packages and dependencies not bundled in uploaded archives. npm lifecycle scripts are disabled, so plugins must ship prebuilt runtime files. Installation files and temporary files stay in `DATA_DIR`, never in the books directory. +Run `docker compose up -d`. Open media from the bookshelf, then Settings → Media libraries. Choose video, music, or audiobooks, set a container path such as `/media/video`, and choose access permissions. Creation starts a scan; inspect scan tasks in settings if it fails. -See the [plugin protocol](source-plugins.md) and [extension pages](plugin-extensions.md). +When running directly on Windows, use an absolute local path such as `D:\Media\Music`. With Docker Desktop, mount the directory and enter its container path instead. -## 5. Upgrade and back up +Alternatively, choose OpenList and provide its service URL, remote directory, and optional token/directory password. No local mount is needed. See [OpenList setup (中文)](media-openlist.md). + +Local scans read NFO and tags; online matching requires TMDB or MusicBrainz [configuration](configuration.en.md). Playback does not transcode. See the [media guide (中文)](media-user-guide.zh-CN.md). + +## 6. Upgrade and back up The [offline backup and restore tool (中文)](backup.zh-CN.md) checks file hashes and SQLite integrity and restores into a new directory. For older builds without this command, use a stopped-service copy as described below. @@ -121,7 +129,7 @@ docker compose pull docker compose up -d ``` -Keep your data directory: it contains accounts, reading records, signing keys, and plugin state. Plugin packages are upgraded separately; disable the plugin in the UI before replacing its package. +Keep your data directory: it contains accounts, reading and playback progress, media metadata, and signing keys. Back up the complete directory and restore reader.db and media.db together. Back up original books and media separately. When moving from the legacy Java version, keep a full backup and use a separate new data directory. Existing book files can be mounted, but accounts, shelves, progress, notes and source settings have no automatic migration tool. Do not copy legacy `/storage` over the new `/data`. Source-built deployments must rebuild using both Compose files instead of relying on `pull`. diff --git a/docs/getting-started.zh-CN.md b/docs/getting-started.zh-CN.md index ce4c1b5..d8415e2 100644 --- a/docs/getting-started.zh-CN.md +++ b/docs/getting-started.zh-CN.md @@ -4,13 +4,13 @@ 本文带你完成 Docker 部署、注册账号和读取第一本书。直接从源码运行请看[开发指南](development.zh-CN.md)。 -本指南对应当前 Node 版工作区。CI 发布 `main`(开发分支)和提交短哈希标签,没有发布 `latest` 的配置;标签可用性以对应构建成功为准。部署后核对版本,长期使用建议固定提交标签。旧 Java 版镜像、`/storage` 数据和 Legado JSON 书源不与新版直接兼容。 +本指南对应当前 Node 版工作区。CI 发布 `main`(开发分支)和提交短哈希标签,没有发布 `latest` 的配置;标签可用性以对应构建成功为准。部署后核对版本,长期使用建议固定提交标签。旧 Java 版镜像、`/storage` 数据不与新版直接兼容。 ## 1. 准备环境 - 安装 Docker Engine 或 Docker Desktop,以及 Docker Compose 插件。 - 准备一个书籍目录和一个独立的数据目录。 -- 确保主机的 `8080` 端口可用;也可修改 Compose 左侧端口,例如 `8090:8080`。 +- 确保主机的 `5888` 端口可用;也可修改 Compose 左侧端口,例如 `5890:5888`。 容器同时提供 API 和 Web 界面,无需单独部署前端。以下命令从仓库根目录执行。 @@ -34,7 +34,7 @@ volumes: | 目录 | 用途 | | --- | --- | | `/books`(`BOOKS_DIR`) | 现有书籍文件 | -| `/data`(`DATA_DIR`) | 数据库、账号、阅读记录、封面缓存、上传暂存、下载文件和插件数据 | +| `/data`(`DATA_DIR`) | 数据库、账号、阅读记录、封面缓存、上传暂存、下载文件与影音数据 | `DATA_DIR` 不能与 `BOOKS_DIR` 相同,也不能位于其中;启动时会检查这项约束。元数据保存在数据目录,不会在书旁生成封面或 `.calibre` 文件。 @@ -53,7 +53,7 @@ docker compose ps docker compose logs --tail=100 reader ``` -打开 `http://localhost:8080`;在另一台设备上使用 `http://<服务器IP>:8080`。 +打开 `http://localhost:5888`;在另一台设备上使用 `http://<服务器IP>:5888`。 1. 注册第一个账号,该账号自动成为管理员。 2. 等待初次扫描,在书架或书库中打开一本书。 @@ -78,7 +78,7 @@ docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build ```sh mkdir -p ./data docker run -d --name reader --restart unless-stopped \ - -p 8080:8080 \ + -p 5888:5888 \ -v /path/to/your/books:/books:ro \ -v "$(pwd)/data:/data" \ cnb.cool/hectorqin/reader:main @@ -98,17 +98,25 @@ Windows 推荐使用上面的 Compose 配置,避免不同 shell 的路径和 管理员在「书源」添加 OPDS 来源并设置服务地址。需要认证时填写当前账号的来源凭据。打开来源后可浏览或搜索目录,获取书籍并加入书架。 -### 外部书源插件 +## 5. 添加影音媒体库 -通用来源插件不是 Legado JSON 解析器。旧版书源 JSON 或订阅链接不能直接当 npm 包安装;只有明确声明支持该格式的独立插件才能提供兼容,是否支持以该插件说明为准。尚无适用插件时,请使用本地书库或 OPDS。 +本地影音需单独挂载。在 Compose 的 volumes 中按需增加: -管理员打开「书源 → 插件管理」,确认信任插件代码后,输入 npm 包名(可带版本或标签),或上传 `npm pack` 生成的 `.tgz` 安装包(最大 100 MiB),安装成功后自动启用。无需手动部署包目录。随后在「书源管理」选择插件提供的来源类型创建实例,从该实例的管理入口配置。一个插件可创建多个独立实例;具体功能与运行依赖由插件声明。 +```yaml + - /path/to/your/videos:/media/video:ro + - /path/to/your/music:/media/music:ro + - /path/to/your/audiobooks:/media/audiobook:ro +``` -插件拥有服务端进程权限,请只安装可信代码。服务端需要 Node.js 和 npm;npm 包及未打包的依赖需要联网下载。安装期间禁用 npm 生命周期脚本,插件应预先构建并打包运行所需文件。所有安装文件与临时文件保存在 `DATA_DIR`,不会写入书库目录。 +执行 `docker compose up -d` 后,从书架「影音」进入「设置 → 媒体库管理」,选择影视、音乐或有声书,填写容器内目录(例如 `/media/video`)及访问范围。创建后自动扫描;扫描任务和失败原因可在设置中查看。 -开发与配置协议见[来源插件](source-plugins.md)和[扩展页面](plugin-extensions.md)。 +Windows 直接运行服务时填本机绝对路径,例如 `D:\Media\Music`;Docker Desktop 则挂载该目录并填写容器内路径。 -## 5. 更新与备份 +也可选择 OpenList,填写服务地址、远端目录及可选令牌/目录密码,无需把远端目录挂载到 Reader 容器。详见 [OpenList 接入](media-openlist.md)。 + +本地扫描可读取 NFO 和标签;在线匹配需按[部署配置](configuration.zh-CN.md)设置 TMDB 或 MusicBrainz。播放不转码,更多操作见[影音手册](media-user-guide.zh-CN.md)。 + +## 6. 更新与备份 推荐使用[离线备份与恢复工具](backup.zh-CN.md),可验证文件清单和数据库完整性,并恢复到新目录。首次从没有维护命令的旧构建升级时,仍可按以下停机复制方式保留完整数据。 @@ -121,7 +129,7 @@ docker compose pull docker compose up -d ``` -不要删除数据目录:其中包含账号、阅读记录、签名密钥和插件状态。插件包需单独升级;替换包前先在界面停用插件。 +不要删除数据目录:其中包含账号、阅读与播放进度、影音资料及签名密钥。备份完整目录,成对恢复 reader.db 和 media.db;书籍和原始媒体目录需单独备份。 从旧 Java 版迁移时,先保留其完整备份,使用独立的新数据目录部署新版。本地书文件可挂载到新书库;账号、书架、进度、笔记和旧书源配置目前没有自动迁移工具,不要直接用旧 `/storage` 覆盖新 `/data`。源码构建部署更新时使用两份 Compose 文件重新构建,不能仅执行 `pull`。 diff --git a/docs/opds-webdav.zh-CN.md b/docs/opds-webdav.zh-CN.md index 9982713..7e30de1 100644 --- a/docs/opds-webdav.zh-CN.md +++ b/docs/opds-webdav.zh-CN.md @@ -24,7 +24,7 @@ ## 上传一致性备份到 WebDAV -这是管理员 CLI,上传已完成的备份目录;不直接同步运行中的 DATA_DIR,也不是 Legado 进度互通。先按 [备份指南](backup.zh-CN.md) 停止全部相关服务和插件、创建并验证备份。上传阶段可重新启动 Reader,备份目录保持不变。 +这是管理员 CLI,上传已完成的备份目录;不直接同步运行中的 DATA_DIR,也不是 Legado 进度互通。先按 [备份指南](backup.zh-CN.md) 停止全部相关服务进程、创建并验证备份。上传阶段可重新启动 Reader,备份目录保持不变。 在编译后的服务端目录运行: diff --git a/docs/p0-progress-2026-09-23.md b/docs/p0-progress-2026-09-23.md index fbedd84..b3121cc 100644 --- a/docs/p0-progress-2026-09-23.md +++ b/docs/p0-progress-2026-09-23.md @@ -1,18 +1,18 @@ # P0 推进记录:第一批 -范围来自 [issue 需求分析](closed-issues-analysis-2026-09-23.md)。本批没有改数据库 schema,也没有执行部署或操作现有用户数据。 +范围为备份、阅读状态与本地数据可靠性。本批没有改数据库 schema,也没有执行部署或操作现有用户数据。 ## 已实现 1. 进度可靠性:后台/隐藏事件经过 App.flush,先等待阅读器待保存位置和本地写队列,再触发同步;打开书籍比较本地和服务端时间,保留较新的记录。服务端查询最长等待 5 秒,不可达时回退本地。存储写入错误向调用者报告,后续写入可重试,阅读器显示保存失败。 2. 数据保护:服务端离线 backup/verify/restore 命令,完整 DATA_DIR 文件校验、SQLite 完整性检查、恢复到新目录、拒绝覆盖与路径重叠。未完成目录和备份目录不能直接启动服务。操作说明见 [备份恢复](backup.zh-CN.md)。 -3. 部署接入:按当前 CI 标签规则把 latest 改为 main,可通过 READER_IMAGE 固定版本;添加源码构建 Compose 覆盖文件;限制容器日志为 3 × 10 MiB;补充新旧版和 Legado 兼容范围。 +3. 部署接入:按当前 CI 标签规则把 latest 改为 main,可通过 READER_IMAGE 固定版本;添加源码构建 Compose 覆盖文件;限制容器日志为 3 × 10 MiB;补充新旧版数据兼容范围。 ## 验证方式 - Web 真实 ReaderScreen/OfflineStore 测试覆盖较新服务端、较新离线记录、网络失败、后台落盘顺序和读取期间不写临时位置。 - 存储失败测试先观察到错误被吞,再修复并验证重试及 outbox 保留。 -- 服务端真实 SQLite 测试覆盖账号/进度/笔记/密钥/插件状态往返、损坏/缺失文件、路径篡改、恢复覆盖拒绝和启动保护。 +- 服务端真实 SQLite 测试覆盖账号/进度/笔记/密钥/服务状态往返、损坏/缺失文件、路径篡改、恢复覆盖拒绝和启动保护。 - Compose 默认和源码构建配置可解析;两端 TypeScript/构建检查。 ## 未完成的 P0 范围 diff --git a/docs/p1-progress-2026-09-23.md b/docs/p1-progress-2026-09-23.md index d24222d..03f30bd 100644 --- a/docs/p1-progress-2026-09-23.md +++ b/docs/p1-progress-2026-09-23.md @@ -6,12 +6,12 @@ | 能力 | 交付行为 | | --- | --- | -| 书内检索 | EPUB/TXT/远程章节逐章搜索、摘要、200 条上限、取消、命中高亮、返回原阅读位置;不对图片或扫描 PDF 做 OCR | +| 书内检索 | EPUB/TXT逐章搜索、摘要、200 条上限、取消、命中高亮、返回原阅读位置;不对图片或扫描 PDF 做 OCR | | 批注 | 正文选区高亮、批注、书签、编辑、删除、回正文;沿用现有离线同步和墓碑机制;修复同 ID 笔记跨账号覆盖 | | EPUB 目录 | Web/服务端解析有序 nav/NCX 树,保留层级、fragment、spine,支持折叠和章内定位 | | 个人纠错 | 精确文字替换、选区过滤、移除及撤销;按账号/书籍保存在 DATA_DIR/reader.db,版本冲突返回 409;不改原书 | | TXT 目录 | 中文、英文、方括号模板和自定义标题前缀;预览后应用,规则持久化并可撤销 | -| 设备离线 | TXT/远程章节范围下载;EPUB/PDF/CBZ 整文件下载,保留 EPUB 内部资源;暂停、继续、取消;失败可重试并跳过完成资源 | +| 设备离线 | TXT范围下载;EPUB/PDF/CBZ 整文件下载,保留 EPUB 内部资源;暂停、继续、取消;失败可重试并跳过完成资源 | | 缓存管理 | 服务地址与账号隔离;默认 256 MiB 配额、实际资源字节占用、按书清理;配额写入串行,失败回滚旧资源 | | 朗读诊断 | 当前引擎试听;HTTP 实际合成检测,分别报告配置、鉴权、响应体超时、非音频、空音频;停止和关面板释放试听 | | 大书库基线 | 10,000 条索引的首尾分页、搜索、增量同步验证,单次查询按页返回 | @@ -36,5 +36,5 @@ - 纠错规则联网保存,已缓存规则离线应用;其他设备下次打开书籍拉取,不通过进度同步接口实时推送。空替换只过滤选区,未实现全书正则过滤。 - 下载任务关闭面板即暂停。整文件下载重试从头请求;章节下载按已完成资源续传。图片目录不支持整书预下载。 - 配额统计是新账号作用域下的正文/整文件缓存,未包含封面、服务端缓存和旧版本非账号隔离缓存;不自动淘汰。 -- 浏览器缓存可能被系统回收;未缓存的章节仍需联网。正文版本变化、目录重排或换源后的旧笔记不会强行匹配到不确定文本。 +- 浏览器缓存可能被系统回收;未缓存的章节仍需联网。正文版本变化或目录重排后的旧笔记不会强行匹配到不确定文本。 - Docker 引擎未启动,本轮未做容器和实际部署验收。 diff --git a/docs/p2-progress-2026-09-24.md b/docs/p2-progress-2026-09-24.md deleted file mode 100644 index 9a384ca..0000000 --- a/docs/p2-progress-2026-09-24.md +++ /dev/null @@ -1,50 +0,0 @@ -# P2 交付与验证记录 - -本轮依据 [需求分析](closed-issues-analysis-2026-09-23.md) F2、F3、G,实现书源质量与插件接入体验,并完成生态互通的独立方案。P0/P1 和其他已有改动保留;未提交、未部署。 - -## 已交付 - -1. **换源质量检测**:按所选章节获取并清洗正文,展示字符数、图片数、字节大小、最新章节和检测耗时;候选卡片保留本次检测摘要或错误。不批量预抓所有来源。切换章节或关闭面板会取消检测并忽略迟到结果。 -2. **空章保护**:刷新和确认换源时均强制验证,空白/清洗后为空的正文返回 `EMPTY_CHAPTER`;失败不替换当前绑定或已有缓存。质量预览不写正文缓存或修改书籍。图片章允许通过。 -3. **个人凭据状态**:增加当前账号的配置状态与最近访问观察,支持删除单项;保存、删除、修改连接配置后重置观察。用 generation 防止旧请求覆盖新凭据状态,不返回凭据值。 -4. **插件接入说明**:显示全部已知能力的“已声明/未声明”;站点登录过期、未登录、人工验证三个错误码不会清除 Reader 会话。说明 OPDS 客户端、网站适配、Legado 与宿主边界。 -5. **电纸书预设**:一键浅色、分页、无翻页动画,沿用当前设备设置存储,不影响其他设备。不是设备全刷控制。 -6. **生态方案**:[OPDS 服务端、WebDAV、进度互通、导出、NAS 与浏览器矩阵](ecosystem-roadmap.zh-CN.md)。这些协议仍需独立实施,本轮没有宣称已提供。 - -## 核心变更入口 - -- `server/src/publications/chapter-quality.ts`、`chapters.ts`:质量统计与读取/提交保护。 -- `server/src/services/source-access.ts`、`source-host.ts`、`db/schema.ts`:账号隔离的访问观察和凭据事务。 -- `server/src/http/routes/sources.ts`、`web/src/api/*`:质量接口、状态读取/删除与错误分类。 -- `web/src/ui/source-capabilities.tsx`、`sources-screen.tsx`:能力表及凭据页。 -- `web/src/ui/reader-chrome.tsx`、`reader-screen.tsx`:检测交互、取消与电纸书预设。 -- [API 说明](api.md)、[来源插件说明](source-plugins.md)、[使用手册](user-guide.zh-CN.md)。 - -## 验证 - -- Web TypeScript `tsc -p tsconfig.json --noEmit`、Vite 生产构建通过。 -- Server TypeScript `tsc -p tsconfig.build.json` 通过。 -- Web 全量 Vitest:41 个文件、594 项通过;独立 Node 测试 29 项通过。 -- Server 全量:342 项,其中 340 通过、2 项 Windows 平台跳过,0 失败。 -- 核心定向测试覆盖:Unicode/空白/HTML/图片章、质量预览不写入、空章不覆盖旧缓存或绑定、书籍所有权、凭据不泄漏、账号隔离、状态重置、旧请求失效、站点错误不退出 Reader、检测结果清理与迟到结果丢弃。 -- `web/tools/ui-review/p2-sources.mjs`:真实 HTTP + SQLite + 受控来源插件 + 生产 Web,Chromium **153.0.8010.12**。凭据保存/删除/状态重置、空章检测和确认换源失败、成功检测/换源、电纸书预设通过;320/390/1280 宽度无横向溢出,页面无未处理异常。 -- 最终文案和取消回归补充后:Web 定向 50 项、Server 来源 API 16 项再次通过,生产构建与浏览器流程再次通过。 -- `git diff --check` 通过。 - -截图见 [窄屏凭据页](ui-review/p2/credentials-320.png)、[窄屏质量检测](ui-review/p2/quality-320.png)、[桌面能力表](ui-review/p2/capabilities-1280.png)。 - -## 边界与后续 - -质量结果是一次读取快照,不能验证缺段、广告、标题错配或版权授权;确认换源会重新读取。耗时包括目录、正文、内嵌图片处理,不包括 acquire 和客户端网络往返。字符数不含空白和 HTML 标记。 - -访问状态表示来源实例最近一次请求观察;聚合插件的部分站点错误也会影响状态,不是逐网站会话管理。插件未报告过期时间时不推测,也不提供任意验证链接。人工验证仍需站点/插件实现。 - -浏览器流程使用受控插件,未对真实付费站点、验证码站点、Safari、Firefox、Android 或电纸书硬件做兼容认证。后续按生态方案单独验收。 - -## 续批:OPDS 服务端与 WebDAV(2026-09-24) - -已新增只读 OPDS 1.2 服务端、个人应用凭据管理界面、独立撤销/到期、账号隔离、分页/搜索/封面/Range 下载。与 Reader 内置 OPDS 客户端完成真实协议对接。 - -新增管理员 WebDAV 备份 CLI:离线快照验证、流式 ZIP、临时上传重试、远端 SHA-256 校验、MOVE 不覆盖发布、取消和失败清理。未配置用户 WebDAV 地址,因此未向用户外部存储上传;已用受控 HTTP WebDAV fixture 验证并解压校验备份。详见 [接入指南](opds-webdav.zh-CN.md)。 - -续批验证:Server 全量在 test-concurrency=2 下 344 项(342 通过、2 Windows 跳过),Web 595 项及已有 Node 29 项;类型与生产构建通过。默认高并发服务端运行曾使既有 1 秒插件超时测试失败,降低并发重跑全量通过。浏览器覆盖新 OPDS 凭据创建、仅一次显示、重新打开不回显、撤销后目录返回 401。 diff --git a/docs/plugin-extensions.md b/docs/plugin-extensions.md deleted file mode 100644 index 3667c02..0000000 --- a/docs/plugin-extensions.md +++ /dev/null @@ -1,63 +0,0 @@ -# 插件扩展页面、搜索与换源 - -## 搜索诊断 - -宿主记录 `search stream started`、`search stream ended`、`search stream provider failed`。结束日志包含 sourceId、sessionId、reason、耗时、最后事件距今时间、结果数量与书源进度。`complete`/`limit` 表示完成,`provider_error` 表示来源调用异常,`connection_closed`/`request_aborted` 表示连接关闭,`superseded` 表示同会话被新连接接替。连接关闭不能单独区分浏览器、网络或反向代理,需要结合代理日志。取消确认失败会保留结束上下文和 cleanupMs。 - -插件 stderr 仅转发 `READER_DIAGNOSTIC ` 前缀的单行 JSON,附加 pluginId/pluginVersion 并记录为 `source plugin diagnostic`;任意文本及超长行丢弃。插件负责脱敏。RPC 超时额外记录 method、rpcId、sourceId、elapsedMs、pendingRequests,以区分搜索与清理调用。 - -Reader 保留 local 与 OPDS 内置,通过通用协议接入独立 Node.js 插件。宿主负责能力校验、权限、进程与任务调度、缓存和通用界面;来源业务由插件实现。一个插件可添加成多个独立配置的来源实例。 - -## 页面与存储 - -实例页面和后台任务在清单的 `sourceTypes[].extensions` 中声明,全局入口使用顶层 `extensions`。实例页面地址为 `#/sources//`,从自定义书源的管理入口打开。插件管理页负责安装、启停和卸载。 - -GET 调用 `extension.page`;POST 调用 `extension.action`,参数为 `{sourceType,context:{instance,userId},pageId,action,values}`。宿主根据 sourceId 从数据库解析插件与实例,客户端不能伪造上下文;暂停的来源仍可管理,停用插件则不可访问页面。普通读者无页面读取及写入权限。 - -返回 Page DTO:`title/description/notice/forms/sections/tabs/activeTab`。每个 Tab 包含 `id/title/description/forms/sections/outputs`,页面公共内容和当前 Tab 同时渲染。Form 包含 `id/title/submit/fields/values`,可选 `layout: "inline"` 和 `confirm` 声明紧凑布局及行内二次确认,fields 支持 text、password、textarea、number、boolean、select;values 携带不透明行 ID。Field 可选 `placeholder/min/max`,Page 可选 `noticeKind: "info" | "error"`;所有字段由宿主验证。section 支持 `emptyText`,item 支持 `collapsible`。`outputs` 用于调试日志、JSON 或普通文本,格式为 `{title,text,format:"text"|"log"|"json"}`,宿主以纯文本块渲染并限制数量与大小,不执行内容。一次动作返回新页面;可选 activeTab 请求切换到指定 Tab,否则保留当前选择。纯 Tab 切换保留输入草稿。提交后保留其它声明未变化的表单草稿;服务端改变表单声明或主动刷新时以新页面为准。 - -操作中的状态、`notice` 和请求错误由宿主统一显示为紧凑浮动提示,不占用页面内容高度。完成提示可关闭并自动消失;错误保留 `alert` 语义,操作完成后的焦点回到内容面板,不滚动到提示。需要持续查看的日志和结果仍放在 `outputs`。 - -宿主校验声明、页面结构、选项和输入配额;未声明页面拒绝访问。渲染器只呈现文本,不接受 HTML、JS、iframe 或任意前端代码。授权在 HTTP 层执行,隐藏入口不代替鉴权。 - -启用 storage 权限后,RPC 获得 `host.dataDir = DATA_DIR/plugin-data/`;带实例上下文时还获得 `host.instanceDataDir = host.dataDir/sources/`。插件负责创建目录和原子写入;数据与 npm 包目录分离,停用、升级、卸载均保留。这是受信任插件的约定,不是操作系统沙箱。 - -## 后台任务 - -宿主每分钟检查启用插件及启用来源实例的声明任务。实例任务调用 `extension.task({taskId,sourceType,context:{instance,userId:""}})`,不携带个人凭据;全局任务继续使用 `{taskId}`。任务串行、同轮合并,执行前重新确认实例仍存在且启用。同一实例的后台任务与管理写入互斥,不阻塞其它实例的配置;下一执行时点和失败次数以插件、实例、任务组合键保存在通用 `plugin_storage`,重启恢复,失败退避。暂停/删除实例后不再调度它,停用插件或关闭宿主会终止进程。此调度独立于章节追更。 - -## 搜索 - -声明 `search.filters`,实现 `searchFilters(ctx)`,返回带不透明 key/value 的选择字段;`SearchRequest.filters` 为字符串映射,宿主只验证结构与大小。搜索历史与下一页保留筛选条件。 - -前端通过 `POST /api/v1/sources/:id/search` 建立一次 Streamable HTTP 请求,使用 `text/event-stream` 持续接收 `results`,并以 `done` 或 `error` 结束;收到结果后立即合并展示。宿主在服务端按插件返回的 `nextCursor` 拉取后续批次或普通分页,直到游标耗尽、达到请求的 `resultLimit` 或被取消。插件内部的游标分页仍保留,前端不再通过轮询获取结果。停止搜索或断开连接会取消在途搜索,已收到的结果保留。 - -远程搜索结果按规范化后的书名和作者集合合并显示,数量按合并后的书籍计数;作者缺失或不同作者不合并。点击“X 条书源”查看实时更新的书源列表,再选择具体条目查看详情或获取。合并仅影响展示,每条结果的不透明 `ref`、获取选项和流游标均保留,单次结果上限仍按原始唯一条目计数。 - -`CatalogPage.errors` 使用 `{source,code,message}` 表达部分失败,由宿主校验。成功条目保留;插件提供脱敏信息,宿主不解释业务错误码。声明 `search.session` 时须同时声明 `search.cancel` 并实现取消接口。宿主按用户与来源隔离会话,前端保留查询、筛选和已收到结果。Web 通过断开结果流停止搜索,宿主负责取消在途调用与暂停插件会话;继续搜索沿用会话及最后收到的游标,重新搜索使用新会话。插件应将搜索轮询与详情/获取操作解耦,并把请求取消信号传到底层任务,避免停止后留下阻塞队列。 - -## 换源 - -声明 `content.alternatives` 并实现 `alternatives(ctx,{publicationRef,query,authors,cursor,sessionId,resultLimit})`,返回普通 CatalogPage。宿主从当前用户私有书籍解析绑定与标题,不接受客户端指定他人的来源上下文。 - -1. 阅读顶部工具栏根据 `source-options.canSwitch` 显示换源图标。打开面板即通过 POST 流持续加载候选;关闭面板断开连接,取消后台搜索。插件按书名、作者校验候选,排除当前来源,并在匹配后应用结果上限。 -2. 点击候选取得其目录。唯一同名章节可预选,否则必须手动选择;确认后从所选章开头阅读,不推测百分比或沿用旧章内偏移。 -3. 请求携带旧 revision。宿主与刷新共用书籍串行队列,版本不符返回冲突。获取新目录、确认章节存在、读取正文并清洗/内嵌图片全部成功后才提交数据库事务。 -4. 事务保存新快照和已验证正文、替换 publicationRef、保留 bookId、书架与订阅,清零新增章计数并推进订阅 generation。失败保留原绑定、目录与缓存。 -5. 客户端读到落点正文后才替换阅读视图,并保存新进度。旧修订缓存继续可读;旧笔记/书签保留原 href,不自动迁移到相似章节。其它已打开客户端仍需刷新目录,未缓存旧章节返回快照过期。 - -重新获取现绑定复用当前书籍 ID;重新加入换源前版本创建独立记录,不会误返回换源后的版本。换源限同一来源实例内提供的候选,跨插件/跨实例不是本版功能。如果目标版本已作为另一条书籍记录入库,返回 SOURCE_ALREADY_ACQUIRED,需从书架打开已有版本,以免合并或覆盖另一本书的笔记和进度。 - -CatalogEntry 可提供 `sourceName`、`latestChapter`,用于详情弹窗和换源列表。ManifestSnapshot 可提供 `sourceName`,章节可提供 `sourceUrl`(仅 HTTP/HTTPS、无用户名密码);宿主保存并投影到阅读 DTO,在顶部栏下展示来源和当前章节链接。宿主不解析插件的不透明引用。 - -目录标题栏的刷新图标仅刷新目录;顶部工具栏的刷新图标强制重新获取当前正文,经过相同的媒体校验、HTML 清洗和图片处理后才覆盖缓存。失败保留原正文和缓存。 - -## 验证 - -服务端测试覆盖实例隔离、页面与任务权限、暂停、删除、重启、协议校验和换源事务;Web 测试覆盖通用 Tab、表单草稿、错误反馈与搜索取消。浏览器验证入口见[UI/UX 评审](ui-review/sources-ux.md)。插件业务测试由插件维护者负责。 - -登录字段使用 `password`:服务端拒绝返回非空的默认密码,客户端不保留密码草稿,提交失败后清空密码。页面及 Tab 可声明 `links: [{title,url}]`,仅支持不包含内嵌凭据的 HTTP(S) 地址,以新窗口和 `noopener noreferrer` 打开。 - -页面和 Tab 可声明 `layout: "workbench"`,桌面将表单和输出分为两栏,窄屏纵向排列;省略时保留原有布局。日志可通过分页表单分批返回,每页仍遵循输出大小限制。 - -Tab 可声明 `loadAction`,用户进入该 Tab 时执行加载动作;加载完成的页面应省略此字段,避免切换时覆盖草稿。select 字段可声明 `changeAction`,选择变化时携带当前表单值调用动作并更新页面;失败时恢复选择,保留草稿。动作名遵循原有标识符校验。 diff --git a/docs/source-login.zh-CN.md b/docs/source-login.zh-CN.md deleted file mode 100644 index 8c2196e..0000000 --- a/docs/source-login.zh-CN.md +++ /dev/null @@ -1,12 +0,0 @@ -# 书源登录与插件管理 - -- 搜书页面仅保留来源选择、搜索、浏览和搜索结果。 -- OPDS 等声明个人凭据的来源:在“书源管理”中点击对应来源的“书源登录”。普通账号也可管理自己的凭据,来源配置仍由管理员维护。 -- Legado 规则书源:进入“书源管理 → 管理 → 书源订阅与管理”,展开具体规则,点击“书源登录”。需要 reader-source-legado 0.3.8 及以上版本。 -- 插件能力与兼容性位于“插件管理”的对应插件下。“安装或更新插件”默认收起。 - -Legado 登录支持 `loginUi` 的文本、密码、按钮控件,动态登录表单,`loginUrl` 登录脚本及 `loginCheckJs` 响应检查。密码不回显,登录会话按 Reader 账号、来源实例和书源规则隔离,加密保存,可退出清除。规则或目标地址变更不会复用旧会话。登录脚本完成不代表网站一定接受,需通过搜索或阅读确认。 - -网页登录在新窗口打开。Web 浏览器无法自动把第三方站点 Cookie 传给 Reader 服务器;完成登录后,在该规则的登录页面手动导入 Cookie 或 Authorization。此流程不提供 Android 内嵌 WebView 或 `startBrowserAwait` 的完整替代。 - -搜索超时后保留已取得的结果,可点击“继续搜索”。再次超时可缩小书源范围,并检查规则及登录状态。2026-09-24 使用报告对应的 128 条规则在本地和服务器分别完成 128/128,未复现报告中的 `PLUGIN_TIMEOUT`;未提高执行期限,不能据此认定其根因已经修复。 diff --git a/docs/source-plugins.md b/docs/source-plugins.md deleted file mode 100644 index c475dca..0000000 --- a/docs/source-plugins.md +++ /dev/null @@ -1,499 +0,0 @@ -# 来源插件系统设计 - -状态:内置来源、插件、配置 UI、章节富文本/图片与自动追更已实现 - -适用接口:`/api/v1`,来源插件协议 1 - -更新日期:2026-09-20 - -本文定义 reader 对本地书库、OPDS 书库和远程书源的统一扩展架构。目标是让核心程序只维护一套书架、阅读、缓存和任务逻辑;内置 `local`、`opds` 两种来源;远程书源以独立插件开发、安装和升级。 - -本文区分目标架构和当前交付。local、OPDS 下载、Node 来源插件、配置界面、持久化章节出版物、富文本/图片缓存、手动刷新和服务端自动追更已经接通。外部来源通过通用进程协议接入。P1 已增加用户主动预下载与配额检查,自动缓存淘汰仍未实现。交付状态见 §13,调用示例见 [API 参考](api.md#来源与插件)。 - -## 1. 目标与范围 - -### 1.1 目标 - -- 通过同一套来源接口支持本地书、OPDS 目录和远程章节书源。 -- 新增远程站点时只安装或更新插件,不修改核心路由、书架和阅读器。 -- 将来源协议复杂性封装在深模块内:调用方只理解发现、详情和获取内容。 -- 让文件内容和在线章节都进入现有 `manifest / toc / assets` 阅读协议。 -- 插件崩溃、超时或禁用时,不破坏书架、阅读进度和已经缓存的内容。 -- 插件升级保持来源引用和章节身份稳定,并支持可验证的状态迁移。 -- 通过能力声明、凭据隔离、网络权限和独立进程降低插件风险。 - -### 1.2 完整版本目标范围 - -包括: - -- 宿主插件注册表、安装/启用/禁用/升级流程。 -- 内置 `local`:扫描 `BOOKS_DIR`,复用现有格式处理器。 -- 内置 `opds`:支持 OPDS 1.x Atom、OPDS 2 JSON、导航、分页、搜索(若目录提供)和文件获取。 -- 外部 Node.js 进程插件及版本化 RPC。 -- 远程书源的搜索、详情、目录、章节正文和图片资源。 -- 宿主统一缓存、下载任务、限流、错误码和日志。 -- 来源配置 JSON Schema 和凭据引用。 - -不包括: - -- 插件直接替换阅读器 UI 或注入任意前端代码。 -- 不可信插件的完整操作系统级沙箱。首个切片只运行管理员明确安装的受信任插件;需要容器或系统沙箱时另行实现。 -- 自动把不同来源的版本合并为同一作品并迁移进度。先保留独立版本,后续可增加可选 `workId`。 - -## 2. 术语与设计原则 - -| 术语 | 定义 | -| --- | --- | -| 插件包(Plugin package) | 可安装、校验、升级的代码与声明,例如 `reader.source.example`。 | -| 来源类型(Source type) | 一套来源行为和配置规范,例如 `local`、`opds`、`demo-chapters`。 | -| 来源实例(Source instance) | 一个具体配置,例如 `/books`、某个 OPDS 地址或一个站点账号。 | -| 来源条目(Source entry) | 来源目录中的书,以 `(sourceInstanceId, externalId)` 标识。 | -| 出版物(Publication) | 可阅读的具体版本,拥有自己的目录、章节/文件和定位体系。 | -| 资源(Resource) | 文件、章节正文、图片、字体等可读取内容。 | -| 宿主(Host) | reader 服务端,负责插件调度和用户数据。 | - -设计遵循 `docs/architecture.md` 的数据边界:`BOOKS_DIR` 是用户书库,是否可写由挂载权限决定;`DATA_DIR` 存数据库、下载、缓存、扫描记录和插件状态。插件不直接访问宿主数据库,也不把任意路径或远程 URL 交给客户端。 - -来源接口是外部 seam。`local`、`opds` 和远程插件是该 seam 上的 adapter;宿主将鉴权、任务、缓存、资源流和错误语义放在接口之后,调用方不需要知道每个来源的协议细节。 - -## 3. 总体架构 - -```mermaid -flowchart TB - UI[书库/搜索/书架] --> API[来源 HTTP API] - API --> Host[SourceHost] - Host --> Registry[PluginRegistry] - Registry --> BuiltinRunner[BuiltinRunner] - Registry --> ProcessRunner[ProcessRunner] - BuiltinRunner --> Local[local adapter] - BuiltinRunner --> OPDS[opds adapter] - ProcessRunner --> Remote[外部来源插件] - Host --> Runtime[Runtime:HTTP/凭据/缓存/任务/日志] - Host --> Content[PublicationContent:manifest/toc/assets] - Content --> Reader[现有阅读器] - Local --> Content - OPDS --> Content - Remote --> Content -``` - -### 3.1 模块职责 - -| 模块 | 职责 | 不负责 | -| --- | --- | --- | -| `PluginRegistry` | 发现插件包、校验 manifest、选择版本、记录状态 | 不执行来源业务 | -| `SourceHost` | 将来源调用包装成统一接口;管理实例、能力、超时、任务 | 不解析具体网站规则 | -| `BuiltinRunner` | 在宿主进程内运行受控的 `local` 和 `opds` adapter | 不加载外部任意代码 | -| `ProcessRunner` | 启动和监督外部插件进程,执行 RPC、取消和资源流 | 不拥有书架或用户数据 | -| `Runtime` | HTTP、凭据、命名空间存储、缓存、限流、日志、取消 | 不定义来源协议 | -| `PublicationContent` | 将文件或章节绑定转换为统一阅读协议 | 不负责搜索和目录发现 | -| `JobManager` | 下载、扫描、刷新目录、离线缓存、重试和进度 | 不修改插件内部状态 | -| `Book/Shelf` | 持久化 publication、书架、进度、笔记 | 不根据书名猜测来源身份 | - -## 4. 来源接口 - -接口以 [`server/src/sources/types.ts`](../server/src/sources/types.ts) 为准。以下摘录首个切片的 SDK 契约;可选能力通过 `capabilities` 声明,注册表拒绝声明能力却缺少对应方法的提供者。 - -```ts -interface SourceProvider { - readonly descriptor: SourceDescriptor; - validateConfig?(config: unknown): void | Promise; - browse?(ctx: SourceContext, request: BrowseRequest): Promise; - search?(ctx: SourceContext, request: SearchRequest): Promise; - detail(ctx: SourceContext, entryRef: string): Promise; - acquire(ctx: SourceContext, request: AcquireRequest): Promise; - openFile?(ctx: SourceContext, - acquisition: Extract): Promise; - getManifest?(ctx: SourceContext, publicationRef: string): Promise; - readResource?(ctx: SourceContext, request: ResourceRequest): Promise; -} -``` - -`SourceProvider` 的接口保持小而稳定。适配器内部可以实现规则解析、登录流程、分页协议和站点兼容逻辑;宿主只依赖这些方法的输入、输出、取消、超时和错误不变量。 - -### 4.1 目录和条目 - -```ts -interface SourceDescriptor { - id: string; - label: string; - version: string; - capabilities: SourceCapability[]; - configSchema?: unknown; -} - -interface CatalogPage { - items: CatalogEntry[]; - navigation?: NavigationEntry[]; - nextCursor?: string; - title?: string; -} - -interface NavigationEntry { - ref: string; - title: string; - kind?: 'catalog' | 'search' | 'collection'; -} - -interface CatalogEntry { - ref: string; - title: string; - authors?: string[]; - description?: string; - language?: string; - coverUrl?: string; - options?: AcquisitionOption[]; - metadata?: Record; -} -``` - -`entryRef`、游标和导航引用由来源解释。宿主只做不透明保存和回传,不拼接 URL,也不把它当作数据库主键。 - -### 4.2 内容获取 - -```ts -type Acquisition = - | { kind: 'ready'; publicationId: string } - | { kind: 'file'; acquisitionRef: string; mediaType: string } - | { kind: 'chapters'; publicationRef: string } - | { kind: 'action-required'; action: AcquisitionAction }; -``` - -`Acquisition` 是提供者返回给宿主的内容绑定。`local` 可以返回已经存在的 `publicationId`;远程提供者返回文件或章节引用,由宿主分配稳定身份并处理获取流程。任何 `ready` ID 都必须由宿主验证确实存在且调用用户有权访问,不能直接信任外部插件的声明。后续引入持久化任务时,HTTP 响应可新增 `pending/jobId`,它不是首个切片的插件返回值。 - -文件内容和章节内容由宿主内部统一为: - -```ts -interface PublicationContent { - manifest(ctx: ReadContext): Promise; - toc(ctx: ReadContext): Promise; - asset(ctx: ReadContext, ref: string): Promise; -} -``` - -SDK 的 `ResourceResponse` 支持 `mediaType`、`size`、`data`、`text` 和 `stream`。内置 OPDS 使用流下载;进程插件暂只支持章节,`acquire.file` 会被拒绝。进程资源通过有大小上限的 `text/base64` JSON 传输;入库章节接受 UTF-8 纯文本或 HTML/XHTML,HTML 内插图通过 `reader-res:` 引用同一插件的二进制资源。宿主清洗并内嵌图片后才返回给阅读器。来源开发预览始终返回 JSON。 - -### 4.3 能力 - -首个切片的能力枚举: - -```text -browse -search -detail -acquire.file -acquire.chapters -content.manifest -content.resource -content.update -``` - -来源级能力决定 UI 是否显示入口;条目级 `options` 决定本书是否支持某种格式、下载或试读。当前来源接口的能力缺失返回 `SOURCE_UNSUPPORTED`;完整错误分类目标见 §8.2。 - -## 5. 插件包与 SDK - -### 5.1 manifest - -```json -{ - "id": "reader.source.example", - "name": "示例远程书源", - "version": "1.0.0", - "apiVersion": 1, - "runtime": "node", - "entry": "dist/main.js", - "sourceTypes": [ - { - "id": "example", - "label": "示例书源", - "capabilities": ["search", "detail", "acquire.chapters", "content.manifest", "content.resource"], - "configSchema": { "type": "object", "properties": {} } - } - ], - "permissions": { - "network": { "domains": ["example.com", "*.example.com"] }, - "storage": true, - "credentials": true - } -} -``` - -目标安装流程校验插件 ID、版本、宿主 `apiVersion`、入口文件、来源类型唯一性、JSON Schema 和权限。首个切片的 manifest 校验集中在 [`registry.ts`](../server/src/sources/registry.ts),进程启动另行检查支持的协议版本和入口路径。语义化版本范围、包内容哈希、签名和完整权限 schema 校验属于后续包管理工作。 - -### 5.2 宿主能力 - -SDK 的目标能力如下。独立进程尚未实现宿主能力的反向 RPC;已实现的凭据注入会在每次调用时,按用户、来源实例、`credentialKeys` 和 `permissions.credentials` 选择允许传递的键,放入 `context.credentials`。这不等于以下全部运行约束都已强制生效: - -| 能力 | 规则 | -| --- | --- | -| `http` | 超时、重定向检查、Cookie、限流和允许域名均由宿主执行。 | -| `credentials` | 按用户和来源实例隔离;插件只能通过引用读取,日志自动脱敏。 | -| `storage` | 插件/来源实例命名空间 KV,带 schema 版本;不能访问 SQLite。 | -| `cache` | 由宿主控制配额和淘汰;缓存键含来源、账号和资源身份。 | -| `logger` | 结构化日志、级别和脱敏由宿主控制。 | -| `signal` | 每次调用都带取消信号、截止时间和最大响应大小。 | - -宿主不提供前端 DOM 和数据库接口。首个切片中的受信任 Node 进程仍可使用 Node 的网络、文件和子进程能力,独立进程只提供故障隔离;系统沙箱落地后才可以强制限制这些直接调用。 - -### 5.3 RPC - -首个切片采用一行一个 JSON 的 stdio JSON-RPC 2.0;stdout 只输出协议消息,插件日志写 stderr: - -```text -request = { jsonrpc: "2.0", id, method, - params: { sourceType, context: { instance, userId, credentials? }, ... } } -response = { jsonrpc: "2.0", id, result } -error = { jsonrpc: "2.0", id, error: { code, message, data? } } -``` - -宿主每次来源调用预算为 60 秒,同一来源实例最多并发 2 次,宿主共 8 次,超限返回 `429 RATE_LIMITED`。插件单次 RPC 预算为 30 秒,每条 JSON 消息上限为 2 MiB(包括 base64 和协议字段)。所有 RPC(包括详情、加入书架、正文与扩展页面/操作/任务)超时或取消时,只结束当前请求:宿主发送 `$/cancelRequest`,清理该请求的计时器和监听器并忽略迟到响应,其它调用及后续请求继续使用同一进程。RPC 超时或 `TimeoutError` 信号返回 `PLUGIN_TIMEOUT`,主动取消返回 `PLUGIN_CANCELLED`。声明 `search.session` 的 `searchCancel` 控制请求不占用普通调用槽位,宿主等待确认最多 5 秒;取消或超时只结束等待,不再向其发送取消通知,让迟到的停止操作仍有机会清理搜索会话。插件应优先处理停止请求,并为断开的搜索设置空闲回收机制。 - -取消通知是尽力而为的协作机制,插件应按请求 ID 中断对应的网络、浏览器和解析任务;不处理通知的插件仍可能继续执行已超时的操作。超时不表示操作尚未生效,宿主不自动重复 `acquire` 等可能有副作用的调用。进程自身崩溃、输入管道损坏、协议错误或响应超过消息上限时,宿主仍会终止 worker,全部在途调用失败;进入 `failed` 后可由管理员重新启用。若插件的事件循环阻塞或内部队列被未取消任务占据,其后续调用仍可能超时,需要插件自身修复或管理员重新启用。 - -## 6. 内置来源 - -### 6.1 `local` - -- 自动创建 `local` 实例,配置固定为 `{}`,使用宿主 `BOOKS_DIR`;首个切片不支持每个实例覆盖目录。文件管理写入是否可用取决于 `BOOKS_DIR` 的挂载权限。 -- 由宿主扫描器负责增量检测,路径必须通过 `resolveInside()`,不跟随越界符号链接。 -- 文件格式继续复用现有 `server/src/indexer/formats` 处理器。 -- 本地文件作为 `Publication` 的 `file` 绑定;书籍身份继续遵循现有 `content_hash` 规则。 -- 文件读取继续保持原接口的缺失错误语义(如 `FILE_MISSING`);本轮不改已有书架、进度及扫描清理规则。 - -### 6.2 `opds` - -- 支持 OPDS 1.x Atom 和 OPDS 2 JSON;解析导航、分页、搜索入口、封面和 acquisition link。 -- 不假设每个链接都可下载。根据 `rel`、`type` 和条目状态产生 `AcquisitionOption`。 -- 首个切片支持公开或 Basic 认证的 EPUB、PDF、TXT、CBZ 下载;借阅、购买、试读等无法直接获取的关系返回 `action-required`。 -- 来源地址、用户名、附加下载 origin 由管理员配置并共享;密码通过凭据接口按用户和来源隔离,以 AES-256-GCM 加密保存。密码不写在普通配置中。 -- 导航和 Feed 请求限制在配置地址的 origin,附加下载 origin 必须列入 `allowedOrigins`;每次重定向重新校验,跨 origin 不转发 Basic 凭据。此策略允许管理员配置内网 OPDS,不等于系统级网络隔离。 -- 下载同步完成后返回 `ready`,没有后台任务 ID。临时文件写入 `DATA_DIR/acquired`,单文件最大 256 MiB;完成后计算真实 SHA-256、解析格式、原子改名并事务写入 `books`、`acquired_files`、`source_acquisitions`,加入调用用户书架。超限、取消和入库失败清理本次文件;现有书籍元数据保持不变。 -- 下载后的 EPUB/PDF 走与 `local` 相同的格式解析和阅读路径。 - -### 6.3 外部远程书源 - -目标上插件负责搜索、详情、目录快照、正文清洗和图片引用;宿主负责缓存、限流、任务、权限和阅读协议。插件返回 `chapters` 绑定后,宿主获取目录快照、分配稳定 book ID 并加入调用用户书架;HTTP 返回 `ready/publicationId`,阅读器继续使用 `/books/:id/manifest|toc|assets`。 - -入库阅读支持 UTF-8 `text/plain`、`text/html` 和 `application/xhtml+xml`。纯文本由客户端转义排版;HTML 经 `sanitize-html` 白名单处理,只保留段落、标题、强调、列表、表格等静态标签。删除脚本、样式、表单、外链和 SVG。插图须声明 `reader-res:<插件资源引用>`,宿主调用同一来源 `readResource`,校验 PNG/JPEG/GIF/WebP 类型与文件签名,再内嵌 data URL。整章(含图片)原子缓存,任一资源失败不写半份缓存。禁用或卸载插件后已缓存正文和插图仍可读。 - -刷新目录通过 `POST /books/:id/refresh` 或订阅调度触发;阅读器目录面板以稳定 href 恢复当前位置。失败保留旧目录,界面在目标章节可读后才替换视图。`chapter_subscriptions` 持久保存开关、15~10080 分钟间隔、检查时间、失败次数和新增章提示。每分钟调度一次,单轮最多 20 本顺序检查,共用来源并发限制;手动与自动检查同书合并在途调用。失败退避,暂停来源、隐藏书籍、禁用账号时跳过,关闭浏览器不影响检查。新目录不强行替换正在阅读的旧快照,也不预下载正文。 - - -## 7. 数据模型 - -实现使用增量表,保留已有 `books`、`book_files`、`user_books` 和 `reading_progress`,没有重写旧书 ID: - -| 表 | 当前用途 | -| --- | --- | -| `source_instances` | 共享来源配置:`id/plugin_id/source_type/name/config_json/enabled/created_at`。 | -| `source_credentials` | `(source_id, user_id, key)` 对应的加密凭据。 | -| `acquired_files` | `book_id` 对应的 `DATA_DIR` 相对文件路径和大小,与扫描目录分离。 | -| `source_acquisitions` | `(source_id, user_id, entry_ref, option_id)` 到 `book_id` 的映射。 | -| `chapter_publications` | 按用户隔离的章节出版物、来源引用、当前 revision 和目录快照。 | -| `chapter_snapshots` | 出版物历次目录快照;刷新后保留旧 revision。 | -| `chapter_resources` | 每个 revision 的章节引用、已缓存正文、`media_type` 和正文 SHA-256;HTML 正文包含校验后的内嵌图片。旧缓存增量迁移为纯文本。 | -| `chapter_subscriptions` | 每书追更开关、间隔、检查时间、失败退避、新增章数及配置 generation。 | -| `plugin_storage` | 宿主 KV,按来源和用户命名空间保存;外部进程尚无反向访问接口。 | -| `installed_plugins` | 插件 ID、已放置的包目录名及启用状态。 | - -来源实例由管理员配置,对登录用户共享。凭据、获取记录和书架属于当前用户;普通用户的来源列表不返回 `config`。同一插件条目可能因账号返回不同正文,因此章节出版物和缓存也按用户隔离,不与他人共享 book ID。禁用来源不删除已下载文件和章节缓存。 - -当前章节关系如下: - -```text -books (format=chapters) - └─ chapter_publications (book_id, user_id, source_id, publication_ref, revision) - └─ chapter_snapshots (book_id, revision, snapshot_json) - └─ chapter_resources (book_id, revision, chapter_id, provider_ref, body?) - ├─ user_books - ├─ reading_progress - └─ notes -``` - -约束: - -- 章节 book ID 由 `(source_instance_id, user_id, publication_ref)` 派生;唯一约束与之对应。反复获取和重新上架沿用同一个 ID。 -- `external_ref`、OPDS URL、章节序号都不是 `publicationId`。 -- `books.content_hash_kind` 是增量字段,旧数据默认 `file`。章节使用 `manifest`,`content_hash` 为规范化目录的真实 SHA-256,不冒充整书文件哈希,也不参与文件去重。 -- 章节必须有稳定 ID。`href` 由该 ID 派生,顺序单独保存;插章不会让旧进度指向另一章。资源的 `resourceRef` 另含目录 revision,客户端用 href 保存位置,用 resourceRef 取正文和缓存。 -- revision 包含目录内容和插件的可选 `version`。即使目录不变,正文修订时插件也必须改变 `version`;否则宿主继续复用已缓存正文。 -- 同一个 resourceRef 的缓存内容不变。旧 revision 已缓存的章节可继续读;旧 revision 未缓存的章节返回 `409 CHAPTER_SNAPSHOT_EXPIRED`,避免取到上游当前正文后冒充旧版。刷新期间发生的资源请求也遵守此规则。 -- 来源失效或插件禁用后,已缓存出版物仍可读;卸载插件默认保留用户数据。现阶段历史快照和正文尚无总配额及自动淘汰策略。 -- 初期不同来源版本不自动合并进度;未来的作品聚合只提供迁移建议。 -- 插件状态写入自己的 namespace,状态迁移失败时保持旧版本或回滚。 - -## 8. 生命周期与故障语义 - -### 8.1 插件生命周期 - -```text -发现 → 校验 → 安装 → 启用 → 健康检查 → 运行 - ↓ - 禁用 / 故障 -``` - -当前安装流程:管理员在 Web 输入 npm 包名或上传 `.tgz`,显式确认信任代码。服务端在 `DATA_DIR/plugins` 中创建独立依赖目录,使用 npm 安装并禁用生命周期脚本,校验真实路径、manifest、入口和来源类型,保存安装记录并自动启用。同 ID 的不同版本自动进入更新流程;相同版本返回中文重复安装提示。失败清理本次目录,不影响已有插件。预部署目录加载接口仍保留,重复加载不会自动覆盖。启动时自动恢复启用的插件。启用、禁用、卸载和更新切换串行执行,禁用先注销提供者再终止进程;卸载移除安装记录,保留包文件、来源实例和已有用户数据。内置 `reader.local`、`reader.opds` 不允许卸载或替换。 - -已实现的在线更新流程: - -1. 下载到独立安装目录,校验包、manifest、API 版本、路径和来源接口。 -2. 检查已有来源实例使用的类型和能力是否仍存在,并用新版 `validateConfig` 校验每个实例的原配置(包括停用实例)。校验失败保留旧版本。 -3. 若旧插件仍有在途 RPC 或管理/后台写入操作,返回 `PLUGIN_BUSY`,由管理员停止搜索或等待后重试。 -4. 在同一次同步切换中更换提供者及安装记录;数据库写入或注册失败则恢复原提供者。成功后停止旧进程并启用新版。 -5. 保留来源 ID、配置、凭据、订阅、插件数据目录、书架及缓存;旧包目录也保留。重启按新的安装记录恢复。 - -宿主不会执行插件数据迁移,也不对插件自行写入的数据提供快照回滚。插件的配置校验应无副作用,版本间需要保持自己的数据格式兼容。签名校验、自动迁移和一键版本回滚尚未实现;管理员可再次上传兼容的其它版本切换代码。 - -插件禁用不删除来源实例、publication、缓存和进度。删除数据是单独的显式操作。 - -### 8.2 统一错误 - -```text -AUTH_REQUIRED 需要登录或凭据过期 -RATE_LIMITED 来源限流 -SOURCE_CHANGED 站点结构或规则失效 -RESOURCE_GONE 远程或本地资源不存在 -CAPABILITY_UNSUPPORTED 当前条目不支持该能力 -PLUGIN_UNAVAILABLE 插件未运行或崩溃 -TIMEOUT 宿主截止时间已到 -QUOTA_EXCEEDED 缓存或下载配额不足 -``` - -该列表是完整版本的错误分类目标。当前 HTTP 响应保持 `{ "error": { "code", "message" } }`,具体已实现错误码以 [API 参考](api.md#错误码) 为准,例如 `SOURCE_TIMEOUT`、`PLUGIN_TIMEOUT`、`RATE_LIMITED`。`retryAfter/details` 未在本轮通用错误响应中实现。 - -## 9. 安全与资源边界 - -以下区分当前强制约束与后续安全工作;不能把 manifest 权限声明当作已生效的系统策略。 - -- 外部插件默认独立进程运行;插件进程崩溃不能让宿主退出。 -- 内置 OPDS 的网络请求经过宿主校验:允许 origin、重定向目标、Basic 凭据转发、超时和响应大小;普通 OPDS 链接不能跳到未配置的 origin。 -- 外部 Node 插件当前是受信任进程,仍拥有本机 Node 的网络、文件和子进程权限;manifest 权限声明和 `SourceContext` 可选能力尚未构成 OS 级网络沙箱。管理员只能安装信任的包。 -- 插件凭据不出现在普通配置、前端 DTO 和日志中。 -- 资源预览只返回 JSON;阅读正文纯文本转义或 HTML 白名单清洗,并带 `nosniff`、禁止脚本和外网资源的 CSP。图片经来源通道获取后内嵌,不让浏览器直接访问书源网站。 -- 本地和已获取文件路径通过宿主 `resolveInside()` 校验;外部插件直接读写路径的能力目前依赖管理员信任,系统沙箱属于后续工作。 -- 硬限制:宿主调用及整章加载 60 秒、插件 RPC 30 秒、JSON 2 MiB、文件获取 256 MiB;目录最多 10,000 项及 2 MiB,原始正文 2 MiB;最多 32 个不同图片、每图 2 MiB,内嵌后整章最多 8 MiB。图片仍受 RPC base64 开销限制。CPU/内存和域名权限的系统级隔离属于后续工作。 -- 插件安装及来源实例配置需要管理员权限;实例配置共享,凭据按用户隔离。 - -manifest 中的权限声明用于宿主授权和展示,不能单独视为安全沙箱;运行不可信插件需要容器或操作系统策略。 - -## 10. 当前 HTTP 接口 - -均位于 `/api/v1` 并遵循现有认证和错误格式: - -```text -GET /plugins 插件及版本状态 -POST /plugins 安装 npm 包(package)或加载预部署目录(folder) -POST /plugins/upload 上传 .tgz,安装并启用 -PATCH /plugins/:id 启用/禁用(enabled) -DELETE /plugins/:id 卸载注册(保留包文件和数据) - -GET /sources/types 当前已注册来源类型 -GET /sources 来源实例列表 -POST /sources 创建来源实例 -PATCH /sources/:id 仅修改 enabled -PUT /sources/:id/credentials/:key 设置当前用户凭据 -GET /sources/:id/browse 浏览目录 -POST /sources/:id/search Streamable HTTP 搜索(SSE results/done/error 事件) -GET /sources/:id/entries?ref=... 详情 -POST /sources/:id/acquire 获取内容,body 传 entryRef -GET /sources/:id/publications/:publicationRef/manifest -GET /sources/:id/publications/:publicationRef/resource?ref=... -POST /books/:id/refresh 获取并提交新的章节目录快照 -``` - -HTTP 返回宿主 DTO,凭据不回显。插件和来源配置管理需管理员权限;浏览、获取和个人凭据需登录。`PATCH /sources/:id` 更新名称/config/启停,config 变更清除所有用户的该来源凭据;有在途来源调用时拒绝变更 config。`DELETE` 只移除无获取记录的非本地来源。Web `#/sources` 根据类型 schema 绘制配置表单,普通成员只有浏览、凭据和个人追更操作。插件可声明 credentialKeys 与 credentials 权限,宿主只按调用用户向进程传递明确声明的键。Web 输入 npm 包名或上传安装包均支持更新同 ID 的已安装插件。 - -## 11. 分阶段实施 - -### 阶段一:内容 seam 与内置 local - -- 抽取 `PublicationContent`,让现有 `/manifest`、`/toc`、`/assets` 不再直接依赖 `book_files → absPath`。 -- 将现有扫描和格式处理包装为 `local` adapter。 -- 保留旧 `bookId`、进度、笔记和书架语义,补充 publication 映射。 -- 验收:已有 EPUB/TXT/PDF/漫画书籍、阅读进度和离线缓存行为不变。 - -### 阶段二:SourceHost 与内置 OPDS - -- 实现来源注册、实例配置、能力 DTO 和 `JobManager`。 -- 实现 OPDS 1.x/2.x 解析、分页、详情和 EPUB/PDF 下载。 -- 下载文件进入 `DATA_DIR`,复用 local 的内容解析链路。 -- 验收:OPDS 书可浏览、搜索(若服务支持)、下载、阅读和重启恢复;失败任务可重试。 - -### 阶段三:插件管理与 ProcessRunner - -- 定义 manifest、SDK、RPC、插件目录和生命周期。 -- 增加一个最小章节插件,验证搜索→详情→目录→正文→图片完整链路。 -- 增加超时、取消、进程崩溃恢复、错误映射和插件状态迁移。 -- 验收:插件无需修改核心代码即可新增来源;禁用插件不影响已缓存内容。 - -### 阶段四:远程书源生态 - -- 实现配置表单、凭据动作、章节缓存和目录刷新。 -- 开发独立来源插件,并使用通用协议验证接入。 -- 建立契约测试样例:分页、登录、限流、规则失效、插章和图片资源。 -- 验收:导入一个书源配置即可创建来源实例;更新规则只升级插件/配置,不改阅读器。 - -## 12. 验证与兼容策略 - -每个 adapter 和插件都必须通过宿主契约测试: - -- 能力声明与实际方法一致。 -- 所有调用支持取消、超时和稳定错误码。 -- 外部引用保持可重复解析;章节 ID 在刷新后稳定。 -- 资源流不会被 JSON 编码截断或超出大小限制。 -- 凭据和缓存按用户/来源实例隔离。 -- 插件崩溃、禁用、升级失败时,书架和已缓存 publication 仍可访问。 - -宿主阅读 API 继续遵循现有长期兼容策略:为章节增加 `revision/resourceRef` 字段和刷新端点,已有文件资源形状保持不变。数据库迁移只新增表和带默认值的列;章节使用明确标记的目录哈希,不伪造整书文件哈希。设备端章节目录、正文、书架和进度缓存按服务地址与用户隔离;升级时恢复已有会话可一次性迁移旧书架、进度和待同步操作,新账号登录不认领旧缓存。 - -## 13. 本轮实施状态与后续工作 - -已交付来源管理 UI、章节富文本/插图与追更订阅;外部来源通过独立 Node.js 进程接入。后续条目不能视为已交付。 - -| 工作 | 本轮状态 | 说明 | -| --- | --- | --- | -| 来源契约 | 已实现并测试 | `server/src/sources/types.ts`,包括目录、获取、章节和资源。 | -| 来源注册表及 manifest 校验 | 已实现并测试 | 验证能力与方法一致,校验插件 DTO、章节 ID 和顺序。 | -| OPDS 解析、浏览、搜索、获取 | 已实现并测试 | OPDS 1.x/2.x、相对链接、OpenSearch、分页、Basic 认证和获取关系。 | -| OPDS 文件下载入库 | 已实现并测试 | 同步下载,真实哈希、256 MiB 上限、失败清理、幂等复用、当前用户上架;复用现有阅读接口。 | -| SourceHost、来源实例及凭据 | 已实现 | 实例由管理员配置共享,密码按来源/用户加密,调用预算 60 秒;并发限额每实例 2、全宿主 8。 | -| 来源管理与配置 UI | 已实现并测试 | 创建、编辑、启停、删除空来源、浏览/搜索、获取及个人凭据。 | -| 内置 local 与本地内容 seam | 已实现并测试 | 保留现有 book ID、书架及阅读接口,集中本地与下载文件解析。 | -| 受信任 Node ProcessRunner | 已实现并测试 | JSON-RPC、30 秒调用预算、所有请求的超时/取消隔离、停止请求隔离、异常退出、2 MiB 消息上限。 | -| 插件安装、启停、卸载与启动恢复 | 已实现并测试 | Web 安装 npm 包或上传 .tgz;失败清理本次目录,卸载保留数据和包文件。 | -| 最小外部来源示例 | 已实现并测试 | `examples/plugins/demo-chapters`,提供静态示例目录和正文,不联网。 | -| 插件安装 UI | 已实现 | 输入 npm 包名或上传 .tgz 后安装/更新并启用;保留来源配置和数据,失败保留原版本;支持启停、重启、卸载。一键版本回滚仍后续。 | -| 后台下载任务、断点恢复、JobManager | 后续 | 当前完整文件会持久化,下载过程本身没有后台任务及恢复机制。 | -| 外部章节写入书架与阅读 | 已实现并测试 | 私有稳定 book ID、现有 manifest/items/toc/assets、书架、继续阅读和进度。 | -| 目录快照与服务端章节缓存 | 已实现并测试 | 稳定 href、revision 资源引用、已读缓存、失败保留旧目录、禁用/卸载/重启后缓存可读。 | -| Web 章节阅读与设备离线缓存 | 已实现 | 目录与已读章节按服务器和用户持久缓存;断网或服务端 5xx 时回退;授权及资源不存在错误不回退。 | -| 手动刷新目录 | 已实现 | 阅读器目录面板入口,恢复当前章节位置,记录检查状态。 | -| 远程富文本与图片 | 已实现并测试 | 白名单 HTML、受控栅格图片、服务端与设备整章缓存;设备仅已读内容可离线。 | -| 整书预缓存、缓存配额与淘汰 | 后续 | 保留历史目录与缓存,无自动清理配额。 | -| 自动追更 | 已实现并测试 | 用户按书订阅,服务端定时检查、持久状态、失败退避与新增章提示。 | -| 声明凭据注入 | 已实现并测试 | 每次调用仅传递获准声明键,按用户和来源隔离。 | -| 反向宿主能力 RPC、系统权限隔离和缓存配额 | 后续 | 类型预留不等于运行策略已生效。 | -| 容器/操作系统沙箱 | 后续 | 首个版本仅允许运行管理员信任的插件。 | - -验证覆盖来源、插件进程、管理接口、OPDS 下载、用户隔离、并发限额、参数校验与既有本地阅读回归。章节端到端测试使用真实 Node 进程和可变目录 fixture,覆盖获取幂等、插章定位、版本缓存、旧快照拒绝、刷新失败、禁用/卸载/扫描/重启、媒体类型不一致拒绝及 HTML 清洗;核心测试另覆盖旧缓存迁移、请求与刷新并发及资源边界。原生规则插件测试使用真实 Node 进程和本地 HTTP fixture,覆盖 npm 安装、按用户 Cookie、插章后按 URL 定位、图片缓存和追更;包测试另覆盖真实 Chromium 与脚本兼容对象,未验证特定公网 OPDS 服务或第三方采集站点。 - -回归入口:在 `server` 和 `web` 分别执行 `npm test`;两端另提供 `npm run typecheck` 和 `npm run build`。测试结果以对应提交的 CI 输出为准。界面评审记录见 [书源界面](ui-review/sources-ux.md)和[书库与阅读界面](ui-review/collections-ux.md)。 - -## 通用配置页、任务、筛选与换源 - -已实现 manifest.extensions.pages/tasks、独立数据目录、声明式页面、通用后台任务、search.filters 与 content.alternatives。详情、责任分配和失败语义见[扩展设计](plugin-extensions.md)。这些扩展不依赖具体插件 ID。 - -### 0.3 实例配置作用域 - - - -来源实例可声明独立配置页面与后台任务,同一插件的多个实例互不共享配置。页面的 Tab、表单和输出由通用 DTO 定义,见[扩展协议](plugin-extensions.md)。 - -## P2 接入体验补充(2026-09-24) - -来源页按 descriptor 展示能力声明,不把声明当作站点可用性保证。个人凭据页显示配置状态和最近访问结果,用户可以编辑、保留或删除指定字段;不回显秘密。 - -插件遇到未登录、登录过期、人工验证时应分别抛出 AUTH_REQUIRED、AUTH_EXPIRED、VERIFICATION_REQUIRED(也可作为搜索部分失败项返回)。不要将登录页面当作成功正文返回。宿主不会识别任意站点的登录页面或自动绕过验证码;实际登录、验证码和网站适配仍由插件负责。未提供会话过期时间时,界面不估算过期时间。 - -换源的质量检测复用 acquire / getManifest / readResource,可能拉取内嵌图片;不要在这些读取调用中加入不可重入的副作用。检测结果是一次快照,确认换源时会重新读取并验证。宿主拒绝空白正文;正文正确性、缺段与广告识别仍须插件验证。 - -生态协议和客户端覆盖范围见 [独立方案](ecosystem-roadmap.zh-CN.md),交付证据见 [P2 记录](p2-progress-2026-09-24.md)。 diff --git a/docs/ui-review/collections-ux.md b/docs/ui-review/collections-ux.md index 59f19f2..f44a852 100644 --- a/docs/ui-review/collections-ux.md +++ b/docs/ui-review/collections-ux.md @@ -14,13 +14,11 @@ 浏览器脚本使用可控 API fixture;没有上传实际文件,也未进行 Android/iOS 真机测试。 -电脑端适配(2026-09-21):从 1024px 起,书架导航与搜索并排,书架、书库、书源和文件管理统一使用最大 80rem 内容宽度与两侧留白。文件操作收至标题右侧,列表采用文件名、元数据、菜单分列布局。书架设置改为右侧 26rem 面板,支持 Esc 关闭并恢复触发按钮焦点;缩窄窗口时恢复底部 sheet。书源及通用插件页面使用紧凑左对齐 tab,标题与正文保持统一宽度。 +电脑端适配(2026-09-21):从 1024px 起,书架导航与搜索并排,书架、书库、书源和文件管理统一使用最大 80rem 内容宽度与两侧留白。文件操作收至标题右侧,列表采用文件名、元数据、菜单分列布局。书架设置改为右侧 26rem 面板,支持 Esc 关闭并恢复触发按钮焦点;缩窄窗口时恢复底部 sheet。 -桌面验证:生产 Web 在 Chromium 中覆盖 1024×768、1366×768、1920×1080;检查书架、书库、文件列表、设置侧栏、键盘焦点、暗色主题和打开面板时跨断点缩放;同时保留 320/390px 手机回归及短视口吸顶断言。34 项书架/书库组件测试通过;真实 HTTP 服务、SQLite、Node 插件的订阅、隔离、筛选搜索、入架、阅读和换源端到端通过。桌面截图为 `collections-*-desktop-*.png`,插件页面截图为 `plugin-config-desktop-*.png`。尚未验证 Firefox、Safari。 阅读页桌面适配:正文采用 52rem 居中纸张区域,顶栏与纸张对齐;底部使用 50rem 悬浮控制条,进度与操作按钮用分隔线区分。纸张外围背景跟随当前主题,浅色、米黄、浅绿和夜间主题均使用主题色。目录使用左侧面板,界面、朗读和设置使用右侧面板,遮罩降低深度以便预览正文。面板支持 Esc 关闭及焦点恢复,聚焦不触发页面滚动。`desktop-reader.mjs` 验证三种桌面尺寸下四个面板、工具栏显隐、正文尺寸/页码/滚动位置不变、翻页模式、夜间主题,以及 1024×420 短窗口的滚轮操作。6 项阅读工具栏组件测试及移动端 `reader-regression.mjs` 全部通过,后者覆盖正文翻页、阅读信息、主题、插图、漫画、PDF 和 320px 面板。截图为 `desktop-reader-*.png`。 -宽度回归:书库、书源主页、插件配置页共用 `--collection-measure`。在 1024/1366/1920px 下逐页比较内容容器及标题的左右坐标和宽度,断言相等;同时验证插件配置的嵌套卡片对齐正文边界,避免只有外层变宽而卡片仍受旧限制。 正文翻页回跳修复:滚动模式原先用整章高度的 `100%` 做滑动动画,实际滚动 619px 后又产生约 3089px 的动画位移。现在用本次真实滚动距离,同时限制章末对齐位置不超过可滚动范围,避免最后一页页码失真。`page-turn-regression.mjs` 在 1366/390px 下逐帧采集正文坐标及滚动偏移,验证从首翻至末、再翻回首时不反向移动,且每次恰好改变一页;修复前该脚本能重现失败,修复后通过。构建、80 项 reader-view/shadow 测试及移动阅读回归通过。 diff --git a/docs/ui-review/source-search.md b/docs/ui-review/source-search.md deleted file mode 100644 index 0430fae..0000000 --- a/docs/ui-review/source-search.md +++ /dev/null @@ -1,9 +0,0 @@ -# 书源搜索反馈与布局验证 - -前端通过 POST Streamable HTTP 接收 `results` 事件并按 ref 合并结果,收到 `done` 或 `error` 后结束。宿主按不透明游标继续拉取,直到搜索结束、用户停止或达到结果上限。搜索不再依赖前端轮询。来源内部如何组织请求由插件实现。 - -停止保留已有结果;退出页面、新搜索和停止后的迟到响应不得覆盖当前结果。通用 `CatalogPage.errors` 经过宿主校验,部分成功时折叠错误,没有结果且失败时展开原因。错误和无匹配采用不同空状态。 - -服务端协议及 API 测试覆盖流式输出、取消、用户隔离、结果上限和错误校验;Web 测试覆盖结果合并、停止、继续、迟到响应和错误反馈。 - -`node web/tools/ui-review/source-search.mjs` 使用生产 Web 与通用 fixture API,在 Chromium 验证 390/1024/1440/1920px 布局、键盘展开错误及搜索交互。预先构建 Web,可通过 `CHROME_PATH` 指定浏览器。这个测试验证宿主界面,不验证外部服务可用性。 diff --git a/docs/ui-review/sources-ux.md b/docs/ui-review/sources-ux.md deleted file mode 100644 index 555f6e0..0000000 --- a/docs/ui-review/sources-ux.md +++ /dev/null @@ -1,27 +0,0 @@ -# 书源端到端与 UI/UX 验证 - -## 测试入口 - -宿主只依赖自包含的 `examples/plugins/demo-chapters` 示例和通用页面 DTO。生产 Web、Fastify、SQLite 与独立 Node 进程共同验证注册、npm 插件激活、创建多个来源、来源搜索和章节阅读;测试使用临时数据目录。 - -先安装 `server` 和 `web` 依赖,安装 Web 的 Playwright Chromium,然后执行: - -```sh -npm run ui:sources --prefix web -node web/tools/ui-review/host-extension-page.mjs -node web/tools/ui-review/source-search.mjs -``` - -可以设置 `CHROME_PATH` 指向已有 Chrome。截图输出到 `docs/ui-review/`,默认不提交。后二者使用通用 fixture API,验证生产界面的交互。 - -## 覆盖范围 - -- 管理与搜索分开,来源类型和扩展入口由能力声明驱动。 -- 添加、编辑与凭据表单使用弹窗;组件测试覆盖关闭、保存失败、焦点返回与搜索状态保留。 -- 顶部 Tab 提供 ARIA 状态,支持方向键、Home 和 End。 -- 实例扩展页验证 Tab 草稿、表单保存、日志按纯文本渲染及移动/桌面布局。 -- 搜索反馈区分无匹配、全部失败和部分失败;结果不会因其它来源失败而丢失。 -- 换源失败保留原正文,成功从明确选择的章节开始。 -- 桌面书库、来源列表和实例配置使用一致的内容宽度;窄屏不得水平溢出。 - -页面协议和权限见[扩展设计](../plugin-extensions.md)。测试结果以当前命令输出与 CI 为准,不使用历史通过数量代替本次验证。视口测试不等于 Android 或 iOS 真机验证。 diff --git a/docs/ui.md b/docs/ui.md index be4bf28..f4a205e 100644 --- a/docs/ui.md +++ b/docs/ui.md @@ -412,7 +412,7 @@ URL 再回落到 `showPage(page)`。这一趟往返就是页能活过 Back、For 全局容器固定在视口底部并避开安全区,宽度随内容变化,最大 28rem,手机两侧至少留 1rem。 最多同时显示三条;加载提示持续显示,进度原位更新;普通提示默认 6–12 秒后消失,也可手动关闭。 成功、错误和加载共享主题样式,错误使用 `alert`,其它消息使用 `status`。 -服务端和插件返回的文案均按纯文本显示,不执行 HTML。 +服务端返回的文案均按纯文本显示,不执行 HTML。 容器和消息正文不拦截点击,关闭按钮可以操作,避免提示挡住阅读按钮。原生弹窗打开时,同一个容器移入弹窗的顶层, 关闭后回到 `body`;消息不抢焦点。提示出现、更新和关闭不得改变内容区尺寸或滚动位置, diff --git a/docs/user-guide.zh-CN.md b/docs/user-guide.zh-CN.md index 2227697..dac5076 100644 --- a/docs/user-guide.zh-CN.md +++ b/docs/user-guide.zh-CN.md @@ -34,7 +34,7 @@ 书籍身份与内容有关,不直接依赖文件路径。移动或重命名通常保留身份,相同内容副本会合并;修改文件内容可能改变识别结果。 -手动元数据覆盖保存在数据库中,优先于书内信息和文件名解析,重新扫描不会覆盖手动值。撤销手动字段后回到提取值。当前没有内置在线元数据抓取服务;远程书源插件与本地书籍元数据处理是不同功能。 +手动元数据覆盖保存在数据库中,优先于书内信息和文件名解析,重新扫描不会覆盖手动值。撤销手动字段后回到提取值。本地书籍当前没有内置在线元数据抓取服务;影音资料匹配见[影音手册](media-user-guide.zh-CN.md)。 ## 阅读设置 @@ -68,44 +68,37 @@ EPUB 章节按需加载,长书的目录与传输窗口分开处理,跨窗口 没有中文语音时,先检查设备安装的语音包和当前引擎。需要服务端语音时,参照 [HTTP 朗读配置](configuration.zh-CN.md#http-朗读)。 -## OPDS 与远程书源 +## OPDS 书库 -管理员管理来源实例;读者在来源中浏览、搜索、填写自己的凭据并获取书籍。local 和 OPDS 内置,其它来源通过插件提供。一个插件可添加多个来源实例,配置与管理页面从对应实例打开,具体选项由插件声明。 +管理员在「书源」中添加 OPDS 服务地址;需要认证时配置当前账号的凭据。打开来源可浏览、搜索并获取书籍,下载完成后加入书架。也可以通过[只读 OPDS 服务](opds-webdav.zh-CN.md)把 Reader 中的文件书提供给外部阅读器。 -安装插件:进入「书源 → 插件管理」,勾选信任代码,输入 npm 包名点击「安装并启用」,或切换到「上传安装包」选择 `.tgz` 文件点击「上传并启用」。支持 `@scope/包名`、`包名@版本` 和 `包名@标签`,上传上限 100 MiB。成功后到「书源管理」添加来源;安装期间请等待页面完成。失败会清理本次安装,不影响已有插件,表单可直接重试。已有插件的重复安装会被拒绝,不会覆盖其代码。 +## 影音入口 -搜书与管理分开。搜索选项由当前来源提供,结果通过 Streamable HTTP 陆续合并;搜索中可手动停止并保留已有结果。 +从书架「影音」进入电影、剧集、音乐和有声书。手机点击顶部频道名称切换,选择「阅读」返回书架。影音拥有独立设置、主题、收藏与播放页面,不改变阅读器和书架设置。 -支持章节阅读的来源可刷新目录和配置自动追更。声明换源能力时,目录中会显示换源入口;确认候选和起始章节后切换,保留书籍记录、书架及旧缓存。旧笔记、书签不会自动匹配到新章节。 - -实例后台任务由服务端执行,关闭网页不影响调度,暂停来源实例会停止其任务。 +管理员可添加本地目录或 OpenList 媒体库,配置权限、扫描与刮削;用户浏览已授权的内容并播放。建库、歌词、字幕、队列、倍速及睡眠定时见[影音使用说明](media-user-guide.zh-CN.md)。 ## 多用户与离线 首个账号是管理员,后续成员默认由管理员创建。每个账号的书架、进度、笔记和高亮独立。阅读界面参数属于当前设备,不随账号覆盖其他设备的设置。 -离线时可使用已经缓存的内容,重新连通后同步阅读状态。在阅读器底部「工具 → 离线缓存」可下载远程章节/TXT 的指定范围,或下载完整 EPUB、PDF、CBZ;自定义目录的 TXT 下载完整文件。任务支持暂停、继续和取消,关闭面板会暂停,已下载内容保留。默认设备账号配额为 256 MiB,可调整或按书清理;不自动淘汰,也不删除原书、进度、笔记。服务端缓存与当前设备缓存独立,只有本设备完成下载的内容才能保证断网读取。停用来源后新内容需要恢复来源;图片目录暂不支持整书下载。 +离线时可使用已经缓存的内容,重新连通后同步阅读状态。在阅读器底部「工具 → 离线缓存」可下载TXT 的指定范围,或下载完整 EPUB、PDF、CBZ;自定义目录的 TXT 下载完整文件。任务支持暂停、继续和取消,关闭面板会暂停,已下载内容保留。默认设备账号配额为 256 MiB,可调整或按书清理;不自动淘汰,也不删除原书、进度、笔记。服务端缓存与当前设备缓存独立,只有本设备完成下载的内容才能保证断网读取。图片目录暂不支持整书下载。 ## 进一步阅读 - [配置与故障排查](configuration.zh-CN.md) - [API:目录、资源、进度、上传和来源](api.md) - [数据边界与实现决策](architecture.md) -- [书源插件扩展](plugin-extensions.md) ## 阅读工具:搜索、笔记与内容整理 -- **书内搜索**:打开「工具 → 书内搜索」,输入文字后逐章检索,最多展示 200 个命中,支持停止。点结果定位并高亮原文,再次打开工具可返回搜索前的位置。支持 EPUB/TXT/远程文字章节;扫描 PDF 和图片不提供 OCR。未缓存章节需要联网。 +- **书内搜索**:打开「工具 → 书内搜索」,输入文字后逐章检索,最多展示 200 个命中,支持停止。点结果定位并高亮原文,再次打开工具可返回搜索前的位置。支持 EPUB/TXT;扫描 PDF 和图片不提供 OCR。未缓存章节需要联网。 - **高亮和批注**:先在正文选择文字,再打开「工具 → 笔记」,选择颜色并保存。填写批注即可形成笔记;无选区也可保存当前位置书签。支持编辑、删除、点击回正文,联网后沿用账号同步。原文变化导致定位不唯一时不会猜测位置。 - **多级目录**:EPUB nav/NCX 保留三级及更深层级和章内锚点,有子项的目录可展开、折叠,选择章节后关闭面板。 - **内容整理**:先选择文字,在「工具 → 内容整理」填写替换内容,留空可以过滤选区。修改以个人覆盖层保存在服务器 DATA_DIR 的 SQLite 中,不修改书籍文件。支持逐项移除和撤销上一次修改;跨设备并发保存冲突时需重新打开书籍。保存需联网,已缓存规则可离线应用。 - **TXT 目录**:可选择中文章回、Chapter、方括号模板,或输入自定义标题前缀,预览后应用;留空恢复默认识别。规则匹配不超过 80 字的标题行,不执行任意正则。重新划分章节后从首章打开,旧笔记保留但可能需要重新定位。预览需要完整 TXT 文件。 - **朗读检测**:按当前引擎试听。HTTP 引擎先实际请求合成,分别提示未配置、鉴权失败、超时、非音频和空音频。关闭面板或点击停止会释放试听;浏览器仍可能要求允许声音播放。 -## 书源质量、登录状态与电纸书 - -在“切换书源”中选择来源与章节,点击“检测所选章节 / 重试”,可查看字符数、图片数、大小和检测耗时。空章会给出错误;检测不会切换当前书籍。关闭选章弹窗后,候选列表保留本次检测摘要。确认换源仍会再次验证,失败保留原内容。检测通过不保证章节完整或与原书一致。 - -在来源页展开“插件能力与兼容性”,查看当前插件声明的能力;打开“登录凭据”查看哪些字段已配置和最近访问结果。未编辑字段会保留,清空后保存会删除。保存成功只代表已存储,请重新搜索或浏览来检查访问。需要人工验证时,到站点或插件提供的管理页面处理后重试,不必退出 Reader 账号。 +## 电纸书 阅读设置中的“应用电纸书预设”会切换为浅色、分页和无翻页动画,仅影响当前设备;其他选项仍可调整。该预设不控制电纸书全刷或硬件残影。浏览器验收范围与 OPDS/WebDAV 后续边界见 [生态互通方案](ecosystem-roadmap.zh-CN.md)。