143 lines
4.2 KiB
Rust
143 lines
4.2 KiB
Rust
use crate::data::models::project::{Project, CreateProjectRequest, UpdateProjectRequest};
|
|
use crate::data::repositories::project_repository::ProjectRepository;
|
|
use crate::infrastructure::file_system::FileSystemService;
|
|
use anyhow::{Result, anyhow};
|
|
|
|
/// 项目业务服务
|
|
/// 遵循 Tauri 开发规范的业务逻辑层设计
|
|
pub struct ProjectService;
|
|
|
|
impl ProjectService {
|
|
/// 创建新项目
|
|
/// 遵循安全第一原则,验证输入数据和文件系统权限
|
|
pub fn create_project(
|
|
repository: &ProjectRepository,
|
|
request: CreateProjectRequest,
|
|
) -> Result<Project> {
|
|
// 验证请求数据
|
|
request.validate().map_err(|e| anyhow!(e))?;
|
|
|
|
// 验证路径
|
|
if !FileSystemService::is_valid_project_directory(&request.path)? {
|
|
return Err(anyhow!("无效的项目路径或没有访问权限"));
|
|
}
|
|
|
|
// 获取绝对路径
|
|
let absolute_path = FileSystemService::get_absolute_path(&request.path)?;
|
|
|
|
// 检查路径是否已被使用
|
|
if repository.path_exists(&absolute_path, None)? {
|
|
return Err(anyhow!("该路径已被其他项目使用"));
|
|
}
|
|
|
|
// 创建项目实例
|
|
let project = Project::new(
|
|
request.name,
|
|
absolute_path.clone(),
|
|
request.description,
|
|
);
|
|
|
|
// 验证项目数据
|
|
project.validate().map_err(|e| anyhow!(e))?;
|
|
|
|
// 创建项目目录结构
|
|
FileSystemService::create_project_structure(&absolute_path)?;
|
|
|
|
// 保存到数据库
|
|
repository.create(&project)?;
|
|
|
|
Ok(project)
|
|
}
|
|
|
|
/// 获取所有活跃项目
|
|
pub fn get_all_projects(repository: &ProjectRepository) -> Result<Vec<Project>> {
|
|
let projects = repository.find_all_active()?;
|
|
|
|
// 验证项目路径是否仍然有效
|
|
let mut valid_projects = Vec::new();
|
|
for project in projects {
|
|
if FileSystemService::validate_path(&project.path).unwrap_or(false) {
|
|
valid_projects.push(project);
|
|
}
|
|
}
|
|
|
|
Ok(valid_projects)
|
|
}
|
|
|
|
/// 根据ID获取项目
|
|
pub fn get_project_by_id(
|
|
repository: &ProjectRepository,
|
|
id: &str,
|
|
) -> Result<Option<Project>> {
|
|
if id.trim().is_empty() {
|
|
return Err(anyhow!("项目ID不能为空"));
|
|
}
|
|
|
|
let project = repository.find_by_id(id)?;
|
|
|
|
// 验证项目路径是否仍然有效
|
|
if let Some(ref proj) = project {
|
|
if !FileSystemService::validate_path(&proj.path).unwrap_or(false) {
|
|
return Err(anyhow!("项目路径不存在或无法访问"));
|
|
}
|
|
}
|
|
|
|
Ok(project)
|
|
}
|
|
|
|
/// 更新项目
|
|
pub fn update_project(
|
|
repository: &ProjectRepository,
|
|
id: &str,
|
|
request: UpdateProjectRequest,
|
|
) -> Result<Project> {
|
|
// 验证请求数据
|
|
request.validate().map_err(|e| anyhow!(e))?;
|
|
|
|
// 获取现有项目
|
|
let mut project = repository.find_by_id(id)?
|
|
.ok_or_else(|| anyhow!("项目不存在"))?;
|
|
|
|
// 更新项目信息
|
|
project.update(request.name, request.description);
|
|
|
|
// 验证更新后的项目数据
|
|
project.validate().map_err(|e| anyhow!(e))?;
|
|
|
|
// 保存更新
|
|
repository.update(&project)?;
|
|
|
|
Ok(project)
|
|
}
|
|
|
|
/// 删除项目
|
|
pub fn delete_project(repository: &ProjectRepository, id: &str) -> Result<()> {
|
|
if id.trim().is_empty() {
|
|
return Err(anyhow!("项目ID不能为空"));
|
|
}
|
|
|
|
// 检查项目是否存在
|
|
let project = repository.find_by_id(id)?
|
|
.ok_or_else(|| anyhow!("项目不存在"))?;
|
|
|
|
// 执行软删除
|
|
repository.delete(&project.id)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 验证项目路径
|
|
pub fn validate_project_path(path: &str) -> Result<bool> {
|
|
if path.trim().is_empty() {
|
|
return Ok(false);
|
|
}
|
|
|
|
FileSystemService::is_valid_project_directory(path)
|
|
}
|
|
|
|
/// 获取目录名称作为默认项目名
|
|
pub fn get_default_project_name(path: &str) -> Result<String> {
|
|
FileSystemService::get_directory_name(path)
|
|
}
|
|
}
|