mixvideo-v2/apps/desktop/src-tauri/src/presentation/commands/material_usage_commands.rs

268 lines
8.9 KiB
Rust

// use std::sync::Arc; // 未使用的导入
use tauri::State;
use crate::app_state::AppState;
use crate::data::models::material_usage::{
CreateMaterialUsageRecordRequest, MaterialUsageRecord, MaterialUsageStats, MaterialUsageType,
ProjectMaterialUsageOverview,
};
use crate::data::repositories::material_usage_repository::MaterialUsageRepository;
/// 创建素材使用记录
#[tauri::command]
pub async fn create_material_usage_record(
state: State<'_, AppState>,
request: CreateMaterialUsageRecordRequest,
) -> Result<MaterialUsageRecord, String> {
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
// 验证请求
request
.validate()
.map_err(|e| format!("请求验证失败: {}", e))?;
repo.create_usage_record(request)
.map_err(|e| format!("创建素材使用记录失败: {}", e))
}
/// 批量创建素材使用记录
#[tauri::command]
pub async fn create_material_usage_records_batch(
state: State<'_, AppState>,
requests: Vec<CreateMaterialUsageRecordRequest>,
) -> Result<Vec<MaterialUsageRecord>, String> {
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
// 验证所有请求
for request in &requests {
request
.validate()
.map_err(|e| format!("请求验证失败: {}", e))?;
}
repo.create_usage_records_batch(requests)
.map_err(|e| format!("批量创建素材使用记录失败: {}", e))
}
/// 获取项目的素材使用记录
#[tauri::command]
pub async fn get_project_material_usage_records(
state: State<'_, AppState>,
project_id: String,
) -> Result<Vec<MaterialUsageRecord>, String> {
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
repo.get_usage_records_by_project(&project_id)
.map_err(|e| format!("获取项目素材使用记录失败: {}", e))
}
/// 获取模板匹配结果的素材使用记录
#[tauri::command]
pub async fn get_matching_result_usage_records(
state: State<'_, AppState>,
matching_result_id: String,
) -> Result<Vec<MaterialUsageRecord>, String> {
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
repo.get_usage_records_by_matching_result(&matching_result_id)
.map_err(|e| format!("获取匹配结果使用记录失败: {}", e))
}
/// 获取项目的素材使用统计信息
#[tauri::command]
pub async fn get_project_material_usage_stats(
state: State<'_, AppState>,
project_id: String,
) -> Result<Vec<MaterialUsageStats>, String> {
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
repo.get_material_usage_stats(&project_id)
.map_err(|e| format!("获取素材使用统计失败: {}", e))
}
/// 获取项目的素材使用概览
#[tauri::command]
pub async fn get_project_material_usage_overview(
state: State<'_, AppState>,
project_id: String,
) -> Result<ProjectMaterialUsageOverview, String> {
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
repo.get_project_usage_overview(&project_id)
.map_err(|e| format!("获取项目素材使用概览失败: {}", e))
}
/// 从匹配结果创建素材使用记录
/// 这是一个便捷方法,用于在应用匹配结果时自动创建使用记录
#[tauri::command]
pub async fn create_usage_records_from_matching_result(
state: State<'_, AppState>,
project_id: String,
template_id: String,
binding_id: String,
template_matching_result_id: String,
matches: Vec<serde_json::Value>, // 匹配结果的JSON格式
) -> Result<Vec<MaterialUsageRecord>, String> {
println!("🔍 开始创建素材使用记录");
println!("📋 参数信息:");
println!(" - project_id: {}", project_id);
println!(" - template_id: {}", template_id);
println!(" - binding_id: {}", binding_id);
println!(" - template_matching_result_id: {}", template_matching_result_id);
println!(" - matches 数量: {}", matches.len());
let database = state.get_database();
let repo = MaterialUsageRepository::new(database);
let mut requests = Vec::new();
// 解析匹配结果并创建使用记录请求
for (index, match_value) in matches.iter().enumerate() {
println!("🔄 处理第 {} 个匹配结果", index + 1);
// 直接从SegmentMatch结构中提取字段
let material_segment_id = match_value
.get("material_segment_id")
.and_then(|v| v.as_str())
.ok_or("缺少material_segment_id字段")?;
// 从material_segment对象中获取material_id
let material_id = match_value
.get("material_segment")
.and_then(|segment| segment.get("material_id"))
.and_then(|v| v.as_str())
.ok_or("缺少material_id字段")?;
let track_segment_id = match_value
.get("track_segment_id")
.and_then(|v| v.as_str())
.ok_or("缺少track_segment_id字段")?;
let match_score = match_value
.get("match_score")
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
let match_reason = match_value
.get("match_reason")
.and_then(|v| v.as_str())
.unwrap_or("模板匹配");
// 创建使用上下文
let usage_context = serde_json::json!({
"match_score": match_score,
"match_reason": match_reason,
"usage_timestamp": chrono::Utc::now().to_rfc3339()
})
.to_string();
// 创建使用记录请求
let request = CreateMaterialUsageRecordRequest {
material_segment_id: material_segment_id.to_string(),
material_id: material_id.to_string(),
project_id: project_id.clone(),
template_matching_result_id: template_matching_result_id.clone(),
template_id: template_id.clone(),
binding_id: binding_id.clone(),
track_segment_id: track_segment_id.to_string(),
usage_type: MaterialUsageType::TemplateMatching,
usage_context: Some(usage_context),
};
requests.push(request);
}
if requests.is_empty() {
return Ok(Vec::new());
}
// 批量创建使用记录
repo.create_usage_records_batch(requests)
.map_err(|e| format!("从匹配结果创建使用记录失败: {}", e))
}
/// 重置素材片段的使用状态
#[tauri::command]
pub async fn reset_material_segment_usage(
state: State<'_, AppState>,
segment_ids: Vec<String>,
) -> Result<String, String> {
let database = state.get_database();
let conn = database.get_connection();
let conn = conn.lock().unwrap();
// 开始事务
let tx = conn
.unchecked_transaction()
.map_err(|e| format!("开始事务失败: {}", e))?;
// 删除使用记录
for segment_id in &segment_ids {
tx.execute(
"DELETE FROM material_usage_records WHERE material_segment_id = ?1",
[segment_id],
)
.map_err(|e| format!("删除使用记录失败: {}", e))?;
// 重置素材片段状态
tx.execute(
"UPDATE material_segments SET usage_count = 0, is_used = 0, last_used_at = NULL WHERE id = ?1",
[segment_id],
).map_err(|e| format!("重置片段状态失败: {}", e))?;
}
// 提交事务
tx.commit().map_err(|e| format!("提交事务失败: {}", e))?;
Ok(format!(
"成功重置 {} 个素材片段的使用状态",
segment_ids.len()
))
}
/// 重置项目所有素材的使用状态
#[tauri::command]
pub async fn reset_project_material_usage(
state: State<'_, AppState>,
project_id: String,
) -> Result<String, String> {
let database = state.get_database();
let conn = database.get_connection();
let conn = conn.lock().unwrap();
// 开始事务
let tx = conn
.unchecked_transaction()
.map_err(|e| format!("开始事务失败: {}", e))?;
// 删除项目的所有使用记录
let deleted_records = tx
.execute(
"DELETE FROM material_usage_records WHERE project_id = ?1",
[&project_id],
)
.map_err(|e| format!("删除使用记录失败: {}", e))?;
// 重置项目所有素材片段状态
let updated_segments = tx
.execute(
"UPDATE material_segments SET usage_count = 0, is_used = 0, last_used_at = NULL
WHERE material_id IN (SELECT id FROM materials WHERE project_id = ?1)",
[&project_id],
)
.map_err(|e| format!("重置片段状态失败: {}", e))?;
// 提交事务
tx.commit().map_err(|e| format!("提交事务失败: {}", e))?;
Ok(format!(
"成功重置项目素材使用状态:删除 {} 条使用记录,重置 {} 个素材片段",
deleted_records, updated_segments
))
}