Files
ks-app-employment-service/utils/jobAnalyzer.js
史典卓 0216f6053a flat:AI+
2025-03-28 15:19:42 +08:00

166 lines
5.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 岗位数据分析模块
*/
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