diff --git a/admin/config/index.js b/admin/config/index.js index 34f2d94..0bc5e47 100644 --- a/admin/config/index.js +++ b/admin/config/index.js @@ -26,11 +26,11 @@ const baseConfig = { // 开发环境配置 const developmentConfig = { ...baseConfig, - // apiUrl: 'http://localhost:9097/admin_api/', - // uploadUrl: 'http://localhost:9097/admin_api/upload', + apiUrl: 'http://localhost:9097/admin_api/', + uploadUrl: 'http://localhost:9097/admin_api/upload', - apiUrl: 'https://work.light120.com/admin_api/', - uploadUrl: 'https://work.light120.com/admin_api/upload', + // apiUrl: 'https://work.light120.com/admin_api/', + // uploadUrl: 'https://work.light120.com/admin_api/upload', // 开发环境显示更多调试信息 debug: true } diff --git a/api/middleware/job/managers/chatManager.js b/api/middleware/job/managers/chatManager.js index d5bcf3b..c289034 100644 --- a/api/middleware/job/managers/chatManager.js +++ b/api/middleware/job/managers/chatManager.js @@ -1,423 +1,344 @@ -const aiServiceModule = require('../../../services/ai_service'); -const logs = require('../../logProxy'); - -// 实例化AI服务 -const aiService = aiServiceModule.getInstance(); +const ai_service_module = require('../../../services/ai_service'); +const ai_service = ai_service_module.getInstance(); /** - * 智能聊天管理模块 - * 负责聊天内容生成、发送策略和效果监控 + * 聊天管理模块 + * 负责沟通列表、沟通详情、发送消息等与设备端的 MQTT 指令对接 */ class ChatManager { - constructor() { - this.chatHistory = new Map(); // 聊天历史记录 - this.chatStrategies = new Map(); // 聊天策略配置 - this.effectStats = new Map(); // 聊天效果统计 - this.initDefaultStrategies(); - } - /** - * 初始化默认聊天策略 + * 解析沟通列表返回值,统一为 { friendList, foldText, ... } + * 设备端可能返回 code:0 + zpData 或 code:200 + data + * @private */ - initDefaultStrategies() { - // 初次打招呼策略 - this.chatStrategies.set('greeting', { - name: '初次打招呼', - description: '向HR发送初次打招呼消息', - template: 'greeting', - timing: 'immediate', - retryCount: 1, - retryInterval: 300000 // 5分钟 - }); - - // 面试邀约策略 - this.chatStrategies.set('interview', { - name: '面试邀约', - description: '发送面试邀约消息', - template: 'interview', - timing: 'after_greeting', - retryCount: 2, - retryInterval: 600000 // 10分钟 - }); - - // 跟进沟通策略 - this.chatStrategies.set('followup', { - name: '跟进沟通', - description: '跟进之前的沟通', - template: 'followup', - timing: 'after_interview', - retryCount: 1, - retryInterval: 86400000 // 24小时 - }); - } - - /** - * 生成聊天内容 - * @param {string} sn_code - 设备SN码 - * @param {object} jobInfo - 岗位信息 - * @param {object} resumeInfo - 简历信息 - * @param {string} chatType - 聊天类型 - * @param {object} context - 聊天上下文 - * @returns {Promise} 聊天内容 - */ - async generateChatContent(sn_code, jobInfo, resumeInfo, chatType = 'greeting', context = {}) { - console.log(`[聊天管理] 开始生成设备 ${sn_code} 的聊天内容,类型: ${chatType}`); - - // 获取聊天策略 - const strategy = this.chatStrategies.get(chatType); - if (!strategy) { - throw new Error(`未找到聊天类型 ${chatType} 的策略配置`); - } - - // 二期规划:AI 生成聊天内容暂时禁用,使用默认模板 - // const chatContent = await aiService.generateChatContent(jobInfo, resumeInfo, chatType); - // if (!chatContent.success) { - // console.error(`[聊天管理] AI生成聊天内容失败:`, chatContent.error); - // throw new Error(chatContent.error); - // } - - console.log(`[聊天管理] AI生成已禁用(二期规划),使用默认聊天模板`); - const chatContent = this.generateDefaultChatContent(jobInfo, resumeInfo, chatType); - - const result = { - sn_code: sn_code, - jobInfo: jobInfo, - chatType: chatType, - strategy: strategy, - content: chatContent.content, - context: context, - timestamp: Date.now() - }; - - // 记录聊天历史 - this.recordChatHistory(sn_code, result); - - console.log(`[聊天管理] 聊天内容生成成功:`, result); - return result; - } - - /** - * 发送聊天消息 - * @param {string} sn_code - 设备SN码 - * @param {object} mqttClient - MQTT客户端 - * @param {object} chatData - 聊天数据 - * @returns {Promise} 发送结果 - */ - async sendChatMessage(sn_code, mqttClient, chatData) { - console.log(`[聊天管理] 开始发送聊天消息到设备 ${sn_code}`); - - // 构建发送指令 - const sendData = { - platform: 'boss', - action: 'send_chat_message', - data: { - jobId: chatData.jobInfo.jobId, - companyId: chatData.jobInfo.companyId, - message: chatData.content, - chatType: chatData.chatType - } - }; - - // 发送MQTT指令 - const response = await mqttClient.publishAndWait(sn_code, sendData); - - if (!response || response.code !== 200) { - // 更新聊天状态 - this.updateChatStatus(sn_code, chatData, 'failed', response); - - console.error(`[聊天管理] 聊天消息发送失败:`, response); - throw new Error(response?.message || '聊天消息发送失败'); - } - - // 更新聊天状态 - this.updateChatStatus(sn_code, chatData, 'sent', response); - - // 记录效果统计 - this.recordChatEffect(sn_code, chatData, 'sent'); - - console.log(`[聊天管理] 聊天消息发送成功:`, response); - return response; - } - - /** - * 生成面试邀约 - * @param {string} sn_code - 设备SN码 - * @param {object} jobInfo - 岗位信息 - * @param {object} chatHistory - 聊天历史 - * @returns {Promise} 面试邀约内容 - */ - async generateInterviewInvitation(sn_code, jobInfo, chatHistory) { - console.log(`[聊天管理] 开始生成设备 ${sn_code} 的面试邀约`); - console.log(`[聊天管理] AI生成已禁用(二期规划),使用默认模板`); - - // 二期规划:AI 生成面试邀约暂时禁用,使用默认模板 - // const invitation = await aiService.generateInterviewInvitation(jobInfo, chatHistory); - // if (!invitation.success) { - // console.error(`[聊天管理] AI生成面试邀约失败:`, invitation.error); - // throw new Error(invitation.error); - // } - - const invitation = this.generateDefaultInterviewInvitation(jobInfo); - - const result = { - sn_code: sn_code, - jobInfo: jobInfo, - chatType: 'interview', - content: invitation.content, - timestamp: Date.now() - }; - - // 记录聊天历史 - this.recordChatHistory(sn_code, result); - - console.log(`[聊天管理] 面试邀约生成成功:`, result); - return result; - } - - /** - * 记录聊天历史 - * @param {string} sn_code - 设备SN码 - * @param {object} chatData - 聊天数据 - */ - recordChatHistory(sn_code, chatData) { - if (!this.chatHistory.has(sn_code)) { - this.chatHistory.set(sn_code, []); - } - - const history = this.chatHistory.get(sn_code); - history.push({ - ...chatData, - id: Date.now() + Math.random(), - status: 'generated' - }); - - // 限制历史记录数量 - if (history.length > 100) { - history.splice(0, history.length - 100); - } - } - - /** - * 更新聊天状态 - * @param {string} sn_code - 设备SN码 - * @param {object} chatData - 聊天数据 - * @param {string} status - 新状态 - * @param {object} response - 响应数据 - */ - updateChatStatus(sn_code, chatData, status, response = {}) { - if (!this.chatHistory.has(sn_code)) { - return; - } - - const history = this.chatHistory.get(sn_code); - const chatRecord = history.find(record => - record.timestamp === chatData.timestamp && - record.chatType === chatData.chatType - ); - - if (chatRecord) { - chatRecord.status = status; - chatRecord.response = response; - } - } - - /** - * 记录聊天效果 - * @param {string} sn_code - 设备SN码 - * @param {object} chatData - 聊天数据 - * @param {string} action - 动作类型 - */ - recordChatEffect(sn_code, chatData, action) { - if (!this.effectStats.has(sn_code)) { - this.effectStats.set(sn_code, { - totalSent: 0, - totalReplied: 0, - totalInterview: 0, - replyRate: 0, - interviewRate: 0, - lastUpdate: Date.now() - }); - } - - const stats = this.effectStats.get(sn_code); - - if (action === 'sent') { - stats.totalSent++; - } else if (action === 'replied') { - stats.totalReplied++; - } else if (action === 'interview') { - stats.totalInterview++; - } - - // 计算比率 - if (stats.totalSent > 0) { - stats.replyRate = (stats.totalReplied / stats.totalSent * 100).toFixed(2); - stats.interviewRate = (stats.totalInterview / stats.totalSent * 100).toFixed(2); - } - - stats.lastUpdate = Date.now(); - } - - /** - * 获取聊天历史 - * @param {string} sn_code - 设备SN码 - * @param {object} filters - 过滤条件 - * @returns {Array} 聊天历史 - */ - getChatHistory(sn_code, filters = {}) { - if (!this.chatHistory.has(sn_code)) { - return []; - } - - let history = this.chatHistory.get(sn_code); - - // 应用过滤条件 - if (filters.chatType) { - history = history.filter(record => record.chatType === filters.chatType); - } - - if (filters.status) { - history = history.filter(record => record.status === filters.status); - } - - if (filters.startTime) { - history = history.filter(record => record.timestamp >= filters.startTime); - } - - if (filters.endTime) { - history = history.filter(record => record.timestamp <= filters.endTime); - } - - // 按时间倒序排列 - return history.sort((a, b) => b.timestamp - a.timestamp); - } - - /** - * 获取聊天效果统计 - * @param {string} sn_code - 设备SN码 - * @returns {object} 效果统计 - */ - getChatEffectStats(sn_code) { - if (!this.effectStats.has(sn_code)) { - return { - totalSent: 0, - totalReplied: 0, - totalInterview: 0, - replyRate: 0, - interviewRate: 0, - lastUpdate: Date.now() - }; - } - - return this.effectStats.get(sn_code); - } - - /** - * 设置聊天策略 - * @param {string} chatType - 聊天类型 - * @param {object} strategy - 策略配置 - */ - setChatStrategy(chatType, strategy) { - this.chatStrategies.set(chatType, { - ...this.chatStrategies.get(chatType), - ...strategy - }); - - console.log(`[聊天管理] 更新聊天策略 ${chatType}:`, strategy); - } - - /** - * 清理过期数据 - */ - cleanup() { - const now = Date.now(); - const expireTime = 30 * 24 * 3600000; // 30天 - - // 清理过期的聊天历史 - for (const [sn_code, history] of this.chatHistory.entries()) { - const filteredHistory = history.filter(record => - now - record.timestamp < expireTime - ); - - if (filteredHistory.length === 0) { - this.chatHistory.delete(sn_code); - } else { - this.chatHistory.set(sn_code, filteredHistory); - } - } - - // 清理过期的效果统计 - for (const [sn_code, stats] of this.effectStats.entries()) { - if (now - stats.lastUpdate > expireTime) { - this.effectStats.delete(sn_code); - } - } - - console.log(`[聊天管理] 数据清理完成`); - } - - /** - * 生成默认聊天内容(替代 AI 生成) - * @param {object} jobInfo - 岗位信息 - * @param {object} resumeInfo - 简历信息 - * @param {string} chatType - 聊天类型 - * @returns {object} 聊天内容 - */ - generateDefaultChatContent(jobInfo, resumeInfo, chatType) { - const templates = { - greeting: '您好,我对这个岗位很感兴趣,希望能进一步了解。', - interview: '感谢您的回复,我很期待与您进一步沟通。', - followup: '您好,想了解一下这个岗位的最新进展。' - }; - - const content = templates[chatType] || templates.greeting; - + _parse_chat_list_response(response) { + if (!response) return null; + const raw = response.zpData != null ? response.zpData : response.data; + if (!raw) return { friendList: [], foldText: '', filterEncryptIdList: [], filterBossIdList: [] }; return { - success: true, - content: content, - chatType: chatType - }; - } - - /** - * 生成默认面试邀约(替代 AI 生成) - * @param {object} jobInfo - 岗位信息 - * @returns {object} 面试邀约内容 - */ - generateDefaultInterviewInvitation(jobInfo) { - return { - success: true, - content: '感谢您的邀请,我很期待与您面谈。请问方便的时间是什么时候?', - jobTitle: jobInfo.jobTitle || '该岗位', - companyName: jobInfo.companyName || '贵公司' + friendList: Array.isArray(raw.friendList) ? raw.friendList : [], + foldText: raw.foldText || '', + filterEncryptIdList: Array.isArray(raw.filterEncryptIdList) ? raw.filterEncryptIdList : [], + filterBossIdList: Array.isArray(raw.filterBossIdList) ? raw.filterBossIdList : [] }; } /** * 获取聊天列表 + * 返回值结构: { friendList, foldText, filterEncryptIdList, filterBossIdList } + * friendList 每项: friendId, encryptFriendId, name, updateTime, brandName, jobName, jobCity, positionName, bossTitle 等 * @param {string} sn_code - 设备SN码 * @param {object} mqttClient - MQTT客户端 * @param {object} params - 参数 - * @returns {Promise} 聊天列表 + * @returns {Promise} { friendList, foldText, filterEncryptIdList, filterBossIdList } */ async get_chat_list(sn_code, mqttClient, params = {}) { const { platform = 'boss', pageCount = 3 } = params; console.log(`[聊天管理] 开始获取设备 ${sn_code} 的聊天列表`); - // 通过MQTT指令获取聊天列表 const response = await mqttClient.publishAndWait(sn_code, { platform, - action: "get_chat_list", + action: 'get_chat_list', data: { pageCount } }); - if (!response || response.code !== 200) { + // 沟通列表接口成功为 code: 0 或 code: 200 + const ok = response && (response.code === 0 || response.code === 200); + if (!ok) { console.error(`[聊天管理] 获取聊天列表失败:`, response); - throw new Error('获取聊天列表失败'); + throw new Error(response?.message || '获取聊天列表失败'); } - console.log(`[聊天管理] 成功获取聊天列表`); - return response.data; + const parsed = this._parse_chat_list_response(response); + console.log(`[聊天管理] 成功获取聊天列表,共 ${parsed.friendList.length} 个联系人`); + return parsed; + } + + /** + * 解析沟通详情返回值(两种形态二选一) + * 形态1 - 会话/职位信息: zpData.data + zpData.job + * 形态2 - 聊天消息列表: zpData.hasMore + zpData.messages + * @private + */ + _parse_chat_detail_response(response) { + if (!response) return null; + const raw = response.zpData != null ? response.zpData : response.data; + if (!raw) return { variant: 'unknown', data: null, job: null, hasMore: false, messages: [] }; + + // 形态2: 消息列表(有 messages 数组) + if (Array.isArray(raw.messages)) { + return { + variant: 'messages', + hasMore: !!raw.hasMore, + messages: raw.messages, + type: raw.type, + minMsgId: raw.minMsgId + }; + } + + // 形态1: 会话详情(data + job) + if (raw.data != null || raw.job != null) { + return { + variant: 'session', + data: raw.data || null, + job: raw.job || null + }; + } + + return { variant: 'unknown', data: null, job: null, hasMore: false, messages: [] }; + } + + /** + * 获取沟通详情(会话信息或聊天消息列表) + * 返回值: { variant: 'session'|'messages', ... } + * - session: data(boss/会话信息), job(职位信息) + * - messages: hasMore, messages[], type, minMsgId + * @param {string} sn_code - 设备SN码 + * @param {object} mqttClient - MQTT客户端 + * @param {object} params - 参数,如 friendId/encryptBossId/encryptJobId 等,由设备端约定 + * @returns {Promise} + */ + async get_chat_detail(sn_code, mqttClient, params = {}) { + const { platform = 'boss', ...rest } = params; + console.log(`[聊天管理] 开始获取设备 ${sn_code} 的沟通详情`); + + const response = await mqttClient.publishAndWait(sn_code, { + platform, + action: 'get_chat_detail', + data: rest + }); + + const ok = response && (response.code === 0 || response.code === 200); + if (!ok) { + console.error(`[聊天管理] 获取沟通详情失败:`, response); + throw new Error(response?.message || '获取沟通详情失败'); + } + + const parsed = this._parse_chat_detail_response(response); + const logExtra = parsed.variant === 'session' + ? `会话` + : parsed.variant === 'messages' + ? `消息 ${parsed.messages.length} 条` + : `未知`; + console.log(`[聊天管理] 成功获取沟通详情 (${logExtra})`); + return parsed; + } + + /** + * 发送聊天消息(支持多条 + 文本/发简历/换电话/换微信) + * @param {string} sn_code - 设备SN码 + * @param {object} mqttClient - MQTT客户端 + * @param {object} params - friendId(必填), messages(数组), chatType, use_real_type, platform + * @param {string} params.friendId - 好友ID,用于打开该好友的聊天面板 + * @param {Array} params.messages - 每项为 string 或 { type: 'text'|'send_resume'|'exchange_phone'|'exchange_wechat', content?: string } + * @param {boolean} params.use_real_type - 是否模拟真实打字,默认 false + * @returns {Promise} 发送结果 + */ + async send_chat_message(sn_code, mqttClient, params) { + const { friendId, messages, chatType, use_real_type = false, platform = 'boss' } = params || {}; + + if (!friendId) throw new Error('friendId 不能为空'); + if (!Array.isArray(messages) || messages.length === 0) throw new Error('messages 必须是非空数组'); + + const normalized_messages = messages.map((item) => { + if (typeof item === 'string') return { type: 'text', content: item }; + return { type: item.type || 'text', content: item.content || '' }; + }); + + console.log(`[聊天管理] 设备 ${sn_code} 发送聊天消息,friendId=${friendId},条数=${normalized_messages.length}`); + + const response = await mqttClient.publishAndWait(sn_code, { + platform, + action: 'send_chat_message', + data: { friendId, messages: normalized_messages, chatType, use_real_type: !!use_real_type } + }); + + if (!response || (response.code !== 0 && response.code !== 200)) { + console.error(`[聊天管理] 聊天消息发送失败:`, response); + throw new Error(response?.message || '聊天消息发送失败'); + } + + console.log(`[聊天管理] 聊天消息发送成功`); + return response; + } + + /** + * 使用 AI 自动决定是否回复,并发送回复 + * 流程: + * 1. 根据参数获取沟通详情(消息列表) + * 2. 如果最后一句是 HR 说的,则调用阿里云 Qwen 生成回复文案 + * 3. 通过 send_chat_message 把回复发出去 + * + * @param {string} sn_code - 设备SN码 + * @param {object} mqttClient - MQTT客户端 + * @param {object} params - 包含 friendId + 获取详情所需参数(如 encryptBossId/encryptJobId 等) + * @returns {Promise} { replied, reply_content?, hr_message_text?, reason? } + */ + async auto_reply_with_ai(sn_code, mqttClient, params = {}) { + const { friendId, platform = 'boss', ...detailParams } = params; + + if (!friendId) { + throw new Error('friendId 不能为空'); + } + + // 1. 获取沟通详情(期望拿到消息列表) + const detail = await this.get_chat_detail(sn_code, mqttClient, { + platform, + ...detailParams + }); + + if (!detail || detail.variant !== 'messages' || !Array.isArray(detail.messages) || detail.messages.length === 0) { + return { replied: false, reason: '无可用消息' }; + } + + const messages = detail.messages; + + // 2. 推断 HR 与 求职者 uid + let hr_uid = null; + let geek_uid = null; + + for (const msg of messages) { + const body = msg.body || {}; + const jobDesc = body.jobDesc || body.job_desc || null; + if (jobDesc) { + if (jobDesc.boss && jobDesc.boss.uid && !hr_uid) { + hr_uid = jobDesc.boss.uid; + } + if (jobDesc.geek && jobDesc.geek.uid && !geek_uid) { + geek_uid = jobDesc.geek.uid; + } + } + if (hr_uid && geek_uid) break; + } + + const last = messages[messages.length - 1]; + + // 兜底:还没有 hr_uid 时,用最后一条的 from/to 做简单推断 + if ((!hr_uid || !geek_uid) && last && last.from && last.to) { + hr_uid = hr_uid || last.from.uid; + geek_uid = geek_uid || last.to.uid; + } + + if (!last || !last.from || !hr_uid || last.from.uid !== hr_uid) { + // 最后一条不是 HR 发的,不自动回复 + return { replied: false, reason: '最后一条不是HR消息' }; + } + + // 取 HR 文本内容(普通文本优先) + const body = last.body || {}; + const hr_message_text = + (typeof body.text === 'string' && body.text) || + (typeof last.pushText === 'string' && last.pushText) || + ''; + + if (!hr_message_text || !hr_message_text.trim()) { + return { replied: false, reason: 'HR消息没有可用文本' }; + } + + // 3. 调用阿里云 Qwen 生成回复文案(已在 config 中切换为 qwen-plus) + const jobInfo = detail.job || {}; + + const reply_content = await ai_service.generateChatContent({ + jobInfo, + resumeInfo: null, + chatType: 'reply', + hrMessage: hr_message_text, + previousMessages: [] // 如需上下文,这里可以把 detail.messages 映射进去 + }); + + if (!reply_content || !reply_content.trim()) { + return { replied: false, reason: 'AI 未生成有效回复' }; + } + + // 4. 通过统一的 send_chat_message 下发回复 + await this.send_chat_message(sn_code, mqttClient, { + friendId, + messages: [{ type: 'text', content: reply_content }], + chatType: 'reply', + platform + }); + + return { + replied: true, + reply_content, + hr_message_text + }; + } + + /** + * 自动获取沟通列表 + 按会话自动 AI 回复 + * 1. 调用 get_chat_list 获取会话列表 + * 2. 对每个会话按 friendId 调用 auto_reply_with_ai(内部会先获取详情,再决定是否回复) + * + * @param {string} sn_code - 设备SN码 + * @param {object} mqttClient - MQTT客户端 + * @param {object} params - { platform?, pageCount? } + * @returns {Promise} { success, total_contacts, replied_count, details: [...] } + */ + async auto_chat_ai(sn_code, mqttClient, params = {}) { + const { platform = 'boss', pageCount = 3 } = params; + + // 1. 获取沟通列表 + const listResult = await this.get_chat_list(sn_code, mqttClient, { + platform, + pageCount + }); + + const friendList = Array.isArray(listResult.friendList) ? listResult.friendList : []; + + if (friendList.length === 0) { + return { + success: true, + total_contacts: 0, + replied_count: 0, + details: [], + message: '没有可沟通的会话' + }; + } + + let replied_count = 0; + const details = []; + + // 2. 逐个会话顺序处理,避免并发下发指令 + for (const friend of friendList) { + const friendId = friend.friendId; + if (!friendId) { + continue; + } + + try { + const r = await this.auto_reply_with_ai(sn_code, mqttClient, { + platform, + friendId + }); + + if (r.replied) { + replied_count++; + } + + details.push({ + friendId, + replied: !!r.replied, + reason: r.reason || null, + reply_content: r.reply_content || null + }); + } catch (error) { + details.push({ + friendId, + replied: false, + reason: error.message || '自动回复失败', + reply_content: null + }); + } + } + + return { + success: true, + total_contacts: friendList.length, + replied_count, + details, + message: '自动获取列表并尝试AI回复完成' + }; } } diff --git a/api/middleware/schedule/handlers/chatHandler.js b/api/middleware/schedule/handlers/chatHandler.js index 8dcd936..d727e09 100644 --- a/api/middleware/schedule/handlers/chatHandler.js +++ b/api/middleware/schedule/handlers/chatHandler.js @@ -59,27 +59,29 @@ class ChatHandler extends BaseHandler { } } - // 4. 创建沟通指令 + // 4. 创建自动沟通 AI 指令(内部会先获取列表,再获取详情并自动回复) const chatCommand = { - command_type: 'autoChat', - command_name: '自动沟通', - command_params: JSON.stringify({ - sn_code, + command_type: 'auto_chat_ai', + command_name: '自动沟通AI回复', + command_params: { platform: platform || accountConfig.platform_type || 'boss', - autoReply: chatStrategy.auto_reply || false, - replyTemplate: chatStrategy.reply_template || '' - }), + pageCount: chatStrategy.page_count || 3 + }, priority: config.getTaskPriority('auto_chat') || 6 }; - // 5. 执行沟通指令 - const result = await command.executeCommands(task.id, [chatCommand], this.mqttClient); + // 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 || {} + : {}; console.log(`[自动沟通] 完成 - 设备: ${sn_code}`); return { - chatCount: result.chatCount || 0, - message: '沟通完成' + chatCount: first.replied_count || 0, + message: first.message || '自动沟通完成', + detail: first }; } } diff --git a/api/middleware/schedule/notifiers/deviceWorkStatusNotifier.js b/api/middleware/schedule/notifiers/deviceWorkStatusNotifier.js index 6b35c4e..b0e332c 100644 --- a/api/middleware/schedule/notifiers/deviceWorkStatusNotifier.js +++ b/api/middleware/schedule/notifiers/deviceWorkStatusNotifier.js @@ -218,7 +218,7 @@ class DeviceWorkStatusNotifier { return '投递简历'; } else if (commandType === 'searchJobs' || commandName.includes('搜索')) { return `搜索职位: ${parsedParams.keyword || ''}`; - } else if (commandType === 'sendChatMessage' || commandName.includes('沟通')) { + } else if (commandType === 'send_chat_message' || commandType === 'sendChatMessage' || commandName.includes('沟通')) { return '发送消息'; } else if (commandName) { return commandName; diff --git a/config/config.js b/config/config.js index dda0422..8a6d78c 100644 --- a/config/config.js +++ b/config/config.js @@ -68,7 +68,7 @@ module.exports = { ai: { "apiKey": "sk-c83cdb06a6584f99bb2cd6e8a5ae3bbc", "baseUrl": "https://dashscope.aliyuncs.com/api/v1", - "model": "qwen-turbo" + "model": "qwen-plus" }, // MQTT配置