1
This commit is contained in:
@@ -2,10 +2,12 @@ const BaseHandler = require('./baseHandler');
|
||||
const ConfigManager = require('../services/configManager');
|
||||
const command = require('../core/command');
|
||||
const config = require('../infrastructure/config');
|
||||
const chatManager = require('../../job/managers/chatManager');
|
||||
const db = require('../../dbProxy');
|
||||
|
||||
/**
|
||||
* 自动沟通处理器
|
||||
* 负责自动回复HR消息
|
||||
* 负责自动回复 HR 消息。auto_chat 是任务,其下按指令执行:获取列表 → 获取详情 →(若需回复)发送消息
|
||||
*/
|
||||
class ChatHandler extends BaseHandler {
|
||||
/**
|
||||
@@ -24,64 +26,153 @@ class ChatHandler extends BaseHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行沟通逻辑
|
||||
* 执行沟通逻辑:先下发「获取列表」指令,再对每个会话下发「获取详情」→(若需回复)「发送消息」指令
|
||||
*/
|
||||
async doChat(task) {
|
||||
const { sn_code, taskParams } = task;
|
||||
const { platform = 'boss' } = taskParams;
|
||||
const platform = taskParams.platform || 'boss';
|
||||
|
||||
console.log(`[自动沟通] 开始 - 设备: ${sn_code}`);
|
||||
|
||||
// 1. 获取账户配置
|
||||
const accountConfig = await this.getAccountConfig(sn_code, ['platform_type', 'chat_strategy']);
|
||||
|
||||
if (!accountConfig) {
|
||||
return {
|
||||
chatCount: 0,
|
||||
message: '未找到账户配置'
|
||||
};
|
||||
return { chatCount: 0, message: '未找到账户配置' };
|
||||
}
|
||||
|
||||
// 2. 解析沟通策略配置
|
||||
const chatStrategy = ConfigManager.parseChatStrategy(accountConfig.chat_strategy);
|
||||
|
||||
// 3. 检查沟通时间范围
|
||||
const timeRange = ConfigManager.getTimeRange(chatStrategy);
|
||||
if (timeRange) {
|
||||
const timeRangeValidator = require('../services/timeRangeValidator');
|
||||
const timeCheck = timeRangeValidator.checkTimeRange(timeRange);
|
||||
|
||||
if (!timeCheck.allowed) {
|
||||
return {
|
||||
chatCount: 0,
|
||||
message: timeCheck.reason
|
||||
};
|
||||
return { chatCount: 0, message: timeCheck.reason };
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 创建自动沟通 AI 指令(内部会先获取列表,再获取详情并自动回复)
|
||||
const chatCommand = {
|
||||
command_type: 'auto_chat_ai',
|
||||
command_name: 'auto_chat_ai',
|
||||
command_params: {
|
||||
platform: platform || accountConfig.platform_type || 'boss',
|
||||
pageCount: chatStrategy.page_count || 3
|
||||
},
|
||||
const platform_type = platform || accountConfig.platform_type || 'boss';
|
||||
const page_count = chatStrategy.page_count || 3;
|
||||
|
||||
// 1. 下发「获取列表」指令
|
||||
const list_command = {
|
||||
command_type: 'get_chat_list',
|
||||
command_name: '获取聊天列表',
|
||||
command_params: { platform: platform_type, pageCount: page_count },
|
||||
priority: config.getTaskPriority('auto_chat') || 6
|
||||
};
|
||||
const list_exec = await command.executeCommands(task.id, [list_command], this.mqttClient);
|
||||
const list_result = list_exec?.results?.[0]?.result;
|
||||
const friend_list = Array.isArray(list_result?.friendList) ? list_result.friendList : [];
|
||||
|
||||
// 5. 执行指令(任务队列会保证该设备内串行执行,不并发下发指令)
|
||||
const exec_result = await command.executeCommands(task.id, [chatCommand], this.mqttClient);
|
||||
const first = exec_result && Array.isArray(exec_result.results) && exec_result.results[0]
|
||||
? exec_result.results[0].result || {}
|
||||
: {};
|
||||
if (friend_list.length === 0) {
|
||||
console.log(`[自动沟通] 完成 - 设备: ${sn_code},无会话`);
|
||||
return { chatCount: 0, message: '没有可沟通的会话', detail: { total_contacts: 0 } };
|
||||
}
|
||||
|
||||
console.log(`[自动沟通] 完成 - 设备: ${sn_code}`);
|
||||
let replied_count = 0;
|
||||
const details = [];
|
||||
|
||||
// 2. 将会话列表同步到聊天记录表(按会话维度做一条摘要记录)
|
||||
try {
|
||||
const chatRecordsModel = db.getModel('chat_records');
|
||||
for (const friend of friend_list) {
|
||||
const friend_id = friend.friendId;
|
||||
if (!friend_id) continue;
|
||||
|
||||
const encryptId = friend.encryptFriendId || '';
|
||||
|
||||
const existing = await chatRecordsModel.findOne({
|
||||
where: {
|
||||
sn_code,
|
||||
platform: platform_type,
|
||||
encryptBossId: encryptId,
|
||||
direction: 'received',
|
||||
chatType: 'session'
|
||||
}
|
||||
});
|
||||
|
||||
const baseData = {
|
||||
sn_code,
|
||||
platform: platform_type,
|
||||
encryptBossId: encryptId,
|
||||
jobTitle: friend.jobName || '',
|
||||
companyName: friend.brandName || '',
|
||||
hrName: friend.name || '',
|
||||
hrTitle: friend.bossTitle || '',
|
||||
hrId: String(friend_id),
|
||||
chatType: 'session',
|
||||
direction: 'received',
|
||||
content: '',
|
||||
contentType: 'text',
|
||||
receiveTime: friend.updateTime ? new Date(friend.updateTime) : new Date()
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
await existing.update(baseData);
|
||||
} else {
|
||||
await chatRecordsModel.create(baseData);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[自动沟通] 同步聊天会话列表到 chat_records 失败:', e.message);
|
||||
}
|
||||
|
||||
// 3. 对每个会话:下发「获取详情」→ 若需回复则下发「发送消息」
|
||||
for (const friend of friend_list) {
|
||||
const friend_id = friend.friendId;
|
||||
if (!friend_id) continue;
|
||||
|
||||
try {
|
||||
const detail_command = {
|
||||
command_type: 'get_chat_detail',
|
||||
command_name: '获取聊天详情',
|
||||
command_params: { platform: platform_type, friendId: friend_id },
|
||||
priority: config.getTaskPriority('auto_chat') || 6
|
||||
};
|
||||
const detail_exec = await command.executeCommands(task.id, [detail_command], this.mqttClient);
|
||||
const detail = detail_exec?.results?.[0]?.result;
|
||||
|
||||
const decision = await chatManager.getReplyContentFromDetail(detail || {});
|
||||
|
||||
if (decision.replied && decision.reply_content) {
|
||||
const send_command = {
|
||||
command_type: 'send_chat_message',
|
||||
command_name: '发送聊天消息',
|
||||
command_params: {
|
||||
platform: platform_type,
|
||||
friendId: friend_id,
|
||||
messages: [{ type: 'text', content: decision.reply_content }],
|
||||
chatType: 'reply'
|
||||
},
|
||||
priority: config.getTaskPriority('auto_chat') || 6
|
||||
};
|
||||
await command.executeCommands(task.id, [send_command], this.mqttClient);
|
||||
replied_count++;
|
||||
}
|
||||
|
||||
details.push({
|
||||
friendId: friend_id,
|
||||
replied: !!decision.replied,
|
||||
reason: decision.reason || null
|
||||
});
|
||||
} catch (err) {
|
||||
details.push({
|
||||
friendId: friend_id,
|
||||
replied: false,
|
||||
reason: err.message || '处理失败'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[自动沟通] 完成 - 设备: ${sn_code},会话 ${friend_list.length},回复 ${replied_count}`);
|
||||
|
||||
return {
|
||||
chatCount: first.replied_count || 0,
|
||||
message: first.message || '自动沟通完成',
|
||||
detail: first
|
||||
chatCount: replied_count,
|
||||
message: '自动沟通完成',
|
||||
detail: {
|
||||
total_contacts: friend_list.length,
|
||||
replied_count,
|
||||
details
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,16 +279,22 @@ class DeliverHandler extends BaseHandler {
|
||||
*/
|
||||
mergeFilterConfig(deliverConfig, filterRules, jobTypeConfig) {
|
||||
// 排除关键词
|
||||
const jobTypeExclude = jobTypeConfig?.excludeKeywords
|
||||
const rawJobTypeExclude = jobTypeConfig?.excludeKeywords
|
||||
? ConfigManager.parseConfig(jobTypeConfig.excludeKeywords, [])
|
||||
: [];
|
||||
|
||||
const deliverExclude = ConfigManager.getExcludeKeywords(deliverConfig);
|
||||
const filterExclude = filterRules.excludeKeywords || [];
|
||||
const jobTypeExclude = Array.isArray(rawJobTypeExclude) ? rawJobTypeExclude : [];
|
||||
|
||||
const deliverExcludeRaw = ConfigManager.getExcludeKeywords(deliverConfig);
|
||||
const deliverExclude = Array.isArray(deliverExcludeRaw) ? deliverExcludeRaw : [];
|
||||
const filterExcludeRaw = filterRules.excludeKeywords || [];
|
||||
const filterExclude = Array.isArray(filterExcludeRaw) ? filterExcludeRaw : [];
|
||||
|
||||
// 过滤关键词
|
||||
const deliverFilter = ConfigManager.getFilterKeywords(deliverConfig);
|
||||
const filterKeywords = filterRules.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
|
||||
|
||||
Reference in New Issue
Block a user