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 { // 验证请求数据 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> { 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> { 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 { // 验证请求数据 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 { if path.trim().is_empty() { return Ok(false); } FileSystemService::is_valid_project_directory(path) } /// 获取目录名称作为默认项目名 pub fn get_default_project_name(path: &str) -> Result { FileSystemService::get_directory_name(path) } }