From aac2321d1cf5536f7ea03f30d55a4aba30fbf710 Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期三, 02 七月 2025 10:39:39 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java |  165 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 154 insertions(+), 11 deletions(-)

diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java
index 3874f5d..ca4e7af 100644
--- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java
@@ -1,19 +1,39 @@
 package cn.lili.modules.lmk.service.impl;
 
+import cn.lili.cache.Cache;
+import cn.lili.cache.CachePrefix;
+import cn.lili.common.properties.RocketmqCustomProperties;
 import cn.lili.common.security.AuthUser;
 import cn.lili.common.security.context.UserContext;
 import cn.lili.common.sensitive.SensitiveWordsFilter;
+import cn.lili.modules.lmk.constant.RedisKeyExpireConstant;
+import cn.lili.modules.lmk.domain.entity.ThumbsUpRecord;
+import cn.lili.modules.lmk.domain.form.ThumbsUpRecordForm;
+import cn.lili.modules.lmk.domain.vo.CollectTypeNumVO;
 import cn.lili.modules.lmk.enums.general.VideoCommentStatusEnum;
+import cn.lili.modules.lmk.event.event.VideoCommentNumCacheEvent;
+import cn.lili.modules.lmk.service.ThumbsUpRecordService;
+import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
+import cn.lili.rocketmq.tags.CommentTagsEnum;
+import cn.lili.rocketmq.tags.OrderTagsEnum;
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import cn.lili.modules.lmk.domain.entity.VideoComment;
 import cn.lili.modules.lmk.mapper.VideoCommentMapper;
 import cn.lili.modules.lmk.service.VideoCommentService;
 import cn.lili.base.Result;
+import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
+import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import cn.lili.modules.lmk.domain.form.VideoCommentForm;
 import cn.lili.modules.lmk.domain.vo.VideoCommentVO;
 import cn.lili.modules.lmk.domain.query.VideoCommentQuery;
+import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import lombok.RequiredArgsConstructor;
 import cn.lili.utils.PageUtil;
