Files
Thing/AI_DEV_GUIDE.md
T
2026-07-13 17:08:38 +08:00

417 lines
9.2 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.
# AI Agent 开发指南
本文档为 AI Agent 开发本项目提供详细的规范和模板,帮助快速理解项目结构、技术栈和开发流程。
## 项目概览
- **项目名称**: Thing
- **技术栈**: Tauri 2 + Vue 3 + Vite + Pinia + shadcn-vue + 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/)
- [shadcn-vue UI Documentation](https://vue.shadcn.org.cn/docs/)
- [Rust Documentation](https://doc.rust-lang.org/)