videcoding
2026年6月12日

beaver个人知识管理系统

融合memo笔记,大纲笔记,无限画布,待办,习惯等为一体的个人知识管理系统

beaver个人知识管理系统

Beaver (MiniFlowy) 🦫

轻量个人知识库 — 一个自托管的、支持多端 PWA 的个人知识管理系统,集大纲笔记、普通笔记、日记、随想、待办、思维导图、画布于一体。

Beaver Logo


目录


功能特性

📝 笔记系统

功能说明
大纲笔记无限层级嵌套,支持折叠/展开、拖拽排序、缩进/取消缩进
普通笔记 (Markdown)支持 GFM 语法、代码高亮、实时预览、HTML 粘贴自动转 Markdown
画布笔记 (Excalidraw)矢量绘图、流程图、思维导图式绘图(桌面端),多窗口版本冲突检测,图片二进制独立存储
思维导图基于大纲结构一键生成思维导图,支持层级折叠
富文本格式加粗、斜体、标题级别、颜色、高亮、待办复选框
@提及@ 链接其他文档,可点击跳转
#标签自动识别标签,支持标签搜索和筛选
图片/附件支持拖拽上传、粘贴上传、URL 自动导入,自动生成缩略图
目录 (TOC)长文档自动生成目录导航
面包屑导航文件夹层级导航
版本冲突检测乐观并发控制,冲突时弹出解决对话框
撤销/重做命令模式实现,支持 Ctrl+Z / Ctrl+Shift+Z

📅 日记

  • 按月组织,日历视图
  • 每天独立节点,支持任务和标签
  • 月度摘要(任务统计、标签汇总)

