diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs index ceae0d7ea..bc578daf8 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs @@ -348,6 +348,17 @@ fn validate_confidence(nodes: &[RecognitionNode]) -> Result<(), String> { }) { return Err("识别阶段不能返回已绑定的 SpriteAssetId".to_string()); } + if node.components.iter().any(|component| { + matches!( + component, + Component::Text(crate::ui_editor::component::text::TextComponent { + font: crate::ui_editor::component::text::FontSource::Bound(_), + .. + }) + ) + }) { + return Err("识别阶段不能返回已绑定的字体素材".to_string()); + } if let Confidence::UnSure(reason) = &node.confidence { if reason.trim().is_empty() { return Err("UnSure 必须包含审阅原因".to_string()); @@ -464,19 +475,23 @@ mod tests { let oversized = (0..=MAX_RECOGNITION_TREE_NODES) .map(|_| serde_json::json!({"children": []})) .collect::>(); - assert!(validate_recognition_response_shape(&serde_json::json!({ - "trees": [{"children": oversized}] - })) - .is_err()); + assert!( + validate_recognition_response_shape(&serde_json::json!({ + "trees": [{"children": oversized}] + })) + .is_err() + ); let mut nested = serde_json::json!({"children": []}); for _ in 0..MAX_RECOGNITION_TREE_DEPTH { nested = serde_json::json!({"children": [nested]}); } - assert!(validate_recognition_response_shape(&serde_json::json!({ - "trees": [{"children": [nested]}] - })) - .is_err()); + assert!( + validate_recognition_response_shape(&serde_json::json!({ + "trees": [{"children": [nested]}] + })) + .is_err() + ); } #[test] @@ -521,6 +536,30 @@ mod tests { assert!(validate_confidence(&[node]).is_err()); } + #[test] + fn recognition_rejects_bound_font_references() { + let mut text = crate::ui_editor::component::text::TextComponent::default(); + text.font = crate::ui_editor::component::text::FontSource::Bound( + crate::ui_editor::utils::FontAssetId::new("font").expect("valid font id"), + ); + let node = RecognitionNode { + global_pos_x_px: 0, + global_pos_y_px: 0, + width_px: 1, + height_px: 1, + local_anchor: Anchor::Preset(PresetAnchor { + horizontal: HorizontalAnchor::Left, + vertical: VerticalAnchor::Top, + }), + name: "文本".to_string(), + description: String::new(), + children: Vec::new(), + confidence: Confidence::Confident, + components: vec![Component::Text(text)], + }; + assert!(validate_confidence(&[node]).is_err()); + } + #[test] fn conversion_stays_in_the_tree_image_coordinate_system() { let image_id = UIDesignImageId::new("slave").expect("valid image id"); @@ -572,11 +611,13 @@ mod tests { children: Vec::new(), }; - assert!(validate_tree_image_ids( - &[tree(page.clone()), tree(slave.clone())], - &[page.clone(), slave.clone()], - ) - .is_ok()); + assert!( + validate_tree_image_ids( + &[tree(page.clone()), tree(slave.clone())], + &[page.clone(), slave.clone()], + ) + .is_ok() + ); assert!( validate_tree_image_ids(&[tree(page.clone())], &[page.clone(), slave.clone()]).is_err() );