新增房间 explore接口

(cherry picked from commit 25ddd251c1d3754b4f578aa70a5b624f9f6be65f)
This commit is contained in:
tianfeng 2026-04-23 12:04:26 +08:00
parent cd0029eab9
commit e62e8b6f17
7 changed files with 172 additions and 1 deletions

View File

@ -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<RoomVoiceProfileCO> explore(RoomExploreQryCmd cmd) {
return liveVoiceRoomService.explore(cmd);
}
}

View File

@ -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<RoomVoiceProfileCO> execute(RoomExploreQryCmd cmd) {
String userRegion = StringUtils.isNotBlank(cmd.getCountryCode())
? null
: userRegionGateway.getRegionCode(cmd.requiredReqUserId());
List<ActiveVoiceRoom> rooms = activeVoiceRoomService.listExplore(
cmd.requireReqSysOrigin(), userRegion, cmd.getCountryCode(), EXPLORE_LIMIT);
List<RoomVoiceProfileCO> roomList = roomVoiceProfileCommon.toListRoomVoiceProfileCO(rooms);
if (CollectionUtils.isEmpty(roomList)) {
return CollectionUtils.newArrayList();
}
fillRocketStatus(roomList);
fillGameIcon(roomList);
return roomList;
}
private void fillRocketStatus(List<RoomVoiceProfileCO> roomList) {
List<Long> roomIds = roomList.stream().map(RoomVoiceProfileCO::getId).toList();
Map<Long, RocketStatus> 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<RoomVoiceProfileCO> roomList) {
List<Long> roomIds = roomList.stream().map(RoomVoiceProfileCO::getId).toList();
Map<Long, String> coverMap = gameLudoService.listGameCoverByRoomIds(roomIds);
roomList.forEach(room -> room.setRoomGameIcon(coverMap.get(room.getId())));
}
}

View File

@ -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<RoomVoiceProfileCO> explore(RoomExploreQryCmd cmd) {
return roomVoiceExploreQryExe.execute(cmd);
}
@Override
public String createPublicRoomByRegion(AppExtCommand cmd) {
return liveVoicePublicRoomCreateCmdExe.execute(cmd);

View File

@ -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;
}

View File

@ -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<RoomVoiceProfileCO> discovery(AppExtCommand cmd);
List<RoomVoiceProfileCO> explore(RoomExploreQryCmd cmd);
String createPublicRoomByRegion(AppExtCommand cmd);
}

View File

@ -90,5 +90,10 @@ public interface ActiveVoiceRoomService {
List<ActiveVoiceRoom> listGetActiveRooms(List<Long> roomIds,String sysOrigin,Integer onlineQuantity);
/**
* explore 页查询.
* 阿语区(region=AR)用户只看阿语区房间其他用户不隔离同区域排前.
*/
List<ActiveVoiceRoom> listExplore(String sysOrigin, String userRegion, String countryCode, Integer limit);
}

View File

@ -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<ActiveVoiceRoom> 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<ActiveVoiceRoom> listGetActiveRooms(List<Long> roomIds, String sysOrigin,Integer onlineQuantity) {
Criteria criteria = Criteria.where("sysOrigin").is(sysOrigin)