一个基于 Rust 构建的现代化文档系统,类似 GitBook,支持独立使用或与 Rainbow-Auth 认证系统集成。
- 文档空间: 类似 GitBook 的 Space 概念,支持多个独立的文档项目
- 层级结构: 支持章节嵌套,灵活的文档组织方式
- Markdown 编辑: 完整的 Markdown 支持,富文本编辑体验
- 实时预览: 编辑时实时预览文档效果
- 版本控制: 完整的文档版本管理和历史记录
- 集成模式: 与 Rainbow-Auth 完全集成,使用企业级 RBAC 权限控制
- 多租户支持: 完整的空间成员管理和邀请系统
- 细粒度权限: 支持空间级别和文档级别的权限控制
- 角色管理: 支持多种角色:所有者、管理员、编辑者、成员、阅读者
- 邀请机制: 通过邮箱或用户ID邀请成员加入空间
- 全文搜索: 快速搜索文档内容,支持高亮显示
- 高级搜索: 按空间、标签、作者等条件筛选
- 搜索建议: 智能搜索自动补全
- 搜索索引: 自动维护的全文搜索索引
- 向量搜索: 支持语义搜索和AI应用集成 详细文档
- 向量存储: 为文档存储向量嵌入,支持语义搜索
- 灵活集成: 支持任何嵌入模型(OpenAI、文心、通义等)
- 批量操作: 高效的批量向量存储和检索接口
- 相似度搜索: 基于余弦相似度的文档匹配
- 查看向量存储功能文档了解更多
- 标签管理: 创建、编辑、删除标签
- 文档标记: 为文档添加多个标签
- 标签统计: 使用频率和热门标签分析
- 标签搜索: 按标签快速查找文档
- 颜色配置: 自定义标签颜色和样式
- 多格式支持: 图片、文档、文本、代码、压缩包等
- 图片处理: 自动生成缩略图,支持多种图片格式
- 文件上传: 支持拖拽上传和批量上传
- 安全验证: 文件类型检查和大小限制
- 关联管理: 文件可关联到文档和空间
- 权限控制: 基于用户和空间的访问控制
- 空间成员管理: 邀请、管理、移除成员
- 角色权限控制: 基于角色的精细化权限管理
- 邀请系统: 支持邮箱邀请和用户ID邀请,邮件通知和站内通知
- 评论系统: 文档评论和讨论
- 通知系统: 站内通知,支持空间邀请、文档更新等多种通知类型
- 活动日志: 完整的操作历史记录
- 多种格式: 支持 PDF、HTML、电子书等格式导出
- 主题定制: 可定制的导出样式和品牌化
- Web框架: Axum (与 Rainbow-Auth 相同)
- 数据库: SurrealDB (与 Rainbow-Auth 相同)
- 认证: JWT + OAuth 2.0 / OIDC
- 文档处理: pulldown-cmark, comrak
- 异步运行时: Tokio
- Rust 1.87.0 或更高版本
- SurrealDB
- Rainbow-Auth
- 足够的磁盘空间用于文件存储
SoulBook 提供了两种运行模式:安装向导模式 和 生产模式。
安装向导提供类似 WordPress/Discuz 的 Web 界面安装体验,无需手动配置文件。
# 1. 克隆项目
git clone https://github.com/RcityHunter/SoulBook.git
cd SoulBook
# 2. 启动安装模式(编译并运行)
cargo run --features installer
# 3. 浏览器访问安装向导
# 访问 http://localhost:3000
# 系统会自动检测未安装状态并显示安装向导# 1. 构建安装版本
./build.sh installer
# 2. 运行编译好的程序
./target/release/soulbook
# 3. 浏览器访问 http://localhost:3000 完成安装- 环境检查 - 检查系统环境和依赖
- 数据库配置 - 配置 SurrealDB 连接
- 管理员账户 - 创建系统管理员账户
- 站点配置 - 配置站点基本信息
- 完成安装 - 保存配置并初始化系统
开发时使用 Cargo Run:
cargo run # 编译+运行开发版本
cargo run --features installer # 编译+运行安装版本- 每次检查代码变化并重新编译
- 适合开发和测试
- 程序运行在前台,Ctrl+C 停止
生产部署使用 Cargo Build:
cargo build --release # 只编译,生成优化的可执行文件
./target/release/soulbook # 运行编译好的程序- 生成独立的二进制文件,可部署到其他机器
- 性能更好,适合生产环境
git clone https://github.com/RcityHunter/SoulBook.git
cd SoulBookcp .env.example .env
# 编辑 .env 文件配置数据库和认证信息# 连接到 SurrealDB
surreal sql --conn http://localhost:8000 --user root --pass root --ns docs --db main
# 导入数据库架构
surreal import --conn http://localhost:8000 --user root --pass root --ns docs --db main schemas/docs_schema.sql# 构建生产版本(不包含安装向导)
cargo build --release
cargo run
# 或直接运行
./target/release/soulbookcurl http://localhost:3000/health系统通过以下机制判断是否需要显示安装向导:
- 首次启动: 没有
.rainbow_docs_installed文件 → 显示安装向导 - 安装完成: 创建
.rainbow_docs_installed文件 → 正常运行模式 - 重新安装: 删除
.rainbow_docs_installed文件 → 重新显示安装向导
# 重新进入安装模式(用于测试)
rm -f .rainbow_docs_installed
cargo run --features installer项目提供了便捷的构建脚本:
# 构建安装版本(包含安装向导)
./build.sh installer
# 构建生产版本(不包含安装向导)
./build.sh production
# 构建开发版本
./build.sh dev
# 查看帮助
./build.sh前端通过 API 请求检查安装状态:
// 前端发送请求检查安装状态
const response = await fetch('/api/install/status')
const data = await response.json()
if (!data.data.is_installed) {
// 显示安装向导界面
return <InstallWizard />
} else {
// 显示正常应用界面
return <NormalApp />
}- 前端访问:
/api/install/status - 通过代理转发到后端:
http://localhost:3000/api/install/status - 后端检查
.rainbow_docs_installed文件并返回状态
# 1. 启动后端(安装模式)
cd SoulBook
cargo run --features installer
# 2. 启动前端(新终端)
cd SoulBookFront
npm run dev
# 3. 浏览器访问 http://localhost:5173
# 4. 前端自动检测并显示安装向导与 Rainbow-Auth 集成,享受企业级认证和权限管理:
RAINBOW_AUTH_URL=http://localhost:8080
RAINBOW_AUTH_INTEGRATION=true
JWT_SECRET=your-jwt-secret
# 文件上传配置
UPLOAD_DIR=./uploads
MAX_FILE_SIZE=10485760RAINBOW_AUTH_INTEGRATION=false
JWT_SECRET=your-jwt-secret
# 文件上传配置
UPLOAD_DIR=./uploads
MAX_FILE_SIZE=10485760UPLOAD_DIR: 文件上传目录,默认为./uploadsMAX_FILE_SIZE: 最大文件大小(字节),默认为 10MB (10485760)
所有API需要在请求头中包含有效的JWT token:
Authorization: Bearer <your-jwt-token>
SoulBook 提供了完整的向量存储和检索 API,支持语义搜索和 AI 应用集成。
- 查看向量存储 API 文档了解详细接口说明
- 支持存储、检索、搜索和批量操作
- 灵活集成各种嵌入模型
GET /api/spaces查询参数:
page(可选): 页码,默认为1per_page(可选): 每页数量,默认为20search(可选): 搜索关键词
响应示例:
{
"spaces": [
{
"id": "space:123",
"name": "API Documentation",
"slug": "api-docs",
"description": "API接口文档",
"is_public": true,
"created_at": "2024-01-01T00:00:00Z",
"created_by": "user123"
}
],
"total_count": 5,
"page": 1,
"per_page": 20
}POST /api/spaces
Content-Type: application/json请求体:
{
"name": "新文档空间",
"slug": "new-space",
"description": "空间描述",
"is_public": true
}响应示例:
{
"id": "space:456",
"name": "新文档空间",
"slug": "new-space",
"description": "空间描述",
"is_public": true,
"created_at": "2024-01-15T10:30:00Z",
"created_by": "user123"
}GET /api/spaces/{space_id}PUT /api/spaces/{space_id}
Content-Type: application/json请求体:
{
"name": "更新的空间名称",
"description": "更新的描述",
"is_public": false
}DELETE /api/spaces/{space_id}GET /api/spaces/{space_id}/statsGET /api/docs/spaces/{space_slug}/members权限要求: 需要 members.manage 权限
响应示例:
{
"success": true,
"data": [
{
"id": "member:123",
"space_id": "space:456",
"user_id": "user:789",
"role": "editor",
"permissions": ["docs.read", "docs.write"],
"status": "accepted",
"invited_at": "2024-01-01T00:00:00Z",
"accepted_at": "2024-01-01T01:00:00Z",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"message": "Members retrieved successfully"
}POST /api/docs/spaces/{space_slug}/invite
Content-Type: application/json权限要求: 需要 members.invite 权限
请求体:
{
"email": "user@example.com",
"role": "editor",
"message": "欢迎加入我们的文档空间!",
"expires_in_days": 7
}或者通过用户ID直接邀请:
{
"user_id": "user:123",
"role": "member",
"message": "邀请你加入我们的项目文档",
"expires_in_days": 30
}角色说明:
owner- 空间所有者(自动拥有所有权限)admin- 管理员(可管理文档、邀请和管理成员)editor- 编辑者(可读写文档)member- 成员(可读写文档)viewer- 阅读者(只读权限)
响应示例:
{
"success": true,
"data": {
"id": "invitation:789",
"space_id": "space:456",
"email": "user@example.com",
"invite_token": "abc123-def456-ghi789",
"role": "editor",
"permissions": ["docs.read", "docs.write"],
"invited_by": "user:current",
"message": "欢迎加入我们的文档空间!",
"expires_at": "2024-01-22T10:30:00Z",
"created_at": "2024-01-15T10:30:00Z"
},
"message": "Invitation sent successfully"
}POST /api/docs/spaces/invitations/accept
Content-Type: application/json请求体:
{
"invite_token": "abc123-def456-ghi789"
}响应示例:
{
"success": true,
"data": {
"id": "member:new123",
"space_id": "space:456",
"user_id": "user:current",
"role": "editor",
"permissions": ["docs.read", "docs.write"],
"status": "accepted",
"invited_at": "2024-01-15T10:30:00Z",
"accepted_at": "2024-01-15T11:00:00Z",
"created_at": "2024-01-15T11:00:00Z",
"updated_at": "2024-01-15T11:00:00Z"
},
"message": "Invitation accepted successfully"
}PUT /api/docs/spaces/{space_slug}/members/{user_id}
Content-Type: application/json权限要求: 需要 members.manage 权限
请求体:
{
"role": "admin",
"permissions": ["docs.read", "docs.write", "docs.admin", "members.invite"]
}响应示例:
{
"success": true,
"data": {
"id": "member:123",
"space_id": "space:456",
"user_id": "user:789",
"role": "admin",
"permissions": ["docs.read", "docs.write", "docs.admin", "members.invite"],
"status": "accepted",
"updated_at": "2024-01-15T12:00:00Z"
},
"message": "Member updated successfully"
}DELETE /api/docs/spaces/{space_slug}/members/{user_id}权限要求: 需要 members.remove 权限
响应示例:
{
"success": true,
"data": null,
"message": "Member removed successfully"
}注意事项:
- 空间所有者不能被移除
- 用户不能移除自己
- 只有拥有
members.remove权限的用户可以移除其他成员
| 角色 | 权限 | 说明 |
|---|---|---|
| Owner | 所有权限 | 空间创建者,拥有所有操作权限 |
| Admin | docs.*, members.* |
可管理文档和成员 |
| Editor | docs.read, docs.write |
可读写文档 |
| Member | docs.read, docs.write |
可读写文档(与Editor相同) |
| Viewer | docs.read |
只读权限 |
| 权限代码 | 说明 |
|---|---|
docs.read |
读取文档 |
docs.write |
创建和编辑文档 |
docs.delete |
删除文档 |
docs.admin |
文档管理权限 |
space.admin |
空间管理权限 |
space.delete |
删除空间权限 |
members.invite |
邀请成员 |
members.manage |
管理成员权限 |
members.remove |
移除成员 |
- 空间权限: 用户在空间中的权限决定了对该空间内所有文档的访问权限
- 公开空间: 任何人都可以读取公开空间的文档(如果文档也是公开的)
- 私有空间: 只有空间成员可以访问私有空间的文档
- 所有者权限: 空间所有者自动拥有该空间的所有权限
GET /api/docs查询参数:
space_id(可选): 空间IDpage(可选): 页码,默认为1per_page(可选): 每页数量,默认为20parent_id(可选): 父文档ID
POST /api/docs
Content-Type: application/json请求体:
{
"space_id": "space:123",
"title": "新文档标题",
"slug": "new-document",
"content": "# 文档内容\n\n这是文档内容...",
"description": "文档描述",
"parent_id": "doc:parent",
"is_public": true
}GET /api/docs/{document_id}PUT /api/docs/{document_id}
Content-Type: application/json请求体:
{
"title": "更新的标题",
"content": "更新的内容",
"description": "更新的描述",
"is_public": false
}DELETE /api/docs/{document_id}PUT /api/docs/{document_id}/move
Content-Type: application/json请求体:
{
"new_parent_id": "doc:new_parent",
"new_order_index": 5
}POST /api/docs/{document_id}/duplicate
Content-Type: application/json请求体:
{
"title": "复制的文档标题",
"slug": "duplicated-document"
}GET /api/docs/{document_id}/breadcrumbsGET /api/docs/{document_id}/childrenGET /api/versions/{document_id}/versions查询参数:
page(可选): 页码,默认为1per_page(可选): 每页数量,默认为20author_id(可选): 按作者筛选
POST /api/versions/{document_id}/versions
Content-Type: application/json请求体:
{
"title": "文档标题",
"content": "文档内容",
"summary": "本次更改的描述",
"change_type": "Updated"
}change_type 可选值: Created, Updated, Restored, Merged
GET /api/versions/{document_id}/versions/currentGET /api/versions/{document_id}/versions/{version_id}POST /api/versions/{document_id}/versions/{version_id}/restore
Content-Type: application/json请求体:
{
"summary": "恢复到版本 3"
}GET /api/versions/{document_id}/versions/compare?from_version={version_id_1}&to_version={version_id_2}GET /api/versions/{document_id}/versions/summaryDELETE /api/versions/{document_id}/versions/{version_id}GET /api/search查询参数:
q: 搜索关键词 (必需)space_id(可选): 限制在特定空间内搜索tags(可选): 按标签筛选,逗号分隔author_id(可选): 按作者筛选page(可选): 页码,默认为1per_page(可选): 每页数量,默认为20sort(可选): 排序方式 (relevance,created_at,updated_at,title)
响应示例:
{
"results": [
{
"document_id": "doc:123",
"space_id": "space:456",
"title": "API文档",
"excerpt": "...包含搜索关键词的摘要...",
"tags": ["api", "documentation"],
"author_id": "user123",
"last_updated": "2024-01-15T10:30:00Z",
"score": 95.5,
"highlights": [
{
"field": "title",
"text": "API文档",
"start": 0,
"end": 5
}
]
}
],
"total_count": 42,
"page": 1,
"per_page": 20,
"total_pages": 3,
"query": "API",
"took": 15
}GET /api/search/suggest?q={prefix}&limit=10POST /api/search/reindexGET /api/search/spaces/{space_id}?q={query}GET /api/search/tags?tags={tag1,tag2}GET /api/tags查询参数:
space_id(可选): 空间ID,为空则获取全局标签page(可选): 页码,默认为1per_page(可选): 每页数量,默认为20search(可选): 搜索关键词
响应示例:
{
"tags": [
{
"id": "tag:123",
"name": "API",
"slug": "api",
"description": "API相关文档",
"color": "#10b981",
"space_id": "space:456",
"usage_count": 15,
"created_by": "user123",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"total_count": 25,
"page": 1,
"per_page": 20,
"total_pages": 2
}POST /api/tags
Content-Type: application/json请求体:
{
"name": "新标签",
"description": "标签描述",
"color": "#3b82f6",
"space_id": "space:123"
}GET /api/tags/{tag_id}PUT /api/tags/{tag_id}
Content-Type: application/json请求体:
{
"name": "更新的标签名",
"description": "更新的描述",
"color": "#ef4444"
}DELETE /api/tags/{tag_id}GET /api/tags/popular?space_id={space_id}&limit=10GET /api/tags/suggest?search={query}&space_id={space_id}GET /api/tags/statistics?space_id={space_id}响应示例:
{
"total_tags": 45,
"used_tags": 32,
"unused_tags": 13,
"most_used_tags": [
{
"id": "tag:123",
"name": "API",
"usage_count": 25
}
]
}POST /api/tags/documents/tag
Content-Type: application/json请求体:
{
"document_id": "doc:123",
"tag_ids": ["tag:456", "tag:789"]
}GET /api/tags/documents/{document_id}响应示例:
{
"document_id": "doc:123",
"tags": [
{
"id": "tag:456",
"name": "Tutorial",
"color": "#3b82f6"
}
]
}DELETE /api/tags/documents/{document_id}/tags/{tag_id}GET /api/tags/{tag_id}/documents?page=1&per_page=20响应示例:
{
"tag_id": "tag:123",
"document_ids": ["doc:456", "doc:789"],
"total_count": 15,
"page": 1,
"per_page": 20
}POST /api/files
Content-Type: multipart/form-data表单数据:
file(必需): 要上传的文件space_id(可选): 关联的空间IDdocument_id(可选): 关联的文档IDdescription(可选): 文件描述
支持的文件类型:
- 图片: JPEG, PNG, GIF, WebP, SVG
- 文档: PDF, Word, Excel, PowerPoint
- 文本: TXT, Markdown, CSV
- 代码: JSON, XML, HTML, CSS, JavaScript
- 压缩包: ZIP, TAR, GZIP
响应示例:
{
"id": "file_upload:123",
"filename": "uuid-filename.jpg",
"original_name": "my-image.jpg",
"file_size": 1048576,
"file_type": "image",
"mime_type": "image/jpeg",
"url": "/api/files/file_upload:123/download",
"thumbnail_url": "/api/files/file_upload:123/thumbnail",
"space_id": "space:456",
"document_id": null,
"uploaded_by": "user123",
"created_at": "2024-01-15T10:30:00Z"
}GET /api/files查询参数:
space_id(可选): 空间ID筛选document_id(可选): 文档ID筛选file_type(可选): 文件类型筛选 (image,document,text,archive, 等)page(可选): 页码,默认为1per_page(可选): 每页数量,默认为20,最大100
响应示例:
{
"files": [
{
"id": "file_upload:123",
"filename": "uuid-filename.jpg",
"original_name": "my-image.jpg",
"file_size": 1048576,
"file_type": "image",
"mime_type": "image/jpeg",
"url": "/api/files/file_upload:123/download",
"thumbnail_url": "/api/files/file_upload:123/thumbnail",
"space_id": "space:456",
"document_id": null,
"uploaded_by": "user123",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total_count": 25,
"page": 1,
"per_page": 20,
"total_pages": 2
}GET /api/files/{file_id}GET /api/files/{file_id}/download响应:
- 返回文件的二进制内容
- 设置正确的
Content-Type和Content-Disposition头
GET /api/files/{file_id}/thumbnail响应:
- 仅适用于图片文件
- 返回 300x300 像素的 JPEG 缩略图
- 设置缓存头
Cache-Control: public, max-age=86400
DELETE /api/files/{file_id}响应示例:
{
"message": "File deleted successfully"
}注意事项:
- 文件删除采用软删除机制,不会立即删除物理文件
- 只有文件上传者或具有相应权限的用户可以删除文件
- 删除后文件仍保留在数据库中,但标记为已删除状态
GET /api/comments/document/{document_id}查询参数:
page(可选): 页码,默认为1per_page(可选): 每页数量,默认为20sort(可选): 排序方式
POST /api/comments/document/{document_id}
Content-Type: application/json请求体:
{
"content": "这是一条评论",
"parent_id": "comment:parent"
}GET /api/comments/{comment_id}PUT /api/comments/{comment_id}
Content-Type: application/json请求体:
{
"content": "更新的评论内容"
}DELETE /api/comments/{comment_id}GET /api/comments/{comment_id}/repliesPOST /api/comments/{comment_id}/likeGET /api/docs/notifications查询参数:
page(可选): 页码,默认为1limit(可选): 每页数量,默认为20unread_only(可选): 是否只显示未读通知,默认为false
响应示例:
{
"success": true,
"data": {
"notifications": [
{
"id": "notification:123",
"user_id": "user:456",
"type": "space_invitation",
"title": "张三 邀请您加入 项目文档 空间",
"content": "张三 邀请您以 编辑者 的身份加入 项目文档 空间。",
"data": {
"space_name": "项目文档",
"invite_token": "abc123-def456",
"role": "editor",
"inviter_name": "张三"
},
"is_read": false,
"read_at": null,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"total": 5
},
"message": "Notifications retrieved successfully"
}GET /api/docs/notifications/unread-count响应示例:
{
"success": true,
"data": {
"count": 3
},
"message": "Unread count retrieved successfully"
}PUT /api/docs/notifications/{notification_id}响应示例:
{
"success": true,
"data": {
"id": "notification:123",
"is_read": true,
"read_at": "2024-01-15T11:00:00Z"
},
"message": "Notification marked as read"
}POST /api/docs/notifications/mark-all-read响应示例:
{
"success": true,
"data": {
"updated_count": 5
},
"message": "All notifications marked as read"
}DELETE /api/docs/notifications/{notification_id}响应示例:
{
"success": true,
"data": null,
"message": "Notification deleted successfully"
}| 通知类型 | 说明 | 数据字段 |
|---|---|---|
space_invitation |
空间邀请通知 | space_name, invite_token, role, inviter_name |
document_shared |
文档分享通知 | document_id, document_title, sharer_name |
comment_mention |
评论提及通知 | comment_id, document_id, commenter_name |
document_update |
文档更新通知 | document_id, document_title, updater_name |
system |
系统通知 | 自定义数据 |
GET /api/stats/search响应示例:
{
"total_documents": 156,
"total_searches_today": 42,
"most_searched_terms": [
{
"term": "API documentation",
"count": 15
}
],
"recent_searches": [
{
"query": "user management",
"results_count": 7,
"timestamp": "2024-01-15T10:30:00Z"
}
]
}GET /api/stats/documents响应示例:
{
"total_documents": 156,
"total_spaces": 12,
"total_comments": 89,
"documents_created_today": 3,
"most_active_spaces": [
{
"space_id": "space_1",
"space_name": "API Documentation",
"document_count": 45,
"recent_activity": 12
}
]
}API使用标准HTTP状态码,错误响应格式:
{
"error": "错误类型",
"message": "详细错误信息",
"details": "额外的错误详情"
}常见状态码:
200- 成功201- 创建成功204- 删除成功400- 请求参数错误401- 未认证403- 权限不足404- 资源不存在409- 资源冲突500- 服务器内部错误
系统使用 SurrealDB 作为数据库,提供完整的关系型数据库功能和灵活的架构设计。
id- 空间唯一标识name- 空间名称slug- URL友好的标识符description- 空间描述is_public- 是否公开owner_id- 所有者用户IDmember_count- 成员数量document_count- 文档数量settings- 空间配置theme_config- 主题配置
id- 成员关系唯一标识space_id- 所属空间user_id- 成员用户IDrole- 成员角色(owner/admin/editor/member/viewer)permissions- 权限列表invited_by- 邀请者用户IDinvited_at- 邀请时间accepted_at- 接受时间status- 状态(pending/accepted/rejected/removed)expires_at- 邀请过期时间
id- 邀请唯一标识space_id- 目标空间email- 被邀请人邮箱user_id- 被邀请人用户ID(如果已注册)invite_token- 唯一邀请令牌role- 预设角色permissions- 预设权限列表invited_by- 邀请者message- 邀请消息max_uses- 最大使用次数used_count- 已使用次数expires_at- 邀请过期时间
id- 文档唯一标识space_id- 所属空间title- 文档标题slug- URL友好标识符content- Markdown内容excerpt- 文档摘要parent_id- 父文档ID(支持层级结构)order_index- 排序索引status- 文档状态(draft/published/archived)word_count- 字数统计reading_time- 预计阅读时间view_count- 访问次数
id- 版本唯一标识document_id- 关联文档version_number- 版本号title- 版本标题content- 版本内容summary- 变更摘要change_type- 变更类型is_current- 是否当前版本author_id- 作者ID
id- 标签唯一标识name- 标签名称slug- URL友好标识符description- 标签描述color- 标签颜色(十六进制)space_id- 所属空间(NULL为全局标签)usage_count- 使用次数created_by- 创建者
id- 关联唯一标识document_id- 文档IDtag_id- 标签IDtagged_by- 标记者tagged_at- 标记时间
id- 评论唯一标识document_id- 关联文档parent_id- 父评论ID(支持嵌套回复)author_id- 评论作者content- 评论内容like_count- 点赞数liked_by- 点赞用户列表is_resolved- 是否已解决
id- 权限唯一标识resource_type- 资源类型resource_id- 资源IDuser_id- 用户IDrole_id- 角色IDpermissions- 权限列表expires_at- 过期时间
id- 索引唯一标识document_id- 文档IDspace_id- 空间IDtitle- 标题content- 纯文本内容tags- 标签列表is_public- 是否公开
id- 收藏唯一标识user_id- 用户IDresource_type- 资源类型resource_id- 资源ID
id- 记录唯一标识document_id- 文档IDuser_id- 用户IDduration- 阅读时长ip_address- IP地址
id- 日志唯一标识user_id- 用户IDaction- 操作类型resource_type- 资源类型resource_id- 资源IDdetails- 操作详情
id- 文件唯一标识filename- 系统生成的文件名(UUID)original_name- 用户原始文件名file_path- 文件存储路径file_size- 文件大小(字节)file_type- 文件类型分类(image/document/text等)mime_type- MIME类型uploaded_by- 上传者用户IDspace_id- 关联空间(可选)document_id- 关联文档(可选)is_deleted- 是否已删除deleted_at- 删除时间deleted_by- 删除者
id- 通知唯一标识user_id- 接收者用户IDtype- 通知类型(space_invitation/document_shared/comment_mention/document_update/system)title- 通知标题content- 通知内容data- 额外数据(JSON格式,如邀请令牌、空间名称等)is_read- 是否已读read_at- 阅读时间created_at- 创建时间updated_at- 更新时间
系统为所有表创建了适当的索引以提升查询性能:
- 主键索引
- 外键关联索引
- 搜索字段索引
- 状态字段索引
- 时间字段索引
系统会自动创建以下默认标签:
- API(绿色)- API相关文档
- Tutorial(蓝色)- 教程文档
- Guide(紫色)- 指南文档
- Reference(橙色)- 参考文档
- FAQ(红色)- 常见问题
src/
├── main.rs # 应用入口
├── config.rs # 配置管理
├── error.rs # 错误处理
├── models/ # 数据模型
│ ├── space.rs # 空间模型
│ ├── space_member.rs # 空间成员模型
│ ├── document.rs # 文档模型
│ ├── version.rs # 版本模型
│ ├── comment.rs # 评论模型
│ ├── permission.rs # 权限模型
│ ├── tag.rs # 标签模型
│ ├── file.rs # 文件模型
│ └── search.rs # 搜索模型
├── routes/ # 路由处理
│ ├── spaces.rs # 空间路由
│ ├── space_members.rs # 空间成员管理路由
│ ├── documents.rs # 文档路由
│ ├── versions.rs # 版本路由
│ ├── comments.rs # 评论路由
│ ├── search.rs # 搜索路由
│ ├── tags.rs # 标签路由
│ ├── files.rs # 文件路由
│ └── stats.rs # 统计路由
├── services/ # 业务逻辑
│ ├── auth.rs # 认证服务
│ ├── spaces.rs # 空间服务
│ ├── space_member.rs # 空间成员服务
│ ├── documents.rs # 文档服务
│ ├── versions.rs # 版本服务
│ ├── comments.rs # 评论服务
│ ├── search.rs # 搜索服务
│ ├── tags.rs # 标签服务
│ └── file_upload.rs # 文件上传服务
└── utils/ # 工具函数
└── markdown.rs # Markdown处理
- 在
models/中定义数据模型 - 在
services/中实现业务逻辑 - 在
routes/中添加 API 端点 - 更新数据库 schema
# 构建镜像
docker build -t soulbook .
# 运行容器
docker run -d \
--name soulbook \
-p 3000:3000 \
-e DATABASE_URL=http://surrealdb:8000 \
-e JWT_SECRET=your-secret \
soulbook- 使用强随机 JWT 密钥
- 配置 HTTPS
- 设置适当的数据库权限
- 配置日志收集
- 设置健康检查
- Fork 项目
- 创建功能分支
- 提交更改
- 推送到分支
- 创建 Pull Request
MIT License
如有问题或建议,请创建 Issue 或联系开发团队。