# 书籍 需求草案

- **阶段** 当前阶段只整理本需求文档，归并已确认需求，未确认项显式标注“需补”，不要求同步修改代码和下游文档
- **要求** 对错误、冲突或不闭环需求应及时纠正并提示；需求整理以逻辑闭环、链路清晰、实现轻量为目标，避免为单点功能引入复杂链路

## 表

### 书籍信息表
- 书名：主标题
- 子标题：副标题
- 书籍类型：系统字典 `book_type`，动态值，必填
- 时代标签：字典 `book_era_tag`，必填
- 封面图片URL：封面图地址
- 出版社：出版机构
- 出版时间：出版日期
- 简介：书籍简介
- 热度：展示聚合值
- 评分：`0-10` 分，建议一位小数
- 点评数：展示聚合值
- 字数：全书总字数
- 书籍完结状态：字典 `book_completion_status`
- 上下架状态：字典 `book_publish_status`
- 系列ID：所属系列，可为空
- 系列内排序：同系列展示顺序
- 原始书籍文件URL：原始 `txt` 文件地址

### 书籍章节表
- 书籍ID：所属书籍
- 章节标题：章节名称
- 章节编号：同书内顺序编号
- 是否可阅读：是否对 `app` 端开放阅读
- 章节内容文件URL：单章内容文件地址
- 总行数：章节内容行数
- 是否启用：章节启停状态

### 书籍系列表
- 名称：系列名称
- 封面图片URL：系列封面地址
- 简介：系列简介
- 是否启用：系列启停状态

### 书籍作者表
- 名称：作者名称
- 状态：字典 `book_author_status`
- 简介：作者简介
- 封面图片URL：作者封面地址

### 书籍作者关联表
- 书籍ID：关联书籍
- 作者ID：关联作者
- 作者排序：作者展示顺序

### 用户阅读记录表
- 会员用户ID：阅读用户
- 书籍ID：所属书籍
- 阅读书籍标题快照：用于阅读历史列表展示
- 阅读进度：前端展示百分比
- 阅读章节ID：当前续读章节
- 阅读文本行Index：当前续读文本行下标，正文首行为 `1`，不允许为 `0`
- 最后阅读时间：最近一次阅读时间

### 用户收藏记录表
- 会员用户ID：收藏用户
- 书籍ID：收藏书籍
- 收藏时间：收藏发生时间

### 书籍评论表
- 评论用户ID：评论用户
- 评论书籍ID：所属书籍
- 评论章节ID：评论目标章节，`0` 表示整本书
- 评论文本行Index：评论目标文本行下标，`0` 表示整章
- 评论内容：评论正文
- 评论点赞数：普通用户点赞聚合值
- 评论状态：字典 `book_comment_status`

### 评论点赞记录表
- 评论ID：被点赞评论
- 点赞用户ID：点赞用户
- 点赞时间：点赞发生时间

## 需求描述

### 书籍主体
- 书籍是核心主体，列表、详情、搜索、推荐都以书籍信息为主。
- 一本书可以不属于任何系列；属于系列时，按 `系列内排序` 展示。
- 一本书不直接存作者名字符串；作者通过关联关系维护，时代标签通过书籍主表字段维护。
- 每本书必须关联 `1` 个书籍类型；`book_type` 使用系统字典动态值承载，并通过业务侧独立封装读写。
- `book_type` 当前仅用于筛选、聚合和展示，不参与业务分支和状态流转。
- `book_publish_status` 当前值域为：`draft`、`off_shelf`、`on_shelf`。
- 热度、评分、点评数可冗余存储，但业务上按聚合值理解。

### 数据来源与上传
- 原始 `txt` 仅作为书籍原始备份和参考来源，不直接作为当前对外章节内容的生效来源。
- 上传原始文件只更新原始文件，不自动覆盖现有章节数据。
- 当前章节数据由后台通过单章文件上传方式新增和替换维护。
- `原始 txt` 一键分割章节功能当前仅保留业务占位，现阶段不定义实现方式和对接细节。
- 章节表、章节发布、阅读定位和评论定位仍属于当前业务范围，不因一键分割章节能力暂缓而取消。

### 章节发布
- 同一本书下，章节编号必须唯一，并按章节编号排序阅读。
- 书内统一定位锚点使用 `书籍ID + 章节ID + 文本行Index`，因此章节内容落地后必须能稳定生成文本行下标。
- 正文实际行号统一从 `1` 开始；`文本行Index=0` 只用于整本书或整章这类非正文行定位。
- 章节一旦对外发布，章节编号和定位规则应保持稳定，避免阅读记录失效。
- 不可阅读或已禁用章节不对 `app` 端展示；若用户通过阅读记录回到该位置，只提示当前章节不可访问，不继续打开正文。

