244 lines
8.3 KiB
Rust
244 lines
8.3 KiB
Rust
use anyhow::{anyhow, Result};
|
|
|
|
use crate::data::repositories::model_dynamic_repository::ModelDynamicRepository;
|
|
use crate::data::models::model_dynamic::{
|
|
ModelDynamic, GeneratedVideo, CreateModelDynamicRequest, UpdateModelDynamicRequest,
|
|
ModelDynamicStats, DynamicStatus, VideoGenerationStatus
|
|
};
|
|
use crate::business::errors::BusinessError;
|
|
|
|
/// 模特动态服务
|
|
/// 遵循 Tauri 开发规范的业务逻辑层设计原则
|
|
pub struct ModelDynamicService;
|
|
|
|
impl ModelDynamicService {
|
|
/// 创建模特动态
|
|
pub fn create_dynamic(
|
|
repository: &ModelDynamicRepository,
|
|
request: CreateModelDynamicRequest,
|
|
) -> Result<ModelDynamic> {
|
|
// 验证请求数据
|
|
if request.model_id.is_empty() {
|
|
return Err(BusinessError::InvalidInput("模特ID不能为空".to_string()).into());
|
|
}
|
|
|
|
if request.description.trim().is_empty() {
|
|
return Err(BusinessError::InvalidInput("动态描述不能为空".to_string()).into());
|
|
}
|
|
|
|
if request.prompt.trim().is_empty() {
|
|
return Err(BusinessError::InvalidInput("提示词不能为空".to_string()).into());
|
|
}
|
|
|
|
if request.source_image_path.trim().is_empty() {
|
|
return Err(BusinessError::InvalidInput("源图片路径不能为空".to_string()).into());
|
|
}
|
|
|
|
if request.video_count < 1 || request.video_count > 9 {
|
|
return Err(BusinessError::InvalidInput("视频个数必须在1-9之间".to_string()).into());
|
|
}
|
|
|
|
// 创建动态
|
|
let dynamic = repository.create(request)
|
|
.map_err(|e| anyhow!("创建模特动态失败: {}", e))?;
|
|
|
|
Ok(dynamic)
|
|
}
|
|
|
|
/// 获取模特动态详情
|
|
pub fn get_dynamic_by_id(
|
|
repository: &ModelDynamicRepository,
|
|
id: &str,
|
|
) -> Result<Option<ModelDynamic>> {
|
|
repository.get_by_id(id)
|
|
.map_err(|e| anyhow!("获取模特动态详情失败: {}", e))
|
|
}
|
|
|
|
/// 获取模特的所有动态
|
|
pub fn get_dynamics_by_model_id(
|
|
repository: &ModelDynamicRepository,
|
|
model_id: &str,
|
|
) -> Result<Vec<ModelDynamic>> {
|
|
repository.get_by_model_id(model_id)
|
|
.map_err(|e| anyhow!("获取模特动态列表失败: {}", e))
|
|
}
|
|
|
|
/// 更新模特动态
|
|
pub fn update_dynamic(
|
|
repository: &ModelDynamicRepository,
|
|
id: &str,
|
|
request: UpdateModelDynamicRequest,
|
|
) -> Result<ModelDynamic> {
|
|
// 检查动态是否存在
|
|
let dynamic = repository.get_by_id(id)?
|
|
.ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", id)))?;
|
|
|
|
// 验证状态转换
|
|
if let Some(new_status) = &request.status {
|
|
Self::validate_status_transition(&dynamic.status, new_status)?;
|
|
}
|
|
|
|
// 更新动态
|
|
repository.update(id, request)
|
|
.map_err(|e| anyhow!("更新模特动态失败: {}", e))
|
|
}
|
|
|
|
/// 删除模特动态
|
|
pub fn delete_dynamic(
|
|
repository: &ModelDynamicRepository,
|
|
id: &str,
|
|
) -> Result<()> {
|
|
// 检查动态是否存在
|
|
let _dynamic = repository.get_by_id(id)?
|
|
.ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", id)))?;
|
|
|
|
// 删除动态
|
|
repository.delete(id)
|
|
.map_err(|e| anyhow!("删除模特动态失败: {}", e))
|
|
}
|
|
|
|
/// 获取模特动态统计
|
|
pub fn get_stats_by_model_id(
|
|
repository: &ModelDynamicRepository,
|
|
model_id: &str,
|
|
) -> Result<ModelDynamicStats> {
|
|
repository.get_stats_by_model_id(model_id)
|
|
.map_err(|e| anyhow!("获取模特动态统计失败: {}", e))
|
|
}
|
|
|
|
/// 添加生成的视频
|
|
pub fn add_generated_video(
|
|
repository: &ModelDynamicRepository,
|
|
dynamic_id: &str,
|
|
video_path: String,
|
|
) -> Result<GeneratedVideo> {
|
|
// 检查动态是否存在
|
|
let mut dynamic = repository.get_by_id(dynamic_id)?
|
|
.ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", dynamic_id)))?;
|
|
|
|
// 创建视频对象
|
|
let video = GeneratedVideo::new(dynamic_id.to_string(), video_path);
|
|
|
|
// 添加到动态
|
|
dynamic.add_generated_video(video.clone());
|
|
|
|
// 更新动态状态
|
|
if dynamic.status == DynamicStatus::Draft {
|
|
dynamic.update_status(DynamicStatus::Publishing);
|
|
}
|
|
|
|
// 更新动态
|
|
let request = UpdateModelDynamicRequest {
|
|
title: None,
|
|
description: None,
|
|
prompt: None,
|
|
status: Some(dynamic.status.clone()),
|
|
};
|
|
|
|
repository.update(dynamic_id, request)?;
|
|
|
|
Ok(video)
|
|
}
|
|
|
|
/// 更新视频生成进度
|
|
pub fn update_video_progress(
|
|
repository: &ModelDynamicRepository,
|
|
dynamic_id: &str,
|
|
video_id: &str,
|
|
progress: u32,
|
|
) -> Result<()> {
|
|
// 检查动态是否存在
|
|
let mut dynamic = repository.get_by_id(dynamic_id)?
|
|
.ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", dynamic_id)))?;
|
|
|
|
// 查找视频
|
|
let video_index = dynamic.generated_videos.iter().position(|v| v.id == video_id)
|
|
.ok_or_else(|| BusinessError::NotFound(format!("视频不存在: {}", video_id)))?;
|
|
|
|
// 更新进度
|
|
dynamic.generated_videos[video_index].update_progress(progress);
|
|
|
|
// 检查是否所有视频都已完成
|
|
let all_completed = dynamic.generated_videos.iter()
|
|
.all(|v| v.status == VideoGenerationStatus::Completed || v.status == VideoGenerationStatus::Failed);
|
|
|
|
// 如果所有视频都已完成,更新动态状态为已发布
|
|
if all_completed && dynamic.status == DynamicStatus::Publishing {
|
|
dynamic.update_status(DynamicStatus::Published);
|
|
}
|
|
|
|
// 更新动态
|
|
let request = UpdateModelDynamicRequest {
|
|
title: None,
|
|
description: None,
|
|
prompt: None,
|
|
status: Some(dynamic.status.clone()),
|
|
};
|
|
|
|
repository.update(dynamic_id, request)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 标记视频生成失败
|
|
pub fn mark_video_as_failed(
|
|
repository: &ModelDynamicRepository,
|
|
dynamic_id: &str,
|
|
video_id: &str,
|
|
error_message: String,
|
|
) -> Result<()> {
|
|
// 检查动态是否存在
|
|
let mut dynamic = repository.get_by_id(dynamic_id)?
|
|
.ok_or_else(|| BusinessError::NotFound(format!("动态不存在: {}", dynamic_id)))?;
|
|
|
|
// 查找视频
|
|
let video_index = dynamic.generated_videos.iter().position(|v| v.id == video_id)
|
|
.ok_or_else(|| BusinessError::NotFound(format!("视频不存在: {}", video_id)))?;
|
|
|
|
// 标记为失败
|
|
dynamic.generated_videos[video_index].mark_as_failed(error_message);
|
|
|
|
// 检查是否所有视频都已完成
|
|
let all_completed = dynamic.generated_videos.iter()
|
|
.all(|v| v.status == VideoGenerationStatus::Completed || v.status == VideoGenerationStatus::Failed);
|
|
|
|
// 如果所有视频都已完成,更新动态状态为已发布
|
|
if all_completed && dynamic.status == DynamicStatus::Publishing {
|
|
dynamic.update_status(DynamicStatus::Published);
|
|
}
|
|
|
|
// 更新动态
|
|
let request = UpdateModelDynamicRequest {
|
|
title: None,
|
|
description: None,
|
|
prompt: None,
|
|
status: Some(dynamic.status.clone()),
|
|
};
|
|
|
|
repository.update(dynamic_id, request)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 验证状态转换
|
|
fn validate_status_transition(
|
|
current_status: &DynamicStatus,
|
|
new_status: &DynamicStatus,
|
|
) -> Result<()> {
|
|
match (current_status, new_status) {
|
|
// 允许的状态转换
|
|
(DynamicStatus::Draft, DynamicStatus::Publishing) => Ok(()),
|
|
(DynamicStatus::Publishing, DynamicStatus::Published) => Ok(()),
|
|
(DynamicStatus::Publishing, DynamicStatus::Failed) => Ok(()),
|
|
(DynamicStatus::Failed, DynamicStatus::Publishing) => Ok(()),
|
|
// 相同状态
|
|
(a, b) if a == b => Ok(()),
|
|
// 不允许的状态转换
|
|
_ => Err(BusinessError::InvalidState(format!(
|
|
"不允许的状态转换: {:?} -> {:?}",
|
|
current_status, new_status
|
|
)).into()),
|
|
}
|
|
}
|
|
}
|