# TraceStudio v0.2.2 功能更新
## 🎉 本次更新概览
本次更新主要完善了多用户系统的细节功能,增强了拖拽交互,添加了节点编辑和持久化功能。
**更新日期**: 2026-01-07
**版本**: v0.2.2
**类型**: 功能增强
---
## ✨ 新增功能
### 1. 动态用户列表 ⭐⭐⭐
#### 功能描述
用户下拉框现在从后端API动态获取真实用户列表,不再使用写死的4个用户。
#### 技术实现
- **组件**: [web/src/components/HeaderBar.tsx](../web/src/components/HeaderBar.tsx)
- **API**: `GET /api/users/list`
- **Fallback**: 如果API失败,降级使用默认用户列表 `['guest', 'admin', 'dev', 'test']`
#### 使用方式
```typescript
// 组件挂载时自动获取用户列表
React.useEffect(() => {
const fetchUsers = async () => {
const response = await fetch('/api/users/list')
const data = await response.json()
setUserList(data.users) // 更新用户列表
}
fetchUsers()
}, [])
```
#### 效果展示
```
用户下拉框显示:
┌────────────────────┐
│ 👤 guest ▼ │
├────────────────────┤
│ ✓ guest │
│ admin │
│ dev │
│ analyst │ ← 新用户动态显示
│ researcher │
└────────────────────┘
```
---
### 2. 工作流右键导入 ⭐⭐
#### 功能描述
在文件浏览器中右键点击 `.utrace` 文件,新增"📂 导入工作流"选项,快速加载工作流。
#### 技术实现
- **组件**: [web/src/components/FileExplorer.tsx](../web/src/components/FileExplorer.tsx)
- **触发**: 右键菜单 → 点击"📂 导入工作流"
- **效果**: 调用 `loadWorkflow(file.path)` 加载到画布
#### 代码示例
```typescript
{contextMenu.file.extension === '.utrace' && (
{
loadWorkflow(contextMenu.file.path)
.then(() => alert(`✅ 已导入工作流`))
.catch((error) => alert(`❌ 导入失败`))
}}>
📂 导入工作流
)}
```
#### 使用流程
1. 在文件浏览器导航到工作流目录
2. 右键点击 `.utrace` 文件
3. 选择"📂 导入工作流"
4. 工作流自动加载到画布
---
### 3. 节点标题可编辑 ⭐⭐⭐
#### 功能描述
在属性面板(Inspector)中,节点标题现在可以点击编辑,自定义节点名称。
#### 技术实现
- **组件**: [web/src/components/Inspector.tsx](../web/src/components/Inspector.tsx)
- **状态**: `isEditingLabel`, `tempLabel`
- **保存**: Enter 确认,Escape 取消
#### 编辑流程
```
1. 点击节点标题 → 进入编辑模式
┌────────────────────────┐
│ 📥 [CSV 数据加载器___] │ ← 输入框
└────────────────────────┘
2. 输入新标题 → 按 Enter 确认
┌────────────────────────┐
│ 📥 销售数据加载器 │ ← 已更新
└────────────────────────┘
```
#### 代码关键点
```typescript
// 点击标题进入编辑模式
{
setIsEditingLabel(true)
setTempLabel(node.data?.label || node.data?.meta?.display_name)
}}>
{node.data?.label || node.data?.meta?.display_name}
// 编辑时显示输入框
{isEditingLabel && (
{
if (e.key === 'Enter') {
updateNodeData(node.id, { label: tempLabel })
setIsEditingLabel(false)
}
}}
/>
)}
```
---
### 4. 节点数据保存 ⭐⭐
#### 功能描述
属性面板新增 "💾 保存" 按钮,可将节点配置保存到服务器。
#### 技术实现
- **组件**: [web/src/components/Inspector.tsx](../web/src/components/Inspector.tsx)
- **API**: `POST /api/nodes/save`
- **数据**: 发送 `nodeId` 和 `nodeData`
#### UI 位置
```
┌─────────────────────────┐
│ 数据预览 │
├─────────────────────────┤
│ [▶ 运行预览] [💾] │ ← 新增保存按钮
└─────────────────────────┘
```
#### 请求示例
```typescript
await fetch('/api/nodes/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nodeId: node.id,
nodeData: node.data
})
})
```
#### 应用场景
- 保存常用节点配置模板
- 协作编辑中的配置同步
- 节点配置版本控制
---
### 5. 拖拽上传文件 ⭐⭐⭐
#### 功能描述
从 Windows 文件管理器直接拖拽文件到应用的文件浏览器,自动触发上传。
#### 技术实现
- **组件**: [web/src/components/FileExplorer.tsx](../web/src/components/FileExplorer.tsx)
- **事件**: `onDrop`, `onDragOver`
- **API**: `POST /api/files/upload`
#### 实现细节
```typescript
const handleDrop = async (e: React.DragEvent) => {
e.preventDefault()
const files = e.dataTransfer.files
// 批量上传拖入的文件
for (let i = 0; i < files.length; i++) {
await uploadFile(files[i], currentPath, currentUser)
}
loadFiles() // 刷新文件列表
alert(`✅ 已上传 ${files.length} 个文件`)
}
```
#### 使用方式
1. 打开 Windows 文件管理器
2. 选择要上传的文件
3. 拖拽到应用的文件浏览器区域
4. 文件自动上传并显示
#### 支持特性
- ✅ 单文件拖拽
- ✅ 多文件批量拖拽
- ✅ 自动刷新文件列表
- ✅ 上传进度提示
---
### 6. 拖拽下载文件 ⭐⭐
#### 功能描述
从应用的文件浏览器拖拽文件到 Windows 文件管理器,触发下载。
#### 技术实现
- **组件**: [web/src/components/FileExplorer.tsx](../web/src/components/FileExplorer.tsx)
- **事件**: `onDragStart`
- **机制**: 使用 `DownloadURL` 数据类型
#### 代码关键点
```typescript
const handleFileDragStart = (e: React.DragEvent, file: FileInfo) => {
if (file.type === 'folder') return // 文件夹不支持拖拽下载
const downloadUrl = getDownloadUrl(file.path)
e.dataTransfer.setData(
'DownloadURL',
`application/octet-stream:${file.name}:${window.location.origin}${downloadUrl}`
)
e.dataTransfer.effectAllowed = 'copy'
}
```
#### 使用方式
1. 在应用文件浏览器中找到目标文件
2. 按住鼠标左键拖拽文件
3. 拖到 Windows 文件管理器或桌面
4. 文件自动下载到目标位置
#### 限制说明
- ⚠️ **仅支持文件**,文件夹不支持拖拽下载
- ⚠️ **浏览器兼容性**:Chrome, Edge 完全支持;Firefox 部分支持
---
### 7. 拖拽导入工作流 ⭐⭐⭐
#### 功能描述
从文件浏览器拖拽 `.utrace` 文件到画布,自动加载工作流。
#### 技术实现
- **组件**: [web/src/components/Workspace.tsx](../web/src/components/Workspace.tsx)
- **检测**: 识别文件扩展名 `.utrace`
- **操作**: 调用 `loadWorkflow()` 加载
#### 代码逻辑
```typescript
const onDrop = useCallback((event: React.DragEvent) => {
const filePath = event.dataTransfer.getData('application/x-file-path')
if (filePath.endsWith('.utrace')) {
// 拖入工作流文件 - 加载工作流
const loadWorkflow = useStore.getState().loadWorkflow
loadWorkflow(filePath)
.then(() => alert('✅ 已导入工作流'))
.catch((error) => alert('❌ 导入失败'))
} else if (filePath.endsWith('.csv')) {
// 拖入CSV文件 - 创建节点
createCSVNode(filePath, position)
}
}, [])
```
#### 使用场景
```
场景 1: 快速加载工作流
┌────────────────┐ ┌──────────────┐
│ 📁 文件浏览器 │ 拖拽→ │ 🖼️ 画布 │
│ └ 分析.utrace │ │ (加载工作流) │
└────────────────┘ └──────────────┘
场景 2: 混合拖拽
- 拖拽 .utrace → 加载工作流
- 拖拽 .csv → 创建 CSV 节点
- 拖拽普通节点 → 添加到画布
```
#### 交互优势
- ✅ 无需右键菜单,直接拖拽
- ✅ 统一的拖拽交互逻辑
- ✅ 支持多种文件类型识别
---
## 🔧 技术细节
### 拖拽数据传递机制
#### 1. 文件路径传递
```typescript
// 设置数据
e.dataTransfer.setData('application/x-file-path', file.path)
// 读取数据
const filePath = e.dataTransfer.getData('application/x-file-path')
```
#### 2. 文件下载
```typescript
// 设置下载URL
e.dataTransfer.setData(
'DownloadURL',
`${mimeType}:${fileName}:${downloadUrl}`
)
```
#### 3. 原生文件上传
```typescript
// 读取拖入的文件
const files = e.dataTransfer.files
for (let file of files) {
await uploadFile(file, path, username)
}
```
### 状态管理优化
#### 节点标题状态
```typescript
// 局部状态管理
const [isEditingLabel, setIsEditingLabel] = useState(false)
const [tempLabel, setTempLabel] = useState('')
// 保存到全局状态
updateNodeData(nodeId, { label: newLabel })
```
#### 用户列表状态
```typescript
// 默认值 + API更新
const [userList, setUserList] = useState(['guest', 'admin', 'dev', 'test'])
// 组件挂载时更新
useEffect(() => {
fetchUsers().then(users => setUserList(users))
}, [])
```
---
## 📊 功能对比表
| 功能 | v0.2.1 | v0.2.2 |
|------|--------|--------|
| 用户列表 | ❌ 写死4个用户 | ✅ 动态从API获取 |
| 工作流导入 | ✅ 双击加载 | ✅ 右键菜单 + 拖拽加载 |
| 节点标题 | ❌ 只读 | ✅ 可点击编辑 |
| 节点保存 | ❌ 无 | ✅ API持久化 |
| 文件上传 | ✅ 点击上传按钮 | ✅ 拖拽 + 按钮 |
| 文件下载 | ✅ 右键菜单 | ✅ 右键 + 拖拽 |
| 拖拽到画布 | ✅ CSV文件 | ✅ CSV + 工作流 |
---
## 🎯 使用示例
### 完整工作流:从文件到节点
#### 场景:分析销售数据
```
步骤 1: 上传数据文件
- 从Windows拖拽 sales_2026.csv 到文件浏览器
- ✅ 文件自动上传到 users/analyst/data/
步骤 2: 创建分析节点
- 拖拽 sales_2026.csv 到画布
- ✅ 自动创建 CSV Loader 节点,路径已填充
步骤 3: 编辑节点标题
- 点击节点标题"CSV 数据加载器"
- 输入"2026年销售数据",按 Enter
- ✅ 节点标题已更新
步骤 4: 保存节点配置
- 点击属性面板的 💾 按钮
- ✅ 节点配置保存到服务器
步骤 5: 保存工作流
- 点击顶部的 💾 按钮
- ✅ 工作流保存为 .utrace 文件
步骤 6: 下次使用
- 拖拽 .utrace 文件到画布
- ✅ 完整工作流自动加载
```
---
## 🐛 已知问题
### 1. 文件拖拽下载的浏览器兼容性
- **问题**: Firefox 浏览器不完全支持 `DownloadURL`
- **影响**: 拖拽到桌面可能无法下载
- **解决方案**: 使用右键菜单的"下载"选项
### 2. 节点保存API未实现
- **问题**: 后端 `POST /api/nodes/save` 接口暂未实现
- **影响**: 点击保存按钮会显示错误
- **临时方案**: 功能已就绪,等待后端实现
- **文档**: 参见 [BACKEND_API_REQUIREMENTS.md](BACKEND_API_REQUIREMENTS.md)
### 3. 用户列表API未实现
- **问题**: 后端 `GET /api/users/list` 接口暂未实现
- **影响**: 降级使用默认4个用户
- **临时方案**: 功能正常,但用户列表不完整
- **文档**: 参见 [BACKEND_API_REQUIREMENTS.md](BACKEND_API_REQUIREMENTS.md)
---
## 🔮 后续计划
### 短期(v0.2.3)
- [ ] 实现后端用户列表API
- [ ] 实现后端节点保存API
- [ ] 添加拖拽上传进度条
- [ ] 优化大文件拖拽性能
### 中期(v0.3.0)
- [ ] 节点模板系统
- [ ] 批量节点操作
- [ ] 工作流版本管理
- [ ] 用户协作功能
### 长期(v0.4.0)
- [ ] 在线预览大文件(CSV, JSON)
- [ ] 文件搜索和过滤
- [ ] 云端同步
- [ ] 工作流市场
---
## 📝 升级指南
### 从 v0.2.1 升级到 v0.2.2
#### 前端升级
```bash
cd web
git pull
npm install # 如有新依赖
npm run dev
```
#### 后端准备
1. 阅读 [BACKEND_API_REQUIREMENTS.md](BACKEND_API_REQUIREMENTS.md)
2. 实现 `GET /api/users/list` 接口(推荐)
3. 实现 `POST /api/nodes/save` 接口(可选)
#### 数据迁移
无需数据迁移,完全向后兼容。
---
## 🙏 贡献者
- **前端开发**: GitHub Copilot
- **API设计**: 开发团队
- **文档撰写**: AI Assistant
- **测试**: 用户社区
---
## 📧 反馈与支持
- **GitHub Issues**: [提交问题](https://github.com/your-repo/issues)
- **功能请求**: [提交想法](https://github.com/your-repo/discussions)
- **文档改进**: 欢迎提交 PR
---
**版本**: v0.2.2
**发布日期**: 2026-01-07
**向后兼容**: ✅ 是
**需要数据库更新**: ❌ 否