From 07f3bab72acd11b3469ff708ac5b2a1e71430616 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 May 2026 20:29:09 +0800 Subject: [PATCH] ✨ feat(im): 将后端的 roomName 和 callId 融合,简化字段和逻辑(一致性更好、概念更简洁) --- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcCallController.java | 47 +++++++++++++++++++++++------------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcLiveKitController.java | 2 +- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallInviteMoreReqVO.java | 7 +++---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallRespVO.java | 5 +---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcGroupCallRespVO.java | 5 +---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcCallDO.java | 17 +++-------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcParticipantDO.java | 6 +++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcCallMapper.java | 8 ++------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcParticipantMapper.java | 16 ++++++++-------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/rtc/core/LiveKitClient.java | 32 ++++++++++++++++---------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallService.java | 28 ++++++++++++++-------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java | 9 ++------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java | 9 ++------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java | 9 ++------- 17 files changed, 150 insertions(+), 192 deletions(-) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcCallController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcCallController.java index 27fe26a..de5398c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcCallController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcCallController.java @@ -26,7 +26,6 @@ import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -// TODO @AI:需要讨论,到底使用 roomName 还是 callId 更好?前端传参;然后,DO 那种,是不是只存储 callId,roomName 二选 1,是不是就行了。或者统一成 room?uuid 完事;callid 还给 call.id 更好理解; @Tag(name = "管理后台 - IM 实时通话") @RestController @RequestMapping("/im/rtc") @@ -47,9 +46,9 @@ public class ImRtcCallController { @PostMapping("/join") @Operation(summary = "加入已有群通话;用于胶囊条「加入」按钮") - @Parameter(name = "roomName", description = "LiveKit 房间名", required = true, example = "im_rtc_call_xxxx") - public CommonResult joinCall(@RequestParam("roomName") String roomName) { - ImRtcCallDO call = rtcCallService.joinCall(getLoginUserId(), roomName); + @Parameter(name = "room", description = "业务通话编号", required = true, example = "f47ac10b58cc4372a567") + public CommonResult joinCall(@RequestParam("room") String room) { + ImRtcCallDO call = rtcCallService.joinCall(getLoginUserId(), room); return success(buildCallResp(call, getLoginUserId())); } @@ -62,41 +61,41 @@ public class ImRtcCallController { @PostMapping("/accept") @Operation(summary = "接听通话") - @Parameter(name = "roomName", description = "LiveKit 房间名", required = true, example = "call_friend_1_2") - public CommonResult accept(@RequestParam("roomName") String roomName) { - ImRtcCallDO call = rtcCallService.acceptCall(getLoginUserId(), roomName); + @Parameter(name = "room", description = "业务通话编号", required = true, example = "f47ac10b58cc4372a567") + public CommonResult accept(@RequestParam("room") String room) { + ImRtcCallDO call = rtcCallService.acceptCall(getLoginUserId(), room); return success(buildCallResp(call, getLoginUserId())); } @PostMapping("/reject") @Operation(summary = "拒绝通话") - @Parameter(name = "roomName", description = "LiveKit 房间名", required = true, example = "call_friend_1_2") - public CommonResult reject(@RequestParam("roomName") String roomName) { - rtcCallService.rejectCall(getLoginUserId(), roomName); + @Parameter(name = "room", description = "业务通话编号", required = true, example = "f47ac10b58cc4372a567") + public CommonResult reject(@RequestParam("room") String room) { + rtcCallService.rejectCall(getLoginUserId(), room); return success(true); } @PostMapping("/cancel") @Operation(summary = "取消邀请;主叫接通前调用") - @Parameter(name = "roomName", description = "LiveKit 房间名", required = true, example = "call_friend_1_2") - public CommonResult cancel(@RequestParam("roomName") String roomName) { - rtcCallService.cancelCall(getLoginUserId(), roomName); + @Parameter(name = "room", description = "业务通话编号", required = true, example = "f47ac10b58cc4372a567") + public CommonResult cancel(@RequestParam("room") String room) { + rtcCallService.cancelCall(getLoginUserId(), room); return success(true); } @PostMapping("/leave") @Operation(summary = "离开通话;接通后调用") - @Parameter(name = "roomName", description = "LiveKit 房间名", required = true, example = "call_friend_1_2") - public CommonResult leave(@RequestParam("roomName") String roomName) { - rtcCallService.leaveCall(getLoginUserId(), roomName); + @Parameter(name = "room", description = "业务通话编号", required = true, example = "f47ac10b58cc4372a567") + public CommonResult leave(@RequestParam("room") String room) { + rtcCallService.leaveCall(getLoginUserId(), room); return success(true); } @GetMapping("/refresh-token") @Operation(summary = "重新签发 Token;客户端重连或 Token 过期续期") - @Parameter(name = "roomName", description = "LiveKit 房间名", required = true, example = "call_friend_1_2") - public CommonResult refreshToken(@RequestParam("roomName") String roomName) { - ImRtcCallDO call = rtcCallService.refreshCallToken(getLoginUserId(), roomName); + @Parameter(name = "room", description = "业务通话编号", required = true, example = "f47ac10b58cc4372a567") + public CommonResult refreshToken(@RequestParam("room") String room) { + ImRtcCallDO call = rtcCallService.refreshCallToken(getLoginUserId(), room); return success(buildCallResp(call, getLoginUserId())); } @@ -114,11 +113,11 @@ public class ImRtcCallController { if (call == null) { return null; } - List participants = rtcCallService.getCallParticipants(call.getCallId()); + List participants = rtcCallService.getCallParticipants(call.getRoom()); return new ImRtcCallRespVO() - .setCallId(call.getCallId()).setRoomName(call.getRoomName()) + .setRoom(call.getRoom()) .setLivekitUrl(imProperties.getRtc().getLivekitUrl()) - .setToken(rtcCallService.signCallToken(userId, call.getRoomName())) + .setToken(rtcCallService.signCallToken(userId, call.getRoom())) .setScene(call.getConversationType()).setMediaType(call.getMediaType()) .setStatus(call.getStatus()).setInviterId(call.getInviterUserId()) .setGroupId(call.getGroupId()) @@ -130,9 +129,9 @@ public class ImRtcCallController { if (call == null) { return null; } - List participants = rtcCallService.getCallParticipants(call.getCallId()); + List participants = rtcCallService.getCallParticipants(call.getRoom()); return new ImRtcGroupCallRespVO() - .setCallId(call.getCallId()).setRoomName(call.getRoomName()) + .setRoom(call.getRoom()) .setGroupId(call.getGroupId()).setMediaType(call.getMediaType()) .setInviterId(call.getInviterUserId()) .setJoinedUserIds(filterUserIds(participants, ImRtcParticipantStatusEnum.JOINED)) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcLiveKitController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcLiveKitController.java index 140583b..c7437f0 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcLiveKitController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/ImRtcLiveKitController.java @@ -57,7 +57,7 @@ public class ImRtcLiveKitController { } // 2. 交给 service 处理;幂等由 service 自己保证 - log.info("[webhook][事件处理 event={} roomName={}]", event.getEvent(), + log.info("[webhook][事件处理 event={} room={}]", event.getEvent(), event.getRoom() == null ? null : event.getRoom().getName()); try { rtcCallService.handleLiveKitEvent(event); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallInviteMoreReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallInviteMoreReqVO.java index 901348d..a766d7c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallInviteMoreReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallInviteMoreReqVO.java @@ -11,11 +11,10 @@ import java.util.Set; @Data public class ImRtcCallInviteMoreReqVO { - @Schema(description = "LiveKit 房间名", requiredMode = Schema.RequiredMode.REQUIRED, example = "call_group_2048") - @NotBlank(message = "房间名不能为空") - private String roomName; + @Schema(description = "业务通话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "f47ac10b58cc4372a567") + @NotBlank(message = "通话编号不能为空") + private String room; - // TODO @AI:targetIds? @Schema(description = "新邀请的用户编号集合", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "请至少选择一位成员") private Set inviteeIds; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallRespVO.java index 42ce0e4..5f4f361 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallRespVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcCallRespVO.java @@ -10,10 +10,7 @@ import java.util.Set; public class ImRtcCallRespVO { @Schema(description = "业务通话编号") - private String callId; - - @Schema(description = "LiveKit 房间名") - private String roomName; + private String room; @Schema(description = "LiveKit Server WebSocket 地址;前端 connect 用") private String livekitUrl; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcGroupCallRespVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcGroupCallRespVO.java index 9898317..5d1d3ce 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcGroupCallRespVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/rtc/vo/ImRtcGroupCallRespVO.java @@ -10,10 +10,7 @@ import java.util.Set; public class ImRtcGroupCallRespVO { @Schema(description = "业务通话编号") - private String callId; - - @Schema(description = "LiveKit 房间名") - private String roomName; + private String room; @Schema(description = "群编号") private Long groupId; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcCallDO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcCallDO.java index 4ae62b3..e6453d1 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcCallDO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcCallDO.java @@ -16,7 +16,7 @@ import java.time.LocalDateTime; /** * IM 通话记录 DO(房间级 / 主表) *

