From 98329cd44b3e84407e91eb061c25dbbc6785cdac Mon Sep 17 00:00:00 2001 From: imbytecat Date: Fri, 16 Jan 2026 20:22:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86=E5=8F=8ANitro=E8=BF=9B?= =?UTF-8?q?=E7=A8=8B=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加全局状态管理以跟踪 Nitro 进程句柄,并在应用启动时创建加载窗口,启动 Nitro sidecar 后自动关闭加载窗口并显示主窗口,同时在应用退出时正确终止 Nitro 进程。 --- src-tauri/src/lib.rs | 63 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index bcc634c..314c7c5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,6 +1,11 @@ +use tauri::Manager; use tauri_plugin_shell::ShellExt; -use tauri_plugin_shell::process::CommandEvent; +use tauri_plugin_shell::process::{CommandEvent, CommandChild}; use std::time::Duration; +use std::sync::Mutex; + +// 全局状态:存储 Nitro 进程句柄 +struct NitroProcess(Mutex>); // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ #[tauri::command] @@ -31,8 +36,25 @@ pub fn run() { .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_shell::init()) .setup(|app| { + // 使用 Tauri 的状态管理存储进程句柄 + app.manage(NitroProcess(Mutex::new(None))); + let app_handle = app.handle().clone(); + // 先创建 loading 窗口 + let _loading_window = tauri::WebviewWindowBuilder::new( + app, + "loading", + tauri::WebviewUrl::App("loading.html".into()) + ) + .title("正在启动...") + .inner_size(400.0, 300.0) + .center() + .resizable(false) + .decorations(true) + .build() + .expect("创建 loading 窗口失败"); + // 异步启动 Nitro sidecar tauri::async_runtime::spawn(async move { // 查找可用端口 @@ -46,7 +68,12 @@ pub fn run() { .expect("无法找到 nitro-server sidecar") .env("NITRO_PORT", port.to_string()); - let (mut rx, mut _child) = sidecar.spawn().expect("启动 sidecar 失败"); + let (mut rx, child) = sidecar.spawn().expect("启动 sidecar 失败"); + + // 保存进程句柄到全局状态 + if let Some(state) = app_handle.try_state::() { + *state.0.lock().unwrap() = Some(child); + } // 监听 stdout,等待服务器就绪信号 let start_time = std::time::Instant::now(); @@ -65,16 +92,25 @@ pub fn run() { // 创建主窗口 let url = format!("http://localhost:{}", port); - tauri::WebviewWindowBuilder::new( + let main_window = tauri::WebviewWindowBuilder::new( &app_handle, "main", tauri::WebviewUrl::External(url.parse().unwrap()) ) .title("Nitro Application") .inner_size(1200.0, 800.0) + .center() .build() .expect("创建窗口失败"); + // 关闭 loading 窗口 + if let Some(loading) = app_handle.get_webview_window("loading") { + let _ = loading.close(); + } + + // 显示主窗口 + let _ = main_window.show(); + break; } } @@ -95,6 +131,23 @@ pub fn run() { Ok(()) }) .invoke_handler(tauri::generate_handler![greet]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); + .build(tauri::generate_context!()) + .expect("error while building tauri application") + .run(|app_handle, event| { + // 监听应用退出事件,清理 Nitro 进程 + match event { + tauri::RunEvent::ExitRequested { .. } | tauri::RunEvent::Exit => { + println!("应用退出,正在清理 Nitro 进程..."); + if let Some(state) = app_handle.try_state::() { + if let Ok(mut process) = state.0.lock() { + if let Some(child) = process.take() { + let _ = child.kill(); + println!("✓ Nitro 进程已终止"); + } + } + } + } + _ => {} + } + }); }