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 { 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, 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 { 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, 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) }