// 简道云API服务 const axios = require('axios'); const config = require('../config/config'); class JiandaoyunService { constructor() { // 简道云API基础配置 this.baseUrl = 'https://api.jiandaoyun.com'; this.apiKey = config.jiandaoyun.apiKey; this.appId = config.jiandaoyun.appId; this.entryId = config.jiandaoyun.entryId; // 人员简道云编号映射表 this.userNameToUsernameMap = { '潘仁平': 'woxjrqDwAA4dI-mX-4auX33id4VzULcQ', '蔡姣': 'woxjrqDwAA9x13NM8QB02q0jvI04kmhA', '宋洋': 'woxjrqDwAAC9EJd4GVTOuo-8cWMqHtuQ', '高沙': 'woxjrqDwAAQZTTfwiY_0dzgAIbezckWQ', '代斯磊': 'woxjrqDwAA0YMesQrdC2YFUfCcQlu7xA', '梁婷': 'woxjrqDwAA4miq7o6KLIW56xT3ZWBRDg', '吴海燕': 'woxjrqDwAAtq9gx3Y3F4wD-kyOU1ZY0w', '何佳芹': 'woxjrqDwAAUY-nHkVmBVxeotmw9M0BeA', '陈骏': 'woxjrqDwAAR48VAlhJBDVfXXHVemYWLA', '胡金凤': 'woxjrqDwAA1f3LS8H1UdmRQ5u7x0ISlA', '李俊波': 'woxjrqDwAA8rO8Grm8voGBRAoTftimFw', '刘琴': 'woxjrqDwAAJbOA6OU2ZR5IIbXRnALU8w', '袁嘉莉': 'woxjrqDwAAKLP25CjOCQg77lSv6oYiGQ', '汤敏': 'woxjrqDwAA0_YzPpRrb1THjzYi1zd4Cw', '杨率': 'woxjrqDwAAMkzyxQt_tE7V2GLPF8gokQ', '李真音': 'woxjrqDwAAZxbx0YzET4gqGkN8693CbQ', '李毅': 'woxjrqDwAAqSLFZnsNy9W61ELGeMazhQ', '李文涛': 'woxjrqDwAAmm8IhlT0cdaB7DjNmIVLsg' }; } // 提交数据到简道云表单 async submitDataToForm(data, userManagement = null) { try { console.log('准备提交数据到简道云:', JSON.stringify(data, null, 2)); // 使用简道云API v5版本,支持data_creator参数 const url = `${this.baseUrl}/api/v5/app/entry/data/create`; const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }; // 根据userManagement.userName从映射表中获取对应的简道云编号作为data_creator let dataCreator = ''; if (userManagement && userManagement.userName) { dataCreator = this.userNameToUsernameMap[userManagement.userName] || ''; } // 如果没有提供dataCreator,使用默认值(确保不为空) if (!dataCreator) { // 使用映射表中的第一个用户作为默认值 const defaultUserName = Object.keys(this.userNameToUsernameMap)[0]; dataCreator = this.userNameToUsernameMap[defaultUserName] || ''; console.log('使用默认data_creator:', dataCreator); } // 构建请求体,添加data_creator参数 const payload = { app_id: this.appId, entry_id: this.entryId, data: data, data_creator: dataCreator }; console.log('请求URL:', url); console.log('请求头:', headers); console.log('请求体:', JSON.stringify(payload, null, 2)); const response = await axios.post(url, payload, { headers }); console.log('简道云API调用成功:', response.data); return response.data; } catch (error) { console.error('简道云API调用失败:', error.message); if (error.response) { console.error('响应状态:', error.response.status); console.error('响应数据:', JSON.stringify(error.response.data, null, 2)); console.error('响应头:', JSON.stringify(error.response.headers, null, 2)); if (error.config) { console.error('请求URL:', error.config.url); console.error('请求头:', JSON.stringify(error.config.headers, null, 2)); console.error('请求数据:', error.config.data); } } throw error; } } // 将数据库数据转换为简道云表单所需格式 transformDataToJiandaoyunFormat(databaseData) { console.log('开始转换数据:', JSON.stringify(databaseData, null, 2)); const jiandaoyunData = {}; const mapping = config.fieldMapping; // 转换主表数据 const user = databaseData.user; console.log('用户数据:', JSON.stringify(user, null, 2)); console.log('字段映射:', JSON.stringify(mapping, null, 2)); // 使用简道云API v1的正确值格式,使用value字段来包装值 // 转换需要的字段:userId, company, level, demand, region, type, followup jiandaoyunData[mapping.userId] = { value: user.userId || '' }; jiandaoyunData[mapping.company] = { value: user.company || '' }; jiandaoyunData[mapping.level] = { value: user.level || '' }; // 将demand转换为数组格式 let demandValue = user.demand || ''; let demandArray = []; if (demandValue && demandValue !== '-') { demandArray = demandValue.split(',').map(item => item.trim()); } jiandaoyunData[mapping.demand] = { value: demandArray }; // 将region转换为数组格式 let regionValue = user.region || ''; let regionArray = []; if (regionValue && regionValue !== '-') { regionArray = regionValue.split(',').map(item => item.trim()); } jiandaoyunData[mapping.region] = { value: regionArray }; jiandaoyunData[mapping.type] = { value: user.type || '' }; // 转换followup字段 jiandaoyunData[mapping.followup] = { value: user.followup || '' }; // 处理子表字段 const subTableField = config.subTableFields.subTable; const subTableData = [{ [config.subTableFields.nickName]: { value: user.nickName || '' }, [config.subTableFields.phoneNumber]: { value: user.phoneNumber || '' }, // 地址字段直接作为字符串写入子表 [config.subTableFields.detailedaddress]: { value: user.detailedaddress || '' } }]; jiandaoyunData[subTableField] = { value: subTableData }; // 转换负责人信息 const userManagement = databaseData.userManagement; console.log('负责人数据:', JSON.stringify(userManagement, null, 2)); if (userManagement && userManagement.userName) { // 根据userName从映射表中获取对应的简道云编号 const userName = userManagement.userName; const username = this.userNameToUsernameMap[userName] || ''; // 根据简道云API v5的格式要求,成员单选字段需要使用包含value字段的对象格式 jiandaoyunData[mapping.userName] = { value: username }; console.log(`设置负责人字段 ${mapping.userName} 的值为:`, JSON.stringify({ value: username })); } console.log('转换后的数据:', JSON.stringify(jiandaoyunData, null, 2)); return jiandaoyunData; } // 查询简道云表单中是否存在指定电话号码的数据 async isPhoneNumberExists(phoneNumber) { try { console.log(`检查电话号码 ${phoneNumber} 是否存在于简道云表单中...`); // 注意:电话号码现在存储在子表中,查询方式需要调整 // 暂时返回false,避免因查询失败而阻止数据同步 console.log('电话号码存储在子表中,暂时跳过存在性检查'); return false; } catch (error) { console.error('查询电话号码是否存在失败:', error.message); if (error.response) { console.error('响应状态:', error.response.status); console.error('响应数据:', error.response.data); } // 发生错误时,为了避免数据丢失,默认返回false,表示不存在该电话号码 return false; } } // 批量提交数据到简道云 async batchSubmitData(dataList, connection) { const results = []; // 尝试从databaseService获取连接,如果参数中没有提供 let dbConnection = connection; if (!dbConnection) { try { const databaseService = require('./databaseService'); if (databaseService.connection) { dbConnection = databaseService.connection; console.log('从databaseService获取数据库连接成功'); } } catch (error) { console.log('无法从databaseService获取连接:', error.message); } } for (const item of dataList) { try { // 检查数据库中是否已有简道云记录ID let recordId = null; if (item.user && 'dataid' in item.user && item.user.dataid) { recordId = item.user.dataid; console.log(`从数据库获取到简道云记录ID: ${recordId}`); } if (recordId) { console.log(`使用记录ID ${recordId} 更新数据`); // 转换数据格式 const jiandaoyunData = this.transformDataToJiandaoyunFormat(item); try { // 更新数据,传递userManagement参数 const result = await this.updateDataInForm(recordId, jiandaoyunData, item.userManagement); // 更新数据库中的同步状态 if (dbConnection && item.user && item.user.userId) { try { console.log(`更新用户 ${item.user.userId} 的同步状态`); const [updateResult] = await dbConnection.execute( `UPDATE ${config.tables.users.name} SET ${config.sync.statusField} = ${config.sync.syncedValue} WHERE userId = ?`, [item.user.userId] ); if (updateResult.affectedRows > 0) { console.log(`✅ 成功更新用户 ${item.user.userId} 的同步状态`); } else { console.log(`⚠️ 更新用户 ${item.user.userId} 的同步状态失败: 未找到匹配的用户`); } } catch (updateError) { console.error(`❌ 更新数据库同步状态时发生错误:`, updateError.message); console.error(`错误堆栈:`, updateError.stack); } } results.push({ success: true, updated: true, data: result, originalData: item }); console.log('数据更新成功:', result); continue; } catch (updateError) { console.error('更新数据失败:', updateError.message); if (updateError.response && updateError.response.data && updateError.response.data.msg === 'Data does not exist.') { console.log('记录不存在,删除数据库中的 dataid 字段并重新提交'); // 删除数据库中的 dataid 字段 if (dbConnection && item.user && item.user.userId) { try { await dbConnection.execute( `UPDATE ${config.tables.users.name} SET dataid = NULL WHERE userId = ?`, [item.user.userId] ); console.log(`✅ 成功删除用户 ${item.user.userId} 的 dataid 字段`); } catch (deleteError) { console.error(`❌ 删除 dataid 字段时发生错误:`, deleteError.message); } } // 继续执行,将数据作为新记录提交 recordId = null; } else { throw updateError; } } } // 转换数据格式 const jiandaoyunData = this.transformDataToJiandaoyunFormat(item); // 提交数据,传递userManagement参数 const result = await this.submitDataToForm(jiandaoyunData, item.userManagement); // 保存返回的记录ID到数据库 console.log('检查返回结果结构:', JSON.stringify(result, null, 2)); if (result && result.data && result.data._id) { const newRecordId = result.data._id; console.log(`获取到简道云记录ID: ${newRecordId}`); if (dbConnection && item.user && item.user.userId) { try { console.log(`准备更新用户 ${item.user.userId} 的dataid为 ${newRecordId} 并设置同步状态`); const [updateResult] = await dbConnection.execute( `UPDATE ${config.tables.users.name} SET dataid = ?, ${config.sync.statusField} = ${config.sync.syncedValue} WHERE userId = ?`, [newRecordId, item.user.userId] ); console.log(`数据库更新结果:`, updateResult); if (updateResult.affectedRows > 0) { console.log(`✅ 成功将简道云记录ID ${newRecordId} 保存到数据库并更新同步状态`); } else { console.log(`⚠️ 更新用户 ${item.user.userId} 的dataid和同步状态失败: 未找到匹配的用户`); } } catch (updateError) { console.error(`❌ 更新数据库dataid和同步状态时发生错误:`, updateError.message); console.error(`错误堆栈:`, updateError.stack); } } else { console.log(`⚠️ 无法更新数据库: 缺少connection或item.user.userId`); console.log(`connection存在: ${!!dbConnection}`); console.log(`item.user存在: ${!!item.user}`); console.log(`item.user.userId存在: ${item.user ? !!item.user.userId : 'N/A'}`); } } else { console.log(`⚠️ 简道云API返回结果中没有包含有效的记录ID`); console.log(`result.data存在: ${!!result.data}`); console.log(`result.data._id存在: ${result.data ? !!result.data._id : 'N/A'}`); } results.push({ success: true, data: result, originalData: item }); console.log('数据提交成功:', result); } catch (error) { results.push({ success: false, error: error.message, originalData: item }); console.error('数据提交失败:', error.message); } } return results; } // 根据电话号码获取简道云记录ID async getRecordIdByPhoneNumber(phoneNumber) { try { console.log(`根据电话号码 ${phoneNumber} 获取简道云记录ID...`); // 注意:电话号码现在存储在子表中,查询方式需要调整 // 暂时返回null,避免因查询失败而阻止数据同步 console.log('电话号码存储在子表中,暂时跳过记录ID查询'); return null; } catch (error) { console.error('获取记录ID失败:', error.message); return null; } } // 更新简道云表单中的数据 async updateDataInForm(recordId, data, userManagement = null) { try { // 使用简道云API v5版本,支持data_creator参数 const url = `${this.baseUrl}/api/v5/app/entry/data/update`; const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }; // 根据userManagement.userName从映射表中获取对应的简道云编号作为data_creator let dataCreator = ''; if (userManagement && userManagement.userName) { dataCreator = this.userNameToUsernameMap[userManagement.userName] || ''; } // 如果没有提供dataCreator,使用默认值(确保不为空) if (!dataCreator) { // 使用映射表中的第一个用户作为默认值 const defaultUserName = Object.keys(this.userNameToUsernameMap)[0]; dataCreator = this.userNameToUsernameMap[defaultUserName] || ''; console.log('使用默认data_creator:', dataCreator); } // 构建更新请求体:记录ID和要更新的数据 const payload = { app_id: this.appId, entry_id: this.entryId, data_id: recordId, data: data, data_creator: dataCreator }; console.log('更新请求URL:', url); console.log('更新请求头:', headers); console.log('更新请求体:', JSON.stringify(payload, null, 2)); const response = await axios.post(url, payload, { headers }); console.log('更新响应:', JSON.stringify(response.data, null, 2)); return response.data; } catch (error) { console.error('更新数据失败:', error.message); if (error.response) { console.error('响应状态:', error.response.status); console.error('响应数据:', JSON.stringify(error.response.data, null, 2)); } throw error; } } // 测试简道云API连接 async testApiConnection() { try { console.log('===== 测试简道云API连接 ====='); // 使用fieldMapping来构建测试数据,验证字段映射是否正确 const mapping = config.fieldMapping; const testData = { [mapping.userId]: { value: '123456' }, // 测试用户ID // 子表字段测试 [config.subTableFields.subTable]: { value: [{ [config.subTableFields.nickName]: { value: '测试联系人' }, [config.subTableFields.phoneNumber]: { value: '13800138000' } }] } }; // 创建测试用的userManagement对象,确保有data_creator const testUserManagement = { userName: Object.keys(this.userNameToUsernameMap)[0] // 使用映射表中的第一个用户 }; const response = await this.submitDataToForm(testData, testUserManagement); console.log('简道云API连接成功'); return true; } catch (error) { console.error('简道云API连接失败:', error.message); if (error.response) { console.error('响应状态:', error.response.status); console.error('响应数据:', error.response.data); } console.error('错误堆栈:', error.stack); return false; } } } module.exports = new JiandaoyunService();