From 21fe005c1992370a15a6a8aeed6410489400c2aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Wed, 8 Apr 2026 14:09:26 +0800 Subject: [PATCH] 1 --- .../src/views/account/pla_account_detail.vue | 9 ++ admin/src/views/account/pla_account_edit.vue | 10 ++ api/middleware/job/managers/jobManager.js | 137 ++++-------------- .../schedule/handlers/deliverHandler.js | 35 +---- .../schedule/handlers/searchHandler.js | 10 +- .../schedule/services/configManager.js | 1 + api/services/pla_account_service.js | 11 +- 7 files changed, 62 insertions(+), 151 deletions(-) diff --git a/admin/src/views/account/pla_account_detail.vue b/admin/src/views/account/pla_account_detail.vue index b0646be..9f6f3a4 100644 --- a/admin/src/views/account/pla_account_detail.vue +++ b/admin/src/views/account/pla_account_detail.vue @@ -229,6 +229,12 @@ +
+ 同公司重复投递间隔(天): + {{ deliverConfig.repeat_deliver_days != null ? deliverConfig.repeat_deliver_days : '-' }} +
+ +
过滤关键词: {{ deliverConfig.filter_keywords || '-' }} @@ -560,6 +566,7 @@ export default { max_salary: 0, page_count: 3, max_deliver: 10, + repeat_deliver_days: 30, filter_keywords: '', exclude_keywords: '' }, @@ -908,6 +915,7 @@ export default { max_salary: deliverConfig.max_salary || 0, page_count: deliverConfig.page_count || 3, max_deliver: deliverConfig.max_deliver || 10, + repeat_deliver_days: deliverConfig.repeat_deliver_days != null ? deliverConfig.repeat_deliver_days : 30, filter_keywords: Array.isArray(deliverConfig.filter_keywords) ? deliverConfig.filter_keywords.join(',') : (deliverConfig.filter_keywords || ''), @@ -926,6 +934,7 @@ export default { max_salary: 0, page_count: 3, max_deliver: 10, + repeat_deliver_days: 30, filter_keywords: '', exclude_keywords: '', deliver_start_time: '09:00', diff --git a/admin/src/views/account/pla_account_edit.vue b/admin/src/views/account/pla_account_edit.vue index 3610813..9aa3990 100644 --- a/admin/src/views/account/pla_account_edit.vue +++ b/admin/src/views/account/pla_account_edit.vue @@ -148,6 +148,9 @@ + + + } 岗位列表 */ async get_job_list(sn_code, mqttClient, params = {}) { - const { - keyword: paramKeyword = '', - platform = 'boss', + const { + platform = 'boss', pageCount = 3, city = '', cityName = '', @@ -439,77 +439,29 @@ class JobManager { financingStage = '', page = 1, pageSize = 20, - tabLabel, - tabIndex, - job_type_id + tabLabel } = params; - // 推荐列表实际按期望 tab 拉取,入库 keyword 应与「职位来源」一致:显式 keyword > deliver_tab_label > 空(不再默认「前端」) - let keyword = paramKeyword != null && String(paramKeyword).trim() !== '' - ? String(paramKeyword).trim() - : ''; - if (!keyword && tabLabel != null && String(tabLabel).trim() !== '') { - keyword = String(tabLabel).trim(); - } + // 入库用:可与前端一致带 keyword;设备端只收 pageCount + tabLabel(与 Electron get_job_list 一致) + const keyword = String(params.keyword || '').trim() || String(tabLabel || '').trim(); - // 仅当调用方显式传入筛选/分页字段时才走多条件分支(避免 page/pageSize 默认值把简单拉列表永远判成「多条件」) - const hasMultiParams = Boolean( - (params.city != null && params.city !== '') || - (params.cityName != null && params.cityName !== '') || - (params.salary != null && params.salary !== '') || - (params.experience != null && params.experience !== '') || - (params.education != null && params.education !== '') || - (params.industry != null && params.industry !== '') || - (params.companySize != null && params.companySize !== '') || - (params.financingStage != null && params.financingStage !== '') || - params.page !== undefined || - params.pageSize !== undefined - ); + const multiKeys = ['city', 'cityName', 'salary', 'experience', 'education', 'industry', 'companySize', 'financingStage']; + const hasMultiParams = multiKeys.some((k) => params[k]) || params.page !== undefined || params.pageSize !== undefined; - /** 期望 tab 与职位类型需原样带给设备端 get_job_list,否则不会切换 .c-expect-select 标签 */ - const appendExpectTabToData = (data) => { - if (tabLabel != null && String(tabLabel).trim() !== '') { - data.tabLabel = String(tabLabel).trim(); - } - if (tabIndex !== undefined && tabIndex !== null && String(tabIndex).trim() !== '') { - const ti = Number(tabIndex); - if (!Number.isNaN(ti)) { - data.tabIndex = ti; - } - } - if (job_type_id != null && job_type_id !== '') { - data.job_type_id = job_type_id; - } - return data; - }; + const devicePayload = () => ({ + pageCount, + ...(String(tabLabel || '').trim() ? { tabLabel: String(tabLabel).trim() } : {}) + }); if (hasMultiParams) { // 使用多条件搜索逻辑 console.log(`[工作管理] 开始多条件搜索设备 ${sn_code} 的职位,关键词: ${keyword}, 城市: ${cityName || city}`); - - // 构建完整的搜索参数对象 - const searchData = appendExpectTabToData({ - keyword, - pageCount - }); - - // 添加可选搜索条件 - if (city) searchData.city = city; - if (cityName) searchData.cityName = cityName; - if (salary) searchData.salary = salary; - if (experience) searchData.experience = experience; - if (education) searchData.education = education; - if (industry) searchData.industry = industry; - if (companySize) searchData.companySize = companySize; - if (financingStage) searchData.financingStage = financingStage; - if (page) searchData.page = page; - if (pageSize) searchData.pageSize = pageSize; // 通过MQTT指令获取岗位列表(保持action不变,前端已使用) const response = await mqttClient.publishAndWait(sn_code, { platform, action: "get_job_list", // 保持与原有get_job_list相同的action,前端已使用 - data: searchData + data: devicePayload() }); if (!response || response.code !== 200) { @@ -517,19 +469,7 @@ class JobManager { throw new Error('多条件搜索职位失败'); } - // 处理职位列表数据 - let jobs = []; - if (Array.isArray(response.data)) { - for (const item of response.data) { - if (item.data?.zpData?.jobList && Array.isArray(item.data.zpData.jobList)) { - jobs = jobs.concat(item.data.zpData.jobList); - } - } - } else if (response.data?.data?.zpData?.jobList) { - jobs = response.data.data.zpData.jobList || []; - } else if (response.data?.zpData?.jobList) { - jobs = response.data.zpData.jobList || []; - } + const jobs = this._jobListFromRecommendMonitorData(response.data); console.log(`[工作管理] 成功获取岗位数据,共 ${jobs.length} 个岗位`); @@ -551,11 +491,10 @@ class JobManager { // 简单搜索逻辑(保持原有逻辑) console.log(`[工作管理] 开始获取设备 ${sn_code} 的岗位列表,关键词: ${keyword}`); - // 通过MQTT指令获取岗位列表(须带上 tabLabel/tabIndex,与 schedule/deliver 下发一致) const response = await mqttClient.publishAndWait(sn_code, { platform, action: "get_job_list", - data: appendExpectTabToData({ keyword, pageCount }) + data: devicePayload() }); if (!response || response.code !== 200) { @@ -563,25 +502,7 @@ class JobManager { throw new Error('获取岗位列表失败'); } - // 处理职位列表数据:response.data 可能是数组(职位列表.json 格式)或单个对象 - let jobs = []; - - if (Array.isArray(response.data)) { - // 如果是数组格式(职位列表.json),遍历每个元素提取岗位数据 - for (const item of response.data) { - if (item.data?.zpData?.jobList && Array.isArray(item.data.zpData.jobList)) { - jobs = jobs.concat(item.data.zpData.jobList); - } - } - console.log(`[工作管理] 从 ${response.data.length} 个响应中提取岗位数据`); - } else if (response.data?.data?.zpData?.jobList) { - // 如果是单个对象格式,从 data.zpData.jobList 获取 - jobs = response.data.data.zpData.jobList || []; - } else if (response.data?.zpData?.jobList) { - // 兼容旧格式:直接从 zpData.jobList 获取 - jobs = response.data.zpData.jobList || []; - } - + const jobs = this._jobListFromRecommendMonitorData(response.data); console.log(`[工作管理] 成功获取岗位数据,共 ${jobs.length} 个岗位`); // 保存职位到数据库 diff --git a/api/middleware/schedule/handlers/deliverHandler.js b/api/middleware/schedule/handlers/deliverHandler.js index 56a2f4a..7b1e19f 100644 --- a/api/middleware/schedule/handlers/deliverHandler.js +++ b/api/middleware/schedule/handlers/deliverHandler.js @@ -89,17 +89,9 @@ class DeliverHandler extends BaseHandler { mqttClient: this.mqttClient }); - // 6. 下发 get_job_list 拉取职位列表(tabLabel 切换期望 tab,job_type_id 随指令下发供设备使用) + // 6. 下发 get_job_list(与前端一致:command 只带 pageCount + tabLabel,设备端不接收 keyword/job_type_id) const tabLabel = resume.deliver_tab_label || ''; - await this.getJobList( - sn_code, - platform, - pageCount, - task.id, - tabLabel, - accountConfig.job_type_id, - accountConfig.keyword - ); + await this.getJobList(sn_code, platform, pageCount, task.id, tabLabel); // 7. 从数据库获取待投递职位 const pendingJobs = await this.getPendingJobs(sn_code, platform, actualMaxCount * 3); @@ -114,8 +106,9 @@ class DeliverHandler extends BaseHandler { // 8. 合并过滤配置 const filterConfig = this.mergeFilterConfig(deliverConfig, filterRules, jobTypeConfig); - // 9. 过滤已投递的公司 - const recentCompanies = await this.getRecentDeliveredCompanies(sn_code, 30); + // 9. 过滤已投递的公司(repeat_deliver_days 由投递配置给出,缺省 30,上限 365) + const repeatDeliverDays = Math.min(365, Math.max(1, Number(deliverConfig.repeat_deliver_days) || 30)); + const recentCompanies = await this.getRecentDeliveredCompanies(sn_code, repeatDeliverDays); // 10. 过滤 + 评分 + 按 60 分阈值筛(入口在 jobFilterEngine,便于阅读) const filteredJobs = await jobFilterEngine.filterAndScoreJobsForDeliver( @@ -281,28 +274,16 @@ class DeliverHandler extends BaseHandler { } /** - * 下发 get_job_list 命令拉取职位列表 - * @param {string} tabLabel - 投递用期望标签文案,对应 resume_info.deliver_tab_label,get_job_list 会按此选择 tab - * @param {number} jobTypeId - 职位类型 ID,随指令下发供设备使用 + * 下发 get_job_list 命令拉取职位列表(command_params 与前端约定:pageCount、tabLabel + sn_code、platform) */ - async getJobList(sn_code, platform, pageCount, taskId, tabLabel = '', jobTypeId = null, accountKeyword = '') { + async getJobList(sn_code, platform, pageCount, taskId, tabLabel = '') { const label = tabLabel != null && String(tabLabel).trim() !== '' ? String(tabLabel).trim() : ''; - const accKw = accountKeyword != null && String(accountKeyword).trim() !== '' ? String(accountKeyword).trim() : ''; - // 与 jobManager 一致:优先期望职位文案,其次账户搜索词,用于 job_postings.keyword - const keyword = label || accKw; - const params = { sn_code, platform, pageCount, - keyword + ...(label ? { tabLabel: label } : {}) }; - if (label) { - params.tabLabel = label; - } - if (jobTypeId != null && jobTypeId !== '') { - params.job_type_id = jobTypeId; - } const getJobListCommand = { command_type: 'get_job_list', command_name: '获取职位列表', diff --git a/api/middleware/schedule/handlers/searchHandler.js b/api/middleware/schedule/handlers/searchHandler.js index 5450924..72dd4ad 100644 --- a/api/middleware/schedule/handlers/searchHandler.js +++ b/api/middleware/schedule/handlers/searchHandler.js @@ -77,18 +77,12 @@ class SearchHandler extends BaseHandler { console.warn('[自动搜索] 读取 resume_info.deliver_tab_label 失败:', e.message); } - let listKeyword = (keyword && String(keyword).trim()) || (accountConfig.keyword && String(accountConfig.keyword).trim()) || ''; - if (!listKeyword && tabLabel) { - listKeyword = tabLabel; - } - const commandParams = { sn_code, - keyword: listKeyword, platform: platformType, - pageCount: pageCount || searchConfig.page_count || 3 + pageCount: pageCount || searchConfig.page_count || 3, + ...(tabLabel ? { tabLabel } : {}) }; - if (tabLabel) commandParams.tabLabel = tabLabel; const searchCommand = { command_type: 'get_job_list', diff --git a/api/middleware/schedule/services/configManager.js b/api/middleware/schedule/services/configManager.js index 1e0cc36..188b3d8 100644 --- a/api/middleware/schedule/services/configManager.js +++ b/api/middleware/schedule/services/configManager.js @@ -43,6 +43,7 @@ class ConfigManager { max_salary: 0, // 最高薪资 page_count: 3, // 搜索页数 max_deliver: 10, // 最大投递数 + repeat_deliver_days: 30, // 多少天内已投递过的公司不再投递(与 getRecentDeliveredCompanies 一致) filter_keywords: [], // 过滤关键词 exclude_keywords: [], // 排除关键词 time_range: null, // 时间范围 diff --git a/api/services/pla_account_service.js b/api/services/pla_account_service.js index c8dc68b..1b75ba5 100644 --- a/api/services/pla_account_service.js +++ b/api/services/pla_account_service.js @@ -481,12 +481,11 @@ class PlaAccountService { ? { ...baseParams, ...commandParams } : baseParams; - // 如果有关键词相关的操作,添加关键词 - if (['search_jobs', 'get_job_list'].includes(commandTypeSnake) && account.keyword) { + if (commandTypeSnake === 'search_jobs' && account.keyword) { finalParams.keyword = account.keyword; } - // get_job_list 从 resume_info 取 deliver_tab_label 作为 tabLabel;入库 keyword 优先用期望职位而非写死 + // get_job_list:command 只约定 pageCount + tabLabel(与前端一致),入库 keyword 由 jobManager 用 tabLabel 推导 if (commandTypeSnake === 'get_job_list') { try { const resume_info = db.getModel('resume_info'); @@ -496,11 +495,7 @@ class PlaAccountService { attributes: ['deliver_tab_label'] }); if (resume && resume.deliver_tab_label) { - const tab = String(resume.deliver_tab_label).trim(); - finalParams.tabLabel = tab; - if (!finalParams.keyword || String(finalParams.keyword).trim() === '') { - finalParams.keyword = tab; - } + finalParams.tabLabel = String(resume.deliver_tab_label).trim(); } } catch (e) { console.warn('[pla_account_service] 读取 resume_info.deliver_tab_label 失败:', e.message);