# 书籍章节 admin 接口 ## 基本信息 - 模块:book - 资源:书籍章节 - 端:admin - 鉴权:`PrivateGroup`,需要 `JWT + Casbin` - 审计:创建、更新、单删、批量删除启用 `OperationRecord` - 前缀:`/book` - 实体模型:`book.BookChapter` - 搜索入参:`bookReq.BookChapterSearch` - 详情响应:`bookRes.BookChapterResponse` - 列表项:`book.BookChapter` - 返回:写操作 `response.Response{msg}`;详情 `response.Response{data}`;列表 `response.PageResult` - 删除策略:硬删 ## CRUD ### 创建书籍章节 - Method:`POST` - Path:`/book/createBookChapter` - Handler:`BookChapterApi.CreateBookChapter` - Service:`BookChapterService.CreateBookChapter` - 审计:是 #### Request Body `book.BookChapter` | 字段 | 类型 | 必填 | 规则 | 说明 | |:---|:---|:---:|:---|:---| | bookId | uint | 是 | `> 0` | 所属书籍 ID | | title | string | 是 | 非空,最长 `255` | 章节标题 | | chapterNo | int | 是 | `> 0`;同一 `bookId` 下唯一 | 同书内章节顺序编号 | | isReadable | bool | 否 | 默认 `false`;为 `true` 时 `totalLines > 0` | 是否对 app 端开放阅读 | | contentFileUrl | string | 是 | 非空,最长 `500` | 章节内容文件 URL | | totalLines | int | 否 | 默认 `0`,`>= 0` | 章节正文总行数 | | isEnabled | bool | 否 | 默认 `true` | 章节是否启用 | #### Response - `response.Response{msg}` #### 规则 - 创建请求禁止传服务端生成字段:`id/createdAt/updatedAt`。 - `bookId + chapterNo` 唯一。 - `isReadable=true` 时,`totalLines` 必须大于 `0`。 ### 删除书籍章节 - Method:`DELETE` - Path:`/book/deleteBookChapter` - Handler:`BookChapterApi.DeleteBookChapter` - Service:`BookChapterService.DeleteBookChapter` - 审计:是 #### Request Query | 参数 | 类型 | 必填 | 规则 | 说明 | |:---|:---|:---:|:---|:---| | id | int | 是 | `> 0` | 章节 ID | #### Response - `response.Response{msg}` ### 批量删除书籍章节 - Method:`DELETE` - Path:`/book/deleteBookChapterByIds` - Handler:`BookChapterApi.DeleteBookChapterByIds` - Service:`BookChapterService.DeleteBookChapterByIds` - 审计:是 #### Request Query | 参数 | 类型 | 必填 | 规则 | 说明 | |:---|:---|:---:|:---|:---| | ids | int[] | 二选一 | 非空,元素均 `> 0` | 章节 ID 数组 | | ids[] | int[] | 二选一 | 非空,元素均 `> 0` | 章节 ID 数组,兼容数组写法 | #### Response - `response.Response{msg}` #### 规则 - `ids` 与 `ids[]` 二选一。 ### 更新书籍章节 - Method:`PUT` - Path:`/book/updateBookChapter` - Handler:`BookChapterApi.UpdateBookChapter` - Service:`BookChapterService.UpdateBookChapter` - 审计:是 #### Request Body `book.BookChapter` | 字段 | 类型 | 必填 | 规则 | 说明 | |:---|:---|:---:|:---|:---| | id | uint | 是 | `> 0` | 章节 ID | | bookId | uint | 是 | `> 0` | 所属书籍 ID | | title | string | 是 | 非空,最长 `255` | 章节标题 | | chapterNo | int | 是 | `> 0`;同一 `bookId` 下唯一 | 同书内章节顺序编号 | | isReadable | bool | 否 | 为 `true` 时 `totalLines > 0` | 是否对 app 端开放阅读 | | contentFileUrl | string | 是 | 非空,最长 `500` | 章节内容文件 URL | | totalLines | int | 否 | `>= 0` | 章节正文总行数 | | isEnabled | bool | 否 | 布尔值 | 章节是否启用 | #### Response - `response.Response{msg}` #### 规则 - 更新请求禁止传服务端维护字段:`createdAt/updatedAt`。 - 更新为实体全量保存,前端应传完整可编辑实体,避免字段被零值覆盖。 - `bookId + chapterNo` 唯一。 - `isReadable=true` 时,`totalLines` 必须大于 `0`。 ### 查询书籍章节详情 - Method:`GET` - Path:`/book/findBookChapter` - Handler:`BookChapterApi.FindBookChapter` - Service:`BookChapterService.GetBookChapter` - 审计:否 #### Request Query | 参数 | 类型 | 必填 | 规则 | 说明 | |:---|:---|:---:|:---|:---| | id | int | 是 | `> 0` | 章节 ID | #### Response `bookRes.BookChapterResponse` | 字段 | 类型 | 说明 | |:---|:---|:---| | bookChapter | object | 章节实体 | | bookChapter.id | uint | 章节 ID | | bookChapter.createdAt | string | 创建时间 | | bookChapter.updatedAt | string | 更新时间 | | bookChapter.bookId | uint | 所属书籍 ID | | bookChapter.title | string | 章节标题 | | bookChapter.chapterNo | int | 同书内章节顺序编号 | | bookChapter.isReadable | bool | 是否对 app 端开放阅读 | | bookChapter.contentFileUrl | string | 章节内容文件 URL | | bookChapter.totalLines | int | 章节正文总行数 | | bookChapter.isEnabled | bool | 章节是否启用 | ### 分页查询书籍章节列表 - Method:`GET` - Path:`/book/getBookChapterList` - Handler:`BookChapterApi.GetBookChapterList` - Service:`BookChapterService.GetBookChapterInfoList` - 审计:否 #### Request Query `bookReq.BookChapterSearch` | 参数 | 类型 | 必填 | 规则 | 说明 | |:---|:---|:---:|:---|:---| | page | int | 否 | 默认 `1`,最小 `1` | 页码 | | pageSize | int | 否 | 默认 `10`,最大 `100` | 每页数量 | | keyword | string | 否 | 章节标题模糊查询 | 关键字 | | bookId | uint | 否 | `> 0` | 所属书籍 ID | | isReadable | bool | 否 | 布尔值 | 是否对 app 端开放阅读 | | isEnabled | bool | 否 | 布尔值 | 章节是否启用 | #### Response `response.PageResult` | 字段 | 类型 | 说明 | |:---|:---|:---| | list | array | `book.BookChapter` 列表 | | list[].id | uint | 章节 ID | | list[].createdAt | string | 创建时间 | | list[].updatedAt | string | 更新时间 | | list[].bookId | uint | 所属书籍 ID | | list[].title | string | 章节标题 | | list[].chapterNo | int | 同书内章节顺序编号 | | list[].isReadable | bool | 是否对 app 端开放阅读 | | list[].contentFileUrl | string | 章节内容文件 URL | | list[].totalLines | int | 章节正文总行数 | | list[].isEnabled | bool | 章节是否启用 | | total | int64 | 总数 | | page | int | 当前页 | | pageSize | int | 每页数量 | #### 规则 - 列表默认排序:`book_id asc, chapter_no asc`。 ## 规则 - 章节使用硬删;删除后数据库不保留软删标记。 - `bookId + chapterNo` 是章节唯一约束;新增或更新时不能与同书已有章节冲突。 - `chapterNo` 必须大于 `0`。 - `totalLines` 不能小于 `0`;`isReadable=true` 时 `totalLines` 必须大于 `0`。 - 创建、更新复用实体 `book.BookChapter`;列表查询复用 `bookReq.BookChapterSearch`;详情返回 `bookRes.BookChapterResponse`。