feat: add note module and route fixes
This commit is contained in:
@@ -0,0 +1,549 @@
|
||||
# Note 模块接口文档
|
||||
|
||||
## 1. 模块说明
|
||||
|
||||
`note` 是独立于现有 `app/api` 业务的笔记小程序模块,代码位置如下:
|
||||
|
||||
- [app/note/controller](/root/work/tp/app/note/controller)
|
||||
- [app/note/service](/root/work/tp/app/note/service)
|
||||
- [app/note/model](/root/work/tp/app/note/model)
|
||||
|
||||
当前已实现能力:
|
||||
|
||||
1. 微信小程序登录
|
||||
2. 笔记创建、列表、详情、更新、删除
|
||||
3. 实时转写文本保存
|
||||
4. AI 总结生成与查询
|
||||
|
||||
路由注册位置:
|
||||
|
||||
- [route/app.php](/root/work/tp/route/app.php)
|
||||
|
||||
---
|
||||
|
||||
## 2. 鉴权说明
|
||||
|
||||
除登录接口外,其余 `note` 接口都需要携带 JWT:
|
||||
|
||||
- Header: `Authorization: Bearer {token}`
|
||||
|
||||
`note` 模块复用现有 JWT 机制,但要求 token 载荷中必须包含:
|
||||
|
||||
```json
|
||||
{
|
||||
"userid": 123,
|
||||
"guard": "note"
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `userid` 对应 `note_user.id`
|
||||
- `guard=note` 用于和旧 `api` 模块登录态隔离
|
||||
|
||||
---
|
||||
|
||||
## 3. 环境变量
|
||||
|
||||
微信登录依赖以下配置:
|
||||
|
||||
- `WECHAT_MINI_APPID`
|
||||
- `WECHAT_MINI_SECRET`
|
||||
- `DB_NOTE_HOSTNAME`
|
||||
- `DB_NOTE_DATABASE`
|
||||
- `DB_NOTE_USERNAME`
|
||||
- `DB_NOTE_PASSWORD`
|
||||
- `DB_NOTE_HOSTPORT`
|
||||
|
||||
示例位置:
|
||||
|
||||
- [\.example.env](/root/work/tp/.example.env)
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据表
|
||||
|
||||
表结构定义位置:
|
||||
|
||||
- [database.sql](/root/work/tp/database.sql#L26)
|
||||
|
||||
当前 `note` 模块使用以下 4 张表:
|
||||
|
||||
1. `note_user`
|
||||
用于小程序用户登录和用户资料
|
||||
|
||||
2. `note_item`
|
||||
笔记主表,包含正文、转写累计文本、状态、录音时长等
|
||||
|
||||
3. `note_transcript`
|
||||
实时转写分片记录表
|
||||
|
||||
4. `note_ai_summary`
|
||||
AI 总结结果表
|
||||
|
||||
---
|
||||
|
||||
## 5. 接口列表
|
||||
|
||||
### 5.1 获取模块概览
|
||||
|
||||
- 方法:`GET`
|
||||
- 路径:`/note/v1/meta/interfaces`
|
||||
- 是否鉴权:否
|
||||
|
||||
用途:
|
||||
|
||||
- 返回 note 模块接口规划概览
|
||||
|
||||
---
|
||||
|
||||
### 5.2 微信小程序登录
|
||||
|
||||
- 方法:`POST`
|
||||
- 路径:`/note/v1/auth/wechat-login`
|
||||
- 是否鉴权:否
|
||||
|
||||
请求参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `code` | string | 是 | `wx.login` 获取的临时 code |
|
||||
| `nickname` | string | 否 | 用户昵称 |
|
||||
| `avatar_url` | string | 否 | 用户头像地址 |
|
||||
|
||||
请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "021xxx",
|
||||
"nickname": "张三",
|
||||
"avatar_url": "https://example.com/avatar.png"
|
||||
}
|
||||
```
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "登录成功",
|
||||
"data": {
|
||||
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.xxx",
|
||||
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.xxx",
|
||||
"expires_in": 604800,
|
||||
"user": {
|
||||
"id": 1,
|
||||
"member_id": 0,
|
||||
"openid": "oxxx",
|
||||
"nickname": "张三",
|
||||
"avatar_url": "https://example.com/avatar.png",
|
||||
"mobile": "",
|
||||
"is_new_user": true
|
||||
}
|
||||
},
|
||||
"time": 1710000000
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
1. 首次登录时自动创建 `note_user`
|
||||
2. 后续登录时按 `openid` 更新资料与最后登录时间
|
||||
3. 若用户被禁用,返回 403
|
||||
|
||||
---
|
||||
|
||||
### 5.3 获取当前用户信息
|
||||
|
||||
- 方法:`GET`
|
||||
- 路径:`/note/v1/auth/me`
|
||||
- 是否鉴权:是
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"member_id": 0,
|
||||
"openid": "oxxx",
|
||||
"nickname": "张三",
|
||||
"avatar_url": "https://example.com/avatar.png",
|
||||
"mobile": "",
|
||||
"status": 1,
|
||||
"last_login_time": 1710000000,
|
||||
"created_at": 1710000000
|
||||
},
|
||||
"time": 1710000001
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.4 创建笔记
|
||||
|
||||
- 方法:`POST`
|
||||
- 路径:`/note/v1/item/create`
|
||||
- 是否鉴权:是
|
||||
|
||||
请求参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `source_type` | string | 是 | `text` / `audio` / `mix` |
|
||||
| `title` | string | 否 | 标题 |
|
||||
| `content` | string | 否 | 正文 |
|
||||
| `audio_duration_ms` | int | 否 | 录音时长 |
|
||||
| `status` | string | 否 | 默认 `draft` |
|
||||
|
||||
请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"source_type": "text",
|
||||
"title": "会议纪要",
|
||||
"content": "今天确认了下周需求排期",
|
||||
"status": "draft"
|
||||
}
|
||||
```
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "创建成功",
|
||||
"data": {
|
||||
"id": 10,
|
||||
"note_user_id": 1,
|
||||
"title": "会议纪要",
|
||||
"content": "今天确认了下周需求排期",
|
||||
"transcript_text": "",
|
||||
"source_type": "text",
|
||||
"status": "draft",
|
||||
"audio_duration_ms": 0,
|
||||
"summary_status": "none",
|
||||
"last_transcript_time": 0,
|
||||
"created_at": 1710000000,
|
||||
"updated_at": 1710000000
|
||||
},
|
||||
"time": 1710000000
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 如果不传 `title`,后端会根据 `content` 自动生成标题
|
||||
- 如果 `title` 和 `content` 都为空,标题会默认为 `未命名笔记`
|
||||
|
||||
---
|
||||
|
||||
### 5.5 笔记列表
|
||||
|
||||
- 方法:`GET`
|
||||
- 路径:`/note/v1/item/list`
|
||||
- 是否鉴权:是
|
||||
|
||||
查询参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `page` | int | 否 | 默认 1 |
|
||||
| `page_size` | int | 否 | 默认 10,最大 100 |
|
||||
| `keyword` | string | 否 | 搜索标题、正文、转写文本 |
|
||||
| `status` | string | 否 | 按状态筛选 |
|
||||
|
||||
响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"id": 10,
|
||||
"note_user_id": 1,
|
||||
"title": "会议纪要",
|
||||
"content": "今天确认了下周需求排期",
|
||||
"transcript_text": "",
|
||||
"source_type": "text",
|
||||
"status": "draft",
|
||||
"audio_duration_ms": 0,
|
||||
"summary_status": "none",
|
||||
"last_transcript_time": 0,
|
||||
"created_at": 1710000000,
|
||||
"updated_at": 1710000000
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 10
|
||||
},
|
||||
"time": 1710000001
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.6 笔记详情
|
||||
|
||||
- 方法:`GET`
|
||||
- 路径:`/note/v1/item/:id`
|
||||
- 是否鉴权:是
|
||||
|
||||
响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"id": 10,
|
||||
"note_user_id": 1,
|
||||
"title": "会议纪要",
|
||||
"content": "今天确认了下周需求排期",
|
||||
"transcript_text": "需要跟进接口联调",
|
||||
"source_type": "mix",
|
||||
"status": "draft",
|
||||
"audio_duration_ms": 120000,
|
||||
"summary_status": "success",
|
||||
"last_transcript_time": 1710000100,
|
||||
"created_at": 1710000000,
|
||||
"updated_at": 1710000200,
|
||||
"summary": {
|
||||
"summary_id": 3,
|
||||
"summary_type": "brief",
|
||||
"summary_text": "今天确认了下周需求排期\n需要跟进接口联调",
|
||||
"todo_list": [
|
||||
"需要跟进接口联调"
|
||||
],
|
||||
"keywords": [
|
||||
"需求",
|
||||
"排期",
|
||||
"接口联调"
|
||||
],
|
||||
"status": "success"
|
||||
}
|
||||
},
|
||||
"time": 1710000201
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.7 更新笔记
|
||||
|
||||
- 方法:`POST`
|
||||
- 路径:`/note/v1/item/update/:id`
|
||||
- 是否鉴权:是
|
||||
|
||||
请求参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `title` | string | 否 | 标题 |
|
||||
| `content` | string | 否 | 正文 |
|
||||
| `status` | string | 否 | 状态 |
|
||||
| `audio_duration_ms` | int | 否 | 录音时长 |
|
||||
|
||||
说明:
|
||||
|
||||
- 只更新传入字段
|
||||
- 只能更新自己的笔记
|
||||
|
||||
---
|
||||
|
||||
### 5.8 删除笔记
|
||||
|
||||
- 方法:`POST`
|
||||
- 路径:`/note/v1/item/delete/:id`
|
||||
- 是否鉴权:是
|
||||
|
||||
说明:
|
||||
|
||||
- 当前为软删除,写入 `deleted_at`
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "删除成功",
|
||||
"data": {
|
||||
"deleted": true,
|
||||
"id": 10
|
||||
},
|
||||
"time": 1710000300
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.9 保存实时转写内容
|
||||
|
||||
- 方法:`POST`
|
||||
- 路径:`/note/v1/item/transcript/:id`
|
||||
- 是否鉴权:是
|
||||
|
||||
请求参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `full_text` | string | 是 | 当前累计完整转写文本 |
|
||||
| `segment_no` | int | 否 | 分片序号,默认 0 |
|
||||
| `segment_text` | string | 否 | 当前分片文本 |
|
||||
| `is_final` | int/bool | 否 | 是否最终片段 |
|
||||
| `audio_duration_ms` | int | 否 | 当前累计录音时长 |
|
||||
|
||||
请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"segment_no": 3,
|
||||
"segment_text": "需要跟进接口联调",
|
||||
"full_text": "今天确认了下周需求排期,需要跟进接口联调",
|
||||
"is_final": 1,
|
||||
"audio_duration_ms": 120000
|
||||
}
|
||||
```
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "转写保存成功",
|
||||
"data": {
|
||||
"note_id": 10,
|
||||
"segment_no": 3,
|
||||
"is_final": 1,
|
||||
"transcript_text": "今天确认了下周需求排期,需要跟进接口联调",
|
||||
"audio_duration_ms": 120000,
|
||||
"updated_at": 1710000400
|
||||
},
|
||||
"time": 1710000400
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 后端会同步更新 `note_item.transcript_text`
|
||||
- 同一个 `note_id + segment_no` 会覆盖写入
|
||||
|
||||
---
|
||||
|
||||
### 5.10 生成 AI 总结
|
||||
|
||||
- 方法:`POST`
|
||||
- 路径:`/note/v1/ai/summary/:id`
|
||||
- 是否鉴权:是
|
||||
|
||||
请求参数:
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `summary_type` | string | 否 | `brief` / `outline` / `todo` |
|
||||
| `force_refresh` | int/bool | 否 | 是否强制重新生成 |
|
||||
|
||||
请求示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"summary_type": "brief",
|
||||
"force_refresh": 1
|
||||
}
|
||||
```
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "总结生成成功",
|
||||
"data": {
|
||||
"summary_id": 3,
|
||||
"note_id": 10,
|
||||
"summary_type": "brief",
|
||||
"summary_text": "今天确认了下周需求排期\n需要跟进接口联调",
|
||||
"todo_list": [
|
||||
"需要跟进接口联调"
|
||||
],
|
||||
"keywords": [
|
||||
"需求",
|
||||
"排期",
|
||||
"接口联调"
|
||||
],
|
||||
"status": "success",
|
||||
"error_message": "",
|
||||
"created_at": 1710000500,
|
||||
"updated_at": 1710000500
|
||||
},
|
||||
"time": 1710000500
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 当前实现为规则版总结,不依赖外部大模型
|
||||
- 若已存在成功总结且 `force_refresh=0`,会直接返回已有结果
|
||||
|
||||
---
|
||||
|
||||
### 5.11 查看 AI 总结
|
||||
|
||||
- 方法:`GET`
|
||||
- 路径:`/note/v1/ai/summary/:id`
|
||||
- 是否鉴权:是
|
||||
|
||||
说明:
|
||||
|
||||
- 返回指定笔记最新的一条总结记录
|
||||
|
||||
---
|
||||
|
||||
## 6. 错误码约定
|
||||
|
||||
当前模块沿用项目统一返回结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 400,
|
||||
"msg": "错误信息",
|
||||
"data": [],
|
||||
"time": 1710000000
|
||||
}
|
||||
```
|
||||
|
||||
常见情况:
|
||||
|
||||
- `400`:参数错误
|
||||
- `401`:未登录或登录态无效
|
||||
- `403`:用户被禁用
|
||||
- `404`:资源不存在
|
||||
- `500`:服务端错误
|
||||
- `502`:调用微信接口失败
|
||||
|
||||
---
|
||||
|
||||
## 7. 调用顺序建议
|
||||
|
||||
小程序端推荐按以下顺序接入:
|
||||
|
||||
1. 调 `wx.login`
|
||||
2. 把 `code` 发给 `POST /note/v1/auth/wechat-login`
|
||||
3. 保存返回的 `token`
|
||||
4. 创建笔记 `POST /note/v1/item/create`
|
||||
5. 录音转写过程中持续调用 `POST /note/v1/item/transcript/:id`
|
||||
6. 需要生成总结时调用 `POST /note/v1/ai/summary/:id`
|
||||
7. 打开详情页时调用 `GET /note/v1/item/:id`
|
||||
|
||||
---
|
||||
|
||||
## 8. 当前限制
|
||||
|
||||
1. AI 总结目前是规则版,不是大模型版
|
||||
2. 微信登录依赖服务端已正确配置 `WECHAT_MINI_APPID` 和 `WECHAT_MINI_SECRET`
|
||||
3. 当前未实现文件音频上传,只实现了“转写文本写回后端”的数据链路
|
||||
Reference in New Issue
Block a user