From 9a96b016cc24940bbac956783d274f25daea83ff Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Wed, 4 Feb 2026 17:30:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=84=E8=AE=BA=E5=88=97=E8=A1=A8=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=A0=B9=E6=8D=AE=E7=83=AD=E5=BA=A6=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dynamic/query/DynamicCommentQryExe.java | 2 +- .../dynamic/query/DynamicMyQryExe.java | 6 +- .../scheduler/DynamicCommentHotScoreTask.java | 125 ++++++++++++++++++ .../rds/entity/dynamic/DynamicComment.java | 6 + .../dynamic/DynamicCommentService.java | 8 ++ .../dynamic/DynamicContentService.java | 2 +- .../impl/DynamicCommentServiceImpl.java | 10 ++ .../impl/DynamicContentServiceImpl.java | 3 +- 8 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/scheduler/DynamicCommentHotScoreTask.java diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicCommentQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicCommentQryExe.java index 473b7ecb..b59458c2 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicCommentQryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicCommentQryExe.java @@ -132,7 +132,7 @@ public class DynamicCommentQryExe { } private PageResult pageData(DynamicCommentLimitCmd cmd) { - return dynamicCommentService.pageRootCommentsByTimeDesc(cmd.getPageReq(), cmd.getDynamicId()); + return dynamicCommentService.pageRootCommentsByHotScore(cmd.getPageReq(), cmd.getDynamicId()); } /** diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicMyQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicMyQryExe.java index b82936fa..b5d9f706 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicMyQryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/dynamic/query/DynamicMyQryExe.java @@ -12,6 +12,7 @@ import com.red.circle.other.domain.gateway.user.UserProfileGateway; import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicContent; import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicPicture; import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicTag; +import com.red.circle.other.infra.database.rds.service.approval.ApprovalDynamicContentService; import com.red.circle.other.infra.database.rds.service.dynamic.DynamicCommentService; import com.red.circle.other.infra.database.rds.service.dynamic.DynamicContentService; import com.red.circle.other.infra.database.rds.service.dynamic.DynamicLikeService; @@ -49,10 +50,13 @@ public class DynamicMyQryExe { private final DynamicCommentService dynamicCommentService; private final UserSubscriptionService userSubscriptionService; private final UserProfileAppConvertor userProfileAppConvertor; + private final ApprovalDynamicContentService approvalDynamicContentService; public PageResult execute(DynamicMyLimitCmd cmd) { + List pendingDynamicIds = approvalDynamicContentService.listPendingDynamicIds(); + PageResult dynamics = dynamicContentService - .pageByTimeDesc(cmd.getUserId(), cmd.getPageReq()); + .pageByTimeDesc(cmd.getUserId(), cmd.getPageReq(), pendingDynamicIds); if (CollectionUtils.isEmpty(dynamics.getRecords())) { return PageResult.newPageResult(0); diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/scheduler/DynamicCommentHotScoreTask.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/scheduler/DynamicCommentHotScoreTask.java new file mode 100644 index 00000000..18b83921 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/scheduler/DynamicCommentHotScoreTask.java @@ -0,0 +1,125 @@ +package com.red.circle.other.app.scheduler; + +import com.red.circle.component.redis.annotation.TaskCacheLock; +import com.red.circle.component.redis.service.RedisService; +import com.red.circle.framework.mybatis.constant.PageConstant; +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.DynamicCommentService; +import com.red.circle.tool.core.collection.CollectionUtils; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * 评论热度分数更新定时任务. + * 每10分钟执行一次,更新最近7天的评论热度分数 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class DynamicCommentHotScoreTask { + + private final DynamicCommentService dynamicCommentService; + private final DynamicCacheService dynamicCacheService; + + /** + * 每10分钟执行一次 + */ + @Scheduled(cron = "0 */10 * * * ?") + @TaskCacheLock(key = "COMMENT_HOT_SCORE_UPDATE", expireSecond = 540) + public void updateHotScore() { + try { + log.info("评论热度分数更新任务 - 开始执行"); + long startTime = System.currentTimeMillis(); + + // 查询最近7天的根评论(分批处理) + long sevenDaysAgo = System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000L); + int totalUpdated = 0; + Long lastId = null; + boolean hasMore = true; + + while (hasMore) { + // 分批查询,每次1000条 + List comments = queryRecentComments(sevenDaysAgo, lastId, 1000); + + if (CollectionUtils.isEmpty(comments)) { + hasMore = false; + break; + } + + // 批量更新热度分数 + for (DynamicComment comment : comments) { + updateCommentHotScore(comment); + totalUpdated++; + } + + // 准备下一批 + lastId = comments.get(comments.size() - 1).getId(); + hasMore = comments.size() >= 1000; + } + + long costTime = System.currentTimeMillis() - startTime; + log.info("评论热度分数更新任务 - 执行完成,更新{}条评论,耗时{}ms", totalUpdated, costTime); + + } catch (Exception e) { + log.error("评论热度分数更新任务 - 执行失败", e); + } + } + + /** + * 查询最近的根评论 + */ + private List queryRecentComments(long since, Long lastId, int limit) { + return dynamicCommentService.query() + .isNull(DynamicComment::getRootCommentId) + .ge(DynamicComment::getCreateTime, new java.sql.Timestamp(since)) + .gt(lastId != null, DynamicComment::getId, lastId) + .orderByAsc(DynamicComment::getId) + .last(PageConstant.formatLimit(limit)) + .list(); + } + + /** + * 更新单条评论的热度分数 + */ + private void updateCommentHotScore(DynamicComment comment) { + try { + // 获取点赞数 + Long likeCount = Optional.ofNullable( + dynamicCacheService.getCommentLikeQuantity(comment.getDynamicContentId(), comment.getId()) + ).orElse(0L); + + // 计算热度分数 + double hotScore = calculateHotScore(comment, likeCount); + + // 更新到数据库 + dynamicCommentService.update() + .set(DynamicComment::getHotScore, hotScore) + .eq(DynamicComment::getId, comment.getId()) + .last(PageConstant.LIMIT_ONE) + .execute(); + + } catch (Exception e) { + log.error("更新评论热度分数失败,commentId={}", comment.getId(), e); + } + } + + /** + * 计算热度分数 + * 公式: 点赞数 / (时间差小时数 + 2)^1.5 + */ + private double calculateHotScore(DynamicComment comment, Long likeCount) { + long currentTime = System.currentTimeMillis(); + long ageMillis = currentTime - comment.getCreateTime().getTime(); + double ageHours = Math.max(ageMillis / (1000.0 * 60 * 60), 0.1); + + return likeCount / Math.pow(ageHours + 2, 1.5); + } + +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/dynamic/DynamicComment.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/dynamic/DynamicComment.java index 82a84dab..7e731324 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/dynamic/DynamicComment.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/dynamic/DynamicComment.java @@ -54,4 +54,10 @@ public class DynamicComment extends TimestampBaseEntity { @TableField("root_comment_id") private Long rootCommentId; + /** + * 热度分数 + */ + @TableField("hot_score") + private Double hotScore; + } diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicCommentService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicCommentService.java index 63de8ec1..7b2cfcdc 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicCommentService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicCommentService.java @@ -92,6 +92,14 @@ public interface DynamicCommentService extends BaseService { */ void deleteById(Long id); + /** + * 分页查询根评论(按热度排序) + * + * @param pageQuery 分页参数 + * @param contentId 动态内容ID + */ + PageResult pageRootCommentsByHotScore(PageQuery pageQuery, Long contentId); + /** * 根据动态ID获得动态评论数量 * diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicContentService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicContentService.java index 5eb74953..f9bfa64e 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicContentService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/DynamicContentService.java @@ -54,7 +54,7 @@ public interface DynamicContentService extends BaseService { * @param pageNumber 第几页 * @param userId 创建人 */ - PageResult pageByTimeDesc(Long userId, PageQuery pageQuery); + PageResult pageByTimeDesc(Long userId, PageQuery pageQuery, List pendingDynamicIds); /** * 获得分页数据 diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicCommentServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicCommentServiceImpl.java index f212cc84..1320cb18 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicCommentServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicCommentServiceImpl.java @@ -68,6 +68,16 @@ public class DynamicCommentServiceImpl extends .page(pageQuery); } + @Override + public PageResult pageRootCommentsByHotScore(PageQuery pageQuery, Long contentId) { + return query() + .eq(DynamicComment::getDynamicContentId, contentId) + .isNull(DynamicComment::getRootCommentId) + .orderByDesc(DynamicComment::getHotScore) + .orderByDesc(DynamicComment::getCreateTime) + .page(pageQuery); + } + @Override public Integer getNumberByRootIdByNotUserId(Long rootCommentId, Long notUserId) { diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicContentServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicContentServiceImpl.java index fae67598..82080438 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicContentServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/dynamic/impl/DynamicContentServiceImpl.java @@ -82,11 +82,12 @@ public class DynamicContentServiceImpl extends } @Override - public PageResult pageByTimeDesc(Long userId, PageQuery pageQuery) { + public PageResult pageByTimeDesc(Long userId, PageQuery pageQuery, List pendingDynamicIds) { return query() .eq(DynamicContent::getDel, Boolean.FALSE) .eq(DynamicContent::getCreateUser, userId) + .notIn(CollectionUtils.isNotEmpty(pendingDynamicIds), DynamicContent::getId, pendingDynamicIds) .orderByDesc(DynamicContent::getCreateTime) .page(pageQuery); }