diff --git a/apps/desktop/src-tauri/src/data/repositories/template_matching_result_repository.rs b/apps/desktop/src-tauri/src/data/repositories/template_matching_result_repository.rs index 1f5cc26..4c4a006 100644 --- a/apps/desktop/src-tauri/src/data/repositories/template_matching_result_repository.rs +++ b/apps/desktop/src-tauri/src/data/repositories/template_matching_result_repository.rs @@ -53,19 +53,19 @@ impl TemplateMatchingResultRepository { &final_result.binding_id, &final_result.result_name, &final_result.description, - &final_result.total_segments.to_string(), - &final_result.matched_segments.to_string(), - &final_result.failed_segments.to_string(), - &final_result.success_rate.to_string(), - &final_result.used_materials.to_string(), - &final_result.used_models.to_string(), - &final_result.matching_duration_ms.to_string(), - &final_result.quality_score.map(|s| s.to_string()), + &final_result.total_segments, + &final_result.matched_segments, + &final_result.failed_segments, + &final_result.success_rate, + &final_result.used_materials, + &final_result.used_models, + &final_result.matching_duration_ms, + &final_result.quality_score, &serde_json::to_string(&final_result.status).unwrap(), &final_result.metadata, &final_result.created_at.to_rfc3339(), &final_result.updated_at.to_rfc3339(), - &(final_result.is_active as i32).to_string(), + &(final_result.is_active as i32), ], )?; @@ -458,8 +458,7 @@ impl TemplateMatchingResultRepository { let status: MatchingResultStatus = serde_json::from_str(&status_str) .unwrap_or(MatchingResultStatus::Success); - let quality_score_str: Option = row.get("quality_score")?; - let quality_score = quality_score_str.and_then(|s| s.parse::().ok()); + let quality_score: Option = row.get("quality_score")?; let created_at_str: String = row.get("created_at")?; let updated_at_str: String = row.get("updated_at")?; @@ -470,8 +469,13 @@ impl TemplateMatchingResultRepository { .unwrap_or_else(|_| Utc::now().into()) .with_timezone(&Utc); - let is_active_str: String = row.get("is_active")?; - let is_active = is_active_str.parse::().unwrap_or(1) != 0; + // 正确处理 is_active 字段,支持多种数据类型 + let is_active = match row.get::<_, rusqlite::types::Value>("is_active")? { + rusqlite::types::Value::Integer(i) => i != 0, + rusqlite::types::Value::Text(s) => s == "1" || s.to_lowercase() == "true", + rusqlite::types::Value::Real(f) => f != 0.0, + _ => true, // 默认为 true + }; Ok(TemplateMatchingResult { id: row.get("id")?, @@ -480,13 +484,13 @@ impl TemplateMatchingResultRepository { binding_id: row.get("binding_id")?, result_name: row.get("result_name")?, description: row.get("description")?, - total_segments: row.get::<_, String>("total_segments")?.parse().unwrap_or(0), - matched_segments: row.get::<_, String>("matched_segments")?.parse().unwrap_or(0), - failed_segments: row.get::<_, String>("failed_segments")?.parse().unwrap_or(0), - success_rate: row.get::<_, String>("success_rate")?.parse().unwrap_or(0.0), - used_materials: row.get::<_, String>("used_materials")?.parse().unwrap_or(0), - used_models: row.get::<_, String>("used_models")?.parse().unwrap_or(0), - matching_duration_ms: row.get::<_, String>("matching_duration_ms")?.parse().unwrap_or(0), + total_segments: row.get("total_segments")?, + matched_segments: row.get("matched_segments")?, + failed_segments: row.get("failed_segments")?, + success_rate: row.get("success_rate")?, + used_materials: row.get("used_materials")?, + used_models: row.get("used_models")?, + matching_duration_ms: row.get("matching_duration_ms")?, quality_score, status, metadata: row.get("metadata")?, diff --git a/apps/desktop/src/pages/ProjectDetails.tsx b/apps/desktop/src/pages/ProjectDetails.tsx index f68ab5a..fe9503b 100644 --- a/apps/desktop/src/pages/ProjectDetails.tsx +++ b/apps/desktop/src/pages/ProjectDetails.tsx @@ -34,6 +34,7 @@ import { zhCN } from 'date-fns/locale'; import { MaterialSegmentStats } from '../components/MaterialSegmentStats'; import { MaterialSegmentViewMode } from '../types/materialSegmentView'; import { TemplateMatchingResultManager } from '../components/TemplateMatchingResultManager'; +import { useNotifications } from '../components/NotificationSystem'; // 格式化时间 const formatTime = (dateString: string) => { @@ -78,6 +79,7 @@ export const ProjectDetails: React.FC = () => { queueStats, getProjectQueueStatus } = useVideoClassificationStore(); + const { success: addNotification } = useNotifications(); // 模板绑定状态管理 const { @@ -362,20 +364,46 @@ export const ProjectDetails: React.FC = () => { const handleApplyMatchingResult = async (result: MaterialMatchingResult) => { try { - // 这里可以添加应用匹配结果的逻辑 - // 例如更新模板绑定的匹配状态等 - console.log('应用匹配结果:', result); + if (!currentMatchingBinding) { + throw new Error('没有找到当前匹配绑定信息'); + } + + // 生成结果名称 + const resultName = `匹配结果_${new Date().toLocaleString('zh-CN')}`; + const description = `模板 ${currentMatchingBinding.template_name} 的匹配结果,成功匹配 ${result.statistics.matched_segments} 个片段`; + + // 调用后端API保存匹配结果 + await invoke('save_matching_result', { + serviceResult: { + project_id: project?.id, + template_id: currentMatchingBinding.binding.template_id, + binding_id: currentMatchingBinding.binding.id, + matches: result.matches, + failed_segments: result.failed_segments, + statistics: result.statistics, + matching_duration_ms: 0 // MaterialMatchingResult 没有这个字段,使用默认值 + }, + resultName, + description, + matchingDurationMs: 0 // 使用默认值 + }); // 关闭对话框 setShowMatchingResultDialog(false); setMatchingResult(null); setCurrentMatchingBinding(null); - // 可以显示成功提示 - alert('匹配结果已应用'); + // 显示成功提示 + addNotification('匹配结果已保存', `已成功保存匹配结果"${resultName}",可在匹配记录页面查看。`); + + // 如果当前在匹配记录选项卡,刷新数据 + if (activeTab === 'matching-results') { + // 触发匹配记录列表刷新 + window.location.reload(); + } } catch (error) { console.error('应用匹配结果失败:', error); - alert(`应用匹配结果失败: ${error}`); + addNotification('保存匹配结果失败', `保存匹配结果时发生错误: ${error}`); } };