岗位类型(三级): 同三级=100 / 同二级=90 / 同一级=85 / 不相关=10

行业(两级):     同二级=100 / 同一级=90 / 不相关=10
fit = min(100, 岗位类型分 × 0.9 + 行业分 × 0.6)
无 AI 分析(两个方向都空)→ 中性分 40
This commit is contained in:
zk
2026-07-14 14:34:35 +08:00
parent 0a413be803
commit dfb79160df
@@ -148,37 +148,34 @@ public class JobMatchService {
/** /**
* 计算方向适配得分 fitScore(百分制) * 计算方向适配得分 fitScore(百分制)
* <p>基于 AI 推荐的岗位方向/行业方向与岗位实际类型/公司行业做层级匹配</p> * <p>基于 AI 推荐的岗位方向/行业方向与岗位实际类型/公司行业做层级匹配</p>
* <p>fitScore = 岗位类型分×70% + 行业分×30%</p> * <p>fitScore = min(100, 岗位类型分×0.9 + 行业分×0.6):两项加法叠加,均强相关时溢出封顶 100</p>
* <p>用户未做过 AI 分析(无 AI 推荐方向)时返回 0</p> * <p>用户未做过 AI 分析(无任何 AI 推荐方向)时返回中性分 40(方向未知,疑罪从无)</p>
*/ */
private int calculateFitScore(JobListItemVo job, List<Long> aiCategoryIds, List<Long> aiIndustryIds, private int calculateFitScore(JobListItemVo job, List<Long> aiCategoryIds, List<Long> aiIndustryIds,
Map<Long, JobCategory> categoryMap, Map<Long, Industry> industryMap) { Map<Long, JobCategory> categoryMap, Map<Long, Industry> industryMap) {
boolean noCategory = aiCategoryIds == null || aiCategoryIds.isEmpty(); boolean noCategory = aiCategoryIds == null || aiCategoryIds.isEmpty();
boolean noIndustry = aiIndustryIds == null || aiIndustryIds.isEmpty(); boolean noIndustry = aiIndustryIds == null || aiIndustryIds.isEmpty();
// 无任何 AI 推荐方向 → 不参与加 // 无任何 AI 推荐方向 → 方向未知,给中性
if (noCategory && noIndustry) { if (noCategory && noIndustry) {
return 0; return 40;
} }
int categoryScore = calculateCategoryFit(aiCategoryIds, job.getCategoryId(), categoryMap); double categoryContribution = noCategory ? 0 : calculateCategoryFit(aiCategoryIds, job.getCategoryId(), categoryMap) * 0.9;
int industryScore = calculateIndustryFit(aiIndustryIds, job.getCompanyIndustryId(), industryMap); double industryContribution = noIndustry ? 0 : calculateIndustryFit(aiIndustryIds, job.getCompanyIndustryId(), industryMap) * 0.6;
return (int) Math.round(categoryScore * 0.7 + industryScore * 0.3); return Math.min(100, (int) Math.round(categoryContribution + industryContribution));
} }
/** /**
* 计算岗位类型方向匹配分(三级树,取 AI 推荐中的最高分) * 计算岗位类型方向匹配分(三级树,取 AI 推荐中的最高分)
* <p>同三级→100,同二级→70,同一级→30,否则→0</p> * <p>同三级→100,同二级→90,同一级→85,不相关→10(保底)</p>
*/ */
private int calculateCategoryFit(List<Long> aiCategoryIds, Long jobCategoryId, Map<Long, JobCategory> categoryMap) { private int calculateCategoryFit(List<Long> aiCategoryIds, Long jobCategoryId, Map<Long, JobCategory> categoryMap) {
if (aiCategoryIds == null || aiCategoryIds.isEmpty() || jobCategoryId == null) { JobCategory jobCategory = jobCategoryId == null ? null : categoryMap.get(jobCategoryId);
return 0;
}
JobCategory jobCategory = categoryMap.get(jobCategoryId);
if (jobCategory == null) { if (jobCategory == null) {
return 0; return 10;
} }
int maxScore = 0; int maxScore = 10;
for (Long aiId : aiCategoryIds) { for (Long aiId : aiCategoryIds) {
JobCategory aiCategory = categoryMap.get(aiId); JobCategory aiCategory = categoryMap.get(aiId);
if (aiCategory == null) continue; if (aiCategory == null) continue;
@@ -186,11 +183,11 @@ public class JobMatchService {
if (aiCategory.getId().equals(jobCategory.getId())) { if (aiCategory.getId().equals(jobCategory.getId())) {
score = 100; score = 100;
} else if (aiCategory.getParentId() != null && aiCategory.getParentId().equals(jobCategory.getParentId())) { } else if (aiCategory.getParentId() != null && aiCategory.getParentId().equals(jobCategory.getParentId())) {
score = 70; score = 90;
} else if (aiCategory.getRootId() != null && aiCategory.getRootId().equals(jobCategory.getRootId())) { } else if (aiCategory.getRootId() != null && aiCategory.getRootId().equals(jobCategory.getRootId())) {
score = 30; score = 85;
} else { } else {
score = 0; score = 10;
} }
maxScore = Math.max(maxScore, score); maxScore = Math.max(maxScore, score);
if (maxScore == 100) return 100; if (maxScore == 100) return 100;
@@ -200,17 +197,14 @@ public class JobMatchService {
/** /**
* 计算行业方向匹配分(两级树,取 AI 推荐中的最高分) * 计算行业方向匹配分(两级树,取 AI 推荐中的最高分)
* <p>同二级→100,同一级→60否则→0</p> * <p>同二级→100,同一级→90不相关→10(保底)</p>
*/ */
private int calculateIndustryFit(List<Long> aiIndustryIds, Long companyIndustryId, Map<Long, Industry> industryMap) { private int calculateIndustryFit(List<Long> aiIndustryIds, Long companyIndustryId, Map<Long, Industry> industryMap) {
if (aiIndustryIds == null || aiIndustryIds.isEmpty() || companyIndustryId == null) { Industry companyIndustry = companyIndustryId == null ? null : industryMap.get(companyIndustryId);
return 0;
}
Industry companyIndustry = industryMap.get(companyIndustryId);
if (companyIndustry == null) { if (companyIndustry == null) {
return 0; return 10;
} }
int maxScore = 0; int maxScore = 10;
for (Long aiId : aiIndustryIds) { for (Long aiId : aiIndustryIds) {
Industry aiIndustry = industryMap.get(aiId); Industry aiIndustry = industryMap.get(aiId);
if (aiIndustry == null) continue; if (aiIndustry == null) continue;
@@ -218,9 +212,9 @@ public class JobMatchService {
if (aiIndustry.getId().equals(companyIndustry.getId())) { if (aiIndustry.getId().equals(companyIndustry.getId())) {
score = 100; score = 100;
} else if (aiIndustry.getParentId() != null && aiIndustry.getParentId().equals(companyIndustry.getParentId())) { } else if (aiIndustry.getParentId() != null && aiIndustry.getParentId().equals(companyIndustry.getParentId())) {
score = 60; score = 90;
} else { } else {
score = 0; score = 10;
} }
maxScore = Math.max(maxScore, score); maxScore = Math.max(maxScore, score);
if (maxScore == 100) return 100; if (maxScore == 100) return 100;