@@ -23,6 +43,7 @@
 
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -36,6 +57,11 @@
 public class VideoCommentServiceImpl extends ServiceImpl<VideoCommentMapper, VideoComment> implements VideoCommentService {
 
     private final VideoCommentMapper videoCommentMapper;
+    private final Cache cache;
+    private final ThumbsUpRecordService thumbsUpRecordService;
+    private final RocketMQTemplate rocketMQTemplate;
+    private final RocketmqCustomProperties rocketmqCustomProperties;
+    private final ApplicationEventPublisher eventPublisher;
 
     /**
      * 娣诲姞
@@ -43,7 +69,6 @@
      * @return
      */
     @Override
-    @Transactional(rollbackFor = Exception.class)
     public Result comment(VideoCommentForm form) {
         // 鐩戞祴鍐呭鏄惁鍖呭惈鏁忔劅璇�
         if (SensitiveWordsFilter.includeSentenceWord(form.getCommentContent())) {
@@ -58,19 +83,17 @@
             }
         }
         VideoComment entity = VideoCommentForm.getEntityByForm(form, null);
-        entity.setStatus(VideoCommentStatusEnum.AUDITING.getValue());
-
+        entity.setStatus(VideoCommentStatusEnum.NORMAL.getValue());
+        entity.setUserId(UserContext.getCurrentUserId());
         AuthUser currentUser = UserContext.getCurrentUser();
         entity.setUserNickname(currentUser.getNickName());
         entity.setUserAvatar(currentUser.getFace());
-
         baseMapper.insert(entity);
-        if (StringUtils.isBlank(entity.getReplyId())) {
-            // 涓嶆槸鍥炲璇勮锛岄偅涔堝氨鏄富璇勮锛屼富璇勮鐨刴asterId璁剧疆涓鸿嚜宸辩殑id
-            entity.setMasterCommentId(entity.getId());
-        }
-        baseMapper.updateById(entity);
-        return Result.ok("娣诲姞鎴愬姛");
+        // 鍒濆鍖杛edis涓瘎璁虹殑鐐硅禐鏁伴噺
+        cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(entity.getId()), 0, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY);
+        // 澶勭悊瑙嗛璇勮鏁�
+        eventPublisher.publishEvent(new VideoCommentNumCacheEvent(this, entity.getVideoId()));
+        return Result.ok("娣诲姞鎴愬姛").data(this.detail(entity.getId()).get("data"));
     }
 
     /**
@@ -134,14 +157,134 @@
 
     @Override
     public Result wxPage(VideoCommentQuery query) {
+        query.setUserId(UserContext.getCurrentUserId());
         IPage<VideoCommentVO> page = PageUtil.getPage(query, VideoCommentVO.class);
         if (StringUtils.isNotBlank(query.getMasterCommentId())) {
             // 鍔犺浇瀛愯瘎璁虹殑鎯呭喌
             baseMapper.replyCommentPage(page, query);
+            for (VideoCommentVO comment : page.getRecords()) {
+                comment.setThumbsUpNum(this.getCommentThumbsUpNum(comment.getId(), comment.getThumbsUpNum()));
+            }
+            return Result.ok().data(page.getRecords());
         } else {
             // 鍔犺浇涓昏瘎璁虹殑鎯呭喌銆備富璇勮id = masterCommentId
             baseMapper.masterCommentPage(page, query);
+            for (VideoCommentVO comment : page.getRecords()) {
+                comment.setThumbsUpNum(this.getCommentThumbsUpNum(comment.getId(), comment.getThumbsUpNum()));
+            }
         }
-        return Result.ok().data(page.getRecords());
+        return Result.ok().data(page.getRecords()).total(page.getTotal());
+    }
+
+
+    @Override
+    public List<CollectTypeNumVO> countNumGroupByVideo() {
+        return baseMapper.countNumGroupByVideo();
+    }
+
+    @Override
+    public Result thumbsUp(ThumbsUpRecordForm form) {
+        ThumbsUpRecord record = ThumbsUpRecordForm.getEntityByForm(form, null);
+        record.setUserId(UserContext.getCurrentUserId());
+
+        // 璧癿q寮傛澶勭悊
+        String destination = rocketmqCustomProperties.getCommentTopic() + ":" + CommentTagsEnum.THUMBS_UP.name();
+        rocketMQTemplate.asyncSend(destination, JSON.toJSONString(record), RocketmqSendCallbackBuilder.commonCallback());
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void mqThumbsUp(ThumbsUpRecord record) {
+        boolean exists = new LambdaQueryChainWrapper<>(thumbsUpRecordService.getBaseMapper())
+                .eq(ThumbsUpRecord::getRefId, record.getRefId())
+                .eq(ThumbsUpRecord::getUserId, record.getUserId())
+                .exists();
+        if (exists) {
+            return;
+        }
+        thumbsUpRecordService.save(record);
+        VideoComment comment = this.getById(record.getRefId());
+        if (cache.exist(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId()))) {
+            cache.incr(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId()));
+        } else {
+            if (Objects.nonNull(comment)) {
+                cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(comment.getId()), comment.getThumbsUpNum() + 1, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY);
+            }
+        }
+        // 鏍囪瘑璇ヨ瘎璁洪渶瑕侀�氳繃瀹氭椂浠诲姟缁熻鐐硅禐鏁�
+        if (Objects.nonNull(comment) && ! comment.getThumbsUpJob()) {
+            new LambdaUpdateChainWrapper<>(baseMapper)
+                    .eq(VideoComment::getId, comment.getId())
+                    .set(VideoComment::getThumbsUpJob, Boolean.TRUE)
+                    .update();
+        }
+    }
+
+    @Override
+    public Result cancelThumbsUp(ThumbsUpRecordForm form) {
+        ThumbsUpRecord record = ThumbsUpRecordForm.getEntityByForm(form, null);
+        record.setUserId(UserContext.getCurrentUserId());
+        // 璧癿q寮傛澶勭悊
+        String destination = rocketmqCustomProperties.getCommentTopic() + ":" + CommentTagsEnum.CANCEL_THUMBS_UP.name();
+        rocketMQTemplate.asyncSend(destination, JSON.toJSONString(record), RocketmqSendCallbackBuilder.commonCallback());
+        return Result.ok();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void mqCancelThumbsUp(ThumbsUpRecord record) {
+        new LambdaUpdateChainWrapper<>(thumbsUpRecordService.getBaseMapper())
+                .eq(ThumbsUpRecord::getRefId, record.getRefId())
+                .eq(ThumbsUpRecord::getThumbsUpType, record.getThumbsUpType())
+                .eq(ThumbsUpRecord::getUserId, record.getUserId())
+                .remove();
+        // redis鏁伴噺鍑忎竴
+        VideoComment comment = this.getById(record.getRefId());
+        if (cache.exist(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId()))) {
+            cache.decr(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(record.getRefId()));
+        } else {
+            if (Objects.nonNull(comment)) {
+                cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(comment.getId()), comment.getThumbsUpNum() - 1, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY);
+            }
+        }
+        // 鏍囪瘑璇ヨ瘎璁洪渶瑕侀�氳繃瀹氭椂浠诲姟缁熻鐐硅禐鏁�
+        if (Objects.nonNull(comment) && ! comment.getThumbsUpJob()) {
+            new LambdaUpdateChainWrapper<>(baseMapper)
+                    .eq(VideoComment::getId, comment.getId())
+                    .set(VideoComment::getThumbsUpJob, Boolean.TRUE)
+                    .update();
+        }
+    }
+
+    /**
+     * 浠巖edis涓幏鍙栬瘎璁虹偣璧炴暟閲忥紝濡傛灉redis涓病鏈夊垯灏唌ysql涓殑鏁伴噺鍐欏叆鍒皉edis
+     *
+     * @param commentId
+     * @param mysqlNum
+     * @return
+     */
+    private Integer getCommentThumbsUpNum(String commentId, Integer mysqlNum) {
+        Object redisNum = cache.get(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(commentId));
+        if (Objects.isNull(redisNum)) {
+            // redis涓病鏈夊氨鎶婃暟鎹簱鐨勫啓鍒皉edis涓�
+            cache.put(CachePrefix.VIDEO_COMMENT_LIKE_NUM.getPrefixWithId(commentId), mysqlNum, RedisKeyExpireConstant.COMMENT_LIKE_NUM_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY);
+            return mysqlNum;
+        }
+        return (Integer) redisNum;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateCommentThumbsUpNumBatch(List<CollectTypeNumVO> numList) {
+        // 鎸�500鏉℃暟鎹繘琛屾媶鍒�
+        List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 500);
+        for (List<CollectTypeNumVO> chunk : chunks) {
+            baseMapper.updateCommentThumbsUpNumBatch(chunk);
+            new LambdaUpdateChainWrapper<>(baseMapper)
+                    .in(VideoComment::getId, chunk.stream().map(CollectTypeNumVO::getId).collect(Collectors.toList()))
+                    .set(VideoComment::getThumbsUpJob, Boolean.FALSE)
+                    .update();
+        }
     }
 }

--
Gitblit v1.8.0