💭 随想笔记 (Memos)

  • 快速记录想法,支持 Markdown
  • 置顶、归档、公开/私密
  • 颜色标记(8 种颜色)
  • 标签系统(#标签 自动识别)
  • 热力图日历(GitHub 风格)
  • 媒体画廊(图片/视频/附件汇总)
  • 随机漫步(随机浏览历史笔记)
  • 转换为正式文档
  • 网页图文粘贴自动转 Markdown + 图片自动上传

✅ 待办

  • 快速创建待办事项
  • 完成状态追踪
  • 截止日期解析(!12.25 格式)
  • 排序功能

🔍 搜索

  • 全局统一搜索(文档、日记、随想、标题)
  • 实时搜索结果

📤 分享

  • 生成公开分享链接(只读)
  • 无需登录即可查看
  • 公开随想笔记

🌐 链接预览

  • 自动提取 URL 的 Open Graph 元数据
  • 显示标题、描述、图片、网站图标
  • SSRF 防护,1 小时缓存

📱 多端适配

  • 响应式设计:桌面端侧边栏布局,移动端底部 Tab 布局
  • PWA 支持:iOS / Android / HarmonyOS / 鸿蒙
  • 中国浏览器兼容:QQ 浏览器、UC 浏览器、360 浏览器
  • 离线支持:Service Worker 缓存 + 离线操作队列 + 恢复连接自动同步

🔒 安全

  • JWT 认证 + bcrypt 密码加密
  • API 速率限制(登录 20次/分钟)
  • 用户数据缓存(5 分钟 TTL)
  • CORS 保护
  • 文件大小限制(50MB)

🎨 个性化

  • 亮色/暗色主题(跟随系统或手动切换)
  • 可配置字体(字体族、字号)
  • 笔记卡片颜色标记

技术栈

后端

技术版本用途
Python3.11运行时
FastAPI0.111.0Web 框架
Uvicorn0.29.0ASGI 服务器
SQLAlchemy2.0.30ORM
SQLite-数据库
Pydantic2.7.1数据验证
python-jose3.3.0JWT 签发/验证
passlib + bcrypt1.7.4 / 4.0.1密码哈希
Pillow10.4.0图片处理(压缩/缩略图)
httpx0.27.0+异步 HTTP 客户端(链接预览、图片下载)
slowapi0.1.9API 速率限制
python-multipart0.0.9文件上传

前端

技术版本用途
React19.2.7UI 框架
TypeScript~5.9.3类型安全
Vite7.3.1构建工具
Tailwind CSS4.2.1样式框架
React Router7.13.1路由
Axios1.13.6HTTP 客户端
react-markdown10.1.0Markdown 渲染
react-syntax-highlighter16.1.1代码高亮
simple-mind-map0.14.0思维导图
@excalidraw/excalidraw0.18.1画布绘图
turndown7.2.4HTML → Markdown 转换
jspdf + html2canvas4.2.1 / 1.4.1PDF 导出
lucide-react0.577.0图标库
vite-plugin-pwa1.2.0PWA 支持
workbox-window7.4.0Service Worker

基础设施

技术用途
Docker + Docker Compose容器化部署
Nginx (Alpine)反向代理 + 静态资源服务
Node 20 (Alpine)前端构建环境

项目结构

miniflowy/
├── README.md                           # 本文档
├── docker-compose.yml                  # 开发环境 Docker Compose
├── .dockerignore
│
├── backend/                            # 后端服务
│   ├── Dockerfile
│   ├── requirements.txt
│   ├── start.sh                        # 启动脚本(数据库迁移 + 启动 uvicorn)
│   ├── migrate_from_old.sh             # 旧版数据库迁移脚本
│   └── app/
│       ├── main.py                     # FastAPI 应用入口
│       ├── database.py                 # 数据库连接配置(SQLite + WAL 模式)
│       ├── models.py                   # SQLAlchemy ORM 模型(9 张表)
│       ├── schemas.py                  # Pydantic 请求/响应模型
│       ├── crud.py                     # CRUD 操作(~38KB)
│       ├── auth.py                     # JWT 认证(bcrypt + python-jose)
│       ├── dependencies.py             # FastAPI 依赖注入(带缓存的用户查询)
│       ├── excalidraw_storage.py       # 画布文件存储层(原子写入、版本控制、图片二进制存储)
│       ├── limiter.py                  # 速率限制配置
│       └── routers/                    # API 路由
│           ├── auth.py                 # 登录 / 注册 / 初始化
│           ├── users.py                # 用户设置
│           ├── documents.py            # 文档 CRUD + 复制
│           ├── nodes.py                # 节点 CRUD + 批量操作
│           ├── attachments.py          # 文件上传 / 下载 / URL 导入
│           ├── shares.py               # 分享链接管理
│           ├── diary.py                # 日记系统
│           ├── memos.py                # 随想笔记
│           ├── search.py               # 全局搜索
│           ├── public_memos.py         # 公开随想(无需认证)
│           ├── link_preview.py         # 链接预览(OG 元数据)
│           ├── excalidraw.py           # 画布数据
│           ├── todos.py                # 待办事项
│           └── api_tokens.py           # API Token 管理
│
├── frontend/                           # 前端应用
│   ├── Dockerfile                      # 两阶段构建(Node 构建 + Nginx 服务)
│   ├── nginx.conf                      # 前端 Nginx 配置(SPA 路由、缓存策略)
│   ├── package.json
│   ├── vite.config.ts                  # Vite 配置(PWA、代码分割、代理)
│   ├── index.html                      # 入口 HTML(PWA meta 标签)
│   ├── public/
│   │   ├── beaver.svg                  # SVG Favicon
│   │   ├── beaver.png                  # PNG Logo
│   │   ├── favicon.ico                 # ICO Favicon
│   │   ├── apple-touch-icon.png        # iOS 桌面图标
│   │   ├── maskable-icon.png           # Android 自适应图标
│   │   ├── shortcut.html               # iOS 捷径下载页
│   │   ├── Beaver.shortcut             # iOS 捷径文件
│   │   └── icons/                      # PWA 多尺寸图标(16x16 ~ 512x512)
│   └── src/
│       ├── main.tsx                    # 应用入口(暗色模式检测)
│       ├── App.tsx                     # 路由定义 + Provider 组合
│       ├── api/                        # API 层
│       │   ├── client.ts               # Axios 实例(重试、认证拦截器)
│       │   ├── auth.ts                 # 认证 API
│       │   ├── data.ts                 # 数据 API(~680 行)
│       │   ├── cache.ts                # 数据缓存层
│       │   └── excalidraw.ts           # 画布 API
│       ├── components/                 # 组件
│       │   ├── MainArea.tsx            # 核心编辑器(~122KB,最大的文件)
│       │   ├── Sidebar.tsx             # 桌面端侧边栏(~71KB)
│       │   ├── NodeItem.tsx            # 节点渲染(~46KB)
│       │   ├── MemoCard.tsx            # 随想卡片(~58KB)
│       │   ├── MemoHome.tsx            # 随想首页
│       │   ├── MemoInput.tsx           # 随想输入框
│       │   ├── MarkdownNoteEditor.tsx  # Markdown 笔记编辑器
│       │   ├── MindMapView.tsx         # 思维导图视图
│       │   ├── MindMapModal.tsx        # 思维导图弹窗
│       │   ├── DiaryCalendar.tsx       # 日记日历
│       │   ├── ExcalidrawEditor.tsx    # 画布编辑器
│       │   ├── FontSettings.tsx        # 字体设置
│       │   ├── Breadcrumbs.tsx         # 面包屑导航
│       │   ├── ConflictResolver.tsx    # 版本冲突解决
│       │   ├── SaveStatusIndicator.tsx # 保存状态指示器
│       │   ├── RecoveryDialog.tsx      # 数据恢复对话框
│       │   ├── ShareDialog.tsx         # 分享对话框
│       │   ├── TableOfContents.tsx     # 文档目录
│       │   ├── ImageViewer.tsx         # 图片查看器
│       │   ├── LinkPreviewCard.tsx     # 链接预览卡片
│       │   ├── TokenDialog.tsx         # API Token 管理
│       │   ├── ReloadPrompt.tsx        # PWA 更新提示
│       │   ├── MemoWanderer.tsx        # 随机漫步
│       │   ├── MemoMediaGallery.tsx    # 媒体画廊
│       │   ├── MemoHeatmapCalendar.tsx # 热力图日历
│       │   └── mobile/                 # 移动端专属组件
│       │       ├── MobileLayout.tsx     # 移动端布局(底部 Tab)
│       │       ├── MobileTopBar.tsx     # 顶部导航栏
│       │       ├── MobileBottomTabBar.tsx # 底部 Tab 栏
│       │       ├── MobileDiaryView.tsx  # 移动端日记
│       │       ├── MobileTodos.tsx      # 移动端待办
│       │       ├── FileTreeView.tsx     # 移动端文件树
│       │       ├── StarredView.tsx      # 收藏视图
│       │       └── NewMenuPopup.tsx     # 新建菜单
│       ├── pages/
│       │   ├── LoginPage.tsx           # 登录页
│       │   ├── SetupPage.tsx           # 首次初始化页
│       │   ├── SearchResultsPage.tsx   # 搜索结果页
│       │   └── SharePage.tsx           # 公开分享页
│       ├── hooks/
│       │   ├── useHistory.ts           # 撤销/重做
│       │   ├── useKeyboardScroll.ts    # 键盘滚动
│       │   ├── useRetryFailedPreviews.ts # 链接预览重试
│       │   ├── useSaveManager.ts       # 保存管理
│       │   └── useResizableTextarea.ts # textarea 拖拽调整高度
│       ├── context/
│       │   ├── AuthContext.tsx          # 认证上下文
│       │   ├── DocumentContext.tsx      # 文档列表上下文
│       │   ├── DiaryContext.tsx         # 日记上下文
│       │   ├── SearchContext.tsx        # 搜索上下文
│       │   └── MobileToolbarContext.tsx # 移动端工具栏上下文
│       ├── commands/
│       │   ├── types.ts                # 命令模式类型定义
│       │   └── implementations.ts      # 命令实现(撤销/重做)
│       └── utils/
│           ├── saveStateManager.ts     # 离线队列 + 保存状态机
│           ├── offlineQueue.ts         # 离线操作包装器
│           ├── pwaState.ts             # PWA 状态持久化(localStorage + IndexedDB)
│           ├── conflictResolver.ts     # 版本冲突解析
│           ├── markdown.ts             # Markdown 解析(大纲 → 树)
│           ├── markdownPreprocess.ts   # Markdown 预处理
│           ├── htmlToMarkdown.ts       # HTML → Markdown(Turndown)
│           ├── listContinuation.ts     # 列表自动续行
│           ├── convertMemo.ts          # 随想 → 文档转换
│           ├── convertNode.ts          # 节点 → Markdown 转换
│           ├── todoDueDate.ts          # 截止日期解析
│           └── toast.ts                # Toast 提示
│
├── nginx/
│   ├── nginx.conf                      # 生产环境 Nginx 配置
│   └── ssl/                            # SSL 证书目录
│
├── deploy/                             # 预打包部署包
│   ├── docker-compose.yml              # 部署用 Docker Compose(端口 8080)
│   ├── package.sh                      # 打包脚本
│   ├── backend/                        # 打包后的后端
│   ├── frontend/                       # 打包后的前端
│   ├── data/                           # 数据目录(数据库 + 上传文件)
│   └── nginx/
│       └── nginx.conf
│
├── chrome-extension/                   # Chrome 浏览器插件
│   ├── manifest.json                   # Manifest V3
│   ├── background.js                   # 后台脚本(右键菜单 + API 调用)
│   ├── popup.html / popup.js / popup.css
│   └── icons/                          # 插件图标
│
└── docs/                               # 文档
    ├── PRD_文件夹功能.md
    └── 技术架构_文件夹功能.md

快速开始

Docker 部署(推荐)

1. 克隆项目

git clone <repository-url> miniflowy
cd miniflowy

2. 启动服务

docker compose up -d --build

首次构建需要几分钟下载镜像和安装依赖。

3. 访问应用

打开浏览器访问 http://your-server-ip:5173

首次访问会跳转到初始化页面,创建管理员账号。

4. 验证服务状态

# 检查容器状态
docker ps

# 检查后端健康状态
curl http://localhost:5173/api/health

开发环境

后端

cd backend

# 创建虚拟环境
python3 -m venv venv
source venv/bin/activate  # Linux/macOS
# venv\Scripts\activate   # Windows

# 安装依赖
pip install -r requirements.txt

# 启动开发服务器
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

后端 API 文档:http://localhost:8000/docs(Swagger UI)

前端

cd frontend

# 安装依赖
npm install

# 启动开发服务器(自动代理 /api 到后端)
npm run dev

前端开发服务器:http://localhost:5173

开发环境 Docker Compose

根目录的 docker-compose.yml 映射端口 5173:80,适合本地开发:

docker compose up -d --build

详细部署指南

服务器要求

项目最低配置推荐配置
CPU1 核2 核
内存1 GB2 GB+
磁盘10 GB20 GB+
操作系统Ubuntu 20.04 / CentOS 8 / Debian 11Ubuntu 22.04
Docker20.10+最新稳定版
Docker Compose2.0+最新稳定版

生产环境部署

方式一:使用 deploy 目录(推荐)

# 1. 打包部署文件
cd miniflowy
bash deploy/package.sh

# 2. 上传 deploy.tar.gz 到服务器
scp deploy.tar.gz user@server:/opt/

# 3. 在服务器上解压并启动
ssh user@server
cd /opt
tar xzf deploy.tar.gz
cd deploy
docker compose up -d --build

默认端口 8080,通过服务器 Nginx 反向代理到 80/443。

方式二:直接部署

# 1. 上传整个项目到服务器
rsync -avz ./miniflowy/ user@server:/opt/miniflowy/

# 2. 在服务器上构建并启动
ssh user@server
cd /opt/miniflowy
docker compose build --no-cache
docker compose up -d

默认端口 5173

HTTPS 配置

编辑 nginx/nginx.conf,取消注释 HTTPS 配置段:

server {
    listen 443 ssl;
    server_name your-domain.com;

    ssl_certificate     /etc/nginx/ssl/your-cert.pem;
    ssl_certificate_key /etc/nginx/ssl/your-key.pem;

    # ... 其余配置与 HTTP 相同
}

server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$host$request_uri;
}

