# zero_tauri **Repository Path**: zmmlet/zero_tauri ## Basic Information - **Project Name**: zero_tauri - **Description**: tauri 基于webview的桌面端架构,当前实现了基础项目框架,便于熟悉tarui开发和实际项目使用 - **Primary Language**: JavaScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-03-25 - **Last Updated**: 2025-09-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Tauri + Vue + TypeScript This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` ``` ## 获取系统信息 安装后会自动写入到 package.json 文件和 Cargo.toml 文件,支持 前端 JS 调用和 后端 Rust 调用 - 安装 `pnpm tauri add os` - Api[https://v2.tauri.org.cn/reference/javascript/os/#arch-1] ## 系统提示对话框 - 安装 `pnpm tauri add dialog` - Api[https://tauri.app/zh-cn/plugin/dialog/] 报错 ```sh Info Installing NPM dependency "@tauri-apps/plugin-dialog@~2"...  ERR_PNPM_VIRTUAL_STORE_DIR_MAX_LENGTH_DIFF  This modules directory was created using a different virtual-store-dir-max-length value. Run "pnpm install" to recreate the modules directory. Failed to install NPM dependency Error Failed to install NPM dependency  ELIFECYCLE  Command failed with exit code 1. ``` 解决方法 npm install -g pnpm ## 1自定义托盘 1. 添加配置 src-tauri\tauri.conf.json ```json "app": { "windows": [ ], "trayIcon": { "iconPath": "icons/icon.ico", "iconAsTemplate": true, "title": "时间管理器", "tooltip": "时间管理器" } }, ``` 2. 添加自定义图标权限 src-tauri\Cargo.toml ```toml [dependencies] tauri = { version = "2", features = ["tray-icon", "image-png"] } ``` 3. 创建自定义托盘 - 3.1 src-tauri\src\tray.rs ```rs use tauri::{ menu::{Menu, MenuItem, Submenu}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, Manager, Runtime, }; pub fn create_tray(app: &tauri::AppHandle) -> tauri::Result<()> { let quit_i = MenuItem::with_id(app, "quit", "退出", true, None::<&str>)?; let show_i = MenuItem::with_id(app, "show", "显示", true, None::<&str>)?; let hide_i = MenuItem::with_id(app, "hide", "隐藏", true, None::<&str>)?; let edit_i = MenuItem::with_id(app, "edit_file", "编辑", true, None::<&str>)?; let new_i = MenuItem::with_id(app, "new_file", "添加", true, None::<&str>)?; let a =Submenu::with_id_and_items(app, "File", "文章", true, &[&new_i, &edit_i])?; // 分割线 let menu = Menu::with_items(app, &[&quit_i, &show_i, &hide_i, &a])?; // 创建系统托盘 let _ = TrayIconBuilder::with_id("tray") // 添加托盘图标 .icon(app.default_window_icon().unwrap().clone()) // 添加菜单 .menu(&menu) // 禁用鼠标左键点击图标显示托盘菜单 .show_menu_on_left_click(false) // 监听事件菜单 .on_menu_event(move |app, event| match event.id.as_ref() { "quit" => { app.exit(0); }, "show" => { let window = app.get_webview_window("main").unwrap(); let _ = window.show(); }, "hide" => { let window = app.get_webview_window("main").unwrap(); let _ = window.hide(); }, "edit_file" => { println!("edit_file"); }, "new_file" => { println!("new_file"); }, // Add more events here _ => {} }) // 监听托盘图标发出的鼠标事件 .on_tray_icon_event(|tray, event| { // 左键点击托盘图标显示窗口 if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(window) = app.get_webview_window("main") { let _ = window.show(); let _ = window.set_focus(); } } }) .build(app); Ok(()) } ``` -3.2 在 src-tauri\src\lib.rs 文件中引用 ```rs #[cfg(desktop)] mod tray; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() // 添加自定义托盘 .setup(|app| { #[cfg(all(desktop))] { let handle = app.handle(); tray::create_tray(handle)?; } Ok(()) }) // 引用插件 .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ``` ## 1托盘图标闪烁 1. 托盘事件定义 tray.rs ```rs use tauri::{ menu::{Menu, MenuItem, Submenu}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, Manager, Runtime, }; pub fn create_tray(app: &tauri::AppHandle) -> tauri::Result<()> { let quit_i = MenuItem::with_id(app, "quit", "退出", true, None::<&str>)?; let show_i = MenuItem::with_id(app, "show", "显示", true, None::<&str>)?; let hide_i = MenuItem::with_id(app, "hide", "隐藏", true, None::<&str>)?; let edit_i = MenuItem::with_id(app, "edit_file", "编辑", true, None::<&str>)?; let new_i = MenuItem::with_id(app, "new_file", "添加", true, None::<&str>)?; let a = Submenu::with_id_and_items(app, "File", "文章", true, &[&new_i, &edit_i])?; // 分割线 let menu = Menu::with_items(app, &[&quit_i, &show_i, &hide_i, &a])?; // 创建系统托盘 let _ = TrayIconBuilder::with_id("icon") let _ = TrayIconBuilder::with_id("tray") // 添加菜单 .menu(&menu) // 添加托盘图标 .icon(app.default_window_icon().unwrap().clone()) .title("zero") .tooltip("zero") .show_menu_on_left_click(false) // 禁用鼠标左键点击图标显示托盘菜单 // .show_menu_on_left_click(false) // 监听事件菜单 .on_menu_event(move |app, event| match event.id.as_ref() { "quit" => { app.exit(0); } "show" => { let window = app.get_webview_window("main").unwrap(); let _ = window.show(); } "hide" => { let window = app.get_webview_window("main").unwrap(); let _ = window.hide(); } "edit_file" => { println!("edit_file"); } "new_file" => { println!("new_file"); } // Add more events here _ => {} }) // 监听托盘图标发出的鼠标事件 .on_tray_icon_event(|tray, event| { // 左键点击托盘图标显示窗口 if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(window) = app.get_webview_window("main") { let _ = window.show(); let _ = window.set_focus(); } } }) .build(app); Ok(()) } ``` 2. lib.rs 使用 ```rs #[cfg(desktop)] mod tray; // 自定义函数声明 #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_log::Builder::new().build()) // 添加自定义托盘 .setup(|app| { #[cfg(all(desktop))] { let handle: &tauri::AppHandle = app.handle(); tray::create_tray(handle)?; } Ok(()) }) // Run the app // 注册 Rust 后端函数,暴露给前端调用 .invoke_handler(tauri::generate_handler![ greet ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ``` 3. 调用托盘事件 ```vue ``` ## http 1. 依赖安装`pnpm tauri add http` 2. 权限配置 src-tauri\capabilities\default.json ```json { "permissions": [ "core:default", "opener:default", { "identifier": "http:default", "allow": [ { "url": "http://**" }, { "url": "https://**" }, { "url": "http://*:*" }, { "url": "https://*:*" } ] } ] } ``` 3. vite.config.json 配置代理 ```ts import { ConfigEnv, defineConfig, loadEnv } from "vite"; import vue from "@vitejs/plugin-vue"; import { resolve } from "node:path"; import { fileURLToPath, URL } from "node:url"; const host = process.env.TAURI_DEV_HOST; export default defineConfig(({ mode }: ConfigEnv) => { const config = loadEnv(mode, process.cwd()); return { // ...... server: { //配置跨域 proxy: { "/tick-basic": { // “/api” 以及前置字符串会被替换为真正域名 target: config.VITE_SERVICE_URL, // 请求域名 changeOrigin: true, // 是否跨域 rewrite: (path) => path.replace(/^\/api/, ""), }, }, port: 1420, strictPort: true, host: host || false, cors: true, // 配置 CORS hmr: host ? { protocol: "ws", host, port: 1421, } : undefined, watch: { ignored: ["**/src-tauri/**"], }, }, }; }); ``` 4. 请求封装 5. 使用封装请求 ## 文件上传下载 1. 依赖安装 `pnpm tauri add upload` ## SQL 1. 依赖安装`pnpm tauri add sql` 2. 在 src-tauri 目录下执行 `cargo add tauri-plugin-sql --features sqlite` ## UI 库 ```sh pnpm add unplugin-auto-import unplugin-vue-components naive-ui -D ``` ```sh pnpm add vue-router@4 ``` ```sh pnpm add pinia pinia-plugin-persistedstate pinia-shared-state ``` ```sh pnpm add @rollup/plugin-terser --dev pnpm add @codecov/vite-plugin --save-dev ``` ```sh pnpm add eslint@latest eslint-plugin-vue@latest -D pnpm add prettier@latest -D ``` 天文计算:使用 astronomy-engine 或 suncalc 来计算行星位置和天象。 农历和节气:使用 lunar-javascript 或 chinese-lunar 来计算农历日期和节气。 ```sh pnpm add lunar-typescript pnpm add astronomy-engine ``` ## TODO 多窗口 ## TODO 发版更新提示 ## TODO 启动画面 https://blog.csdn.net/sxlesq/article/details/145112068?spm=1001.2014.300 src-tauri\tauri.conf.json ```json "app": { "windows": [ { "title": "tauri_demo", "width": 800, "height": 600, "center": true, "fullscreen": false, "resizable": true, "minWidth": 800, "minHeight": 600, "visible": false }, { "label": "start", "url": "/start.html", "center": true, "width": 1200, "height": 800 } ], "security": { "csp": null } }, ``` ## Android环境变量配置 Tauri 开发 Android 应用:环境搭建与入门指南[https://www.kucoding.com/article/259.html] ANDROID_HOME C:\Users\yu\AppData\Local\Android\Sdk JAVA_HOME C:\Program Files\Android\Android Studio\jbr NDK_HOME C:\Users\yu\AppData\Local\Android\Sdk\ndk\27.0.12077973 注意:需要开启,windows11 开发者模式,否则没有调试权限,启动报错 所需要的 JVM 版本大于实际安装版本 ```sh FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':buildSrc:compileKotlin'. > Could not resolve all files for configuration ':buildSrc:compileClasspath'. > Could not resolve com.android.tools.build:gradle:8.5.1. Required by: project :buildSrc > Dependency requires at least JVM runtime version 11. This build uses a Java 8 JVM. * Try: > Run this build using a Java 11 or newer JVM. > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. > Get more help at https://help.gradle.org. BUILD FAILED in 1s  ELIFECYCLE  Command failed with exit code 4294967295. ``` 打包数字证书配置 ## 更新 密钥密码 zero 1. 安装 `pnpm tauri add updater` ```mermaid graph LR [ 外部网络 ] │ ▼ [ 边界防火墙 ] │ ▼ [ 入站流量层 ] ├─ [反向代理集群](如Nginx/HAProxy) └─ [API网关](如Kong/Spring Cloud Gateway) │ ▼ [ 网络安全平台 ] ├─ 防火墙(区域隔离) ├─ IDS/IPS(入侵检测防御) ├─ WAF(Web应用防火墙) └─ 流量审计系统 │ ▼ [ DMZ区 ] ├─ 公共服务集群 │ ├─ 认证服务(OAuth2/Keycloak) │ └─ 缓存服务(Redis集群) │ └─ [出站代理服务器](Squid/正向代理) │ ▼ [ 内部防火墙 ] │ ▼ [ 内网服务层 ] ├─ [内网API网关](服务路由) ├─ 微服务集群(Docker/K8s Pods) ├─ 数据库集群(主从隔离) └─ 消息队列(Kafka/RabbitMQ) │ ▼ [ 内部安全审计 ] ├─ 日志聚合(ELK/Grafana) └─ 行为监控(SIEM系统) ``` 入站请求路径: 客户端 → 边界防火墙(仅放行HTTPS) → 反向代理(URL路由) → WAF(过滤SQLi/XSS) → API网关(鉴权) → 内网微服务 → 数据库 出站请求路径: 内网服务 → 出站代理(域名白名单) → IPS(检测C2通信特征) → 流量审计(记录完整Payload) → 外部API ## 会议系统 系统架构图 ```mermaid graph TD subgraph 客户端 A[Tauri桌面应用] -->|WebRTC媒体流| B((会议房间)) A -->|WebSocket协议| C[信令服务器] A -->|SIP协议| F[FreeSWITCH服务器] A -->|Vue3+TS UI| D[用户界面] end subgraph 服务端 C -->|控制信令| E[FreeSWITCH服务器] E -->|SIP协议| F E -->|RTP/RTCP媒体流| B E -->|数据库操作| G[(数据库)] F -->|SIP中继| H[外部PSTN/SIP网络] end ``` 技术架构图 ```mermaid graph LR subgraph 客户端技术栈 A1[Tauri Core] --> A2[Rust后端] A1 --> A3[WebView渲染] A3 --> A4[Vue3+TS] A4 --> A5[WebRTC API] A4 --> A6[WebSocket Client] A4 --> A7[SIP.js] end subgraph 信令服务 B1[Node.js/Go] --> B2[WebSocket Server] B2 --> B3[信令路由] B3 --> B4[FreeSWITCH ESL] end subgraph 媒体服务 C1[FreeSWITCH] --> C2[会议模块] C1 --> C3[WebRTC网关] C1 --> C4[SIP协议栈] C1 --> C5[RTP引擎] end subgraph 基础设施 D1[PostgreSQL] --> D2[用户数据] D2 --> D3[会议记录] D4[STUN/TURN] --> D5[NAT穿透] end ``` 技术架构说明 客户端层 复制 ┌───────────────────────┐ │ Tauri应用架构 │ ├──────────┬────────────┤ │ Rust层 │ WebView层 │ │ (系统交互)│ Vue3+TS │ │ │ WebRTC API │ │ │ SIP.js │ │ │ WebSocket │ └──────────┴────────────┘ Tauri框架:使用Rust处理原生系统交互,WebView承载Vue界面 Vue3+TS:采用组合式API+TypeScript实现响应式UI WebRTC:处理音视频采集、编解码、网络传输 SIP.js:实现SIP协议栈对接传统电话系统 WebSocket:与信令服务器保持长连接 信令服务层 复制 ┌──────────────────────────────┐ │ 信令服务器功能模块 │ ├─────────────┬────────────────┤ │ 连接管理 │ 信令路由 │ │ 房间状态同步│ FreeSWITCH控制 │ │ 安全认证 │ 事件日志 │ └─────────────┴────────────────┘ 采用Node.js/Go语言开发 实现信令路由、状态同步、权限验证 通过ESL(Event Socket Library)控制FreeSWITCH 媒体服务层 复制 ┌──────────────────────────────┐ │ FreeSWITCH核心功能 │ ├──────────────┬───────────────┤ │ 会议管理 │ SIP协议栈 │ │ 媒体路由 │ WebRTC网关 │ │ 混流服务 │ 录音录像 │ │ DTMF处理 │ 编解码转换 │ └──────────────┴───────────────┘ 支持多种编解码器(OPUS/H264/VP8) 提供会议混音、视频合屏功能 实现WebRTC与传统SIP的协议互通 协议交互流程 用户通过Vue界面发起呼叫 WebSocket发送SDP Offer到信令服务器 信令服务器通过ESL创建FreeSWITCH会议 FreeSWITCH通过SIP协议与终端建立连接 WebRTC ICE协商完成P2P媒体传输 通话质量监控通过RTCP反馈实现 关键技术组合 WebRTC+FreeSWITCH:通过mod_verto模块实现浏览器端WebRTC接入 SIP协议集成:使用RFC7118规范实现WebRTC与SIP的SDP转换 Tauri优化:使用Rust实现高性能的屏幕共享采集 QoS保障:采用TWCC协议实现网络拥塞控制 建议在具体实现时: 使用mediasoup替代原生WebRTC以获得更好的SFU控制 采用Kurento实现高级媒体处理功能 集成Janus Gateway实现更好的协议转换支持