feat(hands): restructure Hands UI with Chinese localization
Major changes: - Add HandList.tsx component for left sidebar - Add HandTaskPanel.tsx for middle content area - Restructure Sidebar tabs: 分身/HANDS/Workflow - Remove Hands tab from RightPanel - Localize all UI text to Chinese - Archive legacy OpenClaw documentation - Add Hands integration lessons document - Update feature checklist with new components UI improvements: - Left sidebar now shows Hands list with status icons - Middle area shows selected Hand's tasks and results - Consistent styling with Tailwind CSS - Chinese status labels and buttons Documentation: - Create docs/archive/openclaw-legacy/ for old docs - Add docs/knowledge-base/hands-integration-lessons.md - Update docs/knowledge-base/feature-checklist.md - Update docs/knowledge-base/README.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
417
docs/knowledge-base/tauri-desktop.md
Normal file
417
docs/knowledge-base/tauri-desktop.md
Normal file
@@ -0,0 +1,417 @@
|
||||
# Tauri 桌面端开发笔记
|
||||
|
||||
> 记录 ZCLAW Desktop Tauri 开发过程中的经验和注意事项。
|
||||
|
||||
---
|
||||
|
||||
## 1. 项目结构
|
||||
|
||||
```
|
||||
desktop/
|
||||
├── src/ # React 前端
|
||||
│ ├── components/ # UI 组件
|
||||
│ ├── store/ # Zustand 状态管理
|
||||
│ ├── lib/ # 工具库
|
||||
│ └── App.tsx # 入口组件
|
||||
├── src-tauri/ # Tauri Rust 后端
|
||||
│ ├── src/
|
||||
│ │ ├── lib.rs # 主入口
|
||||
│ │ └── main.rs # 主函数
|
||||
│ ├── Cargo.toml # Rust 依赖
|
||||
│ ├── tauri.conf.json # Tauri 配置
|
||||
│ └── build.rs # 构建脚本
|
||||
├── package.json
|
||||
└── vite.config.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 开发命令
|
||||
|
||||
### 2.1 常用命令
|
||||
|
||||
```bash
|
||||
# 启动开发服务器 (Vite + Tauri)
|
||||
pnpm tauri dev
|
||||
|
||||
# 仅启动前端 (Vite)
|
||||
pnpm dev
|
||||
|
||||
# 构建生产版本
|
||||
pnpm tauri build
|
||||
|
||||
# 类型检查
|
||||
pnpm tsc --noEmit
|
||||
```
|
||||
|
||||
### 2.2 命令说明
|
||||
|
||||
| 命令 | 说明 | 端口 |
|
||||
|------|------|------|
|
||||
| `pnpm dev` | 仅 Vite 开发服务器 | 1420 |
|
||||
| `pnpm tauri dev` | Tauri + Vite | 1420 (Vite) + Native Window |
|
||||
| `pnpm tauri build` | 生产构建 | - |
|
||||
|
||||
---
|
||||
|
||||
## 3. 配置文件
|
||||
|
||||
### 3.1 tauri.conf.json 关键配置
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm dev",
|
||||
"beforeBuildCommand": "pnpm build",
|
||||
"devPath": "http://localhost:1420",
|
||||
"distDir": "../dist"
|
||||
},
|
||||
"tauri": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "ZCLAW",
|
||||
"width": 1200,
|
||||
"height": 800,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src 'self'; connect-src 'self' ws://localhost:* ws://127.0.0.1:*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Vite 配置
|
||||
|
||||
```typescript
|
||||
// vite.config.ts
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 1420,
|
||||
strictPort: true,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://127.0.0.1:50051',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
ws: true, // WebSocket 支持
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 常见问题
|
||||
|
||||
### 4.1 端口占用
|
||||
|
||||
**症状**: `Port 1420 is already in use`
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```powershell
|
||||
# 查找占用进程
|
||||
netstat -ano | findstr "1420"
|
||||
|
||||
# 终止进程
|
||||
Stop-Process -Id <PID> -Force
|
||||
```
|
||||
|
||||
### 4.2 Tauri 编译失败
|
||||
|
||||
**常见原因**:
|
||||
|
||||
1. **Rust 版本过低**
|
||||
```bash
|
||||
rustup update
|
||||
```
|
||||
|
||||
2. **依赖缺失**
|
||||
```bash
|
||||
# Windows 需要 Visual Studio Build Tools
|
||||
# 安装: https://visualstudio.microsoft.com/visual-cpp-build-tools/
|
||||
|
||||
# 确保 C++ 工作负载已安装
|
||||
```
|
||||
|
||||
3. **Cargo 缓存问题**
|
||||
```bash
|
||||
cd desktop/src-tauri
|
||||
cargo clean
|
||||
cargo build
|
||||
```
|
||||
|
||||
### 4.3 窗口白屏
|
||||
|
||||
**排查步骤**:
|
||||
|
||||
1. 检查 Vite 开发服务器是否运行
|
||||
2. 打开 DevTools (F12) 查看控制台错误
|
||||
3. 检查 `tauri.conf.json` 中的 `devPath`
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```typescript
|
||||
// 确保在 tauri.conf.json 中启用 devtools
|
||||
{
|
||||
"tauri": {
|
||||
"windows": [{
|
||||
"devtools": true // 开发模式下启用
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 热重载不工作
|
||||
|
||||
**检查**:
|
||||
|
||||
1. `beforeDevCommand` 是否正确配置
|
||||
2. 文件监听限制 (Linux)
|
||||
```bash
|
||||
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
|
||||
sudo sysctl -p
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. IPC 通信
|
||||
|
||||
### 5.1 Rust 端暴露命令
|
||||
|
||||
```rust
|
||||
// src-tauri/src/lib.rs
|
||||
#[tauri::command]
|
||||
fn get_app_version() -> String {
|
||||
env!("CARGO_PKG_VERSION").to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
get_app_version,
|
||||
// 其他命令
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 前端调用
|
||||
|
||||
```typescript
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
|
||||
const version = await invoke<string>('get_app_version');
|
||||
```
|
||||
|
||||
### 5.3 常用 Tauri API
|
||||
|
||||
| API | 用途 |
|
||||
|-----|------|
|
||||
| `@tauri-apps/api/core` | invoke, convertFileSrc |
|
||||
| `@tauri-apps/api/window` | 窗口管理 |
|
||||
| `@tauri-apps/api/shell` | 执行 shell 命令 |
|
||||
| `@tauri-apps/api/fs` | 文件系统 |
|
||||
| `@tauri-apps/api/path` | 路径 API |
|
||||
|
||||
---
|
||||
|
||||
## 6. 安全配置
|
||||
|
||||
### 6.1 CSP 配置
|
||||
|
||||
```json
|
||||
{
|
||||
"tauri": {
|
||||
"security": {
|
||||
"csp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; connect-src 'self' ws://localhost:* ws://127.0.0.1:* http://127.0.0.1:*; font-src 'self' https://fonts.gstatic.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 允许的协议
|
||||
|
||||
确保 CSP 允许:
|
||||
- `ws://localhost:*` - 本地 WebSocket
|
||||
- `ws://127.0.0.1:*` - OpenFang WebSocket
|
||||
- `http://127.0.0.1:*` - OpenFang REST API
|
||||
|
||||
---
|
||||
|
||||
## 7. 本地 Gateway 集成
|
||||
|
||||
### 7.1 Bundled Runtime
|
||||
|
||||
ZCLAW Desktop 可以捆绑 OpenFang Runtime:
|
||||
|
||||
```
|
||||
desktop/src-tauri/resources/
|
||||
└── openfang-runtime/
|
||||
├── openfang.exe
|
||||
├── config/
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 7.2 启动本地 Gateway
|
||||
|
||||
```rust
|
||||
#[tauri::command]
|
||||
async fn start_local_gateway(app: AppHandle) -> Result<(), String> {
|
||||
let resource_path = app.path_resolver()
|
||||
.resource_dir()
|
||||
.ok_or("Failed to get resource dir")?;
|
||||
|
||||
let openfang_path = resource_path.join("openfang-runtime/openfang.exe");
|
||||
|
||||
// 启动进程
|
||||
Command::new(openfang_path)
|
||||
.args(["start"])
|
||||
.spawn()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 检测 Gateway 状态
|
||||
|
||||
```typescript
|
||||
// 前端检测
|
||||
async function checkGatewayStatus(): Promise<'running' | 'stopped'> {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:50051/api/health');
|
||||
if (response.ok) {
|
||||
return 'running';
|
||||
}
|
||||
} catch {
|
||||
// Gateway 未运行
|
||||
}
|
||||
return 'stopped';
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 构建发布
|
||||
|
||||
### 8.1 构建命令
|
||||
|
||||
```bash
|
||||
pnpm tauri build
|
||||
```
|
||||
|
||||
输出位置:
|
||||
```
|
||||
desktop/src-tauri/target/release/
|
||||
├── desktop.exe # 可执行文件
|
||||
└── bundle/
|
||||
├── msi/ # Windows 安装包
|
||||
└── nsis/ # NSIS 安装包
|
||||
```
|
||||
|
||||
### 8.2 构建配置
|
||||
|
||||
```json
|
||||
{
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"identifier": "com.zclaw.desktop",
|
||||
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/icon.ico"],
|
||||
"targets": ["msi", "nsis"],
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 减小体积
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[profile.release]
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
strip = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 调试技巧
|
||||
|
||||
### 9.1 启用 DevTools
|
||||
|
||||
开发模式下自动启用,生产模式需要在配置中启用:
|
||||
|
||||
```json
|
||||
{
|
||||
"tauri": {
|
||||
"windows": [{
|
||||
"devtools": true
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 日志记录
|
||||
|
||||
```rust
|
||||
use log::{info, error};
|
||||
|
||||
#[tauri::command]
|
||||
fn some_command() -> Result<String, String> {
|
||||
info!("Command called");
|
||||
// ...
|
||||
Ok("result".to_string())
|
||||
}
|
||||
```
|
||||
|
||||
### 9.3 前端调试
|
||||
|
||||
```typescript
|
||||
// 开发模式下启用详细日志
|
||||
if (import.meta.env.DEV) {
|
||||
console.log('[Debug]', ...args);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 性能优化
|
||||
|
||||
### 10.1 延迟加载
|
||||
|
||||
```typescript
|
||||
// 延迟加载非关键组件
|
||||
const Settings = lazy(() => import('./components/Settings'));
|
||||
const HandsPanel = lazy(() => import('./components/HandsPanel'));
|
||||
```
|
||||
|
||||
### 10.2 状态优化
|
||||
|
||||
```typescript
|
||||
// 使用 selector 避免不必要渲染
|
||||
const messages = useChatStore((state) => state.messages);
|
||||
// 而不是
|
||||
const store = useChatStore();
|
||||
const messages = store.messages; // 会导致所有状态变化都重渲染
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 更新历史
|
||||
|
||||
| 日期 | 变更 |
|
||||
|------|------|
|
||||
| 2026-03-14 | 初始版本 |
|
||||
Reference in New Issue
Block a user