- 新增 users 表(user_id 数据隔离,bcrypt 密码) - 认证: 注册/登录(用户名+密码)/会话绑定用户, 首个用户成为管理员并接管旧数据 - 数据隔离: 笔记/分类/标签/回收站/版本/草稿/图谱/FTS 全部按用户隔离 - 前台: 登录/注册弹窗, 登录后★收藏自己的笔记, 游客只读公开笔记 - 后台: 用户名+密码登录, 每人管理自己的工作区, 越权访问返回404 - 冒烟测试重构+新增多租户隔离用例(78/78)
15 KiB
云笔记 API 文档
基础信息
- Base URL:
http://localhost:8080/api - 认证方式:Cookie(后台管理接口需要)
- 默认密码:
admin123
公开接口
公开接口无需认证即可访问(只读)。
1. 获取笔记列表
获取分页的笔记列表。
请求
GET /api/notes
Query 参数
| 参数 | 类型 | 必填 | 说明 | 默认值 |
|---|---|---|---|---|
| page | int | 否 | 页码 | 1 |
| page_size | int | 否 | 每页数量 | 20 |
| category | string | 否 | 按分类筛选 | - |
| tag | string | 否 | 按标签筛选 | - |
| pinned | bool | 否 | 只看置顶 | - |
| favorite | bool | 否 | 只看收藏 | - |
| parent_id | int | 否 | 按父目录筛选 | - |
响应示例
{
"code": 0,
"message": "success",
"data": {
"items": [
{
"id": 1,
"title": "Go 语言教程",
"category": "技术",
"tags": "[\"Go\",\"编程\"]",
"is_pinned": true,
"is_favorite": false,
"is_folder": false,
"parent_id": 0,
"sort_order": 0,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"total": 50,
"page": 1,
"page_size": 20,
"total_pages": 3
}
}
2. 获取单条笔记
根据 ID 获取笔记详情。
请求
GET /api/notes/:id
路径参数
| 参数 | 类型 | 说明 |
|---|---|---|
| id | int | 笔记 ID |
响应示例
{
"code": 0,
"message": "success",
"data": {
"id": 1,
"title": "Go 语言教程",
"content": "# Go 语言\\n\\nGo 是一门简洁高效的编程语言。",
"category": "技术",
"tags": "[\"Go\",\"编程\"]",
"is_pinned": true,
"is_favorite": false,
"is_folder": false,
"parent_id": 0,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
3. 搜索笔记
搜索标题和内容。
请求
GET /api/notes/search
Query 参数
| 参数 | 类型 | 必填 | 说明 | 默认值 |
|---|---|---|---|---|
| q | string | 是 | 搜索关键词 | - |
| page | int | 否 | 页码 | 1 |
| page_size | int | 否 | 每页数量 | 20 |
响应示例
{
"code": 0,
"message": "success",
"data": {
"items": [...],
"total": 5,
"page": 1,
"page_size": 20,
"total_pages": 1
}
}
4. 获取分类列表
获取所有分类。
请求
GET /api/categories
响应示例
{
"code": 0,
"message": "success",
"data": ["技术", "生活", "工作", "随笔"]
}
5. 获取标签列表
获取所有标签。
请求
GET /api/tags
响应示例
{
"code": 0,
"message": "success",
"data": ["Go", "Python", "JavaScript", "编程", "笔记"]
}
6. 获取树形结构
获取目录树形结构(包含目录和笔记)。
请求
GET /api/tree
响应示例
{
"code": 0,
"message": "success",
"data": [
{
"id": 1,
"title": "技术文档",
"is_folder": true,
"children": [
{
"id": 2,
"title": "Go 语言教程",
"is_folder": false
}
]
},
{
"id": 3,
"title": "生活随笔",
"is_folder": false
}
]
}
管理接口
管理接口需要先登录,获取 Cookie 认证。
7. 登录
请求
POST /admin/login
Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| password | string | 是 | 管理员密码 |
响应示例
{
"code": 0,
"message": "登录成功"
}
8. 登出
请求
POST /admin/logout
响应示例
{
"code": 0,
"message": "已退出登录"
}
9. 检查认证状态
请求
GET /admin/auth
响应示例
{
"authenticated": true
}
10. 创建笔记/目录
请求
POST /api/notes
Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| title | string | 是 | 标题 |
| content | string | 否 | 内容(Markdown) |
| category | string | 否 | 分类 |
| tags | string | string | 标签(JSON 数组格式) |
| is_folder | bool | 否 | 是否为文件夹 |
| is_pinned | bool | 否 | 是否置顶 |
| is_favorite | bool | 否 | 是否收藏 |
| parent_id | int | 否 | 父目录 ID |
| sort_order | int | 否 | 排序顺序 |
请求示例
{
"title": "新建笔记",
"content": "# 我的笔记\\n\\n这是笔记内容",
"category": "技术",
"tags": "[\"笔记\",\"教程\"]",
"is_folder": false
}
响应示例
{
"code": 0,
"message": "笔记创建成功",
"data": {
"id": 10
}
}
11. 更新笔记/目录
请求
PUT /api/notes/:id
Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| title | string | 否 | 标题 |
| content | string | 否 | 内容(Markdown) |
| category | string | 否 | 分类 |
| tags | string | 否 | 标签 |
| is_pinned | bool | 否 | 是否置顶 |
| is_favorite | bool | 否 | 是否收藏 |
| parent_id | int | 否 | 父目录 ID |
| sort_order | int | 否 | 排序顺序 |
响应示例
{
"code": 0,
"message": "笔记更新成功"
}
12. 删除笔记/目录
请求
DELETE /api/notes/:id
说明:删除目录时会同时删除该目录下的所有子项。
响应示例
{
"code": 0,
"message": "笔记删除成功"
}
响应状态码
| code | 说明 |
|---|---|
| 0 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权(需要登录) |
| 404 | 笔记不存在 |
| 500 | 服务器内部错误 |
密码保护笔记接口
访问密码保护的笔记
请求
POST /api/notes/:id/access
Body 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| password | string | 是 | 笔记访问密码 |
响应示例
{
"code": 0,
"message": "访问成功",
"data": {
"id": 1,
"title": "受保护的笔记",
"content": "# 笔记内容..."
}
}
图片上传接口
上传图片
请求
POST /admin/api/upload
说明:需要登录认证。仅支持 jpg、png、gif、webp、bmp 格式,最大 5MB。
Form 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| image | file | 是 | 图片文件 |
响应示例
{
"code": 0,
"message": "上传成功",
"data": {
"url": "/uploads/1234567890_abc123.png"
}
}
图片访问:上传后的图片通过 /uploads/文件名 访问。
导入导出接口
导出笔记为 Markdown
请求
GET /admin/api/export/:id
说明:需要登录认证。导出的文件包含 YAML front matter。
响应:下载 .md 文件,文件名以笔记标题命名。
导入 Markdown 文件
请求
POST /admin/api/import
说明:需要登录认证。仅支持 .md 文件。
Form 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | file | 是 | Markdown 文件 |
响应示例
{
"code": 0,
"message": "导入成功",
"data": {
"id": 15,
"title": "导入的笔记标题"
}
}
错误响应示例
{
"code": 401,
"message": "请先登录后台管理"
}
使用示例
cURL
# 登录
curl -X POST http://localhost:8080/admin/login \
-d "password=admin123" \
-c cookies.txt
# 获取笔记列表
curl http://localhost:8080/api/notes
# 搜索笔记
curl "http://localhost:8080/api/notes/search?q=Go"
# 创建笔记(需要认证)
curl -X POST http://localhost:8080/api/notes \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"title":"新笔记","content":"# 标题\\n\\n内容"}'
# 更新笔记(需要认证)
curl -X PUT http://localhost:8080/api/notes/1 \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"title":"更新后的标题"}'
# 删除笔记(需要认证)
curl -X DELETE http://localhost:8080/api/notes/1 -b cookies.txt
JavaScript (Fetch API)
// 登录
await fetch('/admin/login', {
method: 'POST',
body: new URLSearchParams({ password: 'admin123' }),
credentials: 'include'
});
// 获取笔记列表
const res = await fetch('/api/notes');
const data = await res.json();
// 创建笔记
await fetch('/api/notes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: '新笔记', content: '# 内容' }),
credentials: 'include'
});
新增功能 API(v2)
管理接口认证(安全优化)
后台管理写操作(创建/更新/删除/回收站/版本/分享/导入导出/上传)统一走 /admin/api,
需登录后携带服务端会话 cookie(随机 token,非固定字符串)。未登录返回 401。
安全策略调整
公开接口 GET /api/notes/:id
仅返回 公开且未设置密码 的笔记完整内容。带密码或未公开的笔记返回 403(需走密码验证接口), 防止绕过密码保护直接读取内容。
回收站(软删除)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /admin/api/trash |
回收站列表(含已删除的目录和笔记) |
| POST | /admin/api/restore/:id |
恢复笔记/目录(目录连子树一起恢复) |
| POST | /admin/api/purge/:id |
彻底删除(不可恢复,含版本历史) |
| POST | /admin/api/empty-trash |
清空回收站 |
删除笔记 DELETE /admin/api/notes/:id 现为软删除(进入回收站),目录删除会连带软删除所有子项。
版本历史
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /admin/api/notes/:id/versions |
获取笔记全部历史版本 |
| POST | /admin/api/notes/:id/restore-version |
恢复指定版本(form: version_id) |
每次保存(标题或内容变化)自动生成快照。
分享链接
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /admin/api/notes/:id/share |
创建分享(form: expire_hours,0=永久) |
| POST | /admin/api/notes/:id/revoke-share |
撤销分享 |
| GET | /api/share/:token |
公开获取分享笔记 JSON(有密码需带 ?password=) |
| GET | /share/:token |
分享阅读页(HTML) |
批量导出
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /admin/api/export-all |
全部笔记导出为 zip(按目录结构 + YAML front matter) |
图片上传(安全增强)
上传会做内容嗅探(magic bytes 校验),不仅检查扩展名。伪装成图片的脚本会被拒绝。
后台管理笔记接口
管理端读取/写笔记统一走 /admin/api/notes(可访问私有、带密码笔记):
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /admin/api/notes |
创建 |
| GET | /admin/api/notes/:id |
详情(完整内容) |
| PUT | /admin/api/notes/:id |
更新 |
| DELETE | /admin/api/notes/:id |
软删除 |
前端新增功能
- 深色模式:前台/后台均可切换(🌙/☀️ 按钮),偏好存 localStorage
- Mermaid 图表:前台 Markdown 中
```mermaid代码块渲染为流程图/时序图等 - 待办清单:前台渲染
- [ ]/- [x]可勾选清单 - 字数统计:前台笔记详情显示字数与预估阅读时长
- 回收站/版本历史/分享:后台工具栏按钮 + 面板
v3 新增功能(2026-08-11)
FTS5 全文搜索
GET /api/notes/search?q=关键词&page=1 现使用 SQLite FTS5 全文索引,支持中文短词(1~2 字)与英文。
- 采用
unicode61分词器 + Go 层对中文做逐字分词(segmentCJK),使每个汉字独立成词元,支持短词搜索 - 索引在创建/更新/标签变更时增量维护,启动时全量重建
- 搜索结果按
bm25相关度排序,排除已删除笔记与目录 - FTS 查询失败时自动回退到传统 LIKE 搜索
- 构建需启用
-tags=sqlite_fts5(否则报no such module: fts5)
双向链接 / 知识图谱
支持 [[笔记标题]] wiki 链接语法:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /admin/api/notes/:id/backlinks |
反向链接(谁链接到了该笔记) |
| GET | /admin/api/graph |
知识图谱数据 {nodes:[{id,title}], edges:[{source,target}]} |
- 后台编辑器支持点击
[[链接]]跳转并高亮 - 后台工具栏「🕸 知识图谱」以 SVG 图形化展示节点与链接关系
自动保存草稿
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /admin/api/notes/:id/draft |
保存草稿(body {content}),不触发版本历史 |
| DELETE | /admin/api/notes/:id/draft |
清除草稿(保存正文成功后调用) |
- 后台编辑器每 8 秒自动保存未落盘内容
- 打开笔记时若存在未保存草稿会提示恢复
标签管理
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /admin/api/tags/usage |
标签使用统计 [{name,count}] |
| POST | /admin/api/tags/rename |
重命名 {old_name,new_name} |
| POST | /admin/api/tags/merge |
合并 {from,to}(from 并入 to) |
| DELETE | /admin/api/tags |
删除 {name} |
- 后台工具栏「🏷 标签管理」图形化操作
- 重命名/合并/删除会同步更新所有含该标签的笔记及其全文索引
富文本所见即所得(编辑器增强)
- 后台编辑器新增实时预览:编辑右侧即时渲染 Markdown
- 新增格式工具栏:加粗/斜体/标题/列表/链接/代码/图片/表格/任务清单
- 仍以 Markdown 为存储源(保证 FTS/反向链接/导出兼容),预览所见即所得
移动端 / PWA
- 新增 PWA 支持:
/manifest.json、/sw.js、图标icon-192.png/icon-512.png - 前台页面响应式适配手机(侧栏折叠、字号/按钮优化)
- 可添加到主屏幕离线使用
注:FTS5 需用
-tags=sqlite_fts5编译;note_search虚拟表由 Go 代码维护(手动管理而非 SQL 触发器),保证中文分词正确。
v4 多租户账号体系
认证(用户名 + 密码,bcrypt)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/auth/register |
注册 {username,password,display_name};首个用户自动成为 admin 并接管历史遗留(user_id=0)笔记 |
| POST | /api/auth/login |
登录 {username,password},写入 note_token cookie |
| POST | /api/auth/logout |
登出 |
| GET | /api/auth/me |
当前登录用户信息(游客返回 null) |
多租户数据隔离
- 每篇笔记归属
user_id;所有查询(笔记/分类/标签/回收站/版本/草稿/图谱/FTS 搜索)均按当前用户隔离。 - 前台
/api:登录用户看自己的笔记(前台可★收藏自己的笔记);游客只读所有用户的公开无密码笔记。 - 后台
/admin/api:需登录,每个用户只能管理自己的笔记(越权访问他人笔记返回 404)。 - 旧账号固定密码登录已移除;会话与用户绑定,重启后需重新登录。
安全
note_token会话 cookie:HttpOnly + SameSite=Lax(防 CSRF),随机 32 字节 token,7 天过期,服务端内存校验绑定用户。- 密码 bcrypt(cost 10),兼容旧 SHA-256 自动升级。