更新记录
1.0.0(2026-10-03)
- 新增 Android / iOS 原生沉浸式全屏阅读,支持 uni-app 与 uni-app x。
- 新增直接传入正文、按需加载章节、本地 TXT 三种阅读入口,支持应用可读的绝对路径、
file://与项目资源路径。 - 新增无动画、滑动、覆盖、滚动、仿真五种翻页方式,Android 支持二维纸角仿真与纸背文字效果。
- 新增字号、字体、行距、段距、主题、亮度、单手翻页、页脚和状态栏等阅读设置。
- 新增书籍详情、目录正倒序与分卷、章节信息、笔记与书签筛选,支持本地书封和作者头像。
- 新增阅读进度保存与文字位置恢复、书签管理、当前章节阅读百分比,支持账号和书籍数据隔离。
- 新增受限章节提示、解锁事件和授权后供章流程,由接入项目完成业务授权。
- 新增书架、下载、分享、听书控制和评论面板,通过业务事件与
setReaderUiState接入宿主服务;支持评论总数、排序及资料增量回写。 - 新增章节请求身份校验、缓存数量与容量限制、初始化取消和会话资源释放。
- 新增 uni-app / uni-app x 两套离线演示与按业务模块组织的中文接入文档。
平台兼容性
uni-app(5.24)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | √ | √ | √ | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
uni-app x(5.24)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | √ | √ | × | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | × | √ |
lizhao-novel-reader · 原生小说阅读器
介绍
让你的 App 拥有沉浸式小说阅读体验。
面向 uni-app / uni-app x 的 Android / iOS 原生小说阅读器。一键打开全屏阅读页,支持仿真翻页、本地 TXT、在线章节接入、目录书签和阅读进度记忆,适合小说 App、书城和应用内文字阅读。
喜欢翻书的手感,选择仿真翻页;习惯连续阅读,切换上下滚动。字号、行距、背景和日夜主题按需调整,再次打开同一本书,可接着上次的位置阅读。
提供书架、下载、评论、分享、听书控制界面,可与已有业务系统对接。小说内容由接入项目提供,在线书源、账号、下载任务、评论服务、音频播放、付费授权和云端进度需自行接入。
功能特色
| 功能 | 阅读体验与用途 |
|---|---|
| 五种翻页,按习惯选择 | 仿真、覆盖、平移、上下滚动、无动画,满足翻页阅读和连续阅读习惯 |
| TXT 与小说章节阅读 | 打开本地 TXT、直接传入文字,或接入自己的小说章节内容 |
| 记住进度,接着上次读 | 本地保存阅读位置,再次打开可继续;调整字号后按文字位置重新排版 |
| 目录跳转与书签 | 快速找到想看的章节,把喜欢的段落位置加入书签 |
| 字号、行距与背景自定义 | 调整字体大小、行距、段落间距、页面留白和阅读配色 |
| 日间与夜间模式 | 根据阅读环境切换主题,配合窗口亮度调节 |
| 沉浸式全屏阅读 | 点击正文呼出或收起工具栏,正文分页保持稳定 |
| 听书、评论等业务扩展 | 提供听书控制、评论、书架、下载、分享和书籍详情界面,由你的业务处理服务与数据 |
| 章节按需加载 | 只加载当前阅读与预加载的章节,适合章节较多的小说 |
| 受限章节接入 | 显示章节锁定提示,接入自己的会员或付费授权流程 |
| 多书籍、多账号记录 | 按账号与书籍分别保存本地进度和书签 |
适合哪些场景
- 已有小说接口,希望接入原生阅读页。
- 阅读用户已选择、已授权访问的 TXT 文件。
- 阅读纯文字资料、培训内容或应用内文章合集。
当前不提供 EPUB、PDF、漫画、内嵌阅读组件、内置书城或内置 TTS/音频引擎。听书控制界面会发出业务事件,可接已有播放器、系统 TTS 或 lizhao-smart-tts;getReaderCapabilities().tts 仍为 false,避免把控制界面误报为语音能力。
下载与导入
将完整的 lizhao-novel-reader 目录放入项目 uni_modules,保留目录名。从插件根目录导入公开 API:
import { openReader, destroyReader } from '@/uni_modules/lizhao-novel-reader'
完整示例位于:
- uni-app:
example/uniapp/index.vue - uni-app x:
example/uniappx/index.uvue
示例包含短文、章节延迟、章节失败重试、受限章节、初始化取消,以及书架、下载、听书、评论的事件回写。所有正文、解锁和业务结果均为离线 Mock,不发起网络请求、真实下载、音频播放、评论发布或支付。
5 分钟跑通:打开第一本小说
uni-app
<template>
<view><button @click="read">开始阅读</button></view>
</template>
<script>
import { openReader, destroyReader } from '@/uni_modules/lizhao-novel-reader'
export default {
methods: {
read() {
openReader({
readerId: 'first-reader',
bookId: 'first-book',
title: '雨后的小城',
sourceType: 'text',
content: '雨停时,街边的灯刚刚亮起。\n小林收起伞,沿着河边慢慢走向书店。',
restoreProgress: false,
onEvent(event) {
// close 表示原生阅读页已经退出。
if (event.type === 'close') console.log('阅读已结束')
},
fail(error) {
uni.showToast({ title: error.errMsg, icon: 'none' })
}
})
}
},
onUnload() {
// 已经关闭时返回 9107003;这里无需额外提示。
destroyReader({ readerId: 'first-reader' })
}
}
</script>
uni-app x
<template>
<view><button @click="read">开始阅读</button></view>
</template>
<script setup lang="uts">
import { openReader, destroyReader } from '@/uni_modules/lizhao-novel-reader'
import { OpenReaderOptions, ReaderCommandOptions, ReaderFail } from '@/uni_modules/lizhao-novel-reader'
function read() {
const options: OpenReaderOptions = {
readerId: 'first-reader', bookId: 'first-book', title: '雨后的小城',
sourceType: 'text', restoreProgress: false,
content: '雨停时,街边的灯刚刚亮起。\n小林收起伞,沿着河边慢慢走向书店。',
fail: (error: ReaderFail) => {
uni.showToast({ title: error.errMsg, icon: 'none' })
}
}
openReader(options)
}
onUnload(() => {
destroyReader({ readerId: 'first-reader' } as ReaderCommandOptions)
})
</script>
打开后默认隐藏工具栏。单击正文中区显示目录、书签、设置、听书等入口;单击两侧或拖动纸角翻页,滚动模式使用纵向阅读。
核心配置
| 配置 | 建议 |
|---|---|
readerId |
当前阅读会话的固定 ID,后续控制、取消和关闭均使用它 |
bookId |
长期稳定的书籍 ID,同一本书不要每次随机生成 |
storageNamespace |
登录后使用账号业务 ID;默认 guest,不要传 Token |
contentRevision |
正文改版时更换修订号,默认 '1' |
sourceType |
text / chapters / txtFile |
style |
字号、行高、段距、留白、主题及颜色 |
uiState |
业务已确认的书架、下载、播放器、评论和笔记初始状态 |
pageMode |
默认 curl,可先查询 getReaderCapabilities() |
restoreProgress |
默认 true;首次演示或从头阅读时设为 false |
接入方式选择
| 你的内容 | 使用方式 | 边界 |
|---|---|---|
| 一篇已加载的短文 | sourceType: 'text' + content |
最多 200000 个 UTF-16 单元,章节 ID 固定为 text |
| 已有小说目录和章节接口 | sourceType: 'chapters' + chapters |
目录最多 10000 条;收到请求后提供单章正文 |
| 本地 TXT | sourceType: 'txtFile' + filePath |
最多 50 MiB;后台建立索引并按章读取 |
从基础到进阶:按业务模块使用
以下控制示例假定已经成功打开 readerId: 'first-reader'。每段使用到的方法都从 @/uni_modules/lizhao-novel-reader 导入。uni-app x 中控制参数使用公开的 ReaderCommandOptions 类型;完整强类型写法见随附 .uvue 示例。
一、翻页与目录
import { nextPage, prevPage, getChapterCatalog, gotoPosition } from '@/uni_modules/lizhao-novel-reader'
nextPage({ readerId: 'first-reader' })
// 返回上一页时调用 prevPage({ readerId: 'first-reader' })。
getChapterCatalog({
readerId: 'first-reader', offset: 0, limit: 50,
success(result) { console.log('当前目录', result.chapters) }
})
// chapterId 必须来自当前书籍的真实目录。
gotoPosition({
readerId: 'first-reader',
position: { bookId: 'first-book', contentRevision: '1', chapterId: 'text', textOffset: 0, anchorText: '' }
})
原生目录可直接选择章节。到书籍首尾时继续翻页返回 9107011,不会循环回到另一端。
二、恢复阅读位置
相同 storageNamespace + bookId 默认恢复本地进度。需要云同步时,在 progress 事件中取得 event.progress.position,由业务限频保存到服务器;再次打开时传入 position,优先于本地记录。
import { getProgress } from '@/uni_modules/lizhao-novel-reader'
getProgress({
readerId: 'first-reader',
success(result) {
if (result.progress != null) {
// 将 position 保存到你的业务存储,不要把 pageIndex 当作永久位置。
console.log('当前位置', result.progress.position)
}
}
})
textOffset 基于去除开头 BOM、统一换行后的正文,采用 UTF-16 单元计数。正文修订变化时,插件尝试用 anchorText 辅助定位;无法精确恢复会发出 positionAdjusted。书籍和目录 ID 应保持稳定。
三、字号、纸色与翻页方式
import { setReaderStyle, setPageMode } from '@/uni_modules/lizhao-novel-reader'
setReaderStyle({
readerId: 'first-reader',
style: { theme: 'night', fontSize: 22, lineHeight: 1.8, paragraphSpacing: 10 }
})
setPageMode({ readerId: 'first-reader', pageMode: 'curl' })
未传入的样式字段保留当前值。显式切换 theme 会重置该主题的文字和背景色;同次提供的自定义颜色优先。字号或窗口尺寸变化后重新排版,以当前文字位置为依据。正文文字与背景的最终对比度必须达到 4.5:1;低对比自定义配色会返回 9107001,避免背景弱化正文。
| 模式 | 阅读表现 |
|---|---|
none |
直接切页 |
slide |
页面横向滑动 |
cover |
页面覆盖切换,两端动画方向略有差异 |
scroll |
当前章节纵向滚动,可用底部翻页按钮跨章 |
curl |
原生卷曲翻页;两端具体曲面与手势表现有差异 |
四、在线章节:先用离线数据跑通
目录只提供元数据。收到 chapterRequest 后,把 readerId、generation、requestId、bookId、contentRevision、chapterId 原样带回。每个请求只能成功或失败一次。
import { openReader, resolveChapter, rejectChapter } from '@/uni_modules/lizhao-novel-reader'
// 离线 Mock;替换成业务请求时也保留完整请求身份和失败回写。
const contentByChapter = {
c1: '第一章\n清晨,第一班渡船离开了码头。',
c2: '第二章\n船靠岸时,远处传来了钟声。'
}
openReader({
readerId: 'chapter-reader', bookId: 'river-story', title: '渡口',
sourceType: 'chapters', restoreProgress: false,
chapters: [{ chapterId: 'c1', title: '第一章' }, { chapterId: 'c2', title: '第二章' }],
onEvent(event) {
if (event.type !== 'chapterRequest') return
const identity = {
readerId: event.readerId, generation: event.generation,
requestId: event.requestId, bookId: event.bookId,
contentRevision: event.contentRevision, chapterId: event.chapterId,
fail(error) {
// 用户已关闭、目录已更新或超时后的旧请求会明确失败。
if (error.errCode !== 9107009 && error.errCode !== 9107003) console.log(error.errMsg)
}
}
const content = contentByChapter[event.chapterId]
if (content != null) resolveChapter({ ...identity, content })
else rejectChapter({ ...identity, message: '暂时没有这章正文,请稍后重试' })
},
fail(error) { uni.showToast({ title: error.errMsg, icon: 'none' }) }
})
该段为 uni-app JavaScript 写法;uni-app x 使用 ReaderEvent、ReaderCommandOptions 显式构造对象,见完整示例的 onReaderEvent。
reason 可为 visible、preload、unlock。可预加载相邻的公开章节,受限章节不会自动预取。首次供章失败会关闭初始化页面并触发 openReader.fail;阅读过程中跨章失败保留页面供重试。initialContent 与 initialChapterId 可减少首次请求;自动恢复到其他章节时仍可能请求那个章节。
需要替换目录时调用 setChapterCatalog({ readerId, chapters }),传完整快照。它会使旧请求失效;新目录中的章节 ID 必须唯一。该操作仅用于 chapters 入口。
五、本地 TXT
import { openReader } from '@/uni_modules/lizhao-novel-reader'
// 将此变量替换为文件选择或下载完成后取得的真实可读本地路径。
const localPath = '/你的应用沙盒目录/book.txt'
openReader({
readerId: 'txt-reader', bookId: 'my-local-book', title: '本地小说',
sourceType: 'txtFile', filePath: localPath, encoding: 'auto',
fail(error) { uni.showToast({ title: error.errMsg, icon: 'none' }) }
})
插件不弹出文件选择器、不请求全部文件访问权限。请先由文件选择或下载流程取得授权,并将文件复制到应用可读的沙盒目录。支持绝对路径及 file://;_doc/ 等项目路径会交由运行时转换。不要传远程 URL 或 Android content:// URI。
auto 根据 BOM 识别 UTF-8 / UTF-16,否则尝试严格 UTF-8;无 BOM 的 GB18030 文件请显式指定 gb18030。解码失败返回 9107006,不会用乱码填充后宣称成功。
TXT 在后台分块解码、建立章节索引,不通过 JS 传递整本内容。可识别常见章节标题;过长章节和无标题正文会按受控长度分段。源文件保持只读,导入产生的会话临时文件在关闭时清理。导入期间可用同一 readerId 调用 closeReader 或 destroyReader 取消。
六、书签
import { addBookmark, getBookmarks, gotoPosition, removeBookmark } from '@/uni_modules/lizhao-novel-reader'
addBookmark({ readerId: 'first-reader', title: '下次从这里重读' })
getBookmarks({
readerId: 'first-reader', offset: 0, limit: 50,
success(result) { console.log('我的书签', result.bookmarks) }
})
// 选中书签后,将其 position 传给 gotoPosition。
// 删除时:removeBookmark({ readerId: 'first-reader', bookmarkId: 选中的书签编号 })。
书签按账号命名空间和书籍保存,每本书最多 1000 条。getBookmarks 和 getChapterCatalog 使用 offset / limit 分页,返回列表及 total。不要把返回列表的下标当作书签 ID。
七、受限章节与业务菜单
目录项设置 locked: true,可用 lockedMessage 说明限制。受限页可以正常打开,openReader.success.initialState 为 locked。
用户点击解锁后,收到 menuAction: 'unlock' 及 reason: 'unlock' 的 chapterRequest。业务完成登录、购买或权限校验后,按请求身份 resolveChapter;取消或未获授权时 rejectChapter。本地 locked 是展示标记,服务端仍需校验正文访问权限。
目录、设置、书签由原生页提供;对应菜单事件可用于业务统计,不需要再次弹出一套相同菜单。插件不内置支付 SDK,也不把示例 Mock 的解锁当成真实购买。
八、书籍资料、目录、书架、下载、听书与评论
这些界面由插件原生绘制,但插件不会伪造后端结果。章节展示可传 volumeTitle、wordCountText、updateTimeText、commentCount、summary 和当前章的 chapterProgressText;书籍资料可传 bookScoreText、readerCountText、bookWordCountText、bookUpdateText 与 bookTags。目录和资料面板底部始终保留目录、日夜、设置、听书四个入口。搜索、关注和书评入口会发出 catalogSearch、authorFollowToggle、bookReviews。宿主完成真实业务,再用同一事件携带的 readerId、generation、bookId、contentRevision、chapterId 回写增量状态。旧章节或旧会话的迟到响应会被拒绝。
coverPath 和 authorAvatarPath 只接受应用已有读权限的本地图片,例如 _doc/、static/、file://、unifile:// 或转换后的绝对路径。插件不下载 http/https,不接受 data:、blob: 或 Android content://;单张图片原生解码上限为 10 MiB,路径不可读或解码失败时会显示文字占位。临时文件由宿主管理生命周期;请在阅读会话存续期间保持文件可读,替换素材后用 setReaderUiState 回写新路径。
import { openReader, setReaderUiState } from '@/uni_modules/lizhao-novel-reader'
openReader({
readerId: 'first-reader', bookId: 'first-book', title: '雨后的小城',
sourceType: 'text', content: '第一章\n雨停后,书店亮起了灯。',
uiState: {
author: '林间灯火', bookDescription: '离线示例简介',
coverPath: '_doc/books/rain-book-cover.png',
authorAvatarPath: '_doc/books/rain-book-author.png',
bookScoreText: '9.1分', ratingCountText: '1.2万人点评', readerCountText: '8.6万人在读',
bookWordCountText: '12.8万字', bookUpdateText: '今日更新', bookTags: ['都市日常', '治愈'],
authorFollowed: false, bookshelfAdded: false,
downloadStatus: 'idle', audioStatus: 'idle', audioRate: 1,
commentStatus: 'idle', commentSort: 'hot', commentCount: 0
},
async onEvent(event) {
if (event.type !== 'menuAction') return
const identity = {
readerId: event.readerId, generation: event.generation,
bookId: event.bookId, contentRevision: event.contentRevision,
chapterId: event.chapterId
}
if (event.menuAction === 'bookshelfToggle') {
// 示例直接确认;正式项目应先请求自己的书架接口。
setReaderUiState({ ...identity, uiState: { bookshelfAdded: true } })
} else if (event.menuAction === 'comments') {
setReaderUiState({ ...identity, uiState: { commentStatus: 'loading' } })
const page = await yourCommentService.list(event.chapterId)
setReaderUiState({ ...identity, uiState: {
commentStatus: 'ready', commentCount: page.total, comments: page.items
} })
} else if (event.menuAction === 'audioToggle') {
await yourAudioPlayer.toggle()
setReaderUiState({ ...identity, uiState: { audioStatus: yourAudioPlayer.status } })
}
}
})
上例的 yourCommentService、yourAudioPlayer 是业务占位名,不是插件内置对象。可直接运行的离线 Mock 见两个随附示例。
menuAction |
附加字段 | 宿主职责 |
|---|---|---|
bookshelfToggle |
无 | 加入/移出业务书架,回写 bookshelfAdded |
download |
无 | 创建下载任务,回写 downloadStatus / downloadProgress;需要时同时入架 |
comments |
无 | 拉取评论,回写 commentStatus / comments / commentCount |
share / bookDetail |
无 | 打开宿主分享或书籍详情流程 |
audioOpen / audioToggle |
无 | 准备播放器、播放或暂停,回写音频状态 |
audioPreviousChapter / audioNextChapter |
无 | 切换业务音频章节 |
audioSeekRelative |
actionNumber 为 ±15 秒 |
相对快退或快进 |
audioSeekTo |
actionNumber 为目标秒数 |
跳到指定音频位置 |
audioRate / audioTimer |
actionNumber |
修改实际倍速或停止定时 |
audioVoice |
actionValue 为 voiceId |
切换宿主提供的音色 |
commentSort |
actionValue 为 hot / latest |
按选择重新拉取评论 |
commentSend |
actionValue 为输入正文 |
提交评论后回写新列表或 message |
commentLike |
commentId |
点赞/取消点赞后回写列表 |
commentReply / commentMore |
commentId,回复可带 actionValue |
打开回复或评论管理流程 |
commentsLoadMore |
无 | 拉取下一页评论并增量回写 comments / commentHasMore |
noteOpen |
noteId |
打开或定位宿主保存的笔记详情 |
textSelection |
selectedText、selectionStart、selectionEnd |
处理正文选区;当前由 iOS 上下滚动模式提供 |
catalogSearch |
无 | 打开宿主的书内搜索或全文搜索页面 |
authorFollowToggle |
无 | 关注或取消关注作者,完成后回写 authorFollowed |
bookReviews |
无 | 打开宿主的全部书评页面 |
ReaderUiState 是增量状态;未传字段保持当前值。明确传入 false、0、空字符串仍会更新对应字段;传入空数组可清空对应列表。评论最多回写 200 条、音色最多 50 条。听书界面只控制你接入的播放器,插件不会静默播放、下载或发布评论。
九、监听与页面退出
import { onReaderEvent, offReaderEvent, destroyReader } from '@/uni_modules/lizhao-novel-reader'
onReaderEvent({
readerId: 'first-reader', listenerId: 'page-observer',
callback(event) { console.log('阅读事件', event.type, event.message) }
})
// 页面卸载时精确解除自己的订阅,再释放阅读会话。
offReaderEvent({ readerId: 'first-reader', listenerId: 'page-observer' })
destroyReader({ readerId: 'first-reader' })
监听可在打开前注册。同一 readerId + listenerId 再注册会替换旧监听;最多 128 个独立订阅。openReader.onEvent 随会话关闭自动释放,独立订阅在该会话关闭时也会清理。不要在宿主 onHide 中无条件关闭,否则打开原生页时可能立即退出。
closeReader 和 destroyReader 均结束当前会话、保存进度并释放资源。已关闭后再次调用返回 9107003。close 事件和关闭命令成功回调均发生在原生会话释放之后,可在其中重新打开阅读器。
API 用途速查
| API | 用途 | 结果 |
|---|---|---|
openReader |
打开原生阅读页 | initialState,可带 progress |
closeReader / destroyReader |
关闭、取消初始化并释放资源 | readerId / action |
nextPage / prevPage |
翻页,跨章按需请求正文 | 进度快照或命令受理结果 |
gotoPosition |
跳至稳定文字位置 | 进度快照或命令受理结果 |
getProgress |
查询当前可读位置 | progress |
setReaderStyle / setPageMode |
修改外观、翻页模式 | 命令结果 |
setReaderUiState |
回写宿主已确认的业务状态 | uiState 快照或命令结果 |
setChapterCatalog / getChapterCatalog |
更新或分页查询目录 | 更新结果 / chapters + total |
resolveChapter / rejectChapter |
完成一次章节请求 | 命令结果;可见页随后更新 |
addBookmark / removeBookmark |
新增或删除书签 | bookmark / 命令结果 |
getBookmarks |
分页查询书签 | bookmarks + total |
onReaderEvent / offReaderEvent |
注册或解除独立事件订阅 | 无返回值 |
getReaderCapabilities |
同步查询当前构建支持能力 | ReaderCapabilities |
翻页或跳章如果需要加载正文,命令成功表示请求已受理;实际内容更新以 chapterChange / progress 事件为准。
参数说明
OpenReaderOptions
| 参数 | 类型 | 必填 | 默认值 / 说明 |
|---|---|---|---|
readerId |
string | 是 | 1–128 字符的非空会话 ID |
bookId |
string | 是 | 1–128 字符的稳定书籍 ID |
title |
string | 是 | 非空书名 |
sourceType |
string | 是 | text / chapters / txtFile |
contentRevision |
string | 否 | '1';1–128 字符 |
storageNamespace |
string | 否 | 'guest';1–128 字符 |
content |
string | 条件必填 | text 正文,不超过 200000 个 UTF-16 单元 |
chapters |
ReaderChapter[] | 条件必填 | chapters 目录,1–10000 条 |
initialContent |
string | 否 | 指定初始章的正文,同样受单章大小限制 |
initialChapterId |
string | 否 | 默认第一章,必须属于目录 |
filePath |
string | 条件必填 | txtFile 的本地可读文件 |
encoding |
string | 否 | auto / utf-8 / utf-16le / utf-16be / gb18030 |
position |
ReaderPosition | 否 | 显式位置,优先于本地进度 |
restoreProgress |
boolean | 否 | true |
style |
ReaderStyle | 否 | 见下表 |
uiState |
ReaderUiState | 否 | 业务已确认的初始状态;不执行网络或播放器操作 |
pageMode |
string | 否 | curl;五种模式见上文 |
requestTimeoutMs |
number | 否 | 15000;范围 1000–60000 毫秒 |
cacheLimitBytes |
number | 否 | 8388608;范围 1048576–33554432 字节 |
keepScreenOn |
boolean | 否 | false;仅阅读期间保持亮屏,不修改亮度 |
onEvent |
(ReaderEvent) => void | 否 | 持续事件 |
success / fail / complete |
function | 否 | 单次打开回调,见下文 |
ReaderStyle
| 参数 | 类型 | 默认值 | 范围 |
|---|---|---|---|
theme |
string | paper |
paper / light / night |
fontSize |
number | 24 | 12–40 |
lineHeight |
number | 1.85 | 1–2.5 倍行高 |
paragraphSpacing |
number | 12 | 0–32 |
horizontalPadding |
number | 18 | 8–48 |
textColor |
string | 随主题 | #RRGGBB,与背景对比度 ≥ 4.5:1 |
backgroundColor |
string | 随主题 | #RRGGBB,与正文对比度 ≥ 4.5:1 |
fontFamily |
string | system |
system / serif,不捆绑商业字体 |
bold |
boolean | false |
是否加粗正文 |
brightness |
number | -1 |
-1 跟随系统,或 0–1;只影响阅读窗口 |
showStatus |
boolean | true |
显示页码、时间和电量 |
singleHand |
boolean | false |
左右点击区均向后翻;右滑仍返回上一页 |
pullToBookmark |
boolean | true |
下拉正文添加本地书签 |
showSystemStatusBar |
boolean | false |
阅读期间显示系统状态栏 |
字号使用各端逻辑单位,系统字体设置和设备尺寸可能影响每页字数。
ReaderUiState
| 字段 | 类型 | 说明 |
|---|---|---|
author / bookDescription |
string | 作者与简介展示;音色说明字段为 voiceDescription |
coverPath / authorAvatarPath |
string | 应用可读的本地书封/头像路径;不负责网络下载,单张最大 10 MiB |
bookScoreText / ratingCountText |
string | 已格式化评分与点评人数;未传不显示 |
readerCountText / bookWordCountText |
string | 已格式化在读人数与全书字数 |
bookUpdateText |
string | 已格式化更新说明 |
bookTags |
string[] | 书籍标签,最多 20 项,每项最多 40 字符 |
authorFollowed |
boolean | 宿主确认后的作者关注状态 |
bookshelfAdded |
boolean | 宿主确认后的书架状态 |
downloadStatus |
string | idle / downloading / downloaded / failed |
downloadProgress |
number | 0–1 的实际下载进度 |
audioStatus |
string | idle / loading / playing / paused / error |
audioTitle |
string | 当前音频章节名 |
audioPosition / audioDuration |
number | 实际播放位置与时长,单位秒 |
audioRate |
number | 0.5–4 的实际倍速 |
audioVoice / voices |
string / ReaderVoice[] | 当前音色 ID 与可选音色,最多 50 条 |
audioTimerMinutes |
number | 0 表示关闭,最大 180 分钟 |
commentStatus |
string | idle / loading / ready / error |
commentSort |
string | hot / latest |
commentCount / comments |
number / ReaderComment[] | 评论总数与当前列表,列表最多 200 条 |
commentHasMore |
boolean | 是否还有下一页评论 |
message |
string | 业务完成或失败提示 |
notes |
ReaderNote[] | 当前章的业务笔记/划线,最多 200 条 |
ReaderChapter / ReaderCommandOptions
目录项:chapterId: string、title: string 必填;locked?: boolean 默认 false;lockedMessage?: string 为可选提示。展示字段均可选:volumeTitle 为卷名,wordCountText / updateTimeText 是宿主格式化后的字数与更新时间,commentCount 是评论数,summary 用于详细目录摘要,chapterProgressText 是当前章右侧的业务进度文案(例如“读到7%”)。未传 chapterProgressText 时,插件根据当前章实际文字位置生成整数百分比。插件只展示这些数据,不猜业务统计口径。
控制 API 统一使用 ReaderCommandOptions,均需 readerId,支持 success / fail / complete。其他字段按方法选择:
| 方法 | 额外字段 |
|---|---|
gotoPosition |
position: ReaderPosition |
setReaderStyle |
style: ReaderStyle |
setPageMode |
pageMode: ReaderPageMode |
setReaderUiState |
uiState + generation / bookId / contentRevision / chapterId |
setChapterCatalog |
chapters: ReaderChapter[] |
resolveChapter |
完整请求身份 + content: string |
rejectChapter |
完整请求身份 + 可选 message: string |
addBookmark |
可选 title: string,默认当前章节标题 |
removeBookmark |
bookmarkId: string |
getBookmarks / getChapterCatalog |
offset?: number 默认 0,limit?: number 默认 50,最大 200 |
其他控制方法无需额外字段。偏移与条数需为非负整数,limit 至少为 1。
回调与事件
单次方法只结算一次:success(result) 或 fail(error),随后 complete(resultOrError)。业务回调异步派发,业务函数抛错不会阻止 complete。
openReader.success 表示正文首屏或受限页已经可交互;加载占位不算成功。初始化失败或取消会触发 fail,释放本次会话。后续章节错误通过事件和原生页重试提示通知。
事件 type |
含义 |
|---|---|
ready |
原生阅读页准备完成 |
progress |
阅读位置变化,携带 progress |
chapterRequest |
需要宿主提供章节,携带完整请求身份 |
chapterChange |
当前章节改变 |
menuAction |
原生菜单或业务动作;业务动作值见“书架、下载、听书与评论” |
bookmarkChange |
书签变化 |
positionAdjusted |
恢复位置发生修正 |
error |
阅读中的错误,带 errCode 和中文 message |
close |
会话已释放,最终事件 |
事件公共字段为 readerId、type、message、timestamp(毫秒)。业务事件还带当前 generation、bookId、contentRevision、chapterId,并按动作附加 actionValue、actionNumber、commentId、noteId 或选区字段。页面应按 type 和 menuAction 分发,不要依赖中文文案判断状态。
支持平台
| 能力 | Android | iOS |
|---|---|---|
| 系统最低版本 | Android 7.0 / API 24 | iOS 13.4 |
| 宿主 | uni-app / uni-app x | uni-app / uni-app x |
| 原生全屏、三种正文入口 | 已提供实现 | 已提供实现 |
| 五种翻页模式 | 已提供实现 | 已提供实现 |
| 本地进度、书签、目录 | 已提供实现 | 已提供实现 |
| 业务书架/下载/评论/听书控制 UI | 事件接入 | 事件接入 |
| 正文选区事件 | 暂未提供 | 上下滚动模式提供 |
| EPUB / 内置 TTS / 嵌入式 | 不支持 | 不支持 |
鸿蒙、Web 和小程序当前不支持。getReaderCapabilities() 返回当前构建的入口、翻页模式和编码集合;它是能力查询,不表示当前设备已完成体验验收。上架前请在目标机型检查翻页、长文、旋转和后台恢复。
返回值说明
ReaderResult 始终有 readerId 和 action,其他字段按方法返回。ReaderFail 有 errSubject: 'lizhao-novel-reader'、errCode 和中文 errMsg。
| 类型 | 字段 |
|---|---|
ReaderPosition |
bookId、contentRevision、chapterId、textOffset、anchorText |
ReaderProgress |
position、chapterIndex、chapterCount、pageIndex、pageCount、chapterProgress |
ReaderBookmark |
bookmarkId、title、position、createdAt(毫秒) |
ReaderUiState |
作者、书架、下载、播放器、评论、笔记等宿主业务快照 |
ReaderCapabilities |
platform、nativeFullscreen、sourceTypes、pageModes、encodings、epub、tts、embedded、businessActions |
章节与页索引从 0 开始。pageCount 是当前章在当前排版下的页数;chapterProgress 为当前正文位置比例,并非全书已读百分比。改变字体、行高或屏幕尺寸后页码会变化。
错误码说明
| 错误码 | 说明 | 处理建议 |
|---|---|---|
9107001 |
参数不合法 | 检查 ID、目录、样式和必填字段 |
9107002 |
平台或模式不支持 | 查询能力,选择已实现入口 |
9107003 |
阅读器不存在或已关闭 | 不再向旧会话发控制命令 |
9107004 |
已有阅读器正在打开或显示 | 等待关闭后再打开 |
9107005 |
文件不存在或不可读 | 确认真实路径和文件访问授权 |
9107006 |
TXT 解码或解析失败 | 核对编码,必要时显式指定 |
9107007 |
正文为空 | 检查正文接口及空文件 |
9107008 |
内容或文件超过限制 | 分章供稿,遵守大小上限 |
9107009 |
章节请求已过期或已处理 | 丢弃旧回写,不重放旧 requestId |
9107010 |
章节加载失败或超时 | 允许重试并核对业务请求 |
9107011 |
位置或列表范围不合法 | 检查书籍、章节、页边界及分页参数 |
9107012 |
本地数据保存失败 | 检查可用空间并提示记录未保存 |
9107013 |
操作已取消 | 结束本次加载,不当作业务崩溃 |
9107014 |
原生阅读页面不可用 | 在 App 前台且页面可显示时调用 |
9107015 |
内部操作失败 | 记录方法和错误文案以便定位 |
常见问题
改了字号,为什么页码不同? 页码来自当前排版。保存 ReaderPosition,不要长期保存页码。
为什么 TXT 打不开? 先确认文件已落地到应用可读路径,再核对大小和编码。插件不直接读取网络地址或 content://。
供章已经返回,为什么被拒绝? 超时、关闭、重复回写、目录更新都会使请求失效;必须原样回传完整身份。
缓存会永久保存整本书吗? 不会。内存正文缓存有字节预算,当前章受到保护;TXT 会话索引和规范化文本是临时文件。本地进度与书签会保留。
退出后还收到业务网络响应怎么办? 业务可以取消自己的网络请求;迟到的供章回写会明确失败。不要因此重新打开已关闭的阅读器。
为什么听书按钮可见,但 tts 是 false? 插件提供原生听书控制界面和事件合同,不内置语音引擎。接入自己的播放器或 TTS 后,再把实际状态用 setReaderUiState 回写。
评论、下载或加入书架为什么没有自动成功? 这些是宿主业务。插件只发事件;服务端或播放器确认成功后回写,避免 UI 显示虚假结果。
能否做自己的底部会员面板? 首版为全屏原生页,提供受限章节和事件接入;不支持把页面组件嵌到阅读画布中。
注意事项
- 需要包含当前插件原生实现的应用包。新增或更新原生文件后,请重新进行原生联编或制作匹配的 Android / iOS 自定义基座;仅更新页面资源不能更新原生能力。
- 一次只显示一个阅读会话。
readerId固定到本次会话,bookId和contentRevision固定到实际内容。 - 正文、书签和进度默认在应用本地处理,插件不上传到作者服务器,不内置广告或采集账号凭据。
- 应用卸载、清除数据可能删除本地记录;跨设备恢复请由业务实现云同步。
- 正文缓存预算只约束正文缓存,不等于整个 App 的内存上限。字体排版、页面图像和系统 UI 还会占用额外内存。
- 在业务服务端完成内容授权。不要将本地锁定标记当作付费内容的访问控制。
联系方式
信-微:l-z-1-8-7-1512-5421(-去掉,不这样写会被和谐)
作者系列 UTS 插件
以下插件可按需要搭配使用,本阅读器没有强制依赖它们。
| 插件 | 能力方向 | 插件市场 |
|---|---|---|
lizhao-scan-pro |
原生扫码、连续扫码、相册识别 | 查看插件 |
lizhao-choose-file |
原生文件选择、上传、进度与取消 | 查看插件 |
lizhao-bg-audio |
背景音频播放、队列与事件 | 查看插件 |
lizhao-smart-tts |
系统 TTS、云端合成、听书方案 | 查看插件 |
lizhao-sqlite-pro |
原生 SQLite、迁移与备份 | 查看插件 |

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 6486
赞赏 5
下载 12650933
赞赏 1953
赞赏
京公网安备:11010802035340号