// 使用Intl.Segmenter对中文文本进行分词 function segmentText(text) { const segmenter = new Intl.Segmenter('zh-Hans', { granularity: 'word' }); // 使用中文简体语言 const segments = []; for (let segment of segmenter.segment(text.toLowerCase())) { // 转为小写后进行分词 segments.push(segment.segment); } return segments; } // 语气 停用次 const stopWords = ['的', '了', '啊', '哦', '/', '、', ' ', '', '-', '(', ')', '(', ')', '+', "=", "~", "!", "<", ">", "?", "[", "]", "{", "}" ] function cleanKeywords(arr) { return arr.filter(word => word && !stopWords.includes(word)) } function calculateMatchScore(source, target) { const sourceSet = new Set(cleanKeywords(source)) const targetSet = new Set(cleanKeywords(target)) let matchCount = 0 for (let word of sourceSet) { if (targetSet.has(word)) { matchCount++ } } // 匹配度 = source中匹配到的词 / source总词数 return matchCount / sourceSet.size } class CsimilarityJobs { config = { thresholdVal: 0.69, titleSimilarityWeight: 0.4, salaryMatchWeight: 0.2, areaMatchWeight: 0.2, educationMatchWeight: 0.2, experiencenMatchWeight: 0.1 } userTitle = ['Java', 'C', '全栈工程师']; userSalaryMin = 10000; userSalaryMax = 15000; userArea = 0; // 用户指定的区域(例如:市南区) userEducation = 4; // 用户学历(假设4为本科) userExperience = 2; // 用户工作经验 jobTitle = ''; jobMinSalary = 10000 jobMaxSalary = 15000 jobLocationAreaCode = 0 jobEducation = 4 jobExperience = 2 jobCategory = '' // 系统 log = false constructor() {} setUserInfo(resume) { this.userTitle = resume.jobTitle this.userSalaryMax = Number(resume.salaryMax) this.userSalaryMin = Number(resume.salaryMin) this.userArea = Number(resume.area) this.userEducation = resume.education this.userExperience = this.getUserExperience(Number(resume.age)) } setJobInfo(jobInfo) { this.jobTitle = jobInfo.jobTitle; this.jobMinSalary = jobInfo.minSalary this.jobMaxSalary = jobInfo.maxSalary this.jobLocationAreaCode = jobInfo.jobLocationAreaCode this.jobEducation = jobInfo.education this.jobExperience = jobInfo.experience this.jobCategory = jobInfo.jobCategory } calculationMatchingDegreeJob(resume) { // 计算职位标题相似度 // const titleSimilarity = stringSimilarity.compareTwoStrings(this.userTitle, job.jobTitle); let jobT = null if (this.jobCategory) { jobT = this.calculateBestJobCategoryMatch(resume.jobTitle || resume.jobTitleString || [], this .jobCategory); } else { jobT = this.calculateBestJobMatch(resume.jobTitle || resume.jobTitleString || [], this.jobTitle); } const { bestMatchJobTitle, maxSimilarity } = jobT // 计算薪资匹配度 const salaryMatch = this.calculateSalaryMatch(Number(resume.salaryMin), Number(resume.salaryMax), this .jobMinSalary, this.jobMaxSalary); // 计算区域匹配度 const areaMatch = this.calculateAreaMatch(Number(resume.area), this.jobLocationAreaCode); // 计算学历匹配度 const educationMatch = this.calculateEducationMatch(resume.education, this.jobEducation); // 计算工作经验匹配度 // const experiencenMatch = this.calculateExperienceMatch2(this.userExperience, job.experience); // 综合匹配度 = 0.4 * 职位相似度 + 0.2 * 薪资匹配度 + 0.1 * 区域匹配度 + 0.2 * 学历匹配度 + 0.1 * 工作经验匹配度 const overallMatch = this.config.titleSimilarityWeight * maxSimilarity + this.config.salaryMatchWeight * salaryMatch + this.config.areaMatchWeight * areaMatch + this.config.educationMatchWeight * educationMatch // console.log(`Job ${job.jobTitle}工作经验匹配度: ${experiencenMatch}`); if (this.log) { console.log( `Job ${job.jobTitle} 标题相似度 ${maxSimilarity} 薪资匹配度: ${salaryMatch}学历匹配度: ${educationMatch} 区域匹配度: ${areaMatch} 综合匹配度: ${overallMatch.toFixed(2)}` ); } // 设置阈值进行岗位匹配判断 const threshold = this.config.thresholdVal; return { overallMatch: (overallMatch.toFixed(2) * 100) + '%', data: resume, maxSimilarity, salaryMatch, educationMatch, areaMatch } } calculationMatchingDegree(job) { // 计算职位标题相似度 // console.log(this.userTitle, job.jobTitle) // const titleSimilarity = stringSimilarity.compareTwoStrings(this.userTitle, job.jobTitle); let jobT = null if (job.jobCategory) { jobT = this.calculateBestJobCategoryMatch(this.userTitle, job.jobCategory); } else { jobT = this.calculateBestJobMatch(this.userTitle, job.jobTitle); } const { bestMatchJobTitle, maxSimilarity } = jobT // 计算薪资匹配度 const salaryMatch = this.calculateSalaryMatch(this.userSalaryMin, this.userSalaryMax, job.minSalary, job .maxSalary); // 计算区域匹配度 const areaMatch = this.calculateAreaMatch(this.userArea, job.jobLocationAreaCode); // 计算学历匹配度 const educationMatch = this.calculateEducationMatch(this.userEducation, job.education); // 计算工作经验匹配度 // const experiencenMatch = this.calculateExperienceMatch2(this.userExperience, job.experience); // 综合匹配度 = 0.4 * 职位相似度 + 0.2 * 薪资匹配度 + 0.1 * 区域匹配度 + 0.2 * 学历匹配度 + 0.1 * 工作经验匹配度 const overallMatch = this.config.titleSimilarityWeight * maxSimilarity + this.config.salaryMatchWeight * salaryMatch + this.config.areaMatchWeight * areaMatch + this.config.educationMatchWeight * educationMatch // console.log(`Job ${job.jobTitle}工作经验匹配度: ${experiencenMatch}`); if (this.log) { console.log( `Job ${job.jobTitle} 标题相似度 ${maxSimilarity} 薪资匹配度: ${salaryMatch}学历匹配度: ${educationMatch} 区域匹配度: ${areaMatch} 综合匹配度: ${overallMatch.toFixed(2)}` ); } // 设置阈值进行岗位匹配判断 const threshold = this.config.thresholdVal; if (overallMatch > threshold) { return { overallMatch: (overallMatch.toFixed(2) * 100) + '%', data: job, maxSimilarity, salaryMatch, educationMatch, areaMatch } } } // 根据用户年龄推算工作经验年限区间 getUserExperience(age) { if (age = 0) { // 30以下 return { min: 0, max: 5 }; } else if (age <= 1) { // 40以下 return { min: 5, max: 10 }; } else if (age <= 2) { // 50以下 return { min: 10, max: 20 }; } else { // 50以上 return { min: 20, max: 40 }; } } // 计算经验匹配度 calculateExperienceMatch2(userExperience, jobExperience) { const jobExperienceRange = this.mapJobExperience(jobExperience); if (userExperience.min <= jobExperienceRange.max && userExperience.max >= jobExperienceRange.min) { return 1; } if ( (userExperience.min <= jobExperienceRange.max && userExperience.max > jobExperienceRange.min) || (userExperience.max >= jobExperienceRange.min && userExperience.min < jobExperienceRange.max) ) { return 0.5; // 部分匹配 } return 0; // 不匹配 } // 映射岗位经验要求到工作经验年限区间 mapJobExperience(jobExperience) { const experienceMapping = { "1": { min: 0, max: 0 }, "2": { min: 0, max: 1 }, "3": { min: 0, max: 1 }, "4": { min: 1, max: 3 }, "5": { min: 3, max: 5 }, "6": { min: 5, max: 10 }, "7": { min: 10, max: 20 }, "8": { min: 0, max: 40 } }; return experienceMapping[jobExperience]; } // 计算工作经验匹配度 calculateExperiencenMatch(userExperience, jobExperience) { if (userExperience === jobExperience) { return 1; } else if (userExperience > jobExperience) { return 0.75; } else { return 0; } } calculateSalaryMatch(userMin, userMax, jobMin, jobMax) { const isMinMatch = userMin >= jobMin && userMin <= jobMax; const isMaxMatch = userMax >= jobMin && userMax <= jobMax; if (isMinMatch || isMaxMatch) { return 1; } const minDifference = Math.abs(userMin - jobMin); const maxDifference = Math.abs(userMax - jobMax); if (minDifference > 3000 && maxDifference > 3000) { return 0; } return 0.5; // 部分匹配 } // 计算区域匹配度 calculateAreaMatch(userArea, jobArea) { return userArea === jobArea ? 1 : 0.5; } calculateBestJobCategoryMatch(userJobTitles, jobTitle) { let maxSimilarity = 0; let bestMatchJobTitle = ''; for (let i = 0; i < userJobTitles.length; i++) { let userTitle = userJobTitles[i]; if (userTitle === jobTitle) { maxSimilarity = 1; bestMatchJobTitle = userTitle; break } } return { bestMatchJobTitle, maxSimilarity }; } // 计算职位匹配度 calculateBestJobMatch(userJobTitles, jobTitle) { let maxSimilarity = 0; let bestMatchJobTitle = ''; userJobTitles.forEach((userTitle) => { const userSegments = segmentText(userTitle); const jobSegments = segmentText(jobTitle); // 比较分词的交集,计算匹配度 // const intersection = userSegments.filter(segment => jobSegments.includes(segment)); // const similarity = intersection.length / userSegments.length; // 计算匹配度 // 计算匹配度 const similarity = calculateMatchScore(userSegments, jobSegments) // 记录匹配度最高的职位 if (similarity > maxSimilarity) { maxSimilarity = similarity; bestMatchJobTitle = userTitle; } }); return { bestMatchJobTitle, maxSimilarity }; } // 计算学历匹配度 calculateEducationMatch(userEducation, jobEducation) { if (userEducation === jobEducation) { return 1; } else if (userEducation > jobEducation) { return 1; } else { return 0; } } } const similarityJobs = new CsimilarityJobs() export default similarityJobs