diff --git a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/EmergencyApiService.java b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/EmergencyApiService.java index f2ce0b0..cc918ae 100644 --- a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/EmergencyApiService.java +++ b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/EmergencyApiService.java @@ -45,5 +45,10 @@ public interface EmergencyApiService { boolean addGroupUser(AddOtherMemberDTO dto); + /** + * 拉入关爱联络员和急救人员到群聊(兜底补拉用,失败不抛异常) + */ + void addCareUsersToGroup(String userId, String groupId, String orderId); + boolean removeGroupUser(RemoveGroupMemberDTO dto); } diff --git a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyApiServiceImpl.java b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyApiServiceImpl.java index fe0537a..0034161 100644 --- a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyApiServiceImpl.java +++ b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyApiServiceImpl.java @@ -1001,7 +1001,7 @@ public class EmergencyApiServiceImpl implements EmergencyApiService { * @param groupId IM群组ID * @param orderId 应急工单ID */ - private void addCareUsersToGroup(String userId, String groupId, String orderId) { + public void addCareUsersToGroup(String userId, String groupId, String orderId) { try { // 1. 获取发起人工号 List employeeInfos = sysBaseAPI.queryBaseEmployeeInfo(Collections.singleton(userId)); @@ -1355,6 +1355,14 @@ public class EmergencyApiServiceImpl implements EmergencyApiService { log.warn("获取腾讯IM群成员失败,仅使用本地数据进行去重, groupId: {}", groupId, e); } + // 2. 群成员上限校验:最多9人 + int currentGroupSize = alreadyInGroup.size(); + int newMemberCount = (int) candidateList.stream() + .filter(userId -> !alreadyInGroup.contains(userId)).count(); + if (currentGroupSize + newMemberCount > 9) { + ExceptionAssertsUtil.fail("群成员已达上限"); + } + // memberType: 0=专家/专业人员(默认), 1=员工 Integer memberType = dto.getMemberType(); Integer operatorType = (memberType != null && memberType == 1) ? 2 : 1; diff --git a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyOrderApiServiceImpl.java b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyOrderApiServiceImpl.java index 7b01790..463ddea 100644 --- a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyOrderApiServiceImpl.java +++ b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/service/impl/EmergencyOrderApiServiceImpl.java @@ -28,7 +28,9 @@ import com.renkang.emergency.mapper.*; import com.renkang.emergency.service.IOrderDetailService; import com.renkang.emergency.service.IOrderService; import com.renkang.im.api.IMHelloApi; +import com.renkang.im.dto.AddGroupMemberDTO; import com.renkang.im.entity.ImGroupMsgTextReqDO; +import com.renkang.im.vo.AddGroupMemberVO; import com.renkang.im.vo.GetGroupMemberInfoVO; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -81,6 +83,8 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { private ISysBaseAPI sysBaseAPI; @Autowired private EmergencyCloudManager emergencyCloudManager; + @Autowired + private com.renkang.emergency.api.service.EmergencyApiService emergencyApiService; @Override public IPage initUserOrderPage(Page page) { @@ -733,7 +737,15 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { } String orderId = order.getId(); - // 2. 查order_operator表获取本地参与人员 + // 2. 兜底补拉关爱联络员+急救人员1+急救人员2(重新查询安眼系统) + // 发起应急时这些人员可能还未注册,此处兜底 + try { + emergencyApiService.addCareUsersToGroup(order.getInitiatorUserId(), sessionId, orderId); + } catch (Exception e) { + log.warn("兜底补拉关爱/急救人员异常, sessionId={}", sessionId, e); + } + + // 3. 查order_operator表获取本地参与人员 List orderOperators = orderOperatorMapper.selectList( new LambdaQueryWrapper() .eq(OrderOperator::getOrderId, orderId)); @@ -744,7 +756,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { .collect(Collectors.toList()); } - // 3. 调腾讯IM获取实际群成员 + // 4. 调腾讯IM获取实际群成员 Set imMemberAccounts = new HashSet<>(); boolean imSuccess = false; try { @@ -760,13 +772,18 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { log.error("获取腾讯IM群成员失败,sessionId: {},降级使用本地参与人员", sessionId, e); } - // 4. 如果IM调用失败,降级使用本地成员全集 + // 5. 自动补拉其他遗漏的预设成员(仅IM可用时) + if (imSuccess) { + autoInvitePresetMembers(sessionId, order, imMemberAccounts, localUserIds, loginUser); + } + + // 6. 如果IM调用失败,降级使用本地成员全集 final Set validAccounts = imSuccess ? imMemberAccounts : new HashSet<>(localUserIds); if (!imSuccess) { log.warn("腾讯IM调用失败,降级返回本地参与人员 {} 人, sessionId: {}", localUserIds.size(), sessionId); } - // 5. 发起人:匹配验证集 + // 7. 发起人:匹配验证集 if (validAccounts.contains(order.getInitiatorUserId())) { handleGroupMember(groupMemberVos, orderId, order.getInitiatorUserId(), @@ -776,7 +793,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { 1, -1); } - // 6. 查order_operator表,匹配验证集 + // 8. 查order_operator表,匹配验证集 if (CollectionUtils.isNotEmpty(orderOperators)) { // 查询专业用户信息 Map profUserMap = new HashMap<>(); @@ -824,7 +841,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { } } - // 7. 标记本人 + // 9. 标记本人 String currentUserId = loginUser.getId(); groupMemberVos.forEach(vo -> vo.setIsSelf(currentUserId.equals(vo.getUserId()) ? 1 : 0)); return groupMemberVos; @@ -843,6 +860,65 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService { groupMemberVos.add(groupMemberVO); } + /** + * 自动补拉预设成员入群 + * 预设成员:被救助人 + order_operator 所有参与人员 + * 群成员总数不超过9人 + */ + private void autoInvitePresetMembers(String sessionId, Order order, Set imMemberAccounts, + List localUserIds, LoginUser loginUser) { + Set presetMemberIds = new LinkedHashSet<>(); + // 被救助人 + if (StrUtil.isNotBlank(order.getSalvageUserId())) { + presetMemberIds.add(order.getSalvageUserId()); + } + // order_operator 中所有参与人员(操作人员、专业人员、紧急联系人、健康联络员) + if (CollectionUtils.isNotEmpty(localUserIds)) { + presetMemberIds.addAll(localUserIds); + } + // 排除当前登录用户(不能邀请自己) + presetMemberIds.remove(loginUser.getId()); + + // 找出不在群中的预设成员 + List missingPresetMembers = presetMemberIds.stream() + .filter(id -> !imMemberAccounts.contains(id)) + .collect(Collectors.toList()); + if (missingPresetMembers.isEmpty()) { + return; + } + + // 控制群成员不超过9人 + int currentCount = imMemberAccounts.size(); + int maxInvite = Math.max(0, 9 - currentCount); + if (maxInvite <= 0) { + log.warn("群成员已达上限9人,无法自动补拉预设成员, sessionId={}, current={}", sessionId, currentCount); + return; + } + List toInvite = missingPresetMembers.subList(0, Math.min(missingPresetMembers.size(), maxInvite)); + + try { + AddGroupMemberDTO addDto = new AddGroupMemberDTO(); + addDto.setGroupId(sessionId); + addDto.setSilence(1); + addDto.setMemberList(toInvite.stream().map(userId -> { + AddGroupMemberDTO.MemberListDTO m = new AddGroupMemberDTO.MemberListDTO(); + m.setMemberAccount(userId); + return m; + }).collect(Collectors.toList())); + Result result = imHelloApi.addGroupMember(addDto); + if (result != null && result.isSuccess() && result.getResult() != null + && "OK".equals(result.getResult().getActionStatus())) { + imMemberAccounts.addAll(toInvite); + log.info("自动补拉预设成员入群成功, sessionId={}, userIds={}, currentCount={}", + sessionId, toInvite, currentCount + toInvite.size()); + } else { + log.warn("自动补拉预设成员入群失败, sessionId={}, userIds={}", sessionId, toInvite); + } + } catch (Exception e) { + log.error("自动补拉预设成员入群异常, sessionId={}", sessionId, e); + } + } + @Override public IPage searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize) { LambdaQueryWrapper query = new LambdaQueryWrapper<>();