/** * 薪资解析工具 * 统一处理职位薪资和期望薪资的解析逻辑 */ class SalaryParser { /** * 解析薪资范围字符串 * @param {string} salaryDesc - 薪资描述 (如 "15-20K", "8000-12000元") * @returns {{ min: number, max: number }} 薪资范围(单位:元) */ static parse(salaryDesc) { if (!salaryDesc || typeof salaryDesc !== 'string') { return { min: 0, max: 0 }; } // 尝试各种格式 return this.parseK(salaryDesc) || this.parseYuan(salaryDesc) || this.parseMixed(salaryDesc) || { min: 0, max: 0 }; } /** * 解析 K 格式薪资 (如 "15-20K", "8-12k") */ static parseK(desc) { const kMatch = desc.match(/(\d+)[-~](\d+)[kK千]/); if (kMatch) { return { min: parseInt(kMatch[1]) * 1000, max: parseInt(kMatch[2]) * 1000 }; } return null; } /** * 解析元格式薪资 (如 "8000-12000元", "15000-20000") */ static parseYuan(desc) { const yuanMatch = desc.match(/(\d+)[-~](\d+)元?/); if (yuanMatch) { return { min: parseInt(yuanMatch[1]), max: parseInt(yuanMatch[2]) }; } return null; } /** * 解析混合格式 (如 "8k-12000元") */ static parseMixed(desc) { const mixedMatch = desc.match(/(\d+)[kK千][-~](\d+)元?/); if (mixedMatch) { return { min: parseInt(mixedMatch[1]) * 1000, max: parseInt(mixedMatch[2]) }; } return null; } /** * 检查职位薪资是否在期望范围内 * @param {object} jobSalary - 职位薪资 { min, max } * @param {number} minExpected - 期望最低薪资 * @param {number} maxExpected - 期望最高薪资 */ static isWithinRange(jobSalary, minExpected, maxExpected) { if (!jobSalary || jobSalary.min === 0) { return true; // 无法判断时默认通过 } // 职位最高薪资 >= 期望最低薪资 if (minExpected > 0 && jobSalary.max < minExpected) { return false; } // 职位最低薪资 <= 期望最高薪资 if (maxExpected > 0 && jobSalary.min > maxExpected) { return false; } return true; } /** * 计算薪资匹配度(用于职位评分) * @param {object} jobSalary - 职位薪资 * @param {object} expectedSalary - 期望薪资 * @returns {number} 匹配度 0-1 */ static calculateMatch(jobSalary, expectedSalary) { if (!jobSalary || !expectedSalary || jobSalary.min === 0 || expectedSalary.min === 0) { return 0.5; // 无法判断时返回中性值 } const jobAvg = (jobSalary.min + jobSalary.max) / 2; const expectedAvg = (expectedSalary.min + expectedSalary.max) / 2; const diff = Math.abs(jobAvg - expectedAvg); const range = (jobSalary.max - jobSalary.min + expectedSalary.max - expectedSalary.min) / 2; // 差距越小,匹配度越高 return Math.max(0, 1 - diff / (range || 1)); } /** * 格式化薪资显示 * @param {object} salary - 薪资对象 { min, max } * @returns {string} 格式化字符串 */ static format(salary) { if (!salary || salary.min === 0) { return '面议'; } const minK = (salary.min / 1000).toFixed(0); const maxK = (salary.max / 1000).toFixed(0); return `${minK}-${maxK}K`; } } module.exports = SalaryParser;