#include "project_service.h" #include #include #include #include #include #include namespace { // 生成唯一工程 ID:project-时间戳-随机数 std::string generateProjectId() { const auto timestamp = static_cast( std::chrono::high_resolution_clock::now().time_since_epoch().count()); std::random_device random_device; const auto random_value = static_cast(random_device()); std::ostringstream stream; stream << "project-" << std::hex << timestamp << '-' << random_value; return stream.str(); } } // namespace ProjectService::ProjectService(ProjectStorage &storage) : ProjectService(storage, defaultProjectLimitSettings()) { } ProjectService::ProjectService( ProjectStorage &storage, const ProjectLimitSettings &project_limits) : storage_(storage), project_limits_(project_limits), project_(makeNewProject("未命名工程")) { } const Project &ProjectService::project() const { return project_; } Project &ProjectService::editProject() { modified_ = true; return project_; } const std::string &ProjectService::currentFilePath() const { return current_file_path_; } bool ProjectService::hasCurrentFile() const { return !current_file_path_.empty(); } // 查询是否存在未保存修改 bool ProjectService::isModified() const { return modified_; } const ProjectLimitSettings &ProjectService::projectLimits() const { return project_limits_; } void ProjectService::restoreModifiedState(bool modified) { modified_ = modified; } ProjectOperationResult ProjectService::createNewProject(const std::string &name) { if (isBlank(name)) { return {false, ProjectServiceError::InvalidProjectName, ProjectStorageError::None, "工程名称不能为空"}; } // 新工程创建成功后清除原文件关联,并标记为待保存 project_ = makeNewProject(name); current_file_path_.clear(); modified_ = true; return {true, ProjectServiceError::None, ProjectStorageError::None, {}}; } ProjectOperationResult ProjectService::save() { if (!hasCurrentFile()) { return {false, ProjectServiceError::FilePathRequired, ProjectStorageError::None, "必须指定工程文件路径"}; } // 复用另存为流程,确保两种保存方式拥有相同的校验和错误处理 return saveAs(current_file_path_); } ProjectOperationResult ProjectService::saveAs(const std::string &file_path) { if (isBlank(file_path)) { return {false, ProjectServiceError::FilePathRequired, ProjectStorageError::None, "必须指定工程文件路径"}; } std::string validation_error; if (!project_.validate(project_limits_, &validation_error)) { return {false, ProjectServiceError::InvalidProject, ProjectStorageError::InvalidProject, validation_error}; } // 先完成领域校验,避免将非法工程交给存储层 const ProjectSaveResult result = storage_.save(project_, file_path); if (!result.succeeded) { return storageFailure(result.error, result.message); } // 只有存储成功后才更新文件关联和未保存状态 current_file_path_ = file_path; modified_ = false; return {true, ProjectServiceError::None, ProjectStorageError::None, {}}; } ProjectOperationResult ProjectService::exportAs(const std::string &file_path) const { if (isBlank(file_path)) { return {false, ProjectServiceError::FilePathRequired, ProjectStorageError::None, "必须指定导出文件路径"}; } std::string validation_error; if (!project_.validate(project_limits_, &validation_error)) { return {false, ProjectServiceError::InvalidProject, ProjectStorageError::InvalidProject, validation_error}; } const ProjectSaveResult result = storage_.save(project_, file_path); if (!result.succeeded) { return storageFailure(result.error, result.message); } return {true, ProjectServiceError::None, ProjectStorageError::None, {}}; } ProjectOperationResult ProjectService::load(const std::string &file_path) { if (isBlank(file_path)) { return {false, ProjectServiceError::FilePathRequired, ProjectStorageError::None, "必须指定工程文件路径"}; } // 存储层先在临时结果中解析,避免半个工程替换当前工程 ProjectLoadResult result = storage_.load(file_path); if (!result.succeeded) { return storageFailure(result.error, result.message); } std::string validation_error; if (!result.project.validate(project_limits_, &validation_error)) { return {false, ProjectServiceError::InvalidProject, ProjectStorageError::InvalidProject, validation_error}; } // 文件读取和领域校验均成功后,才替换当前工程状态 project_ = std::move(result.project); current_file_path_ = file_path; modified_ = false; return {true, ProjectServiceError::None, ProjectStorageError::None, {}}; } // 创建一个全新空白工程实例 Project ProjectService::makeNewProject(const std::string &name) { Project project; project.metadata.id = generateProjectId(); project.metadata.name = name; // 新工程固定使用当前存储格式版本 project.metadata.formatVersion = "2.0"; return project; } // 判断字符串是不是空白:空字符串 / 全是空格、制表符都算空白 bool ProjectService::isBlank(const std::string &value) { return value.empty() || std::all_of( value.cbegin(), value.cend(), [](unsigned char character) { return std::isspace(character) != 0; }); } // 包装存储层失败结果 ProjectOperationResult ProjectService::storageFailure( ProjectStorageError error, const std::string &message) { return {false, ProjectServiceError::StorageFailure, error, message}; }