This commit is contained in:
2026-01-30 11:24:57 +08:00
14 changed files with 311 additions and 104 deletions

View File

@@ -218,7 +218,7 @@ public class HotakeAiCommonToolsController extends BaseController {
*/ */
@ApiOperation("候选人面试综合评估") @ApiOperation("候选人面试综合评估")
@PostMapping(value = "/candidateInterviewEvaluation") @PostMapping(value = "/candidateInterviewEvaluation")
public R<HotakeCandidateCompatibilityDto> candidateInterviewEvaluation(@RequestBody HotakeCandidateInterviewEvaluationVo evaluationVo) public R<HotakeCandidateInterviewEvaluationDto> candidateInterviewEvaluation(@RequestBody HotakeCandidateInterviewEvaluationVo evaluationVo)
{ {
return R.ok(hotakeAiCommonToolsService.getCandidateInterviewEvaluation(evaluationVo)); return R.ok(hotakeAiCommonToolsService.getCandidateInterviewEvaluation(evaluationVo));
} }

View File

@@ -191,6 +191,7 @@ chatGpt:
modelAiIntPf: gpt-4o-mini modelAiIntPf: gpt-4o-mini
modelAiCvSr: gpt-4o-mini modelAiCvSr: gpt-4o-mini
modelAiCac: gpt-4o-mini modelAiCac: gpt-4o-mini
modelAiCiv: gpt-4o-mini
role: system role: system
http: http:

View File

@@ -138,6 +138,7 @@ twilio:
reply-to-em7941: noreply@em7941.routez.app reply-to-em7941: noreply@em7941.routez.app
template-ids: template-ids:
routez-verification-code: d-18475c5d41e349e2bc3a35f2b4992182 routez-verification-code: d-18475c5d41e349e2bc3a35f2b4992182
interview-template-code: d-c377f1e7f5e04cb794e2753af9d2e0c8
accountSID: 1111 accountSID: 1111
authToken: 22222 authToken: 22222
sendPhoneNumber: 33333 sendPhoneNumber: 33333

View File

@@ -88,6 +88,9 @@ public class ChatGPTClient {
@Value("${chatGpt.modelAiCac}") @Value("${chatGpt.modelAiCac}")
private String modelAiCac; private String modelAiCac;
@Value("${chatGpt.modelAiCiv}")
private String modelAiCiv;
@Value("${chatGpt.role}") @Value("${chatGpt.role}")
private String role; private String role;
@@ -158,6 +161,9 @@ public class ChatGPTClient {
}else if("AICAC".equals(type)){ }else if("AICAC".equals(type)){
//招聘者查看候选人匹配度 //招聘者查看候选人匹配度
resultText = sendMessage(promptText, modelAiCac,objectMapper,client,role); resultText = sendMessage(promptText, modelAiCac,objectMapper,client,role);
}else if("AICIV".equals(type)){
//候选人面试综合评估
resultText = sendMessage(promptText, modelAiCiv,objectMapper,client,role);
}else { }else {
resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role); resultText = sendMessage(promptText, modelQuestion,objectMapper,client,role);
} }

View File

@@ -6,6 +6,7 @@ import java.util.List;
import com.vetti.common.core.domain.entity.SysUser; import com.vetti.common.core.domain.entity.SysUser;
import com.vetti.hotake.domain.dto.HotakeAiCvScoringRankingDto; import com.vetti.hotake.domain.dto.HotakeAiCvScoringRankingDto;
import com.vetti.hotake.domain.dto.HotakeCandidateCompatibilityDto; import com.vetti.hotake.domain.dto.HotakeCandidateCompatibilityDto;
import com.vetti.hotake.domain.dto.HotakeCandidateInterviewEvaluationDto;
import com.vetti.hotake.domain.dto.HotakeCvInfoDto; import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@@ -136,6 +137,18 @@ public class HotakeRolesApplyInfo extends BaseEntity
@ApiModelProperty("候选人匹配度最终得分") @ApiModelProperty("候选人匹配度最终得分")
private BigDecimal candidateCompatibilityScore; private BigDecimal candidateCompatibilityScore;
@ApiModelProperty("候选人面试综合评估JSON")
private String evaluationJson;
@ApiModelProperty("候选人面试综合评估最终得分")
private BigDecimal evaluationScore;
@ApiModelProperty("AI面试分析JSON 数据")
private String aiInterviewAnalysisJson;
@ApiModelProperty("AI面试问答数据记录JSON")
private String aiInterviewAnalysisQaJson;
@ApiModelProperty("岗位信息") @ApiModelProperty("岗位信息")
private HotakeRolesInfo rolesInfo; private HotakeRolesInfo rolesInfo;
@@ -154,6 +167,9 @@ public class HotakeRolesApplyInfo extends BaseEntity
@ApiModelProperty("招聘者查看候选人匹配度数据对象") @ApiModelProperty("招聘者查看候选人匹配度数据对象")
private HotakeCandidateCompatibilityDto compatibilityDto; private HotakeCandidateCompatibilityDto compatibilityDto;
@ApiModelProperty("候选人面试综合评估数据对象")
private HotakeCandidateInterviewEvaluationDto evaluationDto;
@ApiModelProperty("岗位申请ID数据集合") @ApiModelProperty("岗位申请ID数据集合")
private List<Long> applyRoleIdList; private List<Long> applyRoleIdList;

