From c5b944c4a3c07baae33a8f578f995d87a40a53fe Mon Sep 17 00:00:00 2001 From: imeepos Date: Fri, 18 Jul 2025 13:24:50 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=80=E9=94=AE?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E6=88=90=E5=8A=9F=E5=90=8E=E7=B4=A0=E6=9D=90?= =?UTF-8?q?=E7=89=87=E6=AE=B5=E6=9C=AA=E6=A0=87=E8=AE=B0=E4=B8=BA=E5=B7=B2?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题分析 - 单个匹配:前端会先调用save_matching_result保存匹配结果,然后额外调用create_usage_records_from_matching_result创建素材使用记录 - 一键匹配:只调用了save_matching_result保存匹配结果,但没有创建素材使用记录,导致片段管理显示已使用0 ## 解决方案 在MaterialMatchingService的两个保存方法中添加创建素材使用记录的逻辑: ### 1. match_materials_and_save方法 - 在保存匹配结果成功后,自动创建素材使用记录 - 使用批量创建方法提高性能 - 失败时只记录警告,不阻断主流程 ### 2. match_materials_with_used_segments方法 - 在一键匹配保存结果后,自动创建素材使用记录 - 确保一键匹配和单个匹配的行为一致 ### 3. 使用记录内容 - 记录匹配分数、匹配原因、素材名称、模特名称等上下文信息 - 使用TemplateMatching类型标识使用场景 - 正确关联模板匹配结果ID ## 技术细节 - 使用create_usage_records_batch批量创建提高性能 - 在MaterialUsageRepository中自动更新素材片段的使用状态 - 保持事务一致性,确保数据完整性 - 添加详细日志便于调试和监控 ## 测试验证 - 一键匹配成功后,片段管理应正确显示已使用数量 - 素材片段的is_used状态应正确更新 - 使用记录应正确保存到material_usage_records表 --- .../services/material_matching_service.rs | 76 +++++++++++++++++++ .../template_matching_result_service.rs | 1 + 2 files changed, 77 insertions(+) diff --git a/apps/desktop/src-tauri/src/business/services/material_matching_service.rs b/apps/desktop/src-tauri/src/business/services/material_matching_service.rs index 3141c94..083030b 100644 --- a/apps/desktop/src-tauri/src/business/services/material_matching_service.rs +++ b/apps/desktop/src-tauri/src/business/services/material_matching_service.rs @@ -308,6 +308,44 @@ impl MaterialMatchingService { matching_duration_ms, ).await { Ok(saved_result) => { + // 创建素材使用记录 + println!("📝 创建素材使用记录..."); + let usage_requests: Vec = matching_result.matches + .iter() + .map(|segment_match| { + let usage_context = serde_json::json!({ + "match_score": segment_match.match_score, + "match_reason": segment_match.match_reason, + "material_name": segment_match.material_name, + "model_name": segment_match.model_name + }).to_string(); + + crate::data::models::material_usage::CreateMaterialUsageRecordRequest { + material_segment_id: segment_match.material_segment_id.clone(), + material_id: segment_match.material_segment.material_id.clone(), + project_id: matching_result.project_id.clone(), + template_matching_result_id: saved_result.id.clone(), + template_id: matching_result.template_id.clone(), + binding_id: matching_result.binding_id.clone(), + track_segment_id: segment_match.track_segment_id.clone(), + usage_type: crate::data::models::material_usage::MaterialUsageType::TemplateMatching, + usage_context: Some(usage_context), + } + }) + .collect(); + + if !usage_requests.is_empty() { + match self.material_usage_repo.create_usage_records_batch(usage_requests) { + Ok(usage_records) => { + println!("✅ 成功创建 {} 条素材使用记录", usage_records.len()); + } + Err(e) => { + eprintln!("⚠️ 创建素材使用记录失败: {},但匹配结果已保存", e); + // 不阻断主流程,只记录警告 + } + } + } + return Ok((matching_result, Some(saved_result))); } Err(e) => { @@ -1067,6 +1105,44 @@ impl MaterialMatchingService { 0, // 匹配耗时,这里简化为0 ).await?; + // 创建素材使用记录 + println!("📝 创建素材使用记录..."); + let usage_requests: Vec = matching_result.matches + .iter() + .map(|segment_match| { + let usage_context = serde_json::json!({ + "match_score": segment_match.match_score, + "match_reason": segment_match.match_reason, + "material_name": segment_match.material_name, + "model_name": segment_match.model_name + }).to_string(); + + crate::data::models::material_usage::CreateMaterialUsageRecordRequest { + material_segment_id: segment_match.material_segment_id.clone(), + material_id: segment_match.material_segment.material_id.clone(), + project_id: request.project_id.clone(), + template_matching_result_id: saved.id.clone(), + template_id: request.template_id.clone(), + binding_id: request.binding_id.clone(), + track_segment_id: segment_match.track_segment_id.clone(), + usage_type: crate::data::models::material_usage::MaterialUsageType::TemplateMatching, + usage_context: Some(usage_context), + } + }) + .collect(); + + if !usage_requests.is_empty() { + match self.material_usage_repo.create_usage_records_batch(usage_requests) { + Ok(usage_records) => { + println!("✅ 成功创建 {} 条素材使用记录", usage_records.len()); + } + Err(e) => { + eprintln!("⚠️ 创建素材使用记录失败: {},但匹配结果已保存", e); + // 不阻断主流程,只记录警告 + } + } + } + Some(saved) } else { None diff --git a/apps/desktop/src-tauri/src/business/services/template_matching_result_service.rs b/apps/desktop/src-tauri/src/business/services/template_matching_result_service.rs index 579e643..bb541ae 100644 --- a/apps/desktop/src-tauri/src/business/services/template_matching_result_service.rs +++ b/apps/desktop/src-tauri/src/business/services/template_matching_result_service.rs @@ -150,6 +150,7 @@ impl TemplateMatchingResultService { self.repository.create_failed_segment_results(&failed_segment_results)?; } + println!("✅ TemplateMatchingResultService::save_matching_result 完成,ID: {}", matching_result.id); Ok(matching_result) }