36c506f4bf
- Introduced `note_audio` table for storing audio attachments related to notes. - Implemented audio upload endpoint in `Note` controller to handle audio file uploads. - Added sharing functionality with `note_share` table to manage share tokens and view counts. - Updated API routes to include endpoints for audio uploads and share creation. - Enhanced documentation to reflect new audio and sharing features.
13 KiB
13 KiB
Note 模块接口文档
1. 模块说明
note 是独立于现有 app/api 业务的笔记小程序模块,代码位置如下:
当前已实现能力:
- 微信小程序登录
- 笔记创建、列表、详情、更新、删除
- 实时转写文本保存
- 录音文件上传与播放
- AI 总结生成与查询
- 笔记分享与分享只读访问
路由注册位置:
2. 鉴权说明
除登录接口外,其余 note 接口都需要携带 JWT:
- Header:
Authorization: Bearer {token}
note 模块复用现有 JWT 机制,但要求 token 载荷中必须包含:
{
"userid": 123,
"guard": "note"
}
说明:
userid对应note_user.idguard=note用于和旧api模块登录态隔离
3. 环境变量
微信登录依赖以下配置:
WECHAT_MINI_APPIDWECHAT_MINI_SECRETDB_NOTE_HOSTNAMEDB_NOTE_DATABASEDB_NOTE_USERNAMEDB_NOTE_PASSWORDDB_NOTE_HOSTPORT
示例位置:
4. 数据表
表结构定义位置:
当前 note 模块使用以下 6 张表:
-
note_user用于小程序用户登录和用户资料 -
note_item笔记主表,包含正文、转写累计文本、状态、录音时长等 -
note_transcript实时转写分片记录表 -
note_ai_summaryAI 总结结果表 -
note_audio录音附件表,保存上传后的音频文件地址与时长 -
note_share分享记录表,保存分享 token 与查看次数
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 | 否 | 用户头像地址 |
请求示例:
{
"code": "021xxx",
"nickname": "张三",
"avatar_url": "https://example.com/avatar.png"
}
成功响应示例:
{
"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
}
说明:
- 首次登录时自动创建
note_user - 后续登录时按
openid更新资料与最后登录时间 - 若用户被禁用,返回 403
5.3 获取当前用户信息
- 方法:
GET - 路径:
/note/v1/auth/me - 是否鉴权:是
成功响应示例:
{
"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 |
请求示例:
{
"source_type": "text",
"title": "会议纪要",
"content": "今天确认了下周需求排期",
"status": "draft"
}
成功响应示例:
{
"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 | 否 | 按状态筛选 |
响应示例:
{
"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 - 是否鉴权:是
响应示例:
{
"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
成功响应示例:
{
"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 | 否 | 当前累计录音时长 |
请求示例:
{
"segment_no": 3,
"segment_text": "需要跟进接口联调",
"full_text": "今天确认了下周需求排期,需要跟进接口联调",
"is_final": 1,
"audio_duration_ms": 120000
}
成功响应示例:
{
"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 上传录音文件
- 方法:
POST - 路径:
/note/v1/item/audio/:id - 是否鉴权:是
- Content-Type:
multipart/form-data
表单参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio |
file | 是 | 录音文件 |
audio_duration_ms |
int | 否 | 录音时长 |
说明:
- 上传成功后会返回可直接播放的
audio_url - 后端会同步写入
note_audio,并更新笔记的录音时长
成功响应示例:
{
"code": 200,
"msg": "上传成功",
"data": {
"audio_id": 2,
"disk": "public",
"file_path": "note/audio/20260417/test.m4a",
"audio_url": "http://127.0.0.1:8000/storage/note/audio/20260417/test.m4a",
"file_size": 20480,
"mime_type": "audio/mp4",
"duration_ms": 18500,
"updated_at": 1710000400
},
"time": 1710000400
}
5.11 生成 AI 总结
- 方法:
POST - 路径:
/note/v1/ai/summary/:id - 是否鉴权:是
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
summary_type |
string | 否 | brief / outline / todo |
force_refresh |
int/bool | 否 | 是否强制重新生成 |
请求示例:
{
"summary_type": "brief",
"force_refresh": 1
}
成功响应示例:
{
"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.12 查看 AI 总结
- 方法:
GET - 路径:
/note/v1/ai/summary/:id - 是否鉴权:是
说明:
- 返回指定笔记最新的一条总结记录
5.13 创建分享
- 方法:
POST - 路径:
/note/v1/share/create/:id - 是否鉴权:是
成功响应示例:
{
"code": 200,
"msg": "分享已生成",
"data": {
"note_id": 10,
"share_token": "7a4d2f2d4a5f1b20f6f9670bb1f4d123",
"share_path": "/pages/note/edit?share_token=7a4d2f2d4a5f1b20f6f9670bb1f4d123",
"title": "会议纪要"
},
"time": 1710000600
}
说明:
- 返回
share_token和小程序页面路径 - 小程序可用该路径做转发
5.14 读取分享内容
- 方法:
GET - 路径:
/note/v1/share/read/:token - 是否鉴权:否
成功响应示例:
{
"code": 200,
"msg": "success",
"data": {
"id": 10,
"note_user_id": 1,
"title": "会议纪要",
"content": "今天确认了下周需求排期",
"transcript_text": "今天确认了下周需求排期",
"source_type": "mix",
"status": "draft",
"audio_duration_ms": 18500,
"summary_status": "success",
"last_transcript_time": 1710000300,
"created_at": 1710000000,
"updated_at": 1710000600,
"audio": {
"audio_id": 2,
"disk": "public",
"file_path": "note/audio/20260417/test.m4a",
"audio_url": "http://127.0.0.1:8000/storage/note/audio/20260417/test.m4a",
"file_size": 20480,
"mime_type": "audio/mp4",
"duration_ms": 18500,
"updated_at": 1710000400
},
"summary": {
"summary_text": "今天确认了下周需求排期,需要继续跟进接口联调。",
"status": "success"
},
"share": {
"share_token": "7a4d2f2d4a5f1b20f6f9670bb1f4d123",
"title": "会议纪要",
"view_count": 3
}
},
"time": 1710000601
}
说明:
- 用于收件人直接查看分享的笔记内容、录音和 AI 摘要
6. 错误码约定
当前模块沿用项目统一返回结构:
{
"code": 400,
"msg": "错误信息",
"data": [],
"time": 1710000000
}
常见情况:
400:参数错误401:未登录或登录态无效403:用户被禁用404:资源不存在500:服务端错误502:调用微信接口失败
7. 调用顺序建议
小程序端推荐按以下顺序接入:
- 调
wx.login - 把
code发给POST /note/v1/auth/wechat-login - 保存返回的
token - 创建笔记
POST /note/v1/item/create - 录音转写过程中持续调用
POST /note/v1/item/transcript/:id - 录音停止后上传录音文件
POST /note/v1/item/audio/:id - 需要生成总结时调用
POST /note/v1/ai/summary/:id - 分享前调用
POST /note/v1/share/create/:id - 打开详情页时调用
GET /note/v1/item/:id
8. 当前限制
- AI 总结目前是规则版,不是大模型版
- 微信登录依赖服务端已正确配置
WECHAT_MINI_APPID和WECHAT_MINI_SECRET - 分享读取接口为公开接口,建议前端仅用于只读展示