将 SSL 证书放入 nginx/ssl/ 目录,然后重启 Nginx:

docker compose restart nginx

数据备份

手动备份

# 备份数据库和上传文件
tar czf backup-$(date +%Y%m%d).tar.gz backend/data/

自动备份(Cron)

# 添加定时任务(每天凌晨 3 点备份,保留 7 天)
crontab -e
0 3 * * * cd /opt/miniflowy && tar czf /backups/miniflowy-$(date +\%Y\%m\%d).tar.gz backend/data/ && find /backups -name "miniflowy-*.tar.gz" -mtime +7 -delete

更新升级

# 1. 备份数据
tar czf backup-$(date +%Y%m%d).tar.gz backend/data/

# 2. 拉取最新代码
git pull origin main

# 3. 重新构建并重启
docker compose build --no-cache
docker compose up -d

回滚

# 1. 停止服务
docker compose down

# 2. 恢复数据库备份
tar xzf backup-YYYYMMDD.tar.gz -C ./

# 3. 切换到旧版本代码
git checkout <previous-commit>

# 4. 重新构建并启动
docker compose build --no-cache
docker compose up -d

API 文档

所有 API 以 /api 为前缀。认证接口需要在请求头中携带 JWT Token:

Authorization: Bearer <token>

认证

方法路径说明认证
POST/api/auth/token登录(获取 JWT)
POST/api/auth/setup首次初始化(创建管理员)
GET/api/auth/setup/status检查是否需要初始化

