新建 UI 设计资源复用无冲突编号规则
- 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 的回归用例。
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user