Reading 阅读模块
受众:开发者、二次开发 Agent 摘要:Reading 模块用于作品、章节、付费章节 / 积分章节内容分发、后台作品 / 章节运营、用户书架和阅读进度。扣款、退款和资金账本由 Cashier / Payment / Money 底座承载。
模块定位
- Maven:
spring-open-module-reading - Java 包:
com.springopen.module.reading - API 前缀:
/api/v1/reading/** - 配置前缀:
spring.open.reading.* - 表前缀:
reading_
Reading 与 Blog、CMS、Mall、Video 平级,是可剥离业务模块。跨模块只保存标量 ID,不直接写资金账本。当前后端 contract、Admin 作品 / 章节运营页、章节购买订单运维页、App / PC 用户端入口、公开章节目录、关键词搜索、规则推荐榜单、阅读专题、我的推荐、书架、阅读进度、阅读历史、书签、阅读设置、离线阅读清单、本地离线缓存、付费章节、VIP 章节、积分章节、版权投诉处理、书源配置、健康摘要、受控批次导入、同步 Provider SPI、默认 OpenAPI 书源 Provider、手动同步、到期同步任务底座、书源更新提醒摘要、生产配置检查和授权书源验收 runbook 已落地,默认应用会装配 Reading;真实授权书源连通执行属于部署验收条件,不伪装为本地已完成。
当前能力
| 能力 | 说明 |
|---|---|
| 作品 | reading_work 保存作品标题、简介、封面、作者、访问类型、解锁价格和发布状态 |
| 章节 | reading_chapter 保存章节目录、正文、付费预览、访问类型、解锁价格和发布状态 |
| 购买订单 | reading_chapter_purchase_order 保存用户章节购买订单、金额、币种、支付 Provider、支付状态和退款失效状态 |
| 内容解锁 | 免费章节直接可读;付费 / 积分 / VIP 章节读侧统一通过 Entitlement ContentAccessPolicyService 判定作者直读、已支付订单 / 积分扣减直接解锁和 reading-paid-chapter / reading-vip-chapter 权益凭证;退款后订单变为 refunded 并立即失效 |
| 书架 | reading_shelf_item 保存用户作品书架、当前章节、最近阅读时间和排序时间 |
| 阅读进度 | reading_progress 保存用户在作品章节内的阅读位置、百分比和最近阅读时间 |
| 阅读历史 | GET /api/v1/reading/history 基于阅读进度返回当前用户最近阅读章节,App / PC 均可从历史继续阅读 |
| 书签 | reading_bookmark 保存用户章节书签、位置、百分比、标题和备注,支持章节内快速回到保存位置 |
| 阅读设置 | reading_preference 保存用户字号、行宽、主题和翻页模式;App / PC 阅读器会读取服务端偏好并同步本地显示 |
| 离线清单 / 本地缓存 | GET /api/v1/reading/works/{id}/offline-manifest 生成当前用户的作品离线阅读清单;免费或已解锁章节返回全文,未解锁章节只返回预览、锁定状态和阅读偏好。App / PC 会把生成结果保存到当前设备本地缓存,并在我的书架 / 账号阅读页展示缓存状态 |
| 版权投诉 | reading_copyright_complaint 保存用户投诉原因、证据、联系方式、审核状态和处理记录 |
| 书源配置 | reading_source 保存合法书源编码、API 类型、基础地址、投诉入口、更新频率、超时、重试、启停和健康摘要 |
| 章节目录 | GET /api/v1/reading/works/{workId}/chapters 返回已发布章节目录,不返回章节全文 |
| 作品搜索 | GET /api/v1/reading/works?keyword= 支持按作品编号、标题和简介搜索已发布作品 |
| 规则推荐榜单 | GET /api/v1/reading/rankings 按推荐、最新、免费和付费分组返回已发布作品;推荐分组基于已发布作品稳定排序,不虚构画像或热度指标 |
| 阅读专题 | GET /api/v1/reading/topics 基于已发布作品 extraJson.category / topic / tags / topics 元数据生成专题分组;无专题元数据时回退“最新阅读”,不新增运营表 |
| 我的推荐 | GET /api/v1/reading/me/recommendations 根据当前用户书架和最近阅读作品轻量推荐,排除已在书架作品;无画像时回退已发布作品规则排序 |
| 用户入口 | App / PC 提供阅读书库、作品详情、章节目录、章节阅读器和我的书架入口 |
| 后台运营 | Admin 提供作品列表 / 详情 / 新增 / 编辑、作品下章节列表 / 详情 / 新增 / 编辑、章节购买订单查询 / 收益汇总 / 退款失效 |
| 书源更新计划 | ReadingSourceUpdatePlan 约束合法书源的 source code、API 类型、更新频率、超时、重试、投诉入口和启停状态 |
| 书源运维入口 | Admin /reading/sources 支持书源配置列表、详情、新增、编辑、健康摘要更新、受控批次导入、单源同步和到期书源同步;无 Provider 时写入 degraded 健康摘要,不伪造成功 |
| 书源同步 Provider | ReadingSourceSyncProvider 把合法来源同步转换为 ImportReadingSourceBatchCommand,无变化返回空;默认 OpenApiReadingSourceSyncProvider 支持已授权 HTTP JSON 书源网关 |
| 书源同步配置 | spring.open.reading.source-sync.* 已通过 ReadingServiceProvider 声明配置元数据,后台配置中心可识别启用开关、自动注册任务、固定间隔、任务名、实例 ID、批量大小和默认 OpenAPI Provider 开关;默认 auto-startup=false,默认 openapi.enabled=true |
| 章节差异 | ReadingSourceChapterDelta 约束书源章节新增、更新、无变化和下架差异,包含外部 ID、原始 URL、内容 hash、字数和源站更新时间 |
| 导入批次 | ReadingSourceImportBatch 约束一次书源更新发现的章节差异快照,提供总章节数、需导入数量和是否存在导入工作 |
| 导入决策 | ReadingSourceImportDecision 约束章节导入批次是否进入队列;有导入工作时为 queued,无变化批次可 skipped 并记录原因 |
| 重试决策 | ReadingSourceRetryDecision 约束书源更新失败后的重试或放弃决策,包含失败次数、最大重试次数、下一次重试时间和原因 |
| 书源健康快照 | ReadingSourceHealthSnapshot 约束书源 healthy / degraded / disabled 状态、检查时间、最近成功时间、连续失败次数、调度可用性和运营关注判断 |
| 书源更新结果 | ReadingSourceUpdateResult 约束单次书源更新后的 healthy / degraded / disabled 状态、耗时、导入统计、失败章节和重试时间 |
| 书源任务摘要 | ReadingSourceUpdateTaskSummary 聚合书源计划、健康快照、章节导入、更新结果、重试决策和投诉入口,输出下一步动作和运营关注标记 |
| 书源更新提醒 | Admin /reading/sources 会读取 /api/v1/admin/reading/sources/update-task-summaries,展示下一步动作、是否到期、下一次检查、下一次重试和运营关注标记 |
| 书源生产检查 | Admin /reading/sources 会读取 /api/v1/admin/reading/sources/production-checks,展示授权证明、投诉入口、同步配置、最近成功同步和受控导入 smoke 清单 |
| 书源真实验收 runbook | ./scripts/release reading-source-acceptance --source-code <code> 输出只读验收清单,帮助部署方记录授权证明、真实连通、小批量导入、重复同步、撤稿处理、投诉入口和回滚预案 |
API
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /api/v1/reading/works | 分页查询已发布作品 |
GET | /api/v1/reading/rankings | 查询推荐、最新、免费和付费四组阅读作品榜单 |
GET | /api/v1/reading/topics | 查询基于作品元数据聚合的阅读专题 |
GET | /api/v1/reading/me/recommendations | 查询当前登录用户的阅读推荐 |
GET | /api/v1/reading/works/{id} | 查询已发布作品详情 |
GET | /api/v1/reading/works/{id}/offline-manifest | 当前登录用户生成离线阅读清单,按章节访问权限返回全文或预览 |
GET | /api/v1/reading/works/{workId}/chapters | 分页查询已发布作品的章节目录,不返回章节全文 |
GET | /api/v1/reading/chapters/{id} | 查询章节详情,按用户购买状态决定正文是否可读 |
POST | /api/v1/reading/chapters/{id}/purchases | 创建付费章节 / 积分章节购买订单 |
POST | /api/v1/reading/works/{id}/copyright-complaints | 当前登录用户提交作品版权投诉 |
GET | /api/v1/reading/shelf | 分页查询当前用户书架 |
POST | /api/v1/reading/shelf/items | 加入或更新当前用户书架条目 |
DELETE | /api/v1/reading/shelf/items/{workId} | 从当前用户书架移出作品 |
GET | /api/v1/reading/progress/{workId} | 查询当前用户指定作品最近阅读进度 |
PUT | /api/v1/reading/progress | 保存章节阅读进度,并同步当前作品到书架 |
GET | /api/v1/reading/history | 分页查询当前用户最近阅读历史 |
GET | /api/v1/reading/bookmarks | 分页查询当前用户阅读书签,可按作品和章节筛选 |
POST | /api/v1/reading/bookmarks | 保存当前用户章节书签 |
DELETE | /api/v1/reading/bookmarks/{id} | 删除当前用户书签 |
GET | /api/v1/reading/preferences | 查询当前用户阅读设置,未保存时返回默认设置 |
PUT | /api/v1/reading/preferences | 保存当前用户字号、行宽、主题和翻页模式 |
购买接口创建章节购买订单。paid 章节返回收银台上下文,实际扣款由 Cashier / Payment 承载;Cashier 支付成功回调会把章节购买订单推进为 paid 并解锁章节正文。points 章节使用 unlockPrice 作为整数积分数量,优先使用章节 / 作品 unlockCurrency 作为积分资产码,未配置时默认 MALL,创建订单时通过 Money points:CODE 账户写入 reading-chapter-points 消费流水并立即解锁正文。Cashier 退款回调或后台退款失效动作会把订单推进为 refunded,后续访问不再把该订单视为有效购买。Reading 读侧统一调用 Entitlement ContentAccessPolicyService:已支付订单或积分扣减作为 directUnlock,reading-paid-chapter 可作为付费 / 积分章节通用解锁凭证,reading-vip-chapter 用于 VIP 章节;没有 Entitlement 凭证时不会放行 VIP 内容,作者本人仍可预览自己的章节。
后台运营接口挂在 /api/v1/admin/reading/**:作品使用 /works、/works/{id},章节使用 /works/{workId}/chapters 和 /chapters/{id},章节购买订单使用 /chapter-purchases、/chapter-purchases/revenue-summary 和 /chapter-purchases/{orderNo}/refund-invalidate,版权投诉使用 /copyright-complaints 和 /copyright-complaints/{id},书源配置使用 /sources、/sources/{id}、/sources/{id}/health、/sources/{id}/import-batches、/sources/{id}/sync、/sources/sync-due、/sources/update-task-summaries 和 /sources/production-checks。后台权限码使用 reading:work:view、reading:work:update、reading:chapter:view、reading:chapter:update、reading:chapter-purchase:view、reading:chapter-purchase:update、reading:copyright:view、reading:copyright:handle、reading:source:view、reading:source:update。
用户入口
- Admin:
/#/reading/works管理阅读作品和章节,/#/reading/chapter-purchases查询章节购买订单、查看收益汇总并登记退款失效,/#/reading/copyright-complaints处理版权投诉并可同步调整作品状态,/#/reading/sources管理合法书源配置、更新提醒摘要、生产配置检查、健康摘要、受控导入批次、单源同步和到期同步。 - PC:
/reading查看阅读书库、搜索作品、作品榜单、阅读专题和登录后的我的推荐,/reading/{id}查看作品详情、章节目录、保存 / 下载离线清单并提交版权投诉,/reading/chapter/{id}打开章节阅读器、保存进度、保存书签和应用阅读设置,/account/reading查看我的书架、最近阅读历史和当前浏览器离线缓存。 - App:服务中心新增“阅读书库”和“我的书架”,对应
/reading/index、/detail、/reader、/shelf;阅读首页可展示阅读专题,登录后展示我的推荐,作品详情支持登录用户生成并保存离线缓存、提交版权投诉,阅读器支持阅读设置和书签,书架页展示最近阅读历史和当前设备离线缓存。 - 作品详情支持加入书架;阅读器支持保存
position和progressPercent,保存后后端会同步书架当前章节;书签和阅读设置会落库,便于多端同步。 - 作品详情通过公开章节目录选择章节,不再需要用户手动输入章节 ID。
开发边界
- Reading 不直接依赖 Mall、Payment 实现类;与 Cashier 的交互只通过订单创建和支付 / 退款回调 handler 完成。会员 / 通用解锁只通过 Entitlement 的
ContentAccessPolicyService判定,不在 Reading 内私写会员或权益账本。 - 资金类动作必须通过订单状态和 Cashier / Payment / Money 中性 contract 推进,不在 Reading 中私写余额表;积分章节只通过 Money 积分流水扣减,后台“退款失效”只登记已退款语义并撤销阅读访问权,不发起资金退款。
- 默认 OpenAPI 书源 Provider、阅读专题、我的推荐、书签、历史、阅读设置、离线阅读清单、本地离线缓存和授权书源验收 runbook 已闭口,真实授权书源连通执行仍是后续部署验收;当前已提供
reading_source书源配置表、Admin 运维入口、受控导入批次接口、ReadingSourceSyncProvider同步 SPI、默认OpenApiReadingSourceSyncProvider、单源同步入口、到期同步任务底座、更新提醒摘要、生产配置检查、规则推荐榜单、专题聚合、用户书架推荐和./scripts/release reading-source-acceptance只读验收清单。生产配置检查只基于本地配置校验授权证明、投诉入口、同步配置和最近成功同步,不主动外联真实书源。验收 runbook 只输出检查步骤和记录模板,不连接外部来源、不修改数据库、不证明真实厂商验收。导入只接受管理员提交或 Provider 返回的已授权来源 payload,不主动采集外部站点。书源 contract 包括ReadingSourceUpdatePlan作为书源更新任务输入边界,ReadingSourceChapterDelta作为章节差异边界,ReadingSourceImportBatch作为导入批次边界,ReadingSourceImportDecision作为导入队列决策边界,ReadingSourceRetryDecision作为失败重试决策边界,ReadingSourceHealthSnapshot作为书源健康快照边界,ReadingSourceUpdateResult作为书源更新执行结果边界,并提供ReadingSourceUpdateTaskSummary聚合任务摘要;后续外部 Provider 接入必须复用这些 contract。 apiType=openapi的书源会使用默认 OpenAPI Provider:基础地址来自reading_source.base_url,同步时会追加sourceCode和可选lastCheckedAt查询参数;reading_source.extra_json可配置headers、query、syncPath/path和userAgent,用于接入已授权的 HTTP JSON 书源网关;若extra_json.importer=disabled或syncEnabled=false,Provider 会跳过外联并返回无变化。响应可以使用{ "code": 0, "data": { "batchNo": "...", "work": {...}, "chapters": [...] } },也可以直接返回同等 payload。真实授权源的账号、频率、版权证明和生产连通性仍需在部署环境验收。- 书源同步配置键统一为
spring.open.reading.source-sync.*,包括enabled、auto-startup、fixed-delay、task-name、instance-id、batch-size和openapi.enabled;配置元数据由 Reading 生命周期 Provider 声明,便于后台配置中心展示和治理。 - 书源更新任务必须有 HTTP/HTTPS 投诉入口,更新间隔不得低于 15 分钟,单次超时不得超过 120 秒,重试次数不得超过 5 次;停用书源不会进入调度。
- 只有
degraded更新结果允许携带下一次重试时间;healthy和disabled结果不得进入失败重试队列。 - 章节差异只允许
create/update/unchanged/withdrawn动作;unchanged不进入导入队列,其余动作需要后续执行器按来源与 hash 做审计。 - 导入批次内所有章节差异必须属于同一
sourceCode,批次快照不可变,便于后续导入日志、审计和重试引用。 - 导入决策只有
queued/skipped两类;有导入工作才能入队,无导入工作才能跳过,跳过必须记录可审计原因。 - 重试决策只有
retry-scheduled/give-up两类;停用书源不再重试,失败次数超过maxRetries后必须放弃并记录原因。 - 书源健康快照只有
healthy/degraded/disabled三类;degraded和disabled必须记录原因,disabled不进入调度。 - 书源任务摘要必须保持计划、健康、导入批次、导入决策、更新结果和重试决策的
sourceCode一致;停用或不可调度书源不得携带导入工作或继续安排重试。