登录请求体:

{
  "username": "admin",
  "password": "your-password"
}

登录响应:

{
  "access_token": "eyJ...",
  "token_type": "bearer"
}

用户

方法路径说明
GET/api/users/me获取当前用户信息
PUT/api/users/settings更新用户设置(主题、字体、memo_columns)
PUT/api/users/password修改密码

文档管理

方法路径说明
GET/api/documents/获取所有文档(支持 ?search= 搜索)
GET/api/documents/{id}获取单个文档
POST/api/documents/创建文档
POST/api/documents/{id}/copy复制文档
GET/api/documents/{id}/nodes获取文档的所有节点
PUT/api/documents/{id}更新文档(支持版本冲突检测)
DELETE/api/documents/{id}删除文档

创建文档请求体:

{
  "title": "新文章",
  "type": "document",       // document | folder | excalidraw
  "parent_id": null,        // 父文件夹 ID,null 为根目录
  "sort_order": 1699000000  // 排序值
}

节点管理

方法路径说明
POST/api/nodes/创建节点
PUT/api/nodes/{id}更新节点
PUT/api/nodes/{id}/move移动节点(重新父级 + 排序)
DELETE/api/nodes/{id}删除节点
PUT/api/nodes/batch/move批量移动
POST/api/nodes/batch/delete批量删除
POST/api/nodes/batch/create批量创建
POST/api/nodes/batch/update批量更新(结构)
POST/api/nodes/batch/properties批量更新属性
POST/api/nodes/batch/save批量保存(离线同步/Beacon)

