Files
ks-app-employment-service/utils/jobAnalyzer.js

166 lines
5.0 KiB
JavaScript
Raw Permalink Normal View History

2025-03-28 15:19:42 +08:00
/**
* 岗位数据分析模块
*/
const jobAnalyzer = {
/**
* 清洗无效薪资数据
* @param {Array} jobs 原始岗位数据
* @returns {Array} 有效岗位数据
*/
cleanData: (jobs) => {
if (!Array.isArray(jobs)) return []
return jobs.filter(job =>
Number(job.minSalary) > 0 &&
Number(job.maxSalary) > 0
)
},
/**
* 执行完整分析流程
* @param {Array} jobs 原始岗位数据
* @param {Object} options 配置选项
* @returns {Object} 分析结果
*/
analyze: (jobs, options = {
verbose: false
}) => {
// 数据校验
if (!Array.isArray(jobs)) {
throw new Error('Invalid jobs data format')
}
// 数据清洗
const validJobs = jobAnalyzer.cleanData(jobs)
if (validJobs.length === 0) {
return {
warning: 'No valid job data available'
}
}
// 执行分析
const results = {
salary: jobAnalyzer.analyzeSalaries(validJobs),
categories: jobAnalyzer.countCategories(validJobs),
experience: jobAnalyzer.analyzeExperience(validJobs),
areas: jobAnalyzer.analyzeAreas(validJobs)
}
// 按需控制台输出
if (options.verbose) {
jobAnalyzer.printResults(results)
}
return results
},
/** 薪资分析 */
analyzeSalaries: (jobs) => {
const stats = jobs.reduce((acc, job) => {
acc.totalMin += job.minSalary
acc.totalMax += job.maxSalary
acc.highPay += (job.maxSalary >= 10000) ? 1 : 0
return acc
}, {
totalMin: 0,
totalMax: 0,
highPay: 0
})
return {
avgMin: Math.round(stats.totalMin / jobs.length),
avgMax: Math.round(stats.totalMax / jobs.length),
highPayRatio: Math.round((stats.highPay / jobs.length) * 100)
}
},
/** 岗位类别统计 */
countCategories: (jobs) => {
return jobs.reduce((map, job) => {
map[job.jobCategory] = (map[job.jobCategory] || 0) + 1
return map
}, {})
},
/** 经验要求分析 */
analyzeExperience: (jobs) => {
return jobs.reduce((stats, job) => {
const label = job.experIenceLabel || '未知'
stats[label] = (stats[label] || 0) + 1
return stats
}, {})
},
/** 地区分布分析 */
analyzeAreas: (jobs) => {
return jobs.reduce((map, job) => {
const area = job.jobLocationAreaCodeLabel || '未知'
map[area] = (map[area] || 0) + 1
return map
}, {})
},
/** 格式化输出结果 */
printResults: (results) => {
console.log('【高薪岗位分析】')
console.log(`- 平均月薪范围:${results.salary.avgMin}k ~ ${results.salary.avgMax}k`)
console.log(`- 月薪≥10k的岗位占比${results.salary.highPayRatio}%`)
console.log('\n【热门岗位类别】')
console.log(Object.entries(results.categories)
.sort((a, b) => b[1] - a[1])
.map(([k, v]) => `- ${k} (${v}个)`)
.join('\n'))
console.log('\n【经验要求分布】')
console.log(Object.entries(results.experience)
.map(([k, v]) => `- ${k}: ${v}`)
.join('\n'))
console.log('\n【工作地区分布】')
console.log(Object.entries(results.areas)
.sort((a, b) => b[1] - a[1])
.map(([k, v]) => `- ${k}: ${v}`)
.join('\n'))
},
/** 合并所有统计属性并添加类型前缀 */
_mergeAllStats: (results) => {
const merged = {}
// 合并岗位类别(添加前缀)
Object.entries(results.categories).forEach(([k, v]) => {
merged[`岗位:${k}`] = v
})
// 合并工作地区(添加前缀)
Object.entries(results.areas).forEach(([k, v]) => {
merged[`地区:${k}`] = v
})
// 合并经验要求(添加前缀)
Object.entries(results.experience).forEach(([k, v]) => {
merged[`经验:${k}`] = v
})
return merged
},
/** 全属性统一排序输出 */
printUnifiedResults: (results, options = {
log: false
}) => {
const mergedData = jobAnalyzer._mergeAllStats(results)
const sortedEntries = Object.entries(mergedData)
.sort((a, b) => b[1] - a[1])
if (options.log) {
// 格式化输出
console.log('【全维度排序分析】')
console.log(sortedEntries
.map(([k, v]) => `- ${k}: ${v}`)
.join('\n'))
}
return sortedEntries
}
}
export default jobAnalyzer