feat(emergency): getActualGroupMemberList自动补拉预设成员 + addGroupUser加9人上限

- getActualGroupMemberList: 查询群成员时自动检查预设成员(被救助人、操作人员、专业人员、紧急联系人、健康联络员),不在群中则自动补拉
- addGroupUser: 邀请前校验群成员总数不超过9人,超限返回提示

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-22 11:01:23 +08:00
co-authored by Claude
parent f6f70ebf32
commit df41e0c8ce
2 changed files with 78 additions and 4 deletions
@@ -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("群成员已达上限,当前" + currentGroupSize + "人,最多邀请" + (9 - currentGroupSize) + "");
}
// memberType: 0=专家/专业人员(默认), 1=员工
Integer memberType = dto.getMemberType();
Integer operatorType = (memberType != null && memberType == 1) ? 2 : 1;
@@ -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;
@@ -760,13 +762,18 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
log.error("获取腾讯IM群成员失败,sessionId: {},降级使用本地参与人员", sessionId, e);
}
// 4. 如果IM调用失败,降级使用本地成员全集
// 4. 自动补拉预设成员入群(仅IM可用时)
if (imSuccess) {
autoInvitePresetMembers(sessionId, order, imMemberAccounts, localUserIds, loginUser);
}
// 5. 如果IM调用失败,降级使用本地成员全集
final Set<String> validAccounts = imSuccess ? imMemberAccounts : new HashSet<>(localUserIds);
if (!imSuccess) {
log.warn("腾讯IM调用失败,降级返回本地参与人员 {} 人, sessionId: {}", localUserIds.size(), sessionId);
}
// 5. 发起人:匹配验证集
// 6. 发起人:匹配验证集
if (validAccounts.contains(order.getInitiatorUserId())) {
handleGroupMember(groupMemberVos, orderId,
order.getInitiatorUserId(),
@@ -776,7 +783,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
1, -1);
}
// 6. 查order_operator表,匹配验证集
// 7. 查order_operator表,匹配验证集
if (CollectionUtils.isNotEmpty(orderOperators)) {
// 查询专业用户信息
Map<String, EmergencyProfessionUser> profUserMap = new HashMap<>();
@@ -824,7 +831,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
}
}
// 7. 标记本人
// 8. 标记本人
String currentUserId = loginUser.getId();
groupMemberVos.forEach(vo -> vo.setIsSelf(currentUserId.equals(vo.getUserId()) ? 1 : 0));
return groupMemberVos;
@@ -843,6 +850,65 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
groupMemberVos.add(groupMemberVO);
}
/**
* 自动补拉预设成员入群
* 预设成员:被救助人 + order_operator 中所有参与人员(操作人员、专业人员、紧急联系人、健康联络员)
* 群成员总数不超过9人
*/
private void autoInvitePresetMembers(String sessionId, Order order, Set<String> imMemberAccounts,
List<String> localUserIds, LoginUser loginUser) {
Set<String> 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<String> 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<String> 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<AddGroupMemberVO> 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<EmergencyProfessionUser> searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize) {
LambdaQueryWrapper<EmergencyProfessionUser> query = new LambdaQueryWrapper<>();