TraceStudio-dev/docs/web1.1_filemanager/BACKEND_API_REQUIREMENTS.md
2026-01-07 21:31:22 +08:00

476 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 后端 API 需求文档
## 📋 概述
本文档描述了前端新增功能所需的后端 API 接口。这些接口用于支持多用户管理、节点数据持久化等功能。
---
## 🔌 新增 API 接口
### 1. 获取用户列表
#### 接口信息
- **路径**: `GET /api/users/list`
- **用途**: 获取系统中所有用户的列表,用于用户切换下拉框显示
- **优先级**: ⭐⭐⭐ 高
#### 请求参数
#### 响应格式
```json
{
"users": ["guest", "admin", "dev", "test", "user1", "user2"],
"count": 6
}
```
#### 响应字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| users | string[] | 用户名列表 |
| count | integer | 用户总数 |
#### 实现建议
1. 扫描 `cloud/users/` 目录,返回所有子目录名称
2. 按字母顺序排序
3. 可以添加缓存机制TTL 60秒
4. 排除系统目录(如 `.git`, `__pycache__` 等)
#### 示例代码
```python
from fastapi import APIRouter
from pathlib import Path
from typing import List
router = APIRouter()
@router.get("/api/users/list")
async def list_users():
"""获取所有用户列表"""
users_dir = Path("cloud/users")
if not users_dir.exists():
users_dir.mkdir(parents=True, exist_ok=True)
return {"users": [], "count": 0}
users = []
for item in users_dir.iterdir():
if item.is_dir() and not item.name.startswith('.'):
users.append(item.name)
users.sort()
return {"users": users, "count": len(users)}
```
#### 错误处理
- 如果 `cloud/users/` 不存在,自动创建并返回空列表
- 权限问题返回 `403 Forbidden`
---
### 2. 保存节点数据
#### 接口信息
- **路径**: `POST /api/nodes/save`
- **用途**: 保存单个节点的配置数据到服务器持久化存储
- **优先级**: ⭐⭐ 中
#### 请求参数
**Content-Type**: `application/json`
```json
{
"nodeId": "n_1704614400000_1234",
"nodeData": {
"label": "我的CSV加载器",
"file_path": "users/guest/data/sales.csv",
"delimiter": ",",
"meta": { ... },
"preview": { ... }
}
}
```
#### 请求字段说明
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| nodeId | string | 是 | 节点唯一标识符 |
| nodeData | object | 是 | 节点完整数据对象 |
| nodeData.label | string | 否 | 节点自定义标题 |
| nodeData.* | any | 否 | 其他节点参数 |
#### 响应格式
**成功响应** (200):
```json
{
"success": true,
"nodeId": "n_1704614400000_1234",
"savedAt": "2026-01-07T12:34:56.789Z"
}
```
**失败响应** (400):
```json
{
"success": false,
"error": "Invalid nodeId format"
}
```
#### 实现建议
##### 存储方案 A文件系统
```python
# 存储路径: cloud/nodes/{nodeId}.json
import json
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from pathlib import Path
from datetime import datetime
class NodeSaveRequest(BaseModel):
nodeId: str
nodeData: dict
@router.post("/api/nodes/save")
async def save_node(request: NodeSaveRequest):
"""保存节点数据到文件系统"""
nodes_dir = Path("cloud/nodes")
nodes_dir.mkdir(parents=True, exist_ok=True)
# 验证 nodeId 格式
if not request.nodeId.startswith('n_'):
raise HTTPException(status_code=400, detail="Invalid nodeId format")
# 添加元数据
save_data = {
"nodeId": request.nodeId,
"nodeData": request.nodeData,
"savedAt": datetime.utcnow().isoformat() + "Z"
}
# 保存到文件
file_path = nodes_dir / f"{request.nodeId}.json"
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(save_data, f, indent=2, ensure_ascii=False)
return {
"success": True,
"nodeId": request.nodeId,
"savedAt": save_data["savedAt"]
}
```
##### 存储方案 BSQLite 数据库
```python
# 使用 SQLite 存储节点数据
import sqlite3
import json
def init_db():
conn = sqlite3.connect('cloud/tracestudio.db')
c = conn.cursor()
c.execute('''
CREATE TABLE IF NOT EXISTS nodes (
node_id TEXT PRIMARY KEY,
node_data TEXT NOT NULL,
saved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
@router.post("/api/nodes/save")
async def save_node(request: NodeSaveRequest):
"""保存节点数据到数据库"""
conn = sqlite3.connect('cloud/tracestudio.db')
c = conn.cursor()
c.execute('''
INSERT OR REPLACE INTO nodes (node_id, node_data, saved_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
''', (request.nodeId, json.dumps(request.nodeData)))
conn.commit()
# 获取保存时间
c.execute('SELECT saved_at FROM nodes WHERE node_id = ?', (request.nodeId,))
saved_at = c.fetchone()[0]
conn.close()
return {
"success": True,
"nodeId": request.nodeId,
"savedAt": saved_at
}
```
#### 使用场景
1. 用户在 Inspector 面板编辑节点参数
2. 点击 "💾 保存" 按钮
3. 前端调用此 API 保存节点状态
4. 可用于恢复节点配置、协作编辑等场景
#### 扩展功能(可选)
- 添加用户权限验证(只能保存自己的节点)
- 节点版本控制(保存历史记录)
- 批量保存接口 `POST /api/nodes/batch-save`
---
## 🔄 现有 API 增强建议
### 文件上传 API 增强
**当前**: `POST /api/files/upload?path=xxx&username=xxx`
**建议增强**:
1. 支持批量上传(拖拽多个文件)
2. 返回上传文件的详细信息(路径、大小、类型)
3. 添加上传进度支持WebSocket 或 Server-Sent Events
```python
@router.post("/api/files/upload")
async def upload_files(
files: List[UploadFile], # 支持多文件
path: str = "",
username: str = "guest"
):
"""批量上传文件"""
results = []
for file in files:
# ... 上传逻辑 ...
results.append({
"filename": file.filename,
"path": f"{path}/{file.filename}",
"size": file.size,
"status": "success"
})
return {
"uploaded": len(results),
"files": results
}
```
---
## 📊 优先级排序
| 优先级 | 接口 | 原因 |
|--------|------|------|
| ⭐⭐⭐ 高 | GET /api/users/list | 用户切换下拉框依赖此接口无此接口会显示写死的4个用户 |
| ⭐⭐ 中 | POST /api/nodes/save | 节点持久化功能,不实现不影响基本使用 |
| ⭐ 低 | 文件上传增强 | 已有基础功能,增强为优化体验 |
---
## 🧪 测试用例
### 测试用户列表 API
```bash
# 测试 1: 获取用户列表
curl http://localhost:8000/api/users/list
# 预期响应:
{
"users": ["admin", "dev", "guest", "test"],
"count": 4
}
# 测试 2: 空用户目录
rm -rf cloud/users/*
curl http://localhost:8000/api/users/list
# 预期响应:
{
"users": [],
"count": 0
}
```
### 测试节点保存 API
```bash
# 测试 1: 保存节点
curl -X POST http://localhost:8000/api/nodes/save \
-H "Content-Type: application/json" \
-d '{
"nodeId": "n_1704614400000_1234",
"nodeData": {
"label": "测试节点",
"file_path": "users/guest/data/test.csv"
}
}'
# 预期响应:
{
"success": true,
"nodeId": "n_1704614400000_1234",
"savedAt": "2026-01-07T12:34:56.789Z"
}
# 测试 2: 无效节点ID
curl -X POST http://localhost:8000/api/nodes/save \
-H "Content-Type: application/json" \
-d '{
"nodeId": "invalid_id",
"nodeData": {}
}'
# 预期响应: 400 Bad Request
{
"success": false,
"error": "Invalid nodeId format"
}
```
---
## 🔐 安全注意事项
### 1. 路径遍历防护
```python
def validate_path(path: str) -> bool:
"""防止 ../ 路径遍历攻击"""
safe_path = Path(path).resolve()
base_path = Path("cloud/").resolve()
return str(safe_path).startswith(str(base_path))
```
### 2. 文件大小限制
```python
MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB
MAX_NODE_DATA_SIZE = 10 * 1024 * 1024 # 10MB
# 在上传和保存时检查大小
if len(json.dumps(request.nodeData)) > MAX_NODE_DATA_SIZE:
raise HTTPException(413, "Node data too large")
```
### 3. 用户权限验证
```python
def check_user_permission(username: str, resource_path: str) -> bool:
"""验证用户只能访问自己的资源"""
if not resource_path.startswith(f"users/{username}/"):
raise HTTPException(403, "Permission denied")
```
---
## 📦 数据库 Schema可选
如果使用数据库存储节点数据,建议的表结构:
```sql
-- 节点数据表
CREATE TABLE nodes (
node_id TEXT PRIMARY KEY,
node_type TEXT NOT NULL,
node_data TEXT NOT NULL, -- JSON 格式
created_by TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
version INTEGER DEFAULT 1
);
-- 创建索引
CREATE INDEX idx_nodes_created_by ON nodes(created_by);
CREATE INDEX idx_nodes_created_at ON nodes(created_at);
-- 节点历史表(可选,用于版本控制)
CREATE TABLE node_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
node_id TEXT NOT NULL,
node_data TEXT NOT NULL,
version INTEGER NOT NULL,
saved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (node_id) REFERENCES nodes(node_id)
);
```
---
## 🚀 实施步骤
### 阶段 1: 基础功能(立即实施)
1. ✅ 实现 `GET /api/users/list` 接口
2. ✅ 测试用户列表显示
### 阶段 2: 节点持久化(后续实施)
1. ⏳ 实现 `POST /api/nodes/save` 接口
2. ⏳ 添加节点加载接口 `GET /api/nodes/{nodeId}`
3. ⏳ 添加节点列表接口 `GET /api/nodes/list`
### 阶段 3: 增强功能(可选)
1. ⏸️ 节点版本控制
2. ⏸️ 多用户协作编辑
3. ⏸️ 节点模板管理
---
## 📝 前端调用示例
### 获取用户列表
```typescript
// web/src/components/HeaderBar.tsx
React.useEffect(() => {
const fetchUsers = async () => {
try {
const response = await fetch('/api/users/list')
if (response.ok) {
const data = await response.json()
setUserList(data.users)
}
} catch (error) {
console.warn('获取用户列表失败,使用默认列表')
}
}
fetchUsers()
}, [])
```
### 保存节点数据
```typescript
// web/src/components/Inspector.tsx
const handleSaveNode = async () => {
try {
const response = await fetch('/api/nodes/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nodeId: node.id,
nodeData: node.data
})
})
if (response.ok) {
const result = await response.json()
alert(`✅ 节点已保存: ${result.savedAt}`)
} else {
const error = await response.text()
alert(`❌ 保存失败: ${error}`)
}
} catch (error) {
alert(`❌ 网络错误: ${error}`)
}
}
```
---
## 🔄 版本历史
| 版本 | 日期 | 更新内容 |
|------|------|---------|
| v1.0 | 2026-01-07 | 初始版本定义用户列表和节点保存API |
---
## 📧 联系方式
如有疑问或建议,请通过以下方式联系:
- GitHub Issues: [TraceStudio Issues]
- 文档维护者: 前端开发团队