From e62e8b6f170c16cc21705a16246f0f97c437bac3 Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Thu, 23 Apr 2026 12:04:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=88=BF=E9=97=B4=20explore?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 25ddd251c1d3754b4f578aa70a5b624f9f6be65f) --- .../app/room/LiveVoiceRoomRestController.java | 14 ++++ .../room/query/RoomVoiceExploreQryExe.java | 81 +++++++++++++++++++ .../room/LiveVoiceRoomServiceImpl.java | 8 ++ .../app/dto/cmd/room/RoomExploreQryCmd.java | 21 +++++ .../service/room/LiveVoiceRoomService.java | 3 + .../service/live/ActiveVoiceRoomService.java | 5 ++ .../live/impl/ActiveVoiceRoomServiceImpl.java | 41 +++++++++- 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/query/RoomVoiceExploreQryExe.java create mode 100644 rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/room/RoomExploreQryCmd.java diff --git a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/room/LiveVoiceRoomRestController.java b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/room/LiveVoiceRoomRestController.java index 320712f0..88e695ac 100644 --- a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/room/LiveVoiceRoomRestController.java +++ b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/room/LiveVoiceRoomRestController.java @@ -8,6 +8,7 @@ import com.red.circle.other.app.dto.clientobject.room.RoomOnlineUserCO; import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO; import com.red.circle.other.app.dto.cmd.room.RegionSearchRoomQryCmd; import com.red.circle.other.app.dto.cmd.room.RoomEntryCmd; +import com.red.circle.other.app.dto.cmd.room.RoomExploreQryCmd; import com.red.circle.other.app.dto.cmd.room.RoomOnlineUserFlowQryCmd; import com.red.circle.other.app.dto.cmd.room.SearchRoomAccountCmd; import com.red.circle.other.app.service.room.LiveVoiceRoomService; @@ -158,4 +159,17 @@ public class LiveVoiceRoomRestController extends BaseController { return liveVoiceRoomService.discovery(cmd); } + /** + * explore 列表. + * + * @eo.name explore 列表. + * @eo.url /explore + * @eo.method get + * @eo.request-type formdata + */ + @GetMapping("/explore") + public List explore(RoomExploreQryCmd cmd) { + return liveVoiceRoomService.explore(cmd); + } + } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/query/RoomVoiceExploreQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/query/RoomVoiceExploreQryExe.java new file mode 100644 index 00000000..75cae9e6 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/room/query/RoomVoiceExploreQryExe.java @@ -0,0 +1,81 @@ +package com.red.circle.other.app.command.room.query; + +import com.red.circle.common.business.enums.SVIPLevelEnum; +import com.red.circle.other.app.common.room.RoomVoiceProfileCommon; +import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO; +import com.red.circle.other.app.dto.cmd.room.RoomExploreQryCmd; +import com.red.circle.other.app.service.game.GameLudoService; +import com.red.circle.other.app.service.room.RocketStatusCacheService; +import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway; +import com.red.circle.other.domain.gateway.user.ability.UserSVipGateway; +import com.red.circle.other.domain.rocket.RocketStatus; +import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom; +import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService; +import com.red.circle.tool.core.collection.CollectionUtils; +import com.red.circle.tool.core.text.StringUtils; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * explore 房间列表查询. + * + * @author tf + */ +@Component +@RequiredArgsConstructor +public class RoomVoiceExploreQryExe { + + private static final int EXPLORE_LIMIT = 100; + + private final UserRegionGateway userRegionGateway; + private final UserSVipGateway userSVipGateway; + private final ActiveVoiceRoomService activeVoiceRoomService; + private final RoomVoiceProfileCommon roomVoiceProfileCommon; + private final RocketStatusCacheService rocketStatusCacheService; + private final GameLudoService gameLudoService; + + public List execute(RoomExploreQryCmd cmd) { + String userRegion = StringUtils.isNotBlank(cmd.getCountryCode()) + ? null + : userRegionGateway.getRegionCode(cmd.requiredReqUserId()); + + List rooms = activeVoiceRoomService.listExplore( + cmd.requireReqSysOrigin(), userRegion, cmd.getCountryCode(), EXPLORE_LIMIT); + + List roomList = roomVoiceProfileCommon.toListRoomVoiceProfileCO(rooms); + if (CollectionUtils.isEmpty(roomList)) { + return CollectionUtils.newArrayList(); + } + + fillRocketStatus(roomList); + fillGameIcon(roomList); + + return roomList; + } + + private void fillRocketStatus(List roomList) { + List roomIds = roomList.stream().map(RoomVoiceProfileCO::getId).toList(); + Map rocketStatusMap = rocketStatusCacheService.batchGetRocketStatus(roomIds); + roomList.forEach(room -> { + RocketStatus rs = rocketStatusMap.get(room.getId()); + if (rs != null) { + room.setRocketLevel(rs.getLevel().getLevel()); + room.setRocketEnergy(rs.getCurrentEnergy()); + } else { + room.setRocketLevel(0); + room.setRocketEnergy(0L); + } + }); + } + + private void fillGameIcon(List roomList) { + List roomIds = roomList.stream().map(RoomVoiceProfileCO::getId).toList(); + Map coverMap = gameLudoService.listGameCoverByRoomIds(roomIds); + roomList.forEach(room -> room.setRoomGameIcon(coverMap.get(room.getId()))); + } + +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomServiceImpl.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomServiceImpl.java index 46f2c818..8a4f518b 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomServiceImpl.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomServiceImpl.java @@ -9,6 +9,7 @@ import com.red.circle.other.app.command.room.RoomEnterCmdExe; import com.red.circle.other.app.command.room.query.RoomLatestCreateQryExe; import com.red.circle.other.app.command.room.query.RoomOnlineUserFlowQryExe; import com.red.circle.other.app.command.room.query.RoomVoiceDiscoverQryExe; +import com.red.circle.other.app.command.room.query.RoomVoiceExploreQryExe; import com.red.circle.other.app.command.room.query.RoomVoiceProfileByRoomAccountQryExe; import com.red.circle.other.app.command.room.query.SearchRegionRoomQryExe; import com.red.circle.other.app.command.room.query.UserCurrentLocationRoomQryExe; @@ -17,6 +18,7 @@ import com.red.circle.other.app.dto.clientobject.room.RoomOnlineUserCO; import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO; import com.red.circle.other.app.dto.cmd.room.RegionSearchRoomQryCmd; import com.red.circle.other.app.dto.cmd.room.RoomEntryCmd; +import com.red.circle.other.app.dto.cmd.room.RoomExploreQryCmd; import com.red.circle.other.app.dto.cmd.room.RoomOnlineUserFlowQryCmd; import com.red.circle.other.app.dto.cmd.room.SearchRoomAccountCmd; import com.red.circle.other.inner.model.dto.live.RoomProfileDTO; @@ -39,6 +41,7 @@ public class LiveVoiceRoomServiceImpl implements LiveVoiceRoomService { private final SearchRegionRoomQryExe searchRegionRoomQryExe; private final RoomLatestCreateQryExe roomLatestCreateQryExe; private final RoomVoiceDiscoverQryExe roomVoiceDiscoverQryExe; + private final RoomVoiceExploreQryExe roomVoiceExploreQryExe; private final RoomOnlineUserFlowQryExe roomOnlineUserFlowQryExe; private final LiveVoiceRoomCreateCmdExe liveVoiceRoomCreateCmdExe; private final UserCurrentLocationRoomQryExe userCurrentLocationRoomQryExe; @@ -87,6 +90,11 @@ public class LiveVoiceRoomServiceImpl implements LiveVoiceRoomService { return roomVoiceDiscoverQryExe.execute(cmd); } + @Override + public List explore(RoomExploreQryCmd cmd) { + return roomVoiceExploreQryExe.execute(cmd); + } + @Override public String createPublicRoomByRegion(AppExtCommand cmd) { return liveVoicePublicRoomCreateCmdExe.execute(cmd); diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/room/RoomExploreQryCmd.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/room/RoomExploreQryCmd.java new file mode 100644 index 00000000..86a4a6cc --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/room/RoomExploreQryCmd.java @@ -0,0 +1,21 @@ +package com.red.circle.other.app.dto.cmd.room; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * explore 房间列表查询. + * + * @author tf + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class RoomExploreQryCmd extends AppExtCommand { + + /** + * 国家code,有值时精确匹配. + */ + private String countryCode; + +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomService.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomService.java index 8ed62dff..4582a544 100644 --- a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomService.java +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/room/LiveVoiceRoomService.java @@ -7,6 +7,7 @@ import com.red.circle.other.app.dto.clientobject.room.RoomOnlineUserCO; import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO; import com.red.circle.other.app.dto.cmd.room.RegionSearchRoomQryCmd; import com.red.circle.other.app.dto.cmd.room.RoomEntryCmd; +import com.red.circle.other.app.dto.cmd.room.RoomExploreQryCmd; import com.red.circle.other.app.dto.cmd.room.RoomOnlineUserFlowQryCmd; import com.red.circle.other.app.dto.cmd.room.SearchRoomAccountCmd; import com.red.circle.other.app.dto.cmd.user.user.AccountQryCmd; @@ -36,5 +37,7 @@ public interface LiveVoiceRoomService { List discovery(AppExtCommand cmd); + List explore(RoomExploreQryCmd cmd); + String createPublicRoomByRegion(AppExtCommand cmd); } diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/ActiveVoiceRoomService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/ActiveVoiceRoomService.java index 02a2878c..9bb9500f 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/ActiveVoiceRoomService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/ActiveVoiceRoomService.java @@ -90,5 +90,10 @@ public interface ActiveVoiceRoomService { List listGetActiveRooms(List roomIds,String sysOrigin,Integer onlineQuantity); + /** + * explore 页查询. + * 阿语区(region=AR)用户只看阿语区房间,其他用户不隔离,同区域排前. + */ + List listExplore(String sysOrigin, String userRegion, String countryCode, Integer limit); } diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/ActiveVoiceRoomServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/ActiveVoiceRoomServiceImpl.java index 2b384a7a..9978d76c 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/ActiveVoiceRoomServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/live/impl/ActiveVoiceRoomServiceImpl.java @@ -8,7 +8,7 @@ import com.red.circle.other.infra.database.mongo.dto.query.live.FamilyOnlineRoom import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom; import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService; import com.red.circle.other.inner.model.cmd.live.AppActiveVoiceRoomQryCmd; -import com.red.circle.tool.core.collection.CollectionUtils; +import org.springframework.data.mongodb.core.aggregation.Aggregation; import com.red.circle.tool.core.text.StringUtils; import java.util.*; @@ -19,6 +19,7 @@ import org.springframework.dao.DuplicateKeyException; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Order; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.ConditionalOperators; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; @@ -233,6 +234,44 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService { } return criteria; } + @Override + public List listExplore(String sysOrigin, String userRegion, String countryCode, Integer limit) { + Criteria criteria = Criteria.where("sysOrigin").is(sysOrigin); + + // countryCode 有值:精确匹配,不做区域隔离 + if (StringUtils.isNotBlank(countryCode)) { + criteria.and("countryCode").is(countryCode); + Query query = Query.query(criteria) + .with(Sort.by(Sort.Order.desc("fixedWeights"), Sort.Order.desc("weights"), Sort.Order.desc("onlineQuantity"))); + return mongoTemplate.find(query.limit(limit), ActiveVoiceRoom.class); + } + + // 阿语区用户只看阿语区房间 + boolean isArRegion = "AR".equals(userRegion); + if (isArRegion) { + criteria.and("region").is("AR"); + } + + // 聚合:同区域排前,再按权重/在线数排序 + Aggregation aggregation = Aggregation.newAggregation( + Aggregation.match(criteria), + Aggregation.project("id", "timeId", "sysOrigin", "userId", "roomAccount", "familyProfile", + "runGame", "superVipLevel", "hot", "fixedWeights", "region", "countryCode", + "countryName", "onlineQuantity", "weights", "expiredTime", "createTime", "updateTime") + .and(ConditionalOperators.when(Criteria.where("region").is(userRegion)).then(1).otherwise(0)).as("regionMatchScore") + .and(ConditionalOperators.when(Criteria.where("region").is(userRegion)).then("$fixedWeights").otherwise(0)).as("fixedWeightsScore"), + Aggregation.sort(Sort.by( + Sort.Order.desc("regionMatchScore"), + Sort.Order.desc("fixedWeightsScore"), + Sort.Order.desc("weights"), + Sort.Order.desc("onlineQuantity") + )), + Aggregation.limit(limit) + ); + + return mongoTemplate.aggregate(aggregation, ActiveVoiceRoom.class, ActiveVoiceRoom.class).getMappedResults(); + } + @Override public List listGetActiveRooms(List roomIds, String sysOrigin,Integer onlineQuantity) { Criteria criteria = Criteria.where("sysOrigin").is(sysOrigin)