|
|
|
|
// 简道云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'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提交数据到简道云表单
|
|
|
|
|
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
|
|
|
|
|
jiandaoyunData[mapping.userId] = { value: user.userId || '' };
|
|
|
|
|
|
|
|
|
|
// 处理子表字段
|
|
|
|
|
const subTableField = config.subTableFields.subTable;
|
|
|
|
|
const subTableData = [{
|
|
|
|
|
[config.subTableFields.nickName]: { value: user.nickName || '' },
|
|
|
|
|
[config.subTableFields.phoneNumber]: { value: user.phoneNumber || '' }
|
|
|
|
|
}];
|
|
|
|
|
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();
|