From f1ebd47ff7cc3fc3b059949d60f6d920c2fc3caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 19 Aug 2026 13:06:50 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=20UI=20=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E7=B4=A0=E6=9D=90=E5=AF=BC=E5=85=A5=E5=88=B0=E9=98=BB?= =?UTF-8?q?=E5=A1=9E=E5=B7=A5=E4=BD=9C=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将本地与远端素材导入的同步校验和文件事务移入 Tokio blocking worker 保持项目写锁只覆盖 worker 内的连续同步临界区 补充异步导入命令的本地图片导入回归测试 --- .../src-tauri/src/commands.rs | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/commands.rs b/apps/ai-game-creator-shell/src-tauri/src/commands.rs index a4aa7e7e0..2bc1721e5 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/commands.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/commands.rs @@ -44,7 +44,7 @@ pub(crate) enum UiEditorAssetImportRequest { #[cfg(test)] mod ui_editor_asset_import_request_tests { - use super::UiEditorAssetImportRequest; + use super::*; #[test] fn local_request_accepts_tauri_camel_case_fields() { @@ -63,6 +63,42 @@ mod ui_editor_asset_import_request_tests { assert!(matches!(request, UiEditorAssetImportRequest::Local { .. })); } + + #[tokio::test] + async fn asset_import_async_command_completes_local_file_import() { + let project = tempfile::tempdir().expect("create project directory"); + let root = project.path(); + init_local_game_project_at(root, "ui-editor-import", "UI 编辑器导入测试") + .expect("initialize project"); + let source = tempfile::NamedTempFile::new().expect("create image source"); + fs::write( + source.path(), + [ + 0x89, b'P', b'N', b'G', b'\r', b'\n', 0x1a, b'\n', 0, 0, 0, 0, + ], + ) + .expect("write image source"); + + let result = import_ui_editor_assets(UiEditorAssetImportRequest::Local { + project_path: root.to_string_lossy().into_owned(), + local_source_paths: vec![source.path().to_string_lossy().into_owned()], + local_policy: AssetImportPolicy { + destination: "assets/uploads".to_string(), + accepted_media_types: vec!["image/png".to_string()], + accepted_extensions: vec!["png".to_string()], + }, + local_requirements: AssetImportRequirements { + max_items: 1, + max_file_size_bytes: Some(1024), + max_total_size_bytes: Some(1024), + }, + }) + .await + .expect("import local image through blocking worker"); + + assert_eq!(result.assets.len(), 1); + assert!(root.join(&result.assets[0].local_path).is_file()); + } } fn validate_asset_import_policy(policy: &AssetImportPolicy) -> Result { @@ -175,6 +211,14 @@ fn validate_remote_asset_import_requirements( #[tauri::command] pub(crate) async fn import_ui_editor_assets( request: UiEditorAssetImportRequest, +) -> Result { + tokio::task::spawn_blocking(move || import_ui_editor_assets_blocking(request)) + .await + .map_err(|error| format!("UI 编辑器素材导入任务意外终止:{error}"))? +} + +fn import_ui_editor_assets_blocking( + request: UiEditorAssetImportRequest, ) -> Result { match request { UiEditorAssetImportRequest::Local { @@ -211,7 +255,6 @@ pub(crate) async fn import_ui_editor_assets( remote_assets, remote_requirements.max_file_size_bytes.unwrap_or(u64::MAX), ) - .await } } } @@ -2161,7 +2204,7 @@ mod ui_editor_font_tests { } } -pub(crate) async fn import_ui_editor_remote_assets( +pub(crate) fn import_ui_editor_remote_assets( project_path: String, assets: Vec, max_file_size: u64,