This commit is contained in:
张成
2026-02-28 13:31:32 +08:00
parent dfd3119163
commit 58c9d64e55
6 changed files with 163 additions and 33 deletions

View File

@@ -85,8 +85,9 @@ class DeliverHandler extends BaseHandler {
// 5. 获取职位类型配置
const jobTypeConfig = await this.getJobTypeConfig(accountConfig.job_type_id);
// 6. 搜索职位列表
await this.searchJobs(sn_code, platform, keyword || accountConfig.keyword, pageCount, task.id);
// 6. 搜索职位列表(从 resume_info 取 deliver_tab_label 作为 tabLabel 下发给 get_job_list 切换期望 tab
const tabLabel = resume.deliver_tab_label || '';
await this.searchJobs(sn_code, platform, keyword || accountConfig.keyword, pageCount, task.id, tabLabel);
// 7. 从数据库获取待投递职位
const pendingJobs = await this.getPendingJobs(sn_code, platform, actualMaxCount * 3);
@@ -238,17 +239,22 @@ class DeliverHandler extends BaseHandler {
/**
* 搜索职位列表
* @param {string} tabLabel - 投递用期望标签文案,对应 resume_info.deliver_tab_labelget_job_list 会按此选择 tab
*/
async searchJobs(sn_code, platform, keyword, pageCount, taskId) {
async searchJobs(sn_code, platform, keyword, pageCount, taskId, tabLabel = '') {
const params = {
sn_code,
keyword,
platform,
pageCount
};
if (tabLabel != null && String(tabLabel).trim() !== '') {
params.tabLabel = String(tabLabel).trim();
}
const getJobListCommand = {
command_type: 'get_job_list',
command_name: 'get_job_list',
command_params: JSON.stringify({
sn_code,
keyword,
platform,
pageCount
}),
command_params: JSON.stringify(params),
priority: config.getTaskPriority('search_jobs') || 5
};
@@ -337,18 +343,22 @@ class DeliverHandler extends BaseHandler {
*/
async filterAndScoreJobs(jobs, resume, accountConfig, jobTypeConfig, filterConfig, recentCompanies) {
const scored = [];
const jobDesc = (j) => `${j.companyName || '?'} / ${j.jobTitle || '?'}`;
console.log(`[自动投递-过滤] 开始过滤与评分,待处理职位数: ${jobs.length}`);
for (const job of jobs) {
// 1. 过滤近期已投递的公司
if (job.companyName && recentCompanies.has(job.companyName)) {
console.log(`[自动投递] 跳过已投递公司: ${job.companyName}`);
console.log(`[自动投递-过滤] 步骤1-已投递公司 剔除: ${jobDesc(job)}`);
continue;
}
// 2. 使用 jobFilterEngine 过滤和评分
const filtered = await jobFilterEngine.filterJobs([job], filterConfig, resume);
if (filtered.length === 0) {
continue; // 不符合过滤条件
console.log(`[自动投递-过滤] 步骤2-jobFilterEngine 剔除: ${jobDesc(job)} (不满足过滤条件)`);
continue;
}
// 3. 使用原有的评分系统job_filter_service计算详细分数
@@ -371,21 +381,26 @@ class DeliverHandler extends BaseHandler {
const finalScore = scoreResult.totalScore + keywordBonus.score;
// 5. 只保留评分 >= 60 的职位
if (finalScore >= 60) {
scored.push({
...job,
matchScore: finalScore,
scoreDetails: {
...scoreResult.scores,
keywordBonus: keywordBonus.score
}
});
if (finalScore < 60) {
console.log(`[自动投递-过滤] 步骤5-评分不足(>=60) 剔除: ${jobDesc(job)} | 总分=${finalScore.toFixed(1)} (基础=${scoreResult.totalScore?.toFixed(1)}, 关键词奖励=${keywordBonus.score})`);
continue;
}
scored.push({
...job,
matchScore: finalScore,
scoreDetails: {
...scoreResult.scores,
keywordBonus: keywordBonus.score
}
});
console.log(`[自动投递-过滤] 通过: ${jobDesc(job)} | 总分=${finalScore.toFixed(1)}`);
}
// 按评分降序排序
scored.sort((a, b) => b.matchScore - a.matchScore);
console.log(`[自动投递-过滤] 结束: 原始=${jobs.length}, 通过=${scored.length}, 剔除=${jobs.length - scored.length}`);
return scored;
}

View File

@@ -59,16 +59,36 @@ class SearchHandler extends BaseHandler {
}
}
// 4. 创建搜索指令
// 4. 从 resume_info 取 deliver_tab_label下发给 get_job_list 用于切换期望 tab
const platformType = platform || accountConfig.platform_type || 'boss';
let tabLabel = '';
try {
const db = require('../../dbProxy');
const resume_info = db.getModel('resume_info');
const resume = await resume_info.findOne({
where: { sn_code, platform: platformType, isActive: true },
order: [['last_modify_time', 'DESC']],
attributes: ['deliver_tab_label']
});
if (resume && resume.deliver_tab_label) {
tabLabel = String(resume.deliver_tab_label).trim();
}
} catch (e) {
console.warn('[自动搜索] 读取 resume_info.deliver_tab_label 失败:', e.message);
}
const commandParams = {
sn_code,
keyword: keyword || accountConfig.keyword || '',
platform: platformType,
pageCount: pageCount || searchConfig.page_count || 3
};
if (tabLabel) commandParams.tabLabel = tabLabel;
const searchCommand = {
command_type: 'get_job_list',
command_name: 'get_job_list',
command_params: JSON.stringify({
sn_code,
keyword: keyword || accountConfig.keyword || '',
platform: platform || accountConfig.platform_type || 'boss',
pageCount: pageCount || searchConfig.page_count || 3
}),
command_params: JSON.stringify(commandParams),
priority: config.getTaskPriority('search_jobs') || 8
};

View File

@@ -22,21 +22,42 @@ class JobFilterEngine {
let filtered = [...jobs];
// 1. 薪资过滤
const beforeSalary = filtered.length;
filtered = this.filterBySalary(filtered, config);
const salaryRemoved = beforeSalary - filtered.length;
if (salaryRemoved > 0) {
console.log(`[jobFilterEngine] 步骤1-薪资过滤: 输入${beforeSalary} 输出${filtered.length} 剔除${salaryRemoved} (范围: ${config.min_salary ?? 0}-${config.max_salary ?? 0}K)`);
}
// 2. 关键词过滤
const beforeKeywords = filtered.length;
filtered = this.filterByKeywords(filtered, config);
const keywordsRemoved = beforeKeywords - filtered.length;
if (keywordsRemoved > 0) {
console.log(`[jobFilterEngine] 步骤2-关键词过滤: 输入${beforeKeywords} 输出${filtered.length} 剔除${keywordsRemoved} (排除: ${(config.exclude_keywords || []).join(',') || '无'} 包含: ${(config.filter_keywords || []).join(',') || '无'})`);
}
// 3. 公司活跃度过滤
if (config.filter_inactive_companies) {
const beforeActivity = filtered.length;
filtered = await this.filterByCompanyActivity(filtered, config.company_active_days || 7);
const activityRemoved = beforeActivity - filtered.length;
if (activityRemoved > 0) {
console.log(`[jobFilterEngine] 步骤3-公司活跃度过滤: 输入${beforeActivity} 输出${filtered.length} 剔除${activityRemoved}`);
}
}
// 4. 去重(同一公司、同一职位名称)
if (config.deduplicate) {
const beforeDedup = filtered.length;
filtered = this.deduplicateJobs(filtered);
const dedupRemoved = beforeDedup - filtered.length;
if (dedupRemoved > 0) {
console.log(`[jobFilterEngine] 步骤4-去重: 输入${beforeDedup} 输出${filtered.length} 剔除${dedupRemoved}`);
}
}
console.log(`[jobFilterEngine] filterJobs 结束: 原始${jobs.length} 通过${filtered.length} 总剔除${jobs.length - filtered.length}`);
return filtered;
}