1 介绍

1.1 定义

01.什么是Tauri
    a.跨平台应用框架
        Tauri是基于Rust和Web技术构建的跨平台桌面应用开发框架
        提供了安全、轻量级、高性能的桌面应用解决方案
    b.核心定位
        旨在让开发者使用Web前端技术构建原生体验的桌面应用
        使用Rust后端处理系统级操作,确保安全性和性能
    c.技术背景
        由Tauri团队发起并维护,解决了Electron等现有框架的性能和体积问题
        融合了Rust的系统级编程能力和现代Web技术的易用性

02.架构革新
    a.WebView集成
        使用操作系统原生的WebView组件,而不是打包整个浏览器
        大幅减少了应用体积和内存占用
        提供更好的性能和系统集成体验
    b.Rust后端
        使用Rust编写后端逻辑,提供内存安全和并发安全
        可以访问底层系统API,性能接近原生应用
        强大的类型系统和内存管理
    c.安全优先设计
        默认启用安全特性,最小权限原则
        细粒度的权限控制
        安全的IPC通信机制

03.发展历程
    a.起步阶段(2019-2020)
        项目正式启动,核心架构设计
        第一个版本发布,基本功能完善
    b.快速发展(2021-2022)
        社区快速成长,生态系统建设
        多个版本迭代,功能不断完善
        企业级应用采用增加
    c.成熟阶段(2023-至今)
        技术架构稳定,API趋于完善
        大规模生产环境应用验证
        与其他框架的对比优势明显

1.2 核心概念

01.Tauri CLI
    a.命令行工具
        提供项目创建、构建、打包等命令
        统一的开发和部署工作流
        集成各种前端框架模板
    b.项目模板
        支持多种前端框架(React、Vue、Svelte等)
        提供TypeScript和JavaScript选项
        可自定义的项目配置
    c.开发工具集成
        热重载和实时预览
        开发者工具和调试支持
        构建优化和性能分析

02.Rust后端
    a.main.rs文件
        应用的主入口点
        系统级API调用处理
        IPC通信接口定义
    b.Cargo生态
        丰富的Rust库生态
        依赖管理和构建系统
        跨平台编译支持
    c.Tauri API
        窗口管理API
        文件系统API
        系统通知API
        网络请求API

03.前端WebView
    a.Web技术栈
        HTML5、CSS3、JavaScript/TypeScript
        支持现代前端框架
        Web标准和API兼容性
    b.系统集成
        原生操作系统WebView
        平台特定的功能和特性
        系统主题和外观适配
    c.前端框架支持
        React集成
        Vue.js集成
        Svelte集成
        原生JavaScript支持

04.IPC机制
    a.通信桥梁
        前端和后端之间的安全通信通道
        类型安全的API接口
        异步消息传递
    b.命令系统
        Rust端定义命令
        JavaScript端调用命令
        返回值和错误处理
    c.事件系统
        后端到前端的事件广播
        前端事件监听和处理
        状态同步机制

1.3 优缺点

01.主要优势
    a.体积小巧
        应用包体积极小,通常只有几MB
        不需要打包整个浏览器引擎
        更快的下载和启动速度
    b.性能优异
        原生WebView性能
        Rust后端的高效执行
        低内存占用
    c.安全可靠
        Rust的内存安全保证
        最小权限原则
        安全沙箱环境
    d.开发友好
        热重载开发体验
        丰富的TypeScript支持
        活跃的社区和文档

02.存在挑战
    a.学习曲线
        需要学习Rust编程语言
        概念和API相对复杂
        调试工具相对有限
    b.生态系统
        相比Electron生态系统较小
        第三方库和插件较少
        解决方案和案例较少
    c.平台差异
        不同操作系统的WebView差异
        某些平台特性支持不完整
        调试和测试复杂度较高
    d.开发工具
        开发工具链相对新
        IDE支持不够完善
        调试体验有待改进

03.适用性分析
    a.适合场景
        性能要求高的桌面应用
        安全性敏感的企业应用
        需要小体积的分发应用
        有Rust技术储备的团队
    b.不适合场景
        团队完全不熟悉Rust
        需要复杂UI交互的应用
        急速原型开发
        对开发速度要求极高的项目
    c.替代方案
        Electron(更成熟但体积大)
        Flutter Desktop(Google支持)
        原生开发(性能最佳)
        PWA(轻量级方案)

1.4 使用场景

01.开发工具类应用
    a.代码编辑器
        轻量级IDE
        专用代码编辑器
        配置管理工具
    b.API工具
        接口测试工具
        数据库客户端
        服务器管理工具
    c.设计工具
        UI设计工具
        原型设计软件
        图标编辑器

02.企业级应用
    a.管理系统
        客户关系管理(CRM)
        企业资源计划(ERP)
        人力资源管理系统
    b.数据分析工具
        商业智能工具
        数据可视化平台
        报表生成系统
    c.协作平台
        团队协作工具
        项目管理软件
        文档管理系统

03.多媒体应用
    a.媒体播放器
        音频播放器
        视频播放器
        流媒体客户端
    b.创意工具
        图像编辑器
        视频编辑工具
        动画制作软件
    c.教育软件
        在线教育平台
        学习管理工具
        知识库应用

04.系统工具
    a.系统监控
        性能监控工具
        日志查看器
        进程管理器
    b.网络工具
        网络分析器
        下载管理器
        FTP客户端
    c.实用工具
        文件管理器
        文本编辑器
        系统配置工具

1.5 架构原理

01.架构层次
    a.前端层
        WebView组件
        Web技术栈渲染
        用户界面交互
    b.IPC层
        安全通信桥梁
        命令路由和调度
        数据序列化传输
    c.后端层
        Rust应用程序逻辑
        系统API调用
        业务规则处理

02.WebView集成
    a.平台WebView
        Windows:WebView2(Edge)
        macOS:WKWebView(Safari)
        Linux:WebKitGTK
    b.渲染性能
        原生渲染引擎
        硬件加速支持
        GPU资源优化
    c.系统集成
        原生菜单和快捷键
        系统主题适配
        文件关联处理

03.Rust应用架构
    a.main函数入口
        应用程序初始化
        WebView创建和配置
        IPC命令注册
    b.命令处理
        异步命令执行
        错误处理和返回
        并发请求管理
    c.状态管理
        应用状态维护
        事件驱动架构
        数据持久化

04.安全架构
    a.权限系统
        细粒度权限控制
        运行时权限检查
        权限审计日志
    b.沙箱隔离
        前端沙箱环境
        后端权限隔离
        IPC安全验证
    c.数据保护
        敏感数据加密
        安全存储机制
        传输数据验证

1.6 技术特性

01.跨平台特性
    a.操作系统支持
        Windows 10及以上版本
        macOS 10.14及以上版本
        主流Linux发行版
    b.平台适配
        原生UI组件集成
        平台特定功能支持
        系统级API访问
    c.构建系统
        统一的构建命令
        多平台交叉编译
        依赖管理和优化

02.性能特性
    a.内存管理
        Rust内存安全保证
        零拷贝优化
        智能垃圾回收
    b.并发处理
        多线程支持
        异步编程模型
        锁无关并发
    c.启动性能
        快速启动时间
        最小化加载开销
        预加载优化

03.开发特性
    a.热重载
        实时预览更改
        前端和后端同时热重载
        开发体验优化
    b.TypeScript支持
        完整类型支持
        API自动生成
        智能代码补全
    c.调试工具
        前端开发者工具
        Rust调试器支持
        性能分析工具

04.集成特性
    a.前端框架支持
        React集成模板
        Vue.js集成模板
        Svelte集成模板
    b.构建工具集成
        Vite构建支持
        Webpack配置
        自定义构建流程
    c.包管理器支持
        npm/yarn支持
        Cargo依赖管理
        版本控制集成

1.7 与Electron对比

01.性能对比
    a.应用体积
        Tauri:通常5-15MB
        Electron:通常50-200MB
        差异主要来自浏览器引擎打包
    b.内存占用
        Tauri:较低内存占用
        Electron:较高内存占用
        多进程架构导致内存消耗差异
    c.启动时间
        Tauri:快速启动
        Electron:相对较慢的启动
        初始化过程复杂度不同

02.安全性对比
    a.安全模型
        Tauri:默认安全,权限最小化
        Electron:需要手动配置安全
        安全理念和实践不同
    b.权限控制
        Tauri:细粒度权限控制
        Electron:相对宽松的权限模型
        权限声明和验证机制
    c.沙箱隔离
        Tauri:强化沙箱环境
        Electron:可选沙箱配置
        隔离级别和控制粒度

03.开发体验对比
    a.技术栈
        Tauri:Rust + Web技术
        Electron:Node.js + Web技术
        后端编程语言差异
    b.生态系统
        Electron:更成熟的生态
        Tauri:快速发展的生态
        第三方库和工具支持
    c.学习曲线
        Tauri:需要学习Rust
        Electron:JavaScript开发者友好
        技术门槛和培训成本

04.选择建议
    a.选择Tauri的情况
        性能和体积是关键因素
        安全性要求高
        有Rust技术储备
        长期维护考虑
    b.选择Electron的情况
        团队熟悉Web技术
        生态和社区支持重要
        快速原型开发需求
        复杂UI交互需求
    c.混合方案
        大型项目可以考虑两种方案
        根据具体模块选择合适技术
        团队技术栈和项目需求匹配
        成本效益分析

2 核心组件

2.1 汇总:4个核心组件

00.总结
    a.Tauri CLI
        强大的命令行工具,提供项目创建、构建、打包等完整开发工作流
    b.Rust后端
        基于Rust语言的后端服务,处理系统级操作和业务逻辑
    c.前端WebView
        基于操作系统原生WebView的Web前端界面
    d.IPC机制
        安全的前后端通信桥梁,实现类型安全的数据交换

2.2 Tauri CLI

01.安装和初始化
    a.CLI安装
        # 使用npm安装
        npm install -g @tauri-apps/cli

        # 使用yarn安装
        yarn global add @tauri-apps/cli

        # 使用Cargo安装
        cargo install tauri-cli
    b.项目创建
        # 创建新项目
        npx create-tauri-app my-app

        # 选择前端框架
        ? What framework are you using? ›
        ❯ Vanilla
          Vue
          React
          Svelte
          Angular

        # 配置项目信息
        ? Package name: my-app
        ? Window title: My App
        ? Dist directory: ../dist

        # 使用现有项目
        cd existing-project
        npm install -D @tauri-apps/cli
        npx tauri init
    c.基本命令
        # 开发模式
        npm run tauri dev
        npx tauri dev

        # 构建应用
        npm run tauri build
        npx tauri build

        # 查看帮助
        npx tauri --help
        npx tauri build --help
        ---

02.项目结构
    a.目录组织
        my-app/
        ├── src-tauri/              # Tauri后端代码
        │   ├── src/               # Rust源代码
        │   │   └── main.rs       # 主入口文件
        │   ├── icons/            # 应用图标
        │   ├── target/           # 编译输出目录
        │   ├── Cargo.toml        # Rust依赖配置
        │   └── tauri.conf.json   # Tauri配置文件
        ├── src/                  # 前端源代码
        │   ├── index.html        # 入口HTML
        │   ├── style.css         # 样式文件
        │   └── script.js         # JavaScript文件
        ├── dist/                 # 前端构建输出
        ├── node_modules/         # Node.js依赖
        ├── package.json         # 项目配置
        └── tauri.conf.json      # 全局Tauri配置
    b.配置文件
        # tauri.conf.json - 主要配置
        {
          "build": {
            "beforeBuildCommand": "npm run build",
            "beforeDevCommand": "npm run dev",
            "devPath": "http://localhost:3000",
            "distDir": "../dist"
          },
          "package": {
            "productName": "My App",
            "version": "0.1.0"
          },
          "tauri": {
            "allowlist": {
              "all": false,
              "shell": {
                "all": false,
                "open": true
              }
            },
            "bundle": {
              "active": true,
              "targets": "all",
              "identifier": "com.tauri.my-app",
              "icon": [
                "icons/32x32.png",
                "icons/128x128.png",
                "icons/[email protected]",
                "icons/icon.icns",
                "icons/icon.ico"
              ]
            },
            "security": {
              "csp": null
            },
            "windows": [
              {
                "fullscreen": false,
                "height": 600,
                "resizable": true,
                "title": "My App",
                "width": 800
              }
            ]
          }
        }
    c.Cargo配置
        # Cargo.toml - Rust依赖配置
        [package]
        name = "my-app"
        version = "0.1.0"
        description = "A Tauri App"
        authors = ["you"]
        license = ""
        repository = ""
        edition = "2021"

        [build-dependencies]
        tauri-build = { version = "1.0", features = [] }

        [dependencies]
        tauri = { version = "1.0", features = ["shell-open"] }
        serde = { version = "1.0", features = ["derive"] }
        serde_json = "1.0"

        [features]
        default = ["custom-protocol"]
        custom-protocol = ["tauri/custom-protocol"]
        ---

03.开发工具集成
    a.开发服务器
        # 自动启动前端开发服务器
        npm run tauri dev

        # 配置开发服务器
        "beforeDevCommand": "npm run dev",
        "devPath": "http://localhost:3000",

        # 热重载配置
        watch: true,
        reload: true
    b.调试工具
        # 前端调试
        - 开发者工具自动启用
        - 支持断点调试
        - 控制台日志查看

        # Rust调试
        - VS Code集成
        - 断点调试
        - 内存查看
    c.构建优化
        # 开发构建
        npx tauri dev --debug

        # 生产构建
        npx tauri build --release

        # 优化选项
        targetTriple: "x86_64-pc-windows-msvc",
        debug: false

2.3 Rust后端

01.main.rs核心结构
    a.应用程序入口
        // src-tauri/src/main.rs
        #![cfg_attr(
            not(debug_assertions),
            windows_subsystem = "windows"
        )]

        use tauri::Manager;

        #[derive(Clone, serde::Serialize)]
        struct Payload {
            args: Vec<String>,
            cwd: String,
        }

        fn main() {
            tauri::Builder::default()
                .setup(|app| {
                    // 应用启动时的初始化逻辑
                    println!("应用正在启动...");

                    // 获取主窗口
                    let window = app.get_window("main").unwrap();

                    // 设置窗口标题
                    window.set_title("My Tauri App")?;

                    Ok(())
                })
                .invoke_handler(tauri::generate_handler![
                    greet,
                    get_system_info,
                    read_file,
                    write_file
                ])
                .run(tauri::generate_context!())
                .expect("error while running tauri application");
        }
    b.命令定义
        #[tauri::command]
        fn greet(name: &str) -> String {
            format!("Hello, {}! You've been greeted from Rust!", name)
        }

        #[tauri::command]
        async fn get_system_info() -> Result<SystemInfo, String> {
            let info = SystemInfo {
                os: std::env::consts::OS.to_string(),
                arch: std::env::consts::ARCH.to_string(),
                version: env!("CARGO_PKG_VERSION").to_string(),
            };
            Ok(info)
        }

        #[derive(serde::Serialize)]
        struct SystemInfo {
            os: String,
            arch: String,
            version: String,
        }
    c.错误处理
        #[tauri::command]
        async fn read_file(path: String) -> Result<String, String> {
            use std::fs;
            use std::io::Read;

            // 安全检查
            if path.contains("..") || path.starts_with('/') {
                return Err("不安全的文件路径".to_string());
            }

            match fs::File::open(&path) {
                Ok(mut file) => {
                    let mut content = String::new();
                    match file.read_to_string(&mut content) {
                        Ok(_) => Ok(content),
                        Err(e) => Err(format!("读取文件失败: {}", e)),
                    }
                }
                Err(e) => Err(format!("打开文件失败: {}", e)),
            }
        }

        #[tauri::command]
        async fn write_file(path: String, content: String) -> Result<(), String> {
            use std::fs::File;
            use std::io::Write;

            // 安全检查
            if path.contains("..") || path.starts_with('/') {
                return Err("不安全的文件路径".to_string());
            }

            match File::create(&path) {
                Ok(mut file) => {
                    match file.write_all(content.as_bytes()) {
                        Ok(_) => Ok(()),
                        Err(e) => Err(format!("写入文件失败: {}", e)),
                    }
                }
                Err(e) => Err(format!("创建文件失败: {}", e)),
            }
        }
        ---

02.异步编程
    a.Tokio异步运行时
        # Cargo.toml
        [dependencies]
        tokio = { version = "1", features = ["full"] }

        # main.rs
        use tauri::async_runtime;

        #[tauri::command]
        async fn fetch_data(url: String) -> Result<String, String> {
            let client = reqwest::Client::new();

            match client.get(&url).send().await {
                Ok(response) => {
                    match response.text().await {
                        Ok(text) => Ok(text),
                        Err(e) => Err(format!("读取响应失败: {}", e)),
                    }
                }
                Err(e) => Err(format!("请求失败: {}", e)),
            }
        }

        #[tauri::command]
        async fn background_task() -> Result<String, String> {
            async_runtime::spawn(async move {
                // 长时间运行的后台任务
                tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
                "后台任务完成".to_string()
            }).await.map_err(|e| e.to_string())
        }
    b.并发处理
        use std::sync::Arc;
        use tokio::sync::Mutex;
        use std::collections::HashMap;

        type AppState = Arc<Mutex<HashMap<String, String>>>;

        #[tauri::command]
        async fn set_value(
            state: tauri::State<'_, AppState>,
            key: String,
            value: String,
        ) -> Result<(), String> {
            let mut map = state.lock().await;
            map.insert(key, value);
            Ok(())
        }

        #[tauri::command]
        async fn get_value(
            state: tauri::State<'_, AppState>,
            key: String,
        ) -> Result<Option<String>, String> {
            let map = state.lock().await;
            Ok(map.get(&key).cloned())
        }

        // 在main函数中初始化状态
        fn main() {
            let app_state: AppState = Arc::new(Mutex::new(HashMap::new()));

            tauri::Builder::default()
                .manage(app_state)
                .invoke_handler(tauri::generate_handler![set_value, get_value])
                .run(tauri::generate_context!())
                .expect("error while running tauri application");
        }
    c.定时任务
        use tokio::time::{interval, Duration};

        #[tauri::command]
        fn start_periodic_task(app_handle: tauri::AppHandle) -> Result<(), String> {
            async_runtime::spawn(async move {
                let mut interval = interval(Duration::from_secs(10));

                loop {
                    interval.tick().await;

                    // 发送事件到前端
                    if let Some(window) = app_handle.get_window("main") {
                        let _ = window.emit("periodic-update", "定时任务执行");
                    }
                }
            });

            Ok(())
        }
        ---

03.系统集成
    a.文件系统操作
        use std::fs;
        use std::path::Path;
        use walkdir::WalkDir;

        #[tauri::command]
        async fn list_files(directory: String) -> Result<Vec<String>, String> {
            let mut files = Vec::new();

            // 安全检查
            if !Path::new(&directory).exists() {
                return Err("目录不存在".to_string());
            }

            for entry in WalkDir::new(&directory)
                .max_depth(1)
                .into_iter()
                .filter_map(|e| e.ok())
            {
                if entry.file_type().is_file() {
                    if let Some(path_str) = entry.path().to_str() {
                        files.push(path_str.to_string());
                    }
                }
            }

            Ok(files)
        }

        #[tauri::command]
        async fn create_directory(path: String) -> Result<(), String> {
            match fs::create_dir_all(&path) {
                Ok(_) => Ok(()),
                Err(e) => Err(format!("创建目录失败: {}", e)),
            }
        }
    b.系统信息获取
        use sysinfo::{System, SystemExt, ProcessExt, CpuExt};

        #[tauri::command]
        async fn get_system_stats() -> Result<SystemStats, String> {
            let mut system = System::new_all();
            system.refresh_all();

            let stats = SystemStats {
                cpu_usage: system.global_cpu_info().cpu_usage(),
                memory_total: system.total_memory(),
                memory_used: system.used_memory(),
                process_count: system.processes().len(),
                uptime: system.uptime(),
            };

            Ok(stats)
        }

        #[derive(serde::Serialize)]
        struct SystemStats {
            cpu_usage: f32,
            memory_total: u64,
            memory_used: u64,
            process_count: usize,
            uptime: u64,
        }
    c.网络操作
        #[tauri::command]
        async fn check_internet() -> Result<bool, String> {
            match tokio::net::TcpStream::connect("8.8.8.8:80").await {
                Ok(_) => Ok(true),
                Err(_) => Ok(false),
            }
        }

        #[tauri::command]
        async fn get_local_ip() -> Result<String, String> {
            match local_ip::get() {
                Ok(ip) => Ok(ip.to_string()),
                Err(e) => Err(format!("获取本地IP失败: {}", e)),
            }
        }

2.4 前端WebView

01.Web技术集成
    a.基础HTML结构
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Tauri App</title>
            <style>
                body {
                    font-family: Arial, sans-serif;
                    margin: 0;
                    padding: 20px;
                    background-color: #f5f5f5;
                }

                .container {
                    max-width: 800px;
                    margin: 0 auto;
                    background: white;
                    padding: 20px;
                    border-radius: 8px;
                    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                }

                .button {
                    background: #007bff;
                    color: white;
                    border: none;
                    padding: 10px 20px;
                    border-radius: 4px;
                    cursor: pointer;
                    margin: 5px;
                }

                .button:hover {
                    background: #0056b3;
                }

                .log {
                    background: #f8f9fa;
                    border: 1px solid #dee2e6;
                    border-radius: 4px;
                    padding: 10px;
                    margin-top: 20px;
                    max-height: 300px;
                    overflow-y: auto;
                }
            </style>
        </head>
        <body>
            <div class="container">
                <h1>我的Tauri应用</h1>
                <div>
                    <button class="button" onclick="greet()">问候</button>
                    <button class="button" onclick="getSystemInfo()">系统信息</button>
                    <button class="button" onclick="readFile()">读取文件</button>
                    <button class="button" onclick="writeFile()">写入文件</button>
                </div>
                <div id="output" class="log"></div>
            </div>

            <script src="script.js"></script>
        </body>
        </html>
    b.JavaScript API调用
        // script.js
        const { invoke } = window.__TAURI__.tauri;
        const { listen } = window.__TAURI__.event;

        // 日志输出函数
        function log(message) {
            const output = document.getElementById('output');
            output.innerHTML += `<div>${new Date().toLocaleTimeString()}: ${message}</div>`;
            output.scrollTop = output.scrollHeight;
        }

        // 问候功能
        async function greet() {
            try {
                const response = await invoke('greet', { name: 'Tauri' });
                log(response);
            } catch (error) {
                log(`错误: ${error}`);
            }
        }

        // 获取系统信息
        async function getSystemInfo() {
            try {
                const info = await invoke('get_system_info');
                log(`操作系统: ${info.os}, 架构: ${info.arch}, 版本: ${info.version}`);
            } catch (error) {
                log(`错误: ${error}`);
            }
        }

        // 读取文件
        async function readFile() {
            try {
                const content = await invoke('read_file', {
                    path: 'test.txt'
                });
                log(`文件内容: ${content}`);
            } catch (error) {
                log(`错误: ${error}`);
            }
        }

        // 写入文件
        async function writeFile() {
            try {
                await invoke('write_file', {
                    path: 'test.txt',
                    content: 'Hello from Tauri!'
                });
                log('文件写入成功');
            } catch (error) {
                log(`错误: ${error}`);
            }
        }

        // 监听后台事件
        async function setupEventListeners() {
            await listen('periodic-update', (event) => {
                log(`收到事件: ${event.payload}`);
            });
        }

        // 页面加载时设置事件监听
        window.addEventListener('DOMContentLoaded', () => {
            setupEventListeners();
            log('应用已准备就绪');
        });
    c.状态管理
        // 简单的状态管理
        class AppState {
            constructor() {
                this.state = {
                    user: null,
                    files: [],
                    systemInfo: null
                };
                this.listeners = [];
            }

            setState(newState) {
                this.state = { ...this.state, ...newState };
                this.notifyListeners();
            }

            getState() {
                return this.state;
            }

            subscribe(listener) {
                this.listeners.push(listener);
                return () => {
                    this.listeners = this.listeners.filter(l => l !== listener);
                };
            }

            notifyListeners() {
                this.listeners.forEach(listener => listener(this.state));
            }
        }

        const appState = new AppState();

        // 订阅状态变化
        appState.subscribe((state) => {
            console.log('状态变化:', state);
        });
        ---

02.Tauri JavaScript API
    a.核心API
        const { appWindow } = window.__TAURI__.window;
        const { invoke } = window.__TAURI__.tauri;
        const { listen, emit } = window.__TAURI__.event;
        const { fs } = window.__TAURI__;
        const { dialog } = window.__TAURI__;

        // 窗口操作
        async function windowOperations() {
            // 获取窗口状态
            const isMaximized = await appWindow.isMaximized();
            console.log('窗口是否最大化:', isMaximized);

            // 窗口控制
            await appWindow.minimize();
            await appWindow.maximize();
            await appWindow.unmaximize();
            await appWindow.close();

            // 窗口信息
            const position = await appWindow.position();
            const size = await appWindow.size();
            console.log('窗口位置:', position);
            console.log('窗口大小:', size);
        }

        // 文件操作
        async function fileOperations() {
            // 读取文本文件
            const content = await fs.readTextFile('example.txt');
            console.log('文件内容:', content);

            // 写入文本文件
            await fs.writeTextFile('example.txt', 'Hello Tauri!');

            // 文件信息
            const fileInfo = await fs.stat('example.txt');
            console.log('文件信息:', fileInfo);

            // 目录操作
            const files = await fs.readDir('.');
            console.log('目录文件:', files);
        }

        // 对话框
        async function dialogOperations() {
            // 打开文件对话框
            const selected = await dialog.open({
                multiple: false,
                filters: [
                    {
                        name: 'Text Files',
                        extensions: ['txt', 'md']
                    }
                ]
            });

            console.log('选择的文件:', selected);

            // 保存文件对话框
            const savePath = await dialog.save({
                filters: [
                    {
                        name: 'Text Files',
                        extensions: ['txt']
                    }
                ]
            });

            console.log('保存路径:', savePath);
        }
    b.事件系统
        // 监听事件
        async function setupEventListeners() {
            // 监听窗口事件
            await appWindow.listen('tauri://resize', () => {
                console.log('窗口大小改变');
            });

            await appWindow.listen('tauri://move', () => {
                console.log('窗口位置改变');
            });

            // 监听应用事件
            await listen('custom-event', (event) => {
                console.log('自定义事件:', event.payload);
            });

            // 一次性事件监听
            await appWindow.once('tauri://close-requested', () => {
                console.log('窗口即将关闭');
            });
        }

        // 发送事件
        async function sendEvents() {
            // 发送到当前窗口
            await emit('custom-event', { message: 'Hello from frontend!' });

            // 发送到所有窗口
            await emitToAll('global-event', { data: 'global message' });
        }

        // 事件监听器清理
        async function cleanup() {
            const unlisten = await appWindow.listen('custom-event', (event) => {
                console.log(event.payload);
            });

            // 移除监听器
            unlisten();
        }
    c.应用API
        const { app } = window.__TAURI__;

        // 应用信息
        async function getAppInfo() {
            const appName = await app.getName();
            const appVersion = await app.getVersion();
            const tauriVersion = await app.getTauriVersion();

            console.log('应用名称:', appName);
            console.log('应用版本:', appVersion);
            console.log('Tauri版本:', tauriVersion);
        }

        // 应用控制
        async function appControl() {
            // 退出应用
            await app.quit();

            // 隐藏应用
            await app.hide();

            // 显示应用
            await app.show();
        }
        ---