View File

@@ -1,6 +1,8 @@
package com.vetti.hotake.domain; package com.vetti.hotake.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
@@ -175,5 +177,8 @@ public class HotakeRolesInfo extends BaseEntity
@ApiModelProperty("当前岗位状态(pause:暂停,archived:关闭/归档,open:发布,editing:编辑中)") @ApiModelProperty("当前岗位状态(pause:暂停,archived:关闭/归档,open:发布,editing:编辑中)")
private String status; private String status;
@ApiModelProperty("岗位申请数据集合")
private List<HotakeRolesApplyInfo> rolesApplyInfoList;
} }

View File

@@ -0,0 +1,51 @@
package com.vetti.hotake.domain.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 候选人面试综合评估 返回对象
*
* @author ID
* @date 2025-09-06
*/
@Data
@Accessors(chain = true)
public class HotakeCandidateInterviewEvaluationDto {
@ApiModelProperty("评估分数")
private String assessmentScore;
@ApiModelProperty("评估等级")
private String assessmentLevel;
@ApiModelProperty("评估明细说明")
private List<String> assessmentDetails;
@ApiModelProperty("评分分数")
private String ratingScore;
@ApiModelProperty("评分等级")
private String ratingLevel;
@ApiModelProperty("评分明细说明")
private List<String> ratingDetails;
@ApiModelProperty("问答分数")
private String questionsScore;
@ApiModelProperty("问答等级")
private String questionsLevel;
@ApiModelProperty("问答明细说明")
private List<String> questionsDetails;
@ApiModelProperty("综合分数")
private String overallScore;
@ApiModelProperty("推荐说明")
private String recommendation;
}

View File

@@ -50,6 +50,9 @@ public class HotakeCandidateInterviewEvaluationVo {
@ApiModelProperty("证书") @ApiModelProperty("证书")
private String certifications; private String certifications;
@ApiModelProperty("面试时间")
private String interviewData;
@ApiModelProperty("问题") @ApiModelProperty("问题")
private String questions; private String questions;

View File

@@ -156,6 +156,6 @@ public interface IHotakeAiCommonToolsService {
* @param evaluationVo 候选人面试综合评估 输入信息 * @param evaluationVo 候选人面试综合评估 输入信息
* @return * @return
*/ */
public HotakeCandidateCompatibilityDto getCandidateInterviewEvaluation(HotakeCandidateInterviewEvaluationVo evaluationVo); public HotakeCandidateInterviewEvaluationDto getCandidateInterviewEvaluation(HotakeCandidateInterviewEvaluationVo evaluationVo);
} }

View File

