From d23c80837689a9b7cedfebeea617578f293c88a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 16 Sep 2026 23:24:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20UI=20=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=A4=8D=E7=94=A8=E6=97=A0=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E7=BC=96=E5=8F=B7=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ui_editor/resource_bridge.rs:`next_ui_design_path` 提升为 `pub(crate)` 并补注释,作为两个写入侧唯一的「UI 设计 N」命名规则。 - commands.rs:`create_ui_design_resource` 不再按已登记文档数直接取名,改为复用该规则,resourceId 与文件名同一编号。 - tests/project.rs:新增已存在 `ui/UI 设计 1.json` 时仍能创建并落到编号 2 的回归用例。 --- .../src-tauri/src/commands.rs | 18 ++++------- .../src-tauri/src/tests/project.rs | 31 +++++++++++++++++++ .../src/ui_editor/resource_bridge.rs | 4 ++- 3 files changed, 40 insertions(+), 13 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 11ca2fcb7..1fd1b3489 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/commands.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/commands.rs @@ -2197,17 +2197,8 @@ pub(crate) fn create_ui_design_resource( if manifest.project_id != expected_project_id.trim() { return Err("project-identity-conflict".to_string()); } - let next_index = manifest - .assets - .iter() - .filter(|asset| { - asset.kind == crate::ui_editor::persistence::UI_DESIGN_DOC_ASSET_KIND - && asset.media_type == crate::ui_editor::persistence::UI_DESIGN_DOC_MEDIA_TYPE - }) - .count() - + 1; - let resource_name = format!("UI 设计 {next_index}"); - let relative_path = format!("ui/{resource_name}.json"); + let (resource_name, relative_path) = + crate::ui_editor::resource_bridge::next_ui_design_path(root, &manifest)?; let absolute_path = resolve_local_project_path(root, &relative_path)?; if let Some(parent) = absolute_path.parent() { ensure_game_creator_private_directory_tree(parent, "UI 资源目录")?; @@ -2243,7 +2234,10 @@ pub(crate) fn create_ui_design_resource( GameCreationAppAssetSource { kind: GameCreationAppAssetSourceKind::Generated, canvas_project_id: None, - resource_id: Some(format!("ui:{next_index}")), + resource_id: Some(format!( + "ui:{}", + resource_name.trim_start_matches("UI 设计 ") + )), asset_object_id: None, task_id: None, prompt: None, diff --git a/apps/ai-game-creator-shell/src-tauri/src/tests/project.rs b/apps/ai-game-creator-shell/src-tauri/src/tests/project.rs index f96b864ea..c78e8f242 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/tests/project.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/tests/project.rs @@ -2259,6 +2259,37 @@ fn register_local_asset_derives_category_from_real_write_side_kinds() { fs::remove_dir_all(root).ok(); } +/// 已存在的 `ui/UI 设计 N.json` 不能让新建 UI 设计资源直接失败。 +/// +/// 编号按已登记的 UI 文档数推导,旧项目里 kind 已被收口为 `unknown` 的文档不再计入, +/// 只按计数取名就会撞上仍然存在的同名文件并报「路径已存在」。两个写入侧必须共用 +/// `ui_editor::resource_bridge` 的「第一个空闲编号」规则,既不改名既有文件也不覆盖。 +#[test] +fn create_ui_design_resource_skips_a_taken_ui_design_path() { + let root = unique_project_path(); + init_local_game_project_at(&root, "project-1", "UI 设计编号避让").expect("project init"); + write_local_project_file_at(&root, "ui/UI 设计 1.json", "{}").expect("ui asset file"); + + let result = crate::commands::create_ui_design_resource( + root.to_string_lossy().to_string(), + "project-1".to_string(), + ) + .expect("create UI design resource"); + + assert_eq!(result.asset.local_path, "ui/UI 设计 2.json"); + let registered = result + .manifest + .assets + .iter() + .find(|asset| asset.id == result.asset.id) + .expect("registered UI design asset"); + assert_eq!(registered.source.resource_id.as_deref(), Some("ui:2")); + assert_eq!(registered.kind, GameCreationAppAssetKind::UiDesignDoc); + assert!(root.join("ui/UI 设计 1.json").is_file()); + + fs::remove_dir_all(root).ok(); +} + #[test] fn register_local_asset_rejects_missing_or_unsafe_path() { let root = unique_project_path(); diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/resource_bridge.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/resource_bridge.rs index bde9b6b34..dc76ce37c 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/resource_bridge.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/resource_bridge.rs @@ -190,7 +190,9 @@ pub(crate) fn ensure_ui_design_resource_for_prototype( }) } -fn next_ui_design_path( +/// UI 设计文档的确定性命名:从已登记文档数 + 1 起找第一个既未被占用、 +/// 也未登记进 manifest 的 `ui/UI 设计 N.json`,不覆盖任何既有文件。 +pub(crate) fn next_ui_design_path( root: &Path, manifest: &GameCreationAppManifest, ) -> Result<(String, String), String> {