03.前端框架集成
    a.React集成
        // App.jsx
        import React, { useState, useEffect } from 'react';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        function App() {
            const [message, setMessage] = useState('');
            const [systemInfo, setSystemInfo] = useState({});

            useEffect(() => {
                // 设置事件监听
                const setupListeners = async () => {
                    await listen('tauri://resize', () => {
                        console.log('窗口大小改变');
                    });
                };

                setupListeners();

                // 获取系统信息
                invoke('get_system_info')
                    .then(setSystemInfo)
                    .catch(console.error);
            }, []);

            const handleGreet = async () => {
                try {
                    const response = await invoke('greet', { name: 'React' });
                    setMessage(response);
                } catch (error) {
                    setMessage(`错误: ${error}`);
                }
            };

            return (
                <div className="App">
                    <h1>Tauri + React</h1>
                    <div>
                        <button onClick={handleGreet}>问候</button>
                    </div>
                    {message && <p>{message}</p>}
                    <div>
                        <h3>系统信息:</h3>
                        <p>操作系统: {systemInfo.os}</p>
                        <p>架构: {systemInfo.arch}</p>
                        <p>版本: {systemInfo.version}</p>
                    </div>
                </div>
            );
        }

        export default App;
    b.Vue集成
        <!-- App.vue -->
        <template>
            <div class="app">
                <h1>Tauri + Vue</h1>
                <div class="controls">
                    <button @click="greet">问候</button>
                    <button @click="getSystemInfo">系统信息</button>
                </div>

                <div v-if="message" class="message">
                    {{ message }}
                </div>

                <div v-if="systemInfo.os" class="system-info">
                    <h3>系统信息:</h3>
                    <p>操作系统: {{ systemInfo.os }}</p>
                    <p>架构: {{ systemInfo.arch }}</p>
                    <p>版本: {{ systemInfo.version }}</p>
                </div>
            </div>
        </template>

        <script>
        import { ref, onMounted } from 'vue';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        export default {
            name: 'App',
            setup() {
                const message = ref('');
                const systemInfo = ref({});

                const greet = async () => {
                    try {
                        const response = await invoke('greet', { name: 'Vue' });
                        message.value = response;
                    } catch (error) {
                        message.value = `错误: ${error}`;
                    }
                };

                const getSystemInfo = async () => {
                    try {
                        const info = await invoke('get_system_info');
                        systemInfo.value = info;
                    } catch (error) {
                        console.error('获取系统信息失败:', error);
                    }
                };

                onMounted(async () => {
                    // 设置事件监听
                    await listen('tauri://resize', () => {
                        console.log('窗口大小改变');
                    });

                    // 获取系统信息
                    await getSystemInfo();
                });

                return {
                    message,
                    systemInfo,
                    greet,
                    getSystemInfo
                };
            }
        };
        </script>

        <style>
        .app {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }

        .controls {
            margin: 20px 0;
        }

        .controls button {
            margin-right: 10px;
            padding: 8px 16px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .message {
            margin: 20px 0;
            padding: 10px;
            background: #f8f9fa;
            border-radius: 4px;
        }

        .system-info {
            margin-top: 20px;
            padding: 15px;
            background: #e9ecef;
            border-radius: 4px;
        }
        </style>
    c.Svelte集成
        <!-- App.svelte -->
        <script>
        import { onMount } from 'svelte';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        let message = '';
        let systemInfo = {};

        const greet = async () => {
            try {
                const response = await invoke('greet', { name: 'Svelte' });
                message = response;
            } catch (error) {
                message = `错误: ${error}`;
            }
        };

        const getSystemInfo = async () => {
            try {
                const info = await invoke('get_system_info');
                systemInfo = info;
            } catch (error) {
                console.error('获取系统信息失败:', error);
            }
        };

        onMount(async () => {
            // 设置事件监听
            await listen('tauri://resize', () => {
                console.log('窗口大小改变');
            });

            // 获取系统信息
            await getSystemInfo();
        });
        </script>

        <main>
            <h1>Tauri + Svelte</h1>
            <div class="controls">
                <button on:click={greet}>问候</button>
                <button on:click={getSystemInfo}>系统信息</button>
            </div>

            {#if message}
                <div class="message">{message}</div>
            {/if}

            {#if systemInfo.os}
                <div class="system-info">
                    <h3>系统信息:</h3>
                    <p>操作系统: {systemInfo.os}</p>
                    <p>架构: {systemInfo.arch}</p>
                    <p>版本: {systemInfo.version}</p>
                </div>
            {/if}
        </main>

        <style>
        main {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }

        .controls {
            margin: 20px 0;
        }

        .controls button {
            margin-right: 10px;
            padding: 8px 16px;
            background: #ff3e00;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .message {
            margin: 20px 0;
            padding: 10px;
            background: #f8f9fa;
            border-radius: 4px;
        }

        .system-info {
            margin-top: 20px;
            padding: 15px;
            background: #fff3cd;
            border-radius: 4px;
        }
        </style>

2.5 IPC机制

01.命令系统
    a.Rust端命令定义
        #[tauri::command]
        async fn complex_operation(
            param1: String,
            param2: i32,
            param3: Vec<String>
        ) -> Result<ComplexResult, String> {
            // 参数验证
            if param1.is_empty() {
                return Err("参数1不能为空".to_string());
            }

            if param2 < 0 || param2 > 100 {
                return Err("参数2必须在0-100之间".to_string());
            }

            // 复杂业务逻辑
            let result = ComplexResult {
                message: format!("处理完成: {} - {} - {:?}", param1, param2, param3),
                success: true,
                data: param3.iter().map(|s| s.to_uppercase()).collect(),
            };

            Ok(result)
        }

        #[derive(serde::Serialize)]
        struct ComplexResult {
            message: String,
            success: bool,
            data: Vec<String>,
        }
    b.JavaScript端调用
        async function performComplexOperation() {
            try {
                const result = await invoke('complex_operation', {
                    param1: 'test',
                    param2: 50,
                    param3: ['hello', 'world', 'tauri']
                });

                console.log('操作结果:', result);
                console.log('消息:', result.message);
                console.log('数据:', result.data);
            } catch (error) {
                console.error('操作失败:', error);
            }
        }
    c.类型安全
        // 使用TypeScript定义类型
        interface ComplexResult {
            message: string;
            success: boolean;
            data: string[];
        }

        async function performComplexOperation(): Promise<ComplexResult> {
            const result = await invoke<ComplexResult>('complex_operation', {
                param1: 'test',
                param2: 50,
                param3: ['hello', 'world', 'tauri']
            });

            return result;
        }
        ---

02.事件系统
    a.事件发送
        use tauri::{Manager, WindowEvent};

        #[tauri::command]
        async fn emit_event_to_all(
            app_handle: tauri::AppHandle,
            event_name: String,
            payload: serde_json::Value
        ) -> Result<(), String> {
            app_handle.emit_all(&event_name, payload)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        async fn emit_event_to_window(
            window: tauri::Window,
            event_name: String,
            payload: serde_json::Value
        ) -> Result<(), String> {
            window.emit(&event_name, payload)
                .map_err(|e| e.to_string())
        }
    b.事件监听
        // 监听特定事件
        async function setupEventListeners() {
            await listen('user-login', (event) => {
                console.log('用户登录事件:', event.payload);
                updateUI(event.payload);
            });

            await listen('file-changed', (event) => {
                console.log('文件变更事件:', event.payload);
                refreshFileList();
            });

            await listen('notification', (event) => {
                showNotification(event.payload);
            });
        }

        function updateUI(userData) {
            document.getElementById('username').textContent = userData.name;
            document.getElementById('user-avatar').src = userData.avatar;
        }

        function showNotification(notification) {
            // 使用Web Notification API
            if ('Notification' in window) {
                new Notification(notification.title, {
                    body: notification.body,
                    icon: notification.icon
                });
            }
        }
    c.双向通信
        // Rust端发送请求到前端
        #[tauri::command]
        async fn request_user_data(
            window: tauri::Window
        ) -> Result<serde_json::Value, String> {
            // 发送请求到前端
            let response = window.emit('request-user-data', {});

            // 这里需要实现一个机制等待前端响应
            // 实际项目中可以使用Promise或者回调

            Ok(serde_json::json!({"status": "requested"}))
        }

        // JavaScript端响应请求
        async function setupRequestHandlers() {
            await listen('request-user-data', async (event) => {
                const userData = await fetchUserData();

                // 发送响应回去
                await emit('user-data-response', userData);
            });
        }

        async function fetchUserData() {
            // 从本地存储或API获取用户数据
            return {
                id: 1,
                name: 'John Doe',
                email: '[email protected]'
            };
        }
        ---

03.安全通信
    a.参数验证
        #[derive(serde::Deserialize)]
        struct SafeFileOperation {
            path: String,
            content: Option<String>,
        }

        impl SafeFileOperation {
            fn validate(&self) -> Result<(), String> {
                // 路径安全检查
                if self.path.contains("..") {
                    return Err("路径包含非法字符".to_string());
                }

                // 检查路径长度
                if self.path.len() > 255 {
                    return Err("路径过长".to_string());
                }

                // 检查文件扩展名
                if let Some(ext) = std::path::Path::new(&self.path).extension() {
                    match ext.to_str() {
                        Some("txt") | Some("json") | Some("md") => {},
                        _ => return Err("不支持的文件类型".to_string()),
                    }
                }

                Ok(())
            }
        }

        #[tauri::command]
        async fn safe_file_operation(
            operation: SafeFileOperation
        ) -> Result<String, String> {
            // 验证参数
            operation.validate()?;

            // 执行安全操作
            match operation.content {
                Some(content) => {
                    std::fs::write(&operation.path, content)
                        .map_err(|e| e.to_string())?;
                    Ok("文件写入成功".to_string())
                }
                None => {
                    let content = std::fs::read_to_string(&operation.path)
                        .map_err(|e| e.to_string())?;
                    Ok(content)
                }
            }
        }
    b.权限控制
        // tauri.conf.json 权限配置
        {
          "tauri": {
            "allowlist": {
              "all": false,
              "fs": {
                "readFile": true,
                "writeFile": true,
                "readDir": true,
                "scope": ["$APPDATA/*", "$DOCUMENT/*"]
              },
              "dialog": {
                "open": true,
                "save": true
              },
              "notification": {
                "all": true
              }
            }
          }
        }

        // Rust端权限检查
        #[tauri::command]
        async fn protected_operation(
            window: tauri::Window,
            user_id: String
        ) -> Result<String, String> {
            // 检查用户权限
            if !check_user_permission(&user_id) {
                return Err("权限不足".to_string());
            }

            // 记录操作日志
            log_operation(&window, "protected_operation", &user_id);

            // 执行受保护的操作
            perform_protected_task()
        }

        fn check_user_permission(user_id: &str) -> bool {
            // 实现权限检查逻辑
            // 这里可以查询数据库或检查配置文件
            user_id == "admin"
        }

        fn log_operation(window: &tauri::Window, operation: &str, user_id: &str) {
            let log_entry = format!(
                "操作: {}, 用户: {}, 时间: {}",
                operation,
                user_id,
                chrono::Utc::now().to_rfc3339()
            );

            let _ = window.emit("operation-log", log_entry);
        }

2.6 安全模型

01.安全沙箱
    a.前端沙箱限制
        - 禁用Node.js API访问
        - 限制文件系统访问
        - 控制网络请求
        - 禁用eval()和Function构造器
        - CSP(内容安全策略)支持

    b.权限最小化原则
        // tauri.conf.json 安全配置
        {
          "tauri": {
            "security": {
              "csp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
            },
            "allowlist": {
              "all": false,
              "shell": {
                "open": true
              },
              "dialog": {
                "open": true,
                "save": true
              }
            }
          }
        }

    c.安全的IPC通信
        // 使用类型安全的命令
        #[tauri::command]
        async fn secure_command(
            window: tauri::Window,
            user_input: String
        ) -> Result<String, String> {
            // 输入验证
            if user_input.len() > 1000 {
                return Err("输入过长".to_string());
            }

            // 检查恶意内容
            if user_input.contains("<script>") || user_input.contains("javascript:") {
                return Err("检测到恶意内容".to_string());
            }

            // 清理输入
            let clean_input = sanitize_input(&user_input);

            // 记录操作
            log_security_event(&window, "secure_command", &clean_input);

            Ok(format!("处理完成: {}", clean_input))
        }

        fn sanitize_input(input: &str) -> String {
            input
                .replace('<', "&lt;")
                .replace('>', "&gt;")
                .replace('"', "&quot;")
                .replace('\'', "&#x27;")
                .replace('/', "&#x2F;")
        }
        ---

02.数据保护
    a.敏感数据处理
        #[tauri::command]
        async fn encrypt_sensitive_data(
            data: String,
            key: String
        ) -> Result<String, String> {
            // 验证密钥强度
            if key.len() < 16 {
                return Err("密钥长度不足".to_string());
            }

            // 加密数据
            let encrypted = encrypt_data(&data, &key)
                .map_err(|e| e.to_string())?;

            Ok(encrypted)
        }

        #[tauri::command]
        async fn decrypt_sensitive_data(
            encrypted_data: String,
            key: String
        ) -> Result<String, String> {
            // 验证密钥
            if key.len() < 16 {
                return Err("密钥长度不足".to_string());
            }

            // 解密数据
            let decrypted = decrypt_data(&encrypted_data, &key)
                .map_err(|e| e.to_string())?;

            Ok(decrypted)
        }

        // 实际加密实现(使用ring或rustcrypto)
        fn encrypt_data(data: &str, key: &str) -> Result<String, Box<dyn std::error::Error>> {
            // 这里应该实现实际的加密逻辑
            // 示例中使用简单的base64编码
            Ok(base64::encode(data))
        }

        fn decrypt_data(encrypted_data: &str, key: &str) -> Result<String, Box<dyn std::error::Error>> {
            // 这里应该实现实际的解密逻辑
            // 示例中使用简单的base64解码
            let decoded = base64::decode(encrypted_data)?;
            Ok(String::from_utf8(decoded)?)
        }
    b.安全存储
        #[tauri::command]
        async fn store_securely(
            key: String,
            value: String
        ) -> Result<(), String> {
            // 使用系统安全存储
            #[cfg(target_os = "windows")]
            {
                // Windows DPAPI
                use std::fs;
                use std::path::PathBuf;

                let app_data = dirs::data_dir()
                    .ok_or("无法获取数据目录")?;
                let storage_path = app_data.join("my-secure-app");

                std::fs::create_dir_all(&storage_path)
                    .map_err(|e| e.to_string())?;

                // 在实际应用中应该加密存储
                let file_path = storage_path.join(format!("{}.secure", key));
                std::fs::write(file_path, value)
                    .map_err(|e| e.to_string())?;
            }

            #[cfg(target_os = "macos")]
            {
                // macOS Keychain
                // 实际实现需要使用keychain库
            }

            #[cfg(target_os = "linux")]
            {
                // Linux Secret Service 或 libsecret
                // 实际实现需要使用相应的库
            }

            Ok(())
        }
    c.安全传输
        // 确保所有网络请求使用HTTPS
        #[tauri::command]
        async fn secure_api_call(
            url: String,
            data: serde_json::Value
        ) -> Result<serde_json::Value, String> {
            // 验证URL
            if !url.starts_with("https://") {
                return Err("只允许HTTPS请求".to_string());
            }

            let client = reqwest::Client::builder()
                .timeout(std::time::Duration::from_secs(30))
                .build()
                .map_err(|e| e.to_string())?;

            let response = client
                .post(&url)
                .header("Content-Type", "application/json")
                .json(&data)
                .send()
                .await
                .map_err(|e| e.to_string())?;

            if response.status().is_success() {
                let result = response.json().await
                    .map_err(|e| e.to_string())?;
                Ok(result)
            } else {
                Err(format!("API调用失败: {}", response.status()))
            }
        }
        ---

03.审计和监控
    a.安全事件日志
        use std::fs::OpenOptions;
        use std::io::Write;

        #[derive(serde::Serialize)]
        struct SecurityEvent {
            timestamp: String,
            window_id: Option<String>,
            operation: String,
            user_id: Option<String>,
            details: serde_json::Value,
        }

        fn log_security_event(
            window: &tauri::Window,
            operation: &str,
            details: serde_json::Value
        ) {
            let event = SecurityEvent {
                timestamp: chrono::Utc::now().to_rfc3339(),
                window_id: Some(window.label().to_string()),
                operation: operation.to_string(),
                user_id: get_current_user_id(window),
                details,
            };

            // 异步写入日志
            let event_json = serde_json::to_string(&event).unwrap();
            tokio::spawn(async move {
                if let Err(e) = write_security_log(&event_json) {
                    eprintln!("写入安全日志失败: {}", e);
                }
            });
        }

        fn write_security_log(event_json: &str) -> std::io::Result<()> {
            let app_data = dirs::data_dir()
                .ok_or(std::io::Error::new(std::io::ErrorKind::NotFound, "数据目录不存在"))?;

            let log_dir = app_data.join("my-secure-app/logs");
            std::fs::create_dir_all(&log_dir)?;

            let log_file = log_dir.join("security.log");
            let mut file = OpenOptions::new()
                .create(true)
                .append(true)
                .open(&log_file)?;

            writeln!(file, "{}", event_json)
        }
    b.异常检测
        use std::collections::HashMap;
        use std::time::{Duration, Instant};

        struct SecurityMonitor {
            failed_attempts: HashMap<String, Vec<Instant>>,
            suspicious_patterns: Vec<String>,
        }

        impl SecurityMonitor {
            fn new() -> Self {
                Self {
                    failed_attempts: HashMap::new(),
                    suspicious_patterns: vec![
                        "SELECT * FROM".to_string(),
                        "DROP TABLE".to_string(),
                        "<script>".to_string(),
                    ],
                }
            }

            fn check_failed_attempts(&mut self, identifier: &str) -> Result<(), String> {
                let now = Instant::now();
                let attempts = self.failed_attempts.entry(identifier.to_string())
                    .or_insert_with(Vec::new);

                // 清理1小时前的记录
                attempts.retain(|&time| now.duration_since(time) < Duration::from_secs(3600));

                // 检查5分钟内失败次数
                let recent_attempts: Vec<_> = attempts.iter()
                    .filter(|&&time| now.duration_since(time) < Duration::from_secs(300))
                    .collect();

                if recent_attempts.len() >= 5 {
                    return Err("检测到可疑活动,账户已被锁定".to_string());
                }

                attempts.push(now);
                Ok(())
            }

            fn check_suspicious_content(&self, content: &str) -> bool {
                let lowercase_content = content.to_lowercase();
                self.suspicious_patterns.iter()
                    .any(|pattern| lowercase_content.contains(pattern))
            }
        }

3 环境搭建

3.1 环境准备

01.系统要求
    a.操作系统支持
        Windows 10及以上版本(64位)
        macOS 10.14及以上版本
        Linux发行版(Ubuntu 18.04+, Fedora 32+, Debian 10+)
    b.硬件要求
        至少4GB内存
        2GB可用磁盘空间
        支持现代浏览器WebView
    c.网络要求
        稳定的网络连接(用于下载依赖)
        开发环境可能需要访问GitHub
        某些系统需要安装系统级依赖

02.Rust环境安装
    a.安装Rust工具链
        # 通过rustup安装
        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

        # Windows用户使用PowerShell
        Invoke-WebRequest -Uri https://win.rustup.rs -OutFile rustup-init.exe
        .\rustup-init.exe

        # 验证安装
        rustc --version
        cargo --version
    b.配置Rust环境
        # 更新到最新版本
        rustup update

        # 安装常用工具
        rustup component add rustfmt
        rustup component add clippy

        # 配置Cargo镜像源(中国用户)
        mkdir -p ~/.cargo
        cat > ~/.cargo/config << EOF
        [source.crates-io]
        replace-with = 'ustc'

        [source.ustc]
        registry = "https://mirrors.ustc.edu.cn/crates.io-index"
        EOF
    c.环境变量配置
        # Windows系统环境变量
        # 将以下路径添加到PATH:
        # C:\Users\用户名\.cargo\bin

        # Linux/macOS环境变量
        echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
        source ~/.bashrc

03.Node.js环境
    a.Node.js安装
        # 官方网站下载安装包
        # https://nodejs.org/

        # 或使用版本管理器
        # Windows: nvm-windows
        # macOS/Linux: nvm

        # 验证安装
        node --version
        npm --version
    b.包管理器选择
        # npm(默认)
        npm install -g @tauri-apps/cli

        # yarn(可选)
        npm install -g yarn
        yarn global add @tauri-apps/cli

        # pnpm(推荐)
        npm install -g pnpm
        pnpm add -g @tauri-apps/cli
    c.前端开发工具
        # 代码编辑器
        # VS Code + 官方扩展
        # WebStorm
        # Vim/Neovim

        # 浏览器开发者工具
        # Chrome DevTools
        # Firefox Developer Tools

3.2 项目初始化

01.创建新项目
    a.使用CLI创建
        # 基础项目创建
        npx create-tauri-app my-app

        # 选择前端框架
        # ❯ Vanilla
        #   React
        #   Vue
        #   Svelte
        #   Angular

        # 项目配置
        # Package name: my-app
        # Window title: My App
        # Dist directory: ../dist

        # 进入项目目录
        cd my-app
    b.手动创建项目
        # 1. 创建项目目录
        mkdir my-tauri-app && cd my-tauri-app

        # 2. 初始化前端项目
        # Vue项目示例
        npm create vue@latest .
        # 选择需要的特性
        # ❯ TypeScript
        # ❯ JSX Support
        # ❯ Vue Router
        # ❯ Pinia
        # ❯ Vitest
        # ❯ Nightwatch
        # ❯ End-to-End Testing Solution
        # ❯ ESLint
        # ❯ Prettier

        # 3. 添加Tauri依赖
        npm install -D @tauri-apps/cli

        # 4. 初始化Tauri
        npx tauri init
    c.项目结构理解
        my-tauri-app/
        ├── src-tauri/              # Tauri后端代码
        │   ├── src/               # Rust源代码
        │   │   └── main.rs       # 主入口文件
        │   ├── Cargo.toml        # Rust依赖配置
        │   ├── build.rs          # 构建脚本
        │   ├── icons/            # 应用图标
        │   └── tauri.conf.json   # Tauri配置
        ├── src/                  # 前端源代码
        ├── dist/                 # 前端构建输出
        ├── node_modules/         # Node.js依赖
        ├── package.json         # 项目配置
        └── tauri.conf.json      # 全局Tauri配置

02.配置文件详解
    a.tauri.conf.json主配置
        {
          "build": {
            "beforeBuildCommand": "npm run build",
            "beforeDevCommand": "npm run dev",
            "devPath": "http://localhost:3000",
            "distDir": "../dist",
            "withGlobalTauri": false
          },
          "package": {
            "productName": "My App",
            "version": "0.1.0"
          },
          "tauri": {
            "allowlist": {
              "all": false,
              "shell": {
                "all": false,
                "open": true
              },
              "dialog": {
                "all": false,
                "open": true,
                "save": true
              },
              "fs": {
                "all": false,
                "readFile": true,
                "writeFile": true,
                "scope": ["$APPDATA/*", "$DOCUMENT/*"]
              }
            },
            "bundle": {
              "active": true,
              "targets": "all",
              "identifier": "com.tauri.my-app",
              "icon": [
                "icons/32x32.png",
                "icons/128x128.png",
                "icons/[email protected]",
                "icons/icon.icns",
                "icons/icon.ico"
              ]
            },
            "security": {
              "csp": null,
              "dangerousRemoteDomainIpcAccess": []
            },
            "windows": [
              {
                "fullscreen": false,
                "height": 600,
                "resizable": true,
                "title": "My App",
                "width": 800,
                "minWidth": 400,
                "minHeight": 300,
                "center": true,
                "decorations": true,
                "alwaysOnTop": false,
                "skipTaskbar": false
              }
            ],
            "systemTray": {
              "iconPath": "icons/icon.png",
              "iconAsTemplate": true,
              "menuOnLeftClick": false
            }
          }
        }
    b.Cargo.toml Rust配置
        [package]
        name = "my-app"
        version = "0.1.0"
        description = "A Tauri App"
        authors = ["you"]
        license = ""
        repository = ""
        default-run = "my-app"
        edition = "2021"
        rust-version = "1.57"

        [build-dependencies]
        tauri-build = { version = "1.0", features = [] }

        [dependencies]
        serde_json = "1.0"
        serde = { version = "1.0", features = ["derive"] }
        tauri = { version = "1.0", features = ["api-all", "updater"] }
        tokio = { version = "1", features = ["full"] }

        [features]
        default = ["custom-protocol"]
        custom-protocol = ["tauri/custom-protocol"]
    c.package.json前端配置
        {
          "name": "my-app",
          "version": "0.1.0",
          "private": true,
          "scripts": {
            "dev": "vite",
            "build": "vite build",
            "preview": "vite preview",
            "tauri": "tauri",
            "tauri:dev": "tauri dev",
            "tauri:build": "tauri build"
          },
          "dependencies": {
            "@tauri-apps/api": "^1.0.0",
            "vue": "^3.2.37",
            "vue-router": "^4.0.14",
            "pinia": "^2.0.11"
          },
          "devDependencies": {
            "@tauri-apps/cli": "^1.0.0",
            "@vitejs/plugin-vue": "^2.3.3",
            "vite": "^2.9.9"
          }
        }
        ---

03.模板项目定制
    a.从模板创建
        # 使用特定模板
        npx create-tauri-app my-react-app --template react
        npx create-tauri-app my-vue-app --template vue
        npx create-tauri-app my-svelte-app --template svelte

        # 使用GitHub模板
        git clone https://github.com/tauri-apps/tauri-template-react.git
        cd tauri-template-react
        npm install
        npm run tauri dev
    b.自定义前端框架
        # 创建自定义Vite项目
        npm create vite@latest my-custom-app -- --template react-ts
        cd my-custom-app
        npm install

        # 添加Tauri
        npm install -D @tauri-apps/cli
        npm install @tauri-apps/api
        npx tauri init

        # 配置vite.config.ts
        import { defineConfig } from 'vite';
        import react from '@vitejs/plugin-react';

        export default defineConfig({
          plugins: [react()],
          clearScreen: false,
          server: {
            port: 3000,
            strictPort: true,
            watch: {
              ignored: ["**/src-tauri/**"]
            }
          }
        });
    c.项目配置优化
        # 开发环境优化
        {
          "build": {
            "beforeDevCommand": "npm run dev",
            "devPath": "http://localhost:3000"
          },
          "tauri": {
            "bundle": {
              "active": false  // 开发时禁用打包
            }
          }
        }

        # 生产环境优化
        {
          "build": {
            "beforeBuildCommand": "npm run build",
            "distDir": "dist"
          },
          "tauri": {
            "bundle": {
              "active": true,  // 生产时启用打包
              "resources": ["resources/*"]
            }
          }
        }

3.3 基础配置

01.开发环境配置
    a.VS Code配置
        # 推荐扩展
        - Tauri
        - rust-analyzer
        - ES7+ React/Redux/React-Native snippets
        - Vue Language Features (Volar)
        - Svelte for VS Code

        # workspace配置
        {
          "folders": [
            {
              "path": "."
            }
          ],
          "settings": {
            "rust-analyzer.checkOnSave.command": "clippy",
            "rust-analyzer.cargo.loadOutDirsFromCheck": true,
            "typescript.preferences.importModuleSpecifier": "relative"
          }
        }
    b.调试配置
        # .vscode/launch.json
        {
          "version": "0.2.0",
          "configurations": [
            {
              "name": "Debug Tauri App",
              "type": "node",
              "request": "launch",
              "program": "${workspaceFolder}/src-tauri/target/debug/my-app.exe",
              "cwd": "${workspaceFolder}",
              "outputCapture": "std",
              "windows": {
                "program": "${workspaceFolder}/src-tauri/target/debug/my-app.exe"
              },
              "osx": {
                "program": "${workspaceFolder}/src-tauri/target/debug/my-app"
              },
              "linux": {
                "program": "${workspaceFolder}/src-tauri/target/debug/my-app"
              }
            }
          ]
        }
    c.热重载配置
        # vite.config.js 或 vite.config.ts
        import { defineConfig } from 'vite';

        export default defineConfig({
          server: {
            port: 3000,
            strictPort: true,
            hmr: {
              port: 3001
            },
            watch: {
              ignored: ["**/src-tauri/**"]
            }
          },
          build: {
            outDir: 'dist',
            assetsDir: 'assets',
            sourcemap: true
          }
        });

02.系统特定配置
    a.Windows配置
        # Windows Defender排除
        # 将以下路径添加到Windows Defender排除列表:
        # - 项目目录
        # - %USERPROFILE%\.cargo
        # - %USERPROFILE%\.cache

        # 权限配置
        # 以管理员身份运行以下命令:
        # Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

        # 防火墙配置
        # 在Windows防火墙中允许:
        # - Node.js网络访问
        # - Rust编译器网络访问
    b.macOS配置
        # 安装Xcode命令行工具
        xcode-select --install

        # 安装额外的系统依赖
        brew install openssl

        # 配置环境变量
        echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc
        source ~/.zshrc

        # 配置Keychain访问(用于签名)
        security unlock-keychain ~/Library/Keychains/login.keychain
    c.Linux配置
        # Ubuntu/Debian
        sudo apt update
        sudo apt install -y \
            build-essential \
            curl \
            wget \
            libssl-dev \
            pkg-config \
            libgtk-3-dev \
            libayatana-appindicator3-dev \
            librsvg2-dev

        # Fedora
        sudo dnf install -y \
            gcc \
            gcc-c++ \
            make \
            curl \
            wget \
            openssl-devel \
            pkg-config \
            gtk3-devel \
            libappindicator-gtk3 \
            librsvg2-devel

        # 配置显示服务器(如果是无头环境)
        export DISPLAY=:0

03.构建工具配置
    a.Cargo配置优化
        # ~/.cargo/config.toml
        [build]
        # 启用并行编译
        jobs = 4

        [source.crates-io]
        # 使用国内镜像源(中国用户)
        replace-with = 'ustc'

        [source.ustc]
        registry = "https://mirrors.ustc.edu.cn/crates.io-index"

        [target.x86_64-pc-windows-msvc]
        # Windows特定配置
        rustflags = ["-C", "target-feature=+crt-static"]

        [target.x86_64-unknown-linux-gnu]
        # Linux特定配置
        rustflags = ["-C", "link-args=-Wl,--as-needed"]
    b.Webpack配置(如需要)
        // webpack.config.js
        const path = require('path');

        module.exports = {
          mode: process.env.NODE_ENV || 'development',
          entry: './src/main.js',
          output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'bundle.js'
          },
          resolve: {
            extensions: ['.js', '.ts', '.jsx', '.tsx']
          },
          module: {
            rules: [
              {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
              },
              {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
              }
            ]
          },
          devServer: {
            port: 3000,
            static: {
              directory: path.join(__dirname, 'public')
            }
          }
        };
    c.TSConfig配置
        // tsconfig.json
        {
          "compilerOptions": {
            "target": "ES2020",
            "lib": ["ES2020", "DOM", "DOM.Iterable"],
            "module": "ESNext",
            "skipLibCheck": true,
            "moduleResolution": "bundler",
            "allowImportingTsExtensions": true,
            "resolveJsonModule": true,
            "isolatedModules": true,
            "noEmit": true,
            "jsx": "react-jsx",
            "strict": true,
            "noUnusedLocals": true,
            "noUnusedParameters": true,
            "noFallthroughCasesInSwitch": true,
            "types": ["@tauri-apps/api"]
          },
          "include": ["src"],
          "references": [{ "path": "./tsconfig.node.json" }]
        }

3.4 前端框架集成

01.React集成配置
    a.项目创建
        # 创建React + TypeScript项目
        npx create-tauri-app my-react-app --template react-ts

        # 或手动创建
        npm create vite@latest my-react-app -- --template react-ts
        cd my-react-app
        npm install -D @tauri-apps/cli
        npm install @tauri-apps/api
        npx tauri init
    b.Tauri React Hooks
        // src/hooks/useTauri.ts
        import { useState, useEffect } from 'react';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        export function useTauriCommand<T, P = any>(
            command: string,
            params?: P
        ) {
            const [data, setData] = useState<T | null>(null);
            const [loading, setLoading] = useState(false);
            const [error, setError] = useState<string | null>(null);

            const execute = async (newParams?: P) => {
                setLoading(true);
                setError(null);

                try {
                    const result = await invoke<T>(command, newParams || params);
                    setData(result);
                } catch (err) {
                    setError(err as string);
                } finally {
                    setLoading(false);
                }
            };

            return { data, loading, error, execute };
        }

        export function useTauriEvent<T = any>(
            eventName: string,
            handler: (event: { payload: T }) => void
        ) {
            useEffect(() => {
                let unlisten: (() => void) | null = null;

                const setupListener = async () => {
                    unlisten = await listen<T>(eventName, handler);
                };

                setupListener();

                return () => {
                    unlisten?.();
                };
            }, [eventName, handler]);
        }
    c.React组件示例
        // src/components/TauriApp.tsx
        import React from 'react';
        import { useTauriCommand, useTauriEvent } from '../hooks/useTauri';

        export const TauriApp: React.FC = () => {
            const { data: systemInfo, loading, error, execute } = useTauriCommand<Record<string, any>>('get_system_info');

            useTauriEvent('tauri://resize', (event) => {
                console.log('Window resized:', event.payload);
            });

            const handleGreet = async () => {
                try {
                    const result = await invoke<string>('greet', { name: 'React' });
                    console.log(result);
                } catch (error) {
                    console.error('Greet error:', error);
                }
            };

            return (
                <div className="app">
                    <h1>Tauri + React</h1>
                    <button onClick={handleGreet}>Greet</button>
                    <button onClick={() => execute()}>Get System Info</button>

                    {loading && <p>Loading...</p>}
                    {error && <p>Error: {error}</p>}
                    {data && (
                        <div>
                            <h3>System Info:</h3>
                            <pre>{JSON.stringify(data, null, 2)}</pre>
                        </div>
                    )}
                </div>
            );
        };
        ---

02.Vue集成配置
    a.项目创建
        # 创建Vue + TypeScript项目
        npx create-tauri-app my-vue-app --template vue-ts

        # 或手动创建
        npm create vue@latest my-vue-app
        cd my-vue-app
        npm install
        npm install -D @tauri-apps/cli
        npm install @tauri-apps/api
        npx tauri init
    b.Vue Composable
        // src/composables/useTauri.ts
        import { ref, onMounted, onUnmounted } from 'vue';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        export function useTauriCommand<T, P = any>(command: string) {
            const data = ref<T | null>(null);
            const loading = ref(false);
            const error = ref<string | null>(null);

            const execute = async (params?: P): Promise<void> => {
                loading.value = true;
                error.value = null;

                try {
                    const result = await invoke<T>(command, params);
                    data.value = result;
                } catch (err) {
                    error.value = err as string;
                } finally {
                    loading.value = false;
                }
            };

            return {
                data: data.value,
                loading: loading.value,
                error: error.value,
                execute
            };
        }

        export function useTauriEvent<T = any>(
            eventName: string,
            handler: (event: { payload: T }) => void
        ) {
            let unlisten: (() => void) | null = null;

            onMounted(async () => {
                unlisten = await listen<T>(eventName, handler);
            });

            onUnmounted(() => {
                unlisten?.();
            });
        }
    c.Vue组件示例
        <!-- src/components/TauriApp.vue -->
        <template>
            <div class="app">
                <h1>Tauri + Vue</h1>
                <button @click="greet">Greet</button>
                <button @click="getSystemInfo">Get System Info</button>

                <div v-if="loading" class="loading">
                    Loading...
                </div>

                <div v-if="error" class="error">
                    Error: {{ error }}
                </div>

                <div v-if="systemInfo" class="system-info">
                    <h3>System Info:</h3>
                    <pre>{{ JSON.stringify(systemInfo, null, 2) }}</pre>
                </div>
            </div>
        </template>

        <script setup lang="ts">
        import { ref } from 'vue';
        import { invoke } from '@tauri-apps/api/tauri';
        { useTauriEvent } from '../composables/useTauri';

        const systemInfo = ref<Record<string, any> | null>(null);
        const loading = ref(false);
        const error = ref<string | null>(null);

        // 监听窗口事件
        useTauriEvent('tauri://resize', (event) => {
            console.log('Window resized:', event.payload);
        });

        const greet = async () => {
            try {
                const result = await invoke<string>('greet', { name: 'Vue' });
                console.log(result);
            } catch (err) {
                console.error('Greet error:', err);
            }
        };

        const getSystemInfo = async () => {
            loading.value = true;
            error.value = null;

            try {
                const info = await invoke<Record<string, any>>('get_system_info');
                systemInfo.value = info;
            } catch (err) {
                error.value = err as string;
            } finally {
                loading.value = false;
            }
        };
        </script>

        <style scoped>
        .app {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }

        button {
            margin-right: 10px;
            padding: 8px 16px;
            background: #42b883;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .loading, .error {
            margin: 20px 0;
            padding: 10px;
            border-radius: 4px;
        }

        .loading {
            background: #e3f2fd;
        }

        .error {
            background: #ffebee;
        }

        .system-info {
            margin-top: 20px;
            padding: 15px;
            background: #f5f5f5;
            border-radius: 4px;
        }

        pre {
            white-space: pre-wrap;
            word-wrap: break-word;
        }
        </style>
        ---

03.Svelte集成配置
    a.项目创建
        # 创建Svelte + TypeScript项目
        npx create-tauri-app my-svelte-app --template svelte-ts

        # 或手动创建
        npm create svelte@latest my-svelte-app
        cd my-svelte-app
        npm install
        npm install -D @tauri-apps/cli
        npm install @tauri-apps/api
        npx tauri init
    b.Svelte Store
        // src/stores/tauri.ts
        import { writable } from 'svelte/store';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        export const systemInfo = writable<Record<string, any> | null>(null);
        export const loading = writable(false);
        export const error = writable<string | null>(null);

        export async function getSystemInfo() {
            loading.set(true);
            error.set(null);

            try {
                const info = await invoke<Record<string, any>>('get_system_info');
                systemInfo.set(info);
            } catch (err) {
                error.set(err as string);
            } finally {
                loading.set(false);
            }
        }

        export function setupEventListeners() {
            let unlisten: (() => void) | null = null;

            const setup = async () => {
                unlisten = await listen('tauri://resize', (event) => {
                    console.log('Window resized:', event.payload);
                });
            };

            setup();

            return () => {
                unlisten?.();
            };
        }
    c.Svelte组件示例
        <!-- src/components/TauriApp.svelte -->
        <script lang="ts">
        import { onMount } from 'svelte';
        import { invoke } from '@tauri-apps/api/tauri';
        { systemInfo, loading, error, getSystemInfo, setupEventListeners } from '../stores/tauri';

        let unlisten: (() => void) | null = null;

        onMount(() => {
            unlisten = setupEventListeners();
        });

        const greet = async () => {
            try {
                const result = await invoke<string>('greet', { name: 'Svelte' });
                console.log(result);
            } catch (err) {
                console.error('Greet error:', err);
            }
        };

        $: systemInfoContent = $systemInfo ? JSON.stringify($systemInfo, null, 2) : '';
    </script>

        <div class="app">
            <h1>Tauri + Svelte</h1>
            <button on:click={greet}>Greet</button>
            <button on:click={getSystemInfo}>Get System Info</button>

            {#if $loading}
                <div class="loading">Loading...</div>
            {/if}

            {#if $error}
                <div class="error">Error: {$error}</div>
            {/if}

            {#if $systemInfo}
                <div class="system-info">
                    <h3>System Info:</h3>
                    <pre>{systemInfoContent}</pre>
                </div>
            {/if}
        </div>

        <style>
        .app {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }

        button {
            margin-right: 10px;
            padding: 8px 16px;
            background: #ff3e00;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .loading, .error {
            margin: 20px 0;
            padding: 10px;
            border-radius: 4px;
        }

        .loading {
            background: #fff3cd;
        }

        .error {
            background: #f8d7da;
        }

        .system-info {
            margin-top: 20px;
            padding: 15px;
            background: #e2e3e5;
            border-radius: 4px;
        }

        pre {
            white-space: pre-wrap;
            word-wrap: break-word;
        }
        </style>
        ---

04.Angular集成配置
    a.项目创建
        # 创建Angular项目
        npx create-tauri-app my-angular-app --template angular

        # 或手动创建
        ng new my-angular-app --style=scss --routing=true
        cd my-angular-app
        npm install -D @tauri-apps/cli
        npm install @tauri-apps/api
        npx tauri init
    b.Angular服务
        // src/app/services/tauri.service.ts
        import { Injectable } from '@angular/core';
        import { invoke } from '@tauri-apps/api/tauri';
        { listen } from '@tauri-apps/api/event';

        export interface SystemInfo {
            os: string;
            arch: string;
            version: string;
        }

        @Injectable({
            providedIn: 'root'
        })
        export class TauriService {
            private systemInfo: SystemInfo | null = null;

            constructor() {
                this.setupEventListeners();
            }

            async greet(name: string): Promise<string> {
                try {
                    return await invoke<string>('greet', { name });
                } catch (error) {
                    console.error('Greet error:', error);
                    throw error;
                }
            }

            async getSystemInfo(): Promise<SystemInfo> {
                try {
                    this.systemInfo = await invoke<SystemInfo>('get_system_info');
                    return this.systemInfo;
                } catch (error) {
                    console.error('Get system info error:', error);
                    throw error;
                }
            }

            getCurrentSystemInfo(): SystemInfo | null {
                return this.systemInfo;
            }

            private async setupEventListeners() {
                await listen('tauri://resize', (event) => {
                    console.log('Window resized:', event.payload);
                });
            }
        }
    c.Angular组件示例
        <!-- src/app/components/tauri-app/tauri-app.component.ts -->
        import { Component, OnInit } from '@angular/core';
        { TauriService, SystemInfo } from '../../services/tauri.service';

        @Component({
            selector: 'app-tauri-app',
            templateUrl: './tauri-app.component.html',
            styleUrls: ['./tauri-app.component.scss']
        })
        export class TauriAppComponent implements OnInit {
            systemInfo: SystemInfo | null = null;
            loading = false;
            error: string | null = null;
            message: string | null = null;

            constructor(private tauriService: TauriService) {}

            ngOnInit() {
                this.loadSystemInfo();
            }

            async handleGreet() {
                try {
                    this.message = await this.tauriService.greet('Angular');
                } catch (error) {
                    this.error = error as string;
                }
            }

            async loadSystemInfo() {
                this.loading = true;
                this.error = null;

                try {
                    this.systemInfo = await this.tauriService.getSystemInfo();
                } catch (error) {
                    this.error = error as string;
                } finally {
                    this.loading = false;
                }
            }
        }

        <!-- src/app/components/tauri-app/tauri-app.component.html -->
        <div class="app">
            <h1>Tauri + Angular</h1>
            <button (click)="handleGreet()">Greet</button>
            <button (click)="loadSystemInfo()">Get System Info</button>

            <div *ngIf="loading" class="loading">Loading...</div>

            <div *ngIf="error" class="error">Error: {{ error }}</div>

            <div *ngIf="message" class="message">{{ message }}</div>

            <div *ngIf="systemInfo" class="system-info">
                <h3>System Info:</h3>
                <pre>{{ systemInfo | json }}</pre>
            </div>
        </div>

        <!-- src/app/components/tauri-app/tauri-app.component.scss -->
        .app {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }

        button {
            margin-right: 10px;
            padding: 8px 16px;
            background: #dd0031;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .loading, .error, .message {
            margin: 20px 0;
            padding: 10px;
            border-radius: 4px;
        }

        .loading {
            background: #e1f5fe;
        }

        .error {
            background: #ffebee;
        }

        .message {
            background: #e8f5e8;
        }

        .system-info {
            margin-top: 20px;
            padding: 15px;
            background: #f5f5f5;
            border-radius: 4px;
        }

        pre {
            white-space: pre-wrap;
            word-wrap: break-word;
        }

3.5 开发环境配置

01.调试配置
    a.前端调试
        // Chrome开发者工具配置
        // tauri.conf.json
        {
          "tauri": {
            "security": {
              "devCsp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
            }
          }
        }

        // 启用开发者工具(开发环境)
        // main.rs
        #[cfg(debug_assertions)]
        {
            let window = app.get_window("main").unwrap();
            window.open_devtools();
        }
    b.Rust调试
        # 安装rust-analyzer
        rustup component add rust-analyzer

        # VS Code配置
        # .vscode/settings.json
        {
          "rust-analyzer.checkOnSave.command": "clippy",
          "rust-analyzer.cargo.loadOutDirsFromCheck": true,
          "rust-analyzer.procMacro.enable": true
        }

        # 调试配置
        # .vscode/launch.json
        {
          "version": "0.2.0",
          "configurations": [
            {
              "name": "Debug Rust",
              "type": "lldb",
              "request": "launch",
              "program": "${workspaceFolder}/src-tauri/target/debug/${workspaceFolderBasename}",
              "args": [],
              "cwd": "${workspaceFolder}",
              "environment": [],
              "externalConsole": false,
              "MIMode": "lldb"
            }
          ]
        }
    c.日志配置
        // Rust日志配置
        // Cargo.toml
        [dependencies]
        log = "0.4"
        env_logger = "0.9"

        // main.rs
        use log::{info, warn, error};

        fn main() {
            // 初始化日志
            env_logger::init();

            info!("应用启动");

            tauri::Builder::default()
                .setup(|app| {
                    info!("应用设置完成");
                    Ok(())
                })
                .run(tauri::generate_context!())
                .expect("运行应用失败");
        }

        // 前端日志
        // src/utils/logger.ts
        export class Logger {
            static info(message: string, data?: any) {
                console.log(`[INFO] ${new Date().toISOString()}: ${message}`, data);
            }

            static warn(message: string, data?: any) {
                console.warn(`[WARN] ${new Date().toISOString()}: ${message}`, data);
            }

            static error(message: string, error?: any) {
                console.error(`[ERROR] ${new Date().toISOString()}: ${message}`, error);
            }
        }
        ---

02.开发工具集成
    a.代码质量工具
        # Rust代码格式化
        cargo fmt

        # Rust代码检查
        cargo clippy

        # 前端代码检查
        npm install -D eslint
        npm install -D prettier

        # ESLint配置
        # .eslintrc.js
        module.exports = {
            env: {
                browser: true,
                es2021: true,
                node: true
            },
            extends: [
                'eslint:recommended',
                '@typescript-eslint/recommended'
            ],
            parser: '@typescript-eslint/parser',
            parserOptions: {
                ecmaVersion: 12,
                sourceType: 'module'
            },
            plugins: ['@typescript-eslint'],
            rules: {
                'no-console': 'warn',
                'no-unused-vars': 'error'
            }
        };

        # Prettier配置
        # .prettierrc
        {
            "semi": true,
            "trailingComma": "es5",
            "singleQuote": true,
            "printWidth": 100,
            "tabWidth": 2
        }
    b.自动化工具
        # Git hooks配置
        # 安装husky
        npm install -D husky

        # 初始化husky
        npx husky install

        # 添加pre-commit hook
        npx husky add .husky/pre-commit "npm run lint && npm run format"

        # package.json
        {
          "scripts": {
            "lint": "eslint src --ext .ts,.tsx",
            "lint:fix": "eslint src --ext .ts,.tsx --fix",
            "format": "prettier --write src/**/*.{ts,tsx,css,md}",
            "rust:check": "cd src-tauri && cargo clippy",
            "rust:format": "cd src-tauri && cargo fmt",
            "pre-commit": "npm run lint && npm run format && npm run rust:format"
          }
        }
    c.性能监控
        // Rust性能监控
        use std::time::Instant;

        #[tauri::command]
        async fn performance_test() -> Result<PerformanceMetrics, String> {
            let start = Instant::now();

            // 执行一些操作
            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

            let duration = start.elapsed();

            Ok(PerformanceMetrics {
                duration_ms: duration.as_millis() as u64,
                memory_usage: get_memory_usage(),
            })
        }

        #[derive(serde::Serialize)]
        struct PerformanceMetrics {
            duration_ms: u64,
            memory_usage: u64,
        }

        fn get_memory_usage() -> u64 {
            // 获取内存使用情况的实现
            0
        }

        // 前端性能监控
        class PerformanceMonitor {
            private metrics: Map<string, number> = new Map();

            startTimer(name: string) {
                this.metrics.set(name, performance.now());
            }

            endTimer(name: string): number {
                const startTime = this.metrics.get(name);
                if (startTime) {
                    const duration = performance.now() - startTime;
                    console.log(`Performance: ${name} took ${duration.toFixed(2)}ms`);
                    this.metrics.delete(name);
                    return duration;
                }
                return 0;
            }

            measureFunction<T>(name: string, fn: () => T): T {
                this.startTimer(name);
                const result = fn();
                this.endTimer(name);
                return result;
            }

            async measureAsyncFunction<T>(name: string, fn: () => Promise<T>): Promise<T> {
                this.startTimer(name);
                const result = await fn();
                this.endTimer(name);
                return result;
            }
        }

        export const performanceMonitor = new PerformanceMonitor();
        ---

03.环境管理
    a.多环境配置
        # 开发环境配置
        # src-tauri/tauri.conf.dev.json
        {
          "build": {
            "beforeDevCommand": "npm run dev",
            "devPath": "http://localhost:3000"
          },
          "tauri": {
            "allowlist": {
              "all": true
            },
            "security": {
              "devCsp": null
            },
            "bundle": {
              "active": false
            }
          }
        }

        # 生产环境配置
        # src-tauri/tauri.conf.prod.json
        {
          "build": {
            "beforeBuildCommand": "npm run build",
            "distDir": "dist"
          },
          "tauri": {
            "allowlist": {
              "all": false,
              "shell": { "open": true },
              "dialog": { "all": true }
            },
            "security": {
              "csp": "default-src 'self';"
            },
            "bundle": {
              "active": true
            }
          }
        }

        # package.json脚本
        {
          "scripts": {
            "tauri:dev": "tauri dev --config src-tauri/tauri.conf.dev.json",
            "tauri:build": "tauri build --config src-tauri/tauri.conf.prod.json"
          }
        }
    b.环境变量管理
        # Rust环境变量
        # src-tauri/src/config.rs
        use std::env;

        pub struct Config {
            pub api_url: String,
            pub debug: bool,
        }

        impl Config {
            pub fn from_env() -> Self {
                Config {
                    api_url: env::var("API_URL").unwrap_or_else(|_| "http://localhost:8080".to_string()),
                    debug: env::var("DEBUG").unwrap_or_else(|_| "false".to_string()) == "true",
                }
            }
        }

        # 前端环境变量
        # src/config/environment.ts
        export interface Environment {
            apiUrl: string;
            debug: boolean;
        }

        export const environment: Environment = {
            apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:8080',
            debug: import.meta.env.DEV
        };

        # .env.development
        VITE_API_URL=http://localhost:8080
        DEBUG=true

        # .env.production
        VITE_API_URL=https://api.production.com
        DEBUG=false
    c.测试环境配置
        # 测试配置
        # src-tauri/tests/test_config.rs
        use tauri::Manager;

        pub fn setup_test_app() -> tauri::App {
            tauri::Builder::default()
                .setup(|app| {
                    // 测试环境设置
                    Ok(())
                })
                .invoke_handler(tauri::generate_handler![test_command])
                .build(tauri::generate_context!())
                .expect("failed to build test app")
        }

        #[tauri::command]
        async fn test_command() -> Result<String, String> {
            Ok("test response".to_string())
        }

        # 前端测试配置
        # vitest.config.ts
        import { defineConfig } from 'vitest/config';
        import path from 'path';

        export default defineConfig({
            test: {
                environment: 'jsdom',
                setupFiles: ['./src/test/setup.ts']
            },
            resolve: {
                alias: {
                    '@': path.resolve(__dirname, './src')
                }
            }
        });

        # src/test/setup.ts
        import { vi } from 'vitest';

        // Mock Tauri API
        vi.mock('@tauri-apps/api/tauri', () => ({
            invoke: vi.fn()
        }));

3.6 插件系统

01.插件开发基础
    a.创建插件项目
        # 创建插件目录
        mkdir my-tauri-plugin && cd my-tauri-plugin

        # 初始化Cargo项目
        cargo init --lib

        # 配置Cargo.toml
        [package]
        name = "my-tauri-plugin"
        version = "0.1.0"
        edition = "2021"

        [lib]
        crate-type = ["cdylib"]

        [dependencies]
        tauri = { version = "1.0", features = ["api-all"] }
        serde = { version = "1.0", features = ["derive"] }
        tokio = { version = "1", features = ["full"] }
    b.插件核心结构
        // src/lib.rs
        use tauri::{plugin::{Builder, TauriPlugin}, Manager, Runtime, State};

        pub struct MyPluginState {
            counter: std::sync::Mutex<i32>,
        }

        impl MyPluginState {
            pub fn new() -> Self {
                Self {
                    counter: std::sync::Mutex::new(0),
                }
            }
        }

        #[tauri::command]
        pub fn increment_counter(state: State<'_, MyPluginState>) -> Result<i32, String> {
            let mut counter = state.counter.lock().map_err(|e| e.to_string())?;
            *counter += 1;
            Ok(*counter)
        }

        #[tauri::command]
        pub fn get_counter(state: State<'_, MyPluginState>) -> Result<i32, String> {
            let counter = state.counter.lock().map_err(|e| e.to_string())?;
            Ok(*counter)
        }

        pub fn init<R: Runtime>() -> TauriPlugin<R> {
            Builder::new("my-plugin")
                .invoke_handler(tauri::generate_handler![
                    increment_counter,
                    get_counter
                ])
                .setup(|app| {
                    app.manage(MyPluginState::new());
                    Ok(())
                })
                .build()
        }
    c.插件使用
        // 在主应用中使用插件
        // Cargo.toml
        [dependencies]
        my-tauri-plugin = { path = "../my-tauri-plugin" }

        // main.rs
        use my_tauri_plugin::init as init_my_plugin;

        fn main() {
            tauri::Builder::default()
                .plugin(init_my_plugin())
                .run(tauri::generate_context!())
                .expect("error while running tauri application");
        }

        // 前端调用
        import { invoke } from '@tauri-apps/api/tauri';

        async function usePlugin() {
            const counter = await invoke<number>('plugin:my-plugin|increment_counter');
            console.log('Counter:', counter);

            const currentCounter = await invoke<number>('plugin:my-plugin|get_counter');
            console.log('Current counter:', currentCounter);
        }
        ---

02.常用插件开发
    a.文件系统插件
        // src/filesystem.rs
        use tauri::{plugin::{Builder, TauriPlugin}, Runtime};
        use std::fs;
        use std::path::Path;

        #[tauri::command]
        pub async fn read_text_file(path: String) -> Result<String, String> {
            if !Path::new(&path).exists() {
                return Err("文件不存在".to_string());
            }

            fs::read_to_string(&path)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        pub async fn write_text_file(path: String, content: String) -> Result<(), String> {
            fs::write(&path, content)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        pub async fn create_directory(path: String) -> Result<(), String> {
            fs::create_dir_all(&path)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        pub async fn list_directory(path: String) -> Result<Vec<String>, String> {
            let mut entries = Vec::new();

            for entry in fs::read_dir(&path)
                .map_err(|e| e.to_string())?
            {
                let entry = entry.map_err(|e| e.to_string())?;
                if let Ok(path) = entry.path().into_os_string().into_string() {
                    entries.push(path);
                }
            }

            Ok(entries)
        }

        pub fn init<R: Runtime>() -> TauriPlugin<R> {
            Builder::new("filesystem")
                .invoke_handler(tauri::generate_handler![
                    read_text_file,
                    write_text_file,
                    create_directory,
                    list_directory
                ])
                .build()
        }
    b.数据库插件
        // src/database.rs
        use tauri::{plugin::{Builder, TauriPlugin}, Runtime, State};
        use rusqlite::{Connection, Result};
        use std::sync::Mutex;

        pub struct DatabaseState {
            conn: Mutex<Connection>,
        }

        impl DatabaseState {
            pub fn new(database_path: &str) -> Result<Self> {
                let conn = Connection::open(database_path)?;

                // 创建表
                conn.execute(
                    "CREATE TABLE IF NOT EXISTS users (
                        id INTEGER PRIMARY KEY,
                        name TEXT NOT NULL,
                        email TEXT NOT NULL
                    )",
                    [],
                )?;

                Ok(Self {
                    conn: Mutex::new(conn),
                })
            }
        }

        #[tauri::command]
        pub async fn create_user(
            state: State<'_, DatabaseState>,
            name: String,
            email: String,
        ) -> Result<i64, String> {
            let conn = state.conn.lock().map_err(|e| e.to_string())?;

            conn.execute(
                "INSERT INTO users (name, email) VALUES (?1, ?2)",
                [&name, &email],
            )
            .map_err(|e| e.to_string())
        }

        #[tauri::command]
        pub async fn get_users(state: State<'_, DatabaseState>) -> Result<Vec<User>, String> {
            let conn = state.conn.lock().map_err(|e| e.to_string())?;

            let mut stmt = conn
                .prepare("SELECT id, name, email FROM users")
                .map_err(|e| e.to_string())?;

            let user_iter = stmt
                .query_map([], |row| {
                    Ok(User {
                        id: row.get(0)?,
                        name: row.get(1)?,
                        email: row.get(2)?,
                    })
                })
                .map_err(|e| e.to_string())?;

            let mut users = Vec::new();
            for user in user_iter {
                users.push(user.map_err(|e| e.to_string())?);
            }

            Ok(users)
        }

        #[derive(serde::Serialize)]
        pub struct User {
            id: i64,
            name: String,
            email: String,
        }

        pub fn init<R: Runtime>(database_path: String) -> TauriPlugin<R> {
            Builder::new("database")
                .setup(move |app| {
                    app.manage(DatabaseState::new(&database_path).map_err(|e| e.to_string())?);
                    Ok(())
                })
                .invoke_handler(tauri::generate_handler![
                    create_user,
                    get_users
                ])
                .build()
        }
    c.网络请求插件
        // src/network.rs
        use tauri::{plugin::{Builder, TauriPlugin}, Runtime};
        use serde_json::Value;

        #[tauri::command]
        pub async fn fetch_json(url: String) -> Result<Value, String> {
            let client = reqwest::Client::new();

            let response = client
                .get(&url)
                .send()
                .await
                .map_err(|e| e.to_string())?;

            if response.status().is_success() {
                let json = response
                    .json::<Value>()
                    .await
                    .map_err(|e| e.to_string())?;
                Ok(json)
            } else {
                Err(format!("HTTP请求失败: {}", response.status()))
            }
        }

        #[tauri::command]
        pub async fn post_json(url: String, data: Value) -> Result<Value, String> {
            let client = reqwest::Client::new();

            let response = client
                .post(&url)
                .header("Content-Type", "application/json")
                .json(&data)
                .send()
                .await
                .map_err(|e| e.to_string())?;

            if response.status().is_success() {
                let json = response
                    .json::<Value>()
                    .await
                    .map_err(|e| e.to_string())?;
                Ok(json)
            } else {
                Err(format!("HTTP请求失败: {}", response.status()))
            }
        }

        pub fn init<R: Runtime>() -> TauriPlugin<R> {
            Builder::new("network")
                .invoke_handler(tauri::generate_handler![
                    fetch_json,
                    post_json
                ])
                .build()
        }
        ---

03.插件分发
    a.发布到crates.io
        # 准备发布
        # 1. 更新Cargo.toml
        [package]
        name = "tauri-plugin-my-plugin"
        version = "0.1.0"
        description = "A Tauri plugin for my custom functionality"
        license = "MIT OR Apache-2.0"
        repository = "https://github.com/username/tauri-plugin-my-plugin"
        documentation = "https://docs.rs/tauri-plugin-my-plugin"

        [dependencies]
        tauri = { version = "1.0", features = ["api-all"] }

        # 2. 检查代码
        cargo clippy -- -D warnings
        cargo fmt --check

        # 3. 发布
        cargo publish

        # 使用插件
        # Cargo.toml
        [dependencies]
        tauri-plugin-my-plugin = "0.1"
    b.私有插件
        # 使用Git依赖
        [dependencies]
        tauri-plugin-my-plugin = { git = "https://github.com/company/tauri-plugin-private.git" }

        # 使用本地路径
        [dependencies]
        tauri-plugin-my-plugin = { path = "../plugins/tauri-plugin-my-plugin" }

        # 使用私有registry
        # Cargo.toml
        [dependencies]
        tauri-plugin-my-plugin = { version = "0.1.0", registry = "private" }

        # .cargo/config.toml
        [registries]
        private = { index = "https://registry.private.com/crates.io-index" }
    c.插件文档
        # README.md
        # Tauri My Plugin

        A Tauri plugin for my custom functionality.

        ## Installation

        Add this to your `Cargo.toml`:

        ```toml
        [dependencies]
        tauri-plugin-my-plugin = "0.1"
        ```

        ## Usage

        ### Rust

        ```rust
        use tauri_plugin_my_plugin::init as init_my_plugin;

        fn main() {
            tauri::Builder::default()
                .plugin(init_my_plugin())
                .run(tauri::generate_context!())
                .expect("error while running tauri application");
        }
        ```

        ### JavaScript

        ```javascript
        import { invoke } from '@tauri-apps/api/tauri';

        async function usePlugin() {
            const result = await invoke('plugin:my-plugin|my_command', {
                param1: 'value1',
                param2: 'value2'
            });
            console.log(result);
        }
        ```

        ## API

        ### Commands

        #### `my_command`

        Execute my custom command.

        **Parameters:**
        - `param1` (string): First parameter
        - `param2` (number): Second parameter

        **Returns:**
        `MyResult`: The result of the operation

        ## License

        MIT OR Apache-2.0

4 应用开发

4.1 窗口管理

01.窗口创建和配置
    a.基础窗口创建
        // src-tauri/src/main.rs
        use tauri::{Manager, WindowBuilder, WindowUrl};

        fn create_window(app: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> {
            let window = tauri::WindowBuilder::new(
                app,
                "main",                                    // 窗口标识符
                WindowUrl::App("index.html".into())       // 窗口URL
            )
            .title("My Tauri App")                       // 窗口标题
            .inner_size(800.0, 600.0)                     // 窗口大小
            .min_inner_size(400.0, 300.0)                 // 最小尺寸
            .center()                                     // 居中显示
            .decorations(true)                             // 显示边框
            .always_on_top(false)                          // 不总是置顶
            .resizable(true)                              // 可调整大小
            .maximizable(true)                            // 可最大化
            .minimizable(true)                            // 可最小化
            .fullscreen(false)                            // 非全屏
            .visible(true)                                // 窗口可见
            .build()?;

            // 窗口创建后的配置
            window.show()?;

            Ok(())
        }
    b.多窗口管理
        use tauri::{Manager, State};

        #[derive(Default)]
        struct WindowManager {
            windows: std::sync::Mutex<Vec<String>>,
        }

        #[tauri::command]
        async fn create_child_window(
            app: tauri::AppHandle,
            window_manager: State<'_, WindowManager>
        ) -> Result<String, String> {
            let window_id = format!("child-{}", chrono::Utc::now().timestamp());

            let _window = tauri::WindowBuilder::new(
                &app,
                &window_id,
                tauri::WindowUrl::App("child.html".into())
            )
            .title("Child Window")
            .inner_size(400.0, 300.0)
            .parent(app.get_window("main").unwrap())
            .build()
            .map_err(|e| e.to_string())?;

            // 记录窗口ID
            let mut windows = window_manager.windows.lock().unwrap();
            windows.push(window_id.clone());

            Ok(window_id)
        }

        #[tauri::command]
        async fn close_window(
            app: tauri::AppHandle,
            window_id: String,
            window_manager: State<'_, WindowManager>
        ) -> Result<(), String> {
            if let Some(window) = app.get_window(&window_id) {
                window.close().map_err(|e| e.to_string())?;

                // 从管理器中移除
                let mut windows = window_manager.windows.lock().unwrap();
                windows.retain(|id| id != &window_id);
            }

            Ok(())
        }
    c.窗口状态管理
        use serde::{Deserialize, Serialize};

        #[derive(Serialize, Deserialize, Clone)]
        struct WindowState {
            width: f64,
            height: f64,
            x: f64,
            y: f64,
            maximized: bool,
            fullscreen: bool,
        }

        #[tauri::command]
        async fn save_window_state(
            window: tauri::Window,
            app_state: tauri::State<'_, AppState>
        ) -> Result<(), String> {
            let state = WindowState {
                width: window.inner_size().unwrap().width,
                height: window.inner_size().unwrap().height,
                x: window.outer_position().unwrap().x,
                y: window.outer_position().unwrap().y,
                maximized: window.is_maximized().unwrap_or(false),
                fullscreen: window.is_fullscreen().unwrap_or(false),
            };

            let mut states = app_state.window_states.lock().unwrap();
            states.insert(window.label().unwrap(), state);

            Ok(())
        }

        #[tauri::command]
        async fn restore_window_state(
            window: tauri::Window,
            app_state: tauri::State<'_, AppState>
        ) -> Result<(), String> {
            let window_label = window.label().unwrap();
            let states = app_state.window_states.lock().unwrap();

            if let Some(state) = states.get(&window_label) {
                // 恢复窗口大小和位置
                let _ = window.set_size(tauri::Size::Physical(
                    (state.width as u32, state.height as u32)
                ));
                let _ = window.set_position(tauri::Position::Physical(
                    (state.x as i32, state.y as i32)
                ));

                // 恢复窗口状态
                if state.maximized {
                    let _ = window.maximize();
                }
                if state.fullscreen {
                    let _ = window.set_fullscreen(true);
                }
            }

            Ok(())
        }

        use std::collections::HashMap;
        use std::sync::Mutex;

        struct AppState {
            window_states: Mutex<HashMap<String, WindowState>>,
        }

        impl Default for AppState {
            fn default() -> Self {
                Self {
                    window_states: Mutex::new(HashMap::new()),
                }
            }
        }
        ---

02.窗口事件处理
    a.生命周期事件
        use tauri::{Manager, WindowEvent};

        fn main() {
            tauri::Builder::default()
                .setup(|app| {
                    let window = app.get_window("main").unwrap();

                    // 监听窗口事件
                    let window_clone = window.clone();
                    window.on_window_event(move |event| match event {
                        WindowEvent::CloseRequested { api, .. } => {
                            // 阻止窗口关闭,显示确认对话框
                            api.prevent_close();

                            tauri::api::dialog::ask(
                                Some(&window_clone),
                                "确认关闭",
                                "确定要关闭应用吗?",
                                |answer| {
                                    if answer {
                                        // 用户确认,允许关闭
                                        window_clone.close();
                                    }
                                }
                            );
                        }
                        WindowEvent::Resized { .. } => {
                            println!("窗口大小改变");
                        }
                        WindowEvent::Moved { .. } => {
                            println!("窗口位置改变");
                        }
                        WindowEvent::Focused(focused) => {
                            if *focused {
                                println!("窗口获得焦点");
                            } else {
                                println!("窗口失去焦点");
                            }
                        }
                        WindowEvent::ScaleFactorChanged { .. } => {
                            println!("缩放因子改变");
                        }
                        _ => {}
                    });

                    Ok(())
                })
                .run(tauri::generate_context!())
                .expect("error while running tauri application");
        }
    b.自定义事件系统
        use tauri::{Manager, event};

        #[tauri::command]
        async fn emit_window_event(
            window: tauri::Window,
            event_name: String,
            payload: serde_json::Value
        ) -> Result<(), String> {
            window.emit(&event_name, payload)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        async fn emit_to_all_windows(
            app: tauri::AppHandle,
            event_name: String,
            payload: serde_json::Value
        ) -> Result<(), String> {
            app.emit_all(&event_name, payload)
                .map_err(|e| e.to_string())
        }

        // 前端事件监听
        import { listen } from '@tauri-apps/api/event';

        async function setupEventListeners() {
            await listen('window-resized', (event) => {
                console.log('Window resized:', event.payload);
            });

            await listen('window-closing', (event) => {
                console.log('Window closing:', event.payload);
            });
        }
    c.窗口间通信
        use tauri::Manager;

        #[tauri::command]
        async fn send_message_to_window(
            app: tauri::AppHandle,
            target_window: String,
            message: String
        ) -> Result<(), String> {
            if let Some(window) = app.get_window(&target_window) {
                window.emit("message", message)
                    .map_err(|e| e.to_string())?;
            } else {
                return Err("目标窗口不存在".to_string());
            }

            Ok(())
        }

        #[tauri::command]
        async fn broadcast_message(
            app: tauri::AppHandle,
            message: String
        ) -> Result<(), String> {
            app.emit_all("broadcast", message)
                .map_err(|e| e.to_string())
        }

        // 前端发送消息
        import { invoke } from '@tauri-apps/api/tauri';

        async function sendMessageToWindow(windowId: string, message: string) {
            try {
                await invoke('send_message_to_window', {
                    targetWindow: windowId,
                    message: message
                });
            } catch (error) {
                console.error('发送消息失败:', error);
            }
        }
        ---

03.窗口样式和主题
    a.原生窗口样式
        use tauri::{WindowBuilder, WindowUrl, theme::Theme};

        fn create_themed_window(app: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> {
            let window = WindowBuilder::new(
                app,
                "main",
                WindowUrl::App("index.html".into())
            )
            .title("Themed Window")
            .theme(Some(Theme::Dark))                     // 深色主题
            .title_bar_style(tauri::TitleBarStyle::Overlay) // 覆盖式标题栏
            .hidden_title(true)                          // 隐藏标题
            .transparent(true)                            // 透明窗口
            .shadow(true)                                // 窗口阴影
            .decorations(false)                           // 无边框窗口
            .build()?;

            Ok(())
        }
    b.主题切换
        use serde::{Deserialize, Serialize};
        use std::sync::Mutex;

        #[derive(Serialize, Deserialize, Clone)]
        enum AppTheme {
            Light,
            Dark,
            Auto,
        }

        struct ThemeManager {
            current_theme: Mutex<AppTheme>,
        }

        impl ThemeManager {
            fn new() -> Self {
                Self {
                    current_theme: Mutex::new(AppTheme::Auto),
                }
            }

            fn set_theme(&self, theme: AppTheme, window: &tauri::Window) -> Result<(), Box<dyn std::error::Error>> {
                let theme_to_apply = match theme {
                    AppTheme::Auto => {
                        // 根据系统主题决定
                        if is_dark_mode() {
                            tauri::Theme::Dark
                        } else {
                            tauri::Theme::Light
                        }
                    }
                    AppTheme::Light => tauri::Theme::Light,
                    AppTheme::Dark => tauri::Theme::Dark,
                };

                window.set_theme(theme_to_apply)?;

                let mut current = self.current_theme.lock().unwrap();
                *current = theme;

                // 通知前端主题变化
                window.emit("theme-changed", &theme)?;

                Ok(())
            }
        }

        fn is_dark_mode() -> bool {
            // 实现系统主题检测逻辑
            // 这里可以根据操作系统API检测
            false
        }

        #[tauri::command]
        async fn switch_theme(
            theme: AppTheme,
            window: tauri::Window,
            theme_manager: tauri::State<'_, ThemeManager>
        ) -> Result<(), String> {
            theme_manager.set_theme(theme, &window)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        async fn get_current_theme(
            theme_manager: tauri::State<'_, ThemeManager>
        ) -> Result<AppTheme, String> {
            let theme = theme_manager.current_theme.lock().unwrap();
            Ok((*theme).clone())
        }
    c.窗口动画效果
        use std::time::Duration;

        #[tauri::command]
        async fn animate_window_transition(
            window: tauri::Window,
            from_size: (f64, f64),
            to_size: (f64, f64),
            duration_ms: u64
        ) -> Result<(), String> {
            let steps = 30;
            let step_duration = Duration::from_millis(duration_ms / steps);

            for i in 0..steps {
                let progress = (i + 1) as f64 / steps as f64;
                let current_width = from_size.0 + (to_size.0 - from_size.0) * progress;
                let current_height = from_size.1 + (to_size.1 - from_size.1) * progress;

                window.set_size(tauri::Size::Physical(
                    (current_width as u32, current_height as u32)
                )).map_err(|e| e.to_string())?;

                tokio::time::sleep(step_duration).await;
            }

            Ok(())
        }

        #[tauri::command]
        async fn fade_in_window(
            window: tauri::Window
        ) -> Result<(), String> {
            // 先设置窗口透明
            window.set_decorations(false).map_err(|e| e.to_string())?;

            // 逐步增加不透明度
            for i in 0..10 {
                let opacity = (i + 1) as f64 / 10.0;
                // 注意:这里需要特定平台API来设置透明度
                tokio::time::sleep(Duration::from_millis(50)).await;
            }

            // 显示装饰
            window.set_decorations(true).map_err(|e| e.to_string())?;

            Ok(())
        }

4.2 菜单系统

01.主菜单创建
    a.应用菜单结构
        use tauri::{CustomMenuItem, Menu, MenuItem, Submenu};

        fn create_application_menu() -> Result<Menu, Box<dyn std::error::Error>> {
            let file_menu = Submenu::new(
                "文件(&F)",
                Menu::new()
                    .add_native_item(MenuItem::About("My App".to_string()))
                    .add_item(CustomMenuItem::new("new", "新建(&N)").accelerator("CmdOrCtrl+N"))
                    .add_item(CustomMenuItem::new("open", "打开(&O)").accelerator("CmdOrCtrl+O"))
                    .add_item(CustomMenuItem::new("save", "保存(&S)").accelerator("CmdOrCtrl+S"))
                    .add_native_item(MenuItem::Separator)
                    .add_native_item(MenuItem::Quit)
            );

            let edit_menu = Submenu::new(
                "编辑(&E)",
                Menu::new()
                    .add_native_item(MenuItem::Undo)
                    .add_native_item(MenuItem::Redo)
                    .add_native_item(MenuItem::Separator)
                    .add_native_item(MenuItem::Cut)
                    .add_native_item(MenuItem::Copy)
                    .add_native_item(MenuItem::Paste)
                    .add_native_item(MenuItem::SelectAll)
            );

            let view_menu = Submenu::new(
                "视图(&V)",
                Menu::new()
                    .add_item(CustomMenuItem::new("toggle-toolbar", "工具栏(&T)"))
                    .add_item(CustomMenuItem::new("toggle-sidebar", "侧边栏(&S)"))
                    .add_native_item(MenuItem::Separator)
                    .add_native_item(MenuItem::ZoomIn)
                    .add_native_item(MenuItem::ZoomOut)
                    .add_native_item(MenuItem::ZoomReset)
                    .add_native_item(MenuItem::Separator)
                    .add_native_item(MenuItem::ToggleFullScreen)
            );

            let window_menu = Submenu::new(
                "窗口(&W)",
                Menu::new()
                    .add_item(CustomMenuItem::new("minimize", "最小化"))
                    .add_item(CustomMenuItem::new("maximize", "最大化"))
                    .add_native_item(MenuItem::Separator)
                    .add_item(CustomMenuItem::new("bring-all-to-front", "全部前置"))
            );

            let help_menu = Submenu::new(
                "帮助(&H)",
                Menu::new()
                    .add_item(CustomMenuItem::new("documentation", "文档(&D)"))
                    .add_item(CustomMenuItem::new("check-updates", "检查更新(&U)"))
                    .add_native_item(MenuItem::Separator)
                    .add_native_item(MenuItem::About("My App".to_string()))
            );

            let menu = Menu::new()
                .add_submenu(file_menu)
                .add_submenu(edit_menu)
                .add_submenu(view_menu)
                .add_submenu(window_menu)
                .add_submenu(help_menu);

            Ok(menu)
        }
    b.菜单事件处理
        use tauri::{Manager, MenuEvent};

        fn setup_menu_handlers(app: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> {
            let menu = create_application_menu()?;

            // 获取主窗口
            let window = app.get_window("main").unwrap();

            // 设置菜单事件处理器
            let window_clone = window.clone();
            menu.on_menu_event(move |event| {
                handle_menu_event(event, &window_clone);
            });

            // 应用菜单到窗口
            window.set_menu(menu)?;

            Ok(())
        }

        fn handle_menu_event(event: MenuEvent, window: &tauri::Window) {
            match event.id().as_ref() {
                "new" => {
                    println!("新建文件");
                    window.emit("menu-new", {}).unwrap();
                }
                "open" => {
                    println!("打开文件");
                    open_file_dialog(window);
                }
                "save" => {
                    println!("保存文件");
                    window.emit("menu-save", {}).unwrap();
                }
                "toggle-toolbar" => {
                    println!("切换工具栏");
                    window.emit("toggle-toolbar", {}).unwrap();
                }
                "toggle-sidebar" => {
                    println!("切换侧边栏");
                    window.emit("toggle-sidebar", {}).unwrap();
                }
                "minimize" => {
                    println!("最小化窗口");
                    let _ = window.minimize();
                }
                "maximize" => {
                    println!("切换最大化");
                    if window.is_maximized().unwrap_or(false) {
                        let _ = window.unmaximize();
                    } else {
                        let _ = window.maximize();
                    }
                }
                "documentation" => {
                    println!("打开文档");
                    tauri::api::shell::open(&window.shell_scope(), "https://docs.tauri.app/", None)
                        .unwrap();
                }
                "check-updates" => {
                    println!("检查更新");
                    check_for_updates(window);
                }
                _ => {
                    println!("未知菜单项: {}", event.id());
                }
            }
        }

        fn open_file_dialog(window: &tauri::Window) {
            tauri::api::dialog::FileDialogBuilder::new()
                .add_filter("文本文件", &["txt", "md"])
                .add_filter("所有文件", &["*"])
                .pick_file(|file_path| {
                    if let Some(path) = file_path {
                        window.emit("file-selected", path).unwrap();
                    }
                });
        }

        async fn check_for_updates(window: &tauri::Window) {
            // 检查更新的逻辑
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            window.emit("update-check-complete", {"has_update": false, "version": "1.0.0"}).unwrap();
        }
    c.动态菜单更新
        use std::sync::{Arc, Mutex};

        struct MenuState {
            is_dirty: Arc<Mutex<bool>>,
            recent_files: Arc<Mutex<Vec<String>>>,
        }

        impl MenuState {
            fn new() -> Self {
                Self {
                    is_dirty: Arc::new(Mutex::new(false)),
                    recent_files: Arc::new(Mutex::new(Vec::new())),
                }
            }

            fn set_dirty(&self, dirty: bool) {
                *self.is_dirty.lock().unwrap() = dirty;
                self.update_menu();
            }

            fn add_recent_file(&self, path: String) {
                let mut recent_files = self.recent_files.lock().unwrap();

                // 移除已存在的文件
                recent_files.retain(|f| f != &path);

                // 添加到开头
                recent_files.insert(0, path);

                // 限制最近文件数量
                if recent_files.len() > 10 {
                    recent_files.truncate(10);
                }

                self.update_menu();
            }

            fn update_menu(&self) {
                // 这里需要重新构建菜单
                // 实际实现中需要重新调用app.set_menu()
            }
        }

        #[tauri::command]
        async fn mark_dirty(
            menu_state: tauri::State<'_, MenuState>
        ) -> Result<(), String> {
            menu_state.set_dirty(true);
            Ok(())
        }

        #[tauri::command]
        async fn add_recent_file(
            path: String,
            menu_state: tauri::State<'_, MenuState>
        ) -> Result<(), String> {
            menu_state.add_recent_file(path);
            Ok(())
        }
        ---

02.上下文菜单
    a.自定义上下文菜单
        use tauri::{Manager, window};

        #[tauri::command]
        async fn show_context_menu(
            window: tauri::Window,
            x: f64,
            y: f64
        ) -> Result<(), String> {
            let menu = tauri::Menu::new()
                .add_item(tauri::CustomMenuItem::new("cut", "剪切").accelerator("CmdOrCtrl+X"))
                .add_item(tauri::CustomMenuItem::new("copy", "复制").accelerator("CmdOrCtrl+C"))
                .add_item(tauri::CustomMenuItem::new("paste", "粘贴").accelerator("CmdOrCtrl+V"))
                .add_native_item(tauri::MenuItem::Separator)
                .add_item(tauri::CustomMenuItem::new("select-all", "全选").accelerator("CmdOrCtrl+A"));

            // 显示上下文菜单
            menu.show().map_err(|e| e.to_string())?;

            Ok(())
        }

        #[tauri::command]
        async fn show_text_context_menu(
            window: tauri::Window,
            x: f64,
            y: f64,
            has_selection: bool
        ) -> Result<(), String> {
            let mut menu = tauri::Menu::new();

            if has_selection {
                menu = menu
                    .add_item(tauri::CustomMenuItem::new("cut", "剪切").accelerator("CmdOrCtrl+X"))
                    .add_item(tauri::CustomMenuItem::new("copy", "复制").accelerator("CmdOrCtrl+C"));
            }

            menu = menu
                .add_item(tauri::CustomMenuItem::new("paste", "粘贴").accelerator("CmdOrCtrl+V"))
                .add_native_item(tauri::MenuItem::Separator)
                .add_item(tauri::CustomMenuItem::new("select-all", "全选").accelerator("CmdOrCtrl+A"));

            menu.show().map_err(|e| e.to_string())?;

            Ok(())
        }

        // 前端右键菜单
        import { invoke } from '@tauri-apps/api/tauri';

        document.addEventListener('contextmenu', (event) => {
            event.preventDefault();

            const target = event.target as HTMLElement;
            const rect = target.getBoundingClientRect();

            // 检查是否有选中文本
            const hasSelection = window.getSelection()?.toString() !== '';

            // 显示上下文菜单
            if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
                invoke('show_text_context_menu', {
                    x: event.clientX,
                    y: event.clientY,
                    hasSelection: hasSelection
                });
            } else {
                invoke('show_context_menu', {
                    x: event.clientX,
                    y: event.clientY
                });
            }
        });
    b.动态上下文菜单
        use serde::{Deserialize, Serialize};

        #[derive(Serialize, Deserialize)]
        struct ContextMenuContext {
            x: f64,
            y: f64,
            target_type: String,
            target_id: String,
            additional_data: serde_json::Value,
        }

        #[tauri::command]
        async fn show_dynamic_context_menu(
            window: tauri::Window,
            context: ContextMenuContext
        ) -> Result<(), String> {
            let mut menu = tauri::Menu::new();

            // 根据上下文添加不同的菜单项
            match context.target_type.as_str() {
                "file" => {
                    menu = menu
                        .add_item(tauri::CustomMenuItem::new("open", "打开"))
                        .add_item(tauri::CustomMenuItem::new("edit", "编辑"))
                        .add_item(tauri::CustomMenuItem::new("rename", "重命名"))
                        .add_native_item(tauri::MenuItem::Separator)
                        .add_item(tauri::CustomMenuItem::new("delete", "删除"));
                }
                "folder" => {
                    menu = menu
                        .add_item(tauri::CustomMenuItem::new("open", "打开"))
                        .add_item(tauri::CustomMenuItem::new("new-file", "新建文件"))
                        .add_item(tauri::CustomMenuItem::new("rename", "重命名"))
                        .add_native_item(tauri::MenuItem::Separator)
                        .add_item(tauri::CustomMenuItem::new("delete", "删除"));
                }
                "image" => {
                    menu = menu
                        .add_item(tauri::CustomMenuItem::new("open-image", "打开图片"))
                        .add_item(tauri::CustomMenuItem::new("edit-image", "编辑"))
                        .add_native_item(tauri::MenuItem::Separator)
                        .add_item(tauri::CustomMenuItem::new("set-wallpaper", "设为壁纸"));
                }
                _ => {
                    menu = menu
                        .add_item(tauri::CustomMenuItem::new("refresh", "刷新"))
                        .add_item(tauri::CustomMenuItem::new("properties", "属性"));
                }
            }

            menu.show().map_err(|e| e.to_string())?;

            Ok(())
        }
    c.菜单项状态管理
        #[derive(Clone)]
        struct MenuItemState {
            enabled: bool,
            checked: bool,
            visible: bool,
        }

        struct MenuManager {
            item_states: Arc<Mutex<std::collections::HashMap<String, MenuItemState>>>,
        }

        impl MenuManager {
            fn new() -> Self {
                Self {
                    item_states: Arc::new(Mutex::new(std::collections::HashMap::new())),
                }
            }

            fn set_item_state(&self, id: &str, enabled: bool, checked: bool, visible: bool) {
                let mut states = self.item_states.lock().unwrap();
                states.insert(id.to_string(), MenuItemState {
                    enabled,
                    checked,
                    visible,
                });
            }

            fn get_item_state(&self, id: &str) -> Option<MenuItemState> {
                let states = self.item_states.lock().unwrap();
                states.get(id).cloned()
            }

            fn update_menu_item(&self, id: &str, window: &tauri::Window) {
                if let Some(state) = self.get_item_state(id) {
                    // 更新菜单项状态的具体实现
                    // 这里需要重新构建菜单或使用特定API
                    window.emit("menu-item-state-changed", {
                        id,
                        enabled: state.enabled,
                        checked: state.checked,
                        visible: state.visible
                    }).unwrap();
                }
            }
        }

        #[tauri::command]
        async fn update_menu_state(
            id: String,
            enabled: bool,
            checked: bool,
            visible: bool,
            menu_manager: tauri::State<'_, MenuManager>,
            window: tauri::Window
        ) -> Result<(), String> {
            menu_manager.set_item_state(&id, enabled, checked, visible);
            menu_manager.update_menu_item(&id, &window);
            Ok(())
        }
        ---

03.快捷键管理
    a.全局快捷键
        use tauri::{GlobalShortcutManager, Manager};

        fn setup_global_shortcuts(app: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> {
            let window = app.get_window("main").unwrap();

            // 注册全局快捷键
            let shortcut_manager = app.global_shortcut_manager();

            // Ctrl+N: 新建文件
            shortcut_manager.register("CmdOrCtrl+N", move || {
                window.emit("global-shortcut-new", {}).unwrap();
            })?;

            // Ctrl+S: 保存文件
            shortcut_manager.register("CmdOrCtrl+S", move || {
                window.emit("global-shortcut-save", {}).unwrap();
            })?;

            // Ctrl+Shift+I: 切换开发者工具
            shortcut_manager.register("CmdOrCtrl+Shift+I", move || {
                if window.is_devtools_open().unwrap_or(false) {
                    let _ = window.close_devtools();
                } else {
                    let _ = window.open_devtools();
                }
            })?;

            // F11: 切换全屏
            shortcut_manager.register("F11", move || {
                if window.is_fullscreen().unwrap_or(false) {
                    let _ = window.set_fullscreen(false);
                } else {
                    let _ = window.set_fullscreen(true);
                }
            })?;

            Ok(())
        }

        // 前端监听全局快捷键事件
        import { listen } from '@tauri-apps/api/event';

        async function setupGlobalShortcutListeners() {
            await listen('global-shortcut-new', () => {
                console.log('全局快捷键: 新建文件');
                handleNewFile();
            });

            await listen('global-shortcut-save', () => {
                console.log('全局快捷键: 保存文件');
                handleSaveFile();
            });
        }
    b.窗口快捷键
        use tauri::{KeyboardShortcut, Manager};

        fn setup_window_shortcuts(window: &tauri::Window) -> Result<(), Box<dyn std::error::Error>> {
            // Esc: 关闭对话框或取消操作
            let window_clone = window.clone();
            window.on_keyboard_event(move |event| {
                if event.key == "Escape" {
                    window_clone.emit("escape-pressed", {}).unwrap();
                }
                false // 不阻止事件传播
            });

            // Enter: 确认操作
            let window_clone = window.clone();
            window.on_keyboard_event(move |event| {
                if event.key == "Enter" && !event.modifiers.shift {
                    window_clone.emit("enter-pressed", {}).unwrap();
                }
                false
            });

            // Ctrl+Z: 撤销
            let window_clone = window.clone();
            window.on_keyboard_event(move |event| {
                if event.key == "z" && event.modifiers.control {
                    window_clone.emit("undo-pressed", {}).unwrap();
                }
                false
            });

            // Ctrl+Y: 重做
            let window_clone = window.clone();
            window.on_keyboard_event(move |event| {
                if event.key == "y" && event.modifiers.control {
                    window_clone.emit("redo-pressed", {}).unwrap();
                }
                false
            });

            Ok(())
        }

        #[tauri::command]
        async fn register_window_shortcut(
            window: tauri::Window,
            shortcut: String,
            event_name: String
        ) -> Result<(), String> {
            // 注册窗口级快捷键
            // 这里需要具体的实现逻辑
            Ok(())
        }
    c.快捷键配置管理
        use serde::{Deserialize, Serialize};
        use std::collections::HashMap;

        #[derive(Serialize, Deserialize, Clone)]
        struct ShortcutConfig {
            enabled: bool,
            key_combination: String,
            action: String,
        }

        struct ShortcutManager {
            configs: Arc<Mutex<HashMap<String, ShortcutConfig>>>,
        }

        impl ShortcutManager {
            fn new() -> Self {
                Self {
                    configs: Arc::new(Mutex::new(HashMap::new())),
                }
            }

            fn load_default_configs(&self) {
                let configs = [
                    ("new_file", ShortcutConfig {
                        enabled: true,
                        key_combination: "CmdOrCtrl+N".to_string(),
                        action: "new_file".to_string(),
                    }),
                    ("save_file", ShortcutConfig {
                        enabled: true,
                        key_combination: "CmdOrCtrl+S".to_string(),
                        action: "save_file".to_string(),
                    }),
                    ("open_file", ShortcutConfig {
                        enabled: true,
                        key_combination: "CmdOrCtrl+O".to_string(),
                        action: "open_file".to_string(),
                    }),
                    ("undo", ShortcutConfig {
                        enabled: true,
                        key_combination: "CmdOrCtrl+Z".to_string(),
                        action: "undo".to_string(),
                    }),
                    ("redo", ShortcutConfig {
                        enabled: true,
                        key_combination: "CmdOrCtrl+Y".to_string(),
                        action: "redo".to_string(),
                    }),
                ];

                let mut config_map = self.configs.lock().unwrap();
                for (id, config) in configs.iter() {
                    config_map.insert(id.to_string(), config.clone());
                }
            }

            fn update_config(&self, id: &str, config: ShortcutConfig) {
                let mut configs = self.configs.lock().unwrap();
                configs.insert(id.to_string(), config);
            }

            fn get_config(&self, id: &str) -> Option<ShortcutConfig> {
                let configs = self.configs.lock().unwrap();
                configs.get(id).cloned()
            }

            fn get_all_configs(&self) -> HashMap<String, ShortcutConfig> {
                let configs = self.configs.lock().unwrap();
                configs.clone()
            }
        }

        #[tauri::command]
        async fn update_shortcut_config(
            id: String,
            config: ShortcutConfig,
            shortcut_manager: tauri::State<'_, ShortcutManager>
        ) -> Result<(), String> {
            shortcut_manager.update_config(&id, config);
            Ok(())
        }

        #[tauri::command]
        async fn get_all_shortcuts(
            shortcut_manager: tauri::State<'_, ShortcutManager>
        ) -> Result<HashMap<String, ShortcutConfig>, String> {
            Ok(shortcut_manager.get_all_configs())
        }

        #[tauri::command]
        async fn save_shortcuts_to_file(
            shortcut_manager: tauri::State<'_, ShortcutManager>
        ) -> Result<(), String> {
            let configs = shortcut_manager.get_all_configs();
            let json = serde_json::to_string(&configs).map_err(|e| e.to_string())?;

            std::fs::write("shortcuts.json", json)
                .map_err(|e| e.to_string())?;

            Ok(())
        }

5 进程通信

5.1 IPC基础

01.IPC架构概述
    a.通信模型
        前端WebView和Rust后端之间的安全通信桥梁
        基于命令模式的消息传递机制
        支持同步和异步通信方式
    b.类型安全
        编译时类型检查确保API安全性
        Rust类型系统提供强类型保证
        TypeScript接口定义确保前端类型安全
    c.安全隔离
        前端运行在沙箱环境中
        后端权限严格控制
        消息传输经过验证和过滤

02.命令系统基础
    a.命令定义
        // src-tauri/src/commands.rs
        use tauri::command;
        use serde::{Deserialize, Serialize};

        #[derive(Serialize, Deserialize)]
        struct GreetRequest {
            name: String,
            age: Option<u32>,
        }

        #[derive(Serialize)]
        struct GreetResponse {
            message: String,
            timestamp: String,
        }

        #[command]
        fn greet(request: GreetRequest) -> Result<GreetResponse, String> {
            if request.name.is_empty() {
                return Err("姓名不能为空".to_string());
            }

            let message = if let Some(age) = request.age {
                format!("你好,{}!你今年{}岁了。", request.name, age)
            } else {
                format!("你好,{}!", request.name)
            };

            Ok(GreetResponse {
                message,
                timestamp: chrono::Utc::now().to_rfc3339(),
            })
        }
    b.命令注册
        // src-tauri/src/main.rs
        mod commands;

        use tauri::Manager;

        fn main() {
            tauri::Builder::default()
                .invoke_handler(tauri::generate_handler![
                    commands::greet,
                    commands::get_system_info,
                    commands::read_file,
                    commands::write_file,
                    commands::calculate_sum
                ])
                .run(tauri::generate_context!())
                .expect("运行应用失败");
        }
    c.错误处理
        use thiserror::Error;

        #[derive(Error, Debug)]
        enum AppError {
            #[error("输入验证失败: {0}")]
            Validation(String),
            #[error("文件操作失败: {0}")]
            FileOperation(String),
            #[error("系统错误: {0}")]
            System(String),
        }

        impl From<std::io::Error> for AppError {
            fn from(error: std::io::Error) -> Self {
                AppError::FileOperation(error.to_string())
            }
        }

        #[tauri::command]
        fn safe_file_operation(path: String) -> Result<String, AppError> {
            // 参数验证
            if path.is_empty() {
                return Err(AppError::Validation("文件路径不能为空".to_string()));
            }

            // 安全检查
            if path.contains("..") {
                return Err(AppError::Validation("不安全的文件路径".to_string()));
            }

            // 文件操作
            let content = std::fs::read_to_string(&path)?;
            Ok(content)
        }
        ---

03.消息序列化
    a.JSON序列化
        use serde::{Deserialize, Serialize};

        #[derive(Serialize, Deserialize)]
        struct ComplexData {
            id: u64,
            name: String,
            items: Vec<String>,
            metadata: Metadata,
            timestamp: chrono::DateTime<chrono::Utc>,
        }

        #[derive(Serialize, Deserialize)]
        struct Metadata {
            version: String,
            author: String,
            tags: Vec<String>,
        }

        #[tauri::command]
        async fn process_complex_data(data: ComplexData) -> Result<ComplexData, String> {
            // 处理复杂数据结构
            let mut processed_data = data;
            processed_data.timestamp = chrono::Utc::now();

            // 添加处理标签
            processed_data.metadata.tags.push("processed".to_string());

            Ok(processed_data)
        }
    b.二进制数据处理
        #[tauri::command]
        async fn upload_image(
            image_data: Vec<u8>,
            filename: String
        ) -> Result<String, String> {
            // 验证文件名
            if !filename.ends_with(".jpg") && !filename.ends_with(".png") {
                return Err("只支持JPG和PNG格式".to_string());
            }

            // 验证文件大小(最大10MB)
            if image_data.len() > 10 * 1024 * 1024 {
                return Err("文件大小超过10MB限制".to_string());
            }

            // 保存文件
            let save_path = format!("uploads/{}", filename);
            std::fs::write(&save_path, image_data)
                .map_err(|e| e.to_string())?;

            Ok(save_path)
        }

        #[tauri::command]
        async fn download_image(file_path: String) -> Result<Vec<u8>, String> {
            // 安全检查
            if file_path.contains("..") || !file_path.starts_with("uploads/") {
                return Err("不安全的文件路径".to_string());
            }

            // 读取文件
            let data = std::fs::read(&file_path)
                .map_err(|e| e.to_string())?;

            Ok(data)
        }
    c.自定义序列化
        use serde_json;

        #[tauri::command]
        async fn custom_serialize_operation(
            input: serde_json::Value
        ) -> Result<serde_json::Value, String> {
            // 自定义序列化逻辑
            match input {
                serde_json::Value::Object(map) => {
                    let mut result = serde_json::Map::new();

                    for (key, value) in map {
                        // 对每个键值进行处理
                        let processed_key = key.to_uppercase();
                        result.insert(processed_key, process_value(value));
                    }

                    Ok(serde_json::Value::Object(result))
                }
                _ => Err("输入必须是对象类型".to_string()),
            }
        }

        fn process_value(value: serde_json::Value) -> serde_json::Value {
            match value {
                serde_json::Value::String(s) => {
                    serde_json::Value::String(s.to_uppercase())
                }
                serde_json::Value::Number(n) => {
                    if let Some(i) = n.as_i64() {
                        serde_json::Value::Number(serde_json::Number::from(i * 2))
                    } else {
                        value
                    }
                }
                other => other,
            }
        }

5.2 前端调用后端

01.基础命令调用
    a.同步调用
        // src/api/tauri.ts
        import { invoke } from '@tauri-apps/api/tauri';

        export interface GreetRequest {
            name: string;
            age?: number;
        }

        export interface GreetResponse {
            message: string;
            timestamp: string;
        }

        export class TauriAPI {
            // 同步调用示例
            async greet(request: GreetRequest): Promise<GreetResponse> {
                try {
                    const response = await invoke<GreetResponse>('greet', request);
                    return response;
                } catch (error) {
                    console.error('调用失败:', error);
                    throw new Error(`greet命令失败: ${error}`);
                }
            }

            // 简单的同步调用
            async getSystemInfo(): Promise<any> {
                return await invoke('get_system_info');
            }
        }

        export const tauriAPI = new TauriAPI();
    b.异步调用处理
        export class AsyncTauriAPI {
            private pendingRequests: Map<string, Promise<any>>;

            constructor() {
                this.pendingRequests = new Map();
            }

            // 带缓存的异步调用
            async getCachedData<T>(key: string, command: string, params?: any): Promise<T> {
                if (this.pendingRequests.has(key)) {
                    return this.pendingRequests.get(key);
                }

                const promise = invoke<T>(command, params).catch(error => {
                    console.error(`命令 ${command} 失败:`, error);
                    throw error;
                });

                this.pendingRequests.set(key, promise);

                // 缓存5分钟
                setTimeout(() => {
                    this.pendingRequests.delete(key);
                }, 5 * 60 * 1000);

                return promise;
            }

            // 带重试的异步调用
            async withRetry<T>(
                command: string,
                params: any,
                maxRetries: number = 3,
                delay: number = 1000
            ): Promise<T> {
                let lastError: any;

                for (let i = 0; i <= maxRetries; i++) {
                    try {
                        return await invoke<T>(command, params);
                    } catch (error) {
                        lastError = error;

                        if (i < maxRetries) {
                            await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
                        }
                    }
                }

                throw lastError;
            }
        }
    c.类型安全调用
        // 使用TypeScript接口定义
        interface SystemInfo {
            platform: string;
            arch: string;
            version: string;
            memory: {
                total: number;
                available: number;
                used: number;
            };
        }

        class TypeSafeTauriAPI {
            // 类型安全的命令调用
            async getSystemInfo(): Promise<SystemInfo> {
                return await invoke<SystemInfo>('get_system_info');
            }

            // 带泛型的命令调用
            async executeCommand<T, P = any>(
                command: string,
                params?: P
            ): Promise<T> {
                return await invoke<T>(command, params);
            }

            // 类型化的文件操作
            async readTextFile(filePath: string): Promise<string> {
                if (!filePath.endsWith('.txt') && !filePath.endsWith('.md')) {
                    throw new Error('只支持文本文件');
                }
                return await invoke<string>('read_text_file', { path: filePath });
            }

            async writeTextFile(filePath: string, content: string): Promise<void> {
                if (!filePath.endsWith('.txt') && !filePath.endsWith('.md')) {
                    throw new Error('只支持文本文件');
                }
                return await invoke<void>('write_text_file', {
                    path: filePath,
                    content
                });
            }
        }

        export const typeSafeAPI = new TypeSafeTauriAPI();
        ---

02.高级调用模式
    a.批量操作
        class BatchTauriAPI {
            private batchSize = 10;

            async batchExecute<T>(requests: Array<{
                command: string;
                params?: any;
            }>): Promise<Array<T>> {
                const results: Array<T> = [];

                for (let i = 0; i < requests.length; i += this.batchSize) {
                    const batch = requests.slice(i, i + this.batchSize);
                    const batchResults = await Promise.all(
                        batch.map(req => this.safeExecute<T>(req.command, req.params))
                    );
                    results.push(...batchResults);

                    // 避免过于频繁的调用
                    if (i + this.batchSize < requests.length) {
                        await new Promise(resolve => setTimeout(resolve, 100));
                    }
                }

                return results;
            }

            private async safeExecute<T>(command: string, params: any): Promise<T> {
                try {
                    return await invoke<T>(command, params);
                } catch (error) {
                    console.error(`批量执行失败 ${command}:`, error);
                    throw error;
                }
            }

            // 并发控制
            async concurrentExecute<T>(
                requests: Array<{ command: string; params?: any }>,
                concurrency: number = 5
            ): Promise<Array<T>> {
                const results: Array<T> = [];
                const executing: Array<Promise<T>> = [];

                for (const request of requests) {
                    const promise = this.safeExecute<T>(request.command, request.params);
                    executing.push(promise);

                    if (executing.length >= concurrency) {
                        const completed = await Promise.race(executing);
                        results.push(completed);

                        const index = executing.findIndex(p => p === completed);
                        executing.splice(index, 1);
                    }
                }

                // 等待剩余的请求完成
                const remainingResults = await Promise.all(executing);
                results.push(...remainingResults);

                return results;
            }
        }
    b.流式数据处理
        class StreamingTauriAPI {
            private eventEmitter: EventTarget;

            constructor() {
                this.eventEmitter = new EventTarget();
            }

            // 流式读取大文件
            async streamReadFile(filePath: string, chunkSize: number = 1024 * 1024): Promise<void> {
                try {
                    const chunks = await invoke<Array<string>>('stream_read_file', {
                        path: filePath,
                        chunkSize
                    });

                    for (let i = 0; i < chunks.length; i++) {
                        const chunk = chunks[i];

                        // 发送数据块事件
                        this.emit('data-chunk', {
                            data: chunk,
                            index: i,
                            total: chunks.length
                        });

                        // 允许事件处理
                        await new Promise(resolve => setTimeout(resolve, 0));
                    }

                    this.emit('stream-complete', {
                        filePath,
                        totalChunks: chunks.length
                    });
                } catch (error) {
                    this.emit('stream-error', { filePath, error });
                    throw error;
                }
            }

            // 事件发射器
            private emit(eventName: string, data: any) {
                const event = new CustomEvent(eventName, { detail: data });
                this.eventEmitter.dispatchEvent(event);
            }

            // 事件监听器
            on(eventName: string, handler: (data: any) => void) {
                this.eventEmitter.addEventListener(eventName, (event: any) => {
                    handler(event.detail);
                });
            }

            off(eventName: string, handler: (data: any) => void) {
                this.eventEmitter.removeEventListener(eventName, handler);
            }
        }
    c.会话管理
        class SessionTauriAPI {
            private sessionId: string;
            private messageQueue: Array<any> = [];
            private isConnected = false;

            constructor() {
                this.sessionId = this.generateSessionId();
                this.setupHeartbeat();
            }

            private generateSessionId(): string {
                return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
            }

            async initialize(): Promise<void> {
                try {
                    // 初始化会话
                    await invoke('initialize_session', {
                        sessionId: this.sessionId
                    });

                    this.isConnected = true;

                    // 处理排队的消息
                    await this.processQueue();

                    // 设置事件监听
                    this.setupEventListeners();
                } catch (error) {
                    console.error('会话初始化失败:', error);
                    throw error;
                }
            }

            async executeWithSession<T>(command: string, params?: any): Promise<T> {
                if (!this.isConnected) {
                    throw new Error('会话未初始化');
                }

                return await invoke<T>(command, {
                    ...params,
                    sessionId: this.sessionId
                });
            }

            // 消息队列处理
            private async processQueue() {
                while (this.messageQueue.length > 0 && this.isConnected) {
                    const message = this.messageQueue.shift();
                    try {
                        await this.executeWithSession(message.command, message.params);
                    } catch (error) {
                        console.error('处理队列消息失败:', error);
                    }
                }
            }

            // 心跳机制
            private setupHeartbeat() {
                setInterval(async () => {
                    if (this.isConnected) {
                        try {
                            await invoke('heartbeat', { sessionId: this.sessionId });
                        } catch (error) {
                            console.error('心跳失败:', error);
                            this.isConnected = false;
                        }
                    }
                }, 30000); // 30秒心跳
            }

            private setupEventListeners() {
                // 监听会话断开事件
                const unlisten = tauri.event.listen('session-disconnected', (event) => {
                    if (event.payload.sessionId === this.sessionId) {
                        this.isConnected = false;
                        console.warn('会话已断开');
                    }
                });

                // 在组件卸载时清理监听器
                window.addEventListener('beforeunload', () => {
                    unlisten();
                });
            }
        }
        ---

03.调用优化策略
    a.缓存机制
        class CacheTauriAPI {
            private cache: Map<string, { data: any; timestamp: number }>;
            private ttl: number; // 缓存时间(毫秒)

            constructor(ttl: number = 5 * 60 * 1000) { // 默认5分钟
                this.cache = new Map();
                this.ttl = ttl;
            }

            async cachedInvoke<T>(
                cacheKey: string,
                command: string,
                params?: any,
                customTtl?: number
            ): Promise<T> {
                const now = Date.now();
                const cached = this.cache.get(cacheKey);

                if (cached && (now - cached.timestamp) < this.ttl) {
                    return cached.data;
                }

                try {
                    const data = await invoke<T>(command, params);

                    this.cache.set(cacheKey, {
                        data,
                        timestamp: now
                    });

                    // 设置过期清理
                    setTimeout(() => {
                        this.cache.delete(cacheKey);
                    }, customTtl || this.ttl);

                    return data;
                } catch (error) {
                    console.error(`缓存调用失败 ${command}:`, error);
                    throw error;
                }
            }

            clearCache(pattern?: string): void {
                if (pattern) {
                    const regex = new RegExp(pattern);
                    for (const key of this.cache.keys()) {
                        if (regex.test(key)) {
                            this.cache.delete(key);
                        }
                    }
                } else {
                    this.cache.clear();
                }
            }

            getCacheInfo(): { size: number; keys: string[] } {
                return {
                    size: this.cache.size,
                    keys: Array.from(this.cache.keys())
                };
            }
        }
    b.请求去重
        class DebounceTauriAPI {
            private pendingRequests: Map<string, Promise<any>>;
            private debounceTime: number;

            constructor(debounceTime: number = 300) {
                this.pendingRequests = new Map();
                this.debounceTime = debounceTime;
            }

            async debouncedInvoke<T>(
                key: string,
                command: string,
                params?: any
            ): Promise<T> {
                if (this.pendingRequests.has(key)) {
                    return this.pendingRequests.get(key);
                }

                const promise = new Promise<T>((resolve, reject) => {
                    setTimeout(async () => {
                        try {
                            const result = await invoke<T>(command, params);
                            this.pendingRequests.delete(key);
                            resolve(result);
                        } catch (error) {
                            this.pendingRequests.delete(key);
                            reject(error);
                        }
                    }, this.debounceTime);
                });

                this.pendingRequests.set(key, promise);
                return promise;
            }

            isPending(key: string): boolean {
                return this.pendingRequests.has(key);
            }

            clearPending(key?: string): void {
                if (key) {
                    this.pendingRequests.delete(key);
                } else {
                    this.pendingRequests.clear();
                }
            }
        }
    c.调用链管理
        class ChainTauriAPI {
            private chain: Array<() => Promise<any>>;

            constructor() {
                this.chain = [];
            }

            // 添加链式调用
            addStep<T>(command: string, params?: any): ChainTauriAPI {
                this.chain.push(async () => {
                    return await invoke<T>(command, params);
                });
                return this;
            }

            // 添加异步步骤
            addAsyncStep<T>(step: () => Promise<T>): ChainTauriAPI {
                this.chain.push(step);
                return this;
            }

            // 执行整个调用链
            async execute(): Promise<any[]> {
                const results = [];

                for (const step of this.chain) {
                    try {
                        const result = await step();
                        results.push(result);
                    } catch (error) {
                        console.error('调用链执行失败:', error);
                        throw error;
                    }
                }

                return results;
            }

            // 清空调用链
            clear(): ChainTauriAPI {
                this.chain = [];
                return this;
            }

            // 获取调用链长度
            length(): number {
                return this.chain.length;
            }
        }

        // 使用示例
        const chainAPI = new ChainTauriAPI();

        const result = await chainAPI
            .addStep('initialize_system')
            .addStep('load_config', { profile: 'default' })
            .addStep('setup_database')
            .addAsyncStep(async () => {
                // 自定义异步操作
                await new Promise(resolve => setTimeout(resolve, 1000));
                return 'custom-step-result';
            })
            .addStep('start_application')
            .execute();

5.3 后端通知前端

01.事件广播机制
    a.单窗口事件
        use tauri::{Manager, Window};

        #[tauri::command]
        async fn send_notification_to_window(
            window: tauri::Window,
            title: String,
            message: String,
            level: String
        ) -> Result<(), String> {
            let notification_data = NotificationData {
                title,
                message,
                level: if level.is_empty() { "info".to_string() } else { level },
                timestamp: chrono::Utc::now().to_rfc3339(),
            };

            window.emit("notification", &notification_data)
                .map_err(|e| e.to_string())
        }

        #[derive(serde::Serialize)]
        struct NotificationData {
            title: String,
            message: String,
            level: String,
            timestamp: String,
        }
    b.全局事件广播
        #[tauri::command]
        async fn broadcast_to_all_windows(
            app: tauri::AppHandle,
            event_name: String,
            payload: serde_json::Value
        ) -> Result<(), String> {
            app.emit_all(&event_name, &payload)
                .map_err(|e| e.to_string())
        }

        #[tauri::command]
        async fn send_system_status_update(
            app: tauri::AppHandle
        ) -> Result<(), String> {
            let system_status = SystemStatus {
                cpu_usage: get_cpu_usage(),
                memory_usage: get_memory_usage(),
                disk_usage: get_disk_usage(),
                timestamp: chrono::Utc::now().to_rfc3339(),
            };

            app.emit_all("system-status-update", &system_status)
                .map_err(|e| e.to_string())
        }

        #[derive(serde::Serialize)]
        struct SystemStatus {
            cpu_usage: f64,
            memory_usage: u64,
            disk_usage: u64,
            timestamp: String,
        }

        fn get_cpu_usage() -> f64 {
            // 实现CPU使用率获取逻辑
            use sysinfo::{System, SystemExt, CpuExt};

            let mut system = System::new();
            system.refresh_cpu();

            system.global_cpu_info().cpu_usage()
        }

        fn get_memory_usage() -> u64 {
            // 实现内存使用量获取逻辑
            use sysinfo::{System, SystemExt};

            let mut system = System::new();
            system.refresh_memory();

            system.used_memory()
        }

        fn get_disk_usage() -> u64 {
            // 实现磁盘使用量获取逻辑
            0
        }
    c.条件事件发送
        #[tauri::command]
        async fn conditional_notification(
            window: tauri::Window,
            condition: String,
            message: String
        ) -> Result<bool, String> {
            let should_notify = evaluate_condition(&condition)?;

            if should_notify {
                window.emit("conditional-notification", &message)
                    .map_err(|e| e.to_string())?;
            }

            Ok(should_notify)
        }

        fn evaluate_condition(condition: &str) -> Result<bool, String> {
            // 简单的条件表达式解析
            // 实际项目中可以使用更复杂的表达式解析器
            match condition {
                "cpu_high" => get_cpu_usage() > 80.0,
                "memory_low" => get_memory_usage() < 100 * 1024 * 1024, // 100MB
                "disk_full" => get_disk_usage() > 90 * 1024 * 1024 * 1024, // 90GB
                _ => Ok(false)
            }
        }
        ---

02.事件数据流
    a.流式数据推送
        use std::sync::{Arc, Mutex};
        use tokio::sync::mpsc;
        use std::collections::VecDeque;

        struct StreamingEventEmitter {
            sender: mpsc::UnboundedSender<StreamingEvent>,
        }

        #[derive(serde::Serialize, Clone)]
        enum StreamingEvent {
            DataChunk { chunk_id: u32, data: String },
            Progress { current: u32, total: u32, percentage: f32 },
            Complete { total_chunks: u32 },
            Error { message: String },
        }

        impl StreamingEventEmitter {
            fn new() -> (Self, mpsc::UnboundedReceiver<StreamingEvent>) {
                let (sender, receiver) = mpsc::unbounded_channel();
                (Self { sender }, receiver)
            }

            async fn start_streaming(
                &self,
                window: tauri::Window,
                data: String,
                chunk_size: usize
            ) -> Result<(), String> {
                let chunks: Vec<String> = data
                    .chars()
                    .collect::<Vec<char>>()
                    .chunks(chunk_size)
                    .map(|chunk| chunk.iter().collect())
                    .collect();

                let total_chunks = chunks.len() as u32;

                // 发送开始事件
                self.sender.send(StreamingEvent::Progress {
                    current: 0,
                    total: total_chunks,
                    percentage: 0.0,
                }).map_err(|e| e.to_string())?;

                for (i, chunk) in chunks.into_iter().enumerate() {
                    let event = StreamingEvent::DataChunk {
                        chunk_id: i as u32,
                        data: chunk,
                    };

                    self.sender.send(event).map_err(|e| e.to_string())?;

                    // 更新进度
                    let percentage = ((i + 1) as f32 / total_chunks as f32) * 100.0;
                    let progress = StreamingEvent::Progress {
                        current: (i + 1) as u32,
                        total: total_chunks,
                        percentage,
                    };

                    self.sender.send(progress).map_err(|e| e.to_string())?;

                    // 模拟延迟以观察流式效果
                    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
                }

                // 发送完成事件
                let complete_event = StreamingEvent::Complete { total_chunks };
                self.sender.send(complete_event).map_err(|e| e.to_string())?;

                Ok(())
            }

            async fn send_error(&self, error_message: String) -> Result<(), String> {
                let error_event = StreamingEvent::Error {
                    message: error_message,
                };
                self.sender.send(error_event).map_err(|e| e.to_string())
            }
        }

        #[tauri::command]
        async fn start_data_streaming(
            window: tauri::Window,
            data: String
        ) -> Result<String, String> {
            let (emitter, mut receiver) = StreamingEventEmitter::new();

            // 启动流式发送
            let window_clone = window.clone();
            let data_clone = data.clone();
            tokio::spawn(async move {
                if let Err(e) = emitter.start_streaming(window_clone, data_clone, 100).await {
                    let _ = emitter.send_error(e);
                }
            });

            // 监听事件并发送到前端
            let window_for_listener = window.clone();
            tokio::spawn(async move {
                while let Some(event) = receiver.recv().await {
                    window_for_listener
                        .emit("streaming-event", &event)
                        .unwrap_or_else(|e| {
                            eprintln!("发送流式事件失败: {}", e);
                        });
                }
            });

            Ok("流式数据传输已启动".to_string())
        }
    b.实时数据更新
        use std::sync::{Arc, RwLock};
        use tokio::time::{interval, Duration};

        struct RealtimeDataProducer {
            data: Arc<RwLock<RealtimeData>>,
        }

        #[derive(serde::Serialize, Clone)]
        struct RealtimeData {
            sensor_values: Vec<f64>,
            timestamp: chrono::DateTime<chrono::Utc>,
            status: String,
        }

        impl RealtimeDataProducer {
            fn new() -> Self {
                Self {
                    data: Arc::new(RwLock::new(RealtimeData {
                        sensor_values: Vec::new(),
                        timestamp: chrono::Utc::now(),
                        status: "running".to_string(),
                    })),
                }
            }

            async fn start_production(
                &self,
                app: tauri::AppHandle
            ) -> Result<(), String> {
                let data = self.data.clone();

                tokio::spawn(async move {
                    let mut interval_timer = interval(Duration::from_secs(1));

                    loop {
                        interval_timer.tick().await;

                        // 模拟传感器数据
                        let new_values = (0..10).map(|_| {
                            use rand::Rng;
                            rand::thread_rng().gen_range(0.0..100.0)
                        }).collect();

                        let updated_data = RealtimeData {
                            sensor_values: new_values,
                            timestamp: chrono::Utc::now(),
                            status: "running".to_string(),
                        };

                        // 更新共享数据
                        {
                            let mut data_guard = data.write().unwrap();
                            *data_guard = updated_data.clone();
                        }

                        // 广播到所有窗口
                        if let Err(e) = app.emit_all("realtime-data-update", &updated_data) {
                            eprintln!("广播实时数据失败: {}", e);
                        }
                    }
                });

                Ok(())
            }
        }

        #[tauri::command]
        async fn get_current_realtime_data(
            data: tauri::State<'_, RealtimeDataProducer>
        ) -> Result<RealtimeData, String> {
            let data_guard = data.data.read().map_err(|e| e.to_string())?;
            Ok(data_guard.clone())
        }

        #[tauri::command]
        async fn start_realtime_updates(
            app: tauri::AppHandle,
            data_producer: tauri::State<'_, RealtimeDataProducer>
        ) -> Result<String, String> {
            data_producer.start_production(app)
        }
    c.事件聚合
        use std::collections::HashMap;
        use tokio::sync::RwLock;

        struct EventAggregator {
            aggregated_events: Arc<RwLock<HashMap<String, AggregatedEvent>>>,
        }

        #[derive(serde::Serialize)]
        struct AggregatedEvent {
            event_type: String,
            count: u64,
            first_occurrence: chrono::DateTime<chrono::Utc>,
            last_occurrence: chrono::DateTime<chrono::Utc>,
            data: serde_json::Value,
        }

        impl EventAggregator {
            fn new() -> Self {
                Self {
                    aggregated_events: Arc::new(RwLock::new(HashMap::new())),
                }
            }

            async fn aggregate_event(
                &self,
                app: tauri::AppHandle,
                event_type: String,
                data: serde_json::Value
            ) -> Result<(), String> {
                let now = chrono::Utc::now();
                let mut events = self.aggregated_events.write().unwrap();

                let event = events.entry(event_type.clone())
                    .or_insert_with(|| AggregatedEvent {
                        event_type: event_type.clone(),
                        count: 0,
                        first_occurrence: now,
                        last_occurrence: now,
                        data: serde_json::json!({}),
                    });

                event.count += 1;
                event.last_occurrence = now;

                // 聚合数据逻辑
                event.data = self.merge_data(&event.data, &data, event.count);

                // 广播聚合事件
                app.emit_all("aggregated-event", &*event)
                    .map_err(|e| e.to_string())?;

                Ok(())
            }

            fn merge_data(
                &self,
                existing: &serde_json::Value,
                new: &serde_json::Value,
                count: u64
            ) -> serde_json::Value {
                // 根据事件类型合并数据
                match existing {
                    serde_json::Value::Object(ref map) => {
                        let mut new_map = map.clone();
                        if let Some(count_map) = new_map.get_mut("count") {
                            *count_map = serde_json::Value::Number(serde_json::Number::from(count));
                        }
                        serde_json::Value::Object(new_map)
                    }
                    _ => new.clone()
                }
            }

            #[tauri::command]
            async fn get_aggregated_events(
                &self,
                event_type: Option<String>
            ) -> Result<Vec<AggregatedEvent>, String> {
                let events = self.aggregated_events.read().unwrap();

                if let Some(event_type) = event_type {
                    if let Some(event) = events.get(&event_type) {
                        Ok(vec![event.clone()])
                    } else {
                        Ok(vec![])
                    }
                } else {
                    Ok(events.values().cloned().collect())
                }
            }
        }

5.4 事件系统

01.事件生命周期
    a.事件注册和注销
        use std::sync::{Arc, Mutex};
        use std::collections::HashMap;

        struct EventManager {
            listeners: Arc<Mutex<HashMap<String, Vec<String>>>>,
            event_history: Arc<Mutex<Vec<EventRecord>>>,
        }

        #[derive(Clone, serde::Serialize)]
        struct EventRecord {
            id: String,
            event_type: String,
            payload: serde_json::Value,
            timestamp: chrono::DateTime<chrono::Utc>,
            source: String,
        }

        impl EventManager {
            fn new() -> Self {
                Self {
                    listeners: Arc::new(Mutex::new(HashMap::new())),
                    event_history: Arc::new(Mutex::new(Vec::new())),
                }
            }

            fn register_listener(
                &self,
                event_type: &str,
                window_id: &str
            ) -> Result<String, String> {
                let mut listeners = self.listeners.lock().unwrap();
                let window_listeners = listeners.entry(event_type.to_string())
                    .or_insert_with(Vec::new);

                if window_listeners.contains(&window_id.to_string()) {
                    return Err("监听器已存在".to_string());
                }

                window_listeners.push(window_id.to_string());
                Ok("监听器注册成功".to_string())
            }

            fn unregister_listener(
                &self,
                event_type: &str,
                window_id: &str
            ) -> Result<bool, String> {
                let mut listeners = self.listeners.lock().unwrap();

                if let Some(window_listeners) = listeners.get_mut(event_type) {
                    let index = window_listeners.iter()
                        .position(|id| id == window_id);

                    if let Some(index) = {
                        window_listeners.remove(index);
                        Ok(true)
                    } else {
                    Ok(false)
                    }
                } else {
                    Ok(false)
                }
            }

            fn get_listeners(&self, event_type: &str) -> Vec<String> {
                let listeners = self.listeners.lock().unwrap();
                listeners
                    .get(event_type)
                    .cloned()
                    .unwrap_or_default()
            }

            fn record_event(&self, record: EventRecord) {
                let mut history = self.event_history.lock().unwrap();
                history.push(record);

                // 限制历史记录数量
                if history.len() > 1000 {
                    history.remove(0);
                }
            }
        }
    b.事件优先级处理
        use std::cmp::Ordering;

        #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
        enum EventPriority {
            Critical = 0,
            High = 1,
            Normal = 2,
            Low = 3,
            Background = 4,
        }

        #[derive(serde::Serialize)]
        struct PriorityEvent {
            id: String,
            event_type: String,
            priority: EventPriority,
            payload: serde_json::Value,
            timestamp: chrono::DateTime<chrono::Utc>,
        }

        impl Ord for PriorityEvent {
            fn cmp(&self, other: &Self) -> Ordering {
                self.priority.cmp(&other.priority)
                    .then_with(|| other.timestamp.cmp(&self.timestamp))
            }
        }

        impl PartialOrd for PriorityEvent {
            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                Some(self.cmp(other))
            }
        }

        struct PriorityEventQueue {
            queue: Arc<Mutex<std::collections::BinaryHeap<PriorityEvent>>>,
            processing: Arc<Mutex<bool>>,
        }

        impl PriorityEventQueue {
            fn new() -> Self {
                Self {
                    queue: Arc::new(Mutex::new(std::collections::BinaryHeap::new())),
                    processing: Arc::new(Mutex::new(false)),
                }
            }

            fn push(&self, event: PriorityEvent) -> Result<(), String> {
                let mut queue = self.queue.lock().unwrap();
                queue.push(event);
                Ok(())
            }

            fn pop(&self) -> Option<PriorityEvent> {
                let mut queue = self.queue.lock().unwrap();
                queue.pop()
            }

            fn is_empty(&self) -> bool {
                let queue = self.queue.lock().unwrap();
                queue.is_empty()
            }

            fn set_processing(&self, processing: bool) {
                let mut proc = self.processing.lock().unwrap();
                *proc = processing;
            }

            fn is_processing(&self) -> bool {
                let proc = self.processing.lock().unwrap();
                *proc
            }
        }
    c.事件路由
        use std::collections::HashSet;
        use regex::Regex;

        struct EventRouter {
            routes: Arc<Mutex<Vec<EventRoute>>>,
            compiled_routes: Arc<Mutex<Vec<CompiledRoute>>>,
        }

        struct EventRoute {
            pattern: String,
            target: String,
            enabled: bool,
        }

        struct CompiledRoute {
            pattern: Regex,
            target: String,
            enabled: bool,
        }

        impl EventRouter {
            fn new() -> Self {
                Self {
                    routes: Arc::new(Mutex::new(Vec::new())),
                    compiled_routes: Arc::new(Mutex::new(Vec::new())),
                }
            }

            fn add_route(
                &self,
                pattern: &str,
                target: &str
            ) -> Result<(), String> {
                let route = EventRoute {
                    pattern: pattern.to_string(),
                    target: target.to_string(),
                    enabled: true,
                };

                let mut routes = self.routes.lock().unwrap();
                routes.push(route);

                // 重新编译路由
                self.compile_routes()?;

                Ok(())
            }

            fn compile_routes(&self) -> Result<(), String> {
                let routes = self.routes.lock().unwrap();
                let mut compiled_routes = Vec::new();

                for route in routes.iter() {
                    let pattern = Regex::new(&route.pattern)
                        .map_err(|e| format!("编译路由模式失败: {}", e))?;

                    compiled_routes.push(CompiledRoute {
                        pattern,
                        target: route.target.clone(),
                        enabled: route.enabled,
                    });
                }

                let mut compiled = self.compiled_routes.lock().unwrap();
                *compiled = compiled_routes;

                Ok(())
            }

            fn route_event(&self, event_type: &str) -> Vec<String> {
                let compiled_routes = self.compiled_routes.lock().unwrap();
                let mut targets = Vec::new();
                let mut matched = HashSet::new();

                for route in compiled_routes.iter() {
                    if !route.enabled {
                        continue;
                    }

                    if route.pattern.is_match(event_type) {
                        if !matched.contains(&route.target) {
                            targets.push(route.target.clone());
                            matched.insert(route.target.clone());
                        }
                    }
                }

                targets
            }

            fn enable_route(&self, target: &str) -> Result<(), String> {
                let mut routes = self.routes.lock().unwrap();

                for route in routes.iter_mut() {
                    if route.target == target {
                        route.enabled = true;
                    }
                }

                self.compile_routes()
            }

            fn disable_route(&self, target: &str) -> Result<(), String> {
                let mut routes = self.routes.lock().unwrap();

                for route in routes.iter_mut() {
                    if route.target == target {
                        route.enabled = false;
                    }
                }

                self.compile_routes()
            }
        }
        ---

02.事件过滤
    a.条件过滤器
        #[derive(serde::Deserialize)]
        struct EventFilter {
            event_types: Option<Vec<String>>,
            min_priority: Option<EventPriority>,
            max_priority: Option<EventPriority>,
            sources: Option<Vec<String>>,
            time_range: Option<TimeRange>,
        }

        #[derive(serde::Deserialize)]
        struct TimeRange {
            start: chrono::DateTime<chrono::Utc>,
            end: chrono::DateTime<chrono::Utc>,
        }

        impl EventFilter {
            fn matches(&self, event: &PriorityEvent) -> bool {
                // 事件类型过滤
                if let Some(ref types) = self.event_types {
                    if !types.contains(&event.event_type) {
                        return false;
                    }
                }

                // 优先级过滤
                if let Some(min_priority) = self.min_priority {
                    if event.priority > min_priority {
                        return false;
                    }
                }

                if let Some(max_priority) = self.max_priority {
                    if event.priority < max_priority {
                        return false;
                    }
                }

                // 时间范围过滤
                if let Some(ref time_range) = self.time_range {
                    if event.timestamp < time_range.start || event.timestamp > time_range.end {
                        return false;
                    }
                }

                true
            }
        }

        struct EventFilterManager {
            filters: Arc<Mutex<Vec<EventFilter>>>,
        }

        impl EventFilterManager {
            fn new() -> Self {
                Self {
                    filters: Arc::new(Mutex::new(Vec::new())),
                }
            }

            fn add_filter(&self, filter: EventFilter) {
                let mut filters = self.filters.lock().unwrap();
                filters.push(filter);
            }

            fn should_pass(&self, event: &PriorityEvent) -> bool {
                let filters = self.filters.lock().unwrap();

                // 如果没有过滤器,所有事件都通过
                if filters.is_empty() {
                    return true;
                }

                // 所有过滤器都通过,事件才通过
                filters.iter().all(|filter| filter.matches(event))
            }
        }
    b.事件转换器
        #[derive(serde::Serialize, Deserialize)]
        struct EventTransformer {
            id: String,
            input_pattern: String,
            output_event_type: String,
            transformation_rules: Vec<TransformationRule>,
            enabled: bool,
        }

        #[derive(serde::Serialize, Deserialize)]
        enum TransformationRule {
            FieldRename { from: String, to: String },
            ValueTransform { field: String, transform: String },
            FilterCondition { field: String, condition: String },
        }

        impl EventTransformer {
            fn transform(&self, event: &mut PriorityEvent) -> Result<(), String> {
                if !self.enabled {
                    return Ok(());
                }

                // 检查输入模式是否匹配
                let pattern = Regex::new(&self.input_pattern)
                    .map_err(|e| format!("编译转换器模式失败: {}", e))?;

                if !pattern.is_match(&event.event_type) {
                    return Ok(());
                }

                let mut payload = event.payload.clone();
                let mut updated = false;

                for rule in &self.transformation_rules {
                    match rule {
                        TransformationRule::FieldRename { from, to } => {
                            if let Some(value) = payload.get(from) {
                                payload[to] = value.clone();
                                payload.remove(from);
                                updated = true;
                            }
                        }
                        TransformationRule::ValueTransform { field, transform } => {
                            if let Some(value) = payload.get_mut(field) {
                                *value = self.apply_transformation(value, transform);
                                updated = true;
                            }
                        }
                        TransformationRule::FilterCondition { field, condition } => {
                            if let Some(value) = payload.get(field) {
                                if !self.evaluate_condition(value, condition) {
                                    payload.remove(field);
                                    updated = true;
                                }
                            }
                        }
                    }
                }

                if updated {
                    event.event_type = self.output_event_type.clone();
                    event.payload = payload;
                }

                Ok(())
            }

            fn apply_transformation(&self, value: &serde_json::Value, transform: &str) -> serde_json::Value {
                match transform {
                    "uppercase" => {
                        if let Some(s) = value.as_str() {
                            serde_json::Value::String(s.to_uppercase())
                        } else {
                            value.clone()
                        }
                    }
                    "lowercase" => {
                        if let Some(s) = value.as_str() {
                            serde_json::Value::String(s.to_lowercase())
                        } else {
                            value.clone()
                        }
                    }
                    "timestamp" => {
                        serde_json::Value::String(chrono::Utc::now().to_rfc3339())
                    }
                    _ => value.clone(),
                }
            }

            fn evaluate_condition(&self, value: &serde_json::Value, condition: &str) -> bool {
                match condition {
                    "not_empty" => !value.is_null(),
                    "is_number" => value.is_number(),
                    "is_string" => value.is_string(),
                    _ => true,
                }
            }
        }
    c.事件聚合器
        #[derive(serde::Serialize, Deserialize)]
        struct EventAggregation {
            window_id: String,
            event_type: String,
            aggregation_type: AggregationType,
            time_window: u64, // 秒
            current_data: serde_json::Value,
        }

        #[derive(serde::Serialize, Deserialize)]
        enum AggregationType {
            Count,
            Sum,
            Average,
            Max,
            Min,
            Latest,
        }

        struct EventAggregatorManager {
            aggregations: Arc<Mutex<HashMap<String, EventAggregation>>>,
            event_history: Arc<Mutex<Vec<PriorityEvent>>>,
        }

        impl EventAggregatorManager {
            fn new() -> Self {
                Self {
                    aggregations: Arc::new(Mutex::new(HashMap::new())),
                    event_history: Arc::new(Mutex::new(Vec::new())),
                }
            }

            fn add_aggregation(&self, aggregation: EventAggregation) {
                let key = format!("{}-{}", aggregation.window_id, aggregation.event_type);
                let mut aggregations = self.aggregations.lock().unwrap();
                aggregations.insert(key, aggregation);
            }

            fn process_event(&self, event: PriorityEvent) -> Result<Vec<EventAggregation>, String> {
                // 添加到历史记录
                {
                    let mut history = self.event_history.lock().unwrap();
                    history.push(event.clone());

                    // 限制历史记录数量
                    if history.len() > 10000 {
                        history.remove(0);
                    }
                }

                let mut results = Vec::new();
                let aggregations = self.aggregations.lock().unwrap();
                let now = chrono::Utc::now();

                for aggregation in aggregations.values() {
                    if aggregation.event_type != event.event_type {
                        continue;
                    }

                    // 检查时间窗口
                    let cutoff_time = now - chrono::Duration::seconds(aggregation.time_window as i64);
                    let relevant_events = self.get_relevant_events(&aggregation.window_id, cutoff_time);

                    let new_data = self.calculate_aggregation(
                        &aggregation.aggregation_type,
                        &relevant_events
                    );

                    if new_data != aggregation.current_data {
                        aggregation.current_data = new_data.clone();
                        results.push(aggregation.clone());
                    }
                }

                Ok(results)
            }

            fn get_relevant_events(
                &self,
                window_id: &str,
                cutoff_time: chrono::DateTime<chrono::Utc>
            ) -> Vec<PriorityEvent> {
                let history = self.event_history.lock().unwrap();

                history
                    .iter()
                    .filter(|event| {
                        // 这里需要从事件中获取窗口ID,简化处理
                        event.event_type.contains(window_id)
                    })
                    .filter(|event| event.timestamp >= cutoff_time)
                    .cloned()
                    .collect()
            }

            fn calculate_aggregation(
                &self,
                aggregation_type: &AggregationType,
                events: &[PriorityEvent]
            ) -> serde_json::Value {
                match aggregation_type {
                    AggregationType::Count => {
                        serde_json::json!(events.len())
                    }
                    AggregationType::Sum => {
                        // 假设事件payload中有value字段
                        let sum: f64 = events
                            .iter()
                            .filter_map(|event| {
                                event.payload.get("value").and_then(|v| v.as_f64())
                            })
                            .sum();
                        serde_json::json!(sum)
                    }
                    AggregationType::Average => {
                        let values: Vec<f64> = events
                            .iter()
                            .filter_map(|event| {
                                event.payload.get("value").and_then(|v| v.as_f64())
                            })
                            .collect();

                        if values.is_empty() {
                            serde_json::json!(0.0)
                        } else {
                            let sum: f64 = values.iter().sum();
                            serde_json::json!(sum / values.len() as f64)
                        }
                    }
                    AggregationType::Max => {
                        let max = events
                            .iter()
                            .filter_map(|event| {
                                event.payload.get("value").and_then(|v| v.as_f64())
                            })
                            .fold(f64::MIN, f64::max);
                        serde_json::json!(max)
                    }
                    AggregationType::Min => {
                        let min = events
                            .iter()
                            .filter_map(|event| {
                                event.payload.get("value").and_then(|v| v.as_f64())
                            })
                            .fold(f64::MAX, f64::min);
                        serde_json::json!(min)
                    }
                    AggregationType::Latest => {
                        if let Some(latest) = events.last() {
                            latest.payload.clone()
                        } else {
                            serde_json::Value::Null
                        }
                    }
                }
            }
        }

5.5 异步处理

01.异步命令模式
    a.基础异步命令
        use tokio::time::{sleep, Duration};
        use std::sync::Arc;
        use tokio::sync::Mutex;

        #[tauri::command]
        async fn async_operation(timeout_ms: u64) -> Result<String, String> {
            println!("开始异步操作...");

            // 模拟异步操作
            sleep(Duration::from_millis(timeout_ms)).await;

            println!("异步操作完成");
            Ok("操作完成".to_string())
        }

        #[tauri::command]
        async fn concurrent_operations() -> Result<Vec<String>, String> {
            let handles: Vec<_> = vec![
                tokio::spawn(async {
                    sleep(Duration::from_millis(1000)).await;
                    "任务1完成".to_string()
                }),
                tokio::spawn(async {
                    sleep(Duration::from_millis(1500)).await;
                    "任务2完成".to_string()
                }),
                tokio::spawn(async {
                    sleep(Duration::from_millis(2000)).await;
                    "任务3完成".to_string()
                }),
            ];

            let mut results = Vec::new();

            for handle in handles {
                match handle.await {
                    Ok(result) => results.push(result),
                    Err(e) => return Err(format!("任务执行失败: {}", e)),
                }
            }

            Ok(results)
        }
    b.状态管理
        #[derive(Clone)]
        struct AsyncState {
            is_processing: Arc<Mutex<bool>>,
            progress: Arc<Mutex<f32>>,
            status: Arc<Mutex<String>>,
        }

        impl AsyncState {
            fn new() -> Self {
                Self {
                    is_processing: Arc::new(Mutex::new(false)),
                    progress: Arc::new(Mutex::new(0.0)),
                    status: Arc::new(Mutex::new("idle".to_string())),
                }
            }

            async fn set_processing(&self, processing: bool) {
                let mut is_processing = self.is_processing.lock().unwrap();
                *is_processing = processing;

                if processing {
                    let mut status = self.status.lock().unwrap();
                    *status = "processing".to_string();
                }
            }

            async fn update_progress(&self, progress: f32) {
                let mut prog = self.progress.lock().unwrap();
                *prog = progress;

                let mut status = self.status.lock().unwrap();
                *status = format!("progress: {:.1}%", progress);
            }

            async fn set_status(&self, status: String) {
                let mut stat = self.status.lock().unwrap();
                *stat = status;
            }

            async fn get_state(&self) -> AsyncStateSnapshot {
                AsyncStateSnapshot {
                    is_processing: *self.is_processing.lock().unwrap(),
                    progress: *self.progress.lock().unwrap(),
                    status: self.status.lock().unwrap().clone(),
                }
            }
        }

        #[derive(serde::Serialize)]
        struct AsyncStateSnapshot {
            is_processing: bool,
            progress: f32,
            status: String,
        }

        #[tauri::command]
        async fn start_async_task(
            state: tauri::State<'_, AsyncState>
        ) -> Result<AsyncStateSnapshot, String> {
            state.set_processing(true).await;
            state.set_status("starting".to_string()).await;

            tokio::spawn(async move {
                // 模拟长时间运行的任务
                for i in 0..=100 {
                    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
                    state.update_progress(i as f32).await;
                }

                state.set_processing(false).await;
                state.set_status("completed".to_string()).await;
            });

            state.get_state().await
        }

        #[tauri::command]
        async fn get_async_state(
            state: tauri::State<'_, AsyncState>
        ) -> Result<AsyncStateSnapshot, String> {
            state.get_state().await
        }
    c.超时处理
        #[tauri::command]
        async fn timeout_operation(
            timeout_ms: u64
        ) -> Result<String, String> {
            let result = tokio::time::timeout(
                Duration::from_millis(timeout_ms),
                self.long_running_task()
            ).await;

            match result {
                Ok(result) => result,
                Err(_) => Err("操作超时".to_string()),
            }
        }

        #[tauri::command]
        async fn retry_operation(
            max_retries: u32,
            base_delay_ms: u64
        ) -> Result<String, String> {
            let mut retries = 0;

            loop {
                match self.flaky_operation().await {
                    Ok(result) => return Ok(result),
                    Err(e) if retries < max_retries => {
                        retries += 1;
                        let delay = base_delay_ms * (2_u64.pow(retries));
                        tokio::time::sleep(Duration::from_millis(delay)).await;
                        continue;
                    },
                    Err(e) => return Err(format!("操作失败,已重试{}次: {}", max_retries, e)),
                }
            }
        }

        impl Self {
            async fn long_running_task(&self) -> Result<String, Box<dyn std::error::Error>> {
                // 模拟可能失败的操作
                use rand::Rng;
                let mut rng = rand::thread_rng();

                for _ in 0..5 {
                    tokio::time::sleep(Duration::from_millis(500)).await;

                    if rng.gen::<f32>() < 0.3 {
                        return Err("随机失败".into());
                    }
                }

                Ok("长时操作成功".to_string())
            }

            async fn flaky_operation(&self) -> Result<String, Box<dyn std::error::Error>> {
                tokio::time::sleep(Duration::from_millis(200)).await;

                use rand::Rng;
                let mut rng = rand::thread_rng();

                if rng.gen::<f32>() < 0.4 {
                    return Err("操作失败".into());
                }

                Ok("操作成功".to_string())
            }
        }
        ---

02.流式异步处理
    a.异步流创建
        use tokio::sync::mpsc;
        use futures::StreamExt;

        #[tauri::command]
        async fn create_async_stream() -> Result<String, String> {
            let (tx, rx) = mpsc::channel::<StreamData>(100);

            // 启动数据生成器
            let handle = tokio::spawn(async move {
                let mut counter = 0;

                loop {
                    let data = StreamData {
                        id: counter,
                        timestamp: chrono::Utc::now(),
                        message: format!("数据块 {}", counter),
                    };

                    if tx.send(data).await.is_err() {
                        break; // 接收端已断开
                    }

                    counter += 1;

                    // 每100ms生成一个数据块
                    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
                }
            });

            Ok(format!("异步流已创建,句柄: {:?}", handle)).await
        }

        #[derive(serde::Serialize)]
        struct StreamData {
            id: u64,
            timestamp: chrono::DateTime<chrono::Utc>,
            message: String,
        }

        #[tauri::command]
        async fn process_stream_data() -> Result<Vec<StreamData>, String> {
            let (tx, mut rx) = mpsc::channel::<StreamData>(100);

            // 生成测试数据
            for i in 0..10 {
                let data = StreamData {
                    id: i,
                    timestamp: chrono::Utc::now(),
                    message: format!("处理数据 {}", i),
                };

                tx.send(data).await.unwrap_or_else(|_| {
                    println!("发送数据 {} 失败", i);
                });
            }

            // 关闭发送端
            drop(tx);

            // 接收并处理数据
            let mut processed_data = Vec::new();

            while let Some(data) = rx.recv().await {
                let processed = process_stream_item(data).await;
                processed_data.push(processed);
            }

            Ok(processed_data)
        }

        async fn process_stream_item(data: StreamData) -> StreamData {
            // 模拟处理延迟
            tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;

            StreamData {
                id: data.id,
                timestamp: data.timestamp,
                message: format!("已处理: {}", data.message),
            }
        }
    b.管道操作
        use futures::sink::SinkExt;
        use futures::stream::StreamExt;

        #[tauri::command]
        async fn create_pipeline() -> Result<Vec<String>, String> {
            let stream = futures::stream::iter(0..100)
                .map(|i| i.to_string())
                .map(|s| s.to_uppercase())
                .filter(|s| s.len() % 2 == 0)
                .take(50)
                .collect::<Vec<_>>();

            Ok(stream)
        }

        #[tauri::command]
        async fn async_pipeline() -> Result<Vec<String>, String> {
            let numbers = futures::stream::iter(1..=100)
                .map(|i| i as i32)
                .map(|n| n * 2)
                .filter(|n| n % 3 == 0)
                .map(|n| n.to_string())
                .take(30)
                .collect::<Vec<_>>();

            Ok(numbers)
        }

        #[tauri::command]
        async fn batch_processing(items: Vec<String>) -> Result<Vec<String>, String> {
            // 并发处理
            let futures = items.into_iter()
                .map(|item| tokio::spawn(async move {
                    // 模拟处理时间
                    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
                    format!("已处理: {}", item)
                }))
                .collect::<Vec<_>>();

            let mut results = Vec::new();

            for future in futures {
                match future.await {
                    Ok(result) => results.push(result),
                    Err(e) => {
                        eprintln!("处理任务失败: {}", e);
                        results.push("处理失败".to_string());
                    }
                }
            }

            Ok(results)
        }
    c.背压控制
        use tokio::sync::Semaphore;

        struct BackpressureController {
            semaphore: Semaphore,
        }

        impl BackpressureController {
            fn new(max_concurrent: usize) -> Self {
                Self {
                    semaphore: Semaphore::new(max_concurrent),
                }
            }

            async fn execute_with_backpressure<F, T>(&self, f: F) -> T
            where
                F: std::future::Future<Output = T> + Send + 'static,
                T: Send + 'static,
            {
                let _permit = self.semaphore.acquire().await;
                let result = f.await;
                // permit会在作用域结束时自动释放
                result
            }
        }

        #[tauri::command]
        async fn controlled_batch_processing(
            items: Vec<String>,
            max_concurrent: usize
        ) -> Result<Vec<String>, String> {
            let controller = BackpressureController::new(max_concurrent);

            let futures = items.into_iter()
                .map(|item| {
                    controller.execute_with_backpressure(async move {
                        // 模拟处理时间
                        tokio::time::sleep(tokio::time::Duration::from_millis(200)).await;
                        format!("受限处理: {}", item)
                    })
                })
                .collect::<Vec<_>>();

            let mut results = Vec::new();

            for future in futures {
                match future.await {
                    Ok(result) => results.push(result),
                    Err(e) => {
                        eprintln!("受限处理失败: {}", e);
                        results.push("处理失败".to_string());
                    }
                }
            }

            Ok(results)
        }

        #[tauri::command]
        async fn adaptive_processing(
            items: Vec<String>
        ) -> Result<Vec<String>, String> {
            let mut results = Vec::new();

            // 根据数据量动态调整并发数
            let concurrency = (items.len() / 10).max(1).min(50);
            let controller = BackpressureController::new(concurrency);

            for item in items {
                let result = controller.execute_with_backpressure(async move {
                    // 根据内容复杂度调整处理时间
                    let processing_time = if item.len() > 50 {
                        Duration::from_millis(500)
                    } else {
                        Duration::from_millis(100)
                    };

                    tokio::time::sleep(processing_time).await;
                    format!("自适应处理: {}", item)
                }).await;

                results.push(result);
            }

            Ok(results)
        }
        ---

03.错误处理和恢复
    a.错误传播
        use thiserror::Error;

        #[derive(Error, Debug)]
        enum AsyncError {
            #[error("网络错误: {0}")]
            Network(String),
            #[error("超时错误: {0}")]
            Timeout(String),
            #[error("解析错误: {0}")]
            Parse(String),
            #[error("资源错误: {0}")]
            Resource(String),
            #[error("权限错误: {0}")]
            Permission(String),
        }

        #[tauri::command]
        async fn error_propagation_example() -> Result<String, AsyncError> {
            // 模拟多层异步调用
            self.network_operation()
                .await
                .and_then(|data| self.parse_operation(data))
                .and_then(|parsed| self.validate_operation(parsed))
                .await
        }

        impl Self {
            async fn network_operation(&self) -> Result<String, AsyncError> {
                tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
                Ok("网络数据".to_string())
            }

            async fn parse_operation(&self, data: String) -> Result<String, AsyncError> {
                // 模拟解析失败
                if data.contains("error") {
                    return Err(AsyncError::Parse("解析失败".to_string()));
                }
                Ok(format!("解析成功: {}", data))
            }

            async fn validate_operation(&self, data: String) -> Result<String, AsyncError> {
                // 模拟验证失败
                if data.len() < 5 {
                    return Err(AsyncError::Validation("验证失败".to_string()));
                }
                Ok(format!("验证成功: {}", data))
            }

            #[error("验证错误: {0}")]
            Validation(String);
        }
    b.重试机制
        #[derive(Clone)]
        struct RetryConfig {
            max_attempts: u32,
            base_delay_ms: u64,
            max_delay_ms: u64,
            backoff_multiplier: f64,
        }

        impl Default for RetryConfig {
            fn default() -> Self {
                Self {
                    max_attempts: 3,
                    base_delay_ms: 100,
                    max_delay_ms: 5000,
                    backoff_multiplier: 2.0,
                }
            }
        }

        trait Retryable {
            type Output;
            type Error: std::error::Error + Send + Sync + 'static;

            async fn execute(&self) -> Result<Self::Output, Self::Error>;
            fn is_retryable(&self, error: &Self::Error) -> bool;
        }

        struct AsyncRetryManager;

        impl AsyncRetryManager {
            async fn retry_with_config<R: Retryable>(
                retryable: &R,
                config: RetryConfig
            ) -> Result<R::Output, R::Error> {
                let mut last_error: Option<R::Error> = None;
                let mut delay = config.base_delay_ms;

                for attempt in 1..=config.max_attempts {
                    match retryable.execute().await {
                        Ok(result) => {
                            if attempt > 1 {
                                println!("重试成功,尝试次数: {}", attempt);
                            }
                            return Ok(result);
                        },
                        Err(e) => {
                            last_error = Some(e.clone());

                            if !retryable.is_retryable(&e) {
                                break;
                            }

                            if attempt < config.max_attempts {
                                println!("重试第{}次,延迟{}ms", attempt, delay);
                                tokio::time::sleep(Duration::from_millis(delay)).await;

                                delay = (delay as f64 * config.backoff_multiplier) as u64;
                                delay = delay.min(config.max_delay_ms);
                            }
                        }
                    }
                }

                Err(last_error.unwrap_or_else(|| {
                    std::io::Error::new(std::io::ErrorKind::Other, "未知错误")
                }))
            }

            async fn retry_default<R: Retryable>(retryable: &R) -> Result<R::Output, R::Error> {
                let config = RetryConfig::default();
                Self::retry_with_config(retryable, config).await
            }
        }

        struct FileProcessor {
            max_retries: u32,
        }

        impl Retryable for FileProcessor {
            type Output = String;
            type Error = AsyncError;

            async fn execute(&self) -> Result<Self::Output, Self::Error> {
                // 模拟文件处理
                tokio::time::sleep(Duration::from_millis(200)).await;

                use rand::Rng;
                let mut rng = rand::thread_rng();

                if rng.gen::<f32>() < 0.3 {
                    return Err(AsyncError::Resource("文件处理失败".to_string()));
                }

                Ok("文件处理成功".to_string())
            }

            fn is_retryable(&self, error: &Self::Error) -> Error {
                match error {
                    AsyncError::Network(_) => true,
                    AsyncError::Timeout(_) => true,
                    AsyncError::Resource(_) => true,
                    AsyncError::Permission(_) => false,
                    AsyncError::Parse(_) => false,
                    _ => false,
                }
            }
        }

        #[tauri::command]
        async fn resilient_file_operation(
            max_retries: u32
        ) -> Result<String, String> {
            let processor = FileProcessor { max_retries };
            let config = RetryConfig {
                max_attempts: max_retries,
                base_delay_ms: 200,
                max_delay_ms: 2000,
                backoff_multiplier: 1.5,
            };

            AsyncRetryManager::retry_with_config(&processor, config)
                .await
                .map_err(|e| e.to_string())
        }
    c.断路器模式
        use std::sync::Arc;
        use std::time::{Duration, Instant};

        struct CircuitBreaker {
            failure_count: Arc<Mutex<u32>>,
            last_failure_time: Arc<Mutex<Option<Instant>>>,
            state: Arc<Mutex<CircuitBreakerState>>,
            failure_threshold: u32,
            recovery_timeout: Duration,
            success_threshold: u32,
            request_count: Arc<Mutex<u32>>,
        }

        #[derive(Debug, PartialEq)]
        enum CircuitBreakerState {
            Closed,     // 正常状态
            Open,       // 断路状态
            HalfOpen,   // 半开状态
        }

        impl CircuitBreaker {
            fn new(failure_threshold: u32, recovery_timeout: Duration, success_threshold: u32) -> Self {
                Self {
                    failure_count: Arc::new(Mutex::new(0)),
                    last_failure_time: Arc::new(Mutex::new(None)),
                    state: Arc::new(Mutex::new(CircuitBreakerState::Closed)),
                    failure_threshold,
                    recovery_timeout,
                    success_threshold,
                    request_count: Arc::new(Mutex::new(0)),
                }
            }

            async fn execute<F, R, E>(&self, operation: F) -> Result<R, E>
            where
                F: std::future::Future<Output = Result<R, E>> + Send,
                E: std::error::Error + Send + Sync + 'static,
            {
                let current_state = *self.state.lock().unwrap();

                match current_state {
                    CircuitBreakerState::Closed => {
                        self.execute_closed(operation).await
                    }
                    CircuitBreakerState::Open => {
                        Err(std::io::Error::new(
                            std::io::ErrorKind::Other,
                            "断路器已打开"
                        ))
                    }
                    CircuitBreakerState::HalfOpen => {
                        self.execute_half_open(operation).await
                    }
                }
            }

            async fn execute_closed<F, R, E>(&self, operation: F) -> Result<R, E>
            where
                F: std::future::Future<Output = Result<R, E>> + Send,
                E: std::error::Error + Send + Sync + 'static,
            {
                let result = operation.await;

                match &result {
                    Ok(_) => {
                    self.on_success().await;
                    result
                }
                    Err(_) => {
                        self.on_failure().await;
                    result
                }
                }
            }

            async fn execute_half_open<F, R, E>(&self, operation: F) -> Result<R, E>
            where
                F: std::future::Future<Output = Result<R, E>> + Send,
                E: std::error::Error + Send + Sync + 'static,
            {
                let result = operation.await;

                match &result {
                    Ok(_) => {
                    self.on_success().await;
                    result
                }
                    Err(_) => {
                        self.on_failure().await;
                    result
                }
                }
            }

            async fn on_success(&self) {
                let mut state = self.state.lock().unwrap();
                let mut failure_count = self.failure_count.lock().unwrap();

                *failure_count = 0;

                if *state == CircuitBreakerState::HalfOpen {
                    *state = CircuitBreaker::Closed;
                }
            }

            async fn on_failure(&self) {
                let mut failure_count = self.failure_count.lock().unwrap();
                *failure_count += 1;

                let mut last_failure = self.last_failure_time.lock().unwrap();
                *last_failure = Some(Instant::now());

                if *failure_count >= self.failure_threshold {
                    let mut state = self.state.lock().unwrap();
                    *state = CircuitBreakerState::Open;
                }
            }

            async fn attempt_recovery(&self) -> bool {
                let last_failure = *self.last_failure_time.lock().unwrap();
                let now = Instant::now();

                if let Some(last) = last {
                    if now.duration_since(last) >= self.recovery_timeout {
                        let mut state = self.state.lock().unwrap();
                        *state = CircuitBreakerState::HalfOpen;
                        true
                    } else {
                            false
                        }
                } else {
                    true
                }
            }

            fn get_state(&self) -> CircuitBreakerState {
                *self.state.lock().unwrap()
            }
        }

        #[tauri::command]
        async fn circuit_breaker_example(
            request_count: u32
        ) -> Result<Vec<String>, String> {
            let circuit_breaker = Arc::new(CircuitBreaker::new(
                5,                           // 失败阈值
                Duration::from_secs(10), // 恢复超时
                3                            // 成功阈值
            ));

            let mut results = Vec::new();
            let mut success_count = 0;
            let mut failure_count = 0;

            for i in 0..request_count {
                // 检查是否可以尝试执行
                if circuit_breaker.get_state() == CircuitBreakerState::Open {
                    // 尝试恢复
                    if circuit_breaker.attempt_recovery().await {
                        // 半开状态,允许少量请求通过
                        let circuit_breaker_clone = circuit_breaker.clone();
                        match circuit_breaker_clone
                            .execute_async_operation(i)
                            .await
                        {
                            Ok(result) => {
                                results.push(result);
                                success_count += 1;
                            }
                            Err(_) => {
                                failure_count += 1;
                            }
                        }
                    } else {
                        // 仍然在恢复超时期间
                        return Err("断路器仍在恢复期".to_string());
                    }
                }

                // 执行操作
                let circuit_breaker_clone = circuit_breaker.clone();
                match circuit_breaker_clone
                    .execute_async_operation(i)
                    .await
                {
                    Ok(result) => {
                        results.push(result);
                        success_count += 1;
                    }
                    Err(_) => {
                        failure_count += 1;
                    }
                }
            }

            Ok(results)
        }

        impl CircuitBreaker {
            async fn execute_async_operation(&self, index: u32) -> Result<String, Box<dyn std::error::Error>> {
                // 模拟业务逻辑
                tokio::time::sleep(Duration::from_millis(100)).await;

                use rand::Rng;
                let mut rng = rand::thread_rng();

                // 30%的失败率
                if rng.gen::<f32>() < 0.3 {
                    return Err(Box::new(std::io::Error::new(
                        std::io::ErrorKind::Other,
                        format!("异步操作 {} 失败", index)
                    )));
                }

                Ok(format!("异步操作 {} 成功", index))
            }
        }

6 构建部署

6.1 构建工具使用

01.构建工具概述
    a.Tauri构建特点
        Tauri的构建过程不同于传统Web应用,它需要协调前端和后端两个部分的构建
        Tauri CLI提供了一套完整的构建工具链,能够自动处理复杂的多平台构建过程
    b.开发模式
        在开发模式下,Tauri使用tauri dev命令启动应用
        这个命令会启动Tauri后端进程和前端开发服务器,并自动建立两者之间的通信连接
        后端监听前端开发服务器的变化,当代码发生改变时会自动重新加载应用
    c.生产构建
        构建生产版本时使用tauri build命令
        这个命令会执行多个步骤:首先构建前端资源,然后编译Rust后端代码,最后将它们打包成特定平台的可执行文件
        构建过程可以通过命令行参数进行定制

02.基本命令使用
    a.CLI安装
        # 安装Tauri CLI
        cargo install tauri-cli
    b.开发模式启动
        # 启动开发模式
        npm run tauri dev
        # 或直接使用Tauri CLI
        tauri dev
    c.生产构建
        # 构建生产版本
        npm run tauri build
        # 或直接使用Tauri CLI
        tauri build
        # 指定目标平台
        tauri build --target x86_64-pc-windows-msvc

6.2 多平台构建

01.跨平台支持
    a.支持的平台
        Tauri应用可以构建为多个目标平台,包括Windows、macOS和Linux
        由于Rust的跨平台特性,相同的代码库可以在不同操作系统上编译和运行
        大大降低了跨平台开发的工作量
    b.平台特定优化
        每个平台都有特定的构建配置和优化选项
        Tauri会自动处理平台差异,生成最适合的安装包格式
        开发者可以针对不同平台进行定制化配置

02.Windows平台构建
    a.环境要求
        Windows平台构建需要安装Visual Studio Build Tools和Rust的MSVC工具链
        需要配置正确的环境变量和路径
        确保所有依赖库和工具链版本兼容
    b.构建配置
        # tauri.conf.json中的Windows配置
        [bundle]
        active = true
        targets = ["nsis"]

        [bundle.windows]
        certificate_thumbprint = "YOUR_CERT_THUMBPRINT"
        digest_algorithm = "sha256"
        timestamp_url = "http://timestamp.digicert.com"
    c.输出格式
        Tauri会生成NSIS安装程序或MSI包,包含应用的可执行文件和所有依赖项
        Windows构建会自动处理代码签名和应用程序清单的配置
        支持自动更新和静默安装功能

03.macOS平台构建
    a.环境要求
        macOS平台构建需要macOS系统和Xcode Command Line Tools
        需要有效的Apple开发者账号用于代码签名
        确保所有依赖库和工具链版本兼容
    b.构建配置
        # tauri.conf.json中的macOS配置
        [bundle]
        active = true
        targets = ["dmg"]

        [bundle.macOS]
        frameworks = []
        minimum_system_version = "10.13"
        exception_domain = ""
        signing_identity = "Developer ID Application: Your Name"
        provider_short_name = "YourName"
        entitlements = "entitlements.plist"
    c.输出格式
        Tauri会生成.app应用程序包和.dmg安装镜像
        macOS构建支持代码签名和公证,确保应用能够在Gatekeeper检查下正常运行
        支持自动更新和应用商店分发

04.Linux平台构建
    a.环境要求
        Linux平台构建需要安装必要的系统库和开发工具
        不同Linux发行版可能有不同的依赖要求
        确保所有依赖库和工具链版本兼容
    b.构建配置
        # tauri.conf.json中的Linux配置
        [bundle]
        active = true
        targets = ["deb", "appimage"]

        [bundle.deb]
        depends = ["libgtk-3-0", "libnotify4", "libnss3", "libxss1", "libxtst6", "xdg-utils", "libatspi2.0-0", "libdrm2", "libxcomposite1", "libxdamage1", "libxrandr2", "libgbm1", "libxkbcommon0", "libasound2"]
    c.输出格式
        Linux平台构建最为灵活,支持多种Linux发行版
        Tauri可以生成AppImage、DEB或RPM包,适应不同的包管理系统
        Linux构建不要求代码签名,但可以配置GPG签名增强安全性

6.3 构建优化配置

01.资源优化配置
    a.前端资源处理
        资源优化配置允许开发者控制前端资源的处理方式
        通过beforeBuildCommand和beforeDevCommand可以指定前端构建命令
        确保使用优化的生产构建,distDir配置指定前端构建输出的目录
    b.构建命令配置
        {
            "build": {
                "beforeBuildCommand": "npm run build",
                "beforeDevCommand": "npm run dev",
                "devPath": "http://localhost:3000",
                "distDir": "../dist"
            }
        }
    c.资源压缩和优化
        Tauri会自动将前端资源打包到应用中
        支持资源压缩和代码分割,减少应用体积
        可以配置资源缓存策略,提高应用启动速度

02.应用程序元数据配置
    a.基本信息配置
        应用程序元数据配置影响应用的外观和用户感知
        通过productName、version和identifier定义应用的基本信息
        这些信息会显示在安装程序、应用图标和系统信息中
    b.图标配置
        icon配置支持多尺寸图标,Tauri会自动选择合适的尺寸用于不同场景
        支持PNG、ICO、ICNS等多种图标格式
        可以为不同平台配置不同的图标集
    c.元数据配置示例
        {
            "package": {
                "productName": "My Tauri App",
                "version": "1.0.0"
            },
            "tauri": {
                "bundle": {
                    "active": true,
                    "icon": [
                        "icons/32x32.png",
                        "icons/128x128.png",
                        "icons/[email protected]",
                        "icons/icon.icns",
                        "icons/icon.ico"
                    ]
                }
            }
        }

03.安全白名单配置
    a.权限控制原则
        安全白名单配置定义了前端可以访问的系统API
        Tauri采用最小权限原则,默认情况下只允许必要的API
        开发者需要明确开启每个API的权限,确保应用的安全性
    b.权限配置示例
        {
            "tauri": {
                "allowlist": {
                    "all": false,
                    "fs": {
                        "all": false,
                        "readFile": true,
                        "writeFile": true,
                        "scope": ["$APPDATA/*", "$DOCUMENT/*"]
                    },
                    "dialog": {
                        "all": false,
                        "open": true,
                        "save": true
                    }
                }
            }
        }
    c.安全最佳实践
        限制文件系统访问范围,避免敏感文件泄露
        控制网络请求域名,防止恶意请求
        禁用不必要的API,减少攻击面

6.4 增量更新机制

01.更新机制概述
    a.前后端分离更新
        Tauri应用的更新机制利用了前后端分离的优势,可以分别更新前端资源和后端代码
        前端更新只需替换WebView中的静态资源,后端更新则需要替换整个可执行文件
        这种差异化的更新策略显著减少了更新包的大小
    b.更新流程
        应用启动时检查远程服务器上的最新版本信息
        比较本地和远程的版本号,确定是否需要更新
        下载更新文件并验证完整性
        应用更新并重启应用

02.前端增量更新
    a.哈希值比较
        前端增量更新通过比较本地和远程的前端资源哈希值实现
        只下载有变化的资源文件,而不是整个前端包
        大大减少了更新包的大小和下载时间
    b.更新实现
        use tauri::Manager;

        #[tauri::command]
        async fn check_frontend_update(app: tauri::AppHandle) -> Result<bool, String> {
            let current_version = app.package_info().version.to_string();

            // 检查远程版本信息
            let response = reqwest::get("https://api.example.com/version")
                .await
                .map_err(|e| format!("网络请求失败: {}", e))?;

            let version_info: serde_json::Value = response
                .json()
                .await
                .map_err(|e| format!("解析版本信息失败: {}", e))?;

            let remote_version = version_info["version"].as_str().unwrap_or("");

            Ok(current_version != remote_version)
        }
    c.资源下载和应用
        #[tauri::command]
        async fn download_frontend_update(url: String) -> Result<String, String> {
            let response = reqwest::get(&url)
                .await
                .map_err(|e| format!("下载更新失败: {}", e))?;

            let temp_dir = std::env::temp_dir();
            let update_path = temp_dir.join("frontend_update.zip");

            let mut file = std::fs::File::create(&update_path)
                .map_err(|e| format!("创建更新文件失败: {}", e))?;

            let bytes = response.bytes()
                .await
                .map_err(|e| format!("读取更新数据失败: {}", e))?;

            use std::io::Write;
            file.write_all(&bytes)
                .map_err(|e| format!("写入更新文件失败: {}", e))?;

            Ok(update_path.to_string_lossy().to_string())
        }

03.后端全量更新
    a.更新策略
        后端全量更新需要处理Rust可执行文件的替换
        由于Windows系统不允许正在运行的文件被替换,Tauri使用特殊的更新策略
        下载新版本的可执行文件,然后通过外部脚本或服务在应用关闭后完成替换
    b.更新检查
        #[tauri::command]
        async fn check_backend_update(app: tauri::AppHandle) -> Result<bool, String> {
            let current_version = app.package_info().version.to_string();

            // 检查后端更新
            let response = reqwest::get("https://api.example.com/backend-version")
                .await
                .map_err(|e| format!("检查后端版本失败: {}", e))?;

            let version_info: serde_json::Value = response
                .json()
                .await
                .map_err(|e| format!("解析后端版本失败: {}", e))?;

            let backend_version = version_info["backend_version"].as_str().unwrap_or("");

            Ok(current_version != backend_version)
        }
    c.更新执行
        #[tauri::command]
        async fn schedule_backend_update(url: String) -> Result<(), String> {
            let temp_dir = std::env::temp_dir();
            let update_path = temp_dir.join("backend_update.exe");

            // 下载新版本
            let response = reqwest::get(&url)
                .await
                .map_err(|e| format!("下载后端更新失败: {}", e))?;

            let bytes = response.bytes()
                .await
                .map_err(|e| format!("读取后端更新数据失败: {}", e))?;

            std::fs::write(&update_path, bytes)
                .map_err(|e| format!("保存后端更新失败: {}", e))?;

            // 创建更新脚本(Windows示例)
            let script_content = format!(
                r#"
                @echo off
                timeout /t 3 /nobreak
                move "{}" "{}"
                start "" "{}"
                del "%~f0"
                "#,
                update_path.display(),
                std::env::current_exe().unwrap().display(),
                std::env::current_exe().unwrap().display()
            );

            let script_path = temp_dir.join("update.bat");
            std::fs::write(&script_path, script_content)
                .map_err(|e| format!("创建更新脚本失败: {}", e))?;

            // 启动更新脚本
            std::process::Command::new("cmd")
                .args(&["/C", &script_path.to_string_lossy()])
                .spawn()
                .map_err(|e| format!("启动更新脚本失败: {}", e))?;

            // 退出当前应用
            app.exit(0);

            Ok(())
        }

04.更新策略配置
    a.更新模式
        更新策略的配置和管理需要考虑用户体验和网络状况
        Tauri支持静默更新、用户确认更新和强制更新等多种策略
        开发者可以根据应用类型和用户群体选择合适的更新方式
    b.配置结构
        #[derive(Clone, serde::Deserialize)]
        struct UpdateConfig {
            check_interval: u64, // 检查间隔(秒)
            auto_download: bool,  // 自动下载
            require_confirmation: bool, // 需要用户确认
            force_update: bool,   // 强制更新
        }
    c.配置管理
        #[tauri::command]
        async fn configure_update(config: UpdateConfig, app: tauri::AppHandle) -> Result<(), String> {
            let app_data_dir = app.path_resolver().app_data_dir()
                .ok_or("无法获取应用数据目录")?;

            let config_path = app_data_dir.join("update_config.json");
            let config_json = serde_json::to_string_pretty(&config)
                .map_err(|e| format!("序列化更新配置失败: {}", e))?;

            std::fs::write(config_path, config_json)
                .map_err(|e| format!("保存更新配置失败: {}", e))?;

            Ok(())
        }

6.5 CI/CD自动化

01.CI/CD概述
    a.自动化流程
        持续集成和持续部署(CI/CD)是现代软件开发的重要实践
        Tauri应用同样可以受益于自动化的构建和发布流程
        通过GitHub Actions、GitLab CI等工具,可以实现代码提交后自动构建多平台版本的Tauri应用
    b.多平台并行构建
        CI/CD流程支持多平台并行构建,大大提高了发布效率
        可以在不同的运行器上同时构建Windows、macOS和Linux版本
        自动处理平台特定的依赖和配置
    c.自动化测试
        自动化测试是CI/CD流程的重要组成部分
        Tauri应用的测试分为前端测试和后端测试两部分
        可以使用不同的测试框架和工具进行全面的测试覆盖

02.GitHub Actions配置
    a.工作流设置
        # .github/workflows/build.yml
        name: Build Tauri App

        on:
            push:
                tags:
                    - 'v[0-9]+.[0-9]+.[0-9]+'
            pull_request:

        jobs:
            build:
                strategy:
                    fail-fast: false
                    matrix:
                        platform: [macos-latest, ubuntu-latest, windows-latest]

                runs-on: ${{ matrix.platform }}
                steps:
                    - name: Checkout repository
                      uses: actions/checkout@v3
    b.环境配置
        - name: Install dependencies (ubuntu only)
          if: matrix.platform == 'ubuntu-latest'
          run: |
              sudo apt-get update
              sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
    c.构建和发布
        - name: Rust setup
          uses: dtolnay/rust-toolchain@stable

        - name: Rust cache
          uses: swatinem/rust-cache@v2
          with:
              workspaces: './src-tauri -> target'

        - name: Sync node version and setup cache
          uses: actions/setup-node@v3
          with:
              node-version: '16'
              cache: 'npm'

        - name: Install frontend dependencies
          run: npm ci

        - name: Build app
          uses: tauri-apps/tauri-action@v0
          env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          with:
              tagName: ${{ github.ref_name }}
              releaseName: 'Tauri App ${{ github.ref_name }}'
              releaseBody: 'See the assets to download and install this version.'
              releaseDraft: true
              prerelease: false

03.GitLab CI配置
    a.基础配置
        # .gitlab-ci.yml
        stages:
            - build
            - release

        variables:
            CARGO_HOME: $CI_PROJECT_DIR/cargo
            NPM_CONFIG_CACHE: $CI_PROJECT_DIR/npm

        cache:
            key: $CI_COMMIT_REF_SLUG
            paths:
                - cargo/
                - npm/
    b.构建模板
        .build_template: &build_template
            stage: build
            script:
                - apt-get update && apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
                - rustc --version && cargo --version
                - node --version && npm --version
                - npm ci
                - npm run tauri build
            artifacts:
                paths:
                    - src-tauri/target/release/bundle/
                expire_in: 1 week
    c.平台特定构建
        build:linux:
            <<: *build_template
            image: rust:latest
            tags:
                - linux

        build:macos:
            <<: *build_template
            tags:
                - macos

        build:windows:
            <<: *build_template
            tags:
                - windows

04.自动化测试集成
    a.测试步骤
        # 添加到CI配置中的测试步骤
        - name: Run frontend tests
          run: npm test

        - name: Run backend tests
          run: cd src-tauri && cargo test

        - name: Run integration tests
          run: npm run test:integration
    b.测试覆盖率
        前端测试可以使用Jest、Cypress等工具
        后端测试使用Rust内置的测试框架
        集成测试验证前后端之间的交互是否正确
    c.测试报告
        生成测试报告并上传到CI系统
        设置测试失败时的通知机制
        维护测试历史记录和趋势分析

05.发布管理
    a.版本控制
        发布管理需要考虑版本控制和渠道管理
        Tauri支持稳定版、测试版和开发版等多个发布渠道
        CI/CD流程可以根据不同的分支或标签自动发布到相应的渠道
    b.条件发布
        # 条件发布配置
        - name: Release stable version
          if: startsWith(github.ref, 'refs/tags/v')
          uses: softprops/action-gh-release@v1
          with:
              files: src-tauri/target/release/bundle/*
              draft: false
              prerelease: false
          env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

        - name: Release beta version
          if: github.ref == 'refs/heads/beta'
          uses: softprops/action-gh-release@v1
          with:
              files: src-tauri/target/release/bundle/*
              draft: false
              prerelease: true
              tag_name: beta-${{ github.sha }}
          env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    c.应用商店发布
        部署到应用商店需要额外的步骤和配置
        微软商店、Mac App Store和Linux发行版仓库都有各自的提交流程和要求
        CI/CD流程可以自动化这些步骤,但需要预先配置好开发者账号和证书
        # Microsoft Store发布示例
        - name: Create MSIX package
          run: |
              npm run make:windows
              cd out/make
              msix-packager create-minecraft-windows.msix

        - name: Upload to Microsoft Store
          run: |
              # 使用Microsoft Store API上传包
              curl -X POST "https://manage.devcenter.microsoft.com/v2.0/my/applications/{applicationId}/submissions/{submissionId}/packagedetails" \
                   -H "Authorization: Bearer ${{ secrets.MS_STORE_TOKEN }}" \
                   -F "package=@out/make/*.msix"

7 最佳实践

7.1 应用架构设计

01.架构设计原则
    a.前后端分离
        Tauri应用的成功很大程度上取决于良好的架构设计
        前后端分离是Tauri的核心特点,因此需要仔细设计前端和后端之间的接口边界
        推荐采用领域驱动设计(DDD)的原则,将业务逻辑合理地分布在前后端两端
    b.后端职责划分
        后端Rust代码应该专注于系统级操作、性能敏感的计算和数据持久化
        这些任务利用了Rust的内存安全性和高性能特性,避免了JavaScript在处理大量数据或复杂计算时的性能瓶颈
        例如,文件操作、加密算法、图像处理等任务都应该在后端实现
    c.前端职责划分
        前端JavaScript/TypeScript代码专注于用户界面渲染、用户交互处理和业务逻辑协调
        前端应该尽可能地保持轻量,将复杂的计算和数据处理委托给后端
        这种分工确保了应用的响应性能和用户体验

02.后端架构设计
    a.服务层设计
        // src-tauri/src/services/mod.rs
        pub mod file_service;
        pub mod crypto_service;
        pub mod image_service;

        use serde::{Deserialize, Serialize};

        #[derive(Debug, Serialize, Deserialize)]
        pub struct ServiceResult<T> {
            pub success: bool,
            pub data: Option<T>,
            pub error: Option<String>,
        }

        impl<T> ServiceResult<T> {
            pub fn success(data: T) -> Self {
                Self {
                    success: true,
                    data: Some(data),
                    error: None,
                }
            }

            pub fn error(message: String) -> Self {
                Self {
                    success: false,
                    data: None,
                    error: Some(message),
                }
            }
        }
    b.命令层设计
        命令层负责处理前端请求,协调服务层完成业务逻辑
        每个命令应该有明确的职责,避免过于复杂的逻辑
        使用类型安全的参数和返回值,确保前后端通信的可靠性
    c.数据访问层
        数据访问层负责与数据库、文件系统等存储介质交互
        封装具体的存储实现,提供统一的数据访问接口
        处理事务管理和数据一致性

03.前端架构设计
    a.服务层设计
        // src/services/ApiService.ts
        import { invoke } from '@tauri-apps/api/tauri';

        export class ApiService {
            async processFile(filePath: string): Promise<any> {
                try {
                    const result = await invoke('process_file', { filePath });
                    return result;
                } catch (error) {
                    console.error('文件处理失败:', error);
                    throw error;
                }
            }

            async encryptData(data: string, key: string): Promise<string> {
                try {
                    const result = await invoke('encrypt_data', { data, key });
                    return result;
                } catch (error) {
                    console.error('数据加密失败:', error);
                    throw error;
                }
            }
        }
    b.状态管理
        使用现代前端状态管理库(如Redux、Vuex等)管理应用状态
        将状态与UI分离,提高代码的可维护性和可测试性
        实现状态的持久化和恢复机制
    c.组件设计
        采用组件化开发模式,提高代码复用性
        设计可复用的UI组件库,保持界面一致性
        实现组件的懒加载和按需加载,优化应用性能

04.数据流设计
    a.单向数据流
        数据流设计应该遵循单向数据流的原则,避免复杂的状态同步问题
        前端通过命令向后端请求数据或操作,后端通过事件向前端推送状态变化
        这种模式确保了数据的一致性和可预测性
    b.事件驱动架构
        // src-tauri/src/events.rs
        use tauri::{AppHandle, Manager, Emitter};
        use serde_json::Value;

        pub fn emit_state_change(app: &AppHandle, state: &str, data: Value) {
            let _ = app.emit("state-change", serde_json::json!({
                "state": state,
                "data": data,
                "timestamp": chrono::Utc::now().timestamp()
            }));
        }

        // 使用示例
        #[tauri::command]
        async fn update_user_profile(app: AppHandle, user_id: String, profile: Value) -> Result<(), String> {
            // 更新用户配置文件
            let updated_profile = update_profile_in_database(&user_id, &profile)
                .await
                .map_err(|e| format!("更新配置文件失败: {}", e))?;

            // 发送状态变化事件
            emit_state_change(&app, "user_profile_updated", updated_profile);

            Ok(())
        }
    c.错误处理策略
        设计统一的错误处理机制,确保错误能够被正确捕获和处理
        前端实现全局错误处理器,后端使用Result类型处理错误
        提供用户友好的错误提示,同时记录详细的错误日志

7.2 性能优化策略

01.前端性能优化
    a.资源加载优化
        前端资源优化包括代码分割、懒加载和资源压缩
        Tauri应用虽然是桌面应用,但仍需要关注首次加载时间
        通过动态导入和路由级别的代码分割,可以显著减少初始包大小
    b.路由级代码分割
        // src/router/index.ts
        import { createRouter, createWebHistory } from 'vue-router';

        const router = createRouter({
            history: createWebHistory(),
            routes: [
                {
                    path: '/',
                    name: 'Home',
                    component: () => import('../views/Home.vue')
                },
                {
                    path: '/settings',
                    name: 'Settings',
                    component: () => import('../views/Settings.vue')
                }
            ]
        });

        export default router;
    c.资源压缩和优化
        图片和字体资源的优化也能提升应用启动速度
        使用现代图片格式(如WebP)减少资源大小
        实现资源的预加载和缓存策略

02.后端性能优化
    a.算法和数据结构优化
        后端性能优化重点关注算法选择和数据结构
        Rust的零成本抽象和编译时优化为高性能计算提供了基础,但合理的算法选择更为重要
        对于文件操作,使用缓冲和批处理可以显著提升I/O性能
    b.文件操作优化
        // src-tauri/src/utils/performance.rs
        use std::io::{BufReader, BufRead};
        use std::fs::File;

        pub fn process_large_file(file_path: &str) -> Result<Vec<String>, std::io::Error> {
            let file = File::open(file_path)?;
            let reader = BufReader::new(file);

            let mut results = Vec::new();
            for line in reader.lines() {
                let line = line?;
                if line.len() > 0 {
                    results.push(line);
                }
            }

            Ok(results)
        }
    c.并行处理优化
        // 使用并行处理提升CPU密集型任务性能
        use rayon::prelude::*;

        pub fn process_data_parallel(data: Vec<i32>) -> Vec<i32> {
            data.par_iter()
                .map(|x| x * 2 + 1)
                .collect()
        }

03.内存管理优化
    a.前端内存管理
        内存管理优化对于长时间运行的桌面应用尤为重要
        前端需要避免内存泄漏,合理管理事件监听器和定时器
        使用WeakMap和WeakRef避免循环引用
    b.内存管理工具
        // src/utils/MemoryManager.ts
        export class MemoryManager {
            private timers: Map<string, NodeJS.Timeout> = new Map();
            private listeners: Map<string, EventListener> = new Map();

            setTimer(id: string, callback: () => void, delay: number): void {
                this.clearTimer(id);
                const timer = setTimeout(() => {
                    callback();
                    this.timers.delete(id);
                }, delay);
                this.timers.set(id, timer);
            }

            clearTimer(id: string): void {
                const timer = this.timers.get(id);
                if (timer) {
                    clearTimeout(timer);
                    this.timers.delete(id);
                }
            }

            addListener(element: Element, event: string, listener: EventListener): void {
                element.addEventListener(event, listener);
                const key = `${element.tagName}-${event}`;
                this.listeners.set(key, listener);
            }

            cleanup(): void {
                // 清理所有定时器
                this.timers.forEach(timer => clearTimeout(timer));
                this.timers.clear();

                // 清理所有事件监听器
                this.listeners.clear();
            }
        }
    c.后端内存管理
        后端Rust虽然有自动内存管理,但仍需要注意数据结构的生命周期和大型对象的释放
        使用引用计数和智能指针管理复杂对象的生命周期
        避免不必要的数据复制,使用引用和借用减少内存占用

04.渲染性能优化
    a.虚拟列表技术
        对于大量数据的展示,使用虚拟列表技术只渲染可见区域的元素
        实现高效的滚动和更新机制
        使用requestAnimationFrame优化动画和滚动性能
    b.渲染批处理
        批处理DOM操作,减少重排和重绘
        使用CSS transform和opacity实现动画,避免触发布局计算
        利用硬件加速提升渲染性能
    c.资源预加载
        预加载关键资源,减少用户等待时间
        实现资源的懒加载和按需加载
        使用Service Worker缓存静态资源

7.3 安全性最佳实践

01.配置层面安全
    a.安全白名单配置
        Tauri的安全性设计从根本上考虑了威胁模型,通过多层防护机制保护应用和用户数据
        安全最佳实践从配置、代码设计和运行时监控三个层面确保应用的安全可靠
        配置层面的安全主要通过tauri.conf.json的安全白名单实现
    b.最小权限原则
        遵循最小权限原则,只开启应用必需的API权限
        文件系统访问应该限制在特定的目录范围,避免意外的文件访问
        对于网络请求,应该明确允许的域名和协议
    c.安全配置示例
        {
            "tauri": {
                "allowlist": {
                    "all": false,
                    "fs": {
                        "all": false,
                        "readFile": true,
                        "writeFile": true,
                        "scope": ["$APPDATA/app/*", "$DOCUMENT/app/*"]
                    },
                    "http": {
                        "all": false,
                        "request": true,
                        "scope": ["https://api.example.com/*"]
                    },
                    "dialog": {
                        "all": false,
                        "open": true,
                        "save": true
                    }
                },
                "security": {
                    "csp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:"
                }
            }
        }

02.输入验证和数据处理
    a.输入验证原则
        输入验证和数据处理是防止安全漏洞的关键
        所有来自前端的数据都应该在后端进行严格验证,防止注入攻击和恶意数据
        使用强类型和序列化验证可以减少运行时错误和安全风险
    b.数据验证实现
        // src-tauri/src/validation.rs
        use serde::{Deserialize, Serialize};
        use validator::{Validate, ValidationError};

        #[derive(Debug, Deserialize, Validate)]
        pub struct UserData {
            #[validate(length(min = 1, max = 100))]
            pub username: String,

            #[validate(email)]
            pub email: String,

            #[validate(length(min = 8))]
            pub password: String,
        }

        impl UserData {
            pub fn validate_input(&self) -> Result<(), String> {
                match self.validate() {
                    Ok(_) => Ok(()),
                    Err(errors) => {
                        let error_messages: Vec<String> = errors
                            .field_errors()
                            .values()
                            .flatten()
                            .map(|e| e.message.clone().unwrap_or_default().to_string())
                            .collect();
                        Err(error_messages.join(", "))
                    }
                }
            }
        }
    c.安全数据处理
        #[tauri::command]
        async fn create_user(user_data: UserData) -> Result<String, String> {
            // 验证输入数据
            user_data.validate_input()
                .map_err(|e| format!("输入验证失败: {}", e))?;

            // 处理用户创建逻辑
            let user_id = create_user_in_database(&user_data)
                .await
                .map_err(|e| format!("创建用户失败: {}", e))?;

            Ok(user_id)
        }

03.敏感数据处理
    a.敏感数据保护原则
        敏感数据处理需要特别的防护措施
        密码、API密钥和令牌等敏感信息应该避免在前端存储,必要时使用安全的存储机制
        Rust的内存安全特性为敏感数据处理提供了额外保护,但仍需要正确的实现方式
    b.安全存储实现
        // src-tauri/src/security.rs
        use std::sync::Mutex;
        use tauri::State;

        pub struct SecureStorage {
            secrets: Mutex<std::collections::HashMap<String, String>>,
        }

        impl SecureStorage {
            pub fn new() -> Self {
                Self {
                    secrets: Mutex::new(std::collections::HashMap::new()),
                }
            }

            pub fn store_secret(&self, key: &str, value: &str) -> Result<(), String> {
                // 在实际应用中,这里应该使用操作系统提供的密钥存储
                let mut secrets = self.secrets.lock()
                    .map_err(|e| format!("锁定失败: {}", e))?;
                secrets.insert(key.to_string(), value.to_string());
                Ok(())
            }

            pub fn get_secret(&self, key: &str) -> Result<Option<String>, String> {
                let secrets = self.secrets.lock()
                    .map_err(|e| format!("锁定失败: {}", e))?;
                Ok(secrets.get(key).cloned())
            }

            pub fn clear_secret(&self, key: &str) -> Result<(), String> {
                let mut secrets = self.secrets.lock()
                    .map_err(|e| format!("锁定失败: {}", e))?;
                secrets.remove(key);
                Ok(())
            }
        }
    c.身份验证实现
        // 使用示例
        #[tauri::command]
        async fn authenticate_user(
            username: String,
            password: String,
            storage: State<'_, SecureStorage>
        ) -> Result<bool, String> {
            // 验证用户凭据(这里简化为示例)
            if username == "admin" && password == "secure_password" {
                // 生成会话令牌
                let session_token = generate_session_token(&username)?;
                storage.store_secret("session_token", &session_token)?;
                Ok(true)
            } else {
                Err("用户名或密码错误".to_string())
            }
        }

04.网络安全
    a.HTTPS强制使用
        确保所有网络请求使用HTTPS协议
        验证SSL证书,防止中间人攻击
        实现证书固定(Certificate Pinning)增强安全性
    b.请求安全
        // src-tauri/src/network_security.rs
        #[tauri::command]
        async fn secure_api_call(
            url: String,
            data: serde_json::Value
        ) -> Result<serde_json::Value, String> {
            // 验证URL
            if !url.starts_with("https://") {
                return Err("只允许HTTPS请求".to_string());
            }

            let client = reqwest::Client::builder()
                .timeout(std::time::Duration::from_secs(30))
                .build()
                .map_err(|e| e.to_string())?;

            let response = client
                .post(&url)
                .header("Content-Type", "application/json")
                .json(&data)
                .send()
                .await
                .map_err(|e| e.to_string())?;

            if response.status().is_success() {
                let result = response.json().await
                    .map_err(|e| e.to_string())?;
                Ok(result)
            } else {
                Err(format!("API调用失败: {}", response.status()))
            }
        }
    c.数据传输安全
        实现请求签名机制,防止请求篡改
        使用加密传输敏感数据
        实现重放攻击防护机制

7.4 错误处理与日志

01.前端错误处理
    a.全局错误处理
        完善的错误处理和日志系统是生产级应用的基础
        Tauri应用需要在前后端实现统一的错误处理策略,确保错误能够被正确捕获、记录和用户友好地展示
        前端错误处理应该覆盖所有可能的异常场景,包括网络错误、API调用失败和用户输入错误
    b.错误处理器实现
        // src/utils/ErrorHandler.ts
        export interface AppError {
            code: string;
            message: string;
            details?: any;
        }

        export class ErrorHandler {
            private static instance: ErrorHandler;
            private errorListeners: ((error: AppError) => void)[] = [];

            static getInstance(): ErrorHandler {
                if (!ErrorHandler.instance) {
                    ErrorHandler.instance = new ErrorHandler();
                }
                return ErrorHandler.instance;
            }

            addErrorListener(listener: (error: AppError) => void): void {
                this.errorListeners.push(listener);
            }

            handleError(error: AppError): void {
                console.error('应用错误:', error);
                this.notifyListeners(error);
                this.logError(error);
            }

            private notifyListeners(error: AppError): void {
                this.errorListeners.forEach(listener => listener(error));
            }

            private async logError(error: AppError): Promise<void> {
                try {
                    await invoke('log_error', {
                        code: error.code,
                        message: error.message,
                        details: error.details,
                        timestamp: new Date().toISOString()
                    });
                } catch (logError) {
                    console.error('日志记录失败:', logError);
                }
            }
        }
    c.全局错误捕获
        // 全局错误处理
        window.addEventListener('error', (event) => {
            const error: AppError = {
                code: 'UNEXPECTED_ERROR',
                message: event.message,
                details: {
                    filename: event.filename,
                    lineno: event.lineno,
                    colno: event.colno,
                    stack: event.error?.stack
                }
            };
            ErrorHandler.getInstance().handleError(error);
        });

        window.addEventListener('unhandledrejection', (event) => {
            const error: AppError = {
                code: 'UNHANDLED_PROMISE_REJECTION',
                message: event.reason?.message || '未处理的Promise拒绝',
                details: event.reason
            };
            ErrorHandler.getInstance().handleError(error);
        });

02.后端错误处理
    a.错误类型定义
        后端错误处理需要利用Rust的Result类型和错误处理机制
        定义统一的错误类型,使用thiserror或anyhow等crate简化错误处理
        所有命令函数都应该返回Result类型,确保错误能够正确传播到前端
    b.错误类型实现
        // src-tauri/src/error.rs
        use thiserror::Error;

        #[derive(Error, Debug)]
        pub enum AppError {
            #[error("配置错误: {0}")]
            Config(String),

            #[error("数据库错误: {0}")]
            Database(#[from] sqlx::Error),

            #[error("文件操作错误: {0}")]
            File(#[from] std::io::Error),

            #[error("网络错误: {0}")]
            Network(String),

            #[error("验证错误: {0}")]
            Validation(String),

            #[error("权限错误: {0}")]
            Permission(String),

            #[error("内部服务器错误: {0}")]
            Internal(String),
        }

        impl AppError {
            pub fn code(&self) -> &'static str {
                match self {
                    AppError::Config(_) => "CONFIG_ERROR",
                    AppError::Database(_) => "DATABASE_ERROR",
                    AppError::File(_) => "FILE_ERROR",
                    AppError::Network(_) => "NETWORK_ERROR",
                    AppError::Validation(_) => "VALIDATION_ERROR",
                    AppError::Permission(_) => "PERMISSION_ERROR",
                    AppError::Internal(_) => "INTERNAL_ERROR",
                }
            }
        }

        // 类型别名简化Result类型
        pub type Result<T> = std::result::Result<T, AppError>;

03.日志系统
    a.日志级别和格式
        日志系统应该支持不同级别的日志记录,包括调试、信息、警告和错误
        日志应该包含足够的上下文信息,便于问题排查和性能分析
        使用结构化日志格式,便于日志分析和搜索
    b.日志记录实现
        // src-tauri/src/logging.rs
        use log::{debug, info, warn, error};
        use serde_json::json;
        use tauri::{AppHandle, Manager};

        #[tauri::command]
        async fn log_error(
            app: AppHandle,
            code: String,
            message: String,
            details: Option<serde_json::Value>,
            timestamp: String
        ) -> Result<(), String> {
            error!(
                "前端错误 - Code: {}, Message: {}, Details: {}, Timestamp: {}",
                code, message, details.unwrap_or(json!({})), timestamp
            );

            // 可选:将错误发送到远程日志服务
            if let Err(e) = send_error_to_remote_service(&app, &code, &message, details).await {
                warn!("远程日志服务发送失败: {}", e);
            }

            Ok(())
        }

        async fn send_error_to_remote_service(
            app: &AppHandle,
            code: &str,
            message: &str,
            details: Option<serde_json::Value>
        ) -> Result<(), Box<dyn std::error::Error>> {
            let log_data = json!({
                "app_version": app.package_info().version.to_string(),
                "error_code": code,
                "error_message": message,
                "error_details": details,
                "timestamp": chrono::Utc::now().to_rfc3339(),
                "platform": std::env::consts::OS
            });

            // 这里应该实现实际的远程日志发送逻辑
            debug!("发送错误日志到远程服务: {}", log_data);

            Ok(())
        }

04.性能监控和指标收集
    a.性能指标收集
        性能监控和指标收集对于优化应用性能至关重要
        通过监控关键操作的执行时间、内存使用和资源消耗,可以及时发现性能瓶颈和优化机会
        实现自定义指标收集,满足特定应用的监控需求
    b.指标收集实现
        // src-tauri/src/metrics.rs
        use std::time::{Duration, Instant};
        use std::collections::HashMap;

        pub struct MetricsCollector {
            operations: HashMap<String, Vec<Duration>>,
        }

        impl MetricsCollector {
            pub fn new() -> Self {
                Self {
                    operations: HashMap::new(),
                }
            }

            pub fn record_operation<F, R>(&mut self, operation_name: &str, f: F) -> R
            where
                F: FnOnce() -> R,
            {
                let start = Instant::now();
                let result = f();
                let duration = start.elapsed();

                self.operations
                    .entry(operation_name.to_string())
                    .or_insert_with(Vec::new)
                    .push(duration);

                debug!("操作 '{}' 耗时: {:?}", operation_name, duration);
                result
            }

            pub fn get_average_time(&self, operation_name: &str) -> Option<Duration> {
                self.operations.get(operation_name).map(|times| {
                    let total: Duration = times.iter().sum();
                    total / times.len() as u32
                })
            }

            pub fn get_metrics_summary(&self) -> serde_json::Value {
                let mut summary = serde_json::Map::new();

                for (operation, times) in &self.operations {
                    if let Some(avg_time) = self.get_average_time(operation) {
                        summary.insert(
                            operation.clone(),
                            serde_json::json!({
                                "average_time_ms": avg_time.as_millis(),
                                "total_operations": times.len(),
                                "min_time_ms": times.iter().map(|d| d.as_millis()).min().unwrap_or(0),
                                "max_time_ms": times.iter().map(|d| d.as_millis()).max().unwrap_or(0)
                            })
                        );
                    }
                }

                serde_json::Value::Object(summary)
            }
        }
    c.性能监控命令
        // 使用示例
        #[tauri::command]
        async fn process_data_with_metrics(
            data: Vec<String>,
            metrics: tauri::State<'_, MetricsCollector>
        ) -> Result<Vec<String>, AppError> {
            let result = metrics.record_operation("process_data", || {
                // 实际的数据处理逻辑
                data.iter()
                    .map(|item| format!("processed_{}", item))
                    .collect()
            });

            Ok(result)
        }

        #[tauri::command]
        async fn get_performance_metrics(
            metrics: tauri::State<'_, MetricsCollector>
        ) -> Result<serde_json::Value, AppError> {
            Ok(metrics.get_metrics_summary())
        }

7.5 测试与调试

01.测试策略概述
    a.多层次测试
        全面的测试策略是确保Tauri应用质量的关键
        由于Tauri应用包含前端和后端两个部分,测试需要覆盖单元测试、集成测试和端到端测试三个层次
        每个层次的测试都有其特定的目标和方法,共同构成完整的测试体系
    b.测试金字塔
        单元测试位于测试金字塔的底部,数量最多,执行速度最快
        集成测试位于中间层,测试组件之间的交互
        端到端测试位于顶部,数量最少,执行速度最慢,但最接近真实用户场景
    c.测试自动化
        将测试集成到CI/CD流程中,实现自动化测试
        设置测试覆盖率目标,确保代码质量
        实现测试报告和通知机制,及时发现问题

02.后端单元测试
    a.测试框架
        后端单元测试使用Rust内置的测试框架,重点测试业务逻辑、数据处理和API边界
        每个公共函数都应该有对应的测试用例,覆盖正常情况、边界情况和错误情况
        使用模拟对象和依赖注入,提高测试的可控性和可维护性
    b.测试实现
        // src-tauri/src/services/user_service.rs
        #[cfg(test)]
        mod tests {
            use super::*;
            use tokio_test;

            #[tokio::test]
            async fn test_create_user_success() {
                let user_data = UserData {
                    username: "testuser".to_string(),
                    email: "[email protected]".to_string(),
                    password: "securepassword123".to_string(),
                };

                // 模拟数据库操作
                let mock_db = MockDatabase::new();
                let result = create_user_in_database(&mock_db, &user_data).await;

                assert!(result.is_ok());
                let user_id = result.unwrap();
                assert!(!user_id.is_empty());
            }

            #[tokio::test]
            async fn test_create_user_duplicate_email() {
                let user_data = UserData {
                    username: "testuser2".to_string(),
                    email: "[email protected]".to_string(),
                    password: "securepassword123".to_string(),
                };

                let mock_db = MockDatabase::new();
                mock_db.add_existing_email("[email protected]");
                let result = create_user_in_database(&mock_db, &user_data).await;

                assert!(result.is_err());
                match result.unwrap_err() {
                    AppError::Database(db_error) => {
                        assert!(db_error.to_string().contains("duplicate email"));
                    }
                    _ => panic!("期望数据库错误"),
                }
            }
        }
    c.测试覆盖率
        使用cargo tarpaulin等工具测量测试覆盖率
        设置最低覆盖率要求,确保代码质量
        定期审查未覆盖的代码,补充相应的测试用例

03.前端单元测试
    a.测试框架选择
        前端单元测试使用Jest或Vitest等测试框架,测试组件逻辑、状态管理和工具函数
        React组件可以使用React Testing Library进行测试,Vue组件可以使用Vue Test Utils
        选择与项目技术栈匹配的测试框架和工具
    b.测试实现
        // src/__tests__/services/ApiService.test.ts
        import { describe, it, expect, vi, beforeEach } from 'vitest';
        import { ApiService } from '../../services/ApiService';

        vi.mock('@tauri-apps/api/tauri', () => ({
            invoke: vi.fn()
        }));

        describe('ApiService', () => {
            let apiService: ApiService;

            beforeEach(() => {
                apiService = new ApiService();
                vi.clearAllMocks();
            });

            it('should process file successfully', async () => {
                const mockResult = { success: true, data: 'processed data' };
                (invoke as vi.Mock).mockResolvedValue(mockResult);

                const result = await apiService.processFile('/path/to/file.txt');

                expect(invoke).toHaveBeenCalledWith('process_file', {
                    filePath: '/path/to/file.txt'
                });
                expect(result).toEqual(mockResult);
            });

            it('should handle file processing error', async () => {
                const mockError = new Error('File not found');
                (invoke as vi.Mock).mockRejectedValue(mockError);

                await expect(apiService.processFile('/nonexistent/file.txt'))
                    .rejects.toThrow('File not found');

                expect(invoke).toHaveBeenCalledWith('process_file', {
                    filePath: '/nonexistent/file.txt'
                });
            });
        });
    c.组件测试
        使用React Testing Library或Vue Test Utils测试组件行为
        模拟用户交互,验证组件响应
        测试组件的渲染输出和状态变化

04.集成测试
    a.Tauri集成测试
        集成测试验证前后端之间的交互是否正确
        Tauri提供了专门的测试工具,可以在测试环境中启动完整的应用,模拟用户操作和API调用
        测试IPC通信、事件系统和状态同步等关键功能
    b.测试实现
        // src-tauri/tests/integration_test.rs
        use tauri::{Manager, Runtime};
        use serde_json::json;

        #[tauri::command]
        async fn test_command(value: String) -> Result<String, String> {
            Ok(format!("processed: {}", value))
        }

        fn create_test_app<R: Runtime>() -> tauri::App<R> {
            tauri::Builder::default()
                .invoke_handler(tauri::generate_handler![test_command])
                .build(tauri::generate_context!())
                .expect("failed to build app")
        }

        #[test]
        fn test_command_invocation() {
            let app = create_test_app();
            let window = app.get_window("main").unwrap();

            // 模拟前端调用后端命令
            let result = tauri::test::mock_runtime(app)
                .invoke("test_command", json!("test_value"))
                .await;

            assert_eq!(result, Ok(json!("processed: test_value")));
        }
    c.端到端测试
        端到端测试使用Playwright或Cypress等工具,模拟真实用户的操作流程
        这些测试在完整的桌面应用环境中运行,验证用户界面的正确性和业务流程的完整性
        测试关键用户场景,如登录、数据操作和设置更改

05.调试工具和技巧
    a.调试工具集成
        调试工具和技巧对于开发过程中的问题排查至关重要
        Tauri应用可以利用Rust的调试工具和Web开发工具的组合优势,提供全面的调试支持
        集成VS Code调试配置,实现前后端联合调试
    b.调试命令实现
        // src-tauri/src/debug.rs
        #[cfg(debug_assertions)]
        use log::debug;

        #[tauri::command]
        async fn debug_info(app: tauri::AppHandle) -> Result<serde_json::Value, String> {
            let debug_data = serde_json::json!({
                "app_version": app.package_info().version.to_string(),
                "platform": std::env::consts::OS,
                "arch": std::env::consts::ARCH,
                "debug_mode": cfg!(debug_assertions),
                "current_dir": std::env::current_dir().unwrap_or_default().to_string_lossy(),
                "app_data_dir": app.path_resolver().app_data_dir()
                    .map(|p| p.to_string_lossy().to_string())
                    .unwrap_or_default(),
                "resource_dir": app.path_resolver().resource_dir()
                    .map(|p| p.to_string_lossy().to_string())
                    .unwrap_or_default()
            });

            #[cfg(debug_assertions)]
            debug!("调试信息请求: {:?}", debug_data);

            Ok(debug_data)
        }
    c.开发模式调试
        // 开发模式下的调试命令
        #[cfg(debug_assertions)]
        #[tauri::command]
        async fn simulate_error(error_type: String) -> Result<(), String> {
            match error_type.as_str() {
                "network" => Err("模拟网络错误".to_string()),
                "database" => Err("模拟数据库错误".to_string()),
                "validation" => Err("模拟验证错误".to_string()),
                _ => Err("未知错误类型".to_string()),
            }
        }