1
This commit is contained in:
@@ -30,7 +30,7 @@ class DeliverHandler extends BaseHandler {
|
||||
*/
|
||||
async doDeliver(task) {
|
||||
const { sn_code, taskParams } = task;
|
||||
const { keyword, platform = 'boss', pageCount = 3, maxCount = 10, filterRules = {} } = taskParams;
|
||||
const { keyword, platform = 'boss', pageCount = 3, maxCount = 10 } = taskParams;
|
||||
|
||||
console.log(`[自动投递] 开始 - 设备: ${sn_code}, 关键词: ${keyword}`);
|
||||
|
||||
@@ -103,8 +103,8 @@ class DeliverHandler extends BaseHandler {
|
||||
};
|
||||
}
|
||||
|
||||
// 8. 合并过滤配置
|
||||
const filterConfig = this.mergeFilterConfig(deliverConfig, filterRules, jobTypeConfig);
|
||||
// 8. 过滤配置仅来自职位类型 job_types(排除词 / 标题须含词等),不与账号投递配置、任务参数混用
|
||||
const filterConfig = this.mergeFilterConfig(jobTypeConfig);
|
||||
|
||||
// 9. 过滤已投递的公司(repeat_deliver_days 由投递配置给出,缺省 30,上限 365)
|
||||
const repeatDeliverDays = Math.min(365, Math.max(1, Number(deliverConfig.repeat_deliver_days) || 30));
|
||||
@@ -120,6 +120,9 @@ class DeliverHandler extends BaseHandler {
|
||||
recentCompanies
|
||||
);
|
||||
|
||||
// 本轮未进入「可投递」列表的待投递记录,标记为已过滤,避免长期停留在 pending
|
||||
await this.markFilteredJobsNotPassed(pendingJobs, filteredJobs, sn_code, platform);
|
||||
|
||||
const jobsToDeliver = filteredJobs.slice(0, actualMaxCount);
|
||||
|
||||
console.log(`[自动投递] 职位筛选完成 - 原始: ${pendingJobs.length}, 符合条件: ${filteredJobs.length}, 将投递: ${jobsToDeliver.length}`);
|
||||
@@ -294,6 +297,44 @@ class DeliverHandler extends BaseHandler {
|
||||
await command.executeCommands(taskId, [getJobListCommand], this.mqttClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本批中未通过过滤/评分的职位从 pending 更新为 filtered(仍 pending 的仅为通过筛选且等待下轮投递的)
|
||||
* @param {Array} pendingJobs - 本批拉取的待投递
|
||||
* @param {Array} filteredJobs - filterAndScoreJobsForDeliver 通过的结果(含 matchScore)
|
||||
*/
|
||||
async markFilteredJobsNotPassed(pendingJobs, filteredJobs, sn_code, platform) {
|
||||
if (!pendingJobs || pendingJobs.length === 0) {
|
||||
return;
|
||||
}
|
||||
const passedIds = new Set(
|
||||
(filteredJobs || []).map((j) => j.id).filter((id) => id != null)
|
||||
);
|
||||
const notPassedIds = pendingJobs
|
||||
.map((j) => (j && j.id != null ? j.id : null))
|
||||
.filter((id) => id != null && !passedIds.has(id));
|
||||
if (notPassedIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
const job_postings = db.getModel('job_postings');
|
||||
const { op } = db.models;
|
||||
try {
|
||||
const [n] = await job_postings.update(
|
||||
{ applyStatus: 'filtered' },
|
||||
{
|
||||
where: {
|
||||
id: { [op.in]: notPassedIds },
|
||||
sn_code,
|
||||
platform,
|
||||
applyStatus: 'pending'
|
||||
}
|
||||
}
|
||||
);
|
||||
console.log(`[自动投递] 不符合条件已标记 filtered: ${notPassedIds.length} 条(更新行数 ${n})`);
|
||||
} catch (e) {
|
||||
console.warn('[自动投递] 标记 filtered 失败:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待投递职位
|
||||
*/
|
||||
@@ -314,42 +355,42 @@ class DeliverHandler extends BaseHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并过滤配置
|
||||
* 自动投递过滤配置:仅使用 job_types(excludeKeywords、titleIncludeKeywords)
|
||||
* 薪资筛选不在此合并(min/max 为 0 表示不做薪资过滤);评分权重仍走 accountConfig.is_salary_priority
|
||||
*/
|
||||
mergeFilterConfig(deliverConfig, filterRules, jobTypeConfig) {
|
||||
// 排除关键词
|
||||
const rawJobTypeExclude = jobTypeConfig?.excludeKeywords
|
||||
? ConfigManager.parseConfig(jobTypeConfig.excludeKeywords, [])
|
||||
: [];
|
||||
mergeFilterConfig(jobTypeConfig) {
|
||||
const base = {
|
||||
exclude_keywords: [],
|
||||
filter_keywords: [],
|
||||
title_include_keywords: [],
|
||||
min_salary: 0,
|
||||
max_salary: 0,
|
||||
priority_weights: []
|
||||
};
|
||||
|
||||
const jobTypeExclude = Array.isArray(rawJobTypeExclude) ? rawJobTypeExclude : [];
|
||||
if (!jobTypeConfig) {
|
||||
return base;
|
||||
}
|
||||
|
||||
const deliverExcludeRaw = ConfigManager.getExcludeKeywords(deliverConfig);
|
||||
const deliverExclude = Array.isArray(deliverExcludeRaw) ? deliverExcludeRaw : [];
|
||||
const filterExcludeRaw = filterRules.excludeKeywords || [];
|
||||
const filterExclude = Array.isArray(filterExcludeRaw) ? filterExcludeRaw : [];
|
||||
if (jobTypeConfig.excludeKeywords) {
|
||||
try {
|
||||
const raw = jobTypeConfig.excludeKeywords;
|
||||
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||
base.exclude_keywords = Array.isArray(parsed) ? parsed.map((k) => String(k || '').trim()).filter(Boolean) : [];
|
||||
} catch (e) {
|
||||
base.exclude_keywords = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤关键词
|
||||
const deliverFilterRaw = ConfigManager.getFilterKeywords(deliverConfig);
|
||||
const deliverFilter = Array.isArray(deliverFilterRaw) ? deliverFilterRaw : [];
|
||||
const filterKeywordsRaw = filterRules.keywords || [];
|
||||
const filterKeywords = Array.isArray(filterKeywordsRaw) ? filterKeywordsRaw : [];
|
||||
|
||||
// 薪资范围
|
||||
const salaryRange = filterRules.minSalary || filterRules.maxSalary
|
||||
? { min: filterRules.minSalary || 0, max: filterRules.maxSalary || 0 }
|
||||
: ConfigManager.getSalaryRange(deliverConfig);
|
||||
|
||||
let title_include_keywords = [];
|
||||
if (jobTypeConfig && jobTypeConfig.titleIncludeKeywords != null) {
|
||||
if (jobTypeConfig.titleIncludeKeywords != null) {
|
||||
const v = jobTypeConfig.titleIncludeKeywords;
|
||||
if (Array.isArray(v)) {
|
||||
title_include_keywords = v.map((k) => String(k || '').trim()).filter(Boolean);
|
||||
base.title_include_keywords = v.map((k) => String(k || '').trim()).filter(Boolean);
|
||||
} else if (typeof v === 'string' && v.trim()) {
|
||||
try {
|
||||
const p = JSON.parse(v);
|
||||
if (Array.isArray(p)) {
|
||||
title_include_keywords = p.map((k) => String(k || '').trim()).filter(Boolean);
|
||||
base.title_include_keywords = p.map((k) => String(k || '').trim()).filter(Boolean);
|
||||
}
|
||||
} catch (e) {
|
||||
/* ignore */
|
||||
@@ -357,14 +398,7 @@ class DeliverHandler extends BaseHandler {
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
exclude_keywords: [...jobTypeExclude, ...deliverExclude, ...filterExclude],
|
||||
filter_keywords: filterKeywords.length > 0 ? filterKeywords : deliverFilter,
|
||||
title_include_keywords,
|
||||
min_salary: salaryRange.min,
|
||||
max_salary: salaryRange.max,
|
||||
priority_weights: ConfigManager.getPriorityWeights(deliverConfig)
|
||||
};
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user