diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/PostMapper.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/PostMapper.java index 4556ce9a..d1bd29d5 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/PostMapper.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/PostMapper.java @@ -9,6 +9,7 @@ import org.apache.ibatis.annotations.Mapper; import java.util.Collection; import java.util.List; +import java.util.Collections; @Mapper public interface PostMapper extends BaseMapperX { @@ -35,4 +36,12 @@ public interface PostMapper extends BaseMapperX { return selectOne(PostDO::getCode, code); } + default List selectByCodes(Collection codes) { + if (codes == null || codes.isEmpty()) { + return Collections.emptyList(); + } + return selectList(new LambdaQueryWrapperX() + .in(PostDO::getCode, codes)); + } + } diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncProcessorImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncProcessorImpl.java index 3c92a184..4db5f260 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncProcessorImpl.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncProcessorImpl.java @@ -322,7 +322,41 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor { if (records.isEmpty()) { return result; } + long batchStart = System.currentTimeMillis(); result.increasePulled(records.size()); + // 预取已有用户,避免逐条查询 + long preloadUsersStart = System.currentTimeMillis(); + Map existingUsers = new HashMap<>(); + List userIds = records.stream() + .map(IWorkHrUserPageRespVO.User::getId) + .filter(Objects::nonNull) + .map(Integer::longValue) + .distinct() + .toList(); + if (!userIds.isEmpty()) { + List users = adminUserMapper.selectBatchIds(userIds); + if (CollUtil.isNotEmpty(users)) { + users.forEach(user -> existingUsers.put(user.getId(), user)); + } + } + long preloadUsersMs = System.currentTimeMillis() - preloadUsersStart; + + // 预取岗位,避免逐条按编码查询 + long preloadPostsStart = System.currentTimeMillis(); + List postCodes = records.stream() + .map(IWorkHrUserPageRespVO.User::getJobtitleid) + .filter(Objects::nonNull) + .map(this::buildJobCode) + .distinct() + .toList(); + if (!postCodes.isEmpty()) { + List posts = postMapper.selectByCodes(postCodes); + if (CollUtil.isNotEmpty(posts)) { + posts.forEach(post -> postCache.put(buildPostCacheKey(post.getCode()), post)); + } + } + long preloadPostsMs = System.currentTimeMillis() - preloadPostsStart; + for (IWorkHrUserPageRespVO.User user : records) { if (user == null) { continue; @@ -344,7 +378,7 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor { CommonStatusEnum status = inactive ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE; // 直接沿用 iWork 原始密码,避免重复格式化造成校验偏差 String externalPassword = trimToNull(user.getPassword()); - AdminUserDO existing = adminUserMapper.selectById(user.getId()); + AdminUserDO existing = user.getId() == null ? null : existingUsers.get(user.getId().longValue()); UserSyncOutcome outcome; if (existing == null) { if (!options.isCreateIfMissing()) { @@ -377,6 +411,9 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor { result.withMessage("同步人员失败: " + ex.getMessage()); } } + long totalMs = System.currentTimeMillis() - batchStart; + log.info("[iWork] 人员批次同步完成 size={} preloadUsersMs={} preloadPostsMs={} totalMs={}", + records.size(), preloadUsersMs, preloadPostsMs, totalMs); return result; } //TODO @@ -495,11 +532,43 @@ public class IWorkSyncProcessorImpl implements IWorkSyncProcessor { UserSaveReqVO req = buildUserSaveReq(source, username, deptId, postId, status); req.setId(existing.getId()); boolean disabledChanged = CommonStatusEnum.isDisable(status.getStatus()) && CommonStatusEnum.isEnable(existing.getStatus()); - adminUserService.updateUser(req); - syncPassword(existing, externalPassword); + boolean infoChanged = isUserInfoChanged(existing, req); + boolean passwordChanged = isPasswordChanged(existing, externalPassword); + + if (!infoChanged && !passwordChanged) { + return new UserSyncOutcome(SyncAction.SKIPPED, false, existing.getId()); + } + + if (infoChanged) { + adminUserService.updateUser(req); + } + if (passwordChanged) { + syncPassword(existing, externalPassword); + } return new UserSyncOutcome(SyncAction.UPDATED, disabledChanged, existing.getId()); } + private boolean isUserInfoChanged(AdminUserDO existing, UserSaveReqVO req) { + if (existing == null || req == null) { + return false; + } + return !Objects.equals(existing.getUsername(), req.getUsername()) + || !Objects.equals(existing.getWorkcode(), req.getWorkcode()) + || !Objects.equals(existing.getNickname(), req.getNickname()) + || !Objects.equals(existing.getRemark(), req.getRemark()) + || !Objects.equals(existing.getEmail(), req.getEmail()) + || !Objects.equals(existing.getMobile(), req.getMobile()) + || !Objects.equals(existing.getSex(), req.getSex()) + || !Objects.equals(existing.getStatus(), req.getStatus()); + } + + private boolean isPasswordChanged(AdminUserDO existing, String externalPassword) { + if (existing == null || StrUtil.isBlank(externalPassword)) { + return false; + } + return !StrUtil.equals(externalPassword, existing.getPassword()); + } + private DeptSaveReqVO buildSubcompanySaveReq(IWorkHrSubcompanyPageRespVO.Subcompany data, Long deptId, Long parentId, diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncServiceImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncServiceImpl.java index 95ac0cdc..bc0e763f 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncServiceImpl.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/integration/iwork/impl/IWorkSyncServiceImpl.java @@ -217,11 +217,14 @@ public class IWorkSyncServiceImpl implements IWorkSyncService { int pagesLimit = reqVO.getMaxPages() == null ? Integer.MAX_VALUE : reqVO.getMaxPages(); int processedPages = 0; for (int page = startPage; processedPages < pagesLimit; page++) { + long pageStart = System.currentTimeMillis(); BatchExecution execution = executor.execute(page, pageSize); + long pageMs = System.currentTimeMillis() - pageStart; if (execution == null || execution.totalPulled == 0) { break; } processedPages++; + log.info("[iWork] 全量同步 {} 页={} pulled={} costMs={}", type, page, execution.totalPulled, pageMs); IWorkSyncBatchStatVO batchStat = new IWorkSyncBatchStatVO(); batchStat.setEntityType(type); batchStat.setPageNumber(page); @@ -403,11 +406,14 @@ public class IWorkSyncServiceImpl implements IWorkSyncService { int pagesLimit = reqVO.getMaxPages() == null ? Integer.MAX_VALUE : reqVO.getMaxPages(); int processedPages = 0; for (int page = startPage; processedPages < pagesLimit; page++) { + long pageStart = System.currentTimeMillis(); BatchExecution execution = executor.execute(page, pageSize); + long pageMs = System.currentTimeMillis() - pageStart; if (execution == null || execution.totalPulled == 0) { break; } processedPages++; + log.info("[iWork] 手动同步 {} 页={} pulled={} costMs={}", type, page, execution.totalPulled, pageMs); IWorkSyncBatchStatVO batchStat = new IWorkSyncBatchStatVO(); batchStat.setEntityType(type); batchStat.setPageNumber(page);