feat(emergency): 新增腾讯IM验证的群成员列表接口,优化searchEmployee模糊搜索

- 新增 /order/getActualGroupMemberList 接口,先查本地参与人员再调腾讯IM验证,以交集为准
- 新增 GetGroupMemberInfoVO,封装腾讯IM get_group_member_info API响应
- TencentCloudImUtil 新增 getGroupMemberInfo 方法,TXController/IMHelloApi 新增对应端点
- GroupMemberVO 新增 isSelf 字段区分本人 (0/1),默认值 0
- searchEmployee 姓名/工号/手机号改为模糊搜索(* 包装实现)
- 修复 getActualGroupMemberList IM 调用失败时静默返回空列表的 bug,失败时降级使用本地成员
- 接口文档更新变更摘要,标明新接口替换原 /order/getGroupMemberList 地址

Co-Authored-By: Claude <noreply@anthropic.com>
@
This commit is contained in:
2026-07-07 09:29:19 +08:00
parent 74ecbe6bda
commit 945c0b46d7
9 changed files with 297 additions and 14 deletions
@@ -298,6 +298,12 @@ public class EmergencyOrderApiController {
return Result.OK(emergencyOrderApiService.getGroupMemberList(sessionId));
}
@Operation(summary = "获取实际群成员列表(腾讯IM验证)")
@GetMapping("/getActualGroupMemberList")
public Result<List<GroupMemberVO>> getActualGroupMemberList(@RequestParam("sessionId") String sessionId) {
return Result.OK(emergencyOrderApiService.getActualGroupMemberList(sessionId));
}
@Operation(summary = "搜索专家/专业人员")
@GetMapping("/searchExpert")
public Result<IPage<EmergencyProfessionUser>> searchExpert(
@@ -77,6 +77,11 @@ public interface EmergencyOrderApiService {
List<GroupMemberVO> getGroupMemberList(String sessionId);
/**
* 获取实际群成员列表(先查本地参与人员,再匹配腾讯IM实际群成员)
*/
List<GroupMemberVO> getActualGroupMemberList(String sessionId);
IPage<EmergencyProfessionUser> searchExpert(String realname, String centerId, String excludeSessionId, Integer pageNo, Integer pageSize);
IPage<EmployeeVO> searchEmployee(String realname, String orgCode, String workNo, String phone, String excludeSessionId, Integer pageNo, Integer pageSize);
@@ -28,6 +28,7 @@ import com.renkang.emergency.service.IOrderDetailService;
import com.renkang.emergency.service.IOrderService;
import com.renkang.im.api.IMHelloApi;
import com.renkang.im.entity.ImGroupMsgTextReqDO;
import com.renkang.im.vo.GetGroupMemberInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jeecg.common.api.vo.Result;
@@ -713,6 +714,121 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
return groupMemberVos.stream().filter(groupMemberVO -> !groupMemberVO.getUserId().equals(loginUser.getId())).collect(Collectors.toList());
}
/**
* @description: 获取实际群成员列表(先查本地参与人员,再匹配腾讯IM实际群成员)
* @author PengJ
* @date 2026/7/7
*/
@Override
public List<GroupMemberVO> getActualGroupMemberList(String sessionId) {
List<GroupMemberVO> groupMemberVos = new ArrayList<>();
LoginUser loginUser = GlobalUtils.getLoginUser();
// 1. 校验订单是否存在
Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
.eq(Order::getSessionId, sessionId));
if (order == null) {
ExceptionAssertsUtil.fail("应急单不存在");
}
String orderId = order.getId();
// 2. 查order_operator表获取本地参与人员
List<OrderOperator> orderOperators = orderOperatorMapper.selectList(
new LambdaQueryWrapper<OrderOperator>()
.eq(OrderOperator::getOrderId, orderId));
List<String> localUserIds = new ArrayList<>();
if (CollectionUtils.isNotEmpty(orderOperators)) {
localUserIds = orderOperators.stream()
.map(OrderOperator::getUserId)
.collect(Collectors.toList());
}
// 3. 调腾讯IM获取实际群成员
Set<String> imMemberAccounts = new HashSet<>();
boolean imSuccess = false;
try {
Result<GetGroupMemberInfoVO> imResult = imHelloApi.getGroupMemberInfo(sessionId);
if (imResult != null && imResult.isSuccess() && imResult.getResult() != null) {
GetGroupMemberInfoVO vo = imResult.getResult();
if ("OK".equals(vo.getActionStatus()) && vo.getMemberList() != null) {
vo.getMemberList().forEach(m -> imMemberAccounts.add(m.getMemberAccount()));
imSuccess = true;
}
}
} catch (Exception e) {
log.error("获取腾讯IM群成员失败,sessionId: {},降级使用本地参与人员", sessionId, e);
}
// 4. 如果IM调用失败,降级使用本地成员全集
final Set<String> validAccounts = imSuccess ? imMemberAccounts : new HashSet<>(localUserIds);
if (!imSuccess) {
log.warn("腾讯IM调用失败,降级返回本地参与人员 {} 人, sessionId: {}", localUserIds.size(), sessionId);
}
// 5. 发起人:匹配验证集
if (validAccounts.contains(order.getInitiatorUserId())) {
handleGroupMember(groupMemberVos, orderId,
order.getInitiatorUserId(),
order.getInitiatorUserName(),
order.getInitiatorUserAvatar(),
order.getInitiatorUserMobile(),
1, -1);
}
// 6. 查order_operator表,匹配验证集
if (CollectionUtils.isNotEmpty(orderOperators)) {
// 查询专业用户信息
Map<String, EmergencyProfessionUser> profUserMap = new HashMap<>();
if (!localUserIds.isEmpty()) {
List<EmergencyProfessionUser> profUsers = emergencyProfessionUserMapper.selectList(
new LambdaQueryWrapper<EmergencyProfessionUser>()
.in(EmergencyProfessionUser::getUserId, localUserIds));
profUsers.forEach(u -> profUserMap.put(u.getUserId(), u));
}
// 查询员工成员的系统用户信息
List<String> employeeUserIds = orderOperators.stream()
.filter(op -> op.getOperatorType() != null && op.getOperatorType() == 2)
.map(OrderOperator::getUserId)
.filter(uid -> !profUserMap.containsKey(uid))
.collect(Collectors.toList());
Map<String, LoginUserNew> sysUserMap = new HashMap<>();
if (!employeeUserIds.isEmpty()) {
sysUserMap = emergencyCloudManager.listUser(employeeUserIds);
}
// 遍历order_operator,只保留验证集中的成员
for (OrderOperator op : orderOperators) {
if (!validAccounts.contains(op.getUserId())) {
continue;
}
String userName = "";
String avatar = "";
String phone = "";
EmergencyProfessionUser profUser = profUserMap.get(op.getUserId());
if (profUser != null) {
userName = profUser.getRealname();
avatar = profUser.getAvatar();
phone = profUser.getPhone();
} else {
LoginUserNew sysUser = sysUserMap.get(op.getUserId());
if (sysUser != null) {
userName = sysUser.getRealname();
avatar = sysUser.getAvatar();
phone = sysUser.getPhone();
}
}
handleGroupMember(groupMemberVos, orderId,
op.getUserId(), userName, avatar, phone, 1, op.getOperatorType());
}
}
// 7. 标记本人
String currentUserId = loginUser.getId();
groupMemberVos.forEach(vo -> vo.setIsSelf(currentUserId.equals(vo.getUserId()) ? 1 : 0));
return groupMemberVos;
}
public void handleGroupMember(List<GroupMemberVO> groupMemberVos, String orderId, String userId, String userName, String avatar, String phone, Integer isGroupMember, Integer memberType) {
GroupMemberVO groupMemberVO = new GroupMemberVO();
groupMemberVO.setOrderId(orderId);
@@ -722,6 +838,7 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
groupMemberVO.setPhone(phone);
groupMemberVO.setIsGroupMember(isGroupMember);
groupMemberVO.setMemberType(memberType);
groupMemberVO.setIsSelf(0);
groupMemberVos.add(groupMemberVO);
}
@@ -783,12 +900,12 @@ public class EmergencyOrderApiServiceImpl implements EmergencyOrderApiService {
excludeUserIds.addAll(ops.stream().map(OrderOperator::getUserId).collect(Collectors.toList()));
}
}
// 构建查询条件
// 构建查询条件(姓名、工号、手机号拼接 * 实现模糊搜索)
SysUser filter = new SysUser();
filter.setRealname(realname);
filter.setRealname(StrUtil.isNotBlank(realname) ? "*" + realname + "*" : null);
filter.setOrgCode(orgCode);
filter.setWorkNo(workNo);
filter.setPhone(phone);
filter.setWorkNo(StrUtil.isNotBlank(workNo) ? "*" + workNo + "*" : null);
filter.setPhone(StrUtil.isNotBlank(phone) ? "*" + phone + "*" : null);
Page<SysUser> srcPage = sysBaseAPI.pageUser(filter, pageNo != null ? pageNo : 1, pageSize != null ? pageSize : 10, null);
Page<EmployeeVO> targetPage = new Page<>(srcPage.getCurrent(), srcPage.getSize(), srcPage.getTotal());
targetPage.setRecords(srcPage.getRecords().stream()