This commit is contained in:
2026-07-11 15:14:07 +08:00
parent 46b87506f1
commit 935fe35d15
2 changed files with 602 additions and 1 deletions
+416
View File
@@ -0,0 +1,416 @@
# AI Agent 开发指南
本文档为 AI Agent 开发本项目提供详细的规范和模板,帮助快速理解项目结构、技术栈和开发流程。
## 项目概览
- **项目名称**: Thing
- **技术栈**: Tauri 2 + Vue 3 + Vite + Pinia + Naive UI + Rust
- **平台**: Windows
- **包管理**: Bun
## 核心架构
### 模块系统
项目采用模块化架构,每个模块包含前端组件和 Rust 后端命令:
```
src/modules/<module-name>/ # 前端模块
src-tauri/src/commands/<name>.rs # Rust 命令
```
### IPC 通信
前端通过 Tauri API 调用 Rust 命令:
```typescript
import { invoke } from '@tauri-apps/api/core'
// 调用 Rust 命令
const result = await invoke('module_command', { param: 'value' })
```
### 状态管理
使用 Pinia 管理全局状态,每个模块可拥有独立的 store:
```typescript
// src/stores/moduleName.ts
import { defineStore } from 'pinia'
export const useModuleStore = defineStore('moduleName', {
state: () => ({
// 状态定义
}),
actions: {
// 操作方法
}
})
```
## 开发规范
### 命名规范
| 类型 | 格式 | 示例 |
|------|------|------|
| 组件 | PascalCase | `ProxyManager.vue` |
| 函数 | camelCase | `getSystemProxy()` |
| 文件 | kebab-case | `proxy-manager.ts` |
| 常量 | UPPER_CASE | `MAX_HISTORY_COUNT` |
| Rust 模块 | snake_case | `proxy.rs` |
| Tauri 命令 | snake_case | `get_system_proxy` |
### 代码风格
- **TypeScript**: 使用 ESLint,配置在 `.eslintrc.cjs`
- **Rust**: 使用 `cargo fmt` 格式化
- **提交信息**: Conventional Commits 格式
## 模块开发模板
### 前端模块模板
创建 `src/modules/<module-name>/` 目录,包含以下文件:
```typescript
// index.ts - 模块注册
import type { ModuleConfig } from '@/types'
import ModuleComponent from './ModuleComponent.vue'
export const moduleConfig: ModuleConfig = {
id: 'module-name',
name: '模块名称',
icon: 'icon-name',
component: ModuleComponent
}
```
```vue
<!-- ModuleComponent.vue - 主组件 -->
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { useModuleStore } from '@/stores/moduleName'
const store = useModuleStore()
// 组件逻辑
const data = ref(null)
const loadData = async () => {
// 调用 Rust 命令
}
onMounted(() => {
loadData()
})
onUnmounted(() => {
// 清理资源
})
</script>
<template>
<div class="module-container">
<!-- 模块内容 -->
</div>
</template>
<style scoped>
.module-container {
padding: 20px;
}
</style>
```
### Rust 命令模板
创建 `src-tauri/src/commands/<name>.rs`
```rust
// commands/module_name.rs
use serde::Serialize;
use tauri::State;
#[derive(Serialize)]
pub struct CommandResult<T> {
pub success: bool,
pub data: Option<T>,
pub error: Option<String>,
}
#[tauri::command]
pub async fn module_get_data() -> CommandResult<Vec<String>> {
match fetch_data() {
Ok(data) => CommandResult {
success: true,
data: Some(data),
error: None,
},
Err(e) => CommandResult {
success: false,
data: None,
error: Some(e.to_string()),
},
}
}
#[tauri::command]
pub async fn module_set_data(data: String) -> CommandResult<bool> {
match save_data(&data) {
Ok(_) => CommandResult {
success: true,
data: Some(true),
error: None,
},
Err(e) => CommandResult {
success: false,
data: None,
error: Some(e.to_string()),
},
}
}
fn fetch_data() -> Result<Vec<String>, Box<dyn std::error::Error>> {
// 实现逻辑
Ok(vec![])
}
fn save_data(data: &str) -> Result<(), Box<dyn std::error::Error>> {
// 实现逻辑
Ok(())
}
```
### 注册 Rust 命令
`src-tauri/src/lib.rs` 中注册命令:
```rust
// lib.rs
mod commands;
use commands::module_name::{module_get_data, module_set_data};
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
greet,
module_get_data,
module_set_data
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
```
## 常用 Tauri 插件
| 插件 | 用途 | 安装命令 |
|------|------|----------|
| `tauri-plugin-autostart` | 开机自启 | `cargo add tauri-plugin-autostart` |
| `tauri-plugin-tray` | 系统托盘 | `cargo add tauri-plugin-tray` |
| `tauri-plugin-log` | 日志系统 | `cargo add tauri-plugin-log` |
| `tauri-plugin-shell` | 执行命令 | `cargo add tauri-plugin-shell` |
| `tauri-plugin-clipboard-manager` | 剪贴板 | `cargo add tauri-plugin-clipboard-manager` |
| `tauri-plugin-window-state` | 窗口状态 | `cargo add tauri-plugin-window-state` |
## 进程管理
对于需要管理外部进程的模块(如 mihomo、aria2),使用 `tauri-plugin-shell`
```rust
use tauri_plugin_shell::ShellExt;
#[tauri::command]
pub fn start_process(app: tauri::AppHandle) -> Result<(), String> {
let mut cmd = app.shell().command("path/to/executable");
cmd.arg("--config").arg("config.yaml");
let child = cmd.spawn().map_err(|e| e.to_string())?;
// 保存进程句柄
Ok(())
}
```
## 数据存储
### 配置文件
使用 JSON 格式存储在应用数据目录:
```rust
// 获取应用数据目录
let app_dir = app.path().app_data_dir()?;
let config_path = app_dir.join("config.json");
```
### SQLite
对于需要查询的数据(如剪贴板历史),使用 `rusqlite` crate
```toml
# Cargo.toml
rusqlite = { version = "0.30", features = ["bundled"] }
```
## 权限配置
`src-tauri/capabilities/default.json` 中配置权限:
```json
{
"$schema": "../node_modules/@tauri-apps/cli/schemas/desktop-capability.json",
"identifier": "default",
"description": "Default capabilities for the app",
"windows": ["main"],
"permissions": [
"core:default",
"shell:allow-execute",
"shell:allow-spawn",
"path:allow-app-data-dir",
"path:allow-read",
"path:allow-write"
]
}
```
## 调试指南
### 前端调试
- 使用 Chrome DevTools`Ctrl+Shift+I`
- 打印日志:`console.log()`
### Rust 调试
- 使用 `println!()` 输出到终端
- 使用 `dbg!()` 宏调试变量
- 使用 Visual Studio Code 的 Rust 调试插件
### 构建问题排查
1. **Rust 编译错误**:检查 `Cargo.toml` 依赖版本
2. **前端构建错误**:检查 `package.json` 依赖和 TypeScript 类型
3. **Tauri 配置错误**:检查 `tauri.conf.json` 路径和权限配置
## 常见问题
### Windows 路径问题
使用 `std::path::Path` 处理路径,避免硬编码分隔符:
```rust
let path = Path::new("data").join("config.json");
```
### Tauri 2 权限问题
确保在 `capabilities` 中声明所需权限,否则命令调用会失败。
### WebView2 兼容性
确保用户安装了 Microsoft Edge WebView2 Runtime
- 安装包:https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/
## 开发流程
1. **创建模块目录**`src/modules/<module-name>/``src-tauri/src/commands/<name>.rs`
2. **实现前端组件**:创建 Vue 组件和 Pinia store
3. **实现 Rust 命令**:编写后端逻辑和命令
4. **注册命令**:在 `lib.rs` 中注册新命令
5. **配置权限**:更新 `capabilities/default.json`
6. **测试**:运行 `bun run tauri dev` 测试
7. **构建**:运行 `bun run tauri build` 构建生产版本
## 模板代码生成
### 快速生成模块
使用以下命令创建新模块结构:
```bash
# 创建前端模块目录
mkdir -p src/modules/new-module
# 创建 Rust 命令文件
touch src-tauri/src/commands/new_module.rs
```
### 模板文件
复制以下模板快速开始:
**前端组件模板**:
```vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const loading = ref(false)
const error = ref('')
const fetchData = async () => {
loading.value = true
try {
// 调用 Rust 命令
} catch (e) {
error.value = (e as Error).message
} finally {
loading.value = false
}
}
onMounted(() => {
fetchData()
})
</script>
<template>
<n-spin :show="loading">
<div v-if="error" class="error">{{ error }}</div>
<div v-else class="content">
<!-- 内容 -->
</div>
</n-spin>
</template>
<style scoped>
.error { color: #f56c6c; padding: 10px; }
.content { padding: 20px; }
</style>
```
**Rust 命令模板**:
```rust
#[tauri::command]
pub async fn new_module_action() -> Result<serde_json::Value, String> {
// 实现逻辑
Ok(serde_json::json!({}))
}
```
## 注意事项
1. **避免阻塞主线程**Rust 命令使用 `async` 避免阻塞
2. **资源清理**:在组件卸载时清理定时器和事件监听器
3. **错误处理**:所有操作都应有错误处理和用户提示
4. **安全考虑**:避免执行未验证的用户输入作为命令参数
5. **性能优化**:对于高频更新的数据使用 `watch``computed`
## 参考资源
- [Tauri 2 Documentation](https://v2.tauri.app/)
- [Vue 3 Documentation](https://vuejs.org/)
- [Pinia Documentation](https://pinia.vuejs.org/)
- [Naive UI Documentation](https://www.naiveui.com/)
- [Rust Documentation](https://doc.rust-lang.org/)