@@ -1,6 +1,7 @@
package com.vetti.hotake.service.impl; package com.vetti.hotake.service.impl;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
@@ -1058,13 +1059,17 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
HotakeCandidateAiInterviewAnalysisDto analysisDto = new HotakeCandidateAiInterviewAnalysisDto(); HotakeCandidateAiInterviewAnalysisDto analysisDto = new HotakeCandidateAiInterviewAnalysisDto();
String prompt = AiCommonPromptConstants.initializationCandidateAiInterviewAnalysisPrompt(); String prompt = AiCommonPromptConstants.initializationCandidateAiInterviewAnalysisPrompt();
String qa = ""; String qa = "";
String qStr = "";
String aStr = "";
if (CollectionUtil.isNotEmpty(analysisVo.getAiInterviewQuestionRecordVoList())) { if (CollectionUtil.isNotEmpty(analysisVo.getAiInterviewQuestionRecordVoList())) {
for (HotakeAiInterviewQuestionRecordVo recordVo : analysisVo.getAiInterviewQuestionRecordVoList()) { for (HotakeAiInterviewQuestionRecordVo recordVo : analysisVo.getAiInterviewQuestionRecordVoList()) {
if ("assistant".equals(recordVo.getUserType())) { if ("assistant".equals(recordVo.getUserType())) {
qa = qa + "Question:" + recordVo.getContentText(); qa = qa + "Question:" + recordVo.getContentText();
qStr = qStr + ";" + recordVo.getContentText();
} }
if ("user".equals(recordVo.getUserType())) { if ("user".equals(recordVo.getUserType())) {
qa = qa + "Answer:" + recordVo.getContentText(); qa = qa + "Answer:" + recordVo.getContentText();
aStr = aStr + ";" + recordVo.getContentText();
} }
} }
} }
@@ -1138,8 +1143,48 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
throw new ServiceException("No rating"); throw new ServiceException("No rating");
} }
} }
//todo 把面试结果分析保存到记录表中 //把面试结果分析和问答Qa保存到记录表中
if (analysisVo.getRoleApplyId() != null) {
HotakeRolesApplyInfo applyInfo = hotakeRolesApplyInfoMapper.selectHotakeRolesApplyInfoById(analysisVo.getRoleApplyId());
applyInfo.setAiInterviewAnalysisJson(JSONUtil.toJsonStr(analysisVo));
applyInfo.setAiInterviewAnalysisQaJson(JSONUtil.toJsonStr(analysisVo.getAiInterviewQuestionRecordVoList()));
HotakeRolesInfo rolesInf = hotakeRolesInfoMapper.selectHotakeRolesInfoById(applyInfo.getRoleId());
try {
//候选人面试综合评估
HotakeCandidateInterviewEvaluationVo evaluationVo = new HotakeCandidateInterviewEvaluationVo();
evaluationVo.setTitle(rolesInf.getRoleName());
evaluationVo.setDescription(rolesInf.getAboutRole());
evaluationVo.setRequiredSkills(rolesInf.getRequiredSkillsJson());
evaluationVo.setPreferredSkills(rolesInf.getNiceToHaveSkillsJson());
evaluationVo.setExperienceRequired(rolesInf.getJobExperience());
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(applyInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
evaluationVo.setName(cvInfoDto.getName());
evaluationVo.setCurrentPosition(cvInfoDto.getPosition());
evaluationVo.setEmail(cvInfoDto.getEmail());
evaluationVo.setWorkExperience(JSONUtil.toJsonStr(cvInfoDto.getExperience()));
evaluationVo.setSkills(JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()));
evaluationVo.setEducation(JSONUtil.toJsonStr(cvInfoDto.getEducation()));
evaluationVo.setCertifications("");
evaluationVo.setInterviewData(DateUtil.now());
evaluationVo.setQuestions(qStr);
evaluationVo.setAnswers(aStr);
evaluationVo.setTechnical(analysisDto.getTechnical().toString());
evaluationVo.setCommunication(analysisDto.getCommunication().toString());
evaluationVo.setSafetyAwareness("");
evaluationVo.setProblemSolving("");
HotakeCandidateInterviewEvaluationDto evaluationDto = getCandidateInterviewEvaluation(evaluationVo);
applyInfo.setEvaluationJson(JSONUtil.toJsonStr(evaluationDto));
applyInfo.setEvaluationScore(new BigDecimal(evaluationDto.getOverallScore()));
} catch (Exception e) {
e.printStackTrace();
}
hotakeRolesApplyInfoMapper.updateHotakeRolesApplyInfo(applyInfo);
}
return analysisDto; return analysisDto;
} }
@@ -1340,30 +1385,30 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
* @return * @return
*/ */
@Override @Override
public HotakeCandidateCompatibilityDto getCandidateInterviewEvaluation(HotakeCandidateInterviewEvaluationVo evaluationVo) { public HotakeCandidateInterviewEvaluationDto getCandidateInterviewEvaluation(HotakeCandidateInterviewEvaluationVo evaluationVo) {
HotakeCandidateCompatibilityDto dto = new HotakeCandidateCompatibilityDto(); HotakeCandidateInterviewEvaluationDto dto = new HotakeCandidateInterviewEvaluationDto();
String prompt = AiCommonPromptConstants.initializationCandidateInterviewEvaluationPrompt(); String prompt = AiCommonPromptConstants.initializationCandidateInterviewEvaluationPrompt();
String userPrompt_1 = "Job Posting:\n" + String userPrompt_1 = "Job Posting:\n" +
"Title: " + evaluationVo.getTitle() + "\n" + "Title: " + evaluationVo.getTitle() + "\n" +
"Description: " + evaluationVo.getDescription() + "\n" + "Description: " + evaluationVo.getDescription() + "\n" +
"Required Skills: ${jobPosting.required_skills.join(', ')}\n" + "Required Skills: " + evaluationVo.getRequiredSkills() + "\n" +
"Preferred Skills: ${jobPosting.preferred_skills.join(', ')}\n" + "Preferred Skills: " + evaluationVo.getPreferredSkills() + "\n" +
"Experience Required: ${jobPosting.experience_required}\n" + "Experience Required: " + evaluationVo.getExperienceRequired() + "\n" +
"\n" + "\n" +
"Candidate Information:\n" + "Candidate Information:\n" +
"Name: ${candidate.name}\n" + "Name: " + evaluationVo.getName() + "\n" +
"Current Position: ${candidate.current_position}\n" + "Current Position: " + evaluationVo.getCurrentPosition() + "\n" +
"Email: ${candidate.email}\n" + "Email: " + evaluationVo.getEmail() + "\n" +
"Work Experience: ${candidate.work_experience}\n" + "Work Experience: " + evaluationVo.getWorkExperience() + "\n" +
"Skills: ${candidate.skills.join(', ')}\n" + "Skills: " + evaluationVo.getSkills() + "\n" +
"Education: ${candidate.education}\n" + "Education: " + evaluationVo.getEducation() + "\n" +
"Certifications: ${candidate.certifications.join(', ')}\n" + "Certifications: " + evaluationVo.getCertifications() + "\n" +
"\n" + "\n" +
"${interviewData ? `Interview Data:\n" + "Interview Data:" + evaluationVo.getInterviewData() + "\n" +
"Questions: ${interviewData.questions.join('; ')}\n" + "Questions: " + evaluationVo.getQuestions() + "\n" +
"Answers: ${interviewData.answers.join('; ')}\n" + "Answers: " + evaluationVo.getAnswers() + "\n" +
"Scores: Technical=${interviewData.scores.technical}, Communication=${interviewData.scores.communication}, Safety Awareness=${interviewData.scores.safety_awareness}, Problem Solving=${interviewData.scores.problem_solving}` : ''}\n" + "Scores: Technical=" + evaluationVo.getTechnical() + ", Communication=" + evaluationVo.getCommunication() + ", Safety Awareness=" + evaluationVo.getSafetyAwareness() + ", Problem Solving=" + evaluationVo.getProblemSolving() + "}\n" +
"\n" + "\n" +
"Please analyze this candidate and provide a comprehensive overview with Assessment, Rating, and Questions scores."; "Please analyze this candidate and provide a comprehensive overview with Assessment, Rating, and Questions scores.";
@@ -1378,38 +1423,37 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
mapUserEntityOne.put("content", userPrompt_1); mapUserEntityOne.put("content", userPrompt_1);
listOne.add(mapUserEntityOne); listOne.add(mapUserEntityOne);
String promptJsonOne = JSONUtil.toJsonStr(listOne); String promptJsonOne = JSONUtil.toJsonStr(listOne);
String resultStrOne = chatGPTClient.handleAiChat(promptJsonOne, "AICAC"); String resultStrOne = chatGPTClient.handleAiChat(promptJsonOne, "AICIV");
String resultJsonOne = resultStrOne.replaceAll("```json", "").replaceAll("```", ""); String resultJsonOne = resultStrOne.replaceAll("```json", "").replaceAll("```", "");
log.info("候选人面试综合评估:{}", resultJsonOne); log.info("候选人面试综合评估:{}", resultJsonOne);
Map dataMap = JSONUtil.toBean(resultJsonOne, Map.class); Map dataMap = JSONUtil.toBean(resultJsonOne, Map.class);
if(ObjectUtil.isNotEmpty(dataMap.get("strengths_score"))){ Map scoreBreakdownMap = (Map) dataMap.get("score_breakdown");
dto.setStrengthsScore(new BigDecimal(dataMap.get("strengths_score").toString())); if (scoreBreakdownMap != null) {
}else{ Map assessmentMap = (Map) scoreBreakdownMap.get("assessment");
dto.setStrengthsScore(BigDecimal.ZERO); if (assessmentMap != null) {
dto.setAssessmentScore(assessmentMap.get("score").toString());
dto.setAssessmentLevel(assessmentMap.get("score").toString());
List<String> details = (List<String>) assessmentMap.get("details");
dto.setAssessmentDetails(details);
} }
if(ObjectUtil.isNotEmpty(dataMap.get("differences_score"))){ Map ratingMap = (Map) scoreBreakdownMap.get("rating");
dto.setDifferencesScore(new BigDecimal(dataMap.get("differences_score").toString())); if (ratingMap != null) {
}else{ dto.setRatingScore(ratingMap.get("score").toString());
dto.setDifferencesScore(BigDecimal.ZERO); dto.setRatingLevel(ratingMap.get("score").toString());
List<String> details = (List<String>) ratingMap.get("details");
dto.setRatingDetails(details);
}
Map questionsMap = (Map) scoreBreakdownMap.get("questions");
if (questionsMap != null) {
dto.setQuestionsScore(questionsMap.get("score").toString());
dto.setQuestionsLevel(questionsMap.get("score").toString());
List<String> details = (List<String>) questionsMap.get("details");
dto.setQuestionsDetails(details);
} }
if(ObjectUtil.isNotEmpty(dataMap.get("cultural_score"))){
dto.setCulturalScore(new BigDecimal(dataMap.get("cultural_score").toString()));
}else{
dto.setCulturalScore(BigDecimal.ZERO);
} }
List<String> strengths = (List<String>)dataMap.get("key_strengths"); dto.setOverallScore(dataMap.get("overall_score").toString());
dto.setKeyStrengths(strengths); dto.setRecommendation(dataMap.get("recommendation").toString());
List<String> differences = (List<String>)dataMap.get("key_differences");
dto.setKeyDifferences(differences);
List<String> fitDetails = (List<String>)dataMap.get("cultural_fit_details");
dto.setCulturalFitDetails(fitDetails);
BigDecimal overallScore = dto.getStrengthsScore().multiply(new BigDecimal(0.4)).
add(dto.getDifferencesScore().multiply(new BigDecimal(0.3)).add(dto.getCulturalScore().multiply(new BigDecimal(0.3))));
dto.setOverallScore(overallScore);
return dto; return dto;
} }

