Files
SGGL_HBAZ/PDF书籍WebAPI接口文档.md
T
2026-09-11 11:14:08 +08:00

424 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PDF 书籍模块 WebAPI 接口文档
> 对应功能:PC 端《PDF 书籍阅读》页(FineUIPro.Web/HSSE/PDFDOC/PdfBookView.aspx)—— 多级章节目录 + 富文本正文维护。
> 服务项目:SGGL/WebAPI(经典 ASP.NET Web API.NET Framework 4.8);数据服务:SGGL/BLL/API/APIPdfBookService.cs。
> 数据表:Sys_PdfBook(书籍)/ Sys_PdfChapter(章节,目录层级用 ParentChapterId + Level(1章 2节 3小节),同级用 SortNo 排序,正文 HTML 存 [Text])。
> 状态:已实现并经本地 IIS Express 联调验证(2026-09)。
---
## 1. 通用约定
### 1.1 地址与路由
- 路由模板:api/{controller}/{action}/{id},本模块控制器名为 **PdfBook**
- 调用前缀示例:http://<host>/api/PdfBook/getBooks
- 只支持 JSON 输出(服务端已清除 XML 格式化器);请使用 UTF-8 编码收发中文。
### 1.2 统一响应包装(Model.ResponeData
所有接口返回同一结构:
| 字段 | 类型 | 说明 |
|---|---|---|
| code | int | **1** = 成功;**0** = 失败(注:权限过滤返回的 code 为字符串 "0" |
| message | string | 失败时的中文错误描述;成功为 null |
| data | object | 业务数据,失败为 null |
示例:
```json
{ "code": 1, "message": null, "data": { } }
```
### 1.3 字段命名
响应 JSON 键名与 C# 属性一致,采用 **PascalCase**(如 BookId、ChapterTitle),与全站既有 API 保持一致;请求 JSON 键名大小写不敏感(Newtonsoft 反序列化),文档示例统一小写开头书写。
### 1.4 鉴权
本模块接口按读/写区分权限(全局过滤器 WebAPI/Filter/TestPermissionAttribute.cs):
| 类型 | 接口 | 鉴权 |
|---|---|---|
| 只读 | getBooks / getChapterTree / getChapter / searchChapter | **免登录**(已加入白名单,与 ProtectionStandards 等规范类只读接口一致) |
| 维护 | addBook / addChapter / editChapter / deleteChapter / saveContent | 需**登录态 + token 双重校验**(见下) |
维护接口调用步骤:
1. 先调登录接口获取 FormsAuth Cookie
POST /api/user/postLoginOn
```json
{ "Account": "jinkn", "Password": "xxxxxx" }
```
成功后响应会写入名为 auth 的 Cookie(十年有效),后续请求须携带该 Cookie。
2. 请求头携带 token: <UserId>Sys_User.UserId,登录响应 data.UserId 即该值)。
3. 二者缺一不可:缺 Cookie 或缺有效 token 均返回 {"code":"0","message":"您没有权限!"}。
---
## 2. 接口总览
| # | 方法 | 路径 | 说明 |
|---|---|---|---|
| 1 | GET | /api/PdfBook/getBooks | 书籍列表(含章节数) |
| 2 | GET | /api/PdfBook/getChapterTree?bookId= | 某本书多级章节目录树 |
| 3 | GET | /api/PdfBook/getChapter?chapterId= | 章节正文详情(HTML + 纯文本) |
| 4 | POST | /api/PdfBook/searchChapter | 章节关键词检索(可限定书籍) |
| 5 | POST | /api/PdfBook/addBook | 新增书籍(需登录) |
| 6 | POST | /api/PdfBook/addChapter | 新增章节(可指定父章节,需登录) |
| 7 | POST | /api/PdfBook/editChapter | 修改章节名称(需登录) |
| 8 | POST | /api/PdfBook/deleteChapter | 删除章节(连同全部子章节,需登录) |
| 9 | POST | /api/PdfBook/saveContent | 保存章节正文(富文本 HTML,需登录) |
---
## 3. 接口明细
### 3.1 书籍列表
GET /api/PdfBook/getBooks
无参数。返回按登记时间升序的全部书籍(与 PC 页下拉一致,第一本即页面默认选中书)。
响应示例(实测):
```json
{
"code": 1,
"message": null,
"data": [
{
"BookId": "BOOK_SAFE_20260827",
"Title": "《施工现场安全防护手册》",
"ChapterCount": 366,
"CreateTime": "2026-09-03T10:30:49"
},
{
"BookId": "BOOK_TEST_001",
"Title": "《测试书籍-数据库连通》",
"ChapterCount": 0,
"CreateTime": "2026-09-04T15:50:30.39"
}
]
}
```
data 数组元素字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| BookId | string | 书籍主键 |
| Title | string | 书名 |
| ChapterCount | int | 章节总数 |
| CreateTime | datetime? | 登记时间 |
### 3.2 章节目录树
GET /api/PdfBook/getChapterTree?bookId=BOOK_SAFE_20260827
| 参数 | 必填 | 说明 |
|---|---|---|
| bookId | 是 | 书籍主键 |
返回**多级嵌套树**:顶级节点数组,子章节在 Children 中递归(叶子章节 Children 为空数组),同级按 SortNo 排序。
响应示例(实测节选):
```json
{
"code": 1,
"message": null,
"data": [
{
"ChapterId": "BOOK_SAFE_20260827_C001",
"ChapterTitle": "第一章 安全防护",
"Level": 1,
"PageStart": 0,
"PageEnd": 0,
"HasContent": false,
"Children": [
{
"ChapterId": "BOOK_SAFE_20260827_C002",
"ChapterTitle": "1.1三宝四口五临边",
"Level": 2,
"PageStart": 0,
"PageEnd": 0,
"HasContent": true,
"Children": []
},
{
"ChapterId": "BOOK_SAFE_20260827_C003",
"ChapterTitle": "1.2三宝",
"Level": 2,
"PageStart": 0,
"PageEnd": 0,
"HasContent": false,
"Children": [
{
"ChapterId": "BOOK_SAFE_20260827_C004",
"ChapterTitle": "1.2.1安全帽",
"Level": 3,
"PageStart": 0,
"PageEnd": 0,
"HasContent": true,
"Children": []
}
]
}
]
}
]
}
```
data 节点字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| ChapterId | string | 章节主键(getChapter / saveContent 等接口用) |
| ChapterTitle | string | 章节名称 |
| Level | int | 层级:1=章,2=节,3=小节 |
| PageStart / PageEnd | int | 起止页码(手动维护模式无页码则为 0) |
| HasContent | bool | 该章节是否已录入正文(true 才建议作为可阅读节点) |
| Children | array | 子章节数组(叶子为 []) |
> 提示:与 PC 页交互一致——目录型节点(有子章节)自身通常无正文(HasContent=false),正文多录入在叶子章节。
### 3.3 章节正文详情
GET /api/PdfBook/getChapter?chapterId=BOOK_SAFE_20260827_C004
| 参数 | 必填 | 说明 |
|---|---|---|
| chapterId | 是 | 章节主键 |
响应示例(实测,Content 字段较长已省略):
```json
{
"code": 1,
"message": null,
"data": {
"ChapterId": "BOOK_SAFE_20260827_C004",
"BookId": "BOOK_SAFE_20260827",
"BookTitle": "《施工现场安全防护手册》",
"ChapterTitle": "1.2.1安全帽",
"ParentChapterId": "BOOK_SAFE_20260827_C003",
"Level": 3,
"PageStart": 0,
"PageEnd": 0,
"Content": "<p>…安全帽在购买、日常检查时要检查如下内容…</p>",
"ContentText": "1、安全帽在购买、日常检查时要检查如下内容: (1)安全帽如有下颊带,应使用宽度不小于10mm的织带…"
}
}
```
- Content:富文本 HTMLUMeditor 生成)。2026-09 起页面上传图片在保存时转为 base64 内嵌(data:image/png;base64,...),正文自包含不依赖图片文件;个别历史数据仍可能是 res/umeditor 路径引用。WebView/rich-text 均可直接渲染 data URL
- ContentText:去标签纯文本,适合列表摘要/全文展示;
- 章节不存在时返回 code=0、message=章节不存在或已被删除。
### 3.4 章节关键词检索
POST /api/PdfBook/searchChapter
请求体:
```json
{ "keyword": "安全帽", "bookId": "BOOK_SAFE_20260827" }
```
| 字段 | 必填 | 说明 |
|---|---|---|
| keyword | 是 | 检索关键词(正文纯文本 LIKE 字面匹配;% _ 通配符已转义) |
| bookId | 否 | 限定书籍;不传则全库检索 |
响应示例(实测,命中两章):
```json
{
"code": 1,
"message": null,
"data": [
{
"BookId": "BOOK_SAFE_20260827",
"BookTitle": "《施工现场安全防护手册》",
"ChapterId": "BOOK_SAFE_20260827_C002",
"ChapterTitle": "1.1三宝四口五临边",
"PageStart": 0,
"PageEnd": 0,
"Snippet": "1.三宝:是指安全帽、安全带、安全网…"
},
{
"BookId": "BOOK_SAFE_20260827",
"BookTitle": "《施工现场安全防护手册》",
"ChapterId": "BOOK_SAFE_20260827_C004",
"ChapterTitle": "1.2.1安全帽",
"PageStart": 0,
"PageEnd": 0,
"Snippet": "1、安全帽在购买、日常检查时要检查如下内容…"
}
]
}
```
- 匹配对象为 Sys_PdfChapter.[Text](先剔除 HTML 标签再做 LIKE),命中片段取关键词前后各约 40 字;
- 说明:当前为字面匹配,未做分词/全文索引,后续可升级 SQL Server 全文检索。
---
### 3.5 新增书籍(需登录)
POST /api/PdfBook/addBook
请求体:
```json
{ "title": "《新书示例》", "createUser": "apitest" }
```
| 字段 | 必填 | 说明 |
|---|---|---|
| title | 是 | 书名 |
| createUser | 否 | 登记人,缺省 api |
响应:
```json
{ "code": 1, "message": null, "data": { "bookId": "PB202609051447346108" } }
```
新增书籍无章节;与 PC 页一致:FilePath=NULL、TotalPages=0、IndexStatus=2(手动维护)。
### 3.6 新增章节(需登录)
POST /api/PdfBook/addChapter
请求体:
```json
{ "bookId": "PB202609051447346108", "parentChapterId": "", "chapterTitle": "第一章 示例" }
```
| 字段 | 必填 | 说明 |
|---|---|---|
| bookId | 是 | 所属书籍主键 |
| parentChapterId | 否 | 父章节主键;**为空=顶级章节**;传入则挂到该章节下(层级=父级+1) |
| chapterTitle | 是 | 章节名称 |
| createUser | 否 | 预留 |
响应:
```json
{ "code": 1, "message": null, "data": { "chapterId": "CH20260905144734f549" } }
```
### 3.7 修改章节名称(需登录)
POST /api/PdfBook/editChapter
```json
{ "chapterId": "CH20260905144734ba08", "chapterTitle": "1.1 子章节(改名后)" }
```
成功响应:{ "code": 1, "data": true };仅改名,不影响层级与正文。
### 3.8 删除章节(需登录,级联删除)
POST /api/PdfBook/deleteChapter
```json
{ "chapterId": "CH20260905144734f549" }
```
成功响应(实测:父章节带 1 个子章节,共删 2 条):
```json
{ "code": 1, "message": null, "data": { "deletedCount": 2 } }
```
> 删除会递归收集该章节的**全部后代子章节**一并删除(与 PC 页删除章节及其子章节行为一致),请谨慎调用。
### 3.9 保存章节正文(需登录)
POST /api/PdfBook/saveContent
```json
{
"chapterId": "CH20260905144734ba08",
"content": "<p>安全帽验收接口测试正文:检查下颊带宽度。</p>"
}
```
成功响应:{ "code": 1, "data": true }content 为 UMeditor 风格富文本 HTML,存 Sys_PdfChapter.[Text]。PC 页保存时会把本站上传图片引用转成 base64 内嵌,App/第三方提交的内容按原样存储。
---
## 4. 常见错误
| code | message | 场景 |
|---|---|---|
| 1 | - | 成功 |
| 0 | 书名不能为空 / 章节名称不能为空 / bookId 不能为空 / chapterId 不能为空 / keyword 不能为空 | 必填参数缺失 |
| 0 | 父章节不存在:xxx / 章节不存在:xxx / 章节不存在或已被删除 | 引用的数据不存在 |
| "0" | 您没有权限! | 维护接口未携带 auth Cookie 或有效 token |
| "0" | 登录超出,请重新登录! | 同上(过滤器另一分支文案,同为未授权) |
---
## 5. 附录
### 5.1 数据结构说明(SQL Server
Sys_PdfBook
| 列 | 说明 |
|---|---|
| BookId | 主键(PB+yyyyMMddHHmmss+4位随机,服务端生成) |
| Title | 书名 |
| IndexStatus | 2=手动维护(无自动索引流程) |
| CreateUser / CreateTime | 登记人 / 登记时间 |
Sys_PdfChapter
| 列 | 说明 |
|---|---|
| ChapterId | 主键(CH+yyyyMMddHHmmss+4位随机,服务端生成) |
| BookId | 所属书籍 |
| ParentChapterId | 父章节,NULL=顶级 |
| Level | 1=章 2=节 3=小节(新增自动=父级+1) |
| ChapterTitle | 章节名称 |
| PageStart / PageEnd | 页码(手动维护为 NULL,接口输出 0) |
| Text | 正文富文本 HTML |
| SortNo | 同级排序(新增=全书 MAX+1) |
### 5.2 curl 调用示例(Windows;含中文的 JSON 请用文件方式 --data-binary 发送)
```bat
REM 1) 登录,保存 cookielogin.json 内容见 1.4
curl -c cookies.txt -X POST -H "Content-Type: application/json" --data-binary "@login.json" http://localhost:7143/api/user/postLoginOn
REM 2) 只读(免登录)
curl "http://localhost:7143/api/PdfBook/getBooks"
curl "http://localhost:7143/api/PdfBook/getChapterTree?bookId=BOOK_SAFE_20260827"
REM 3) 维护(cookie + token 头)
curl -b cookies.txt -H "token: <UserId>" -X POST -H "Content-Type: application/json" --data-binary "@body.json" http://localhost:7143/api/PdfBook/saveContent
```
### 5.3 与 PC 页面(HSSE/PDFDOC/PdfBookView.aspx)的对应关系
| 页面操作 | 接口 |
|---|---|
| 页首书籍下拉(默认第一本) | getBooks |
| 左侧多级目录树 | getChapterTree |
| 点击叶子章节显示正文 | getChapter |
| 保存内容(富文本) | saveContent |
| 新增书籍弹窗 | addBook |
| 新增章节 / 编辑名称 / 删除章节(含子章节) | addChapter / editChapter / deleteChapter |
### 5.4 变更记录
| 日期 | 内容 |
|---|---|
| 2026-09-05 | 初版:新增 PdfBookController + APIPdfBookService9 个接口全部经本地 IIS Expresshttp://localhost:7143)联调通过;只读接口加入权限白名单免登录 |
| 2026-09-05 | 页面富文本图片改为 base64 内嵌存储:保存内容时自动转换(getChapter 返回的 Content 中图片为 data URL |