268 lines
8.9 KiB
Rust
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
|
|
))
|
|
}
|