flat:AI+
This commit is contained in:
166
utils/jobAnalyzer.js
Normal file
166
utils/jobAnalyzer.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* 岗位数据分析模块
|
||||
*/
|
||||
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
|
Reference in New Issue
Block a user