View File

@@ -18,15 +18,9 @@ import com.vetti.common.utils.DateUtils;
import com.vetti.common.utils.SecurityUtils; import com.vetti.common.utils.SecurityUtils;
import com.vetti.common.utils.readFile.FileContentUtil; import com.vetti.common.utils.readFile.FileContentUtil;
import com.vetti.hotake.domain.*; import com.vetti.hotake.domain.*;
import com.vetti.hotake.domain.dto.HotakeAiCvScoringRankingDto; import com.vetti.hotake.domain.dto.*;
import com.vetti.hotake.domain.dto.HotakeCandidateCompatibilityDto;
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
import com.vetti.hotake.domain.dto.HotakeInitialQuestionEliminationScoreDto;
import com.vetti.hotake.domain.dto.VcDto.*; import com.vetti.hotake.domain.dto.VcDto.*;
import com.vetti.hotake.domain.vo.HotakeAiCvScoringRankingRoleApplyVo; import com.vetti.hotake.domain.vo.*;
import com.vetti.hotake.domain.vo.HotakeCandidateCompatibilityVo;
import com.vetti.hotake.domain.vo.HotakeInitScreQuestionsReplyRecordInfoVo;
import com.vetti.hotake.domain.vo.HotakeInitialQuestionEliminationScoreVo;
import com.vetti.hotake.mapper.HotakeCvInfoMapper; import com.vetti.hotake.mapper.HotakeCvInfoMapper;
import com.vetti.hotake.mapper.HotakeRolesApplyInfoMapper; import com.vetti.hotake.mapper.HotakeRolesApplyInfoMapper;
import com.vetti.hotake.mapper.HotakeRolesInfoMapper; import com.vetti.hotake.mapper.HotakeRolesInfoMapper;
@@ -264,22 +258,53 @@ public class HotakeInitScreQuestionsReplyRecordInfoServiceImpl extends BaseServi
applyInfo.setAiCvScore(scoringRankingDto.getOverallScore()); applyInfo.setAiCvScore(scoringRankingDto.getOverallScore());
//招聘者查看候选人匹配度 //招聘者查看候选人匹配度
HotakeCandidateCompatibilityVo compatibilityVo = new HotakeCandidateCompatibilityVo(); // HotakeCandidateCompatibilityVo compatibilityVo = new HotakeCandidateCompatibilityVo();
compatibilityVo.setPosition(rolesInf.getRoleName()); // compatibilityVo.setPosition(rolesInf.getRoleName());
// HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(applyInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
// compatibilityVo.setCurrentPosition(cvInfoDto.getPosition());
// compatibilityVo.setOverallRating(scoringRankingDto.getOverallScore().toString());
// compatibilityVo.setWorkExperience(cvInfoDto.getExperienceYear());
// List<String> skills = new ArrayList<>();
// if(CollectionUtil.isNotEmpty(cvInfoDto.getSkillsTools())){
// for (VcSkillsToolsDto toolsDto : cvInfoDto.getSkillsTools()){
// skills.add(toolsDto.getContent());
// }
// }
// compatibilityVo.setSkills(skills);
//
//
//
// HotakeCandidateCompatibilityDto compatibilityDto = aiCommonToolsService.handleCandidateCompatibility(compatibilityVo);
// applyInfo.setCandidateCompatibilityJson(JSONUtil.toJsonStr(compatibilityDto));
// applyInfo.setCandidateCompatibilityScore(compatibilityDto.getOverallScore());
//候选人面试综合评估
HotakeCandidateInterviewEvaluationVo evaluationVo = new HotakeCandidateInterviewEvaluationVo();
evaluationVo.setTitle(rolesInf.getRoleName());
evaluationVo.setDescription(rolesInf.getAboutRole());
evaluationVo.setRequiredSkills(rolesInf.getRequiredSkillsJson());
evaluationVo.setPreferredSkills(rolesInf.getNiceToHaveSkillsJson());
evaluationVo.setExperienceRequired(rolesInf.getJobExperience());
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(applyInfo.getCvTemplateJson(), HotakeCvInfoDto.class); HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(applyInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
compatibilityVo.setCurrentPosition(cvInfoDto.getPosition()); evaluationVo.setName(cvInfoDto.getName());
compatibilityVo.setOverallRating(scoringRankingDto.getOverallScore().toString()); evaluationVo.setCurrentPosition(cvInfoDto.getPosition());
compatibilityVo.setWorkExperience(cvInfoDto.getExperienceYear()); evaluationVo.setEmail(cvInfoDto.getEmail());
List<String> skills = new ArrayList<>(); evaluationVo.setWorkExperience(JSONUtil.toJsonStr(cvInfoDto.getExperience()));
if(CollectionUtil.isNotEmpty(cvInfoDto.getSkillsTools())){ evaluationVo.setSkills(JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()));
for (VcSkillsToolsDto toolsDto : cvInfoDto.getSkillsTools()){ evaluationVo.setEducation(JSONUtil.toJsonStr(cvInfoDto.getEducation()));
skills.add(toolsDto.getContent()); evaluationVo.setCertifications("");
} evaluationVo.setInterviewData("");
} evaluationVo.setQuestions("");
compatibilityVo.setSkills(skills); evaluationVo.setAnswers("");
HotakeCandidateCompatibilityDto compatibilityDto = aiCommonToolsService.handleCandidateCompatibility(compatibilityVo); evaluationVo.setTechnical("");
applyInfo.setCandidateCompatibilityJson(JSONUtil.toJsonStr(compatibilityDto)); evaluationVo.setCommunication("");
applyInfo.setCandidateCompatibilityScore(compatibilityDto.getOverallScore()); evaluationVo.setSafetyAwareness("");
evaluationVo.setProblemSolving("");
HotakeCandidateInterviewEvaluationDto evaluationDto = aiCommonToolsService.getCandidateInterviewEvaluation(evaluationVo);
applyInfo.setEvaluationJson(JSONUtil.toJsonStr(evaluationDto));
applyInfo.setEvaluationScore(new BigDecimal(evaluationDto.getOverallScore()));
applyInfo.setRecruiterId(rolesInf.getRecruiterId()); applyInfo.setRecruiterId(rolesInf.getRecruiterId());
applyInfo.setStage(StageEnum.APPLIED.getCode()); applyInfo.setStage(StageEnum.APPLIED.getCode());

