Browse Source

完成简道云动态配置和同步状态管理功能

JDY3
Trae AI 1 month ago
parent
commit
719285eda0
  1. 15
      index.js
  2. 103
      src/config/config.js
  3. 7
      src/services/databaseService.js
  4. 94
      src/services/jiandaoyunService.js
  5. 72
      test-single-user.js

15
index.js

@ -24,17 +24,8 @@ async function syncData() {
console.log('开始向简道云提交数据...');
const results = await jiandaoyunService.batchSubmitData(syncData, connection);
// 4. 更新同步状态
console.log('\n更新同步状态...');
for (let i = 0; i < results.length; i++) {
const result = results[i];
const data = syncData[i];
if (result.success && !result.skipped) {
// 同步成功且未被跳过,更新状态为已同步
await databaseService.updateSyncStatus(data.userId, true);
}
}
// 4. 同步状态已在jiandaoyunService.js中更新,此处不再重复更新
console.log('\n同步状态已在提交过程中更新');
// 5. 统计结果
const successCount = results.filter(result => result.success).length;
@ -131,4 +122,4 @@ async function startAutoSync() {
main().catch(error => {
console.error('程序执行失败:', error.message);
process.exit(1);
});
});

103
src/config/config.js

@ -36,15 +36,102 @@ module.exports = {
}
},
// 简道云配置
// 简道云配置 - 根据sync_statuss值不同使用不同配置
jiandaoyun: {
appId: '684bd1da61702bed58d15d13',
entryId: '6822e45e5b34abd7d81f34b5',
apiKey: 'JgTzhmiwlwzz4LWl4dJ4FGZ6yr3VqxoW',
apiUrl: 'https://api.jiandaoyun.com/api/v1'
default: {
appId: '684bd1da61702bed58d15d13',
entryId: '6822e45e5b34abd7d81f34b5',
apiKey: 'JgTzhmiwlwzz4LWl4dJ4FGZ6yr3VqxoW',
apiUrl: 'https://api.jiandaoyun.com/api/v1',
fieldMapping: {
'userId': '_widget_1767422700667',
'userName': '_widget_1747117151082',
'company': '_widget_1747117151075',
'level': '_widget_1755333366982',
'demand': '_widget_1757035166649',
'region': '_widget_1749864292852',
'detailedaddress': '_widget_1747204368174',
'type': '_widget_1768897870066',
'followup': '_widget_1767426290793'
},
subTableFields: {
'subTable': '_widget_1747117151085',
'nickName': '_widget_1747117151087',
'phoneNumber': '_widget_1747117151088',
'detailedaddress': '_widget_1747204368174'
}
},
// sync_statuss=1时的配置
1: {
appId: '684bd1da61702bed58d15d13',
entryId: '6822f75848b106daeab8a284',
apiKey: 'JgTzhmiwlwzz4LWl4dJ4FGZ6yr3VqxoW',
apiUrl: 'https://api.jiandaoyun.com/api/v1',
fieldMapping: {
'userId': '_widget_1767426694297',
'userName': '_widget_1747186159197',
'company': '_widget_1747122009104',
'level': '_widget_1754983406535',
'demand': '_widget_1749870821108',
'region': '_widget_1749870420548',
'detailedaddress': '_widget_1747204368174',
'type': '_widget_1747122009109',
'followup': '_widget_1767426694300'
},
subTableFields: {
'subTable': '_widget_1747122009118',
'nickName': '_widget_1747122009120',
'phoneNumber': '_widget_1747122009121',
'detailedaddress': '_widget_1747204368174'
}
},
// sync_statuss=2时的配置
2: {
appId: '681db12023f2ca535ff29cfc',
entryId: '681dc81e821222305984219e',
apiKey: 'JgTzhmiwlwzz4LWl4dJ4FGZ6yr3VqxoW',
apiUrl: 'https://api.jiandaoyun.com/api/v1',
fieldMapping: {
'userId': '_widget_1769138938780',
'userName': '_widget_1747364014473',
'company': '_widget_1746782238762',
'level': '_widget_1746782238764',
'demand': '_widget_1747374154860',
'region': '_widget_1749870420548',
'detailedaddress': '_widget_1747204368174',
'type': '_widget_1746782238763',
'followup': '_widget_1769138938795'
},
subTableFields: {
'subTable': '_widget_1747105269437',
'nickName': '_widget_1747105269440',
'phoneNumber': '_widget_1747364014484',
'detailedaddress': '_widget_1747204368174'
}
},
// sync_statuss=3时的配置
3: {
appId: '681db12023f2ca535ff29cfc',
entryId: '6826ec6872f007130d304d9c',
apiKey: 'JgTzhmiwlwzz4LWl4dJ4FGZ6yr3VqxoW',
apiUrl: 'https://api.jiandaoyun.com/api/v1',
fieldMapping: {
'userId': '_widget_1769157566033',
'userName': '_widget_1747381352563',
'company': '_widget_1747381352567',
'demand': '_widget_1747381352569',
'type': '_widget_1747381352568',
'followup': '_widget_1769157566032'
},
subTableFields: {
'subTable': '_widget_1747385370675',
'nickName': '_widget_1747385370677',
'phoneNumber': '_widget_1747385370678'
}
}
},
// 字段映射关系
// 保持原配置结构兼容,默认使用default配置
fieldMapping: {
'userId': '_widget_1767422700667',
'userName': '_widget_1747117151082',
@ -57,7 +144,7 @@ module.exports = {
'followup': '_widget_1767426290793'
},
// 子表字段配置
// 保持原配置结构兼容,默认使用default配置
subTableFields: {
'subTable': '_widget_1747117151085',
'nickName': '_widget_1747117151087',
@ -72,7 +159,7 @@ module.exports = {
// 同步状态字段
statusField: 'sync_statuss',
// 已同步状态值
syncedValue: 1,
syncedValue: 4,
// 未同步状态值
unsyncedValue: 0,
// 自动同步配置

7
src/services/databaseService.js

@ -47,13 +47,14 @@ class DatabaseService {
${config.tables.users.fields.detailedaddress},
${config.tables.users.fields.type},
${config.tables.users.fields.followup},
${config.sync.statusField},
dataid
FROM ${config.tables.users.name}`;
// 如果是增量同步,查询未同步的数据
// 如果是增量同步,查询sync_statuss为0、1、2、3的数据(只有4是已同步状态)
if (config.sync.incremental) {
usersQuery += ` WHERE ${config.sync.statusField} = ${config.sync.unsyncedValue}`;
console.log('启用增量同步模式,查询未同步数据');
usersQuery += ` WHERE ${config.sync.statusField} IN (0, 1, 2, 3)`;
console.log('启用增量同步模式,查询sync_statuss为0、1、2、3的数据');
} else {
console.log('启用全量同步模式,查询所有数据');
}

94
src/services/jiandaoyunService.js

@ -6,9 +6,8 @@ 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;
// 从配置中获取apiKey(所有表单共享)
this.apiKey = config.jiandaoyun.default.apiKey;
// 人员简道云编号映射表
this.userNameToUsernameMap = {
@ -33,11 +32,26 @@ class JiandaoyunService {
};
}
// 根据syncStatus获取对应的表单配置
getFormConfig(syncStatus) {
// 如果syncStatus为0或未定义,使用默认配置
if (!syncStatus || syncStatus === 0) {
return config.jiandaoyun.default;
}
// 否则使用对应的配置,如果不存在则使用默认配置
return config.jiandaoyun[syncStatus] || config.jiandaoyun.default;
}
// 提交数据到简道云表单
async submitDataToForm(data, userManagement = null) {
async submitDataToForm(data, userManagement = null, syncStatus = 0) {
try {
console.log('准备提交数据到简道云:', JSON.stringify(data, null, 2));
// 根据syncStatus获取对应的表单配置
const formConfig = this.getFormConfig(syncStatus);
const appId = formConfig.appId;
const entryId = formConfig.entryId;
// 使用简道云API v5版本,支持data_creator参数
const url = `${this.baseUrl}/api/v5/app/entry/data/create`;
const headers = {
@ -61,8 +75,8 @@ class JiandaoyunService {
// 构建请求体,添加data_creator参数
const payload = {
app_id: this.appId,
entry_id: this.entryId,
app_id: appId,
entry_id: entryId,
data: data,
data_creator: dataCreator
};
@ -92,11 +106,16 @@ class JiandaoyunService {
}
// 将数据库数据转换为简道云表单所需格式
transformDataToJiandaoyunFormat(databaseData) {
transformDataToJiandaoyunFormat(databaseData, syncStatus) {
console.log('开始转换数据:', JSON.stringify(databaseData, null, 2));
console.log('使用的syncStatus:', syncStatus);
// 根据syncStatus获取对应的表单配置
const formConfig = this.getFormConfig(syncStatus);
const mapping = formConfig.fieldMapping;
const subTableConfig = formConfig.subTableFields;
const jiandaoyunData = {};
const mapping = config.fieldMapping;
// 转换主表数据
const user = databaseData.user;
@ -131,12 +150,12 @@ class JiandaoyunService {
jiandaoyunData[mapping.followup] = { value: user.followup || '' };
// 处理子表字段
const subTableField = config.subTableFields.subTable;
const subTableField = subTableConfig.subTable;
const subTableData = [{
[config.subTableFields.nickName]: { value: user.nickName || '' },
[config.subTableFields.phoneNumber]: { value: user.phoneNumber || '' },
[subTableConfig.nickName]: { value: user.nickName || '' },
[subTableConfig.phoneNumber]: { value: user.phoneNumber || '' },
// 地址字段直接作为字符串写入子表
[config.subTableFields.detailedaddress]: { value: user.detailedaddress || '' }
[subTableConfig.detailedaddress]: { value: user.detailedaddress || '' }
}];
jiandaoyunData[subTableField] = { value: subTableData };
@ -209,27 +228,31 @@ class JiandaoyunService {
console.log(`从数据库获取到简道云记录ID: ${recordId}`);
}
// 获取sync_statuss值,默认为0
const syncStatus = item.user[config.sync.statusField] || 0;
console.log(`当前用户的sync_statuss值: ${syncStatus}`);
if (recordId) {
console.log(`使用记录ID ${recordId} 更新数据`);
// 转换数据格式
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item);
// 转换数据格式,传递syncStatus
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item, syncStatus);
try {
// 更新数据,传递userManagement参数
const result = await this.updateDataInForm(recordId, jiandaoyunData, item.userManagement);
// 更新数据,传递userManagement参数和syncStatus
const result = await this.updateDataInForm(recordId, jiandaoyunData, item.userManagement, syncStatus);
// 更新数据库中的同步状态
if (dbConnection && item.user && item.user.userId) {
try {
console.log(`更新用户 ${item.user.userId} 的同步状态`);
console.log(`更新用户 ${item.user.userId} 的同步状态${config.sync.syncedValue}`);
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} 的同步状态`);
console.log(`✅ 成功更新用户 ${item.user.userId} 的同步状态${config.sync.syncedValue}`);
} else {
console.log(`⚠️ 更新用户 ${item.user.userId} 的同步状态失败: 未找到匹配的用户`);
}
@ -271,11 +294,11 @@ class JiandaoyunService {
}
}
// 转换数据格式
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item);
// 转换数据格式,传递syncStatus
const jiandaoyunData = this.transformDataToJiandaoyunFormat(item, syncStatus);
// 提交数据,传递userManagement参数
const result = await this.submitDataToForm(jiandaoyunData, item.userManagement);
// 提交数据,传递userManagement参数和syncStatus
const result = await this.submitDataToForm(jiandaoyunData, item.userManagement, syncStatus);
// 保存返回的记录ID到数据库
console.log('检查返回结果结构:', JSON.stringify(result, null, 2));
@ -286,7 +309,7 @@ class JiandaoyunService {
if (dbConnection && item.user && item.user.userId) {
try {
console.log(`准备更新用户 ${item.user.userId} 的dataid为 ${newRecordId} 并设置同步状态`);
console.log(`准备更新用户 ${item.user.userId} 的dataid为 ${newRecordId} 并设置同步状态${config.sync.syncedValue}`);
const [updateResult] = await dbConnection.execute(
`UPDATE ${config.tables.users.name} SET dataid = ?, ${config.sync.statusField} = ${config.sync.syncedValue} WHERE userId = ?`,
[newRecordId, item.user.userId]
@ -294,7 +317,7 @@ class JiandaoyunService {
console.log(`数据库更新结果:`, updateResult);
if (updateResult.affectedRows > 0) {
console.log(`✅ 成功将简道云记录ID ${newRecordId} 保存到数据库并更新同步状态`);
console.log(`✅ 成功将简道云记录ID ${newRecordId} 保存到数据库并更新同步状态${config.sync.syncedValue}`);
} else {
console.log(`⚠️ 更新用户 ${item.user.userId} 的dataid和同步状态失败: 未找到匹配的用户`);
}
@ -349,8 +372,13 @@ class JiandaoyunService {
}
// 更新简道云表单中的数据
async updateDataInForm(recordId, data, userManagement = null) {
async updateDataInForm(recordId, data, userManagement = null, syncStatus = 0) {
try {
// 根据syncStatus获取对应的表单配置
const formConfig = this.getFormConfig(syncStatus);
const appId = formConfig.appId;
const entryId = formConfig.entryId;
// 使用简道云API v5版本,支持data_creator参数
const url = `${this.baseUrl}/api/v5/app/entry/data/update`;
const headers = {
@ -374,8 +402,8 @@ class JiandaoyunService {
// 构建更新请求体:记录ID和要更新的数据
const payload = {
app_id: this.appId,
entry_id: this.entryId,
app_id: appId,
entry_id: entryId,
data_id: recordId,
data: data,
data_creator: dataCreator
@ -389,13 +417,13 @@ class JiandaoyunService {
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));
console.error('更新数据失败:', error.message);
if (error.response) {
console.error('响应状态:', error.response.status);
console.error('响应数据:', JSON.stringify(error.response.data, null, 2));
}
throw error;
}
throw error;
}
}
// 测试简道云API连接

72
test-single-user.js

@ -1,72 +0,0 @@
// 测试单个用户数据同步
const mysql = require('mysql2/promise');
const config = require('./src/config/config');
const jiandaoyunService = require('./src/services/jiandaoyunService');
async function testSingleUserSync() {
console.log('===== 测试单个用户数据同步 =====');
try {
// 连接数据库
const connection = await mysql.createConnection(config.db);
// 查询指定用户数据
const [users] = await connection.execute(
`SELECT DISTINCT ${config.tables.users.fields.userId},
${config.tables.users.fields.nickName},
${config.tables.users.fields.phoneNumber},
${config.tables.users.fields.company},
${config.tables.users.fields.level},
${config.tables.users.fields.demand},
${config.tables.users.fields.region},
${config.tables.users.fields.detailedaddress},
${config.tables.users.fields.type},
dataid
FROM ${config.tables.users.name}
WHERE ${config.tables.users.fields.userId} = ?`,
['user_1768360161521_zz8rtwtip']
);
if (users.length === 0) {
console.log('未找到指定用户数据');
return;
}
const user = users[0];
console.log('用户数据:', JSON.stringify(user, null, 2));
// 查询负责人信息
const [userManagements] = await connection.execute(
`SELECT ${config.tables.userManagements.fields.userName}
FROM ${config.tables.userManagements.name}
WHERE ${config.tables.userManagements.fields.userId} = ?`,
[user.userId]
);
const syncData = [{
user: user,
userManagement: userManagements[0] || {},
userId: user.userId
}];
// 转换数据格式
const transformedData = jiandaoyunService.transformDataToJiandaoyunFormat(syncData[0]);
console.log('转换后的数据:', JSON.stringify(transformedData, null, 2));
// 检查地址字段是否正确包含在子表中
const subTableData = transformedData[config.subTableFields.subTable].value;
console.log('子表数据:', JSON.stringify(subTableData, null, 2));
// 执行同步
const results = await jiandaoyunService.batchSubmitData(syncData, connection);
console.log('同步结果:', JSON.stringify(results, null, 2));
await connection.end();
console.log('测试完成');
} catch (error) {
console.error('测试过程中发生错误:', error.message);
console.error('错误堆栈:', error.stack);
}
}
testSingleUserSync();
Loading…
Cancel
Save