127 lines
3.6 KiB
JavaScript
127 lines
3.6 KiB
JavaScript
/**
|
|
* 薪资解析工具
|
|
* 统一处理职位薪资和期望薪资的解析逻辑
|
|
*/
|
|
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;
|