View File

@@ -105,6 +105,7 @@ public class HotakeRolesApplyInfoServiceImpl extends BaseServiceImpl implements
List<HotakeRolesApplyInfo> applyInfoList = hotakeRolesApplyInfoMapper.selectHotakeRolesApplyInfoList(hotakeRolesApplyInfo); List<HotakeRolesApplyInfo> applyInfoList = hotakeRolesApplyInfoMapper.selectHotakeRolesApplyInfoList(hotakeRolesApplyInfo);
if(CollectionUtil.isNotEmpty(applyInfoList)) { if(CollectionUtil.isNotEmpty(applyInfoList)) {
List<SysUser> sysUserList = userService.selectUserList(new SysUser());
List<HotakeInitScreQuestionsReplyRecordInfo> screQuestionsReplyRecordInfoList = initScreQuestionsReplyRecordInfoMapper.selectHotakeInitScreQuestionsReplyRecordInfoList(new HotakeInitScreQuestionsReplyRecordInfo()); List<HotakeInitScreQuestionsReplyRecordInfo> screQuestionsReplyRecordInfoList = initScreQuestionsReplyRecordInfoMapper.selectHotakeInitScreQuestionsReplyRecordInfoList(new HotakeInitScreQuestionsReplyRecordInfo());
@@ -149,6 +150,12 @@ public class HotakeRolesApplyInfoServiceImpl extends BaseServiceImpl implements
} }
applyInfo.setScreQuestionsReplyRecordInfoList(screQuestionsReplyRecordInfos); applyInfo.setScreQuestionsReplyRecordInfoList(screQuestionsReplyRecordInfos);
} }
if(applyInfo.getCandidateId() != null){
List<SysUser> userList = sysUserList.stream().filter(e->e.getUserId().longValue() == applyInfo.getCandidateId().longValue()).toList();
if(CollectionUtil.isNotEmpty(userList)) {
applyInfo.setCandidateUSer(userList.get(0));
}
}
} }
} }
return applyInfoList; return applyInfoList;

