166 lines
5.0 KiB
JavaScript
166 lines
5.0 KiB
JavaScript
/**
|
||
* 岗位数据分析模块
|
||
*/
|
||
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 |