### 章节重建策略
- 原始 `txt` 一键分割章节与重建能力当前仅保留业务占位，现阶段不定义具体模式、流程和交互规则。
- 后续若启动该能力，再单独补充分割策略、覆盖边界和历史定位兼容规则。

### 连载与完结
- 书籍完结状态用于展示和搜索，区分连载与完结。
- 完结状态仅作为业务标签，不直接限制后台新增或修改章节。
- 已发布章节允许修订正文内容。
- 修订已发布章节正文时，必须通过锚点兼容机制保证历史阅读记录和评论定位仍然可用。
- 若新的正文内容无法兼容既有 `章节ID + 文本行Index` 定位，则不允许直接覆盖已发布章节。

### 系列
- 系列用于组织同一作品的上部/下部、第一部/第二部等顺序关系。
- 系列下书籍通过 `系列ID + 系列内排序` 关联，系列自身不直接承载章节内容。
- 未启用系列不影响已挂载书籍基础信息，但 `app` 端不应继续以系列形式对外展示。

### 作者
- 作者名称应唯一，避免同名重复建档。
- 每本书至少关联 `1` 个作者。
- 同一本书下，同一个作者只能关联一次。
- 禁用作者不再允许被新增关联，但历史上已关联的书籍仍可保留展示。
- 作者排序决定书籍详情页和列表页的作者展示顺序。

### 时代标签
- 时代标签使用系统字典 `book_era_tag` 承载，不单独建设标签主数据表。
- `book_era_tag` 当前值域为：未知时代、远古、汉、唐、宋、元、明、清、近代、现代。
- 每本书必须设置 `1` 个时代标签；无法判断时使用 `未知时代`。
- 时代标签对外读写入口独立封装，不直接暴露系统字典通用入口。
- 时代标签用于书籍筛选和聚合，不使用主表字符串自由录入。

### 阅读记录
- 阅读记录同时承担“用户阅读历史”和“续读书签锚点”两种用途，不拆成两套数据。
- 阅读历史列表按“用户 + 书籍”维度展示；每个用户对每本书只保留一条最新阅读记录。
- 用户再次进入同一本书时，应优先按该记录中的最新锚点恢复到上次阅读位置；新的阅读行为覆盖旧的续读位置、阅读进度和最后阅读时间。
- 主定位以 `书籍ID + 章节ID + 文本行Index` 为准，进度百分比和书籍标题快照仅用于列表展示和回显。
- 章节禁用或书籍下架后，阅读记录仍保留用于历史展示；再次进入时只提示当前书籍或章节不可访问，不恢复正文内容。

### 收藏
- 每个用户对每本书只能收藏一次。
- 仅上架书籍允许新增收藏；下架后历史收藏记录保留，但不再新增。

### 评论
- 评论统一通过 `书籍ID + 章节ID + 文本行Index` 表达评论目标。
- 当 `章节ID=0` 时，表示对整本书的评价；此时 `文本行Index` 也应为 `0`。
- 当 `章节ID>0` 且 `文本行Index=0` 时，表示对整章的评价。
- 当 `章节ID>0` 且 `文本行Index>0` 时，表示对书中某一句话的评论。
- `book_comment_status` 当前值域为：`normal`、`hidden`。
- 评论默认只允许发生在已上架书籍上；若评论目标指向具体章节或具体文本行，则对应章节必须可阅读。
- 后台必须具备隐藏或下架评论能力，不能直接依赖物理删除处理违规内容。
- 评论点赞数表示普通用户点赞聚合值，不承载其他认可语义。

### 评论点赞
- 点赞关系以“用户 + 评论”唯一确定，同一用户对同一评论只能存在一条有效点赞关系。
- 点赞功能只支持“点赞 / 取消点赞”两种操作，不扩展表情、权重、连击、分值等复杂玩法。
- 点赞和取消点赞都要按幂等处理，重复点赞或重复取消点赞不应导致计数异常。
- 评论列表和详情展示的 `评论点赞数` 直接使用评论表聚合值，不在读请求里实时汇总点赞记录。
- 点赞记录只用于维护点赞关系和判断“当前用户是否已点赞”，不承载通知、积分、排行榜等额外流程。
