diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs index 32b49adc6..05a4ed683 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/persistence.rs @@ -42,7 +42,13 @@ pub fn project_relative_path(root: &Path, path: &Path) -> Result Ok(value) } -pub fn write_separation_state(path: &Path, state: &SeparationState) -> Result<(), String> { +pub async fn write_separation_state(path: PathBuf, state: SeparationState) -> Result<(), String> { + tokio::task::spawn_blocking(move || write_separation_state_blocking(&path, &state)) + .await + .map_err(|error| format!("写入 separation state 任务失败:{error}"))? +} + +fn write_separation_state_blocking(path: &Path, state: &SeparationState) -> Result<(), String> { if state.schema_version != SEPARATION_STATE_SCHEMA_VERSION { app_log!("ui_separation.error stage=state_write reason=schema_mismatch"); return Err("不支持的 separation state schema".to_string()); diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs index 62dae2474..c4195e9ad 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/separation/workflow/mod.rs @@ -98,13 +98,15 @@ pub(crate) async fn separate_ui_impl( image.pixel_size.x.round() as u32, image.pixel_size.y.round() as u32 ); - write_separation_state(&state_path, &separation).map_err(|error| { - app_log!( - "ui_separation.error stage=state_checkpoint tree_index={} error={error}", - tree_index - ); - error - })?; + write_separation_state(state_path.clone(), separation.clone()) + .await + .map_err(|error| { + app_log!( + "ui_separation.error stage=state_checkpoint tree_index={} error={error}", + tree_index + ); + error + })?; let mut batch_index = 0usize; loop { let batch_started = Instant::now(); @@ -146,7 +148,7 @@ pub(crate) async fn separate_ui_impl( Ok(value) => value, Err(error) => { app_log!("ui_separation.error stage=image_edit tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(&state_path, &separation)?; + write_separation_state(state_path.clone(), separation.clone()).await?; return Err(error); } }; @@ -155,7 +157,7 @@ pub(crate) async fn separate_ui_impl( extract::write_processed_image(processed_url.clone(), processed_path.clone()).await { app_log!("ui_separation.error stage=processed_image_write tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(&state_path, &separation)?; + write_separation_state(state_path.clone(), separation.clone()).await?; return Err(error); } let binding = match binding::visual_binding( @@ -169,7 +171,7 @@ pub(crate) async fn separate_ui_impl( Ok(value) => value, Err(error) => { app_log!("ui_separation.error stage=visual_binding tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(&state_path, &separation)?; + write_separation_state(state_path.clone(), separation.clone()).await?; return Err(error); } }; @@ -220,11 +222,11 @@ pub(crate) async fn separate_ui_impl( } if let Some(error) = cut_error { app_log!("ui_separation.error stage=cut_batch tree_index={} batch_index={} error={error}", tree_index, batch_index); - write_separation_state(&state_path, &separation)?; + write_separation_state(state_path.clone(), separation.clone()).await?; return Err(error); } patch::apply_batch_patch(&mut separation, tree_index, &binding.decisions, &cut_paths)?; - write_separation_state(&state_path, &separation)?; + write_separation_state(state_path.clone(), separation.clone()).await?; app_log!( "ui_separation.batch_completed tree_index={} batch_index={} cuts={} bound={} problematic={} elapsed_ms={}", tree_index, batch_index, cut_paths.len(), separation.bound.len(), separation.problematic_nodes.len(), batch_started.elapsed().as_millis()