根据简历ID同步更新个人资料
This commit is contained in:
@@ -53,6 +53,14 @@ public class UserProfileController {
|
|||||||
userProfileService.saveProfile(po);
|
userProfileService.saveProfile(po);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据简历ID同步更新个人资料(主表+5子表全量覆盖,触发一次异步AI分析)
|
||||||
|
*/
|
||||||
|
@PostMapping("/syncFromResume")
|
||||||
|
public void syncFromResume(@RequestParam Long resumeId) {
|
||||||
|
userProfileService.syncProfileFromResume(resumeId);
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 教育经历 ====================
|
// ==================== 教育经历 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.jiayunet.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.exception.BusinessException;
|
||||||
|
import org.jiayunet.exception.BusinessExpCodeEnum;
|
||||||
import org.jiayunet.mapper.*;
|
import org.jiayunet.mapper.*;
|
||||||
import org.jiayunet.pojo.po.*;
|
import org.jiayunet.pojo.po.*;
|
||||||
import org.jiayunet.tool.UserSecurityTool;
|
import org.jiayunet.tool.UserSecurityTool;
|
||||||
@@ -11,6 +13,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,6 +51,34 @@ public class UserProfileService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private org.jiayunet.service.UserProfileAnalyzeService userProfileAnalyzeService;
|
private org.jiayunet.service.UserProfileAnalyzeService userProfileAnalyzeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserResumeMapper userResumeMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserResumeEducationMapper resumeEducationMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserResumeWorkMapper resumeWorkMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserResumeInternshipMapper resumeInternshipMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserResumeProjectMapper resumeProjectMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserResumeCompetitionMapper resumeCompetitionMapper;
|
||||||
|
|
||||||
|
/** 学历文本→枚举映射 */
|
||||||
|
private static final Map<String, Integer> DEGREE_MAP = Map.of(
|
||||||
|
"大专", 1, "本科", 2, "硕士", 3, "博士", 4
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 学习形式文本→枚举映射 */
|
||||||
|
private static final Map<String, Integer> STUDY_TYPE_MAP = Map.of(
|
||||||
|
"全日制", 0, "非全日制", 1
|
||||||
|
);
|
||||||
|
|
||||||
// ==================== 主表 ====================
|
// ==================== 主表 ====================
|
||||||
|
|
||||||
/** 查询当前用户个人资料 */
|
/** 查询当前用户个人资料 */
|
||||||
@@ -265,6 +297,178 @@ public class UserProfileService {
|
|||||||
userProfileAnalyzeService.analyzeUserProfile(userId);
|
userProfileAnalyzeService.analyzeUserProfile(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 从简历同步到个人资料 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据简历ID同步更新个人资料
|
||||||
|
* <p>1. 校验简历归属 2. 读取简历主表+5子表 3. 事务内覆盖写入Profile主表+5子表 4. 触发一次异步AI分析</p>
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void syncProfileFromResume(Long resumeId) {
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
|
||||||
|
// 1. 校验简历归属当前用户
|
||||||
|
UserResume resume = userResumeMapper.selectById(resumeId);
|
||||||
|
if (resume == null || !resume.getUserId().equals(userId)) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.PERMISSION_DENIED, "简历不存在或无权操作");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 读取简历5张子表
|
||||||
|
List<UserResumeEducation> resumeEducationList = resumeEducationMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<UserResumeEducation>().eq(UserResumeEducation::getResumeId, resumeId).orderByAsc(UserResumeEducation::getSortOrder));
|
||||||
|
List<UserResumeWork> resumeWorkList = resumeWorkMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<UserResumeWork>().eq(UserResumeWork::getResumeId, resumeId).orderByAsc(UserResumeWork::getSortOrder));
|
||||||
|
List<UserResumeInternship> resumeInternshipList = resumeInternshipMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<UserResumeInternship>().eq(UserResumeInternship::getResumeId, resumeId).orderByAsc(UserResumeInternship::getSortOrder));
|
||||||
|
List<UserResumeProject> resumeProjectList = resumeProjectMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<UserResumeProject>().eq(UserResumeProject::getResumeId, resumeId).orderByAsc(UserResumeProject::getSortOrder));
|
||||||
|
List<UserResumeCompetition> resumeCompetitionList = resumeCompetitionMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<UserResumeCompetition>().eq(UserResumeCompetition::getResumeId, resumeId).orderByAsc(UserResumeCompetition::getSortOrder));
|
||||||
|
|
||||||
|
Instant now = Instant.now();
|
||||||
|
|
||||||
|
// 3. 同步主表(upsert,只更新共有字段,保留Profile独有字段原值)
|
||||||
|
UserProfile existing = userProfileMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<UserProfile>().eq(UserProfile::getUserId, userId));
|
||||||
|
Long profileId;
|
||||||
|
if (existing != null) {
|
||||||
|
profileId = existing.getId();
|
||||||
|
existing.setName(resume.getName());
|
||||||
|
existing.setEmail(resume.getEmail());
|
||||||
|
existing.setMobileNumber(resume.getMobileNumber());
|
||||||
|
existing.setWechatNumber(resume.getWechatNumber());
|
||||||
|
existing.setPortfolioUrl(resume.getPortfolioUrl());
|
||||||
|
existing.setSkills(resume.getSkills());
|
||||||
|
existing.setCertificates(resume.getCertificates());
|
||||||
|
existing.setUpdateTime(now);
|
||||||
|
userProfileMapper.updateById(existing);
|
||||||
|
} else {
|
||||||
|
UserProfile profile = new UserProfile();
|
||||||
|
profile.setUserId(userId);
|
||||||
|
profile.setName(resume.getName());
|
||||||
|
profile.setEmail(resume.getEmail());
|
||||||
|
profile.setMobileNumber(resume.getMobileNumber());
|
||||||
|
profile.setWechatNumber(resume.getWechatNumber());
|
||||||
|
profile.setPortfolioUrl(resume.getPortfolioUrl());
|
||||||
|
profile.setSkills(resume.getSkills());
|
||||||
|
profile.setCertificates(resume.getCertificates());
|
||||||
|
profile.setCreateTime(now);
|
||||||
|
profile.setUpdateTime(now);
|
||||||
|
userProfileMapper.insert(profile);
|
||||||
|
profileId = profile.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 同步教育经历(先删后插,含degree/studyType映射)
|
||||||
|
educationMapper.delete(new LambdaQueryWrapper<UserProfileEducation>().eq(UserProfileEducation::getUserId, userId));
|
||||||
|
if (!resumeEducationList.isEmpty()) {
|
||||||
|
List<UserProfileEducation> profileEducationList = IntStream.range(0, resumeEducationList.size()).mapToObj(i -> {
|
||||||
|
UserResumeEducation src = resumeEducationList.get(i);
|
||||||
|
UserProfileEducation dest = new UserProfileEducation();
|
||||||
|
dest.setProfileId(profileId);
|
||||||
|
dest.setUserId(userId);
|
||||||
|
dest.setSchool(src.getSchool());
|
||||||
|
dest.setMajor(src.getMajor());
|
||||||
|
dest.setDegree(DEGREE_MAP.get(src.getDegree()));
|
||||||
|
dest.setStudyType(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());
|
||||||
|
educationMapper.batchInsert(profileEducationList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 同步工作经历
|
||||||
|
workMapper.delete(new LambdaQueryWrapper<UserProfileWork>().eq(UserProfileWork::getUserId, userId));
|
||||||
|
if (!resumeWorkList.isEmpty()) {
|
||||||
|
List<UserProfileWork> profileWorkList = IntStream.range(0, resumeWorkList.size()).mapToObj(i -> {
|
||||||
|
UserResumeWork src = resumeWorkList.get(i);
|
||||||
|
UserProfileWork dest = new UserProfileWork();
|
||||||
|
dest.setProfileId(profileId);
|
||||||
|
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());
|
||||||
|
workMapper.batchInsert(profileWorkList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 同步实习经历
|
||||||
|
internshipMapper.delete(new LambdaQueryWrapper<UserProfileInternship>().eq(UserProfileInternship::getUserId, userId));
|
||||||
|
if (!resumeInternshipList.isEmpty()) {
|
||||||
|
List<UserProfileInternship> profileInternshipList = IntStream.range(0, resumeInternshipList.size()).mapToObj(i -> {
|
||||||
|
UserResumeInternship src = resumeInternshipList.get(i);
|
||||||
|
UserProfileInternship dest = new UserProfileInternship();
|
||||||
|
dest.setProfileId(profileId);
|
||||||
|
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());
|
||||||
|
internshipMapper.batchInsert(profileInternshipList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 同步项目经历
|
||||||
|
projectMapper.delete(new LambdaQueryWrapper<UserProfileProject>().eq(UserProfileProject::getUserId, userId));
|
||||||
|
if (!resumeProjectList.isEmpty()) {
|
||||||
|
List<UserProfileProject> profileProjectList = IntStream.range(0, resumeProjectList.size()).mapToObj(i -> {
|
||||||
|
UserResumeProject src = resumeProjectList.get(i);
|
||||||
|
UserProfileProject dest = new UserProfileProject();
|
||||||
|
dest.setProfileId(profileId);
|
||||||
|
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());
|
||||||
|
projectMapper.batchInsert(profileProjectList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 同步竞赛经历
|
||||||
|
competitionMapper.delete(new LambdaQueryWrapper<UserProfileCompetition>().eq(UserProfileCompetition::getUserId, userId));
|
||||||
|
if (!resumeCompetitionList.isEmpty()) {
|
||||||
|
List<UserProfileCompetition> profileCompetitionList = IntStream.range(0, resumeCompetitionList.size()).mapToObj(i -> {
|
||||||
|
UserResumeCompetition src = resumeCompetitionList.get(i);
|
||||||
|
UserProfileCompetition dest = new UserProfileCompetition();
|
||||||
|
dest.setProfileId(profileId);
|
||||||
|
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());
|
||||||
|
competitionMapper.batchInsert(profileCompetitionList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 事务内所有数据写入完成,触发一次异步AI分析
|
||||||
|
userProfileAnalyzeService.analyzeUserProfile(userId);
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 内部方法 ====================
|
// ==================== 内部方法 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user