Files
mini_tp/docs/note_api.md
T
nepiedg 36c506f4bf feat(note): add audio upload and sharing functionality
- 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.
2026-04-17 10:33:33 +00:00

13 KiB
Raw Blame History

Note 模块接口文档

1. 模块说明

note 是独立于现有 app/api 业务的笔记小程序模块,代码位置如下:

当前已实现能力:

  1. 微信小程序登录
  2. 笔记创建、列表、详情、更新、删除
  3. 实时转写文本保存
  4. 录音文件上传与播放
  5. AI 总结生成与查询
  6. 笔记分享与分享只读访问

路由注册位置:


2. 鉴权说明

除登录接口外,其余 note 接口都需要携带 JWT

  • Header: Authorization: Bearer {token}

note 模块复用现有 JWT 机制,但要求 token 载荷中必须包含:

{
  "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

示例位置:


4. 数据表

表结构定义位置:

当前 note 模块使用以下 6 张表:

  1. note_user 用于小程序用户登录和用户资料

  2. note_item 笔记主表,包含正文、转写累计文本、状态、录音时长等

  3. note_transcript 实时转写分片记录表

  4. note_ai_summary AI 总结结果表

  5. note_audio 录音附件表,保存上传后的音频文件地址与时长

  6. 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
}

说明:

  1. 首次登录时自动创建 note_user
  2. 后续登录时按 openid 更新资料与最后登录时间
  3. 若用户被禁用,返回 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 自动生成标题
  • 如果 titlecontent 都为空,标题会默认为 未命名笔记

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-Typemultipart/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. 调用顺序建议

小程序端推荐按以下顺序接入:

  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/item/audio/:id
  7. 需要生成总结时调用 POST /note/v1/ai/summary/:id
  8. 分享前调用 POST /note/v1/share/create/:id
  9. 打开详情页时调用 GET /note/v1/item/:id

8. 当前限制

  1. AI 总结目前是规则版,不是大模型版
  2. 微信登录依赖服务端已正确配置 WECHAT_MINI_APPIDWECHAT_MINI_SECRET
  3. 分享读取接口为公开接口,建议前端仅用于只读展示