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

235 lines
8.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use tauri::{command, State};
use crate::app_state::AppState;
use crate::business::services::video_generation_service::{VideoGenerationService, VideoGenerationStatistics};
use crate::data::models::video_generation::{
VideoGenerationTask, VideoGenerationQueryParams, CreateVideoGenerationRequest
};
/// 创建视频生成任务命令
/// 遵循 Tauri 开发规范的命令设计模式
#[command]
pub async fn create_video_generation_task(
state: State<'_, AppState>,
request: CreateVideoGenerationRequest,
) -> Result<VideoGenerationTask, String> {
// 克隆仓库引用以避免跨await边界的Send问题
let (video_gen_repo, model_repo) = {
let video_gen_repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let video_gen_repository = video_gen_repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
let model_repository_guard = state.get_model_repository()
.map_err(|e| format!("获取模特仓库失败: {}", e))?;
let model_repository = model_repository_guard.as_ref()
.ok_or("模特仓库未初始化")?;
// 这里我们需要克隆仓库但由于仓库包含Arc这应该是轻量级的
(video_gen_repository.clone(), model_repository.clone())
};
VideoGenerationService::create_task(&video_gen_repo, &model_repo, request)
.await
.map_err(|e| e.to_string())
}
/// 执行视频生成任务命令
#[command]
pub async fn execute_video_generation_task(
state: State<'_, AppState>,
task_id: String,
) -> Result<VideoGenerationTask, String> {
let (video_gen_repo, model_repo) = {
let video_gen_repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let video_gen_repository = video_gen_repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
let model_repository_guard = state.get_model_repository()
.map_err(|e| format!("获取模特仓库失败: {}", e))?;
let model_repository = model_repository_guard.as_ref()
.ok_or("模特仓库未初始化")?;
(video_gen_repository.clone(), model_repository.clone())
};
VideoGenerationService::execute_task(&video_gen_repo, &model_repo, &task_id)
.await
.map_err(|e| e.to_string())
}
/// 获取视频生成任务命令
#[command]
pub async fn get_video_generation_task(
state: State<'_, AppState>,
task_id: String,
) -> Result<Option<VideoGenerationTask>, String> {
let repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
VideoGenerationService::get_task(repository, &task_id)
.map_err(|e| e.to_string())
}
/// 获取视频生成任务列表命令
#[command]
pub async fn get_video_generation_tasks(
state: State<'_, AppState>,
params: VideoGenerationQueryParams,
) -> Result<Vec<VideoGenerationTask>, String> {
let repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
VideoGenerationService::get_tasks(repository, &params)
.map_err(|e| e.to_string())
}
/// 取消视频生成任务命令
#[command]
pub async fn cancel_video_generation_task(
state: State<'_, AppState>,
task_id: String,
) -> Result<VideoGenerationTask, String> {
let repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
VideoGenerationService::cancel_task(repository, &task_id)
.map_err(|e| e.to_string())
}
/// 删除视频生成任务命令
#[command]
pub async fn delete_video_generation_task(
state: State<'_, AppState>,
task_id: String,
) -> Result<(), String> {
let repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
VideoGenerationService::delete_task(repository, &task_id)
.map_err(|e| e.to_string())
}
/// 重试视频生成任务命令
#[command]
pub async fn retry_video_generation_task(
state: State<'_, AppState>,
task_id: String,
) -> Result<VideoGenerationTask, String> {
let (video_gen_repo, model_repo) = {
let video_gen_repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let video_gen_repository = video_gen_repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
let model_repository_guard = state.get_model_repository()
.map_err(|e| format!("获取模特仓库失败: {}", e))?;
let model_repository = model_repository_guard.as_ref()
.ok_or("模特仓库未初始化")?;
(video_gen_repository.clone(), model_repository.clone())
};
VideoGenerationService::retry_task(&video_gen_repo, &model_repo, &task_id)
.await
.map_err(|e| e.to_string())
}
/// 获取模特视频生成统计命令
#[command]
pub async fn get_model_video_generation_statistics(
state: State<'_, AppState>,
model_id: String,
) -> Result<VideoGenerationStatistics, String> {
let repository_guard = state.get_video_generation_repository()
.map_err(|e| format!("获取视频生成仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("视频生成仓库未初始化")?;
VideoGenerationService::get_model_statistics(repository, &model_id)
.map_err(|e| e.to_string())
}
/// 获取模特详情(包含照片)命令
#[command]
pub async fn get_model_detail_with_photos(
state: State<'_, AppState>,
model_id: String,
) -> Result<Option<crate::data::models::model::Model>, String> {
let repository_guard = state.get_model_repository()
.map_err(|e| format!("获取模特仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("模特仓库未初始化")?;
// 使用完整的get_by_id方法获取包含照片的模特信息
repository.get_by_id(&model_id)
.map_err(|e| e.to_string())
}
/// 批量上传模特照片命令(上传到云端)
#[command]
pub async fn batch_upload_model_photos(
state: State<'_, AppState>,
model_id: String,
file_paths: Vec<String>,
photo_type: crate::data::models::model::PhotoType,
description: Option<String>,
tags: Option<Vec<String>>,
) -> Result<Vec<crate::data::models::model::ModelPhoto>, String> {
// 克隆仓库引用以避免跨await边界的Send问题
let repository = {
let repository_guard = state.get_model_repository()
.map_err(|e| format!("获取模特仓库失败: {}", e))?;
let repository = repository_guard.as_ref()
.ok_or("模特仓库未初始化")?;
repository.clone()
};
let mut uploaded_photos = Vec::new();
for file_path in file_paths {
match crate::business::services::model_service::ModelService::add_model_photo_with_cloud_upload(
&repository,
&model_id,
file_path,
photo_type.clone(),
description.clone(),
tags.clone(),
).await {
Ok(photo) => uploaded_photos.push(photo),
Err(e) => {
println!("⚠️ 上传照片失败: {}", e);
// 继续上传其他照片,不中断整个过程
}
}
}
if uploaded_photos.is_empty() {
return Err("没有成功上传任何照片".to_string());
}
Ok(uploaded_photos)
}