From 38cd49d2928c1356b46efb8fdcaec2fb629e83cb Mon Sep 17 00:00:00 2001 From: zk Date: Thu, 2 Jul 2026 14:30:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8E=A5=E5=8F=A3=20?= =?UTF-8?q?=E8=B7=9F=E6=8D=AE=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E7=AE=80=E5=8E=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserProfileController.java | 8 + .../jiayunet/service/UserProfileService.java | 166 ++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/client-api/src/main/java/org/jiayunet/controller/UserProfileController.java b/client-api/src/main/java/org/jiayunet/controller/UserProfileController.java index 88d8295..ef5fc7a 100644 --- a/client-api/src/main/java/org/jiayunet/controller/UserProfileController.java +++ b/client-api/src/main/java/org/jiayunet/controller/UserProfileController.java @@ -61,6 +61,14 @@ public class UserProfileController { userProfileService.syncProfileFromResume(resumeId); } + /** + * 根据当前用户个人资料创建一份新简历(名"个人资料简历"),返回新简历ID + */ + @PostMapping("/createResume") + public Long createResumeFromProfile() { + return userProfileService.createResumeFromProfile(); + } + // ==================== 教育经历 ==================== /** diff --git a/client-api/src/main/java/org/jiayunet/service/UserProfileService.java b/client-api/src/main/java/org/jiayunet/service/UserProfileService.java index 22fbf91..a5193c2 100644 --- a/client-api/src/main/java/org/jiayunet/service/UserProfileService.java +++ b/client-api/src/main/java/org/jiayunet/service/UserProfileService.java @@ -80,6 +80,16 @@ public class UserProfileService { "全日制", 0, "非全日制", 1 ); + /** 学历枚举→文本映射(个人资料→简历反向映射) */ + private static final Map REVERSE_DEGREE_MAP = Map.of( + 1, "大专", 2, "本科", 3, "硕士", 4, "博士" + ); + + /** 学习形式枚举→文本映射(个人资料→简历反向映射) */ + private static final Map REVERSE_STUDY_TYPE_MAP = Map.of( + 0, "全日制", 1, "非全日制" + ); + // ==================== 主表 ==================== /** 查询当前用户个人资料 */ @@ -480,6 +490,162 @@ public class UserProfileService { userProfileAnalyzeService.analyzeUserProfile(userId); } + // ==================== 从个人资料生成简历 ==================== + + /** + * 根据当前用户的个人资料创建一份新简历 + *

syncProfileFromResume 的反向操作:读取个人资料主表+5子表,新建一份简历(名"个人资料简历")及对应子表,返回新简历ID

+ *

1. 校验个人资料存在 2. 读取个人资料5子表 3. 新建简历主表(复制共有字段,简历独有字段targetPosition/avatarUrl/city/summary留空) + * 4. 转换并批量插入5张简历子表(含degree/studyType反向映射) 5. 返回新简历ID

+ *

注意:这是创建新简历(非覆盖),不删除已有简历;简历侧无AI分析,故不触发分析