附件管理

方法路径说明
POST/api/attachments/upload上传文件(最大 50MB,图片自动生成缩略图)
POST/api/attachments/upload-from-url从 URL 下载并上传(绕过 CORS)
GET/api/attachments/download/{filename}下载文件
DELETE/api/attachments/{id}删除附件

upload-from-url 请求体:

{
  "url": "https://example.com/image.png"
}

分享

方法路径说明
POST/api/shares/{document_id}创建分享链接
GET/api/shares/{document_id}获取文档的分享信息
DELETE/api/shares/{token}删除分享
GET/api/public/share/{token}查看分享内容(公开,无需认证)

日记

方法路径说明
GET/api/diary/months获取所有日记月份
GET/api/diary/{year}/{month}获取月度日记(文档 + 节点)
POST/api/diary/{year}/{month}/days/{day}获取或创建某天的节点
GET/api/diary/{year}/{month}/days获取有日记的日期列表
GET/api/diary/summary获取日记摘要(任务 + 标签)

随想笔记 (Memos)

方法路径说明
POST/api/memos/创建随想
GET/api/memos/列表(分页,支持 ?archived= ?public= ?tag= ?search=
GET/api/memos/heatmap/{year}/{month}热力图数据
GET/api/memos/tags所有标签
GET/api/memos/{id}获取单条
PUT/api/memos/{id}更新
DELETE/api/memos/{id}删除

待办 (Todos)

方法路径说明
POST/api/todos/创建待办
GET/api/todos/列表(?completed=false 仅未完成)
PUT/api/todos/{id}更新
DELETE/api/todos/{id}删除

搜索

方法路径说明
GET/api/search/?q=keyword全局搜索(文档、日记、随想、标题)

链接预览

方法路径说明
GET/api/link-preview/?url=https://...获取链接预览(OG 元数据,1 小时缓存)

画布 (Excalidraw)

方法路径说明
GET/api/excalidraw/{document_id}获取画布数据(含版本号)
POST/api/excalidraw/创建画布数据
PUT/api/excalidraw/{document_id}更新画布(自动保存,支持版本控制)
DELETE/api/excalidraw/{document_id}删除画布
GET/api/excalidraw/{document_id}/files获取画布图片元数据
GET/api/excalidraw/{document_id}/files/{file_id}获取单个图片文件(二进制)

版本控制:PUT 请求支持 version 参数(乐观锁),版本不匹配返回 409 Conflict。

API Token

方法路径说明
POST/api/tokens/创建 Token
GET/api/tokens/列出所有 Token
DELETE/api/tokens/{id}删除 Token

创建 Token 请求体:

{
  "name": "iOS 捷径"
}

公开接口(无需认证)

方法路径说明
GET/api/public/memos公开随想列表
GET/api/public/memos/{id}单条公开随想
GET/api/public/share/{token}分享文档内容

系统

方法路径说明
GET/api/health健康检查

数据库设计

SQLite 数据库,使用 WAL 模式优化并发性能。

表结构

users(用户)

字段类型说明
idUUID主键
usernameVARCHAR用户名(唯一)
password_hashVARCHARbcrypt 哈希密码
themeVARCHAR主题(light/dark)
font_familyVARCHAR字体族
font_sizeINTEGER字号
memo_columnsINTEGERMemo 列数

documents(文档)

字段类型说明
idUUID主键
titleVARCHAR标题
typeVARCHAR类型(document/folder/excalidraw)
parent_idUUID (FK)父文件夹(自引用)
sort_orderFLOAT排序值
is_starredBOOLEAN是否收藏
iconVARCHAR自定义图标
diary_dateDATE日记日期
versionINTEGER版本号(乐观锁)

nodes(节点)

字段类型说明
idUUID主键
document_idUUID (FK)所属文档
parent_node_idUUID (FK)父节点(自引用,大纲结构)
contentTEXT内容
noteTEXT备注
is_completedBOOLEAN是否完成
is_in_progressBOOLEAN是否进行中
is_collapsedBOOLEAN是否折叠
sort_orderFLOAT排序值
headingINTEGER标题级别(0-6)
is_boldBOOLEAN加粗
is_italicBOOLEAN斜体
colorVARCHAR颜色
highlightVARCHAR高亮颜色
is_todoBOOLEAN是否待办
content_typeVARCHAR内容类型(text/image/attachment)
file_pathVARCHAR文件路径
file_nameVARCHAR文件名
versionINTEGER版本号(乐观锁)

memos(随想笔记)

字段类型说明
idUUID主键
contentTEXTMarkdown 内容
is_pinnedBOOLEAN是否置顶
is_archivedBOOLEAN是否归档
is_publicBOOLEAN是否公开
colorVARCHAR卡片颜色
created_atDATETIME创建时间
updated_atDATETIME更新时间

todos(待办)

字段类型说明
idUUID主键
contentTEXT内容
is_completedBOOLEAN是否完成
sort_orderFLOAT排序值
created_atDATETIME创建时间
updated_atDATETIME更新时间

shares(分享)

字段类型说明
idUUID主键
document_idUUID (FK)分享的文档
tokenVARCHAR(32)分享 Token(唯一)
created_atDATETIME创建时间

attachments(附件)

字段类型说明
idUUID主键
file_pathVARCHAR存储路径
file_nameVARCHAR原始文件名
file_typeVARCHARMIME 类型
file_sizeINTEGER文件大小(字节)
created_atDATETIME创建时间

api_tokens(API Token)

字段类型说明
idUUID主键
user_idUUID (FK)所属用户
nameVARCHARToken 名称
token_hashVARCHARToken 哈希
created_atDATETIME创建时间
last_used_atDATETIME最后使用时间

excalidraw_data(画布数据)

字段类型说明
idVARCHAR主键
document_idUUID (FK, unique)关联文档
scene_dataTEXT已迁移至文件系统,此字段为 NULL
thumbnailTEXT缩略图(Base64)
created_atDATETIME创建时间
updated_atDATETIME更新时间

画布数据存储:场景数据存储在 data/excalidraw/{document_id}.json,图片存储为二进制文件在 data/excalidraw/{document_id}/ 目录。SQLite 只存元数据索引。支持乐观锁版本控制(_version 字段)。

SQLite 优化配置

PRAGMA journal_mode = WAL;       -- 写前日志模式,提升并发读写
PRAGMA cache_size = -20480;      -- 20MB 缓存
PRAGMA busy_timeout = 30000;     -- 30 秒忙等待
PRAGMA synchronous = FULL;       -- 每次 commit 等待数据写入磁盘,防止数据丢失

PWA 配置

Beaver 支持全平台 PWA 安装:

安装方式

平台安装方式
iOSSafari → 分享按钮 → 添加到主屏幕
AndroidChrome → 菜单 → 添加到主屏幕(自动弹出安装提示)
HarmonyOS浏览器 → 添加到桌面
桌面 Chrome地址栏右侧安装图标

Service Worker 缓存策略

资源类型策略缓存时间
HTMLStaleWhileRevalidate5 分钟
JS / CSSCacheFirst30 天
图片StaleWhileRevalidate1 天
API GETNetworkFirst1 天

离线支持

  • Service Worker 预缓存所有静态资源
  • 离线时操作自动入队,恢复连接后自动同步
  • PWA 状态通过 localStorage + IndexedDB 持久化
  • iOS PWA 后台终止后自动恢复视图状态

更新提示

  • 每小时检查一次更新
  • 发现新版本后显示更新提示
  • 用户关闭后 24 小时内不再重复提示

Chrome 浏览器插件

chrome-extension/ 目录包含 Manifest V3 的 Chrome 插件:

功能

  • 弹窗设置:点击插件图标打开设置弹窗,配置服务器地址和 API Token
  • 注入浮动按钮:在当前页面注入浮动操作按钮,支持保存选中文字和提取整页正文
  • 右键菜单保存:选中文字或图片 → 右键 → 保存到 Beaver
  • 一键保存网页:保存当前页面标题和 URL
  • 图片保存:右键保存图片到随想笔记

安装

  1. 打开 Chrome → chrome://extensions/
  2. 开启「开发者模式」
  3. 点击「加载已解压的扩展程序」
  4. 选择 chrome-extension/ 目录

配置

点击插件图标,在弹窗中填写:

  • 服务器地址https://your-domain.com(不要带 /api)
  • API Token:在 Beaver 设置中生成

iOS 捷径

frontend/public/Beaver.shortcut 是 iOS 快捷指令:

功能

  • 一键保存 Safari 中选中的文字
  • 保存当前页面 URL
  • 保存图片到 Beaver

安装

  1. 在 iPhone 上打开 https://your-domain.com/shortcut.html
  2. 点击「下载 iOS 捷径」
  3. 在弹出的快捷指令中点击「添加快捷指令」
  4. 在捷径设置中填入服务器地址和 API Token

前端路由

路径组件认证说明
/setupSetupPage首次初始化(创建管理员)
/loginLoginPage登录页
/s/:shareTokenSharePage公开分享页
/MainArea首页(随想笔记 / 文档编辑器)
/d/:documentIdMainArea文档编辑页
/searchSearchResultsPage搜索结果页

移动端布局

屏幕宽度 < 768px 时自动切换为移动端布局:

Tab内容
随想MemoHome(随想笔记列表)
日记DiaryCalendar(日历视图)
文件FileTreeView(文件夹/文档树)
收藏StarredView(收藏的文档)
新建 +NewMenuPopup(大纲笔记/普通笔记/待办/文件夹/API Token)

环境变量

变量默认值说明
DATABASE_URLsqlite:///./data/app.db数据库连接字符串
SECRET_KEY(硬编码,建议覆盖)JWT 签名密钥

生产环境建议覆盖 SECRET_KEY:

# docker-compose.yml
environment:
  - SECRET_KEY=your-random-secret-key-here

生成随机密钥:

python3 -c "import secrets; print(secrets.token_hex(32))"

架构设计

整体架构

┌─────────────────────────────────────────────────────┐
│                      Nginx                          │
│              (反向代理 + 静态资源)                     │
│                                                     │
│   ┌─────────────┐          ┌─────────────────┐     │
│   │   Frontend   │          │    Backend      │     │
│   │  (React SPA) │  ──API── │   (FastAPI)     │     │
│   │   Nginx:80   │          │  Uvicorn:8000   │     │
│   └─────────────┘          └────────┬────────┘     │
│                                      │              │
│                              ┌───────▼───────┐      │
│                              │    SQLite      │      │
│                              │   (WAL 模式)   │      │
│                              └───────────────┘      │
└─────────────────────────────────────────────────────┘

前端状态管理

AuthContext (认证状态)
    │
DocumentContext (文档列表)
    │
DiaryContext (日记数据)
    │
SearchContext (搜索状态)
    │
MobileToolbarContext (移动端工具栏)
    │
saveStateManager (保存状态机 + 离线队列)

保存状态机

idle → pending → saving → saved
                    ↓
                  error → retry
                    ↓
offline → queue → sync on reconnect

命令模式(撤销/重做)

Command {
  description: string
  execute: () => Promise<void>
  undo: () => Promise<void>
}

commands.createUpdateContentCommand(id, oldContent, newContent)
commands.createTogglePropertyCommand(id, property, newValue)
commands.createBatchTogglePropertyCommand(ids, property, newValue)
commands.createMoveNodeCommand(id, oldParent, newParent, oldSort, newSort)
commands.createDeleteNodeCommand(node)
commands.createInsertNodeCommand(node)

离线支持架构

用户操作 → saveStateManager.markPending()
    │
    ├── 在线 → API 调用 → markSaving → markSaved
    │
    └── 离线 → 入队 (localStorage) → 等待恢复连接
                                          │
                                   syncOfflineOperations()
                                          │
                                   逐个重放 → 成功/重试(指数退避)

License

MIT License


致谢

评论 (0)

加载中...