|
|
|
@ -9,23 +9,52 @@ class JiandaoyunService { |
|
|
|
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) { |
|
|
|
async submitDataToForm(data, userManagement = null) { |
|
|
|
try { |
|
|
|
console.log('准备提交数据到简道云:', JSON.stringify(data, null, 2)); |
|
|
|
|
|
|
|
// 简道云API v1的正确请求格式 - 使用data_create端点
|
|
|
|
const url = `${this.baseUrl}/api/v1/app/${this.appId}/entry/${this.entryId}/data_create`; |
|
|
|
// 使用简道云API v5版本,支持data_creator参数
|
|
|
|
const url = `${this.baseUrl}/api/v5/app/entry/data/create`; |
|
|
|
const headers = { |
|
|
|
'Content-Type': 'application/json', |
|
|
|
'Authorization': `Bearer ${this.apiKey}` |
|
|
|
}; |
|
|
|
|
|
|
|
// 简道云API v1只需要在请求体中包含data字段
|
|
|
|
// 根据userManagement.userName从映射表中获取对应的简道云编号作为data_creator
|
|
|
|
let dataCreator = ''; |
|
|
|
if (userManagement && userManagement.userName) { |
|
|
|
dataCreator = this.userNameToUsernameMap[userManagement.userName] || ''; |
|
|
|
} |
|
|
|
|
|
|
|
// 构建请求体,添加data_creator参数
|
|
|
|
const payload = { |
|
|
|
data: data |
|
|
|
app_id: this.appId, |
|
|
|
entry_id: this.entryId, |
|
|
|
data: data, |
|
|
|
data_creator: dataCreator |
|
|
|
}; |
|
|
|
|
|
|
|
console.log('请求URL:', url); |
|
|
|
@ -65,30 +94,32 @@ class JiandaoyunService { |
|
|
|
console.log('字段映射:', JSON.stringify(mapping, null, 2)); |
|
|
|
|
|
|
|
// 使用简道云API v1的正确值格式,使用value字段来包装值
|
|
|
|
// 转换需要的字段:userId
|
|
|
|
jiandaoyunData[mapping.userId] = { value: user.userId || '' }; |
|
|
|
jiandaoyunData[mapping.nickName] = { value: user.nickName || '' }; |
|
|
|
jiandaoyunData[mapping.phoneNumber] = { value: user.phoneNumber || '' }; |
|
|
|
jiandaoyunData[mapping.type] = { value: user.type || '' }; |
|
|
|
jiandaoyunData[mapping.authorizedRegion] = { value: user.authorizedRegion || '' }; |
|
|
|
|
|
|
|
// 处理子表字段
|
|
|
|
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) { |
|
|
|
jiandaoyunData[mapping.userName] = { value: userManagement.userName || '' }; |
|
|
|
} |
|
|
|
|
|
|
|
// 转换产品数据
|
|
|
|
const products = databaseData.products; |
|
|
|
console.log('产品数据:', JSON.stringify(products, null, 2)); |
|
|
|
|
|
|
|
if (products && products.length > 0) { |
|
|
|
const firstProduct = products[0]; |
|
|
|
jiandaoyunData[mapping.productName] = { value: firstProduct.productName || '' }; |
|
|
|
jiandaoyunData[mapping.specification] = { value: firstProduct.specification || '' }; |
|
|
|
jiandaoyunData[mapping.quantity] = { value: firstProduct.quantity || '' }; |
|
|
|
jiandaoyunData[mapping.grossWeight] = { value: firstProduct.grossWeight || '' }; |
|
|
|
jiandaoyunData[mapping.yolk] = { value: firstProduct.yolk || '' }; |
|
|
|
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)); |
|
|
|
@ -99,44 +130,12 @@ class JiandaoyunService { |
|
|
|
// 查询简道云表单中是否存在指定电话号码的数据
|
|
|
|
async isPhoneNumberExists(phoneNumber) { |
|
|
|
try { |
|
|
|
const mapping = config.fieldMapping; |
|
|
|
console.log(`检查电话号码 ${phoneNumber} 是否存在于简道云表单中...`); |
|
|
|
console.log(`使用的字段映射: ${mapping.phoneNumber}`); |
|
|
|
|
|
|
|
const url = `${this.baseUrl}/api/v1/app/${this.appId}/entry/${this.entryId}/data_list`; |
|
|
|
const headers = { |
|
|
|
'Content-Type': 'application/json', |
|
|
|
'Authorization': `Bearer ${this.apiKey}` |
|
|
|
}; |
|
|
|
|
|
|
|
// 构建查询条件:电话号码字段等于指定值
|
|
|
|
const payload = { |
|
|
|
filter: { |
|
|
|
rel: 'and', |
|
|
|
cond: [ |
|
|
|
{ |
|
|
|
field: mapping.phoneNumber, |
|
|
|
type: 'text', |
|
|
|
method: 'eq', |
|
|
|
value: phoneNumber |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
page_size: 10 // 返回更多结果以便调试
|
|
|
|
}; |
|
|
|
|
|
|
|
console.log('发送的查询请求:', JSON.stringify(payload, null, 2)); |
|
|
|
|
|
|
|
const response = await axios.post(url, payload, { headers }); |
|
|
|
|
|
|
|
console.log('查询响应状态:', response.status); |
|
|
|
console.log('查询响应数据:', JSON.stringify(response.data, null, 2)); |
|
|
|
|
|
|
|
// 如果返回的数据数量大于0,则表示该电话号码已存在
|
|
|
|
const exists = response.data.data.length > 0; |
|
|
|
console.log(`电话号码 ${phoneNumber} 存在: ${exists}`); |
|
|
|
|
|
|
|
return exists; |
|
|
|
|
|
|
|
// 注意:电话号码现在存储在子表中,查询方式需要调整
|
|
|
|
// 暂时返回false,避免因查询失败而阻止数据同步
|
|
|
|
console.log('电话号码存储在子表中,暂时跳过存在性检查'); |
|
|
|
return false; |
|
|
|
} catch (error) { |
|
|
|
console.error('查询电话号码是否存在失败:', error.message); |
|
|
|
if (error.response) { |
|
|
|
@ -168,57 +167,80 @@ class JiandaoyunService { |
|
|
|
|
|
|
|
for (const item of dataList) { |
|
|
|
try { |
|
|
|
// 检查数据库中是否已有简道云记录ID
|
|
|
|
let recordId = null; |
|
|
|
if (item.user && 'jiandaoyun_record_id' in item.user) { |
|
|
|
recordId = item.user.jiandaoyun_record_id; |
|
|
|
console.log(`从数据库获取到简道云记录ID: ${recordId}`); |
|
|
|
} |
|
|
|
|
|
|
|
if (recordId) { |
|
|
|
console.log(`使用记录ID ${recordId} 更新数据`); |
|
|
|
// 检查数据库中是否已有简道云记录ID
|
|
|
|
let recordId = null; |
|
|
|
if (item.user && 'dataid' in item.user && item.user.dataid) { |
|
|
|
recordId = item.user.dataid; |
|
|
|
console.log(`从数据库获取到简道云记录ID: ${recordId}`); |
|
|
|
} |
|
|
|
|
|
|
|
// 转换数据格式
|
|
|
|
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item); |
|
|
|
if (recordId) { |
|
|
|
console.log(`使用记录ID ${recordId} 更新数据`); |
|
|
|
|
|
|
|
// 更新数据
|
|
|
|
const result = await this.updateDataInForm(recordId, jiandaoyunData); |
|
|
|
// 转换数据格式
|
|
|
|
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item); |
|
|
|
|
|
|
|
// 更新数据库中的同步状态
|
|
|
|
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}, ${config.sync.timeField} = NOW() WHERE userId = ?`, |
|
|
|
[item.user.userId] |
|
|
|
); |
|
|
|
// 更新数据,传递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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (updateResult.affectedRows > 0) { |
|
|
|
console.log(`✅ 成功更新用户 ${item.user.userId} 的同步状态`); |
|
|
|
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 { |
|
|
|
console.log(`⚠️ 更新用户 ${item.user.userId} 的同步状态失败: 未找到匹配的用户`); |
|
|
|
throw updateError; |
|
|
|
} |
|
|
|
} catch (updateError) { |
|
|
|
console.error(`❌ 更新数据库同步状态时发生错误:`, updateError.message); |
|
|
|
console.error(`错误堆栈:`, updateError.stack); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
results.push({ |
|
|
|
success: true, |
|
|
|
updated: true, |
|
|
|
data: result, |
|
|
|
originalData: item |
|
|
|
}); |
|
|
|
console.log('数据更新成功:', result); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// 转换数据格式
|
|
|
|
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item); |
|
|
|
|
|
|
|
// 提交数据
|
|
|
|
const result = await this.submitDataToForm(jiandaoyunData); |
|
|
|
// 提交数据,传递userManagement参数
|
|
|
|
const result = await this.submitDataToForm(jiandaoyunData, item.userManagement); |
|
|
|
|
|
|
|
// 保存返回的记录ID到数据库
|
|
|
|
console.log('检查返回结果结构:', JSON.stringify(result, null, 2)); |
|
|
|
@ -229,9 +251,9 @@ class JiandaoyunService { |
|
|
|
|
|
|
|
if (dbConnection && item.user && item.user.userId) { |
|
|
|
try { |
|
|
|
console.log(`准备更新用户 ${item.user.userId} 的jiandaoyun_record_id为 ${newRecordId} 并设置同步状态`); |
|
|
|
console.log(`准备更新用户 ${item.user.userId} 的dataid为 ${newRecordId} 并设置同步状态`); |
|
|
|
const [updateResult] = await dbConnection.execute( |
|
|
|
`UPDATE ${config.tables.users.name} SET jiandaoyun_record_id = ?, ${config.sync.statusField} = ${config.sync.syncedValue}, ${config.sync.timeField} = NOW() WHERE userId = ?`, |
|
|
|
`UPDATE ${config.tables.users.name} SET dataid = ?, ${config.sync.statusField} = ${config.sync.syncedValue} WHERE userId = ?`, |
|
|
|
[newRecordId, item.user.userId] |
|
|
|
); |
|
|
|
|
|
|
|
@ -239,10 +261,10 @@ class JiandaoyunService { |
|
|
|
if (updateResult.affectedRows > 0) { |
|
|
|
console.log(`✅ 成功将简道云记录ID ${newRecordId} 保存到数据库并更新同步状态`); |
|
|
|
} else { |
|
|
|
console.log(`⚠️ 更新用户 ${item.user.userId} 的jiandaoyun_record_id和同步状态失败: 未找到匹配的用户`); |
|
|
|
console.log(`⚠️ 更新用户 ${item.user.userId} 的dataid和同步状态失败: 未找到匹配的用户`); |
|
|
|
} |
|
|
|
} catch (updateError) { |
|
|
|
console.error(`❌ 更新数据库jiandaoyun_record_id和同步状态时发生错误:`, updateError.message); |
|
|
|
console.error(`❌ 更新数据库dataid和同步状态时发生错误:`, updateError.message); |
|
|
|
console.error(`错误堆栈:`, updateError.stack); |
|
|
|
} |
|
|
|
} else { |
|
|
|
@ -279,35 +301,11 @@ class JiandaoyunService { |
|
|
|
// 根据电话号码获取简道云记录ID
|
|
|
|
async getRecordIdByPhoneNumber(phoneNumber) { |
|
|
|
try { |
|
|
|
const mapping = config.fieldMapping; |
|
|
|
const url = `${this.baseUrl}/api/v1/app/${this.appId}/entry/${this.entryId}/data_list`; |
|
|
|
const headers = { |
|
|
|
'Content-Type': 'application/json', |
|
|
|
'Authorization': `Bearer ${this.apiKey}` |
|
|
|
}; |
|
|
|
|
|
|
|
// 构建查询条件:电话号码字段等于指定值
|
|
|
|
const payload = { |
|
|
|
filter: { |
|
|
|
rel: 'and', |
|
|
|
cond: [ |
|
|
|
{ |
|
|
|
field: mapping.phoneNumber, |
|
|
|
type: 'text', |
|
|
|
method: 'eq', |
|
|
|
value: phoneNumber |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
page_size: 1 // 只需要一条记录即可
|
|
|
|
}; |
|
|
|
|
|
|
|
const response = await axios.post(url, payload, { headers }); |
|
|
|
|
|
|
|
// 如果找到记录,返回第一条记录的_id
|
|
|
|
if (response.data.data.length > 0) { |
|
|
|
return response.data.data[0]._id; |
|
|
|
} |
|
|
|
console.log(`根据电话号码 ${phoneNumber} 获取简道云记录ID...`); |
|
|
|
|
|
|
|
// 注意:电话号码现在存储在子表中,查询方式需要调整
|
|
|
|
// 暂时返回null,避免因查询失败而阻止数据同步
|
|
|
|
console.log('电话号码存储在子表中,暂时跳过记录ID查询'); |
|
|
|
return null; |
|
|
|
} catch (error) { |
|
|
|
console.error('获取记录ID失败:', error.message); |
|
|
|
@ -316,25 +314,43 @@ class JiandaoyunService { |
|
|
|
} |
|
|
|
|
|
|
|
// 更新简道云表单中的数据
|
|
|
|
async updateDataInForm(recordId, data) { |
|
|
|
async updateDataInForm(recordId, data, userManagement = null) { |
|
|
|
try { |
|
|
|
const url = `${this.baseUrl}/api/v1/app/${this.appId}/entry/${this.entryId}/data_update`; |
|
|
|
// 使用简道云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] || ''; |
|
|
|
} |
|
|
|
|
|
|
|
// 构建更新请求体:记录ID和要更新的数据
|
|
|
|
const payload = { |
|
|
|
app_id: this.appId, |
|
|
|
entry_id: this.entryId, |
|
|
|
data_id: recordId, |
|
|
|
data: data |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -348,11 +364,13 @@ class JiandaoyunService { |
|
|
|
const mapping = config.fieldMapping; |
|
|
|
const testData = { |
|
|
|
[mapping.userId]: { value: '123456' }, // 测试用户ID
|
|
|
|
[mapping.company]: { value: '测试公司' }, |
|
|
|
[mapping.nickName]: { value: '测试联系人' }, |
|
|
|
[mapping.phoneNumber]: { value: '13800138000' }, |
|
|
|
[mapping.type]: { value: '零售客户' }, // 测试客户类型
|
|
|
|
[mapping.city]: { value: '北京' } // 测试地区
|
|
|
|
// 子表字段测试
|
|
|
|
[config.subTableFields.subTable]: { |
|
|
|
value: [{ |
|
|
|
[config.subTableFields.nickName]: { value: '测试联系人' }, |
|
|
|
[config.subTableFields.phoneNumber]: { value: '13800138000' } |
|
|
|
}] |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const response = await this.submitDataToForm(testData); |
|
|
|
|