diff --git a/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java b/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java index d500177..9d65d24 100644 --- a/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java +++ b/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java @@ -92,6 +92,11 @@ public class ConfigProperties { */ private String serverUrl; + /** + * websopy 服务地址(用于同步用户数据) + */ + private String websopyUrl; + /** * 阿里云存储 OSS * Endpoint diff --git a/src/main/java/com/gxwebsoft/common/system/controller/UserController.java b/src/main/java/com/gxwebsoft/common/system/controller/UserController.java index 81ff503..bc6dc80 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/UserController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/UserController.java @@ -66,6 +66,8 @@ public class UserController extends BaseController { private ConfigProperties configProperties; @Resource private LoginRecordService loginRecordService; + @Resource + private UserSyncService userSyncService; @PreAuthorize("hasAuthority('sys:auth:user')") @Operation(summary = "分页查询用户") @@ -142,6 +144,8 @@ public class UserController extends BaseController { return fail("该手机号码已存在"); } if (userService.saveUser(user)) { + // 同步到 websopy + userSyncService.syncUserToWebsopy(user); return success("添加成功", user.getUserId()); } return fail("添加失败"); @@ -159,6 +163,8 @@ public class UserController extends BaseController { return fail("该手机号码已存在"); } if (userService.saveUser(user)) { + // 同步到 websopy + userSyncService.syncUserToWebsopy(user); return success("添加成功", user.getUserId()); } return fail("添加失败"); @@ -181,6 +187,8 @@ public class UserController extends BaseController { userList.removeIf(d -> phoneCollect.containsKey(d.getPhone())); if (userService.saveBatch(userList)) { + // 同步到 websopy(异步处理,不阻塞响应) + userList.forEach(user -> userSyncService.syncUserToWebsopy(user)); return success("添加成功"); } return fail("添加失败"); @@ -201,6 +209,8 @@ public class UserController extends BaseController { userParam.setLimit(500L); final PageResult result = userService.pageRel(userParam); final Set collect = result.getList().stream().map(User::getUserId).collect(Collectors.toSet()); + // 同步到 websopy(异步处理,不阻塞响应) + userList.forEach(user -> userSyncService.syncUserToWebsopy(user)); return success("添加成功", collect); } return fail("添加失败"); @@ -511,6 +521,7 @@ public class UserController extends BaseController { // 保存新用户(逐个保存以处理角色关系) int successCount = 0; List failedUsers = new ArrayList<>(); + List successUsers = new ArrayList<>(); for (User user : users) { try { @@ -524,6 +535,7 @@ public class UserController extends BaseController { userRoleService.saveBatch(user.getUserId(), roleIds); } successCount++; + successUsers.add(user); } else { failedUsers.add(user.getUsername()); } @@ -534,6 +546,11 @@ public class UserController extends BaseController { } } + // 同步成功导入的用户到 websopy + for (User successUser : successUsers) { + userSyncService.syncUserToWebsopy(successUser); + } + // 构建返回消息 StringBuilder message = new StringBuilder(); if (successCount > 0) { diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java index 9fd01ed..2e5aed2 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java @@ -65,6 +65,8 @@ public class WxLoginController extends BaseController { private ConfigProperties config; @Resource private UserRefereeService userRefereeService; + @Resource + private UserSyncService userSyncService; public WxLoginController(StringRedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; @@ -473,6 +475,8 @@ public class WxLoginController extends BaseController { userRole.setTenantId(addUser.getTenantId()); userRole.setRoleId(addUser.getRoleId()); userRoleService.save(userRole); + // 同步到 websopy + userSyncService.syncUserToWebsopy(addUser); } // 绑定关系 if (userParam.getSceneType() != null && userParam.getSceneType().equals("save_referee") && userParam.getRefereeId() != null && userParam.getRefereeId() != 0) { diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java index 85933e8..716ca8e 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java @@ -22,6 +22,7 @@ import com.gxwebsoft.common.system.service.RoleService; import com.gxwebsoft.common.system.service.UserOauthService; import com.gxwebsoft.common.system.service.UserRoleService; import com.gxwebsoft.common.system.service.UserService; +import com.gxwebsoft.common.system.service.UserSyncService; import com.gxwebsoft.common.system.vo.WxOfficialButton; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; @@ -69,6 +70,8 @@ public class WxOfficialController extends BaseController { @Resource private UserRoleService userRoleService; @Resource + private UserSyncService userSyncService; + @Resource private UserOauthService userOauthService; @Resource private RedisUtil redisUtil; @@ -155,6 +158,8 @@ public class WxOfficialController extends BaseController { userRole.setTenantId(user.getTenantId()); userRole.setRoleId(user.getRoleId()); userRoleService.save(userRole); + // 同步到 websopy + userSyncService.syncUserToWebsopy(user); } System.out.println("新微信公众号用户 = " + userId); } diff --git a/src/main/java/com/gxwebsoft/common/system/service/UserSyncService.java b/src/main/java/com/gxwebsoft/common/system/service/UserSyncService.java new file mode 100644 index 0000000..e284fcd --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/service/UserSyncService.java @@ -0,0 +1,137 @@ +package com.gxwebsoft.common.system.service; + +import com.gxwebsoft.common.core.config.ConfigProperties; +import com.gxwebsoft.common.core.utils.HttpUtils; +import com.gxwebsoft.common.system.entity.User; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * 用户同步服务(同步到 websopy) + * + * @author WebSoft + * @since 2026-04-04 + */ +@Slf4j +@Service +public class UserSyncService { + + @Resource + private ConfigProperties configProperties; + + private String websopyBaseUrl; + + @PostConstruct + public void init() { + websopyBaseUrl = configProperties.getWebsopyUrl(); + if (websopyBaseUrl == null || websopyBaseUrl.isEmpty()) { + log.warn("websopyUrl 未配置,用户同步功能将不可用"); + } else { + log.info("用户同步服务初始化完成,websopy地址: {}", websopyBaseUrl); + } + } + + /** + * 同步单个用户到 websopy + * + * @param user 用户信息 + */ + public void syncUserToWebsopy(User user) { + if (websopyBaseUrl == null || websopyBaseUrl.isEmpty()) { + log.warn("websopyUrl 未配置,跳过用户同步: userId={}", user.getUserId()); + return; + } + + if (user == null || user.getUserId() == null) { + log.warn("用户信息为空,跳过同步"); + return; + } + + try { + // 构建请求体 + JSONObject userCache = new JSONObject(); + userCache.put("userId", user.getUserId()); + userCache.put("username", user.getUsername()); + userCache.put("nickname", user.getNickname()); + userCache.put("avatar", user.getAvatar()); + userCache.put("phone", user.getPhone()); + userCache.put("status", user.getStatus()); + userCache.put("updateTime", System.currentTimeMillis()); + + String url = websopyBaseUrl + "/api/app/user-sync/single"; + String body = userCache.toJSONString(); + + log.info("同步用户到 websopy: userId={}, url={}", user.getUserId(), url); + + // 发送 HTTP POST 请求 + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + HttpResponse response = HttpUtils.doPost(url, "", "POST", headers, null, body); + String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + + log.debug("websopy 响应: {}", responseBody); + + // 解析响应 + JSONObject result = JSON.parseObject(responseBody); + if (result != null && result.getIntValue("code") == 0) { + log.info("用户同步成功: userId={}", user.getUserId()); + } else { + String message = result != null ? result.getString("message") : "未知错误"; + log.error("用户同步失败: userId={}, message={}", user.getUserId(), message); + } + } catch (Exception e) { + log.error("用户同步异常: userId={}, error={}", user.getUserId(), e.getMessage(), e); + } + } + + /** + * 刷新 websopy 端的用户缓存 + * 只传 userId,websopy 端会通过 API 回查获取完整信息 + * + * @param userId 用户ID + */ + public void refreshUserCache(Integer userId) { + if (websopyBaseUrl == null || websopyBaseUrl.isEmpty()) { + log.warn("websopyUrl 未配置,跳过刷新缓存: userId={}", userId); + return; + } + + if (userId == null) { + log.warn("userId 为空,跳过刷新"); + return; + } + + try { + String url = websopyBaseUrl + "/api/app/user-sync/refresh/" + userId; + + log.info("刷新用户缓存: userId={}, url={}", userId, url); + + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + HttpResponse response = HttpUtils.doPost(url, "", "POST", headers, null, ""); + String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + + JSONObject result = JSON.parseObject(responseBody); + if (result != null && result.getIntValue("code") == 0) { + log.info("刷新缓存成功: userId={}", userId); + } else { + String message = result != null ? result.getString("message") : "未知错误"; + log.error("刷新缓存失败: userId={}, message={}", userId, message); + } + } catch (Exception e) { + log.error("刷新缓存异常: userId={}, error={}", userId, e.getMessage(), e); + } + } +}