|
@@ -127,97 +127,155 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
|
|
|
*/
|
|
*/
|
|
|
private void executeSync(Long tenantId, String corpId) {
|
|
private void executeSync(Long tenantId, String corpId) {
|
|
|
tenantDataSourceUtil.executeWithResult(tenantId, () -> {
|
|
tenantDataSourceUtil.executeWithResult(tenantId, () -> {
|
|
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
|
+ log.info("========== 开始同步用户数据 ==========");
|
|
|
|
|
+ log.info("租户ID: {}, 企业ID: {}", tenantId, corpId);
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
- // 1. 获取部门列表
|
|
|
|
|
- QwDeptResult userList = qwApiService.getDepartmentList(corpId);
|
|
|
|
|
- List<Department> deptUser = userList.getDepartment();
|
|
|
|
|
- log.info("同步部门数量:{}", deptUser.size());
|
|
|
|
|
|
|
+ // ========== 1. 获取部门列表 ==========
|
|
|
|
|
+ log.info("步骤1: 获取部门列表");
|
|
|
|
|
+ QwDeptResult deptResult = qwApiService.getDepartmentList(corpId);
|
|
|
|
|
+ List<Department> departmentList = deptResult.getDepartment();
|
|
|
|
|
+
|
|
|
|
|
+ if (departmentList == null || departmentList.isEmpty()) {
|
|
|
|
|
+ log.warn("未获取到任何部门,同步结束");
|
|
|
|
|
+ return R.ok("未获取到部门列表");
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("获取到部门数量: {}", departmentList.size());
|
|
|
|
|
|
|
|
- // 2. 获取企业信息和token
|
|
|
|
|
|
|
+ // ========== 2. 获取企业信息和access_token ==========
|
|
|
|
|
+ log.info("步骤2: 获取企业信息和access_token");
|
|
|
QwCompany qwCompany = iQwCompanyService.selectQwCompanyByCorpId(corpId);
|
|
QwCompany qwCompany = iQwCompanyService.selectQwCompanyByCorpId(corpId);
|
|
|
|
|
+ if (qwCompany == null) {
|
|
|
|
|
+ log.error("未找到企业信息, corpId: {}", corpId);
|
|
|
|
|
+ return R.error("未找到企业信息");
|
|
|
|
|
+ }
|
|
|
String accessToken = qwApiService.getToken(corpId, qwCompany.getPermanentCode());
|
|
String accessToken = qwApiService.getToken(corpId, qwCompany.getPermanentCode());
|
|
|
|
|
+ log.info("获取access_token成功");
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 3. 批量获取所有部门的用户(去重) ==========
|
|
|
|
|
+ log.info("步骤3: 遍历所有部门获取用户列表");
|
|
|
|
|
+ Map<String, DeptUserResult> userMap = new ConcurrentHashMap<>();
|
|
|
|
|
+ int totalDeptUsers = 0;
|
|
|
|
|
+ int emptyDeptCount = 0;
|
|
|
|
|
+
|
|
|
|
|
+ for (Department department : departmentList) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ log.debug("正在获取部门 [{}] {} 的用户列表", department.getId(), department.getName());
|
|
|
|
|
+ UserResult userResult = qwApiService.getUserSimpleList(corpId, accessToken, department.getId());
|
|
|
|
|
+ List<DeptUserResult> deptUsers = userResult.getUserlist();
|
|
|
|
|
+
|
|
|
|
|
+ if (deptUsers == null || deptUsers.isEmpty()) {
|
|
|
|
|
+ log.debug("部门 [{}] {} 没有用户", department.getId(), department.getName());
|
|
|
|
|
+ emptyDeptCount++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 使用putIfAbsent实现去重(保留第一次出现的用户信息)
|
|
|
|
|
+ for (DeptUserResult user : deptUsers) {
|
|
|
|
|
+ userMap.putIfAbsent(user.getUserid(), user);
|
|
|
|
|
+ }
|
|
|
|
|
+ totalDeptUsers += deptUsers.size();
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("获取部门 [{}] {} 的用户列表失败", department.getId(), department.getName(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("部门统计: 总部门数={}, 空部门数={}, 原始用户总数={}, 去重后用户数={}",
|
|
|
|
|
+ departmentList.size(), emptyDeptCount, totalDeptUsers, userMap.size());
|
|
|
|
|
|
|
|
- // 3. 批量获取所有部门用户
|
|
|
|
|
- Map<String, DeptUserResult> userMap = deptUser.parallelStream()
|
|
|
|
|
- .flatMap(department -> {
|
|
|
|
|
- try {
|
|
|
|
|
- log.info("正在获取部门 {} 的用户列表", department.getId());
|
|
|
|
|
- UserResult userResult = qwApiService.getUserSimpleList(corpId, accessToken, department.getId());
|
|
|
|
|
- List<DeptUserResult> deptUserResults = userResult.getUserlist();
|
|
|
|
|
- if (deptUserResults == null || deptUserResults.isEmpty()) {
|
|
|
|
|
- log.warn("部门 {} 没有用户", department.getId());
|
|
|
|
|
- return Stream.empty();
|
|
|
|
|
- }
|
|
|
|
|
- return deptUserResults.stream();
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("获取部门 {} 用户失败", department.getId(), e);
|
|
|
|
|
- return Stream.empty();
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .collect(Collectors.toMap(
|
|
|
|
|
- DeptUserResult::getUserid,
|
|
|
|
|
- Function.identity(),
|
|
|
|
|
- (existing, replacement) -> existing
|
|
|
|
|
- ));
|
|
|
|
|
-
|
|
|
|
|
- log.info("去重后用户总数:{}", userMap.size());
|
|
|
|
|
if (userMap.isEmpty()) {
|
|
if (userMap.isEmpty()) {
|
|
|
log.info("无用户需要同步");
|
|
log.info("无用户需要同步");
|
|
|
return R.ok("无用户需要同步");
|
|
return R.ok("无用户需要同步");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 4. 批量查询现有用户
|
|
|
|
|
|
|
+ // ========== 4. 查询数据库中已存在的用户 ==========
|
|
|
|
|
+ log.info("步骤4: 查询数据库中已存在的用户");
|
|
|
List<String> userIds = new ArrayList<>(userMap.keySet());
|
|
List<String> userIds = new ArrayList<>(userMap.keySet());
|
|
|
List<QwUser> existingUsers = qwUserMapper.selectQwUsersByCorpIdAndUserIds(corpId, userIds);
|
|
List<QwUser> existingUsers = qwUserMapper.selectQwUsersByCorpIdAndUserIds(corpId, userIds);
|
|
|
Map<String, QwUser> existingUserMap = existingUsers.stream()
|
|
Map<String, QwUser> existingUserMap = existingUsers.stream()
|
|
|
.collect(Collectors.toMap(QwUser::getQwOpenUserId, Function.identity()));
|
|
.collect(Collectors.toMap(QwUser::getQwOpenUserId, Function.identity()));
|
|
|
|
|
|
|
|
- // 5. 批量获取用户详细信息
|
|
|
|
|
|
|
+ log.info("数据库已存在用户数: {}, 新增用户数: {}",
|
|
|
|
|
+ existingUserMap.size(), userIds.size() - existingUserMap.size());
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 5. 批量获取用户详细信息并构建处理对象 ==========
|
|
|
|
|
+ log.info("步骤5: 批量处理用户详情(每批100个)");
|
|
|
List<QwUser> usersToProcess = new ArrayList<>();
|
|
List<QwUser> usersToProcess = new ArrayList<>();
|
|
|
List<List<String>> batches = Lists.partition(userIds, 100);
|
|
List<List<String>> batches = Lists.partition(userIds, 100);
|
|
|
|
|
|
|
|
- for (List<String> batch : batches) {
|
|
|
|
|
- List<QwUser> batchUsers = batch.parallelStream()
|
|
|
|
|
- .map(userId -> {
|
|
|
|
|
- try {
|
|
|
|
|
- DeptUserResult user = userMap.get(userId);
|
|
|
|
|
- QwUser existingQwUser = existingUserMap.get(userId);
|
|
|
|
|
|
|
+ int successCount = 0;
|
|
|
|
|
+ int errorCount = 0;
|
|
|
|
|
+
|
|
|
|
|
+ for (int batchIndex = 0; batchIndex < batches.size(); batchIndex++) {
|
|
|
|
|
+ List<String> batch = batches.get(batchIndex);
|
|
|
|
|
+ log.info("处理第 {}/{} 批,本批用户数: {}", batchIndex + 1, batches.size(), batch.size());
|
|
|
|
|
+
|
|
|
|
|
+ List<QwUser> batchUsers = new ArrayList<>();
|
|
|
|
|
+ for (String userId : batch) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ DeptUserResult apiUser = userMap.get(userId);
|
|
|
|
|
+ if (apiUser == null) {
|
|
|
|
|
+ log.warn("用户 {} 在API结果中不存在,跳过", userId);
|
|
|
|
|
+ errorCount++;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 判断是否需要更新
|
|
|
|
|
- if (existingQwUser != null && !needUpdateUserInfo(existingQwUser)) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ QwUser existingQwUser = existingUserMap.get(userId);
|
|
|
|
|
+ boolean isNewUser = (existingQwUser == null);
|
|
|
|
|
|
|
|
- // 转换openid
|
|
|
|
|
- QwOpenidByUserParams param = new QwOpenidByUserParams();
|
|
|
|
|
- param.setUserid(userId);
|
|
|
|
|
- QwOpenidResult qwOpenidResult = qwApiService.useridToOpenid(param, corpId);
|
|
|
|
|
-
|
|
|
|
|
- QwUser qwUser = new QwUser();
|
|
|
|
|
- qwUser.setDepartment(user.getDepartment().toString());
|
|
|
|
|
- qwUser.setQwUserName(user.getName());
|
|
|
|
|
- qwUser.setCorpId(corpId);
|
|
|
|
|
- qwUser.setOpenid(qwOpenidResult.getOpenid());
|
|
|
|
|
- qwUser.setQwOpenUserId(userId);
|
|
|
|
|
-
|
|
|
|
|
- if (existingQwUser != null) {
|
|
|
|
|
- qwUser.setId(existingQwUser.getId());
|
|
|
|
|
- qwUser.setIsDel(0);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 调用API转换openid
|
|
|
|
|
+ QwOpenidByUserParams params = new QwOpenidByUserParams();
|
|
|
|
|
+ params.setUserid(userId);
|
|
|
|
|
+ QwOpenidResult openidResult = qwApiService.useridToOpenid(params, corpId);
|
|
|
|
|
|
|
|
- return qwUser;
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("处理用户失败,userId: {}", userId, e);
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- .filter(Objects::nonNull)
|
|
|
|
|
- .collect(Collectors.toList());
|
|
|
|
|
|
|
+ // 构建QwUser对象
|
|
|
|
|
+ QwUser qwUser = new QwUser();
|
|
|
|
|
+
|
|
|
|
|
+ // 设置部门(取第一个部门)
|
|
|
|
|
+ List<Integer> departmentList_ = apiUser.getDepartment();
|
|
|
|
|
+ if (departmentList_ != null && !departmentList_.isEmpty()) {
|
|
|
|
|
+ qwUser.setDepartment(String.valueOf(departmentList_.get(0)));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ qwUser.setDepartment("");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ qwUser.setQwUserName(apiUser.getName());
|
|
|
|
|
+ qwUser.setCorpId(corpId);
|
|
|
|
|
+ qwUser.setOpenid(openidResult.getOpenid());
|
|
|
|
|
+ qwUser.setQwOpenUserId(userId);
|
|
|
|
|
+
|
|
|
|
|
+ // 设置id(存在则设置,不存在则为null)
|
|
|
|
|
+ if (existingQwUser != null) {
|
|
|
|
|
+ qwUser.setId(existingQwUser.getId());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ qwUser.setId(null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ batchUsers.add(qwUser);
|
|
|
|
|
+ successCount++;
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("处理用户失败,userId: {}", userId, e);
|
|
|
|
|
+ errorCount++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
usersToProcess.addAll(batchUsers);
|
|
usersToProcess.addAll(batchUsers);
|
|
|
|
|
+ log.info("第 {} 批处理完成: 成功={}, 失败={}", batchIndex + 1, batchUsers.size(), batch.size() - batchUsers.size());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("用户处理统计: 成功={}, 失败={}", successCount, errorCount);
|
|
|
|
|
+ log.info("最终待处理用户数: {}", usersToProcess.size());
|
|
|
|
|
+
|
|
|
|
|
+ if (usersToProcess.isEmpty()) {
|
|
|
|
|
+ log.info("没有需要新增或更新的用户");
|
|
|
|
|
+ return R.ok(String.format("同步完成: 失败%d个", errorCount));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 6. 批量数据库操作
|
|
|
|
|
|
|
+ // ========== 6. 批量数据库操作 ==========
|
|
|
|
|
+ log.info("步骤6: 执行数据库批量操作");
|
|
|
List<QwUser> toInsert = usersToProcess.stream()
|
|
List<QwUser> toInsert = usersToProcess.stream()
|
|
|
.filter(u -> u.getId() == null)
|
|
.filter(u -> u.getId() == null)
|
|
|
.collect(Collectors.toList());
|
|
.collect(Collectors.toList());
|
|
@@ -225,21 +283,35 @@ public class OpenQwApiServiceImpl implements OpenQwApiService {
|
|
|
.filter(u -> u.getId() != null)
|
|
.filter(u -> u.getId() != null)
|
|
|
.collect(Collectors.toList());
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
- int successCount = 0;
|
|
|
|
|
|
|
+ log.info("数据库操作: 待新增{}条, 待更新{}条", toInsert.size(), toUpdate.size());
|
|
|
|
|
+
|
|
|
|
|
+ int insertSuccess = 0;
|
|
|
|
|
+ int updateSuccess = 0;
|
|
|
|
|
+
|
|
|
if (!toInsert.isEmpty()) {
|
|
if (!toInsert.isEmpty()) {
|
|
|
- successCount += qwUserMapper.batchInsertQwUser(toInsert);
|
|
|
|
|
- log.info("批量新增用户:{}", toInsert.size());
|
|
|
|
|
|
|
+ insertSuccess = qwUserMapper.batchUpdateQwUser(toInsert);
|
|
|
|
|
+ log.info("批量新增用户成功: {}条", insertSuccess);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
if (!toUpdate.isEmpty()) {
|
|
if (!toUpdate.isEmpty()) {
|
|
|
- successCount += qwUserMapper.batchUpdateQwUser(toUpdate);
|
|
|
|
|
- log.info("批量更新用户:{}", toUpdate.size());
|
|
|
|
|
|
|
+ updateSuccess = qwUserMapper.batchUpdateQwUser(toUpdate);
|
|
|
|
|
+ log.info("批量更新用户成功: {}条", updateSuccess);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- log.info("同步完成,成功:{},失败:{}", successCount, usersToProcess.size() - successCount);
|
|
|
|
|
- return R.ok(String.format("同步完成,成功%d个,失败%d个", successCount, usersToProcess.size() - successCount));
|
|
|
|
|
|
|
+ long endTime = System.currentTimeMillis();
|
|
|
|
|
+ String resultMsg = String.format(
|
|
|
|
|
+ "同步完成!总耗时: %d ms | 新增: %d/%d | 更新: %d/%d | 失败: %d",
|
|
|
|
|
+ (endTime - startTime), insertSuccess, toInsert.size(),
|
|
|
|
|
+ updateSuccess, toUpdate.size(), errorCount
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ log.info(resultMsg);
|
|
|
|
|
+ log.info("========== 用户同步结束 ==========");
|
|
|
|
|
+
|
|
|
|
|
+ return R.ok(resultMsg);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- log.error("同步用户过程异常", e);
|
|
|
|
|
|
|
+ log.error("同步用户过程发生异常", e);
|
|
|
return R.error("同步失败:" + e.getMessage());
|
|
return R.error("同步失败:" + e.getMessage());
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|