From 4d76e36d065d95efe89262cf78a6ae8a0c1ff93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 5 Aug 2026 13:25:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=A7=BB=E8=A7=92=E8=89=B2=E5=8A=A8?= =?UTF-8?q?=E4=BD=9C=E7=94=BB=E5=B8=83=E5=AE=8C=E6=88=90=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在来源解析和预扣泥点前拒绝缺少项目的画布完成请求 补充校验顺序回归测试 --- .../src/character_animation_assets.rs | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/server-rs/crates/api-server/src/character_animation_assets.rs b/server-rs/crates/api-server/src/character_animation_assets.rs index 560bae973..d293188da 100644 --- a/server-rs/crates/api-server/src/character_animation_assets.rs +++ b/server-rs/crates/api-server/src/character_animation_assets.rs @@ -676,6 +676,18 @@ pub(crate) async fn generate_editor_character_animation_for_owner( let asset_folder_id = payload.asset_folder_id.clone(); let asset_label = resolve_editor_character_animation_asset_label(payload.asset_label.as_deref()); + if canvas_completion.is_some() + && project_id + .as_deref() + .map(str::trim) + .filter(|value| !value.is_empty()) + .is_none() + { + return Err(character_animation_error_response( + &request_context, + editor_character_animation_bad_request("角色动作画布完成需要有效的 projectId。"), + )); + } if matches_inline_media_source(payload.source_image_src.as_str()) { return Err(character_animation_error_response( &request_context, @@ -914,17 +926,6 @@ pub(crate) async fn generate_editor_character_animation_for_owner( let (generated, frames, normalized, final_resource, final_asset) = result.map_err(|error| character_animation_error_response(&request_context, error))?; let completed_project = if let Some(completion) = canvas_completion.as_ref() { - if project_id - .as_deref() - .map(str::trim) - .filter(|value| !value.is_empty()) - .is_none() - { - return Err(character_animation_error_response( - &request_context, - editor_character_animation_bad_request("角色动作画布完成需要有效的 projectId。"), - )); - } let final_resource = final_resource.as_ref().ok_or_else(|| { character_animation_error_response( &request_context, @@ -6789,6 +6790,20 @@ mod tests { ); } + #[test] + fn editor_character_animation_rejects_projectless_canvas_completion_before_billing() { + let source = include_str!("character_animation_assets.rs"); + assert_function_contains_in_order( + source, + "pub(crate) async fn generate_editor_character_animation_for_owner", + "pub async fn generate_editor_video", + &[ + "角色动作画布完成需要有效的 projectId。", + "execute_billable_asset_operation_with_cost", + ], + ); + } + #[test] fn editor_video_intermediate_outputs_are_registered_before_derivatives() { let source = include_str!("character_animation_assets.rs");