新增子评论列表接口

This commit is contained in:
tianfeng 2026-01-29 16:21:30 +08:00
parent 435bf5e728
commit 603b952548
10 changed files with 278 additions and 25 deletions

1
.gitignore vendored
View File

@ -93,3 +93,4 @@ target/
.DS_Store
devops-monitor-id_rsa.key
/claude/

View File

@ -13,14 +13,7 @@ import com.red.circle.other.app.dto.clientobject.dynamic.DynamicListCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicMessageListCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicSendRestrictCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicTagCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicByTagLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicContentAddCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicLikeCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicMyLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicReportCmd;
import com.red.circle.other.app.dto.cmd.dynamic.*;
import com.red.circle.other.app.service.dynamic.DynamicService;
import java.util.List;
import lombok.RequiredArgsConstructor;
@ -84,6 +77,20 @@ public class DynamicRestController extends BaseController {
return dynamicService.listDynamicComment(cmd);
}
/**
* 动态子评论列表.
*
* @eo.name 动态子评论列表.
* @eo.url /list/comment/children
* @eo.method get
* @eo.request-type formdata
*/
@GetMapping("/list/comment/children")
public PageResult<DynamicCommentListCO> listDynamicChildComment(
@Validated DynamicChildCommentLimitCmd cmd) {
return dynamicService.listDynamicChildComment(cmd);
}
/**
* 动态内容详情.
*

View File

@ -0,0 +1,112 @@
package com.red.circle.other.app.command.dynamic.query;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicCommentListCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicChildCommentLimitCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.database.cache.service.other.DynamicCacheService;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicComment;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicCommentLikeService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicCommentService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.NumUtils;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 动态子评论列表查询.
*
* @author pengshigang
* @since 2025-01-29
*/
@Component
@RequiredArgsConstructor
public class DynamicChildCommentQryExe {
private final UserProfileGateway userProfileGateway;
private final DynamicCacheService dynamicCacheService;
private final DynamicCommentService dynamicCommentService;
private final DynamicCommentLikeService dynamicCommentLikeService;
public PageResult<DynamicCommentListCO> execute(DynamicChildCommentLimitCmd cmd) {
PageResult<DynamicComment> comments = pageData(cmd);
if (CollectionUtils.isEmpty(comments.getRecords())) {
return PageResult.newPageResult(0);
}
Map<Long, UserProfile> userMap = userProfileGateway.mapByUserIds(getUserIds(comments));
Map<Long, Boolean> commentLikeMap = getCommentLikeMap(cmd, comments);
return comments.convert(comment -> {
DynamicCommentListCO listCO = new DynamicCommentListCO();
UserProfile createUser = userMap.get(comment.getCreateUser());
if (Objects.isNull(createUser)) {
return null;
}
listCO.setUserAvatar(createUser.getUserAvatar());
listCO.setUserNickname(createUser.getUserNickname());
listCO.setUserSex(createUser.getUserSex());
listCO.setUserId(createUser.getId());
listCO.setRootCommentId(comment.getRootCommentId());
UserProfile toUser = userMap.get(comment.getToUserId());
if (Objects.nonNull(toUser)) {
listCO.setToUserId(toUser.getId());
listCO.setToUserNickname(toUser.getUserNickname());
}
listCO.setLike(getLike(commentLikeMap, comment));
listCO.setLikeStrQuantity(getLikeStrQuantity(comment));
listCO.setId(comment.getId());
listCO.setDynamicId(comment.getDynamicContentId());
listCO.setContent(comment.getContent());
listCO.setCreateTime(comment.getCreateTime());
return listCO;
});
}
private Boolean getLike(Map<Long, Boolean> commentLikeMap, DynamicComment comment) {
return Optional.ofNullable(commentLikeMap.get(comment.getId())).orElse(Boolean.FALSE);
}
private Map<Long, Boolean> getCommentLikeMap(DynamicChildCommentLimitCmd cmd,
PageResult<DynamicComment> comments) {
return dynamicCommentLikeService
.mapByCommentIdsByUserId(comments.getRecords().stream().map(DynamicComment::getId).collect(
Collectors.toSet()), cmd.getReqUserId());
}
private String getLikeStrQuantity(DynamicComment comment) {
return NumUtils.formatLong(Optional.ofNullable(
dynamicCacheService.getCommentLikeQuantity(comment.getDynamicContentId(), comment.getId()))
.orElse(0L));
}
private Set<Long> getUserIds(PageResult<DynamicComment> comments) {
Set<Long> userIds = comments.getRecords().stream().map(DynamicComment::getCreateUser)
.filter(Objects::nonNull).collect(Collectors.toSet());
userIds.addAll(comments.getRecords().stream().map(DynamicComment::getToUserId)
.filter(Objects::nonNull)
.collect(Collectors.toSet()));
return userIds;
}
private PageResult<DynamicComment> pageData(DynamicChildCommentLimitCmd cmd) {
return dynamicCommentService.pageChildCommentsByTimeDesc(cmd.getPageReq(),
cmd.getRootCommentId());
}
}

