buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java
@@ -2,6 +2,7 @@ import cn.lili.group.Update; import cn.lili.group.Add; import cn.lili.modules.lmk.domain.form.ThumbsUpRecordForm; import cn.lili.modules.lmk.domain.form.VideoFootPrintForm; import cn.lili.modules.lmk.domain.form.VideoHomePageInfoForm; import cn.lili.modules.lmk.domain.form.WxVideoForm; @@ -129,4 +130,10 @@ public Result wxDetail(@PathVariable("id") String id) { return videoService.wxDetail(id); } @PostMapping("/change/thumbs-up") @ApiOperation(value = "点赞/取消点赞视频", notes = "点赞/取消点赞视频") public Result changeThumbsUp(@RequestBody @Validated(Add.class) ThumbsUpRecordForm form) { return videoService.changeThumbsUp(form); } } consumer/src/main/java/cn/lili/listener/VideoMessageListener.java
@@ -53,6 +53,9 @@ case COLLECT: this.collect(msg); break; case THUMBS_UP: this.changeThumbsUp(msg); break; case ES_RECREATE: this.recreateVideoIndex(); break; @@ -120,4 +123,9 @@ esService.deleteDocument(EsSuffix.VIDEO_INDEX_NAME, id); } public void changeThumbsUp(String msg) { ThumbsUpRecord thumbsUpRecord = JSON.parseObject(msg, ThumbsUpRecord.class); videoService.mqChangeThumbsUp(thumbsUpRecord); } } framework/src/main/java/cn/lili/cache/CachePrefix.java
@@ -528,6 +528,11 @@ */ VIDEO_COLLECT_NUM, /** * 视频点赞数量 */ VIDEO_THUMBS_UP_NUM, /** * 扫码登录 framework/src/main/java/cn/lili/modules/lmk/constant/RedisKeyExpireConstant.java
@@ -25,6 +25,11 @@ */ public static final Long COLLECT_NUM_EXPIRE = 15l; /** * 视频点赞数过期时间 */ public static final Long VIDEO_THUMBS_UP_EXPIRE = 15l; /** * 过期时间单位 framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java
@@ -85,10 +85,18 @@ /** 评论数 */ private Integer commentNum; @TableField("thumbs_up_num") /** 点赞数 */ private Integer thumbsUpNum; @TableField("collect_num_job") /** 是否需要定时任务统计收藏数 */ private Boolean collectNumJob; @TableField("thumbs_up_num_job") /** 是否需要定时任务统计点赞数 */ private Boolean thumbsUpNumJob; @TableField("comment_num_job") /** 是否需要定时任务统计评论数 */ private Boolean commentNumJob; framework/src/main/java/cn/lili/modules/lmk/domain/vo/KitchenVideoVO.java
@@ -97,6 +97,10 @@ @ApiModelProperty("评论数") private Integer commentNum; /** 点赞数 */ @ApiModelProperty("点赞数") private Integer thumbsUpNum; /** 权重 */ @ApiModelProperty("权重") private double weight; framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleMyThumbsUpVO.java
New file @@ -0,0 +1,24 @@ package cn.lili.modules.lmk.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 我的点赞展示 * * @author xp * @since 2025-05-22 */ @Data @ApiModel(value = "我的点赞响应数据", description = "我的点赞响应数据") public class SimpleMyThumbsUpVO { private String id; /** 点赞对应的id,视频id、评论id,根据点赞类型定 */ @ApiModelProperty("点赞对应的id,视频id、评论id,根据点赞类型定") private String refId; } framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java
@@ -89,6 +89,10 @@ @ApiModelProperty("评论数") private Integer commentNum; /** 点赞数 */ @ApiModelProperty("点赞数") private Integer thumbsUpNum; /** 权重 */ @ApiModelProperty("权重") private double weight; framework/src/main/java/cn/lili/modules/lmk/domain/vo/WxVideoVO.java
@@ -81,6 +81,9 @@ @ApiModelProperty("当前用户是否收藏了该视频") private Boolean collected = Boolean.FALSE; @ApiModelProperty("当前用户是否点赞了该视频") private Boolean thumbsUp = Boolean.FALSE; /** 收藏数 */ @ApiModelProperty("收藏数") private Integer collectNum; @@ -89,6 +92,10 @@ @ApiModelProperty("评论数") private Integer commentNum; /** 点赞数 */ @ApiModelProperty("点赞数") private Integer thumbsUpNum; /** 视频拥有的操作 */ @ApiModelProperty("视频支持的操作") private List<VideoOption> options; framework/src/main/java/cn/lili/modules/lmk/enums/general/ThumbsUpTypeEnum.java
@@ -13,6 +13,7 @@ public enum ThumbsUpTypeEnum { VIDEO_COMMENT("video_comment", "视频评论"), VIDEO("video", "视频"), ; private final String value; framework/src/main/java/cn/lili/modules/lmk/mapper/ThumbsUpRecordMapper.java
@@ -2,6 +2,7 @@ import cn.lili.modules.lmk.domain.entity.ThumbsUpRecord; import cn.lili.modules.lmk.domain.vo.CollectTypeNumVO; import cn.lili.modules.lmk.domain.vo.SimpleMyThumbsUpVO; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import cn.lili.modules.lmk.domain.vo.ThumbsUpRecordVO; @@ -38,4 +39,20 @@ * @return */ List<CollectTypeNumVO> countNumGroupByComment(); /** * 统计视频点赞数量 * * @return */ List<CollectTypeNumVO> countNumGroupByVideo(); /** * 根据视频id查询我的点赞 * * @param videoIds * @param userId * @return */ List<SimpleMyThumbsUpVO> getThumbssByVideoIds(@Param("videoIds") List<String> videoIds, @Param("userId") String userId); } framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java
@@ -67,6 +67,13 @@ void updateCommentNumBatch(@Param("list") List<CollectTypeNumVO> numList); /** * 批量更新视频点赞数 * * @param numList */ void updateThumbsUpNumBatch(@Param("list") List<CollectTypeNumVO> numList); /** * 视频主页作者信息 * * @param authorId framework/src/main/java/cn/lili/modules/lmk/service/ThumbsUpRecordService.java
@@ -5,8 +5,10 @@ import cn.lili.modules.lmk.domain.form.ThumbsUpRecordForm; import cn.lili.modules.lmk.domain.query.ThumbsUpRecordQuery; import cn.lili.modules.lmk.domain.vo.CollectTypeNumVO; import cn.lili.modules.lmk.domain.vo.SimpleMyThumbsUpVO; import com.baomidou.mybatisplus.extension.service.IService; import java.util.Collection; import java.util.List; /** @@ -57,4 +59,19 @@ * @return */ List<CollectTypeNumVO> countNumGroupByComment(); /** * 统计视频的点赞数 * * @return */ List<CollectTypeNumVO> countNumGroupByVideo(); /** * 根据视频id查询我的点赞 * * @param videoIds * @return */ List<SimpleMyThumbsUpVO> getThumbssByVideoIds(List<String> videoIds); } framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java
@@ -2,6 +2,7 @@ import cn.lili.group.Add; import cn.lili.modules.lmk.domain.entity.MyCollect; import cn.lili.modules.lmk.domain.entity.ThumbsUpRecord; import cn.lili.modules.lmk.domain.entity.Video; import cn.lili.modules.lmk.domain.form.*; import cn.lili.modules.lmk.domain.query.*; @@ -258,4 +259,26 @@ * @return */ Result recreateEsIndex(); /** * 修改视频点赞状态 * * @param form * @return */ Result changeThumbsUp(ThumbsUpRecordForm form); /** * mq修改视频点赞状态 * * @param thumbsUpRecord */ void mqChangeThumbsUp(ThumbsUpRecord thumbsUpRecord); /** * 批量更新视频点赞数量 * * @param numList */ void updateThumbsUpNumBatch(List<CollectTypeNumVO> numList); } framework/src/main/java/cn/lili/modules/lmk/service/impl/ThumbsUpRecordServiceImpl.java
@@ -1,6 +1,8 @@ package cn.lili.modules.lmk.service.impl; import cn.lili.common.security.context.UserContext; import cn.lili.modules.lmk.domain.vo.CollectTypeNumVO; import cn.lili.modules.lmk.domain.vo.SimpleMyThumbsUpVO; import com.baomidou.mybatisplus.core.metadata.IPage; import cn.lili.modules.lmk.domain.entity.ThumbsUpRecord; import cn.lili.modules.lmk.mapper .ThumbsUpRecordMapper; @@ -94,4 +96,14 @@ public List<CollectTypeNumVO> countNumGroupByComment() { return baseMapper.countNumGroupByComment(); } @Override public List<CollectTypeNumVO> countNumGroupByVideo() { return baseMapper.countNumGroupByVideo(); } @Override public List<SimpleMyThumbsUpVO> getThumbssByVideoIds(List<String> videoIds) { return baseMapper.getThumbssByVideoIds(videoIds, UserContext.getCurrentUserId()); } } framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java
@@ -73,6 +73,7 @@ private final RocketmqCustomProperties rocketmqCustomProperties; private final RocketMQTemplate rocketMQTemplate; private final ThumbsUpRecordService thumbsUpRecordService; /** @@ -471,16 +472,21 @@ Map<String, List<SimpleVideoTagVO>> tagMap = videoTagRefService.getTagsByVideoIds(videoIds) .stream() .collect(Collectors.groupingBy(SimpleVideoTagVO::getVideoId)); Map<String, List<SimpleMyCollectVO>> collectMap =myCollectService.getCollectsByVideoIds(videoIds) Map<String, List<SimpleMyCollectVO>> collectMap = myCollectService.getCollectsByVideoIds(videoIds) .stream() .collect(Collectors.groupingBy(SimpleMyCollectVO::getRefId)); Map<String, List<SimpleMyThumbsUpVO>> thumbsUpMap = thumbsUpRecordService.getThumbssByVideoIds(videoIds) .stream() .collect(Collectors.groupingBy(SimpleMyThumbsUpVO::getRefId)); List<String> subscribes = mySubscribeService.getSubscribesByUserId(UserContext.getCurrentUserId()); // 3. 获取视频临时访问地址、设置视频标签、我是否收藏、作者是否关注 // 3. 获取视频临时访问地址、设置视频标签、我是否收藏、是否点赞、作者是否关注 page.getRecords().forEach(v -> { v.setTagList(tagMap.get(v.getId())); v.setCollected(CollectionUtils.isNotEmpty(collectMap.get(v.getId()))); v.setThumbsUp(CollectionUtils.isNotEmpty(thumbsUpMap.get(v.getId()))); v.setCommentNum(this.getCommentNum(v.getId(), v.getCommentNum())); v.setCollectNum(this.getCollectNum(v.getId(), v.getCollectNum())); v.setThumbsUpNum(this.getThumbsUpNum(v.getId(), v.getThumbsUpNum())); if (VideoContentTypeEnum.VIDEO.getValue().equals(v.getVideoContentType())) { v.setVideoUrl(cosUtil.getPreviewUrl(v.getVideoFileKey())); v.setCoverUrl(cosUtil.getPreviewUrl(v.getCoverFileKey())); @@ -532,6 +538,23 @@ return (Integer) redisNum; } /** * 从redis中获取点赞数量,如果redis中没有则将mysql中的数量写入到redis * * @param videoId * @param mysqlNum * @return */ private Integer getThumbsUpNum(String videoId, Integer mysqlNum) { Object redisNum = cache.get(CachePrefix.VIDEO_THUMBS_UP_NUM.getPrefixWithId(videoId)); if (Objects.isNull(redisNum)) { // redis中没有就把数据库的写到redis中 cache.put(CachePrefix.VIDEO_THUMBS_UP_NUM.getPrefixWithId(videoId), mysqlNum, RedisKeyExpireConstant.VIDEO_THUMBS_UP_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY); return mysqlNum; } return (Integer) redisNum; } @Override public Result healthRecommendVideo(WxHealthVideoQuery query) { IPage<WxVideoVO> page = PageUtil.getPage(query, WxVideoVO.class); @@ -572,8 +595,8 @@ @Override @Transactional(rollbackFor = Exception.class) public void updateCollectNumBatch(List<CollectTypeNumVO> numList) { // 按500条数据进行拆分 List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 500); // 按200条数据进行拆分 List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 200); for (List<CollectTypeNumVO> chunk : chunks) { baseMapper.updateCollectNumBatch(chunk); new LambdaUpdateChainWrapper<>(baseMapper) @@ -586,8 +609,8 @@ @Override @Transactional(rollbackFor = Exception.class) public void updateCommentNumBatch(List<CollectTypeNumVO> numList) { // 按500条数据进行拆分 List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 500); // 按200条数据进行拆分 List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 200); for (List<CollectTypeNumVO> chunk : chunks) { baseMapper.updateCommentNumBatch(chunk); new LambdaUpdateChainWrapper<>(baseMapper) @@ -903,4 +926,73 @@ rocketMQTemplate.asyncSend(destination, "1", RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("已成功发起构建请求,稍作等待后便会自动完成"); } @Override public Result changeThumbsUp(ThumbsUpRecordForm form) { // mq异步处理 ThumbsUpRecord thumbsUp = new ThumbsUpRecord(); thumbsUp.setRefId(form.getRefId()); thumbsUp.setThumbsUpType(ThumbsUpTypeEnum.VIDEO.getValue()); thumbsUp.setUserId(UserContext.getCurrentUserId()); String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.THUMBS_UP.name(); rocketMQTemplate.asyncSend(destination, JSON.toJSONString(thumbsUp), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok(); } @Override @Transactional(rollbackFor = Exception.class) public void mqChangeThumbsUp(ThumbsUpRecord thumbsUpRecord) { ThumbsUpRecord exists = new LambdaQueryChainWrapper<>(thumbsUpRecordService.getBaseMapper()) .eq(ThumbsUpRecord::getUserId, thumbsUpRecord.getUserId()) .eq(ThumbsUpRecord::getRefId, thumbsUpRecord.getRefId()) .eq(ThumbsUpRecord::getThumbsUpType, thumbsUpRecord.getThumbsUpType()) .one(); boolean add = false; if (Objects.nonNull(exists)) { // 取消点赞 thumbsUpRecordService.removeById(exists.getId()); } else { // 点赞 thumbsUpRecordService.save(thumbsUpRecord); add = true; } // 处理缓存 Video video = baseMapper.selectById(thumbsUpRecord.getRefId()); if (cache.exist(CachePrefix.VIDEO_THUMBS_UP_NUM.getPrefixWithId(thumbsUpRecord.getRefId()))) { if (add) { cache.incr(CachePrefix.VIDEO_THUMBS_UP_NUM.getPrefixWithId(thumbsUpRecord.getRefId())); } else { cache.decr(CachePrefix.VIDEO_THUMBS_UP_NUM.getPrefixWithId(thumbsUpRecord.getRefId())); } } else { if (Objects.nonNull(video)) { cache.put(CachePrefix.VIDEO_THUMBS_UP_NUM.getPrefixWithId(video.getId()), video.getThumbsUpNum() + (add ? 1 : -1), RedisKeyExpireConstant.VIDEO_THUMBS_UP_EXPIRE, RedisKeyExpireConstant.EXPIRE_DAY); } } // 标识该视频需要通过定时任务统计收藏数 if (Objects.nonNull(video) && ! video.getCollectNumJob()) { new LambdaUpdateChainWrapper<>(baseMapper) .eq(Video::getId, video.getId()) .set(Video::getThumbsUpNumJob, Boolean.TRUE) .update(); } } @Override @Transactional(rollbackFor = Exception.class) public void updateThumbsUpNumBatch(List<CollectTypeNumVO> numList) { // 按200条数据进行拆分 List<List<CollectTypeNumVO>> chunks = ListUtils.partition(numList, 200); for (List<CollectTypeNumVO> chunk : chunks) { baseMapper.updateThumbsUpNumBatch(chunk); new LambdaUpdateChainWrapper<>(baseMapper) .in(Video::getId, chunk.stream().map(CollectTypeNumVO::getId).collect(Collectors.toList())) .set(Video::getThumbsUpNumJob, Boolean.FALSE) .update(); } } } framework/src/main/java/cn/lili/rocketmq/tags/VideoTagsEnum.java
@@ -12,6 +12,7 @@ * 收藏 */ COLLECT("收藏"), THUMBS_UP("点赞"), ES_RECREATE("重建视频索引"), ES_DOC_ADD_OR_UPDATE("新增或全量修改视频"), ES_DOC_UPDATE_SOME_FIELD("修改视频某些字段"), framework/src/main/resources/mapper/lmk/ThumbsUpRecordMapper.xml
@@ -56,4 +56,31 @@ LTUR.ref_id </select> <select id="countNumGroupByVideo" resultType="cn.lili.modules.lmk.domain.vo.CollectTypeNumVO"> SELECT LV.id as id, count(LTUR.ref_id) as countNum FROM lmk_video LV LEFT JOIN lmk_thumbs_up_record LTUR ON LTUR.ref_id = LV.id AND LTUR.thumbs_up_type = 'video' AND LTUR.delete_flag = 0 WHERE LV.thumbs_up_num_job = 1 AND LV.delete_flag = 0 GROUP BY LTUR.ref_id </select> <select id="getThumbssByVideoIds" resultType="cn.lili.modules.lmk.domain.vo.SimpleMyThumbsUpVO"> SELECT id, ref_id as refId FROM lmk_thumbs_up_record WHERE user_id = #{userId} AND delete_flag = 0 AND thumbs_up_type = 'video' AND ref_id IN <foreach collection="videoIds" open="(" item="videoId" close=")" separator=",">#{videoId}</foreach> </select> </mapper> framework/src/main/resources/mapper/lmk/VideoMapper.xml
@@ -17,6 +17,7 @@ <result column="play_num" property="playNum" /> <result column="collect_num" property="collectNum" /> <result column="comment_num" property="commentNum" /> <result column="thumbs_up_num" property="thumbsUpNum" /> <result column="weight" property="weight" /> <result column="audit_pass_time" property="auditPassTime" /> <result column="update_time" property="updateTime" /> @@ -70,6 +71,7 @@ <result column="play_num" property="playNum" /> <result column="collect_num" property="collectNum" /> <result column="comment_num" property="commentNum" /> <result column="thumbs_up_num" property="thumbsUpNum" /> <result column="weight" property="weight" /> <result column="audit_pass_time" property="auditPassTime" /> <result column="update_time" property="updateTime" /> @@ -91,6 +93,7 @@ <result column="title" property="title" /> <result column="collect_num" property="collectNum" /> <result column="comment_num" property="commentNum" /> <result column="thumbs_up_num" property="thumbsUpNum" /> <result column="status" property="status" /> <result column="video_content_type" property="videoContentType" /> <result column="video_type" property="videoType" /> @@ -114,6 +117,7 @@ LV.play_num, LV.collect_num, LV.comment_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -145,6 +149,7 @@ LV.play_num, LV.collect_num, LV.comment_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -176,6 +181,7 @@ LV.play_num, LV.collect_num, LV.comment_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -218,6 +224,7 @@ LV.play_num, LV.comment_num, LV.collect_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -251,6 +258,7 @@ LV.play_num, LV.comment_num, LV.collect_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -283,6 +291,7 @@ LV.play_num, LV.comment_num, LV.collect_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -326,6 +335,20 @@ WHEN #{video.id} THEN #{video.countNum} </foreach> ELSE comment_num END WHERE id IN <foreach collection="list" item="video" open="(" separator="," close=")"> #{video.id} </foreach> </update> <update id="updateThumbsUpNumBatch"> UPDATE lmk_video SET thumbs_up_num = CASE id <foreach collection="list" item="video"> WHEN #{video.id} THEN #{video.countNum} </foreach> ELSE thumbs_up_num END WHERE id IN <foreach collection="list" item="video" open="(" separator="," close=")"> @@ -378,6 +401,7 @@ LV.play_num, LV.comment_num, LV.collect_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -416,6 +440,7 @@ LV.play_num, LV.comment_num, LV.collect_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -479,6 +504,7 @@ LV.play_num, LV.collect_num, LV.comment_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -520,6 +546,7 @@ LV.play_num, LV.collect_num, LV.comment_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -591,6 +618,7 @@ LV.play_num, LV.comment_num, LV.collect_num, LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, lmk-job/src/main/java/cn/lili/job/VideoJob.java
@@ -72,4 +72,19 @@ } } /** * 视频点赞数统计 * * @throws Exception */ @XxlJob("videoThumbsUpNumJob") public void videoThumbsUpNumJob() throws Exception { XxlJobHelper.log("开始执行:视频点赞数统计"); List<CollectTypeNumVO> numList = thumbsUpRecordService.countNumGroupByVideo(); if (CollectionUtils.isNotEmpty(numList)) { videoService.updateThumbsUpNumBatch(numList); } } }