221 lines
7.4 KiB
Rust
221 lines
7.4 KiB
Rust
use tauri::State;
|
||
use crate::app_state::AppState;
|
||
use crate::data::models::outfit_image::{
|
||
OutfitImageRecord, OutfitImageGenerationRequest, OutfitImageGenerationResponse,
|
||
OutfitImageStats, ProductImage, OutfitImage
|
||
};
|
||
use crate::data::repositories::outfit_image_repository::OutfitImageRepository;
|
||
use crate::data::repositories::model_repository::ModelRepository;
|
||
use crate::data::models::model::PhotoType;
|
||
|
||
/// 模特个人看板统计信息
|
||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||
pub struct ModelDashboardStats {
|
||
pub model_id: String,
|
||
pub model_name: String,
|
||
pub total_photos: u32,
|
||
pub portrait_photos: u32,
|
||
pub work_photos: u32,
|
||
pub outfit_stats: OutfitImageStats,
|
||
pub recent_generations: u32,
|
||
pub success_rate: f32,
|
||
pub favorite_count: u32,
|
||
pub total_generation_time_ms: u64,
|
||
pub average_generation_time_ms: u64,
|
||
}
|
||
|
||
/// 获取模特个人看板统计信息
|
||
#[tauri::command]
|
||
pub async fn get_model_dashboard_stats(
|
||
state: State<'_, AppState>,
|
||
model_id: String,
|
||
) -> Result<ModelDashboardStats, String> {
|
||
println!("📊 获取模特个人看板统计信息: {}", model_id);
|
||
|
||
// 获取数据库连接
|
||
let database = state.get_database();
|
||
let outfit_repo = OutfitImageRepository::new(database.clone());
|
||
let model_repo = ModelRepository::new(database.clone());
|
||
|
||
// 获取模特基本信息
|
||
let model = model_repo.get_by_id(&model_id)
|
||
.map_err(|e| format!("获取模特信息失败: {}", e))?
|
||
.ok_or_else(|| "模特不存在".to_string())?;
|
||
|
||
// 获取穿搭图片统计
|
||
let outfit_stats = outfit_repo.get_stats_by_model_id(&model_id)
|
||
.map_err(|e| format!("获取穿搭图片统计失败: {}", e))?;
|
||
|
||
// 计算照片统计
|
||
let total_photos = model.photos.len() as u32;
|
||
let portrait_photos = model.photos.iter()
|
||
.filter(|photo| matches!(photo.photo_type, PhotoType::Portrait))
|
||
.count() as u32;
|
||
let work_photos = model.photos.iter()
|
||
.filter(|photo| matches!(photo.photo_type, PhotoType::Commercial | PhotoType::Artistic))
|
||
.count() as u32;
|
||
|
||
// 计算成功率
|
||
let success_rate = if outfit_stats.total_records > 0 {
|
||
outfit_stats.completed_records as f32 / outfit_stats.total_records as f32
|
||
} else {
|
||
0.0
|
||
};
|
||
|
||
// 获取最近30天的生成记录(简化实现,实际应该查询数据库)
|
||
let recent_generations = outfit_stats.total_records; // TODO: 实现真正的30天统计
|
||
|
||
// 计算总生成时间和平均生成时间(简化实现)
|
||
let total_generation_time_ms = outfit_stats.completed_records as u64 * 5000; // 假设平均5秒
|
||
let average_generation_time_ms = if outfit_stats.completed_records > 0 {
|
||
total_generation_time_ms / outfit_stats.completed_records as u64
|
||
} else {
|
||
0
|
||
};
|
||
|
||
let dashboard_stats = ModelDashboardStats {
|
||
model_id: model_id.clone(),
|
||
model_name: model.name.clone(),
|
||
total_photos,
|
||
portrait_photos,
|
||
work_photos,
|
||
outfit_stats: outfit_stats.clone(),
|
||
recent_generations,
|
||
success_rate,
|
||
favorite_count: outfit_stats.favorite_images,
|
||
total_generation_time_ms,
|
||
average_generation_time_ms,
|
||
};
|
||
|
||
println!("✅ 模特个人看板统计信息获取成功");
|
||
Ok(dashboard_stats)
|
||
}
|
||
|
||
/// 获取模特的穿搭图片生成记录列表
|
||
#[tauri::command]
|
||
pub async fn get_outfit_image_records(
|
||
state: State<'_, AppState>,
|
||
model_id: String,
|
||
) -> Result<Vec<OutfitImageRecord>, String> {
|
||
println!("📋 获取模特穿搭图片生成记录: {}", model_id);
|
||
|
||
let database = state.get_database();
|
||
let outfit_repo = OutfitImageRepository::new(database);
|
||
|
||
let records = outfit_repo.get_records_by_model_id(&model_id)
|
||
.map_err(|e| format!("获取穿搭图片记录失败: {}", e))?;
|
||
|
||
println!("✅ 获取到 {} 条穿搭图片记录", records.len());
|
||
Ok(records)
|
||
}
|
||
|
||
/// 创建穿搭图片生成记录
|
||
#[tauri::command]
|
||
pub async fn create_outfit_image_record(
|
||
state: State<'_, AppState>,
|
||
request: OutfitImageGenerationRequest,
|
||
) -> Result<String, String> {
|
||
println!("🎨 创建穿搭图片生成记录: {:?}", request);
|
||
|
||
let database = state.get_database();
|
||
let outfit_repo = OutfitImageRepository::new(database);
|
||
|
||
// 创建生成记录
|
||
let mut record = OutfitImageRecord::new(
|
||
request.model_id,
|
||
request.model_image_id,
|
||
request.generation_prompt,
|
||
);
|
||
|
||
println!("📝 开始处理商品图片,共 {} 个", request.product_image_paths.len());
|
||
|
||
// 创建商品图片记录(使用异步文件操作)
|
||
for (index, product_path) in request.product_image_paths.iter().enumerate() {
|
||
println!("📷 处理商品图片 {}/{}: {}", index + 1, request.product_image_paths.len(), product_path);
|
||
|
||
let file_name = std::path::Path::new(product_path)
|
||
.file_name()
|
||
.and_then(|n| n.to_str())
|
||
.unwrap_or(&format!("product_{}", index))
|
||
.to_string();
|
||
|
||
// 使用异步文件操作,添加超时
|
||
let file_size = match tokio::time::timeout(
|
||
std::time::Duration::from_secs(5),
|
||
tokio::fs::metadata(product_path)
|
||
).await {
|
||
Ok(Ok(metadata)) => {
|
||
println!("📊 获取文件大小成功: {} bytes", metadata.len());
|
||
metadata.len()
|
||
},
|
||
Ok(Err(e)) => {
|
||
println!("⚠️ 获取文件元数据失败: {}, 使用默认大小", e);
|
||
0
|
||
},
|
||
Err(_) => {
|
||
println!("⚠️ 获取文件元数据超时,使用默认大小");
|
||
0
|
||
}
|
||
};
|
||
|
||
let product_image = ProductImage::new(
|
||
record.id.clone(),
|
||
product_path.clone(),
|
||
file_name,
|
||
file_size,
|
||
);
|
||
|
||
record.product_images.push(product_image);
|
||
}
|
||
|
||
println!("💾 开始保存到数据库");
|
||
|
||
// 使用事务保存所有数据
|
||
match outfit_repo.create_record_with_products(&record) {
|
||
Ok(_) => {
|
||
println!("✅ 穿搭图片生成记录创建成功: {}", record.id);
|
||
Ok(record.id)
|
||
},
|
||
Err(e) => {
|
||
println!("❌ 创建穿搭图片记录失败: {}", e);
|
||
Err(format!("创建穿搭图片记录失败: {}", e))
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 删除穿搭图片生成记录
|
||
#[tauri::command]
|
||
pub async fn delete_outfit_image_record(
|
||
state: State<'_, AppState>,
|
||
record_id: String,
|
||
) -> Result<(), String> {
|
||
println!("🗑️ 删除穿搭图片生成记录: {}", record_id);
|
||
|
||
let database = state.get_database();
|
||
let outfit_repo = OutfitImageRepository::new(database);
|
||
|
||
outfit_repo.delete_record(&record_id)
|
||
.map_err(|e| format!("删除穿搭图片记录失败: {}", e))?;
|
||
|
||
println!("✅ 穿搭图片生成记录删除成功");
|
||
Ok(())
|
||
}
|
||
|
||
/// 获取穿搭图片生成记录详情
|
||
#[tauri::command]
|
||
pub async fn get_outfit_image_record_detail(
|
||
state: State<'_, AppState>,
|
||
record_id: String,
|
||
) -> Result<Option<OutfitImageRecord>, String> {
|
||
println!("🔍 获取穿搭图片生成记录详情: {}", record_id);
|
||
|
||
let database = state.get_database();
|
||
let outfit_repo = OutfitImageRepository::new(database);
|
||
|
||
let record = outfit_repo.get_record_by_id(&record_id)
|
||
.map_err(|e| format!("获取穿搭图片记录详情失败: {}", e))?;
|
||
|
||
println!("✅ 穿搭图片生成记录详情获取成功");
|
||
Ok(record)
|
||
}
|