View File

@ -57,6 +57,9 @@ public class DynamicCommentQryExe {
userProfileGateway.mapByUserIds(getUserIds(comments));
Map<Long, Boolean> commentLikeMap = getCommentLikeMap(cmd, comments);
// 批量查询所有根评论的子评论数量
Map<Long, Integer> childCommentCountMap = getChildCommentCountMap(comments);
return comments.convert(comment -> {
@ -89,6 +92,11 @@ public class DynamicCommentQryExe {
listCO.setContent(comment.getContent());
listCO.setCreateTime(comment.getCreateTime());
// 设置子评论数量仅根评论有值
if (Objects.isNull(comment.getRootCommentId())) {
listCO.setChildCommentCount(childCommentCountMap.getOrDefault(comment.getId(), 0));
}
return listCO;
});
@ -124,7 +132,23 @@ public class DynamicCommentQryExe {
}
private PageResult<DynamicComment> pageData(DynamicCommentLimitCmd cmd) {
return dynamicCommentService.pageByTimeDesc(cmd.getPageReq(), cmd.getDynamicId());
return dynamicCommentService.pageRootCommentsByTimeDesc(cmd.getPageReq(), cmd.getDynamicId());
}
/**
* 批量查询根评论的子评论数量
*/
private Map<Long, Integer> getChildCommentCountMap(PageResult<DynamicComment> comments) {
Set<Long> rootCommentIds = comments.getRecords().stream()
.filter(comment -> Objects.isNull(comment.getRootCommentId()))
.map(DynamicComment::getId)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(rootCommentIds)) {
return java.util.Collections.emptyMap();
}
return dynamicCommentService.mapChildCommentCount(rootCommentIds);
}
}

View File

