library-picturebook-activity/docs/api/public-leai-work-form.md
zhonghua 5ae9233afc feat: work-form 无 Token 白名单与 leai_status 原样持久化
- Security: /public/leai-works/** 放行;Controller 使用 getCurrentUserIdOrNull;匿名仅按 remoteWorkId 定位作品

- saveWorkForm: 请求体 status 写入 leai_status(原样覆盖,不做区间收敛)

- 文档与编目/配音页相关调整

Made-with: Cursor
2026-04-16 10:31:22 +08:00

173 lines
6.2 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.

# 乐读派作品表单本库快照API
面向外部系统与本平台前端「创作壳」对齐:**不经过乐读派 B2 的 GET/PUT 作品详情**,直接读写本库 `t_ugc_work` / `t_ugc_work_page` 中的编目与分页快照。
| 项 | 说明 |
|----|------|
| Base URL | 部署域名 + **context-path `/api`**(见 `application.yml` `server.servlet.context-path` |
| 完整路径前缀 | `/api/public/leai-works` |
| 认证 | **可选**。未带 Token 时接口仍可访问Spring Security 白名单 `/public/leai-works/**`),供外部系统对接;携带 `Authorization: Bearer <JWT>`后端会校验作品归属当前用户。Web 端可继续加 `X-Tenant-Code`、`X-Tenant-Id`(见前端 `request.ts` |
| 安全说明 | 无 Token 时**仅凭路径中的 `remoteWorkId` 定位作品**,请依赖 ID 保密性并在网络层做访问控制;带 Token 时仍按用户维度校验。 |
---
## 1. 保存编目 / 分页快照
### 请求
| 项 | 值 |
|----|-----|
| Method | **PUT** |
| URL | `/api/public/leai-works/{remoteWorkId}/work-form` |
| Content-Type | `application/json` |
### 路径参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `remoteWorkId` | string | 是 | 乐读派侧作品 ID可能为大整数**建议按字符串传输**;路径中需 URL 编码) |
**示例**
```http
PUT /api/public/leai-works/2044362486899150848/work-form HTTP/1.1
Host: <your-host>
Authorization: Bearer <access_token>
Content-Type: application/json
```
### 请求体JSON 对象)
- **不能为空**`{}` 会返回 **400**`请求体不能为空`)。
- 服务端从 body 中读取三类数据:
1. **编目字段**(可选子集):仅处理以下键,其余顶层键若存在会被忽略(除 `pageList`、`status` 外):
`author`、`title`、`subtitle`、`intro`、`tags`
2. **进度**`status`(整数)原样写入本库 `leai_status`,与 GET 返回的 `status` 一致(不做区间收敛)。
3. **分页**`pageList` 为数组时,按乐读派 `pageList` 形态写入本库分页表。
| 字段 | 类型 | 说明 |
|------|------|------|
| `title` | string | 标题 |
| `author` | string | 作者署名 |
| `subtitle` | string | 副标题 |
| `intro` | string | 简介 |
| `tags` | string[] | 标签列表 |
| `status` | number | 乐读派创作进度(`leai_status`见下文「status 取值」 |
| `pageList` | object[] | 分页列表;元素字段见下表 |
`pageList` 元素:
| 字段 | 类型 | 说明 |
|------|------|------|
| `pageNum` | number | 页码(与后端 `page_no` 对应) |
| `imageUrl` | string | 插图 URL |
| `text` | string | 本页文案 |
| `audioUrl` | string | 配音 URL可为空字符串表示未配 |
### 业务规则(摘要)
- 作品必须属于**当前登录用户**且 `remote_work_id` 匹配,否则 **404**`作品不存在或无权操作`)。
- 若本次请求更新了编目,且作品为草稿、且乐读派进度已 ≥「生成完成」,可能将发布状态从草稿置为未发布(见 `PublicLeaiWorkFormService`)。
- 若同时携带 `pageList` 且**每一页**均有非空 `audioUrl`,保存分页后会将 `leai_status` 置为 **5已配音**,覆盖本次请求中的 `status` 值。
-`pageList` 非空,且**每一页**的 `audioUrl` 均为非空白字符串,则将 `leai_status` 更新为 **已配音5**
### 成功响应
HTTP **200**Body 为统一包装:
```json
{
"code": 200,
"message": "success",
"data": null
}
```
`data` 可能为 `null`,以实际返回为准。)
### 错误响应
| HTTP | codebody | 典型 message |
|------|----------------|--------------|
| 400 | 400 | `remoteWorkId 无效` / `请求体不能为空` |
| 401 | 401 | 未认证或 Token 无效 |
| 404 | 404 | `作品不存在或无权操作` |
错误体结构与项目统一 `Result` 一致(含 `message` 等字段)。
---
## 2. 查询本库作品详情(建议与 PUT 配合:先 GET 再改后 PUT
便于外部系统做「读-改-写」合并,避免只提交部分字段时覆盖丢失其它字段。
| 项 | 值 |
|----|-----|
| Method | **GET** |
| URL | `/api/public/leai-works/{remoteWorkId}/work-form` |
| 认证 | 同 PUT**Bearer JWT** |
### 成功响应 `data` 结构(对象)
| 字段 | 类型 | 说明 |
|------|------|------|
| `workId` | string | 与路径中 `remoteWorkId` 一致(乐读派 ID |
| `status` | number | 乐读派创作进度 `leai_status`,见下表 |
| `title` | string | 标题 |
| `author` | string | 作者 |
| `coverUrl` | string | 封面 URL |
| `subtitle` | string | 副标题 |
| `intro` | string | 简介 |
| `tags` | array | 标签 |
| `pageList` | object[] | 分页;元素含 `pageNum`、`imageUrl`、`text`、`audioUrl` |
### `status``leai_status`)取值参考
| 值 | 含义 |
|----|------|
| -1 | 失败 |
| 0 | 草稿 |
| 1 | 待处理 |
| 2 | 处理中 |
| 3 | 生成完成 |
| 4 | 已编目 |
| 5 | 已配音 |
(定义见后端 `LeaiCreationStatus`。)
---
## 3. 对接建议
1. **大整数 ID**`remoteWorkId` 在部分语言中超出 IEEE754 安全整数,**全程使用字符串**。
2. **合并提交**:若只改编目,可先 **GET** 全量,在内存中覆盖 `author`/`subtitle`/`intro`/`tags`/`title` 等字段后再 **PUT** 全量,与当前前端「快照 + 覆盖」策略一致,避免清空 `pageList`
3. **仅改分页**:可只带 `pageList`(及必须的非空 body编目键可选。
4. **Swagger**:若服务开启 Knife4j可在 `/doc.html` 查看 **公众端-乐读派作品表单** 分组(以部署为准)。
---
## 4. 实现位置(源码索引)
| 说明 | 路径 |
|------|------|
| Controller | `lesingle-creation-backend/.../pub/controller/PublicLeaiWorkController.java` |
| 业务 | `lesingle-creation-backend/.../pub/service/PublicLeaiWorkFormService.java` |
文档版本与接口行为以服务端代码为准;若行为变更请同步更新本文档。