删除架构文档和改造计划文档,清理不再需要的文件,以简化项目结构和文档管理。

This commit is contained in:
BetterAndBetterII
2025-08-18 20:06:55 +08:00
committed by Yuzhong Zhang
parent d27df30788
commit 6fb8f69497
4 changed files with 0 additions and 648 deletions
-220
View File
@@ -1,220 +0,0 @@
---
description:
globs:
alwaysApply: true
---
# Excalidraw-Complete 架构文档
本文档旨在详细阐述 `excalidraw-complete` 项目的系统架构、技术栈、模块设计和数据流,以便于开发者理解、维护和进行二次开发。
## 1. 概述 (Overview)
`excalidraw-complete` 是一个将优秀的开源白板工具 [Excalidraw](https://github.com/excalidraw/excalidraw) 进行整合与封装的自托管解决方案。其核心目标是简化 Excalidraw 的私有化部署流程,将前端UI、后端数据存储和实时协作服务打包成一个单一的、易于部署的Go二进制文件。
**核心特性:**
- **一体化部署**:将所有服务打包成单个可执行文件,无需复杂的依赖配置。
- **可插拔存储**:通过环境变量支持多种数据持久化方案,包括内存、本地文件系统、SQLite和AWS S3。
- **实时协作**:内置基于 Socket.IO 的实时协作服务器,允许多个用户同时在同一个画板上工作。
- **Firebase 兼容层**:提供一个内存实现的 Firebase API 兼容层,以满足 Excalidraw 前端对 Firebase 的部分依赖。
---
## 2. 技术栈 (Tech Stack)
项目采用了现代化的前后端技术栈。
### 后端 (Backend)
- **语言**: [Go](https://go.dev/) (v1.21+)
- **Web框架**: [Chi (v5)](https://github.com/go-chi/chi) - 一个轻量级、高性能的 Go HTTP 路由器。
- **实时通信**: [Socket.IO for Go](https://github.com/zishang520/socket.io/v2) - 实现了 Socket.IO 协议,用于实时协作。
- **数据库驱动**:
- [go-sqlite3](https://github.com/mattn/go-sqlite3) - 用于 SQLite 存储。
- [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) - 用于与 AWS S3 交互。
- **日志**: [Logrus](https://github.com/sirupsen/logrus) - 结构化的日志记录库。
- **ID生成**: [ULID](https://github.com/oklog/ulid) - 用于生成唯一、可排序的文档ID。
### 前端 (Frontend)
- **核心**: [Excalidraw](https://github.com/excalidraw/excalidraw) (作为 Git Submodule)
- **框架**: [React](https://reactjs.org/)
- **构建工具**: [Vite](https://vitejs.dev/)
- **语言**: [TypeScript](https://www.typescriptlang.org/)
### 构建与部署 (Build & Deployment)
- **容器化**: [Docker](https://www.docker.com/) & `Dockerfile`
- **构建自动化**: Go Build Tools, npm/yarn
---
## 3. 系统架构 (System Architecture)
`excalidraw-complete` 是一个典型的**单体架构 (Monolith)**,但内部逻辑分层清晰。
```
+-------------------------------------------------------------------------+
| User |
| (Browser with Excalidraw React App) |
+-------------------------------------------------------------------------+
| ^
| HTTP/S (API Calls) | HTTP/S (HTML/JS/CSS)
| WebSocket (Collaboration) |
v |
+-------------------------------------------------------------------------+
| excalidraw-complete Go Binary |
| |
| +-------------------------+ +-----------------------------------+ |
| | HTTP Server (Chi) | | Socket.IO Server | |
| |-------------------------| |-----------------------------------| |
| | - API Routes (/api/v2) | <--> | - Connection Handling | |
| | - Firebase Routes | | - Room Management (Join/Leave) | |
| | - Static File Serving | | - Message Broadcasting | |
| +-------------------------+ +-----------------------------------+ |
| | ^ |
| | | |
| v | |
| +-------------------------------------------------------------------+ |
| | Core Logic & Modules | |
| |-------------------------------------------------------------------| |
| | | | |
| | +--------------------------+ | +-----------------------------+ | |
| | | Handlers (API Logic) | | | Embedded Frontend Assets | | |
| | +--------------------------+ | | (Patched Excalidraw UI) | | |
| | | | +-----------------------------+ | |
| | v | | |
| | +--------------------------+ | | |
| | | Storage Interface | | | |
| | | (core.DocumentStore) | | | |
| | +--------------------------+ | | |
| | | | | | | | |
| |----|------|--------|-------|--------------------------------------| |
| v v v v v |
| [S3] [SQLite] [FS] [Memory] (Storage Implementations) |
| |
+-------------------------------------------------------------------------+
```
**架构说明:**
1. **Go主程序 (`main.go`)**: 作为应用的入口,它初始化并启动所有服务。
2. **HTTP服务器**: 使用 `Chi` 路由器来处理所有HTTP请求。这包括:
- **API服务**: 提供用于创建和获取文档的 RESTful API。
- **Firebase兼容层**: 模拟 Excalidraw 前端所需的 Firebase API。
- **静态文件服务**: 将嵌入的、经过修改的 Excalidraw 前端应用(HTML, JS, CSS等)提供给浏览器。
3. **Socket.IO服务器**: 独立处理 WebSocket 连接,负责所有实时协作功能,如同步绘图数据、光标位置等。
4. **存储层 (`stores`)**: 通过一个统一的 `core.DocumentStore` 接口,将数据存储逻辑抽象出来。可以根据环境变量在启动时选择不同的实现(S3、SQLite等)。
5. **嵌入式前端**: 前端 `Excalidraw` UI 作为一个 Git 子模块被包含在内。在构建阶段,它会被编译,并通过 Go 的 `embed` 特性直接嵌入到最终的二进制文件中。
---
## 4. 模块与服务说明 (Modules & Services)
### 4.1. 后端 (Backend)
#### 主应用 (`main.go`)
- **职责**: 应用的启动器和协调器。
- **核心逻辑**:
- 解析命令行参数 (`-listen`, `-loglevel`)。
- 根据环境变量初始化存储层 (`stores.GetStore()`)。
- 设置 `Chi` 路由器 (`setupRouter`),定义所有API路由。
- 设置 `Socket.IO` 服务器 (`setupSocketIO`),定义所有协作事件。
- 将 `/socket.io/` 路径的请求代理到 Socket.IO 服务器。
- **动态前端服务 (`handleUI`)**:
- 使用 Go 的 `embed` 包将编译后的前端文件打包进二进制文件。
- 在提供前端文件时,动态替换文件内容中的URL(如将 `firestore.googleapis.com` 替换为 `localhost:3002`),以重定向API请求到自身。
- 监听系统信号以实现优雅停机 (`waitForShutdown`)。
#### 核心模块 (`core/`)
- **`core/entity.go`**: 定义了项目中最核心的数据结构和接口。
- `Document`: 代表一个画板文档。
- `DocumentStore`: 一个接口,定义了所有存储后端必须实现的两个方法:`FindID` 和 `Create`。这是实现可插拔存储的关键。
#### 存储层 (`stores/`)
- **`stores/storage.go`**: 工厂模式的实现。`GetStore()` 函数根据环境变量 `STORAGE_TYPE` 的值,创建并返回一个具体的 `DocumentStore` 接口实例。
- **存储实现**:
- `stores/memory/`: 将文档保存在内存中,服务重启后数据丢失。
- `stores/filesystem/`: 将每个文档作为单独的文件保存在本地文件系统上。
- `stores/sqlite/`: 使用 SQLite 数据库来存储文档数据。
- `stores/aws/`: 使用 AWS S3 对象存储来保存文档。
#### HTTP处理器 (`handlers/`)
- **`handlers/api/documents/`**: 实现了自定义的文档API (`/api/v2`)。
- `HandleCreate`: 处理文档的创建请求。
- `HandleGet`: 处理文档的读取请求。
- **`handlers/api/firebase/`**: 一个内存实现的 Firebase API 模拟层。它拦截了原始 Excalidraw 前端对 Firebase 的 `batchGet` 和 `commit` 请求,并在内存中进行处理,以确保前端协作功能可以正常工作,而无需真实的 Firebase 后端。
### 4.2. 前端 (Frontend)
#### Excalidraw UI (`excalidraw/` submodule)
- 项目通过 Git Submodule 引入了官方的 `excalidraw` 仓库。这使得跟踪上游更新变得容易。
#### 前端补丁 (`frontend.patch`)
- 这是一个至关重要的文件。由于我们是自托管,需要修改 Excalidraw 前端的一些硬编码配置。该补丁文件在构建时应用,主要做了以下修改:
- **重定向API端点**: 将所有对 `excalidraw.com` 官方后端的API请求(如 `VITE_APP_BACKEND_V2_GET_URL`, `VITE_APP_WS_SERVER_URL`)重定向到自托管服务的地址(如 `http://localhost:3002`)。
- **修改Firebase配置**: 清空部分 Firebase 配置,因为后端已经提供了兼容层。
- **禁用追踪**: 设置 `VITE_APP_DISABLE_TRACKING=yes` 以禁用官方的数据追踪。
### 4.3. 前端架构分析 (Frontend Architecture)
`excalidraw` 自身是一个复杂的 `monorepo` 项目,其核心是可独立使用的 `@excalidraw/excalidraw` 包和一个完整的Web应用 `excalidraw-app`。我们的项目构建并嵌入的是 `excalidraw-app`。
#### `excalidraw-app` 项目地图 (Project Map)
以下是 `excalidraw/excalidraw-app` 目录的关键结构:
```
excalidraw-app/
├── public/ # 静态资源,如 a-icons, fonts, manifest
├── components/ # 应用的主要React组件
│ ├── AppWelcomeScreen.tsx # 欢迎界面
│ ├── CollabButton.tsx # 协作按钮
│ ├── Library.tsx # 元素库UI
│ ├── Tooltip.tsx # 工具提示组件
│ └── ... # 其他UI组件
├── data/ # 数据处理与持久化相关的模块
│ ├── localForage.ts # IndexedDB的封装
│ ├── excalidraw.ts # Excalidraw核心库的导出与封装
│ └── ...
├── collab/ # 实时协作相关逻辑
│ ├── Collab.tsx # 协作功能的封装组件
│ ├── Portal.ts # 管理协作房间和用户
│ └── index.ts # 协作功能的初始化与管理
├── tests/ # 测试文件
├── App.tsx # 应用的根React组件,组织所有UI和逻辑
├── index.tsx # 应用的入口文件,将App组件渲染到DOM中
└── vite.config.mts # Vite构建配置文件
```
#### 核心组件与逻辑
- **`App.tsx`**: 这是前端的"心脏"。它是一个巨大的组件,负责:
- 渲染主要的 Excalidraw 画布 (`<Excalidraw />` 组件)。
- 管理整个应用的状态(如图形元素、应用状态如当前工具、缩放等)。
- 处理用户输入事件。
- 初始化并集成协作模块 (`collab`)。
- **`components/`**: 包含了构成 Excalidraw 界面的所有可复用React组件,例如工具栏、菜单、对话框等。这使得UI层具有良好的模块化。
- **`collab/`**: 封装了所有与实时协作相关的功能。
- 它使用 `socket.io-client` 与后端的 Socket.IO 服务器建立连接。
- 负责发送和接收绘图数据、光标位置、用户加入/离开等事件。
- `Portal.ts` 是关键,它维护了当前协作会话的状态。
- **`data/`**: 负责数据的加载和保存。在自托管模式下,它通过 `fetch` API 与我们的Go后端进行通信,以保存和加载画板数据。原始的 Firebase 逻辑被我们后端的兼容层所替代。
**总结**: 前端是一个高度组件化的 React 应用。通过 `frontend.patch`,我们巧妙地将其数据和协作的"后端"从官方服务切换到了我们自己的一体化Go服务器上,实现了完全的自托管。
---
## 5. 构建与部署 (Build & Deployment)
`
-108
View File
@@ -1,108 +0,0 @@
---
description:
globs:
alwaysApply: true
---
# Excalidraw-Complete 改造计划 (BYOC - Bring Your Own Cloud Edition)
本文档旨在规划和跟踪将 `excalidraw-complete` 升级为一个支持用户认证、多画布管理,并具备前端直连云存储能力的协作平台所需要的开发任务。
**核心思想**: 后端负责 **"身份认证"** 与 **"默认存储"**,前端负责 **"存储适配与执行"**。
---
## ✅ 第一阶段:后端认证与用户体系基础
**目标**:为应用引入用户身份。这是所有个性化功能(如按用户存储画布)的基石。
### 后端 (Go)
- [x] **1.1.1**: 在 `go.mod` 中添加 `golang.org/x/oauth2` 依赖。
- [x] **1.1.2**: 创建新的 HTTP 处理器用于处理 OAuth2 流程。
- [x] **1.1.3**: 在 `main.go` 中添加认证路由:
- [x] `GET /auth/login`
- [x] `GET /auth/callback`
- [x] **1.1.4**: 实现从 GitHub API 获取用户信息的逻辑。
- [x] **1.1.5**: 引入 JWT 库 (e.g., `github.com/golang-jwt/jwt/v5`)。
- [x] **1.1.6**: 实现用户登录成功后生成和颁发 JWT 的逻辑。
- [x] **1.1.7**: 创建 `core/user.go` 定义 `User` 实体。
- [x] **1.1.8**: 创建一个可重用的 JWT 中间件,用于解析 Token 并将用户信息注入请求上下文。
### 前端 (React)
- [x] **1.2.1**: 在 UI 中AppWelcomeScreen中添加"使用 GitHub 登录"按钮。在excalidraw\excalidraw-app\components\AppMainMenu.tsx中添加"登录"按钮。
- [x] **1.2.2**: 添加api层,实现点击按钮后跳转到后端 `/auth/login` 的逻辑。
- [x] **1.2.3**: 创建一个用于处理登录回调的组件/页面,能从 URL 中解析出 JWT。
- [x] **1.2.4**: 将获取到的 JWT 安全地存储在 `localStorage` 或 `sessionStorage` 中。
- [x] **1.2.5**: 创建一个全局 API 请求封装(如 Axios 拦截器),为所有请求自动附加 `Authorization` 头。
- [x] **1.2.6**: 建立全局用户状态管理 (e.g., Jotai/Zustand),并在登录后更新 UI(如显示用户头像)。
---
## ✅ 第二阶段:前端存储抽象层与UI框架
**目标**:在前端建立一个灵活的存储适配器架构和相应的UI,为后续接入多种存储后端做好准备。
### 前端 (React)
- [x] **2.1.1**: 在 `src/data/` 目录下创建 `storage.ts` 文件。
- [x] **2.1.2**: 在 `storage.ts` 中定义 `IStorageAdapter` TypeScript 接口,包含 `listCanvases`, `loadCanvas`, `saveCanvas`, `createCanvas`, `deleteCanvas` 等方法。
- [x] **2.1.3**: 设计并实现一个新的"数据源配置"设置页面或模态框。
- [x] **2.1.4**: 在设置UI中,创建一个下拉菜单,包含未来的存储选项("默认后端", "Cloudflare KV", "Amazon S3")。
- [x] **2.1.5**: 根据下拉菜单的选择,动态渲染用于输入凭证的表单。
- [x] **2.1.6**: 在 UI 上添加明确的安全警告,告知用户密钥仅存储在浏览器会话中。
- [x] **2.1.7**: 创建全局状态来管理存储配置,将敏感凭证存储在 `sessionStorage`,非敏感配置存储在 `localStorage`。
---
## ✅ 第三阶段:实现默认后端KV作为第一个存储适配器
**目标**:将项目自身的 Go 后端作为第一个可用的存储选项,实现并验证前端的存储适配器架构。
### 后端 (Go)
- [ ] **3.1.1**: 升级 `core/entity.go` 中的 `Document` 结构,增加 `UserID`, `Name`, `CreatedAt` 等字段。
- [ ] **3.1.2**: 重构 `core.DocumentStore` 接口,增加 `ListByUser`, `Update`, `Delete` 等方法,并使所有方法都接受 `userID` 参数。
- [ ] **3.1.3**: 更新所有现有的存储实现 (`sqlite`, `filesystem` 等) 以匹配新的 `DocumentStore` 接口,并确保数据按用户ID隔离。
- [ ] **3.1.4**: 创建新的受 JWT 保护的 API 路由:
- [ ] `GET /api/v2/canvases`
- [ ] `POST /api/v2/canvases`
- [ ] `GET /api/v2/canvases/{id}`
- [ ] `PUT /api/v2/canvases/{id}`
- [ ] `DELETE /api/v2/canvases/{id}`
### 前端 (React)
- [ ] **3.2.1**: 创建 `src/data/BackendStorageAdapter.ts` 文件,并使其实现 `IStorageAdapter` 接口。
- [ ] **3.2.2**: 在该适配器内部,实现所有接口方法,使其通过 `fetch` 调用后端的 `/api/v2/canvases` 相关 API。
- [ ] **3.2.3**: 实现多画布管理的侧边栏 UI。
- [ ] **3.2.4**: 将侧边栏 UI 与 `BackendStorageAdapter` 连接,实现一个功能完整的、由后端驱动的多画布管理系统。
---
## ✅ 第四阶段:实现Cloudflare KV客户端适配器
**目标**:实现第一个纯前端的存储选项,数据直接从浏览器发送到用户的Cloudflare KV。
### 前端 (React)
- [ ] **4.1.1**: 创建 `src/data/CloudflareKVAdapter.ts` 文件,并使其实现 `IStorageAdapter` 接口。
- [ ] **4.1.2**: 实现其构造函数,用于接收用户输入的 `accountId`, `namespaceId`, 和 `apiToken`。
- [ ] **4.1.3**: 在适配器内部,使用 `fetch` 实现对 Cloudflare KV 官方 API 的直接调用。
- [ ] **4.1.4**: 设计并在适配器中实现 KV 的键名(Key)管理策略。
- [ ] **4.1.5**: 在主应用逻辑中,当用户在设置中选择并配置了 Cloudflare KV 后,实例化并切换到 `CloudflareKVAdapter`。
- [ ] **4.1.6**: 验证所有画布操作(增删改查)都能在用户的 CF KV 上正确执行。
---
## ✅ 第五阶段:实现Amazon S3客户端适配器与最终打磨
**目标**:添加对S3的支持,并完善整个用户体验。
### 前端 (React)
- [ ] **5.1.1**: 在前端项目中添加 AWS SDK 依赖: `npm install @aws-sdk/client-s3`。
- [ ] **5.1.2**: 创建 `src/data/S3StorageAdapter.ts` 文件,并使其实现 `IStorageAdapter` 接口。
- [ ] **5.1.3**: 实现其构造函数,用于接收用户输入的 `accessKeyId`, `secretAccessKey`, `region`, `bucketName`。
- [ ] **5.1.4**: 在适配器内部,使用 `@aws-sdk/client-s3` 实现对 S3 对象的 `List`, `Get`, `Put`, `Delete` 操作。
- [ ] **5.1.5**: 设计并在适配器中实现 S3 的对象键(Key)管理策略。
- [ ] **5.1.6**: 在主应用逻辑中,当用户在设置中选择并配置了 S3 后,实例化并切换到 `S3StorageAdapter`。
### UX/UI 打磨
- [ ] **5.2.1**: 在每个数据源配置界面添加"测试连接"按钮,提供即时反馈。
- [ ] **5.2.2**: 完善在不同数据源之间切换时的用户体验,如提示保存未保存的更改。
- [ ] **5.2.3**: 在文档和UI中提供详细的指南,说明如何获取各种云服务的API密钥。
-214
View File
@@ -1,214 +0,0 @@
# Excalidraw-Complete 架构文档
本文档旨在详细阐述 `excalidraw-complete` 项目的系统架构、技术栈、模块设计和数据流,以便于开发者理解、维护和进行二次开发。
## 1. 概述 (Overview)
`excalidraw-complete` 是一个将优秀的开源白板工具 [Excalidraw](https://github.com/excalidraw/excalidraw) 进行整合与封装的自托管解决方案。其核心目标是简化 Excalidraw 的私有化部署流程,将前端UI、后端数据存储和实时协作服务打包成一个单一的、易于部署的Go二进制文件。
**核心特性:**
- **一体化部署**:将所有服务打包成单个可执行文件,无需复杂的依赖配置。
- **可插拔存储**:通过环境变量支持多种数据持久化方案,包括内存、本地文件系统、SQLite和AWS S3。
- **实时协作**:内置基于 Socket.IO 的实时协作服务器,允许多个用户同时在同一个画板上工作。
- **Firebase 兼容层**:提供一个内存实现的 Firebase API 兼容层,以满足 Excalidraw 前端对 Firebase 的部分依赖。
---
## 2. 技术栈 (Tech Stack)
项目采用了现代化的前后端技术栈。
### 后端 (Backend)
- **语言**: [Go](https://go.dev/) (v1.21+)
- **Web框架**: [Chi (v5)](https://github.com/go-chi/chi) - 一个轻量级、高性能的 Go HTTP 路由器。
- **实时通信**: [Socket.IO for Go](https://github.com/zishang520/socket.io/v2) - 实现了 Socket.IO 协议,用于实时协作。
- **数据库驱动**:
- [go-sqlite3](https://github.com/mattn/go-sqlite3) - 用于 SQLite 存储。
- [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) - 用于与 AWS S3 交互。
- **日志**: [Logrus](https://github.com/sirupsen/logrus) - 结构化的日志记录库。
- **ID生成**: [ULID](https://github.com/oklog/ulid) - 用于生成唯一、可排序的文档ID。
### 前端 (Frontend)
- **核心**: [Excalidraw](https://github.com/excalidraw/excalidraw) (作为 Git Submodule)
- **框架**: [React](https://reactjs.org/)
- **构建工具**: [Vite](https://vitejs.dev/)
- **语言**: [TypeScript](https://www.typescriptlang.org/)
### 构建与部署 (Build & Deployment)
- **容器化**: [Docker](https://www.docker.com/) & `Dockerfile`
- **构建自动化**: Go Build Tools, npm/yarn
---
## 3. 系统架构 (System Architecture)
`excalidraw-complete` 是一个典型的**单体架构 (Monolith)**,但内部逻辑分层清晰。
```
+-------------------------------------------------------------------------+
| User |
| (Browser with Excalidraw React App) |
+-------------------------------------------------------------------------+
| ^
| HTTP/S (API Calls) | HTTP/S (HTML/JS/CSS)
| WebSocket (Collaboration) |
v |
+-------------------------------------------------------------------------+
| excalidraw-complete Go Binary |
| |
| +-------------------------+ +-----------------------------------+ |
| | HTTP Server (Chi) | | Socket.IO Server | |
| |-------------------------| |-----------------------------------| |
| | - API Routes (/api/v2) | <--> | - Connection Handling | |
| | - Firebase Routes | | - Room Management (Join/Leave) | |
| | - Static File Serving | | - Message Broadcasting | |
| +-------------------------+ +-----------------------------------+ |
| | ^ |
| | | |
| v | |
| +-------------------------------------------------------------------+ |
| | Core Logic & Modules | |
| |-------------------------------------------------------------------| |
| | | | |
| | +--------------------------+ | +-----------------------------+ | |
| | | Handlers (API Logic) | | | Embedded Frontend Assets | | |
| | +--------------------------+ | | (Patched Excalidraw UI) | | |
| | | | +-----------------------------+ | |
| | v | | |
| | +--------------------------+ | | |
| | | Storage Interface | | | |
| | | (core.DocumentStore) | | | |
| | +--------------------------+ | | |
| | | | | | | | |
| |----|------|--------|-------|--------------------------------------| |
| v v v v v |
| [S3] [SQLite] [FS] [Memory] (Storage Implementations) |
| |
+-------------------------------------------------------------------------+
```
**架构说明:**
1. **Go主程序 (`main.go`)**: 作为应用的入口,它初始化并启动所有服务。
2. **HTTP服务器**: 使用 `Chi` 路由器来处理所有HTTP请求。这包括:
- **API服务**: 提供用于创建和获取文档的 RESTful API。
- **Firebase兼容层**: 模拟 Excalidraw 前端所需的 Firebase API。
- **静态文件服务**: 将嵌入的、经过修改的 Excalidraw 前端应用(HTML, JS, CSS等)提供给浏览器。
3. **Socket.IO服务器**: 独立处理 WebSocket 连接,负责所有实时协作功能,如同步绘图数据、光标位置等。
4. **存储层 (`stores`)**: 通过一个统一的 `core.DocumentStore` 接口,将数据存储逻辑抽象出来。可以根据环境变量在启动时选择不同的实现(S3、SQLite等)。
5. **嵌入式前端**: 前端 `Excalidraw` UI 作为一个 Git 子模块被包含在内。在构建阶段,它会被编译,并通过 Go 的 `embed` 特性直接嵌入到最终的二进制文件中。
---
## 4. 模块与服务说明 (Modules & Services)
### 4.1. 后端 (Backend)
#### 主应用 (`main.go`)
- **职责**: 应用的启动器和协调器。
- **核心逻辑**:
- 解析命令行参数 (`-listen`, `-loglevel`)。
- 根据环境变量初始化存储层 (`stores.GetStore()`)。
- 设置 `Chi` 路由器 (`setupRouter`),定义所有API路由。
- 设置 `Socket.IO` 服务器 (`setupSocketIO`),定义所有协作事件。
-`/socket.io/` 路径的请求代理到 Socket.IO 服务器。
- **动态前端服务 (`handleUI`)**:
- 使用 Go 的 `embed` 包将编译后的前端文件打包进二进制文件。
- 在提供前端文件时,动态替换文件内容中的URL(如将 `firestore.googleapis.com` 替换为 `localhost:3002`),以重定向API请求到自身。
- 监听系统信号以实现优雅停机 (`waitForShutdown`)。
#### 核心模块 (`core/`)
- **`core/entity.go`**: 定义了项目中最核心的数据结构和接口。
- `Document`: 代表一个画板文档。
- `DocumentStore`: 一个接口,定义了所有存储后端必须实现的两个方法:`FindID``Create`。这是实现可插拔存储的关键。
#### 存储层 (`stores/`)
- **`stores/storage.go`**: 工厂模式的实现。`GetStore()` 函数根据环境变量 `STORAGE_TYPE` 的值,创建并返回一个具体的 `DocumentStore` 接口实例。
- **存储实现**:
- `stores/memory/`: 将文档保存在内存中,服务重启后数据丢失。
- `stores/filesystem/`: 将每个文档作为单独的文件保存在本地文件系统上。
- `stores/sqlite/`: 使用 SQLite 数据库来存储文档数据。
- `stores/aws/`: 使用 AWS S3 对象存储来保存文档。
#### HTTP处理器 (`handlers/`)
- **`handlers/api/documents/`**: 实现了自定义的文档API (`/api/v2`)。
- `HandleCreate`: 处理文档的创建请求。
- `HandleGet`: 处理文档的读取请求。
- **`handlers/api/firebase/`**: 一个内存实现的 Firebase API 模拟层。它拦截了原始 Excalidraw 前端对 Firebase 的 `batchGet``commit` 请求,并在内存中进行处理,以确保前端协作功能可以正常工作,而无需真实的 Firebase 后端。
### 4.2. 前端 (Frontend)
#### Excalidraw UI (`excalidraw/` submodule)
- 项目通过 Git Submodule 引入了官方的 `excalidraw` 仓库。这使得跟踪上游更新变得容易。
#### 前端补丁 (`frontend.patch`)
- 这是一个至关重要的文件。由于我们是自托管,需要修改 Excalidraw 前端的一些硬编码配置。该补丁文件在构建时应用,主要做了以下修改:
- **重定向API端点**: 将所有对 `excalidraw.com` 官方后端的API请求(如 `VITE_APP_BACKEND_V2_GET_URL`, `VITE_APP_WS_SERVER_URL`)重定向到自托管服务的地址(如 `http://localhost:3002`)。
- **修改Firebase配置**: 清空部分 Firebase 配置,因为后端已经提供了兼容层。
- **禁用追踪**: 设置 `VITE_APP_DISABLE_TRACKING=yes` 以禁用官方的数据追踪。
### 4.3. 前端架构分析 (Frontend Architecture)
`excalidraw` 自身是一个复杂的 `monorepo` 项目,其核心是可独立使用的 `@excalidraw/excalidraw` 包和一个完整的Web应用 `excalidraw-app`。我们的项目构建并嵌入的是 `excalidraw-app`
#### `excalidraw-app` 项目地图 (Project Map)
以下是 `excalidraw/excalidraw-app` 目录的关键结构:
```
excalidraw-app/
├── public/ # 静态资源,如 a-icons, fonts, manifest
├── components/ # 应用的主要React组件
│ ├── AppWelcomeScreen.tsx # 欢迎界面
│ ├── CollabButton.tsx # 协作按钮
│ ├── Library.tsx # 元素库UI
│ ├── Tooltip.tsx # 工具提示组件
│ └── ... # 其他UI组件
├── data/ # 数据处理与持久化相关的模块
│ ├── localForage.ts # IndexedDB的封装
│ ├── excalidraw.ts # Excalidraw核心库的导出与封装
│ └── ...
├── collab/ # 实时协作相关逻辑
│ ├── Collab.tsx # 协作功能的封装组件
│ ├── Portal.ts # 管理协作房间和用户
│ └── index.ts # 协作功能的初始化与管理
├── tests/ # 测试文件
├── App.tsx # 应用的根React组件,组织所有UI和逻辑
├── index.tsx # 应用的入口文件,将App组件渲染到DOM中
└── vite.config.mts # Vite构建配置文件
```
#### 核心组件与逻辑
- **`App.tsx`**: 这是前端的"心脏"。它是一个巨大的组件,负责:
- 渲染主要的 Excalidraw 画布 (`<Excalidraw />` 组件)。
- 管理整个应用的状态(如图形元素、应用状态如当前工具、缩放等)。
- 处理用户输入事件。
- 初始化并集成协作模块 (`collab`)。
- **`components/`**: 包含了构成 Excalidraw 界面的所有可复用React组件,例如工具栏、菜单、对话框等。这使得UI层具有良好的模块化。
- **`collab/`**: 封装了所有与实时协作相关的功能。
- 它使用 `socket.io-client` 与后端的 Socket.IO 服务器建立连接。
- 负责发送和接收绘图数据、光标位置、用户加入/离开等事件。
- `Portal.ts` 是关键,它维护了当前协作会话的状态。
- **`data/`**: 负责数据的加载和保存。在自托管模式下,它通过 `fetch` API 与我们的Go后端进行通信,以保存和加载画板数据。原始的 Firebase 逻辑被我们后端的兼容层所替代。
**总结**: 前端是一个高度组件化的 React 应用。通过 `frontend.patch`,我们巧妙地将其数据和协作的"后端"从官方服务切换到了我们自己的一体化Go服务器上,实现了完全的自托管。
---
## 5. 构建与部署 (Build & Deployment)
`
-106
View File
@@ -1,106 +0,0 @@
# Excalidraw-Complete 改造计划 (BYOC - Bring Your Own Cloud Edition)
本文档旨在规划和跟踪将 `excalidraw-complete` 升级为一个支持用户认证、多画布管理,并具备前端直连云存储能力的协作平台所需要的开发任务。
**核心思想**: 后端负责 **"身份认证"** 与 **"默认存储"**,前端负责 **"存储适配与执行"**。
---
## ✅ 第一阶段:后端认证与用户体系基础
**目标**:为应用引入用户身份。这是所有个性化功能(如按用户存储画布)的基石。
### 后端 (Go)
- [x] **1.1.1**: 在 `go.mod` 中添加 `golang.org/x/oauth2` 依赖。
- [x] **1.1.2**: 创建新的 HTTP 处理器用于处理 OAuth2 流程。
- [x] **1.1.3**: 在 `main.go` 中添加认证路由:
- [x] `GET /auth/github/login`
- [x] `GET /auth/github/callback`
- [x] **1.1.4**: 实现从 GitHub API 获取用户信息的逻辑。
- [x] **1.1.5**: 引入 JWT 库 (e.g., `github.com/golang-jwt/jwt/v5`)。
- [x] **1.1.6**: 实现用户登录成功后生成和颁发 JWT 的逻辑。
- [x] **1.1.7**: 创建 `core/user.go` 定义 `User` 实体。
- [x] **1.1.8**: 创建一个可重用的 JWT 中间件,用于解析 Token 并将用户信息注入请求上下文。
### 前端 (React)
- [x] **1.2.1**: 在 UI 中AppWelcomeScreen中添加"使用 GitHub 登录"按钮。在excalidraw\excalidraw-app\components\AppMainMenu.tsx中添加"登录"按钮。
- [x] **1.2.2**: 添加api层,实现点击按钮后跳转到后端 `/auth/github/login` 的逻辑。
- [x] **1.2.3**: 创建一个用于处理登录回调的组件/页面,能从 URL 中解析出 JWT。
- [x] **1.2.4**: 将获取到的 JWT 安全地存储在 `localStorage``sessionStorage` 中。
- [x] **1.2.5**: 创建一个全局 API 请求封装(如 Axios 拦截器),为所有请求自动附加 `Authorization` 头。
- [x] **1.2.6**: 建立全局用户状态管理 (e.g., Jotai/Zustand),并在登录后更新 UI(如显示用户头像)。
---
## ✅ 第二阶段:前端存储抽象层与UI框架
**目标**:在前端建立一个灵活的存储适配器架构和相应的UI,为后续接入多种存储后端做好准备。
### 前端 (React)
- [x] **2.1.1**: 在 `src/data/` 目录下创建 `storage.ts` 文件。
- [x] **2.1.2**: 在 `storage.ts` 中定义 `IStorageAdapter` TypeScript 接口,包含 `listCanvases`, `loadCanvas`, `saveCanvas`, `createCanvas`, `deleteCanvas` 等方法。
- [x] **2.1.3**: 设计并实现一个新的"数据源配置"设置页面或模态框。
- [x] **2.1.4**: 在设置UI中,创建一个下拉菜单,包含未来的存储选项("默认后端", "Cloudflare KV", "Amazon S3""IndexDB")。
- [x] **2.1.5**: 根据下拉菜单的选择,动态渲染用于输入凭证的表单。
- [x] **2.1.6**: 在 UI 上添加明确的安全警告,告知用户密钥仅存储在浏览器会话中。
- [x] **2.1.7**: 创建全局状态来管理存储配置,将敏感凭证存储在 `sessionStorage`,非敏感配置存储在 `localStorage`
---
## ✅ 第三阶段:实现后端作为第一个KV存储适配器
**目标**:将项目自身的 Go 后端实现为一个简单的、面向用户的KV存储,作为第一个可用的存储选项。
### 后端 (Go) - KV API 设计
- **API理念**: 放弃复杂的RESTful设计,提供纯粹的KV操作接口,所有权与当前JWT用户绑定。
- **路由规划**:
- `GET /api/v2/kv`: 列出当前用户所有画布的元信息 (ID, Name, UpdatedAt)。
- `GET /api/v2/kv/{key}`: 获取单个画布的完整内容。
- `PUT /api/v2/kv/{key}`: 创建或更新一个画布。
- `DELETE /api/v2/kv/{key}`: 删除一个画布。
### 后端 (Go) - 执行步骤
- [x] **3.1.1**: 创建新的 `core/canvas.go` 文件,定义 `Canvas` 实体和 `CanvasStore` 接口。此举可避免与用于实时协作的旧 `Document` 模型冲突。
- [x] **3.1.2**: `Canvas` 实体将包含 `ID`, `UserID`, `Name`, `Data`, `CreatedAt`, `UpdatedAt` 字段。
- [x] **3.1.3**: `CanvasStore` 接口将定义 `List`, `Get`, `Save`, `Delete` 方法,所有方法都基于 `UserID` 操作以保证数据隔离。
- [x] **3.1.4**: 更新现有存储实现 (`sqlite`, `filesystem` 等) 以实现新的 `CanvasStore` 接口。
- [x] **3.1.5**: 创建新的 `handlers/api/kv/` 目录和处理器,实现上述KV API路由,并使用JWT中间件进行保护。
### 前端 (React)
- [x] **3.2.1**: 创建 `src/data/BackendStorageAdapter.ts` 文件,并使其实现 `IStorageAdapter` 接口。
- [x] **3.2.2**: 在该适配器内部,实现所有接口方法,使其通过 `fetch` 调用后端的 `/api/v2/kv` 相关 API。
- [x] **3.2.3**: 实现多画布管理的侧边栏 UI。
- [x] **3.2.4**: 将侧边栏 UI 与 `BackendStorageAdapter` 连接,实现一个功能完整的、由后端驱动的多画布管理系统。
---
## ✅ 第四阶段:实现Cloudflare KV客户端适配器
**目标**:实现第一个纯前端的存储选项,数据直接从浏览器发送到用户的Cloudflare KV。
### 前端 (React)
- [ ] **4.1.1**: 创建 `src/data/CloudflareKVAdapter.ts` 文件,并使其实现 `IStorageAdapter` 接口。
- [ ] **4.1.2**: 实现其构造函数,用于接收用户输入的 `accountId`, `namespaceId`, 和 `apiToken`
- [ ] **4.1.3**: 在适配器内部,使用 `fetch` 实现对 Cloudflare KV 官方 API 的直接调用。
- [ ] **4.1.4**: 设计并在适配器中实现 KV 的键名(Key)管理策略。
- [ ] **4.1.5**: 在主应用逻辑中,当用户在设置中选择并配置了 Cloudflare KV 后,实例化并切换到 `CloudflareKVAdapter`
- [ ] **4.1.6**: 验证所有画布操作(增删改查)都能在用户的 CF KV 上正确执行。
---
## ✅ 第五阶段:实现Amazon S3客户端适配器与最终打磨
**目标**:添加对S3的支持,并完善整个用户体验。
### 前端 (React)
- [ ] **5.1.1**: 在前端项目中添加 AWS SDK 依赖: `npm install @aws-sdk/client-s3`
- [ ] **5.1.2**: 创建 `src/data/S3StorageAdapter.ts` 文件,并使其实现 `IStorageAdapter` 接口。
- [ ] **5.1.3**: 实现其构造函数,用于接收用户输入的 `accessKeyId`, `secretAccessKey`, `region`, `bucketName`
- [ ] **5.1.4**: 在适配器内部,使用 `@aws-sdk/client-s3` 实现对 S3 对象的 `List`, `Get`, `Put`, `Delete` 操作。
- [ ] **5.1.5**: 设计并在适配器中实现 S3 的对象键(Key)管理策略。
- [ ] **5.1.6**: 在主应用逻辑中,当用户在设置中选择并配置了 S3 后,实例化并切换到 `S3StorageAdapter`
### UX/UI 打磨
- [ ] **5.2.1**: 在每个数据源配置界面添加"测试连接"按钮,提供即时反馈。
- [ ] **5.2.2**: 完善在不同数据源之间切换时的用户体验,如提示保存未保存的更改。
- [ ] **5.2.3**: 在文档和UI中提供详细的指南,说明如何获取各种云服务的API密钥。