@ -16,6 +16,7 @@ import com.red.circle.other.app.command.dynamic.delete.DynamicCommentDelCmdExe;
import com.red.circle.other.app.command.dynamic.delete.DynamicContentDelCmdExe;
import com.red.circle.other.app.command.dynamic.delete.DynamicMessageAllDelCmdExe;
import com.red.circle.other.app.command.dynamic.delete.DynamicMessageDelCmdExe;
import com.red.circle.other.app.command.dynamic.query.DynamicChildCommentQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicCommentQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicDetailsQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicFollowQryExe;
@ -30,14 +31,8 @@ import com.red.circle.other.app.dto.clientobject.dynamic.DynamicListCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicMessageListCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicSendRestrictCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicTagCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicByTagLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicContentAddCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicLikeCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicMyLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicReportCmd;
import com.red.circle.other.app.dto.cmd.dynamic.*;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -66,6 +61,7 @@ public class DynamicServiceImpl implements DynamicService {
private final DynamicPopularQryExe dynamicPopularQryExe;
private final DynamicDetailsQryExe dynamicDetailsQryExe;
private final DynamicCommentQryExe dynamicCommentQryExe;
private final DynamicChildCommentQryExe dynamicChildCommentQryExe;
private final DynamicCommentDelCmdExe dynamicCommentDelExe;
private final DynamicCommentLikeCmdExe dynamicCommentLikeExe;
private final DynamicContentDelCmdExe dynamicContentDelExe;
@ -91,6 +87,11 @@ public class DynamicServiceImpl implements DynamicService {
return dynamicCommentQryExe.execute(cmd);
}
@Override
public PageResult<DynamicCommentListCO> listDynamicChildComment(DynamicChildCommentLimitCmd cmd) {
return dynamicChildCommentQryExe.execute(cmd);
}
@Override
public DynamicListCO getDynamicDetails(IdLongCmd cmd) {
return dynamicDetailsQryExe.execute(cmd);

View File

@ -94,4 +94,9 @@ public class DynamicCommentListCO extends ClientObject {
*/
private Long rootCommentId;
/**
* 子评论数量仅根评论有值
*/
private Integer childCommentCount;
}

View File

@ -0,0 +1,35 @@
package com.red.circle.other.app.dto.cmd.dynamic;
import com.red.circle.common.business.dto.PageReq;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 动态-子评论列表.
*
* @author pengshigang
* @since 2025-01-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DynamicChildCommentLimitCmd extends AppExtCommand {
/**
* 页码.
*
* @eo.required
*/
@NotNull
private PageReq pageReq;
/**
* 根评论id.
*
* @eo.required
*/
@NotNull
private Long rootCommentId;
}

View File

@ -10,14 +10,8 @@ import com.red.circle.other.app.dto.clientobject.dynamic.DynamicListCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicMessageListCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicSendRestrictCO;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicTagCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicByTagLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicContentAddCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicLikeCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicMyLimitCmd;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicReportCmd;
import com.red.circle.other.app.dto.cmd.dynamic.*;
import java.util.List;
/**
@ -46,6 +40,11 @@ public interface DynamicService {
*/
PageResult<DynamicCommentListCO> listDynamicComment(DynamicCommentLimitCmd cmd);
/**
* 动态子评论列表.
*/
PageResult<DynamicCommentListCO> listDynamicChildComment(DynamicChildCommentLimitCmd cmd);
/**
* 动态内容详情.
*/

View File

@ -28,6 +28,22 @@ public interface DynamicCommentService extends BaseService<DynamicComment> {
*/
PageResult<DynamicComment> pageByTimeDesc(PageQuery pageQuery, Long contentId);
/**
* 分页查询根评论按时间倒序
*
* @param pageQuery 分页参数
* @param contentId 动态内容ID
*/
PageResult<DynamicComment> pageRootCommentsByTimeDesc(PageQuery pageQuery, Long contentId);
/**
* 分页查询子评论按时间倒序
*
* @param pageQuery 分页参数
* @param rootCommentId 根评论ID
*/
PageResult<DynamicComment> pageChildCommentsByTimeDesc(PageQuery pageQuery, Long rootCommentId);
/**
* 获得子评论数
*
@ -83,4 +99,12 @@ public interface DynamicCommentService extends BaseService<DynamicComment> {
*/
Map<Long, Integer> mapCommentQuantity(Collection<Long> contentIds);
/**
* 批量获取根评论的子评论数量
*
* @param rootCommentIds 根评论ID集合
* @return Map<根评论ID, 子评论数量>
*/
Map<Long, Integer> mapChildCommentCount(Collection<Long> rootCommentIds);
}

View File

@ -51,6 +51,23 @@ public class DynamicCommentServiceImpl extends
.page(pageQuery);
}
@Override
public PageResult<DynamicComment> pageRootCommentsByTimeDesc(PageQuery pageQuery, Long contentId) {
return query()
.eq(DynamicComment::getDynamicContentId, contentId)
.isNull(DynamicComment::getRootCommentId)
.orderByDesc(DynamicComment::getCreateTime)
.page(pageQuery);
}
@Override
public PageResult<DynamicComment> pageChildCommentsByTimeDesc(PageQuery pageQuery, Long rootCommentId) {
return query()
.eq(DynamicComment::getRootCommentId, rootCommentId)
.orderByDesc(DynamicComment::getCreateTime)
.page(pageQuery);
}
@Override
public Integer getNumberByRootIdByNotUserId(Long rootCommentId, Long notUserId) {
@ -150,4 +167,32 @@ public class DynamicCommentServiceImpl extends
return result;
}
@Override
public Map<Long, Integer> mapChildCommentCount(Collection<Long> rootCommentIds) {
if (CollectionUtils.isEmpty(rootCommentIds)) {
return Maps.newHashMap();
}
// 查询所有子评论
List<DynamicComment> childComments = query()
.select(DynamicComment::getRootCommentId)
.in(DynamicComment::getRootCommentId, rootCommentIds)
.list();
Map<Long, Integer> result = Maps.newHashMap();
// 初始化所有根评论ID默认0
for (Long rootCommentId : rootCommentIds) {
result.put(rootCommentId, 0);
}
// 统计每个根评论的子评论数量
for (DynamicComment comment : childComments) {
Long rootCommentId = comment.getRootCommentId();
result.put(rootCommentId, result.getOrDefault(rootCommentId, 0) + 1);
}
return result;
}
}