无缝续读:Auto-Novel阅读位置保存的全链路技术实现
【免费下载链接】auto-novel 轻小说机翻网站,支持网络小说/文库小说/本地小说 项目地址: https://gitcode.com/GitHub_Trending/au/auto-novel
你是否曾在阅读小说时被打断,再次打开却需要重新寻找上次看到的位置?Auto-Novel通过精心设计的阅读位置保存系统,让你在任何设备上都能无缝接续阅读体验。本文将深入剖析这一功能从前端到后端的完整实现方案。
功能架构概览
Auto-Novel的阅读位置保存系统采用双层存储架构,结合本地缓存与云端同步,实现了高效可靠的阅读状态管理:
- 本地存储:使用浏览器 localStorage 保存临时阅读位置,确保页面刷新或重新打开时快速恢复
- 云端同步:通过后端API将阅读记录持久化到数据库,支持多设备同步和历史记录管理
核心实现模块包括:
- 前端状态管理:web/src/stores/useReadHistoryStore.ts
- 本地存储操作:web/src/repos/useReadPosition.ts
- 后端API接口:server/src/main/kotlin/api/RouteUserReadHistoryWeb.kt
- 数据访问层:web/src/api/novel/ReadHistoryApi.ts
前端实现:本地存储与状态管理
本地阅读位置存储
前端采用localStorage存储阅读位置,通过ReadPositionRepo提供统一操作接口。存储结构设计如下:
interface ReadPosition {
chapterId: string; // 章节ID
scrollY: number; // 滚动位置
}
type ReaderPositions = Record<string, ReadPosition | undefined>;
关键实现代码位于web/src/repos/useReadPosition.ts:
const addPosition = (gnid: GenericNovelId, position: ReadPosition) => {
const positions = storage.get();
if (position.scrollY === 0) {
delete positions[GenericNovelId.toString(gnid)];
} else {
positions[GenericNovelId.toString(gnid)] = position;
}
storage.set(positions);
};
该实现通过GenericNovelId(通用小说ID)作为键,关联具体的阅读位置信息,支持网络小说、文库小说和本地小说的统一管理。
阅读历史状态管理
使用Pinia状态管理库实现阅读历史的全局状态管理,位于web/src/stores/useReadHistoryStore.ts:
export const useReadHistoryStore = defineStore('read-history', () => {
const readHistoryPaused = ref<boolean>(false);
let remoteFetched = false;
const loadReadHistoryPausedState = async () => {
if (remoteFetched) return;
readHistoryPaused.value = await ReadHistoryApi.isReadHistoryPaused();
remoteFetched = true;
};
// 暂停/恢复阅读历史记录功能
const pauseReadHistory = async () => {
await ReadHistoryApi.pauseReadHistory();
readHistoryPaused.value = true;
};
const resumeReadHistory = async () => {
await ReadHistoryApi.resumeReadHistory();
readHistoryPaused.value = false;
};
return {
readHistoryPaused,
loadReadHistoryPausedState,
pauseReadHistory,
resumeReadHistory,
};
});
该状态管理模块提供了阅读历史记录的暂停/恢复功能,用户可以随时控制是否记录阅读行为。
后端实现:API接口与数据持久化
RESTful API设计
后端API接口采用RESTful设计风格,位于server/src/main/kotlin/api/RouteUserReadHistoryWeb.kt,主要提供以下功能:
- 获取阅读历史列表
- 清除阅读历史
- 更新阅读位置
- 删除特定小说阅读记录
- 暂停/恢复阅读历史记录
核心路由定义:
fun Route.routeUserReadHistoryWeb() {
authenticateDb {
get<UserReadHistoryWebRes.List> { loc -> ... } // 获取阅读历史列表
delete<UserReadHistoryWebRes> { ... } // 清除所有阅读历史
put<UserReadHistoryWebRes.Paused> { ... } // 暂停阅读历史记录
delete<UserReadHistoryWebRes.Paused> { ... } // 恢复阅读历史记录
put<UserReadHistoryWebRes.Novel> { loc -> ... } // 更新阅读位置
delete<UserReadHistoryWebRes.Novel> { loc -> ... } // 删除特定记录
}
}
数据访问实现
API实现类UserReadHistoryWebApi处理具体业务逻辑,包括权限验证、参数校验和数据操作:
class UserReadHistoryWebApi(
private val userRepo: UserRepository,
private val historyRepo: WebNovelReadHistoryRepository,
private val metadataRepo: WebNovelMetadataRepository,
) {
suspend fun updateReadHistory(
user: User,
providerId: String,
novelId: String,
chapterId: String,
) {
// 检查阅读历史记录功能是否已暂停
if (userRepo.isReadHistoryPaused(user.id)) {
return
}
// 验证小说是否存在
val novel = metadataRepo.get(providerId, novelId)
?: throwNotFound("小说不存在")
// 更新阅读历史
historyRepo.updateReadHistory(
userId = user.id,
novelId = novel.id.toHexString(),
chapterId = chapterId,
)
}
}
前后端交互流程
阅读位置保存的完整流程如下:
- 用户阅读小说时,前端定期记录滚动位置到localStorage
- 页面关闭或章节切换时,通过ReadHistoryApi同步到服务器
- 用户下次访问时,先从localStorage加载位置,再从服务器同步最新记录
- 提供暂停/恢复同步功能,保护用户隐私
流程图如下:
异常处理与边界情况
系统针对多种异常情况进行了处理:
- 隐私保护:用户可暂停阅读历史记录,暂停状态保存在用户配置中
- 数据一致性:本地存储与服务器存储冲突时,采用"最近更新优先"原则
- 性能优化:使用防抖机制减少同步请求,避免频繁操作影响性能
- 错误恢复:服务器不可用时,优先使用本地存储,待服务恢复后自动同步
总结与最佳实践
Auto-Novel的阅读位置保存系统通过分层设计实现了可靠、高效的阅读状态管理:
- 双层存储:结合localStorage和服务器存储,兼顾性能与可靠性
- 模块化设计:前端状态管理与数据访问分离,后端业务逻辑与数据访问分离
- 隐私保护:提供暂停/恢复功能,尊重用户隐私选择
- 统一接口:通过GenericNovelId实现不同类型小说的统一管理
该实现方案不仅满足了基本的阅读位置保存需求,还通过精心设计的状态管理和数据同步机制,为用户提供了无缝的跨设备阅读体验。
完整实现代码可参考:
【免费下载链接】auto-novel 轻小说机翻网站,支持网络小说/文库小说/本地小说 项目地址: https://gitcode.com/GitHub_Trending/au/auto-novel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