+ */ + @Transactional(rollbackFor = Exception.class) + public Long createResumeFromProfile() { + Long userId = UserSecurityTool.getUserId(); + + // 1. 校验个人资料存在 + UserProfile profile = userProfileMapper.selectOne( + new LambdaQueryWrapper().eq(UserProfile::getUserId, userId)); + if (profile == null) { + throw new BusinessException(BusinessExpCodeEnum.DATA_NOT_EXIST, "个人资料不存在"); + } + Long profileId = profile.getId(); + + // 2. 读取个人资料5张子表 + List profileEducationList = educationMapper.selectList(new LambdaQueryWrapper().eq(UserProfileEducation::getProfileId, profileId).orderByAsc(UserProfileEducation::getSortOrder)); + List profileWorkList = workMapper.selectList(new LambdaQueryWrapper().eq(UserProfileWork::getProfileId, profileId).orderByAsc(UserProfileWork::getSortOrder)); + List profileInternshipList = internshipMapper.selectList(new LambdaQueryWrapper().eq(UserProfileInternship::getProfileId, profileId).orderByAsc(UserProfileInternship::getSortOrder)); + List profileProjectList = projectMapper.selectList(new LambdaQueryWrapper().eq(UserProfileProject::getProfileId, profileId).orderByAsc(UserProfileProject::getSortOrder)); + List profileCompetitionList = competitionMapper.selectList(new LambdaQueryWrapper().eq(UserProfileCompetition::getProfileId, profileId).orderByAsc(UserProfileCompetition::getSortOrder)); + + Instant now = Instant.now(); + + // 3. 新建简历主表(复制共有字段,简历独有字段targetPosition/avatarUrl/city/summary留空) + UserResume resume = new UserResume(); + resume.setUserId(userId); + resume.setResumeName("个人资料简历"); + resume.setName(profile.getName()); + resume.setEmail(profile.getEmail()); + resume.setMobileNumber(profile.getMobileNumber()); + resume.setWechatNumber(profile.getWechatNumber()); + resume.setPortfolioUrl(profile.getPortfolioUrl()); + resume.setSkills(profile.getSkills()); + resume.setCertificates(profile.getCertificates()); + // 无简历时新建的这份自动设为默认,与 UserResumeService.saveResume 逻辑一致 + boolean hasResume = userResumeMapper.selectCount(new LambdaQueryWrapper().eq(UserResume::getUserId, userId)) > 0; + resume.setIsDefault(hasResume ? 0 : 1); + resume.setSortOrder(0); + resume.setCreateTime(now); + resume.setUpdateTime(now); + userResumeMapper.insert(resume); + Long resumeId = resume.getId(); + + // 4. 转换并插入简历教育经历(含degree/studyType枚举→文本反向映射) + if (!profileEducationList.isEmpty()) { + List resumeEducationList = IntStream.range(0, profileEducationList.size()).mapToObj(i -> { + UserProfileEducation src = profileEducationList.get(i); + UserResumeEducation dest = new UserResumeEducation(); + dest.setResumeId(resumeId); + dest.setUserId(userId); + dest.setSchool(src.getSchool()); + dest.setMajor(src.getMajor()); + dest.setDegree(Objects.isNull(src.getDegree()) ? null : REVERSE_DEGREE_MAP.get(src.getDegree())); + dest.setStudyType(Objects.isNull(src.getStudyType()) ? null : REVERSE_STUDY_TYPE_MAP.get(src.getStudyType())); + dest.setStartDate(src.getStartDate()); + dest.setEndDate(src.getEndDate()); + dest.setDescription(src.getDescription()); + dest.setSortOrder(i); + dest.setCreateTime(now); + dest.setUpdateTime(now); + return dest; + }).collect(Collectors.toList()); + resumeEducationMapper.batchInsert(resumeEducationList); + } + + // 5. 转换并插入简历工作经历 + if (!profileWorkList.isEmpty()) { + List resumeWorkList = IntStream.range(0, profileWorkList.size()).mapToObj(i -> { + UserProfileWork src = profileWorkList.get(i); + UserResumeWork dest = new UserResumeWork(); + dest.setResumeId(resumeId); + dest.setUserId(userId); + dest.setCompanyName(src.getCompanyName()); + dest.setPosition(src.getPosition()); + dest.setStartDate(src.getStartDate()); + dest.setEndDate(src.getEndDate()); + dest.setDescription(src.getDescription()); + dest.setSortOrder(i); + dest.setCreateTime(now); + dest.setUpdateTime(now); + return dest; + }).collect(Collectors.toList()); + resumeWorkMapper.batchInsert(resumeWorkList); + } + + // 6. 转换并插入简历实习经历 + if (!profileInternshipList.isEmpty()) { + List resumeInternshipList = IntStream.range(0, profileInternshipList.size()).mapToObj(i -> { + UserProfileInternship src = profileInternshipList.get(i); + UserResumeInternship dest = new UserResumeInternship(); + dest.setResumeId(resumeId); + dest.setUserId(userId); + dest.setCompanyName(src.getCompanyName()); + dest.setPosition(src.getPosition()); + dest.setStartDate(src.getStartDate()); + dest.setEndDate(src.getEndDate()); + dest.setDescription(src.getDescription()); + dest.setSortOrder(i); + dest.setCreateTime(now); + dest.setUpdateTime(now); + return dest; + }).collect(Collectors.toList()); + resumeInternshipMapper.batchInsert(resumeInternshipList); + } + + // 7. 转换并插入简历项目经历 + if (!profileProjectList.isEmpty()) { + List resumeProjectList = IntStream.range(0, profileProjectList.size()).mapToObj(i -> { + UserProfileProject src = profileProjectList.get(i); + UserResumeProject dest = new UserResumeProject(); + dest.setResumeId(resumeId); + dest.setUserId(userId); + dest.setCompanyName(src.getCompanyName()); + dest.setProjectName(src.getProjectName()); + dest.setRole(src.getRole()); + dest.setStartDate(src.getStartDate()); + dest.setEndDate(src.getEndDate()); + dest.setDescription(src.getDescription()); + dest.setSortOrder(i); + dest.setCreateTime(now); + dest.setUpdateTime(now); + return dest; + }).collect(Collectors.toList()); + resumeProjectMapper.batchInsert(resumeProjectList); + } + + // 8. 转换并插入简历竞赛经历 + if (!profileCompetitionList.isEmpty()) { + List resumeCompetitionList = IntStream.range(0, profileCompetitionList.size()).mapToObj(i -> { + UserProfileCompetition src = profileCompetitionList.get(i); + UserResumeCompetition dest = new UserResumeCompetition(); + dest.setResumeId(resumeId); + dest.setUserId(userId); + dest.setCompetitionName(src.getCompetitionName()); + dest.setAward(src.getAward()); + dest.setAwardDate(src.getAwardDate()); + dest.setDescription(src.getDescription()); + dest.setSortOrder(i); + dest.setCreateTime(now); + dest.setUpdateTime(now); + return dest; + }).collect(Collectors.toList()); + resumeCompetitionMapper.batchInsert(resumeCompetitionList); + } + + // 9. 返回新简历ID + return resumeId; + } + // ==================== 内部方法 ==================== /**