diff --git a/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userdept/UserDeptSyncServiceImpl.java b/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userdept/UserDeptSyncServiceImpl.java
index 9027e379..04f16ae4 100644
--- a/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userdept/UserDeptSyncServiceImpl.java
+++ b/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userdept/UserDeptSyncServiceImpl.java
@@ -1,56 +1,101 @@
package com.zt.plat.framework.databus.client.handler.userdept;
import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
+import com.zt.plat.module.system.api.userdept.UserDeptApi;
+import com.zt.plat.module.system.api.userdept.dto.UserDeptSaveReqDTO;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
- * 用户-部门关系同步服务实现
+ * 用户-部门关系同步服务实现(通过 Feign API 调用远程服务)
*
* 使用条件:
* 1. zt.databus.sync.client.enabled=true
+ * 2. 系统中存在 UserDeptApi 接口(Feign 客户端)
*
- * 注意:由于用户-部门关系通常集成在用户管理中,此实现为占位符。
- * 分公司可以根据实际情况:
- * 1. 自定义实现此接口,直接操作本地数据库
- * 2. 或者通过用户管理 API 间接处理关联关系
+ * 如果分公司需要自定义实现,可以创建自己的 UserDeptSyncService Bean,
+ * 此默认实现会自动失效(@ConditionalOnMissingBean)
*
* @author ZT
*/
@Slf4j
@Service
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
+@ConditionalOnClass(name = "com.zt.plat.module.system.api.userdept.UserDeptApi")
public class UserDeptSyncServiceImpl implements UserDeptSyncService {
+ @Autowired(required = false)
+ private UserDeptApi userDeptApi; // Feign 远程调用接口
+
@Override
public void create(DatabusUserDeptData data) {
- log.info("[UserDeptSync] 收到创建用户-部门关系请求, userId={}, deptId={}",
- data.getUserId(), data.getDeptId());
- log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法,通过本地 API 或直接数据库操作完成同步
+ if (userDeptApi == null) {
+ log.warn("[UserDeptSync] UserDeptApi未注入,跳过创建用户-部门关系, userId={}", data.getUserId());
+ return;
+ }
+ UserDeptSaveReqDTO dto = buildUserDeptDTO(data);
+ userDeptApi.createUserDept(dto).checkError();
+ log.info("[UserDeptSync] 用户-部门关系创建成功, userId={}, deptId={}", data.getUserId(), data.getDeptId());
}
@Override
public void update(DatabusUserDeptData data) {
- log.info("[UserDeptSync] 收到更新用户-部门关系请求, userId={}, deptId={}",
- data.getUserId(), data.getDeptId());
- log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法
+ if (userDeptApi == null) {
+ log.warn("[UserDeptSync] UserDeptApi未注入,跳过更新用户-部门关系, userId={}", data.getUserId());
+ return;
+ }
+ UserDeptSaveReqDTO dto = buildUserDeptDTO(data);
+ userDeptApi.updateUserDept(dto).checkError();
+ log.info("[UserDeptSync] 用户-部门关系更新成功, userId={}, deptId={}", data.getUserId(), data.getDeptId());
}
@Override
public void delete(Long id) {
- log.info("[UserDeptSync] 收到删除用户-部门关系请求, id={}", id);
- log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法
+ if (userDeptApi == null) {
+ log.warn("[UserDeptSync] UserDeptApi未注入,跳过删除用户-部门关系, id={}", id);
+ return;
+ }
+ userDeptApi.deleteUserDept(id).checkError();
+ log.info("[UserDeptSync] 用户-部门关系删除成功, id={}", id);
}
@Override
public void fullSync(DatabusUserDeptData data) {
- log.info("[UserDeptSync] 收到全量同步用户-部门关系请求, userId={}, deptId={}",
- data.getUserId(), data.getDeptId());
- log.warn("[UserDeptSync] 用户-部门关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法,逻辑:存在则更新,不存在则插入
+ if (userDeptApi == null) {
+ log.warn("[UserDeptSync] UserDeptApi未注入,跳过全量同步用户-部门关系, userId={}", data.getUserId());
+ return;
+ }
+ UserDeptSaveReqDTO dto = buildUserDeptDTO(data);
+ try {
+ // 尝试获取,存在则更新,不存在则创建
+ var existing = userDeptApi.getUserDept(dto.getId());
+ if (existing.isSuccess() && existing.getData() != null) {
+ userDeptApi.updateUserDept(dto).checkError();
+ log.info("[UserDeptSync] 用户-部门关系全量同步-更新成功, id={}", dto.getId());
+ } else {
+ userDeptApi.createUserDept(dto).checkError();
+ log.info("[UserDeptSync] 用户-部门关系全量同步-创建成功, id={}", dto.getId());
+ }
+ } catch (Exception e) {
+ // 获取失败,尝试创建
+ log.warn("[UserDeptSync] 用户-部门关系获取失败,尝试创建, id={}", dto.getId());
+ userDeptApi.createUserDept(dto).checkError();
+ log.info("[UserDeptSync] 用户-部门关系全量同步-创建成功, id={}", dto.getId());
+ }
+ }
+
+ /**
+ * 构建用户部门关系 DTO(用于 Feign 调用)
+ */
+ private UserDeptSaveReqDTO buildUserDeptDTO(DatabusUserDeptData data) {
+ UserDeptSaveReqDTO dto = new UserDeptSaveReqDTO();
+ dto.setId(data.getId());
+ dto.setUserId(data.getUserId());
+ dto.setDeptId(data.getDeptId());
+ dto.setRemark(data.getRemark());
+ return dto;
}
}
diff --git a/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userpost/UserPostSyncServiceImpl.java b/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userpost/UserPostSyncServiceImpl.java
index b41d6ac8..01eb2b4b 100644
--- a/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userpost/UserPostSyncServiceImpl.java
+++ b/zt-framework/zt-spring-boot-starter-databus-client/src/main/java/com/zt/plat/framework/databus/client/handler/userpost/UserPostSyncServiceImpl.java
@@ -1,56 +1,100 @@
package com.zt.plat.framework.databus.client.handler.userpost;
import com.zt.plat.module.databus.api.data.DatabusUserPostData;
+import com.zt.plat.module.system.api.userpost.UserPostApi;
+import com.zt.plat.module.system.api.userpost.dto.UserPostSaveReqDTO;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
/**
- * 用户-岗位关系同步服务实现
+ * 用户-岗位关系同步服务实现(通过 Feign API 调用远程服务)
*
* 使用条件:
* 1. zt.databus.sync.client.enabled=true
+ * 2. 系统中存在 UserPostApi 接口(Feign 客户端)
*
- * 注意:由于用户-岗位关系通常集成在用户管理中,此实现为占位符。
- * 分公司可以根据实际情况:
- * 1. 自定义实现此接口,直接操作本地数据库
- * 2. 或者通过用户管理 API 间接处理关联关系
+ * 如果分公司需要自定义实现,可以创建自己的 UserPostSyncService Bean,
+ * 此默认实现会自动失效(@ConditionalOnMissingBean)
*
* @author ZT
*/
@Slf4j
@Service
@ConditionalOnProperty(prefix = "zt.databus.sync.client", name = "enabled", havingValue = "true")
+@ConditionalOnClass(name = "com.zt.plat.module.system.api.userpost.UserPostApi")
public class UserPostSyncServiceImpl implements UserPostSyncService {
+ @Autowired(required = false)
+ private UserPostApi userPostApi; // Feign 远程调用接口
+
@Override
public void create(DatabusUserPostData data) {
- log.info("[UserPostSync] 收到创建用户-岗位关系请求, userId={}, postId={}",
- data.getUserId(), data.getPostId());
- log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法,通过本地 API 或直接数据库操作完成同步
+ if (userPostApi == null) {
+ log.warn("[UserPostSync] UserPostApi未注入,跳过创建用户-岗位关系, userId={}", data.getUserId());
+ return;
+ }
+ UserPostSaveReqDTO dto = buildUserPostDTO(data);
+ userPostApi.createUserPost(dto).checkError();
+ log.info("[UserPostSync] 用户-岗位关系创建成功, userId={}, postId={}", data.getUserId(), data.getPostId());
}
@Override
public void update(DatabusUserPostData data) {
- log.info("[UserPostSync] 收到更新用户-岗位关系请求, userId={}, postId={}",
- data.getUserId(), data.getPostId());
- log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法
+ if (userPostApi == null) {
+ log.warn("[UserPostSync] UserPostApi未注入,跳过更新用户-岗位关系, userId={}", data.getUserId());
+ return;
+ }
+ UserPostSaveReqDTO dto = buildUserPostDTO(data);
+ userPostApi.updateUserPost(dto).checkError();
+ log.info("[UserPostSync] 用户-岗位关系更新成功, userId={}, postId={}", data.getUserId(), data.getPostId());
}
@Override
public void delete(Long id) {
- log.info("[UserPostSync] 收到删除用户-岗位关系请求, id={}", id);
- log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法
+ if (userPostApi == null) {
+ log.warn("[UserPostSync] UserPostApi未注入,跳过删除用户-岗位关系, id={}", id);
+ return;
+ }
+ userPostApi.deleteUserPost(id).checkError();
+ log.info("[UserPostSync] 用户-岗位关系删除成功, id={}", id);
}
@Override
public void fullSync(DatabusUserPostData data) {
- log.info("[UserPostSync] 收到全量同步用户-岗位关系请求, userId={}, postId={}",
- data.getUserId(), data.getPostId());
- log.warn("[UserPostSync] 用户-岗位关系同步服务需要分公司自定义实现,当前为占位符实现");
- // TODO: 分公司需要实现此方法,逻辑:存在则更新,不存在则插入
+ if (userPostApi == null) {
+ log.warn("[UserPostSync] UserPostApi未注入,跳过全量同步用户-岗位关系, userId={}", data.getUserId());
+ return;
+ }
+ UserPostSaveReqDTO dto = buildUserPostDTO(data);
+ try {
+ // 尝试获取,存在则更新,不存在则创建
+ var existing = userPostApi.getUserPost(dto.getId());
+ if (existing.isSuccess() && existing.getData() != null) {
+ userPostApi.updateUserPost(dto).checkError();
+ log.info("[UserPostSync] 用户-岗位关系全量同步-更新成功, id={}", dto.getId());
+ } else {
+ userPostApi.createUserPost(dto).checkError();
+ log.info("[UserPostSync] 用户-岗位关系全量同步-创建成功, id={}", dto.getId());
+ }
+ } catch (Exception e) {
+ // 获取失败,尝试创建
+ log.warn("[UserPostSync] 用户-岗位关系获取失败,尝试创建, id={}", dto.getId());
+ userPostApi.createUserPost(dto).checkError();
+ log.info("[UserPostSync] 用户-岗位关系全量同步-创建成功, id={}", dto.getId());
+ }
+ }
+
+ /**
+ * 构建用户岗位关系 DTO(用于 Feign 调用)
+ */
+ private UserPostSaveReqDTO buildUserPostDTO(DatabusUserPostData data) {
+ UserPostSaveReqDTO dto = new UserPostSaveReqDTO();
+ dto.setId(data.getId());
+ dto.setUserId(data.getUserId());
+ dto.setPostId(data.getPostId());
+ return dto;
}
}
diff --git a/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/consumer/DatabusUserChangeConsumer.java b/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/consumer/DatabusUserChangeConsumer.java
index dd3a52e0..43fd8e97 100644
--- a/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/consumer/DatabusUserChangeConsumer.java
+++ b/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/consumer/DatabusUserChangeConsumer.java
@@ -34,7 +34,15 @@ public class DatabusUserChangeConsumer implements RocketMQListener dataMap = new HashMap<>();
diff --git a/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/provider/UserDeptDataFeignProvider.java b/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/provider/UserDeptDataFeignProvider.java
new file mode 100644
index 00000000..81f3bcf2
--- /dev/null
+++ b/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/provider/UserDeptDataFeignProvider.java
@@ -0,0 +1,81 @@
+package com.zt.plat.framework.databus.server.provider;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.databus.server.core.provider.DataProvider;
+import com.zt.plat.framework.databus.server.core.provider.DataProviderRegistry;
+import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
+import com.zt.plat.module.databus.api.dto.CursorPageResult;
+import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
+import com.zt.plat.module.databus.api.provider.DatabusUserDeptProviderApi;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户-部门关系数据提供者
+ */
+@Slf4j
+@Component
+public class UserDeptDataFeignProvider implements DataProvider {
+
+ public static final String PROVIDER_TYPE = "USER_DEPT";
+
+ @Resource
+ private DatabusUserDeptProviderApi userDeptProviderApi;
+
+ @Resource
+ private DataProviderRegistry dataProviderRegistry;
+
+ @PostConstruct
+ public void init() {
+ dataProviderRegistry.register(this);
+ }
+
+ @Override
+ public String getProviderType() {
+ return PROVIDER_TYPE;
+ }
+
+ @Override
+ public CursorPageData getPageByCursor(LocalDateTime cursorTime, Long cursorId,
+ int batchSize, Long tenantId) {
+ CursorPageReqDTO reqDTO = CursorPageReqDTO.builder()
+ .cursorTime(cursorTime)
+ .cursorId(cursorId)
+ .batchSize(batchSize)
+ .tenantId(tenantId)
+ .build();
+
+ CommonResult> result = userDeptProviderApi.getPageByCursor(reqDTO);
+ if (!result.isSuccess()) {
+ throw new RuntimeException("获取用户-部门关系数据失败: " + result.getMsg());
+ }
+
+ CursorPageResult pageResult = result.getData();
+ return CursorPageData.of(
+ pageResult.getList(),
+ pageResult.getNextCursorTime(),
+ pageResult.getNextCursorId(),
+ pageResult.getCount(),
+ Boolean.TRUE.equals(pageResult.getHasMore()),
+ (pageResult.getTotal() != null ? pageResult.getTotal() : 0L)
+ );
+ }
+
+ @Override
+ public long count(Long tenantId) {
+ CommonResult result = userDeptProviderApi.count(tenantId);
+ if (!result.isSuccess()) {
+ throw new RuntimeException("获取用户-部门关系总数失败: " + result.getMsg());
+ }
+ return result.getData();
+ }
+
+ @Override
+ public Long extractUid(DatabusUserDeptData data) {
+ return data.getId();
+ }
+}
diff --git a/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/provider/UserPostDataFeignProvider.java b/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/provider/UserPostDataFeignProvider.java
new file mode 100644
index 00000000..b7df241a
--- /dev/null
+++ b/zt-framework/zt-spring-boot-starter-databus-server/src/main/java/com/zt/plat/framework/databus/server/provider/UserPostDataFeignProvider.java
@@ -0,0 +1,81 @@
+package com.zt.plat.framework.databus.server.provider;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.databus.server.core.provider.DataProvider;
+import com.zt.plat.framework.databus.server.core.provider.DataProviderRegistry;
+import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
+import com.zt.plat.module.databus.api.dto.CursorPageResult;
+import com.zt.plat.module.databus.api.data.DatabusUserPostData;
+import com.zt.plat.module.databus.api.provider.DatabusUserPostProviderApi;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户-岗位关系数据提供者
+ */
+@Slf4j
+@Component
+public class UserPostDataFeignProvider implements DataProvider {
+
+ public static final String PROVIDER_TYPE = "USER_POST";
+
+ @Resource
+ private DatabusUserPostProviderApi userPostProviderApi;
+
+ @Resource
+ private DataProviderRegistry dataProviderRegistry;
+
+ @PostConstruct
+ public void init() {
+ dataProviderRegistry.register(this);
+ }
+
+ @Override
+ public String getProviderType() {
+ return PROVIDER_TYPE;
+ }
+
+ @Override
+ public CursorPageData getPageByCursor(LocalDateTime cursorTime, Long cursorId,
+ int batchSize, Long tenantId) {
+ CursorPageReqDTO reqDTO = CursorPageReqDTO.builder()
+ .cursorTime(cursorTime)
+ .cursorId(cursorId)
+ .batchSize(batchSize)
+ .tenantId(tenantId)
+ .build();
+
+ CommonResult> result = userPostProviderApi.getPageByCursor(reqDTO);
+ if (!result.isSuccess()) {
+ throw new RuntimeException("获取用户-岗位关系数据失败: " + result.getMsg());
+ }
+
+ CursorPageResult pageResult = result.getData();
+ return CursorPageData.of(
+ pageResult.getList(),
+ pageResult.getNextCursorTime(),
+ pageResult.getNextCursorId(),
+ pageResult.getCount(),
+ Boolean.TRUE.equals(pageResult.getHasMore()),
+ (pageResult.getTotal() != null ? pageResult.getTotal() : 0L)
+ );
+ }
+
+ @Override
+ public long count(Long tenantId) {
+ CommonResult result = userPostProviderApi.count(tenantId);
+ if (!result.isSuccess()) {
+ throw new RuntimeException("获取用户-岗位关系总数失败: " + result.getMsg());
+ }
+ return result.getData();
+ }
+
+ @Override
+ public Long extractUid(DatabusUserPostData data) {
+ return data.getId();
+ }
+}
diff --git a/zt-module-databus/zt-module-databus-api/src/main/java/com/zt/plat/module/databus/api/provider/DatabusUserDeptProviderApi.java b/zt-module-databus/zt-module-databus-api/src/main/java/com/zt/plat/module/databus/api/provider/DatabusUserDeptProviderApi.java
new file mode 100644
index 00000000..5e393626
--- /dev/null
+++ b/zt-module-databus/zt-module-databus-api/src/main/java/com/zt/plat/module/databus/api/provider/DatabusUserDeptProviderApi.java
@@ -0,0 +1,71 @@
+package com.zt.plat.module.databus.api.provider;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
+import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
+import com.zt.plat.module.databus.api.dto.CursorPageResult;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * Databus 用户-部门关系数据提供者 API
+ *
+ * 供 Databus 调用,获取用户-部门关联数据用于全量/增量同步
+ *
+ * @author ZT
+ */
+@FeignClient(name = "${databus.provider.user-dept.service:system-server}")
+@Tag(name = "RPC 服务 - Databus 用户-部门关系数据提供者")
+public interface DatabusUserDeptProviderApi {
+
+ String PREFIX = "/rpc/databus/user-dept";
+
+ /**
+ * 游标分页查询用户-部门关系数据(用于全量同步)
+ *
+ * @param reqDTO 游标分页请求
+ * @return 用户-部门关系数据分页结果
+ */
+ @PostMapping(PREFIX + "/page-by-cursor")
+ @Operation(summary = "游标分页查询用户-部门关系数据")
+ CommonResult> getPageByCursor(@RequestBody CursorPageReqDTO reqDTO);
+
+ /**
+ * 根据ID查询用户-部门关系详情(用于增量同步)
+ *
+ * @param id 关系ID
+ * @return 用户-部门关系数据
+ */
+ @GetMapping(PREFIX + "/get")
+ @Operation(summary = "查询用户-部门关系详情")
+ @Parameter(name = "id", description = "关系ID", required = true, example = "1001")
+ CommonResult getById(@RequestParam("id") Long id);
+
+ /**
+ * 批量查询用户-部门关系详情(用于增量同步批量获取)
+ *
+ * @param ids 关系ID列表
+ * @return 用户-部门关系数据列表
+ */
+ @GetMapping(PREFIX + "/list")
+ @Operation(summary = "批量查询用户-部门关系详情")
+ @Parameter(name = "ids", description = "关系ID列表", required = true, example = "1001,1002,1003")
+ CommonResult> getListByIds(@RequestParam("ids") List ids);
+
+ /**
+ * 统计用户-部门关系总数(用于全量同步进度计算)
+ *
+ * @param tenantId 租户ID(可选)
+ * @return 用户-部门关系总数
+ */
+ @GetMapping(PREFIX + "/count")
+ @Operation(summary = "统计用户-部门关系总数")
+ @Parameter(name = "tenantId", description = "租户ID", example = "1")
+ CommonResult count(@RequestParam(value = "tenantId", required = false) Long tenantId);
+
+}
diff --git a/zt-module-databus/zt-module-databus-api/src/main/java/com/zt/plat/module/databus/api/provider/DatabusUserPostProviderApi.java b/zt-module-databus/zt-module-databus-api/src/main/java/com/zt/plat/module/databus/api/provider/DatabusUserPostProviderApi.java
new file mode 100644
index 00000000..6e00365d
--- /dev/null
+++ b/zt-module-databus/zt-module-databus-api/src/main/java/com/zt/plat/module/databus/api/provider/DatabusUserPostProviderApi.java
@@ -0,0 +1,71 @@
+package com.zt.plat.module.databus.api.provider;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.databus.api.data.DatabusUserPostData;
+import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
+import com.zt.plat.module.databus.api.dto.CursorPageResult;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * Databus 用户-岗位关系数据提供者 API
+ *
+ * 供 Databus 调用,获取用户-岗位关联数据用于全量/增量同步
+ *
+ * @author ZT
+ */
+@FeignClient(name = "${databus.provider.user-post.service:system-server}")
+@Tag(name = "RPC 服务 - Databus 用户-岗位关系数据提供者")
+public interface DatabusUserPostProviderApi {
+
+ String PREFIX = "/rpc/databus/user-post";
+
+ /**
+ * 游标分页查询用户-岗位关系数据(用于全量同步)
+ *
+ * @param reqDTO 游标分页请求
+ * @return 用户-岗位关系数据分页结果
+ */
+ @PostMapping(PREFIX + "/page-by-cursor")
+ @Operation(summary = "游标分页查询用户-岗位关系数据")
+ CommonResult> getPageByCursor(@RequestBody CursorPageReqDTO reqDTO);
+
+ /**
+ * 根据ID查询用户-岗位关系详情(用于增量同步)
+ *
+ * @param id 关系ID
+ * @return 用户-岗位关系数据
+ */
+ @GetMapping(PREFIX + "/get")
+ @Operation(summary = "查询用户-岗位关系详情")
+ @Parameter(name = "id", description = "关系ID", required = true, example = "1001")
+ CommonResult getById(@RequestParam("id") Long id);
+
+ /**
+ * 批量查询用户-岗位关系详情(用于增量同步批量获取)
+ *
+ * @param ids 关系ID列表
+ * @return 用户-岗位关系数据列表
+ */
+ @GetMapping(PREFIX + "/list")
+ @Operation(summary = "批量查询用户-岗位关系详情")
+ @Parameter(name = "ids", description = "关系ID列表", required = true, example = "1001,1002,1003")
+ CommonResult> getListByIds(@RequestParam("ids") List ids);
+
+ /**
+ * 统计用户-岗位关系总数(用于全量同步进度计算)
+ *
+ * @param tenantId 租户ID(可选)
+ * @return 用户-岗位关系总数
+ */
+ @GetMapping(PREFIX + "/count")
+ @Operation(summary = "统计用户-岗位关系总数")
+ @Parameter(name = "tenantId", description = "租户ID", example = "1")
+ CommonResult count(@RequestParam(value = "tenantId", required = false) Long tenantId);
+
+}
diff --git a/zt-module-databus/zt-module-databus-server/src/main/java/com/zt/plat/module/databus/framework/rpc/config/RpcConfiguration.java b/zt-module-databus/zt-module-databus-server/src/main/java/com/zt/plat/module/databus/framework/rpc/config/RpcConfiguration.java
index 32e911e1..d79beb52 100644
--- a/zt-module-databus/zt-module-databus-server/src/main/java/com/zt/plat/module/databus/framework/rpc/config/RpcConfiguration.java
+++ b/zt-module-databus/zt-module-databus-server/src/main/java/com/zt/plat/module/databus/framework/rpc/config/RpcConfiguration.java
@@ -4,9 +4,13 @@ import com.zt.plat.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import com.zt.plat.module.databus.api.provider.DatabusDeptProviderApi;
import com.zt.plat.module.databus.api.provider.DatabusPostProviderApi;
import com.zt.plat.module.databus.api.provider.DatabusUserProviderApi;
+import com.zt.plat.module.databus.api.provider.DatabusUserDeptProviderApi;
+import com.zt.plat.module.databus.api.provider.DatabusUserPostProviderApi;
import com.zt.plat.module.system.api.dept.DeptApi;
import com.zt.plat.module.system.api.dept.PostApi;
import com.zt.plat.module.system.api.user.AdminUserApi;
+import com.zt.plat.module.system.api.userdept.UserDeptApi;
+import com.zt.plat.module.system.api.userpost.UserPostApi;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
@@ -21,9 +25,12 @@ import org.springframework.context.annotation.Configuration;
DatabusDeptProviderApi.class,
DatabusUserProviderApi.class,
DatabusPostProviderApi.class,
- PostApi.class,
- DeptApi.class,
- AdminUserApi.class,
+ DatabusUserDeptProviderApi.class,
+ DatabusUserPostProviderApi.class,
+ PostApi.class,
+ DeptApi.class,
+ UserDeptApi.class,
+ UserPostApi.class,
})
public class RpcConfiguration {
}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/UserDeptApi.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/UserDeptApi.java
new file mode 100644
index 00000000..d48c6b69
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/UserDeptApi.java
@@ -0,0 +1,64 @@
+package com.zt.plat.module.system.api.userdept;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.system.api.userdept.dto.UserDeptRespDTO;
+import com.zt.plat.module.system.api.userdept.dto.UserDeptSaveReqDTO;
+import com.zt.plat.module.system.enums.ApiConstants;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 用户-部门关系 Feign API
+ *
+ * @author ZT
+ */
+@FeignClient(name = ApiConstants.NAME)
+@Tag(name = "RPC 服务 - 用户部门关系")
+public interface UserDeptApi {
+
+ String PREFIX = ApiConstants.PREFIX + "/user-dept";
+
+ @PostMapping(PREFIX + "/create")
+ @Operation(summary = "新增用户部门关系")
+ CommonResult createUserDept(@RequestBody UserDeptSaveReqDTO reqVO);
+
+ @PutMapping(PREFIX + "/update")
+ @Operation(summary = "修改用户部门关系")
+ CommonResult updateUserDept(@RequestBody UserDeptSaveReqDTO reqVO);
+
+ @DeleteMapping(PREFIX + "/delete")
+ @Operation(summary = "删除用户部门关系")
+ @Parameter(name = "id", description = "关系编号", example = "1", required = true)
+ CommonResult deleteUserDept(@RequestParam("id") Long id);
+
+ @GetMapping(PREFIX + "/get")
+ @Operation(summary = "通过ID查询用户部门关系")
+ @Parameter(name = "id", description = "关系编号", example = "1", required = true)
+ CommonResult getUserDept(@RequestParam("id") Long id);
+
+ @GetMapping(PREFIX + "/list-by-user-id")
+ @Operation(summary = "通过用户ID查询用户部门关系列表")
+ @Parameter(name = "userId", description = "用户编号", example = "1", required = true)
+ CommonResult> getUserDeptListByUserId(@RequestParam("userId") Long userId);
+
+ @GetMapping(PREFIX + "/list-by-dept-id")
+ @Operation(summary = "通过部门ID查询用户部门关系列表")
+ @Parameter(name = "deptId", description = "部门编号", example = "1", required = true)
+ CommonResult> getUserDeptListByDeptId(@RequestParam("deptId") Long deptId);
+
+ @DeleteMapping(PREFIX + "/delete-by-user-id")
+ @Operation(summary = "通过用户ID删除用户部门关系")
+ @Parameter(name = "userId", description = "用户编号", example = "1", required = true)
+ CommonResult deleteUserDeptByUserId(@RequestParam("userId") Long userId);
+
+ @DeleteMapping(PREFIX + "/delete-by-dept-id")
+ @Operation(summary = "通过部门ID删除用户部门关系")
+ @Parameter(name = "deptId", description = "部门编号", example = "1", required = true)
+ CommonResult deleteUserDeptByDeptId(@RequestParam("deptId") Long deptId);
+}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/dto/UserDeptRespDTO.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/dto/UserDeptRespDTO.java
new file mode 100644
index 00000000..5a558b90
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/dto/UserDeptRespDTO.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.system.api.userdept.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户部门关系 Response DTO
+ *
+ * @author ZT
+ */
+@Schema(description = "RPC 服务 - 用户部门关系 Response DTO")
+@Data
+public class UserDeptRespDTO {
+
+ @Schema(description = "关系编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "用户编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "部门编号", example = "100")
+ private Long deptId;
+
+ @Schema(description = "备注", example = "主部门")
+ private String remark;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/dto/UserDeptSaveReqDTO.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/dto/UserDeptSaveReqDTO.java
new file mode 100644
index 00000000..b18f2a56
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userdept/dto/UserDeptSaveReqDTO.java
@@ -0,0 +1,26 @@
+package com.zt.plat.module.system.api.userdept.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 用户部门关系创建/修改 Request DTO
+ *
+ * @author ZT
+ */
+@Schema(description = "RPC 服务 - 用户部门关系创建/修改 Request DTO")
+@Data
+public class UserDeptSaveReqDTO {
+
+ @Schema(description = "关系编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "用户编号", example = "1", required = true)
+ private Long userId;
+
+ @Schema(description = "部门编号", example = "100", required = true)
+ private Long deptId;
+
+ @Schema(description = "备注", example = "主部门")
+ private String remark;
+}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/UserPostApi.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/UserPostApi.java
new file mode 100644
index 00000000..a58e09cb
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/UserPostApi.java
@@ -0,0 +1,64 @@
+package com.zt.plat.module.system.api.userpost;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.system.api.userpost.dto.UserPostRespDTO;
+import com.zt.plat.module.system.api.userpost.dto.UserPostSaveReqDTO;
+import com.zt.plat.module.system.enums.ApiConstants;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 用户-岗位关系 Feign API
+ *
+ * @author ZT
+ */
+@FeignClient(name = ApiConstants.NAME)
+@Tag(name = "RPC 服务 - 用户岗位关系")
+public interface UserPostApi {
+
+ String PREFIX = ApiConstants.PREFIX + "/user-post";
+
+ @PostMapping(PREFIX + "/create")
+ @Operation(summary = "新增用户岗位关系")
+ CommonResult createUserPost(@RequestBody UserPostSaveReqDTO reqVO);
+
+ @PutMapping(PREFIX + "/update")
+ @Operation(summary = "修改用户岗位关系")
+ CommonResult updateUserPost(@RequestBody UserPostSaveReqDTO reqVO);
+
+ @DeleteMapping(PREFIX + "/delete")
+ @Operation(summary = "删除用户岗位关系")
+ @Parameter(name = "id", description = "关系编号", example = "1", required = true)
+ CommonResult deleteUserPost(@RequestParam("id") Long id);
+
+ @GetMapping(PREFIX + "/get")
+ @Operation(summary = "通过ID查询用户岗位关系")
+ @Parameter(name = "id", description = "关系编号", example = "1", required = true)
+ CommonResult getUserPost(@RequestParam("id") Long id);
+
+ @GetMapping(PREFIX + "/list-by-user-id")
+ @Operation(summary = "通过用户ID查询用户岗位关系列表")
+ @Parameter(name = "userId", description = "用户编号", example = "1", required = true)
+ CommonResult> getUserPostListByUserId(@RequestParam("userId") Long userId);
+
+ @GetMapping(PREFIX + "/list-by-post-id")
+ @Operation(summary = "通过岗位ID查询用户岗位关系列表")
+ @Parameter(name = "postId", description = "岗位编号", example = "1", required = true)
+ CommonResult> getUserPostListByPostId(@RequestParam("postId") Long postId);
+
+ @DeleteMapping(PREFIX + "/delete-by-user-id")
+ @Operation(summary = "通过用户ID删除用户岗位关系")
+ @Parameter(name = "userId", description = "用户编号", example = "1", required = true)
+ CommonResult deleteUserPostByUserId(@RequestParam("userId") Long userId);
+
+ @DeleteMapping(PREFIX + "/delete-by-post-id")
+ @Operation(summary = "通过岗位ID删除用户岗位关系")
+ @Parameter(name = "postId", description = "岗位编号", example = "1", required = true)
+ CommonResult deleteUserPostByPostId(@RequestParam("postId") Long postId);
+}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/dto/UserPostRespDTO.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/dto/UserPostRespDTO.java
new file mode 100644
index 00000000..e7251a61
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/dto/UserPostRespDTO.java
@@ -0,0 +1,28 @@
+package com.zt.plat.module.system.api.userpost.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户岗位关系 Response DTO
+ *
+ * @author ZT
+ */
+@Schema(description = "RPC 服务 - 用户岗位关系 Response DTO")
+@Data
+public class UserPostRespDTO {
+
+ @Schema(description = "关系编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "用户编号", example = "1")
+ private Long userId;
+
+ @Schema(description = "岗位编号", example = "100")
+ private Long postId;
+
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/dto/UserPostSaveReqDTO.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/dto/UserPostSaveReqDTO.java
new file mode 100644
index 00000000..4ad5af68
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/userpost/dto/UserPostSaveReqDTO.java
@@ -0,0 +1,23 @@
+package com.zt.plat.module.system.api.userpost.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 用户岗位关系创建/修改 Request DTO
+ *
+ * @author ZT
+ */
+@Schema(description = "RPC 服务 - 用户岗位关系创建/修改 Request DTO")
+@Data
+public class UserPostSaveReqDTO {
+
+ @Schema(description = "关系编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "用户编号", example = "1", required = true)
+ private Long userId;
+
+ @Schema(description = "岗位编号", example = "100", required = true)
+ private Long postId;
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserDeptProviderApiImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserDeptProviderApiImpl.java
new file mode 100644
index 00000000..3a461df9
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserDeptProviderApiImpl.java
@@ -0,0 +1,127 @@
+package com.zt.plat.module.system.api.databus;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.databus.api.data.DatabusUserDeptData;
+import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
+import com.zt.plat.module.databus.api.dto.CursorPageResult;
+import com.zt.plat.module.databus.api.provider.DatabusUserDeptProviderApi;
+import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
+import com.zt.plat.module.system.dal.mysql.userdept.UserDeptMapper;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+/**
+ * Databus 用户-部门关系数据提供者 API 实现
+ *
+ * @author ZT
+ */
+@Slf4j
+@RestController
+@Validated
+public class DatabusUserDeptProviderApiImpl implements DatabusUserDeptProviderApi {
+
+ @Resource
+ private UserDeptMapper userDeptMapper;
+
+ @Override
+ public CommonResult> getPageByCursor(CursorPageReqDTO reqDTO) {
+ // 多查一条判断是否有更多数据
+ int limit = reqDTO.getBatchSize() != null ? reqDTO.getBatchSize() : 100;
+
+ // ⚠️ 使用关联查询,只查询 userSource = 2 的用户的部门关系
+ List list = userDeptMapper.selectPageByCursorWithUserSource(
+ reqDTO.isFirstPage() ? null : reqDTO.getCursorTime(),
+ reqDTO.isFirstPage() ? null : reqDTO.getCursorId(),
+ reqDTO.getTenantId(),
+ limit + 1
+ );
+
+ // 判断是否有更多
+ boolean hasMore = list.size() > limit;
+ if (hasMore) {
+ list = list.subList(0, limit);
+ }
+
+ if (CollUtil.isEmpty(list)) {
+ return success(CursorPageResult.empty());
+ }
+
+ // 转换为同步数据
+ List dataList = list.stream()
+ .map(this::convertToData)
+ .collect(Collectors.toList());
+
+ // 获取最后一条数据的游标
+ UserDeptDO last = list.get(list.size() - 1);
+
+ // 首次查询时返���总数
+ Long total = null;
+ if (reqDTO.isFirstPage()) {
+ // ⚠️ 只统计 userSource = 2 的用户的部门关系
+ total = userDeptMapper.countWithUserSource(reqDTO.getTenantId());
+ }
+
+ return success(CursorPageResult.of(
+ dataList,
+ last.getCreateTime(),
+ last.getId(),
+ hasMore,
+ total
+ ));
+ }
+
+ @Override
+ public CommonResult getById(Long id) {
+ UserDeptDO userDept = userDeptMapper.selectById(id);
+ if (userDept == null) {
+ return success(null);
+ }
+ return success(convertToData(userDept));
+ }
+
+ @Override
+ public CommonResult> getListByIds(List ids) {
+ if (CollUtil.isEmpty(ids)) {
+ return success(Collections.emptyList());
+ }
+
+ List list = userDeptMapper.selectBatchIds(ids);
+ if (CollUtil.isEmpty(list)) {
+ return success(Collections.emptyList());
+ }
+
+ return success(list.stream()
+ .map(this::convertToData)
+ .collect(Collectors.toList()));
+ }
+
+ @Override
+ public CommonResult count(Long tenantId) {
+ // ⚠️ 只统计 userSource = 2 的用户的部门关系
+ return success(userDeptMapper.countWithUserSource(tenantId));
+ }
+
+ /**
+ * 将 UserDeptDO 转换为 DatabusUserDeptData
+ */
+ private DatabusUserDeptData convertToData(UserDeptDO userDept) {
+ return DatabusUserDeptData.builder()
+ .id(userDept.getId())
+ .userId(userDept.getUserId())
+ .deptId(userDept.getDeptId())
+ .tenantId(userDept.getTenantId())
+ .remark(userDept.getRemark())
+ .build();
+ }
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserPostProviderApiImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserPostProviderApiImpl.java
new file mode 100644
index 00000000..faabe471
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserPostProviderApiImpl.java
@@ -0,0 +1,125 @@
+package com.zt.plat.module.system.api.databus;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.databus.api.data.DatabusUserPostData;
+import com.zt.plat.module.databus.api.dto.CursorPageReqDTO;
+import com.zt.plat.module.databus.api.dto.CursorPageResult;
+import com.zt.plat.module.databus.api.provider.DatabusUserPostProviderApi;
+import com.zt.plat.module.system.dal.dataobject.dept.UserPostDO;
+import com.zt.plat.module.system.dal.mysql.dept.UserPostMapper;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+/**
+ * Databus 用户-岗位关系数据提供者 API 实现
+ *
+ * @author ZT
+ */
+@Slf4j
+@RestController
+@Validated
+public class DatabusUserPostProviderApiImpl implements DatabusUserPostProviderApi {
+
+ @Resource
+ private UserPostMapper userPostMapper;
+
+ @Override
+ public CommonResult> getPageByCursor(CursorPageReqDTO reqDTO) {
+ // 多查一条判断是否有更多数据
+ int limit = reqDTO.getBatchSize() != null ? reqDTO.getBatchSize() : 100;
+
+ // ⚠️ 使用关联查询,只查询 userSource = 2 的用户的岗位关系
+ List list = userPostMapper.selectPageByCursorWithUserSource(
+ reqDTO.isFirstPage() ? null : reqDTO.getCursorTime(),
+ reqDTO.isFirstPage() ? null : reqDTO.getCursorId(),
+ reqDTO.getTenantId(),
+ limit + 1
+ );
+
+ // 判断是否有更多
+ boolean hasMore = list.size() > limit;
+ if (hasMore) {
+ list = list.subList(0, limit);
+ }
+
+ if (CollUtil.isEmpty(list)) {
+ return success(CursorPageResult.empty());
+ }
+
+ // 转换为同步数据
+ List dataList = list.stream()
+ .map(this::convertToData)
+ .collect(Collectors.toList());
+
+ // 获取最后一条数据的游标
+ UserPostDO last = list.get(list.size() - 1);
+
+ // 首次查询时返回总数
+ Long total = null;
+ if (reqDTO.isFirstPage()) {
+ // ⚠️ 只统计 userSource = 2 的用户的岗位关系
+ total = userPostMapper.countWithUserSource(reqDTO.getTenantId());
+ }
+
+ return success(CursorPageResult.of(
+ dataList,
+ last.getCreateTime(),
+ last.getId(),
+ hasMore,
+ total
+ ));
+ }
+
+ @Override
+ public CommonResult getById(Long id) {
+ UserPostDO userPost = userPostMapper.selectById(id);
+ if (userPost == null) {
+ return success(null);
+ }
+ return success(convertToData(userPost));
+ }
+
+ @Override
+ public CommonResult> getListByIds(List ids) {
+ if (CollUtil.isEmpty(ids)) {
+ return success(Collections.emptyList());
+ }
+
+ List list = userPostMapper.selectBatchIds(ids);
+ if (CollUtil.isEmpty(list)) {
+ return success(Collections.emptyList());
+ }
+
+ return success(list.stream()
+ .map(this::convertToData)
+ .collect(Collectors.toList()));
+ }
+
+ @Override
+ public CommonResult count(Long tenantId) {
+ // ⚠️ 只统计 userSource = 2 的用户的岗位关系
+ return success(userPostMapper.countWithUserSource(tenantId));
+ }
+
+ /**
+ * 将 UserPostDO 转换为 DatabusUserPostData
+ */
+ private DatabusUserPostData convertToData(UserPostDO userPost) {
+ return DatabusUserPostData.builder()
+ .id(userPost.getId())
+ .userId(userPost.getUserId())
+ .postId(userPost.getPostId())
+ .build();
+ }
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserProviderApiImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserProviderApiImpl.java
index 286b9984..f6b9050a 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserProviderApiImpl.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusUserProviderApiImpl.java
@@ -54,6 +54,9 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
// 构建游标查询条件
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
+ // ⚠️ 只同步 userSource = 2 的用户
+ queryWrapper.eq(AdminUserDO::getUserSource, 2);
+
// 游标条件:create_time > cursorTime OR (create_time = cursorTime AND id > cursorId)
if (!reqDTO.isFirstPage()) {
queryWrapper.and(w -> w
@@ -100,6 +103,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
Long total = null;
if (reqDTO.isFirstPage()) {
LambdaQueryWrapper countWrapper = new LambdaQueryWrapper<>();
+ // ⚠️ 只统计 userSource = 2 的用户
+ countWrapper.eq(AdminUserDO::getUserSource, 2);
if (reqDTO.getTenantId() != null) {
countWrapper.eq(AdminUserDO::getTenantId, reqDTO.getTenantId());
}
@@ -143,6 +148,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
@Override
public CommonResult count(Long tenantId) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
+ // ⚠️ 只统计 userSource = 2 的用户
+ queryWrapper.eq(AdminUserDO::getUserSource, 2);
if (tenantId != null) {
queryWrapper.eq(AdminUserDO::getTenantId, tenantId);
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/dept/PostApiImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/dept/PostApiImpl.java
index 40c7e22b..97cf029e 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/dept/PostApiImpl.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/dept/PostApiImpl.java
@@ -10,6 +10,7 @@ import com.zt.plat.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.zt.plat.module.system.dal.dataobject.dept.PostDO;
import com.zt.plat.module.system.service.dept.PostService;
import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
@@ -20,6 +21,7 @@ import java.util.List;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
+@Slf4j
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class PostApiImpl implements PostApi {
@@ -36,6 +38,7 @@ public class PostApiImpl implements PostApi {
@Override
public CommonResult updatePost(PostSaveReqDTO updateReqVO) {
+ log.error("ssssssssss");
PostSaveReqVO reqVO = BeanUtils.toBean(updateReqVO, PostSaveReqVO.class);
postService.updatePost(reqVO);
return success(true);
@@ -49,6 +52,7 @@ public class PostApiImpl implements PostApi {
@Override
public CommonResult getPost(Long id) {
+ log.error("cccccccc"+id);
PostDO post = postService.getPost(id);
return success(BeanUtils.toBean(post, PostRespDTO.class));
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/UserPostMapper.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/UserPostMapper.java
index fa9bd6aa..2df5c891 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/UserPostMapper.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/dept/UserPostMapper.java
@@ -5,7 +5,10 @@ import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.module.system.dal.dataobject.dept.UserPostDO;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
@@ -29,4 +32,44 @@ public interface UserPostMapper extends BaseMapperX {
default void deleteByUserId(Long userId) {
delete(Wrappers.lambdaUpdate(UserPostDO.class).eq(UserPostDO::getUserId, userId));
}
+
+ /**
+ * 游标分页查询用户-岗位关系(只查询 userSource = 2 的用户)
+ * @param cursorTime 游标时间
+ * @param cursorId 游标ID
+ * @param tenantId 租户ID(可选)
+ * @param limit 限制数量
+ * @return 用户岗位关系列表
+ */
+ @Select("")
+ List selectPageByCursorWithUserSource(@Param("cursorTime") LocalDateTime cursorTime,
+ @Param("cursorId") Long cursorId,
+ @Param("tenantId") Long tenantId,
+ @Param("limit") Integer limit);
+
+ /**
+ * 统计用户-岗位关系数量(只统计 userSource = 2 的用户)
+ * @param tenantId 租户ID(可选)
+ * @return 数量
+ */
+ @Select("")
+ Long countWithUserSource(@Param("tenantId") Long tenantId);
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/userdept/UserDeptMapper.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/userdept/UserDeptMapper.java
index b9aad69a..bf21f41d 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/userdept/UserDeptMapper.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/userdept/UserDeptMapper.java
@@ -4,7 +4,10 @@ import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.module.system.dal.dataobject.userdept.UserDeptDO;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -45,4 +48,44 @@ public interface UserDeptMapper extends BaseMapperX {
);
}
+ /**
+ * 游标分页查询用户-部门关系(只查询 userSource = 2 的用户)
+ * @param cursorTime 游标时间
+ * @param cursorId 游标ID
+ * @param tenantId 租户ID(可选)
+ * @param limit 限制数量
+ * @return 用户部门关系列表
+ */
+ @Select("")
+ List selectPageByCursorWithUserSource(@Param("cursorTime") LocalDateTime cursorTime,
+ @Param("cursorId") Long cursorId,
+ @Param("tenantId") Long tenantId,
+ @Param("limit") Integer limit);
+
+ /**
+ * 统计用户-部门关系数量(只统计 userSource = 2 的用户)
+ * @param tenantId 租户ID(可选)
+ * @return 数量
+ */
+ @Select("")
+ Long countWithUserSource(@Param("tenantId") Long tenantId);
+
}
\ No newline at end of file