View File

@@ -16,10 +16,12 @@ import com.vetti.common.utils.SecurityUtils;
import com.vetti.common.utils.uuid.IdUtils; import com.vetti.common.utils.uuid.IdUtils;
import com.vetti.hotake.domain.HotakeAiInterviewQuestionsInfo; import com.vetti.hotake.domain.HotakeAiInterviewQuestionsInfo;
import com.vetti.hotake.domain.HotakeInitialScreeningQuestionsInfo; import com.vetti.hotake.domain.HotakeInitialScreeningQuestionsInfo;
import com.vetti.hotake.domain.HotakeRolesApplyInfo;
import com.vetti.hotake.domain.HotakeRolesInfo; import com.vetti.hotake.domain.HotakeRolesInfo;
import com.vetti.hotake.domain.dto.AiQuestionDto; import com.vetti.hotake.domain.dto.AiQuestionDto;
import com.vetti.hotake.domain.dto.HotakeRolesInfoDto; import com.vetti.hotake.domain.dto.HotakeRolesInfoDto;
import com.vetti.hotake.domain.dto.roleDto.*; import com.vetti.hotake.domain.dto.roleDto.*;
import com.vetti.hotake.mapper.HotakeRolesApplyInfoMapper;
import com.vetti.hotake.mapper.HotakeRolesInfoMapper; import com.vetti.hotake.mapper.HotakeRolesInfoMapper;
import com.vetti.hotake.service.IHotakeAiInterviewQuestionsInfoService; import com.vetti.hotake.service.IHotakeAiInterviewQuestionsInfoService;
import com.vetti.hotake.service.IHotakeInitialScreeningQuestionsInfoService; import com.vetti.hotake.service.IHotakeInitialScreeningQuestionsInfoService;
@@ -48,6 +50,9 @@ public class HotakeRolesInfoServiceImpl extends BaseServiceImpl implements IHota
@Autowired @Autowired
private SysUserMapper sysUserMapper; private SysUserMapper sysUserMapper;
@Autowired
private HotakeRolesApplyInfoMapper hotakeRolesApplyInfoMapper;
@Autowired @Autowired
private IHotakeInitialScreeningQuestionsInfoService hotakeInitialScreeningQuestionsInfoService; private IHotakeInitialScreeningQuestionsInfoService hotakeInitialScreeningQuestionsInfoService;
@@ -144,13 +149,30 @@ public class HotakeRolesInfoServiceImpl extends BaseServiceImpl implements IHota
@Override @Override
public List<HotakeRolesInfo> selectHotakeRolesInfoList(HotakeRolesInfo hotakeRolesInfo) public List<HotakeRolesInfo> selectHotakeRolesInfoList(HotakeRolesInfo hotakeRolesInfo)
{ {
List<HotakeRolesInfo> rolesInfoList = hotakeRolesInfoMapper.selectHotakeRolesInfoList(hotakeRolesInfo); List<HotakeRolesInfo> rolesInfoList = hotakeRolesInfoMapper.selectHotakeRolesInfoList(hotakeRolesInfo);
//计算一个发布日期 //计算一个发布日期
if(CollectionUtil.isNotEmpty(rolesInfoList)){ if(CollectionUtil.isNotEmpty(rolesInfoList)){
List<HotakeRolesApplyInfo> applyInfoList = hotakeRolesApplyInfoMapper.selectHotakeRolesApplyInfoList(new HotakeRolesApplyInfo());
List<SysUser> sysUserList = sysUserMapper.selectUserList(new SysUser());
for (HotakeRolesInfo rolesInfo : rolesInfoList) { for (HotakeRolesInfo rolesInfo : rolesInfoList) {
String posted = DateUtils.getTimeAgo(rolesInfo.getCreateTime()); String posted = DateUtils.getTimeAgo(rolesInfo.getCreateTime());
rolesInfo.setPosted(posted); rolesInfo.setPosted(posted);
if(CollectionUtil.isNotEmpty(applyInfoList)){
List<HotakeRolesApplyInfo> applyInfos = applyInfoList.stream().filter(e->e.getRoleId().longValue() == rolesInfo.getId().longValue()).toList();
if(CollectionUtil.isNotEmpty(applyInfos)){
for (HotakeRolesApplyInfo applyInfo : applyInfos) {
if(applyInfo.getCandidateId() != null){
List<SysUser> userList = sysUserList.stream().filter(e->e.getUserId().longValue() == applyInfo.getCandidateId().longValue()).toList();
if(CollectionUtil.isNotEmpty(userList)) {
applyInfo.setCandidateUSer(userList.get(0));
}
}
}
rolesInfo.setRolesApplyInfoList(applyInfos);
}
}
} }
} }
return rolesInfoList; return rolesInfoList;

View File

@@ -32,6 +32,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="candidateCompatibilityJson" column="candidate_compatibility_json" /> <result property="candidateCompatibilityJson" column="candidate_compatibility_json" />
<result property="candidateCompatibilityScore" column="candidate_compatibility_score" /> <result property="candidateCompatibilityScore" column="candidate_compatibility_score" />
<result property="evaluationJson" column="evaluation_json" />
<result property="evaluationScore" column="evaluation_score" />
<result property="aiInterviewAnalysisJson" column="ai_interview_analysis_json" />
<result property="aiInterviewAnalysisQaJson" column="ai_interview_analysis_qa_json" />
<result property="delFlag" column="del_flag" /> <result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
@@ -44,7 +51,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectHotakeRolesApplyInfoVo"> <sql id="selectHotakeRolesApplyInfoVo">
select id, candidate_id,recruiter_id, role_id, full_name, email, phone_number, cv_file, cv_file_suffix,file_size_show, select id, candidate_id,recruiter_id, role_id, full_name, email, phone_number, cv_file, cv_file_suffix,file_size_show,
cover_letter, candidate_status, stage, last_contact, cv_template_json, cv_score, cv_md5, experience, ai_match_score, cover_letter, candidate_status, stage, last_contact, cv_template_json, cv_score, cv_md5, experience, ai_match_score,
ai_match_score_percentage,status, ai_cv_scoring_ranking_json,ai_cv_score,candidate_compatibility_json,candidate_compatibility_score, ai_match_score_percentage,status, ai_cv_scoring_ranking_json,ai_cv_score,candidate_compatibility_json,
candidate_compatibility_score,evaluation_json,evaluation_score,ai_interview_analysis_json,ai_interview_analysis_qa_json,
del_flag, create_by, create_time, update_by, update_time, remark from hotake_roles_apply_info del_flag, create_by, create_time, update_by, update_time, remark from hotake_roles_apply_info
</sql> </sql>
@@ -178,6 +186,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="candidateCompatibilityJson != null">candidate_compatibility_json,</if> <if test="candidateCompatibilityJson != null">candidate_compatibility_json,</if>
<if test="candidateCompatibilityScore != null">candidate_compatibility_score,</if> <if test="candidateCompatibilityScore != null">candidate_compatibility_score,</if>
<if test="evaluationJson != null">evaluation_json,</if>
<if test="evaluationScore != null">evaluation_score,</if>
<if test="aiInterviewAnalysisJson != null">ai_interview_analysis_json,</if>
<if test="aiInterviewAnalysisQaJson != null">ai_interview_analysis_qa_json,</if>
<if test="delFlag != null">del_flag,</if> <if test="delFlag != null">del_flag,</if>
<if test="createBy != null">create_by,</if> <if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if> <if test="createTime != null">create_time,</if>
@@ -212,6 +226,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="candidateCompatibilityJson != null">#{candidateCompatibilityJson},</if> <if test="candidateCompatibilityJson != null">#{candidateCompatibilityJson},</if>
<if test="candidateCompatibilityScore != null">#{candidateCompatibilityScore},</if> <if test="candidateCompatibilityScore != null">#{candidateCompatibilityScore},</if>
<if test="evaluationJson != null">#{evaluationJson},</if>
<if test="evaluationScore != null">#{evaluationScore},</if>
<if test="aiInterviewAnalysisJson != null">#{aiInterviewAnalysisJson},</if>
<if test="aiInterviewAnalysisQaJson != null">#{aiInterviewAnalysisQaJson},</if>
<if test="delFlag != null">#{delFlag},</if> <if test="delFlag != null">#{delFlag},</if>
<if test="createBy != null">#{createBy},</if> <if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if> <if test="createTime != null">#{createTime},</if>
@@ -250,6 +270,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="candidateCompatibilityJson != null">candidate_compatibility_json = #{candidateCompatibilityJson},</if> <if test="candidateCompatibilityJson != null">candidate_compatibility_json = #{candidateCompatibilityJson},</if>
<if test="candidateCompatibilityScore != null">candidate_compatibility_score = #{candidateCompatibilityScore},</if> <if test="candidateCompatibilityScore != null">candidate_compatibility_score = #{candidateCompatibilityScore},</if>
<if test="evaluationJson != null">evaluation_json = #{evaluationJson},</if>
<if test="evaluationScore != null">evaluation_score = #{evaluationScore},</if>
<if test="aiInterviewAnalysisJson != null">ai_interview_analysis_json = #{aiInterviewAnalysisJson},</if>
<if test="aiInterviewAnalysisQaJson != null">ai_interview_analysis_qa_json = #{aiInterviewAnalysisQaJson},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if> <if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="createBy != null">create_by = #{createBy},</if> <if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if> <if test="createTime != null">create_time = #{createTime},</if>