package com.mydreamjob.skill; import com.mydreamjob.skill.domain.SkillCategory; import com.mydreamjob.skill.dto.SkillCloudItem; import com.mydreamjob.skill.dto.SkillLearningPathItem; import com.mydreamjob.skill.dto.SkillLearningPathResponse; import com.mydreamjob.skill.dto.SkillMatchResponse; import com.mydreamjob.skill.repository.SkillCategoryRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Locale; import java.util.stream.IntStream; @Service @Transactional(readOnly = true) public class SkillLearningPathService { private final SkillMatchService skillMatchService; private final SkillCategoryRepository skillCategoryRepository; public SkillLearningPathService(SkillMatchService skillMatchService, SkillCategoryRepository skillCategoryRepository) { this.skillMatchService = skillMatchService; this.skillCategoryRepository = skillCategoryRepository; } public SkillLearningPathResponse generate(Long studentUserId, Long industryId, Long occupationId, Long categoryId) { SkillMatchResponse matchResponse = skillMatchService.match( studentUserId, industryId, occupationId, categoryId); List missingSkills = matchResponse.missingSkills(); List items = IntStream.range(0, missingSkills.size()) .mapToObj(index -> toItem(missingSkills.get(index), index + 1, occupationId)) .toList(); return new SkillLearningPathResponse(items.size(), items); } private SkillLearningPathItem toItem(SkillCloudItem skill, int priority, Long occupationId) { SuggestionTemplate template = resolveTemplate(skill, occupationId); String skillName = skill.nameZh(); return new SkillLearningPathItem( priority, skill.skillId(), skillName, skill.categoryId(), skill.categoryName(), template.render(skillName) ); } private SuggestionTemplate resolveTemplate(SkillCloudItem skill, Long occupationId) { if (skill.categoryId() == null) { return SuggestionTemplate.GENERAL; } String templateCode = skillCategoryRepository .findByIdAndOccupationId(skill.categoryId(), occupationId) .map(SkillCategory::getSuggestionTemplateCode) .orElse(null); return SuggestionTemplate.fromCode(templateCode); } private enum SuggestionTemplate { PROGRAMMING_LANGUAGE("先掌握{skill}的基础语法和常见数据结构,再完成至少一个编码练习。"), FRAMEWORK("先理解{skill}的核心概念与生命周期,再通过一个小型项目练习集成。"), TOOL("先完成{skill}的安装与基础配置,再结合现有工程完成一次实际操作。"), GENERAL("先了解{skill}的核心概念和常见应用场景,再通过一个简短实践巩固。"); private final String template; SuggestionTemplate(String template) { this.template = template; } String render(String skillName) { return template.replace("{skill}", skillName); } static SuggestionTemplate fromCode(String code) { if (code == null || code.isBlank()) { return GENERAL; } try { return valueOf(code.trim().toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException exception) { return GENERAL; } } } }