- * 一通通话一行;状态机 CREATED → RUNNING → ENDED;和明细表 {@link ImRtcParticipantDO} 通过 callId 关联 + * 一通通话一行;状态机 CREATED → RUNNING → ENDED;和明细表 {@link ImRtcParticipantDO} 通过 {@link #room} 关联 * * @author 芋道源码 */ @@ -31,25 +31,14 @@ import java.time.LocalDateTime; public class ImRtcCallDO extends BaseDO { /** - * LiveKit 房间名前缀;roomName 格式固定为 {@code ROOM_NAME_PREFIX + callId} - */ - public static final String ROOM_NAME_PREFIX = "im_rtc_call_"; - - /** * 编号 */ @TableId private Long id; /** - * 业务通话编号;唯一;UUID 生成 - */ - private String callId; - /** - * LiveKit 房间名 - * - * 格式 {@code im_rtc_call_{callId}} + * 业务通话编号(UUID,同时作为 LiveKit 房间名);唯一 */ - private String roomName; + private String room; /** * 会话类型 * diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcParticipantDO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcParticipantDO.java index ea93547..586c247 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcParticipantDO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/rtc/ImRtcParticipantDO.java @@ -13,7 +13,7 @@ import java.time.LocalDateTime; /** * IM 通话参与者 DO(用户级 / 明细表) *

- * 一通通话每个参与者一行;通过 callId 关联主表 {@link ImRtcCallDO} + * 一通通话每个参与者一行;通过 {@link #room} 关联主表 {@link ImRtcCallDO} *

* 终态闭合:通话 ENDED 时所有明细 status 必属 {LEFT / REJECTED / NO_ANSWER} 之一 * @@ -37,9 +37,9 @@ public class ImRtcParticipantDO extends BaseDO { /** * 业务通话编号 *

- * 关联 {@link ImRtcCallDO#getCallId()} + * 关联 {@link ImRtcCallDO#getRoom()} */ - private String callId; + private String room; /** * 参与者用户编号 *

diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcCallMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcCallMapper.java index 49315d1..dee8ff5 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcCallMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcCallMapper.java @@ -18,12 +18,8 @@ import java.util.List; @Mapper public interface ImRtcCallMapper extends BaseMapperX { - default ImRtcCallDO selectByCallId(String callId) { - return selectOne(ImRtcCallDO::getCallId, callId); - } - - default ImRtcCallDO selectByRoomName(String roomName) { - return selectOne(ImRtcCallDO::getRoomName, roomName); + default ImRtcCallDO selectByRoom(String room) { + return selectOne(ImRtcCallDO::getRoom, room); } default ImRtcCallDO selectLastOneByGroupIdAndStatusIn(Long groupId, Collection statuses) { diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcParticipantMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcParticipantMapper.java index da7d156..ea8d5d1 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcParticipantMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/rtc/ImRtcParticipantMapper.java @@ -17,19 +17,19 @@ import java.util.List; @Mapper public interface ImRtcParticipantMapper extends BaseMapperX { - default ImRtcParticipantDO selectByCallIdAndUserId(String callId, Long userId) { + default ImRtcParticipantDO selectByRoomAndUserId(String room, Long userId) { return selectOne(new LambdaQueryWrapperX() - .eq(ImRtcParticipantDO::getCallId, callId) + .eq(ImRtcParticipantDO::getRoom, room) .eq(ImRtcParticipantDO::getUserId, userId)); } - default List selectListByCallId(String callId) { - return selectList(ImRtcParticipantDO::getCallId, callId); + default List selectListByRoom(String room) { + return selectList(ImRtcParticipantDO::getRoom, room); } - default List selectListByCallIdAndStatus(String callId, Integer status) { + default List selectListByRoomAndStatus(String room, Integer status) { return selectList(new LambdaQueryWrapperX() - .eq(ImRtcParticipantDO::getCallId, callId) + .eq(ImRtcParticipantDO::getRoom, room) .eq(ImRtcParticipantDO::getStatus, status)); } @@ -47,9 +47,9 @@ public interface ImRtcParticipantMapper extends BaseMapperX } @SuppressWarnings("UnusedReturnValue") - default int updateByCallIdAndStatus(String callId, Integer oldStatus, ImRtcParticipantDO updateObj) { + default int updateByRoomAndStatus(String room, Integer oldStatus, ImRtcParticipantDO updateObj) { return update(updateObj, Wrappers.lambdaUpdate() - .eq(ImRtcParticipantDO::getCallId, callId) + .eq(ImRtcParticipantDO::getRoom, room) .eq(ImRtcParticipantDO::getStatus, oldStatus)); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/rtc/core/LiveKitClient.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/rtc/core/LiveKitClient.java index 10b7562..a9c1342 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/rtc/core/LiveKitClient.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/rtc/core/LiveKitClient.java @@ -62,18 +62,18 @@ public class LiveKitClient { * * @param identity 用户唯一标识;写入 sub claim;同 identity 重连会踢前一个连接 * @param displayName 客户端展示名;可空 - * @param roomName 房间名 + * @param room 房间名 * @return JWT 字符串 */ - public String signJoinToken(String identity, String displayName, String roomName) { + public String signJoinToken(String identity, String displayName, String room) { Assert.notBlank(identity, "identity 不可为空"); - Assert.notBlank(roomName, "roomName 不可为空"); + Assert.notBlank(room, "room 不可为空"); ImProperties.Rtc cfg = imProperties.getRtc(); // video claim:限定客户端能在该房间内做什么 Map video = new HashMap<>(); video.put("roomJoin", true); // 允许加入房间 - video.put("room", roomName); // 限定只能加入这个房间 + video.put("room", room); // 限定只能加入这个房间 video.put("canPublish", true); // 允许发布媒体(推流) video.put("canSubscribe", true); // 允许订阅媒体(拉流) video.put("canPublishData", true); // 允许发送 data channel 消息 @@ -96,11 +96,11 @@ public class LiveKitClient { /** * 调用 LiveKit Server API 删除房间:用于通话结束时,强制断开异常残留客户端 * - * @param roomName 房间名 + * @param room 房间名 */ @SuppressWarnings("EmptyTryBlock") - public void deleteRoom(String roomName) { - try (HttpResponse ignored = postTwirp(TWIRP_DELETE_ROOM, roomName)) { + public void deleteRoom(String room) { + try (HttpResponse ignored = postTwirp(TWIRP_DELETE_ROOM, room)) { // 状态码不区分;调用方失败即兜底 } } @@ -110,17 +110,17 @@ public class LiveKitClient { *

* 房间不存在 LiveKit 返回 404,视同 0 人 * - * @param roomName 房间名 + * @param room 房间名 * @return 参与者数量;HTTP 失败返回 -1 */ - public int listParticipants(String roomName) { - try (HttpResponse response = postTwirp(TWIRP_LIST_PARTICIPANTS, roomName)) { + public int listParticipants(String room) { + try (HttpResponse response = postTwirp(TWIRP_LIST_PARTICIPANTS, room)) { if (response.getStatus() == 404) { return 0; } if (!response.isOk()) { - log.warn("[listParticipants][LiveKit 返回非 2xx status={} roomName={} body={}]", - response.getStatus(), roomName, response.body()); + log.warn("[listParticipants][LiveKit 返回非 2xx status={} room={} body={}]", + response.getStatus(), room, response.body()); return -1; } JSONArray participants = JSONUtil.parseObj(response.body()).getJSONArray("participants"); @@ -223,16 +223,16 @@ public class LiveKitClient { * Twirp 协议 POST 调用;统一处理 ws→http 协议切换、签 admin token、Bearer 头、JSON body、超时 * * @param path Twirp 端点路径,例如 {@code /twirp/livekit.RoomService/DeleteRoom} - * @param roomName 房间名;写入 JSON body 的 room 字段 + * @param room 房间名;写入 JSON body 的 room 字段 * @return HTTP 响应;调用方负责 close 与状态码判断 */ - private HttpResponse postTwirp(String path, String roomName) { - Assert.notBlank(roomName, "roomName 不可为空"); + private HttpResponse postTwirp(String path, String room) { + Assert.notBlank(room, "room 不可为空"); String token = signAdminToken(); return HttpRequest.post(HttpUtils.wsUrlToHttp(imProperties.getRtc().getLivekitUrl()) + path) .header("Authorization", "Bearer " + token) .header("Content-Type", "application/json") - .body(JSONUtil.toJsonStr(Map.of("room", roomName))) + .body(JSONUtil.toJsonStr(Map.of("room", room))) .timeout(SERVER_API_TIMEOUT_MS) .execute(); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallService.java index 0b78fa8..e530bcf 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallService.java @@ -28,17 +28,17 @@ public interface ImRtcCallService { /** * 加入已有群通话:用于群胶囊条「加入」按钮;旁观者作为 ACTIVE_JOIN 加入,邀请池内成员转 JOINED * - * @param userId 加入者用户编号 - * @param roomName LiveKit 房间名;从胶囊条 activeCall 拿 + * @param userId 加入者用户编号 + * @param room 业务通话编号;从胶囊条 activeCall 拿 * @return 通话主表 */ - ImRtcCallDO joinCall(Long userId, String roomName); + ImRtcCallDO joinCall(Long userId, String room); /** * 通话中追加成员:仅群通话场景可用;给新邀请人推 RTC_CALL(INVITE) * * @param userId 操作人编号;必须是当前会话参与者 - * @param reqVO 房间名 + 新邀请的用户编号集合 + * @param reqVO room + 新邀请的用户编号集合 */ void inviteMoreCall(Long userId, ImRtcCallInviteMoreReqVO reqVO); @@ -47,22 +47,22 @@ public interface ImRtcCallService { * * @return 通话主表 */ - ImRtcCallDO acceptCall(Long userId, String roomName); + ImRtcCallDO acceptCall(Long userId, String room); /** * 拒绝通话;仅 INVITING 状态可拒;群通话拒绝等同于不参与,房间仍存在 */ - void rejectCall(Long userId, String roomName); + void rejectCall(Long userId, String room); /** * 取消邀请;主叫在 INVITING 状态主动取消 */ - void cancelCall(Long userId, String roomName); + void cancelCall(Long userId, String room); /** * 离开通话;RUNNING 状态下离开;私聊任一方离开 = 通话结束;群通话最后一人离开才结束 */ - void leaveCall(Long userId, String roomName); + void leaveCall(Long userId, String room); /** * 校验用户仍是该通话的参与者,用于客户端重连或 Token 过期续期前的合法性检查; @@ -70,7 +70,7 @@ public interface ImRtcCallService { * * @return 通话主表 */ - ImRtcCallDO refreshCallToken(Long userId, String roomName); + ImRtcCallDO refreshCallToken(Long userId, String room); /** * 查询当前正在进行的通话;目前仅群聊场景(胶囊条),私聊未来扩展再补 peerUserId 参数 @@ -86,19 +86,19 @@ public interface ImRtcCallService { /** * 查询某通话的全部参与者明细;交给 Controller 拼装 inviteeIds / joinedUserIds * - * @param callId 业务通话编号 + * @param room 业务通话编号 * @return 参与者明细列表 */ - List getCallParticipants(String callId); + List getCallParticipants(String room); /** * 签发指定用户进入该通话的 LiveKit Token;供 Controller 拼接到响应 VO * - * @param userId 进房用户编号;token 内 displayName 取该用户昵称 - * @param roomName LiveKit 房间名 + * @param userId 进房用户编号;token 内 displayName 取该用户昵称 + * @param room 业务通话编号 * @return JWT 字符串 */ - String signCallToken(Long userId, String roomName); + String signCallToken(Long userId, String room); /** * 处理 LiveKit Webhook 事件;用于关 tab / 强杀 / 网络断开等异常退出场景的兜底清理 diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java index 2c691b7..fb71718 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/rtc/ImRtcCallServiceImpl.java @@ -155,28 +155,26 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { * @return 通话主表 */ private ImRtcCallDO createCall(Long inviterId, ImRtcCallInviteReqVO reqVO) { - // 1. 构造参数:派生 callId / roomName,解析被邀请池(私聊单元素;群聊 invitee 子集或全员) - // TODO @AI:callId、roomName 都抽成小方法。 - String callId = IdUtil.fastSimpleUUID(); - String roomName = ImRtcCallDO.ROOM_NAME_PREFIX + callId; + // 1. 构造参数:room 用 UUID;解析被邀请池 + String room = IdUtil.fastSimpleUUID(); LocalDateTime now = LocalDateTime.now(); Set invitees = resolveInvitees(reqVO, inviterId); // 2.1 INSERT 主表;群聊发起人即时 JOINED 但通话仍处 CREATED,等首个非发起人接通才切 RUNNING - ImRtcCallDO call = new ImRtcCallDO().setCallId(callId).setRoomName(roomName) + ImRtcCallDO call = new ImRtcCallDO().setRoom(room) .setConversationType(reqVO.getScene()).setMediaType(reqVO.getMediaType()) .setInviterUserId(inviterId).setGroupId(reqVO.getGroupId()) .setStatus(ImRtcCallStatusEnum.CREATED.getStatus()).setStartTime(now); rtcCallMapper.insert(call); // 2.2 批量 INSERT 参与表:发起人即时 JOINED,被邀请人 INVITING 等接通 List participants = new ArrayList<>(invitees.size() + 1); - participants.add(new ImRtcParticipantDO().setCallId(callId).setUserId(inviterId) + participants.add(new ImRtcParticipantDO().setRoom(room).setUserId(inviterId) .setRole(ImRtcParticipantRoleEnum.INVITER.getRole()) .setStatus(ImRtcParticipantStatusEnum.JOINED.getStatus()) .setInviteTime(now).setAcceptTime(now)); for (Long inviteeId : invitees) { participants.add(new ImRtcParticipantDO() - .setCallId(callId).setUserId(inviteeId) + .setRoom(room).setUserId(inviteeId) .setRole(ImRtcParticipantRoleEnum.INVITEE.getRole()) .setStatus(ImRtcParticipantStatusEnum.INVITING.getStatus()) .setInviteTime(now)); @@ -197,10 +195,10 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { } @Override - public ImRtcCallDO joinCall(Long userId, String roomName) { + public ImRtcCallDO joinCall(Long userId, String room) { ensureEnabled(); // 1.1 校验通话存在且活跃 - ImRtcCallDO call = validateCallActive(roomName); + ImRtcCallDO call = validateCallActive(room); // 1.2 仅群通话支持「旁观者加入」 if (!ImConversationTypeEnum.isGroup(call.getConversationType())) { throw exception(RTC_GROUP_REQUIRED); @@ -208,7 +206,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { // 2. 入参与表:已有记录切回 JOINED;不在记录则以 ACTIVE_JOIN 角色 INSERT LocalDateTime now = LocalDateTime.now(); - ImRtcParticipantDO existing = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcParticipantDO existing = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (existing != null) { // 非 JOINED 状态切回 JOINED + accept_time;INVITER / INVITEE 重连 / 旁观点胶囊条都走这条 if (!ImRtcParticipantStatusEnum.isJoined(existing.getStatus())) { @@ -217,7 +215,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { } } else { // 旁观者主动加入:INSERT role=ACTIVE_JOIN - rtcParticipantMapper.insert(new ImRtcParticipantDO().setCallId(call.getCallId()) + rtcParticipantMapper.insert(new ImRtcParticipantDO().setRoom(call.getRoom()) .setUserId(userId).setRole(ImRtcParticipantRoleEnum.ACTIVE_JOIN.getRole()) .setStatus(ImRtcParticipantStatusEnum.JOINED.getStatus()).setInviteTime(now).setAcceptTime(now)); } @@ -231,13 +229,13 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { public void inviteMoreCall(Long userId, ImRtcCallInviteMoreReqVO reqVO) { ensureEnabled(); // TODO @AI:校验的,按照 1.1 1.2 1.3 这样; - ImRtcCallDO call = validateCallActive(reqVO.getRoomName()); + ImRtcCallDO call = validateCallActive(reqVO.getRoom()); // 仅群通话支持追加邀请 if (!ImConversationTypeEnum.isGroup(call.getConversationType())) { throw exception(RTC_GROUP_REQUIRED); } // 操作者必须是已在房间的参与者 - ImRtcParticipantDO operator = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcParticipantDO operator = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (operator == null || !ImRtcParticipantStatusEnum.isJoined(operator.getStatus())) { throw exception(RTC_NOT_PARTICIPANT); } @@ -246,7 +244,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { Set validMemberIds = new LinkedHashSet<>( groupMemberService.getActiveGroupMemberUserIdsByGroupId(call.getGroupId())); // TODO @AI:convertSet; - Set existingUserIds = rtcParticipantMapper.selectListByCallId(call.getCallId()).stream() + Set existingUserIds = rtcParticipantMapper.selectListByRoom(call.getRoom()).stream() .map(ImRtcParticipantDO::getUserId) .collect(Collectors.toSet()); // TODO @AI:incomingUserIds;直接 remove 原始的元素;没必要;单独的; @@ -262,7 +260,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { LocalDateTime now = LocalDateTime.now(); for (Long inviteeId : incoming) { rtcParticipantMapper.insert(new ImRtcParticipantDO() - .setCallId(call.getCallId()).setUserId(inviteeId) + .setRoom(call.getRoom()).setUserId(inviteeId) .setRole(ImRtcParticipantRoleEnum.INVITEE.getRole()) .setStatus(ImRtcParticipantStatusEnum.INVITING.getStatus()) .setInviteTime(now)); @@ -276,11 +274,11 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { } @Override - public ImRtcCallDO acceptCall(Long userId, String roomName) { + public ImRtcCallDO acceptCall(Long userId, String room) { ensureEnabled(); // TODO @AI:按照 inviteMoreCall 风格,优化下注释; - ImRtcCallDO call = validateCallActive(roomName); - ImRtcParticipantDO participant = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcCallDO call = validateCallActive(room); + ImRtcParticipantDO participant = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (participant == null) { throw exception(RTC_NOT_PARTICIPANT); } @@ -305,11 +303,11 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { } @Override - public void rejectCall(Long userId, String roomName) { + public void rejectCall(Long userId, String room) { ensureEnabled(); // TODO @AI:按照 inviteMoreCall 风格,优化下注释; - ImRtcCallDO call = validateCallActive(roomName); - ImRtcParticipantDO participant = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcCallDO call = validateCallActive(room); + ImRtcParticipantDO participant = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (participant == null) { throw exception(RTC_NOT_PARTICIPANT); } @@ -337,10 +335,10 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { } @Override - public void cancelCall(Long userId, String roomName) { + public void cancelCall(Long userId, String room) { ensureEnabled(); // TODO @AI:按照 inviteMoreCall 风格,优化下注释; - ImRtcCallDO call = validateCallActive(roomName); + ImRtcCallDO call = validateCallActive(room); // TODO @AI:notEquals; if (!Objects.equals(call.getInviterUserId(), userId)) { throw exception(RTC_NOT_PARTICIPANT); @@ -355,11 +353,11 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { } @Override - public void leaveCall(Long userId, String roomName) { + public void leaveCall(Long userId, String room) { ensureEnabled(); // TODO @AI:按照 inviteMoreCall 风格,优化下注释; - ImRtcCallDO call = validateCallActive(roomName); - ImRtcParticipantDO participant = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcCallDO call = validateCallActive(room); + ImRtcParticipantDO participant = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (participant == null) { throw exception(RTC_NOT_PARTICIPANT); } @@ -373,7 +371,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { // TODO @AI:群聊的关房,本质和单聊,是不是一样的?是否有必要统一掉? // 关房条件:私聊任一方离开 = 关;群通话仅在「无人在房 + 无人响铃」时关 if (ImConversationTypeEnum.isPrivate(call.getConversationType()) - || shouldCloseGroupRoom(call.getCallId())) { + || shouldCloseGroupRoom(call.getRoom())) { endSession(call, userId, ImRtcCallEndReasonEnum.HANGUP); } // 群通话单人离开:LiveKit `ParticipantDisconnected` 自动通知房内成员;业务后端不另外推 @@ -386,9 +384,9 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { *

* 关房后 endSession 会把残留 INVITING 批量改 NO_ANSWER 并推 RTC_CALL_END,响铃端 UI 自动收敛 */ - private boolean shouldCloseGroupRoom(String callId) { + private boolean shouldCloseGroupRoom(String room) { // TODO @AI:通过查询,计算情况?;感觉所有群聊的关闭条件:都是只有 1 个 join,剩余都处于结束,说白了没人可以和他电话了。。。。 - List joined = rtcParticipantMapper.selectListByCallIdAndStatus(callId, + List joined = rtcParticipantMapper.selectListByRoomAndStatus(room, ImRtcParticipantStatusEnum.JOINED.getStatus()); return CollUtil.isEmpty(joined); } @@ -406,13 +404,13 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { if (aPart == null) { return null; } - ImRtcCallDO call = rtcCallMapper.selectByCallId(aPart.getCallId()); + ImRtcCallDO call = rtcCallMapper.selectByRoom(aPart.getRoom()); if (call == null || !ImConversationTypeEnum.isPrivate(call.getConversationType()) || ImRtcCallStatusEnum.isEnded(call.getStatus())) { return null; } - ImRtcParticipantDO bPart = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userIdB); + ImRtcParticipantDO bPart = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userIdB); if (bPart == null || !ImRtcParticipantStatusEnum.ACTIVE_STATUSES.contains(bPart.getStatus())) { return null; @@ -422,11 +420,11 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { // TODO @AI:怎么感觉这个要改下?是不是根据 userid + callid 更合理? @Override - public ImRtcCallDO refreshCallToken(Long userId, String roomName) { + public ImRtcCallDO refreshCallToken(Long userId, String room) { ensureEnabled(); // TODO @AI:按照 inviteMoreCall 风格,优化下注释; - ImRtcCallDO call = validateCallActive(roomName); - ImRtcParticipantDO participant = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcCallDO call = validateCallActive(room); + ImRtcParticipantDO participant = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (participant == null) { throw exception(RTC_NOT_PARTICIPANT); } @@ -444,16 +442,16 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { // TODO @AI:方法名,复数应该使用 List,不使用 s; @Override - public List getCallParticipants(String callId) { - return rtcParticipantMapper.selectListByCallId(callId); + public List getCallParticipants(String room) { + return rtcParticipantMapper.selectListByRoom(room); } @Override - public String signCallToken(Long userId, String roomName) { + public String signCallToken(Long userId, String room) { AdminUserRespDTO user = adminUserApi.getUser(userId); // TODO @AI:不能为空。。。nickname 为空,则使用 userid; String displayName = user == null ? null : user.getNickname(); - return signToken(userId, displayName, roomName); + return signToken(userId, displayName, room); } // TODO DONE @AI:兼容 JDK8 —— 项目 Spring Boot 3 已要求 JDK17+,switch arrow case 可直接用 @@ -483,8 +481,8 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { return; } // 前置检查 - String roomName = event.getRoom().getName(); - ImRtcCallDO call = rtcCallMapper.selectByRoomName(roomName); + String room = event.getRoom().getName(); + ImRtcCallDO call = rtcCallMapper.selectByRoom(room); if (call == null || ImRtcCallStatusEnum.isEnded(call.getStatus())) { return; } @@ -506,8 +504,8 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { return; } // 前置检查 - String roomName = event.getRoom().getName(); - ImRtcCallDO call = rtcCallMapper.selectByRoomName(roomName); + String room = event.getRoom().getName(); + ImRtcCallDO call = rtcCallMapper.selectByRoom(room); if (call == null || ImRtcCallStatusEnum.isEnded(call.getStatus())) { return; } @@ -515,7 +513,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { if (userId == null) { return; } - ImRtcParticipantDO participant = rtcParticipantMapper.selectByCallIdAndUserId(call.getCallId(), userId); + ImRtcParticipantDO participant = rtcParticipantMapper.selectByRoomAndUserId(call.getRoom(), userId); if (participant == null || !ImRtcParticipantStatusEnum.isJoined(participant.getStatus())) { return; } @@ -526,14 +524,14 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { if (updated == 0) { return; } - log.info("[handleParticipantLeft][roomName={} userId={} 由 LiveKit Webhook 兜底]", roomName, userId); + log.info("[handleParticipantLeft][room={} userId={} 由 LiveKit Webhook 兜底]", room, userId); // 推 1603 通知参与方 / 全群参与方 pushParticipantDisconnectedNotification(call, userId); // 关房条件与 leave 一致;群通话仅在「无人在房 + 无人响铃」时关 // TODO @AI:注释风格;感觉可以抽个 endSessionIfXXX;收口更统一; if (ImConversationTypeEnum.isPrivate(call.getConversationType()) - || shouldCloseGroupRoom(call.getCallId())) { + || shouldCloseGroupRoom(call.getRoom())) { endSession(call, userId, ImRtcCallEndReasonEnum.HANGUP); } } @@ -546,14 +544,14 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { return; } // 前置检查 - String roomName = event.getRoom().getName(); - ImRtcCallDO call = rtcCallMapper.selectByRoomName(roomName); + String room = event.getRoom().getName(); + ImRtcCallDO call = rtcCallMapper.selectByRoom(room); if (call == null || ImRtcCallStatusEnum.isEnded(call.getStatus())) { return; } // TODO @AI:注释。带序号的; - log.info("[handleRoomFinished][roomName={} 由 LiveKit Webhook 兜底]", roomName); + log.info("[handleRoomFinished][room={} 由 LiveKit Webhook 兜底]", room); endSession(call, null, ImRtcCallEndReasonEnum.HANGUP); } @@ -572,17 +570,15 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { for (ImRtcCallDO call : candidates) { int count; try { - count = liveKitClient.listParticipants(call.getRoomName()); + count = liveKitClient.listParticipants(call.getRoom()); } catch (Exception e) { - log.warn("[cleanupZombieCalls][查询 LiveKit 失败 callId={} roomName={}]", - call.getCallId(), call.getRoomName(), e); + log.warn("[cleanupZombieCalls][查询 LiveKit 失败 room={}]", call.getRoom(), e); continue; } if (count != 0) { continue; } - log.info("[cleanupZombieCalls][清理僵尸通话 callId={} roomName={}]", - call.getCallId(), call.getRoomName()); + log.info("[cleanupZombieCalls][清理僵尸通话 room={}]", call.getRoom()); endSession(call, null, ImRtcCallEndReasonEnum.HANGUP); cleaned++; } @@ -604,8 +600,8 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { /** * 校验通话存在且活跃:不存在 / 已 ENDED 直接抛 */ - private ImRtcCallDO validateCallActive(String roomName) { - ImRtcCallDO call = rtcCallMapper.selectByRoomName(roomName); + private ImRtcCallDO validateCallActive(String room) { + ImRtcCallDO call = rtcCallMapper.selectByRoom(room); if (call == null || ImRtcCallStatusEnum.isEnded(call.getStatus())) { throw exception(RTC_SESSION_NOT_EXISTS); } @@ -729,29 +725,29 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { new ImRtcCallDO().setStatus(ImRtcCallStatusEnum.ENDED.getStatus()) .setEndReason(reason.getReason()).setEndTime(now)); if (updated == 0) { - log.info("[endSession][已被另一路径终结,跳过 callId={} roomName={} operator={} reason={}]", - call.getCallId(), call.getRoomName(), operatorId, reason); + log.info("[endSession][已被另一路径终结,跳过 room={} operator={} reason={}]", + call.getRoom(), operatorId, reason); return; } // 1.2 更新参与表为已结束:残留 INVITING 改 NO_ANSWER;残留 JOINED 改 LEFT 并写 leaveTime - rtcParticipantMapper.updateByCallIdAndStatus(call.getCallId(), ImRtcParticipantStatusEnum.INVITING.getStatus(), + rtcParticipantMapper.updateByRoomAndStatus(call.getRoom(), ImRtcParticipantStatusEnum.INVITING.getStatus(), new ImRtcParticipantDO().setStatus(ImRtcParticipantStatusEnum.NO_ANSWER.getStatus())); - rtcParticipantMapper.updateByCallIdAndStatus(call.getCallId(), ImRtcParticipantStatusEnum.JOINED.getStatus(), + rtcParticipantMapper.updateByRoomAndStatus(call.getRoom(), ImRtcParticipantStatusEnum.JOINED.getStatus(), new ImRtcParticipantDO().setStatus(ImRtcParticipantStatusEnum.LEFT.getStatus()).setLeaveTime(now)); // 2. 兜底删除 LiveKit 房间,强制断开异常残留客户端;失败仅记日志,不阻断业务 try { - liveKitClient.deleteRoom(call.getRoomName()); + liveKitClient.deleteRoom(call.getRoom()); } catch (Exception e) { - log.warn("[endSession][删除 LiveKit 房间失败 callId={} roomName={} operator={} reason={}]", - call.getCallId(), call.getRoomName(), operatorId, reason, e); + log.warn("[endSession][删除 LiveKit 房间失败 room={} operator={} reason={}]", + call.getRoom(), operatorId, reason, e); } // 3. 推 RTC_CALL_END Long durationSeconds = call.getAcceptTime() != null ? Duration.between(call.getAcceptTime(), now).getSeconds() : null; pushCallEndNotification(call, operatorId, reason, durationSeconds); - log.info("[endSession][roomName={} operator={} reason={}]", call.getRoomName(), operatorId, reason); + log.info("[endSession][room={} operator={} reason={}]", call.getRoom(), operatorId, reason); } // TODO @AI:getCallAudienceUserIdList? @@ -765,7 +761,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { return groupMemberService.getActiveGroupMemberUserIdsByGroupId(call.getGroupId()); } return CollectionUtils.convertSet( - rtcParticipantMapper.selectListByCallId(call.getCallId()), ImRtcParticipantDO::getUserId); + rtcParticipantMapper.selectListByRoom(call.getRoom()), ImRtcParticipantDO::getUserId); } // TODO @AI:这里的 ========== 太短了; @@ -779,7 +775,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { * 不能走 imPrivateMessageService.send:persistent=false 时 send 仅推 sender 多端,receiver 不感知 */ private void pushCallInviteNotification(ImRtcCallDO call, AdminUserRespDTO inviter, Long inviteeId) { - String token = signToken(inviteeId, inviter == null ? null : inviter.getNickname(), call.getRoomName()); + String token = signToken(inviteeId, inviter == null ? null : inviter.getNickname(), call.getRoom()); ImRtcCallNotification payload = ImRtcCallNotification.ofInvite( call, inviter, imProperties.getRtc().getLivekitUrl(), token); webSocketService.sendPrivateMessageAsync(inviteeId, ImPrivateMessageDTO.ofRtcNotification( @@ -865,7 +861,7 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { // 私聊:发起人总是 sender;receiver = 通话另一方 ImRtcParticipantDO peer = CollUtil.findOne( - rtcParticipantMapper.selectListByCallId(call.getCallId()), + rtcParticipantMapper.selectListByRoom(call.getRoom()), p -> !Objects.equals(p.getUserId(), senderId)); Long receiverId = peer != null ? peer.getUserId() : senderId; ImPrivateMessageSendDTO dto = new ImPrivateMessageSendDTO().setReceiverId(receiverId) @@ -879,9 +875,9 @@ public class ImRtcCallServiceImpl implements ImRtcCallService { * 签 LiveKit Token */ // TODO @AI:sign 方法,是不是传递 adminuserdo? - private String signToken(Long userId, String displayName, String roomName) { - // TODO @AI:是不是抽一个 signJoinToken(userid, displayName, roomName)做减法 - return liveKitClient.signJoinToken(liveKitClient.buildIdentity(userId), displayName, roomName); + private String signToken(Long userId, String displayName, String room) { + // TODO @AI:是不是抽一个 signJoinToken(userid, displayName, room)做减法 + return liveKitClient.signJoinToken(liveKitClient.buildIdentity(userId), displayName, room); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java index 9399721..9676ac5 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallEndNotification.java @@ -25,7 +25,7 @@ public class ImRtcCallEndNotification { /** * 业务通话编号 */ - private String callId; + private String room; /** * 会话类型 */ @@ -60,7 +60,7 @@ public class ImRtcCallEndNotification { public static ImRtcCallEndNotification of(ImRtcCallDO call, ImRtcCallEndReasonEnum reason, Long durationSeconds, Long operatorId, AdminUserRespDTO operator) { ImRtcCallEndNotification notification = new ImRtcCallEndNotification(); - notification.callId = call.getCallId(); + notification.room = call.getRoom(); notification.conversationType = call.getConversationType(); notification.mediaType = call.getMediaType(); notification.endReason = reason.getReason(); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java index 97fcd31..fee069d 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallNotification.java @@ -27,11 +27,7 @@ public class ImRtcCallNotification { /** * 业务通话编号 */ - private String callId; - /** - * LiveKit 房间名 - */ - private String roomName; + private String room; /** * 会话类型 */ @@ -176,8 +172,7 @@ public class ImRtcCallNotification { private static ImRtcCallNotification baseOf(ImRtcCallDO call, Integer status) { ImRtcCallNotification notification = new ImRtcCallNotification(); notification.status = status; - notification.callId = call.getCallId(); - notification.roomName = call.getRoomName(); + notification.room = call.getRoom(); notification.conversationType = call.getConversationType(); notification.mediaType = call.getMediaType(); notification.groupId = call.getGroupId(); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java index d375d4c..965a8a2 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcCallStartNotification.java @@ -23,7 +23,7 @@ public class ImRtcCallStartNotification { /** * 业务通话编号 */ - private String callId; + private String room; /** * 会话类型:当前固定 GROUP(私聊无 START) */ @@ -47,7 +47,7 @@ public class ImRtcCallStartNotification { public static ImRtcCallStartNotification of(ImRtcCallDO call, AdminUserRespDTO inviter) { ImRtcCallStartNotification notification = new ImRtcCallStartNotification(); - notification.callId = call.getCallId(); + notification.room = call.getRoom(); notification.conversationType = call.getConversationType(); notification.mediaType = call.getMediaType(); notification.inviterUserId = call.getInviterUserId(); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java index 283bc35..4bbfb48 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantConnectedNotification.java @@ -18,11 +18,7 @@ public class ImRtcParticipantConnectedNotification { /** * 业务通话编号 */ - private String callId; - /** - * LiveKit 房间名 - */ - private String roomName; + private String room; /** * 加入的参与者用户编号 */ @@ -53,8 +49,7 @@ public class ImRtcParticipantConnectedNotification { */ public static ImRtcParticipantConnectedNotification of(ImRtcCallDO call, Long userId) { ImRtcParticipantConnectedNotification notification = new ImRtcParticipantConnectedNotification(); - notification.callId = call.getCallId(); - notification.roomName = call.getRoomName(); + notification.room = call.getRoom(); notification.userId = userId; notification.conversationType = call.getConversationType(); notification.groupId = call.getGroupId(); diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java index ffe2671..94168c0 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/rtc/ImRtcParticipantDisconnectedNotification.java @@ -18,11 +18,7 @@ public class ImRtcParticipantDisconnectedNotification { /** * 业务通话编号 */ - private String callId; - /** - * LiveKit 房间名 - */ - private String roomName; + private String room; /** * 离开的参与者用户编号 */ @@ -45,8 +41,7 @@ public class ImRtcParticipantDisconnectedNotification { */ public static ImRtcParticipantDisconnectedNotification of(ImRtcCallDO call, Long userId) { ImRtcParticipantDisconnectedNotification notification = new ImRtcParticipantDisconnectedNotification(); - notification.callId = call.getCallId(); - notification.roomName = call.getRoomName(); + notification.room = call.getRoom(); notification.userId = userId; notification.conversationType = call.getConversationType(); notification.groupId = call.getGroupId(); -- libgit2 0.21.4