无缝续读:Auto-Novel阅读位置保存的全链路技术实现

无缝续读:Auto-Novel阅读位置保存的全链路技术实现

【免费下载链接】auto-novel 轻小说机翻网站,支持网络小说/文库小说/本地小说 【免费下载链接】auto-novel 项目地址: https://gitcode.com/GitHub_Trending/au/auto-novel

你是否曾在阅读小说时被打断,再次打开却需要重新寻找上次看到的位置?Auto-Novel通过精心设计的阅读位置保存系统,让你在任何设备上都能无缝接续阅读体验。本文将深入剖析这一功能从前端到后端的完整实现方案。

功能架构概览

Auto-Novel的阅读位置保存系统采用双层存储架构,结合本地缓存与云端同步,实现了高效可靠的阅读状态管理:

  • 本地存储:使用浏览器 localStorage 保存临时阅读位置,确保页面刷新或重新打开时快速恢复
  • 云端同步:通过后端API将阅读记录持久化到数据库,支持多设备同步和历史记录管理

功能架构

核心实现模块包括:

前端实现:本地存储与状态管理

本地阅读位置存储

前端采用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,
    )
  }
}

前后端交互流程

阅读位置保存的完整流程如下:

  1. 用户阅读小说时,前端定期记录滚动位置到localStorage
  2. 页面关闭或章节切换时,通过ReadHistoryApi同步到服务器
  3. 用户下次访问时,先从localStorage加载位置,再从服务器同步最新记录
  4. 提供暂停/恢复同步功能,保护用户隐私

流程图如下:

mermaid

异常处理与边界情况

系统针对多种异常情况进行了处理:

  1. 隐私保护:用户可暂停阅读历史记录,暂停状态保存在用户配置中
  2. 数据一致性:本地存储与服务器存储冲突时,采用"最近更新优先"原则
  3. 性能优化:使用防抖机制减少同步请求,避免频繁操作影响性能
  4. 错误恢复:服务器不可用时,优先使用本地存储,待服务恢复后自动同步

总结与最佳实践

Auto-Novel的阅读位置保存系统通过分层设计实现了可靠、高效的阅读状态管理:

  1. 双层存储:结合localStorage和服务器存储,兼顾性能与可靠性
  2. 模块化设计:前端状态管理与数据访问分离,后端业务逻辑与数据访问分离
  3. 隐私保护:提供暂停/恢复功能,尊重用户隐私选择
  4. 统一接口:通过GenericNovelId实现不同类型小说的统一管理

该实现方案不仅满足了基本的阅读位置保存需求,还通过精心设计的状态管理和数据同步机制,为用户提供了无缝的跨设备阅读体验。

完整实现代码可参考:

【免费下载链接】auto-novel 轻小说机翻网站,支持网络小说/文库小说/本地小说 【免费下载链接】auto-novel 项目地址: https://gitcode.com/GitHub_Trending/au/auto-novel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值