const BaseTask = require('./baseTask'); const db = require('../../dbProxy'); const config = require('../infrastructure/config'); /** * 自动搜索职位任务 * 定期搜索符合条件的职位并保存到数据库 */ class AutoSearchTask extends BaseTask { constructor() { super('auto_search', { defaultInterval: 60, // 默认60分钟 defaultPriority: 8, // 高优先级(比投递高,先搜索后投递) requiresLogin: true, // 需要登录 conflictsWith: [ // 与这些任务冲突 'auto_deliver', // 投递任务 'auto_active_account' // 活跃账号任务 ] }); } /** * 验证任务参数 */ validateParams(params) { if (!params.keyword && !params.jobType) { return { valid: false, reason: '缺少必要参数: keyword 或 jobType' }; } return { valid: true }; } /** * 获取任务名称 */ getTaskName(params) { return `自动搜索 - ${params.keyword || params.jobType || '默认'}`; } /** * 执行自动搜索任务 */ async execute(sn_code, params) { console.log(`[自动搜索] 设备 ${sn_code} 开始执行搜索任务`); // 1. 获取账号信息 const account = await this.getAccountInfo(sn_code); if (!account) { throw new Error(`账号 ${sn_code} 不存在`); } // 2. 获取搜索配置 const searchConfig = this.parseSearchConfig(account.search_config); // 3. 检查日搜索限制 const dailyLimit = config.dailyLimits.maxSearch || 20; const todaySearched = await this.getTodaySearchCount(sn_code); if (todaySearched >= dailyLimit) { throw new Error(`今日搜索已达上限 (${todaySearched}/${dailyLimit})`); } // 4. 执行搜索(这里需要调用实际的搜索逻辑) const searchResult = { success: true, keyword: params.keyword || account.keyword, pageCount: searchConfig.page_count || 3, jobsFound: 0, // 实际搜索到的职位数 jobsSaved: 0 // 保存到数据库的职位数 }; console.log(`[自动搜索] 设备 ${sn_code} 搜索完成,找到 ${searchResult.jobsFound} 个职位`); return searchResult; } /** * 获取账号信息 */ async getAccountInfo(sn_code) { const { pla_account } = db.models; const account = await pla_account.findOne({ where: { sn_code: sn_code, is_delete: 0, is_enabled: 1 } }); return account ? account.toJSON() : null; } /** * 解析搜索配置 */ parseSearchConfig(search_config) { if (typeof search_config === 'string') { try { search_config = JSON.parse(search_config); } catch (e) { search_config = {}; } } return { search_interval: search_config?.search_interval || 60, page_count: search_config?.page_count || 3, city: search_config?.city || '', salary_range: search_config?.salary_range || '', experience: search_config?.experience || '', education: search_config?.education || '', time_range: search_config?.time_range || null }; } /** * 获取今日已搜索数量 */ async getTodaySearchCount(sn_code) { const { task_status } = db.models; const Sequelize = require('sequelize'); const today = new Date(); today.setHours(0, 0, 0, 0); const count = await task_status.count({ where: { sn_code: sn_code, taskType: 'auto_search', status: 'completed', endTime: { [Sequelize.Op.gte]: today } } }); return count; } /** * 添加搜索任务到队列 */ async addToQueue(sn_code, taskQueue, customParams = {}) { const now = new Date(); console.log(`[自动搜索] ${now.toLocaleString()} 尝试为设备 ${sn_code} 添加任务`); try { // 1. 获取账号信息 const account = await this.getAccountInfo(sn_code); if (!account) { console.log(`[自动搜索] 账号 ${sn_code} 不存在或未启用`); return { success: false, reason: '账号不存在或未启用' }; } // 2. 检查是否开启了自动搜索 if (!account.auto_search) { console.log(`[自动搜索] 设备 ${sn_code} 未开启自动搜索`); return { success: false, reason: '未开启自动搜索' }; } // 3. 获取搜索配置 const searchConfig = this.parseSearchConfig(account.search_config); // 4. 检查时间范围 if (searchConfig.time_range) { const timeCheck = this.checkTimeRange(searchConfig.time_range); if (!timeCheck.allowed) { console.log(`[自动搜索] 设备 ${sn_code} ${timeCheck.reason}`); return { success: false, reason: timeCheck.reason }; } } // 5. 执行所有层级的冲突检查 const conflictCheck = await this.canExecuteTask(sn_code, taskQueue); if (!conflictCheck.allowed) { return { success: false, reason: conflictCheck.reason }; } // 6. 检查搜索间隔 const intervalCheck = await this.checkExecutionInterval( sn_code, searchConfig.search_interval ); if (!intervalCheck.allowed) { console.log(`[自动搜索] 设备 ${sn_code} ${intervalCheck.reason}`); return { success: false, reason: intervalCheck.reason }; } // 7. 构建任务参数 const taskParams = { keyword: account.keyword || '', jobType: account.job_type || '', platform: account.platform_type || 'boss', pageCount: searchConfig.page_count || 3, city: searchConfig.city || '', salaryRange: searchConfig.salary_range || '', ...customParams }; // 8. 验证参数 const validation = this.validateParams(taskParams); if (!validation.valid) { return { success: false, reason: validation.reason }; } // 9. 添加任务到队列 await taskQueue.addTask(sn_code, { taskType: this.taskType, taskName: this.getTaskName(taskParams), taskParams: taskParams, priority: this.config.defaultPriority }); console.log(`[自动搜索] 已为设备 ${sn_code} 添加搜索任务,间隔: ${searchConfig.search_interval} 分钟`); return { success: true }; } catch (error) { console.error(`[自动搜索] 添加任务失败:`, error); return { success: false, reason: error.message }; } finally { // 统一释放任务锁 this.releaseTaskLock(sn_code); } } } // 导出单例 module.exports = new AutoSearchTask();