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/resources/mapper/lmk/ThumbsUpRecordMapper.xml | 27 + framework/src/main/java/cn/lili/modules/search/repository/EsVideoIndexRepository.java | 15 framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java | 4 framework/src/main/java/cn/lili/modules/lmk/service/ThumbsUpRecordService.java | 17 buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java | 15 framework/src/main/java/cn/lili/modules/lmk/mapper/ThumbsUpRecordMapper.java | 17 framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java | 368 ++++++++++++++-- framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java | 2 framework/src/main/java/cn/lili/cache/CachePrefix.java | 5 framework/src/main/java/cn/lili/modules/lmk/constant/RedisKeyExpireConstant.java | 5 framework/src/main/java/cn/lili/modules/lmk/domain/vo/WxVideoVO.java | 7 framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java | 8 framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoGoodsDetailVO.java | 8 framework/src/main/resources/mapper/lmk/VideoMapper.xml | 127 +++++ framework/src/main/resources/es/video.json | 49 ++ framework/src/main/java/cn/lili/modules/lmk/service/impl/ThumbsUpRecordServiceImpl.java | 12 manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java | 22 framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleMyThumbsUpVO.java | 24 + framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java | 53 + framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java | 25 + framework/src/main/java/cn/lili/modules/lmk/enums/general/ThumbsUpTypeEnum.java | 1 lmk-job/src/main/java/cn/lili/job/VideoJob.java | 15 framework/src/main/java/cn/lili/modules/lmk/service/EsService.java | 68 +++ framework/src/main/java/cn/lili/modules/lmk/domain/vo/KitchenVideoVO.java | 4 framework/src/main/java/cn/lili/modules/lmk/domain/dto/VideoEsUpdateDTO.java | 24 + consumer/src/main/java/cn/lili/listener/VideoMessageListener.java | 70 +++ framework/src/main/java/cn/lili/elasticsearch/EsSuffix.java | 5 framework/src/main/java/cn/lili/rocketmq/tags/VideoTagsEnum.java | 5 framework/src/main/java/cn/lili/modules/lmk/domain/es/VideoIndex.java | 94 ++++ framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoEsServiceImpl.java | 214 +++++++++ framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleVideoTagVO.java | 5 31 files changed, 1,233 insertions(+), 82 deletions(-) diff --git a/buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java b/buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java index 19e4379..a8f665f 100644 --- a/buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java +++ b/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; @@ -38,7 +39,7 @@ } @PutMapping - @ApiOperation(value = "淇敼", notes = "淇敼") + @ApiOperation(value = "淇敼瑙嗛", notes = "淇敼瑙嗛") public Result update(@RequestBody @Validated(Update.class) WxVideoForm form) { return videoService.updatePublish(form); } @@ -118,6 +119,12 @@ return videoService.getAuthorCollectVideoPage(query); } + @GetMapping("/author-like-video-page") + @ApiOperation(value = "鑾峰彇瑙嗛涓婚〉浣滆�呯偣璧炵殑瑙嗛鍒嗛〉", notes = "鑾峰彇瑙嗛涓婚〉浣滆�呯偣璧炵殑瑙嗛鍒嗛〉") + public Result getAuthorLikeVideoPage(AuthorVideoQuery query) { + return videoService.getAuthorLikeVideoPage(query); + } + @PostMapping("/home-page-info-edit") @ApiOperation(value = "淇濆瓨瑙嗛涓婚〉鐨勪釜浜轰俊鎭慨鏀�", notes = "淇濆瓨瑙嗛涓婚〉鐨勪釜浜轰俊鎭慨鏀�") public Result homePageInfoEdit(@RequestBody @Validated VideoHomePageInfoForm form) { @@ -129,4 +136,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); + } } diff --git a/consumer/src/main/java/cn/lili/listener/VideoMessageListener.java b/consumer/src/main/java/cn/lili/listener/VideoMessageListener.java index 613f9af..e970292 100644 --- a/consumer/src/main/java/cn/lili/listener/VideoMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/VideoMessageListener.java @@ -1,9 +1,13 @@ package cn.lili.listener; import cn.lili.cache.Cache; +import cn.lili.elasticsearch.EsSuffix; +import cn.lili.modules.lmk.domain.dto.VideoEsUpdateDTO; import cn.lili.modules.lmk.domain.entity.MyCollect; import cn.lili.modules.lmk.domain.entity.ThumbsUpRecord; +import cn.lili.modules.lmk.domain.es.VideoIndex; import cn.lili.modules.lmk.domain.form.ThumbsUpRecordForm; +import cn.lili.modules.lmk.service.EsService; import cn.lili.modules.lmk.service.ThumbsUpRecordService; import cn.lili.modules.lmk.service.VideoCommentService; import cn.lili.modules.lmk.service.VideoService; @@ -16,6 +20,7 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** @@ -33,20 +38,35 @@ private VideoService videoService; @Autowired + @Qualifier("videoEsServiceImpl") + private EsService esService; + + @Autowired private Cache<Object> cache; @Override public void onMessage(MessageExt messageExt) { try { String msg = new String(messageExt.getBody()); - if (StringUtils.isBlank(msg)) { - log.error("video msg is null, cant not consumer"); - return; - } + switch (VideoTagsEnum.valueOf(messageExt.getTags())) { case COLLECT: this.collect(msg); break; + case THUMBS_UP: + this.changeThumbsUp(msg); + break; + case ES_RECREATE: + this.recreateVideoIndex(); + break; + case ES_DOC_ADD_OR_UPDATE: + this.addOrUpdateEsVideo(msg); + break; + case ES_DOC_UPDATE_SOME_FIELD: + this.updateEsVideoSomeField(msg); + break; + case ES_DOC_DEL: + this.delEsVideo(msg); default: log.error("video msg not match correct tag, consumer err"); break; @@ -66,4 +86,46 @@ videoService.mqCollectChange(collect); } + /** + * 閲嶅缓瑙嗛绱㈠紩 + * + */ + public void recreateVideoIndex() { + esService.recreateIndex(EsSuffix.VIDEO_INDEX_NAME, "/es/video.json"); + } + + /** + * 鏂板es瑙嗛鏁版嵁/鏇存柊 + * + * @param msg + */ + public void addOrUpdateEsVideo(String msg) { + VideoIndex videoIndex = JSON.parseObject(msg, VideoIndex.class); + esService.addOrUpdateDocument(videoIndex); + } + + /** + * 鏇存柊es瑙嗛鐨勬煇浜涘瓧娈� + * + * @param msg + */ + public void updateEsVideoSomeField(String msg) { + VideoEsUpdateDTO dto = JSON.parseObject(msg, VideoEsUpdateDTO.class); + esService.updateSomeField(EsSuffix.VIDEO_INDEX_NAME, dto.getId(), dto.getFields()); + } + + /** + * 鏍规嵁id鍒犻櫎es涓殑瑙嗛 + * + * @param id + */ + public void delEsVideo(String id) { + esService.deleteDocument(EsSuffix.VIDEO_INDEX_NAME, id); + } + + public void changeThumbsUp(String msg) { + ThumbsUpRecord thumbsUpRecord = JSON.parseObject(msg, ThumbsUpRecord.class); + videoService.mqChangeThumbsUp(thumbsUpRecord); + } + } diff --git a/framework/src/main/java/cn/lili/cache/CachePrefix.java b/framework/src/main/java/cn/lili/cache/CachePrefix.java index e3cb80b..9d8ec0b 100644 --- a/framework/src/main/java/cn/lili/cache/CachePrefix.java +++ b/framework/src/main/java/cn/lili/cache/CachePrefix.java @@ -528,6 +528,11 @@ */ VIDEO_COLLECT_NUM, + /** + * 瑙嗛鐐硅禐鏁伴噺 + */ + VIDEO_THUMBS_UP_NUM, + /** * 鎵爜鐧诲綍 diff --git a/framework/src/main/java/cn/lili/elasticsearch/EsSuffix.java b/framework/src/main/java/cn/lili/elasticsearch/EsSuffix.java index 9b6e4a9..72bd99c 100644 --- a/framework/src/main/java/cn/lili/elasticsearch/EsSuffix.java +++ b/framework/src/main/java/cn/lili/elasticsearch/EsSuffix.java @@ -14,6 +14,11 @@ public static final String GOODS_INDEX_NAME = "goods"; /** + * 瑙嗛绱㈠紩鍚庣紑 + */ + public static final String VIDEO_INDEX_NAME = "video"; + + /** * 鏃ュ織绱㈠紩鍚庣紑 */ public static final String LOGS_INDEX_NAME = "logs"; diff --git a/framework/src/main/java/cn/lili/modules/lmk/constant/RedisKeyExpireConstant.java b/framework/src/main/java/cn/lili/modules/lmk/constant/RedisKeyExpireConstant.java index 2c4a4ba..edc1aa4 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/constant/RedisKeyExpireConstant.java +++ b/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; + /** * 杩囨湡鏃堕棿鍗曚綅 diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/dto/VideoEsUpdateDTO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/dto/VideoEsUpdateDTO.java new file mode 100644 index 0000000..ea3ee6d --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/dto/VideoEsUpdateDTO.java @@ -0,0 +1,24 @@ +package cn.lili.modules.lmk.domain.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * @author锛歺p + * @date锛�2025/7/1 10:01 + */ +@Data +public class VideoEsUpdateDTO { + + /** + * 瑙嗛id + */ + private String id; + + /** + * 淇敼鍝簺瀛楁 + */ + private Map<String, Object> fields; + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java index 35ca6a7..d2e7e15 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java +++ b/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; diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/es/VideoIndex.java b/framework/src/main/java/cn/lili/modules/lmk/domain/es/VideoIndex.java new file mode 100644 index 0000000..b38db0a --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/es/VideoIndex.java @@ -0,0 +1,94 @@ +package cn.lili.modules.lmk.domain.es; + +import cn.lili.elasticsearch.EsSuffix; +import cn.lili.modules.lmk.domain.vo.SimpleVideoTagVO; +import cn.lili.modules.lmk.domain.vo.VideoGoodsDetailVO; +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.util.List; + +/** + * es鐨勮棰慸ocument锛堝瓨鍌ㄥ崟鍏冿級 + * + * @author锛歺p + * @date锛�2025/6/30 14:50 + */ +@Data +@Document(indexName = "#{@elasticsearchProperties.indexPrefix}_" + EsSuffix.VIDEO_INDEX_NAME, createIndex = false) +public class VideoIndex { + + /** 瑙嗛id */ + @Id + private String id; + + /** 瑙嗛鏍囬 */ + @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word") + private String title; + + /** 浣滆�卛d */ + @Field(type = FieldType.Keyword) + private String authorId; + + /** 浣滆�呭悕绉� */ + @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word") + private String authorName; + + /** 浣滆�呭ご鍍� */ + @Field(type = FieldType.Keyword) + private String authorAvatar; + + /** 灏侀潰 */ + @Field(type = FieldType.Keyword) + private String coverFileKey; + + /** 瑙嗛鍦板潃 */ + @Field(type = FieldType.Keyword) + private String videoFileKey; + + /** + * 瑙嗛鍐呭绫诲瀷锛氳棰戙�佸浘鐗� + * @see cn.lili.modules.lmk.enums.general.VideoContentTypeEnum + */ + @Field(type = FieldType.Keyword) + private String videoContentType; + + /** + * 瑙嗛绫诲瀷锛氳棰戙�佸ぇ鍋ュ悍銆佺鍘� + * @see cn.lili.modules.lmk.enums.general.VideoTypeEnum + */ + @Field(type = FieldType.Keyword) + private String videoType; + + /** 鍥鹃泦-json鏁扮粍 */ + @Field(type = FieldType.Keyword) + private String videoImgs; + + /** 瑙嗛鏍囩 */ + @Field(type = FieldType.Nested) + private List<SimpleVideoTagVO> tagList; + + /** 瑙嗛鏃堕暱锛氱 */ + @Field(type = FieldType.Keyword) + private Long videoDuration; + + /** 瑙嗛濉厖妯″紡 */ + @Field(type = FieldType.Keyword) + private String videoFit; + + /** 瑙嗛鐘舵�� */ + @Field(type = FieldType.Keyword) + private String status; + + /** 鍟嗗搧淇℃伅 */ + @Field(type = FieldType.Nested) + private List<VideoGoodsDetailVO> goodsList; + + /** 鏄惁鎺ㄨ崘瑙嗛 */ + @Field(type = FieldType.Keyword) + private boolean recommend = false; + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java b/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java index 8aa7959..832bf33 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java @@ -24,7 +24,7 @@ @ApiModelProperty("浣滆�卛d") private String authorId; - @ApiModelProperty("瑙嗛鏉ユ簮锛歳ecommend鎺ㄨ崘銆乤uthor鏌愪綔鑰呯殑瑙嗛銆乧ollect鏌愪綔鑰呮敹钘忕殑瑙嗛") + @ApiModelProperty("瑙嗛鏉ユ簮锛歳ecommend鎺ㄨ崘銆乤uthor鏌愪綔鑰呯殑瑙嗛銆乧ollect鏌愪綔鑰呮敹钘忕殑瑙嗛銆乴ike鏌愪綔鑰呯偣璧炵殑瑙嗛") private String videoFrom; /** diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/KitchenVideoVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/KitchenVideoVO.java index 7511b4d..bf57ce5 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/KitchenVideoVO.java +++ b/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; diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleMyThumbsUpVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleMyThumbsUpVO.java new file mode 100644 index 0000000..7d43ba7 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleMyThumbsUpVO.java @@ -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; + + /** 鐐硅禐瀵瑰簲鐨刬d锛岃棰慽d銆佽瘎璁篿d锛屾牴鎹偣璧炵被鍨嬪畾 */ + @ApiModelProperty("鐐硅禐瀵瑰簲鐨刬d锛岃棰慽d銆佽瘎璁篿d锛屾牴鎹偣璧炵被鍨嬪畾") + private String refId; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleVideoTagVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleVideoTagVO.java index 87c6671..a613316 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleVideoTagVO.java +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/SimpleVideoTagVO.java @@ -6,6 +6,8 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.beans.BeanUtils; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; import org.springframework.lang.NonNull; /** @@ -19,13 +21,16 @@ public class SimpleVideoTagVO { @ApiModelProperty("鏍囩id") + @Field(type = FieldType.Keyword) private String id; /** 鏍囩鍚嶇О */ @ApiModelProperty("鏍囩鍚嶇О") + @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word") private String tagName; @ApiModelProperty(hidden = true) + @Field(type = FieldType.Keyword) private String videoId; diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoGoodsDetailVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoGoodsDetailVO.java index a98f5dc..c5d4acc 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoGoodsDetailVO.java +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoGoodsDetailVO.java @@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; /** * @author锛歺p @@ -14,20 +16,26 @@ public class VideoGoodsDetailVO { @ApiModelProperty("鍟嗗搧id") + @Field(type = FieldType.Keyword) private String goodsId; @ApiModelProperty("鍟嗗搧skuid") + @Field(type = FieldType.Keyword) private String id; @ApiModelProperty("鍟嗗搧鍚嶇О") + @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word") private String goodsName; @ApiModelProperty("浠锋牸") + @Field(type = FieldType.Keyword) private String price; @ApiModelProperty("缂╃暐鍥�") + @Field(type = FieldType.Keyword) private String thumbnail; @ApiModelProperty("鍟嗗搧鏁伴噺") + @Field(type = FieldType.Keyword) private Integer goodsNum; } diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java index 6f80172..bbcc48f 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java +++ b/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; diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/WxVideoVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/WxVideoVO.java index 9041166..16ca447 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/WxVideoVO.java +++ b/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; diff --git a/framework/src/main/java/cn/lili/modules/lmk/enums/general/ThumbsUpTypeEnum.java b/framework/src/main/java/cn/lili/modules/lmk/enums/general/ThumbsUpTypeEnum.java index f8374f2..48303e6 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/enums/general/ThumbsUpTypeEnum.java +++ b/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; diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/ThumbsUpRecordMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/ThumbsUpRecordMapper.java index 013bc58..c1040cc 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/mapper/ThumbsUpRecordMapper.java +++ b/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); } diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java index c8a6340..252babb 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java +++ b/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java @@ -1,6 +1,7 @@ package cn.lili.modules.lmk.mapper; import cn.lili.modules.lmk.domain.entity.Video; +import cn.lili.modules.lmk.domain.es.VideoIndex; import cn.lili.modules.lmk.domain.query.*; import cn.lili.modules.lmk.domain.vo.*; import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -66,6 +67,13 @@ void updateCommentNumBatch(@Param("list") List<CollectTypeNumVO> numList); /** + * 鎵归噺鏇存柊瑙嗛鐐硅禐鏁� + * + * @param numList + */ + void updateThumbsUpNumBatch(@Param("list") List<CollectTypeNumVO> numList); + + /** * 瑙嗛涓婚〉浣滆�呬俊鎭� * * @param authorId @@ -106,6 +114,14 @@ IPage getAuthorCollectVideoPage(IPage page, @Param("query") AuthorVideoQuery query); /** + * 鑾峰彇瑙嗛涓婚〉浣滆�呯偣璧炵殑瑙嗛鍒嗛〉 + * + * @param page + * @param query + */ + IPage getAuthorLikeVideoPage(IPage page, @Param("query") AuthorVideoQuery query); + + /** * 灏忕▼搴�-瑙嗛璇︽儏 * * @param id @@ -130,4 +146,13 @@ * @return */ List<VideoGoodsDetailVO> getVideoGoods(@Param("id") String videoId); + + /** + * es鍚屾鏌ヨ瑙嗛鏁版嵁 + * + * @param start 寮�濮嬩綅缃� + * @param pageSize 姣忛〉鏉℃暟 + * @return + */ + List<VideoIndex> getEsPage(@Param("start") int start, @Param("pageSize") int pageSize); } diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/EsService.java b/framework/src/main/java/cn/lili/modules/lmk/service/EsService.java new file mode 100644 index 0000000..1054162 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/EsService.java @@ -0,0 +1,68 @@ +package cn.lili.modules.lmk.service; + +import java.util.Map; + +/** + * es澶勭悊 + * + * @author锛歺p + * @date锛�2025/6/30 14:47 + */ +public interface EsService { + + /** + * 鑾峰彇绱㈠紩鐨勫畬鏁村悕绉� + * + * @param indexName + * @return + */ + String getIndexFullName(String indexName); + + /** + * 鍒涘缓绱㈠紩 + * + * @param indexName 绱㈠紩鍚嶇О + * @param mappingJsonPath json鏂囦欢浣嶇疆锛岀浉瀵逛簬resource鐩綍锛屼緥濡傦細/es/video.json + */ + void createIndex(String indexName, String mappingJsonPath); + + /** + * 閲嶅缓绱㈠紩锛屽苟閲嶆柊娣诲姞绱㈠紩鏁版嵁 + * + * @param indexName 绱㈠紩鍚嶇О + * @param mappingJsonPath json鏂囦欢浣嶇疆锛岀浉瀵逛簬resource鐩綍锛屼緥濡傦細/es/video.json + */ + void recreateIndex(String indexName, String mappingJsonPath); + + /** + * 娣诲姞/淇敼 鏂囨。锛屽鏋滄槸淇敼锛屽垯鏄暣鏉℃暟鎹洿鏂� + * + * @param data 鏁版嵁瀵硅薄 + */ + void addOrUpdateDocument(Object data); + + /** + * 鏇存柊鏌愪簺瀛楁鐨勫�� + * + * @param indexName 绱㈠紩鍚嶇О + * @param id 鏁版嵁id + * @param updateList 鏇存柊鍝簺瀛楁锛宬ey 瀛楁 value瑕佷慨鏀圭殑鍊� + */ + void updateSomeField(String indexName, String id, Map<String, Object> updateList); + + /** + * 鍒犻櫎鏂囨。 + * @param indexName 绱㈠紩鍚嶇О + * @param id es涓婚敭锛屽彲浼犱笟鍔′富閿� + */ + void deleteDocument(String indexName, String id); + + /** + * 绱㈠紩鏄惁瀛樺湪 + * + * @param indexName + * @return + */ + boolean indexExist(String indexName); + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/ThumbsUpRecordService.java b/framework/src/main/java/cn/lili/modules/lmk/service/ThumbsUpRecordService.java index 24a2102..05864c1 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/ThumbsUpRecordService.java +++ b/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); } diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java b/framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java index 0671480..96614ec 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java +++ b/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.*; @@ -20,20 +21,6 @@ * @since 2025-05-16 */ public interface VideoService extends IService<Video> { - - /** - * 娣诲姞 - * @param form - * @return - */ - Result add(WxVideoForm form); - - /** - * 淇敼 - * @param form - * @return - */ - Result update(WxVideoForm form); /** * 鎵归噺鍒犻櫎 @@ -178,6 +165,14 @@ Result getAuthorCollectVideoPage(AuthorVideoQuery query); /** + * 鑾峰彇瑙嗛涓婚〉浣滆�呯偣璧炶棰戝垎椤� + * + * @param query + * @return + */ + Result getAuthorLikeVideoPage(AuthorVideoQuery query); + + /** * 淇濆瓨瑙嗛涓婚〉鐨勪釜浜轰俊鎭慨鏀� * * @param form @@ -265,4 +260,34 @@ * @param collect */ void mqCollectChange(MyCollect collect); + + /** + * 閲嶅缓瑙嗛es绱㈠紩 + * + * @return + */ + Result recreateEsIndex(); + + /** + * 淇敼瑙嗛鐐硅禐鐘舵�� + * + * @param form + * @return + */ + Result changeThumbsUp(ThumbsUpRecordForm form); + + /** + * mq淇敼瑙嗛鐐硅禐鐘舵�� + * + * @param thumbsUpRecord + */ + void mqChangeThumbsUp(ThumbsUpRecord thumbsUpRecord); + + /** + * 鎵归噺鏇存柊瑙嗛鐐硅禐鏁伴噺 + * + * @param numList + */ + void updateThumbsUpNumBatch(List<CollectTypeNumVO> numList); + } diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/ThumbsUpRecordServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/ThumbsUpRecordServiceImpl.java index 44570b1..e3ec3f0 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/ThumbsUpRecordServiceImpl.java +++ b/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()); + } } diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoEsServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoEsServiceImpl.java new file mode 100644 index 0000000..3823ce3 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoEsServiceImpl.java @@ -0,0 +1,214 @@ +package cn.lili.modules.lmk.service.impl; + +import cn.lili.elasticsearch.BaseElasticsearchService; +import cn.lili.elasticsearch.EsSuffix; +import cn.lili.elasticsearch.config.ElasticsearchProperties; +import cn.lili.modules.lmk.domain.entity.Video; +import cn.lili.modules.lmk.domain.es.VideoIndex; +import cn.lili.modules.lmk.enums.general.VideoStatusEnum; +import cn.lili.modules.lmk.mapper.VideoMapper; +import cn.lili.modules.lmk.service.EsService; +import cn.lili.modules.search.repository.EsVideoIndexRepository; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.bulk.BulkRequest; +import org.elasticsearch.action.delete.DeleteRequest; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.indices.CreateIndexRequest; +import org.elasticsearch.client.indices.CreateIndexResponse; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.springframework.data.elasticsearch.core.document.Document; +import org.springframework.data.elasticsearch.core.query.UpdateQuery; +import org.springframework.stereotype.Service; +import org.springframework.util.FileCopyUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; + +/** + * 瑙嗛es + * + * @author锛歺p + * @date锛�2025/6/30 15:54 + */ +@Slf4j +@RequiredArgsConstructor +@Service("videoEsServiceImpl") +public class VideoEsServiceImpl extends BaseElasticsearchService implements EsService { + + private final ElasticsearchProperties elasticsearchProperties; + private final VideoMapper videoMapper; + private final EsVideoIndexRepository esVideoIndexRepository; + + @Override + public String getIndexFullName(String indexName) { + return elasticsearchProperties.getIndexPrefix() + "_" + indexName; + } + + @Override + public void createIndex(String indexName, String mappingJsonPath) { + if (! indexName.startsWith(elasticsearchProperties.getIndexPrefix())) { + indexName = this.getIndexFullName(indexName); + } + if (this.indexExist(indexName)) { + throw new RuntimeException(String.format("绱㈠紩锛�%s宸茬粡瀛樺湪锛屾棤娉曞垱寤�", indexName)); + } + CreateIndexRequest request = new CreateIndexRequest(indexName); + + // 1. 閰嶇疆绱㈠紩 + request.settings(Settings.builder() + .put("index.number_of_shards", elasticsearchProperties.getIndex().getNumberOfShards()) + .put("index.number_of_replicas", elasticsearchProperties.getIndex().getNumberOfReplicas()) + .put("index.max_result_window", 100000) //鏈�澶ф煡璇㈢粨鏋滄暟 + .put("index.mapping.total_fields.limit", 2000)); + // 2. 閰嶇疆mapping + String mapping; + try (InputStream inputStream = this.getClass().getResourceAsStream(mappingJsonPath)) { + byte[] bytes = FileCopyUtils.copyToByteArray(inputStream); + mapping = new String(bytes, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(String.format("璇诲彇es鏄犲皠json鏂囦欢锛�%s寮傚父", mappingJsonPath), e); + } + request.mapping(mapping, XContentType.JSON); + // 3. 鍒涘缓绱㈠紩 + try { + CreateIndexResponse createIndexResponse = client.indices().create(request, COMMON_OPTIONS); + } catch (IOException e) { + throw new RuntimeException(String.format("es鍒涘缓绱㈠紩澶辫触锛�%s", indexName), e); + } + } + + @Override + public void recreateIndex(String indexName, String mappingJsonPath) { + indexName = this.getIndexFullName(indexName); + // 1. 濡傛灉绱㈠紩瀛樺湪锛屽厛鍒犻櫎绱㈠紩锛屽啀鍒涘缓绱㈠紩 + if (this.indexExist(indexName)) { + DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName); + try { + AcknowledgedResponse deleteRes = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT); + this.createIndex(indexName, mappingJsonPath); + } catch (IOException e) { + log.error("鍒犻櫎绱㈠紩澶辫触", e); + throw new RuntimeException("鍒犻櫎绱㈠紩澶辫触"); + } + } else { + this.createIndex(indexName, mappingJsonPath); + } + // 2. 澶氱嚎绋嬫煡璇㈣棰戞暟鎹紝鏋勫缓鏂囨。瀵硅薄 + Long totalVideo = new LambdaQueryChainWrapper<>(videoMapper) + .count(); + int totalThreads = (int) Math.ceil((double) totalVideo / 200); // 璁$畻闇�瑕佸灏戜釜绾跨▼ + CountDownLatch latch = new CountDownLatch(totalThreads); + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( + 4, + 10, + 10, + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(4), + Executors.defaultThreadFactory(), + new ThreadPoolExecutor.AbortPolicy()); + BlockingQueue<VideoIndex> dataList = new LinkedBlockingQueue<>(); + for (int page = 0; page < totalThreads; page++) { + final int currentPage = page; + threadPoolExecutor.execute(() -> { + try { + List<VideoIndex> pageData = videoMapper.getEsPage(currentPage * 200, 200); + dataList.addAll(pageData); + } catch (Exception e) { + log.error("绗瑊}椤垫暟鎹煡璇㈠け璐�", currentPage, e); + } finally { + latch.countDown(); // 绾跨▼鎵ц瀹屾垚 -1 + } + }); + } + try { + latch.await(); // 绛夊緟鎵�鏈夌嚎绋嬫墽琛屽畬鎴� + // 3. 娣诲姞es鏁版嵁 +// BulkRequest bulkRequest = new BulkRequest(); +// String finalIndexName = indexName; +// dataList.forEach(data -> { +// IndexRequest indexRequest = new IndexRequest(finalIndexName) +// .id(data.getId()) +// .source(data); +// bulkRequest.add(indexRequest); +// }); +// client.bulk(bulkRequest, RequestOptions.DEFAULT); + esVideoIndexRepository.saveAll(dataList); + } catch (InterruptedException e) { + log.error("澶氱嚎绋嬭鍙栬棰戞暟鎹紓甯�", e); + } finally { + threadPoolExecutor.shutdown(); + } + } + + @Override + public void addOrUpdateDocument(Object data) { + VideoIndex videoIndex = (VideoIndex) data; + esVideoIndexRepository.save(videoIndex); +// indexName = this.getIndexFullName(indexName); +// IndexRequest request = new IndexRequest(indexName); +// request.id(id).source(data); +// try { +// client.index(request, RequestOptions.DEFAULT); +// } catch (IOException e) { +// throw new RuntimeException("es鏂囨。娣诲姞/淇敼澶辫触", e); +// } + } + + @Override + public void updateSomeField(String indexName, String id, Map<String, Object> updateList) { + indexName = this.getIndexFullName(indexName); + // 鏋勫缓鏇存柊璇锋眰 + UpdateRequest request = new UpdateRequest(indexName, id); + + try { + // 鏋勫缓鏇存柊鍐呭 + XContentBuilder builder = XContentFactory.jsonBuilder().startObject(); + for (Map.Entry<String, Object> entry : updateList.entrySet()) { + builder.field(entry.getKey(), entry.getValue()); + } + builder.endObject(); + + request.doc(builder); // 璁剧疆閮ㄥ垎鏇存柊鍐呭 + + // 鍙�夐厤缃� + request.retryOnConflict(2); // 鍐茬獊閲嶈瘯娆℃暟 +// request.fetchSource(true); // 杩斿洖鏇存柊鍚庣殑鏂囨。 + + client.update(request, RequestOptions.DEFAULT); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void deleteDocument(String indexName, String id) { + indexName = this.getIndexFullName(indexName); + DeleteRequest request = new DeleteRequest(indexName, id); + try { + client.delete(request, RequestOptions.DEFAULT); + } catch (IOException e) { + throw new RuntimeException("鍒犻櫎es鏂囨。澶辫触锛�" + id, e); + } + } + + @Override + public boolean indexExist(String indexName) { + if (!indexName.startsWith(elasticsearchProperties.getIndexPrefix())) { + indexName = this.getIndexFullName(indexName); + } + return super.indexExist(indexName); + } +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java index 116f4f6..cdfff28 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java @@ -2,9 +2,13 @@ import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; +import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.context.UserContext; +import cn.lili.elasticsearch.EsSuffix; import cn.lili.modules.lmk.constant.RedisKeyExpireConstant; +import cn.lili.modules.lmk.domain.dto.VideoEsUpdateDTO; import cn.lili.modules.lmk.domain.entity.*; +import cn.lili.modules.lmk.domain.es.VideoIndex; import cn.lili.modules.lmk.domain.form.*; import cn.lili.modules.lmk.domain.query.*; import cn.lili.modules.lmk.domain.vo.*; @@ -14,6 +18,9 @@ import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.service.FootprintService; import cn.lili.modules.member.service.MemberService; +import cn.lili.rocketmq.RocketmqSendCallbackBuilder; +import cn.lili.rocketmq.tags.CommentTagsEnum; +import cn.lili.rocketmq.tags.VideoTagsEnum; import cn.lili.utils.COSUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -26,6 +33,8 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import cn.lili.utils.PageUtil; @@ -62,33 +71,10 @@ private final KitchenTypeService kitchenTypeService; private final Cache cache; - /** - * 娣诲姞 - * @param form - * @return - */ - @Override - public Result add(WxVideoForm form) { - Video entity = WxVideoForm.getEntityByForm(form, null); - baseMapper.insert(entity); - return Result.ok("娣诲姞鎴愬姛"); - } + private final RocketmqCustomProperties rocketmqCustomProperties; + private final RocketMQTemplate rocketMQTemplate; + private final ThumbsUpRecordService thumbsUpRecordService; - /** - * 淇敼 - * @param form - * @return - */ - @Override - public Result update(WxVideoForm form) { - Video entity = baseMapper.selectById(form.getId()); - - // 涓虹┖鎶汭llegalArgumentException锛屽仛鍏ㄥ眬寮傚父澶勭悊 - Assert.notNull(entity, "璁板綍涓嶅瓨鍦�"); - BeanUtils.copyProperties(form, entity); - baseMapper.updateById(entity); - return Result.ok("淇敼鎴愬姛"); - } /** * 鎵归噺鍒犻櫎 @@ -107,8 +93,18 @@ * @return */ @Override + @Transactional(rollbackFor = Exception.class) public Result removeById(String id) { baseMapper.deleteById(id); + new LambdaUpdateChainWrapper<>(videoGoodsService.getBaseMapper()) + .eq(VideoGoods::getVideoId, id) + .remove(); + new LambdaUpdateChainWrapper<>(videoTagRefService.getBaseMapper()) + .eq(VideoTagRef::getVideoId, id) + .remove(); + // mq寮傛鍒犻櫎es鏁版嵁 + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_DEL.name(); + rocketMQTemplate.asyncSend(destination, id, RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("鍒犻櫎鎴愬姛"); } @@ -170,11 +166,13 @@ video.setStatus(VideoStatusEnum.AUDITING.getValue()); video.setCoverUrl(form.getCover()); video.setVideoType(VideoTypeEnum.VIDEO.getValue()); + video.setRecommend(Boolean.FALSE); if (VideoContentTypeEnum.IMG.getValue().equals(form.getVideoContentType())) { video.setVideoImgs(JSON.toJSONString(form.getVideoImgs())); } baseMapper.insert(video); // 2.澶勭悊鏍囩 + List<SimpleVideoTagVO> esTagList = new ArrayList<>(2); List<VideoTagRef> videoTagRefs = form.getTags().stream().map(tag -> { VideoTagRef videoTagRef = new VideoTagRef(); videoTagRef.setVideoId(video.getId()); @@ -194,14 +192,19 @@ } else { videoTagRef.setVideoTagId(tag.getId()); } + SimpleVideoTagVO esTag = new SimpleVideoTagVO(); + esTag.setVideoId(video.getId()); + esTag.setTagName(tag.getTagName()); + esTag.setId(tag.getId()); + esTagList.add(esTag); return videoTagRef; }).collect(Collectors.toList()); videoTagRefService.saveBatch(videoTagRefs); // 3. 淇濆瓨瑙嗛鏂囦欢淇℃伅 lmkFileService.addByForm(form.getFileInfo()); // 4. 澶勭悊閫夋嫨鐨勫晢鍝� + List<VideoGoods> videoGoods = new ArrayList<>(2); if (CollectionUtils.isNotEmpty(form.getGoodsList())) { - List<VideoGoods> videoGoods = new ArrayList<>(2); for (int i = 0; i < form.getGoodsList().size(); i++) { VideoGoods e = new VideoGoods(); e.setVideoId(video.getId()); @@ -209,10 +212,23 @@ e.setGoodsSkuId(form.getGoodsList().get(i).getGoodsSkuId()); e.setGoodsNum(form.getGoodsList().get(i).getGoodsNum()); e.setOrderNum(i); - videoGoods.add(e); + videoGoodsService.save(e); } videoGoodsService.saveBatch(videoGoods); } + // 5. 鏋勫缓es涓暟鎹紝mq寮傛澶勭悊 + VideoIndex videoIndex = new VideoIndex(); + BeanUtils.copyProperties(video, videoIndex); + videoIndex.setCoverFileKey(video.getCoverUrl()); + List<VideoGoodsDetailVO> esGoodsList = videoGoods.stream().map(goods -> { + VideoGoodsDetailVO vo = new VideoGoodsDetailVO(); + BeanUtils.copyProperties(goods, vo); + return vo; + }).collect(Collectors.toList()); + videoIndex.setGoodsList(esGoodsList); + videoIndex.setTagList(esTagList); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_ADD_OR_UPDATE.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(videoIndex), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("鍙戝竷鎴愬姛锛岃棰戝鏍镐腑~"); } @@ -236,6 +252,7 @@ new LambdaUpdateChainWrapper<>(videoTagRefService.getBaseMapper()) .eq(VideoTagRef::getVideoId, video.getId()) .remove(); + List<SimpleVideoTagVO> esTagList = new ArrayList<>(2); List<VideoTagRef> videoTagRefs = form.getTags().stream().map(tag -> { VideoTagRef videoTagRef = new VideoTagRef(); videoTagRef.setVideoId(video.getId()); @@ -255,6 +272,11 @@ } else { videoTagRef.setVideoTagId(tag.getId()); } + SimpleVideoTagVO esTag = new SimpleVideoTagVO(); + esTag.setVideoId(video.getId()); + esTag.setTagName(tag.getTagName()); + esTag.setId(tag.getId()); + esTagList.add(esTag); return videoTagRef; }).collect(Collectors.toList()); videoTagRefService.saveBatch(videoTagRefs); @@ -264,8 +286,8 @@ new LambdaUpdateChainWrapper<>(videoGoodsService.getBaseMapper()) .eq(VideoGoods::getVideoId, video.getId()) .remove(); + List<VideoGoods> videoGoods = new ArrayList<>(2); if (CollectionUtils.isNotEmpty(form.getGoodsList())) { - List<VideoGoods> videoGoods = new ArrayList<>(2); for (int i = 0; i < form.getGoodsList().size(); i++) { VideoGoods e = new VideoGoods(); e.setVideoId(video.getId()); @@ -277,6 +299,19 @@ } videoGoodsService.saveBatch(videoGoods); } + // 5. 鏇存柊es涓殑鏁版嵁锛宮q寮傛澶勭悊 + VideoIndex videoIndex = new VideoIndex(); + BeanUtils.copyProperties(video, videoIndex); + videoIndex.setCoverFileKey(video.getCoverUrl()); + List<VideoGoodsDetailVO> esGoodsList = videoGoods.stream().map(goods -> { + VideoGoodsDetailVO vo = new VideoGoodsDetailVO(); + BeanUtils.copyProperties(goods, vo); + return vo; + }).collect(Collectors.toList()); + videoIndex.setGoodsList(esGoodsList); + videoIndex.setTagList(esTagList); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_ADD_OR_UPDATE.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(videoIndex), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("鍙戝竷鎴愬姛锛岃棰戝鏍镐腑~"); } @@ -305,6 +340,15 @@ .eq(Video::getId, form.getId()) .set(Video::getRecommend, form.getRecommend()) .update(); + + // mq寮傛鏇存柊es + Map<String, Object> fields = new HashMap<>(2); + fields.put("recommend", form.getRecommend()); + VideoEsUpdateDTO dto = new VideoEsUpdateDTO(); + dto.setId(form.getId()); + dto.setFields(fields); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_UPDATE_SOME_FIELD.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(dto), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("璁剧疆鎴愬姛"); } @@ -324,34 +368,64 @@ } videoAuditRecordService.save(auditRecord); // 2. 淇敼瑙嗛鐘舵�� + Map<String, Object> fields = new HashMap<>(2); if (form.getResult()) { video.setStatus(VideoStatusEnum.PUBLISHED.getValue()); video.setAuditPassTime(new Date()); + + fields.put("status", VideoStatusEnum.PUBLISHED.getValue()); } else { video.setStatus(VideoStatusEnum.REJECT.getValue()); + fields.put("status", VideoStatusEnum.REJECT.getValue()); } baseMapper.updateById(video); + + // 3. mq寮傛鏇存柊es + VideoEsUpdateDTO dto = new VideoEsUpdateDTO(); + dto.setId(video.getId()); + dto.setFields(fields); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_UPDATE_SOME_FIELD.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(dto), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok(); } @Override public Result up(String id) { + // 1. 鏇存柊鏁版嵁搴� new LambdaUpdateChainWrapper<>(baseMapper) .eq(Video::getId, id) .set(Video::getStatus, VideoStatusEnum.PUBLISHED.getValue()) .update(); + // 2. mq寮傛鏇存柊es + Map<String, Object> fields = new HashMap<>(2); + fields.put("status", VideoStatusEnum.PUBLISHED.getValue()); + VideoEsUpdateDTO dto = new VideoEsUpdateDTO(); + dto.setId(id); + dto.setFields(fields); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_UPDATE_SOME_FIELD.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(dto), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("涓婃灦鎴愬姛"); } @Override public Result down(VideoDownForm form) { + // 1. 鏇存柊鏁版嵁搴� new LambdaUpdateChainWrapper<>(baseMapper) .eq(Video::getId, form.getId()) .set(Video::getStatus, VideoStatusEnum.DISABLE.getValue()) .update(); + // 2. mq寮傛鏇存柊es + Map<String, Object> fields = new HashMap<>(2); + fields.put("status", VideoStatusEnum.DISABLE.getValue()); + VideoEsUpdateDTO dto = new VideoEsUpdateDTO(); + dto.setId(form.getId()); + dto.setFields(fields); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_UPDATE_SOME_FIELD.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(dto), RocketmqSendCallbackBuilder.commonCallback()); // TODO 灏嗕笅鏋跺師鍥犱互閫氱煡鐨勬柟寮忓憡鐭ョ敤鎴� + return Result.ok("涓嬫灦鎴愬姛"); } @@ -361,6 +435,14 @@ .eq(Video::getId, id) .set(Video::getStatus, VideoStatusEnum.DISABLE.getValue()) .update(); + // 2. mq寮傛鏇存柊es + Map<String, Object> fields = new HashMap<>(2); + fields.put("status", VideoStatusEnum.DISABLE.getValue()); + VideoEsUpdateDTO dto = new VideoEsUpdateDTO(); + dto.setId(id); + dto.setFields(fields); + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_DOC_UPDATE_SOME_FIELD.name(); + rocketMQTemplate.asyncSend(destination, JSON.toJSONString(dto), RocketmqSendCallbackBuilder.commonCallback()); return Result.ok("涓嬫灦鎴愬姛"); } @@ -382,6 +464,10 @@ query2.setAuthorId(query.getAuthorId()); baseMapper.getAuthorCollectVideoPage(page, query2); break; + case "like": + AuthorVideoQuery query3 = new AuthorVideoQuery(); + query3.setAuthorId(query.getAuthorId()); + baseMapper.getAuthorLikeVideoPage(page, query3); default: break; } @@ -390,16 +476,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())); @@ -451,6 +542,23 @@ return (Integer) redisNum; } + /** + * 浠巖edis涓幏鍙栫偣璧炴暟閲忥紝濡傛灉redis涓病鏈夊垯灏唌ysql涓殑鏁伴噺鍐欏叆鍒皉edis + * + * @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涓病鏈夊氨鎶婃暟鎹簱鐨勫啓鍒皉edis涓� + 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); @@ -491,8 +599,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) @@ -505,8 +613,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) @@ -547,16 +655,39 @@ IPage<WxVideoVO> page = PageUtil.getPage(query, WxVideoVO.class); query.setAuthorSelf(UserContext.getCurrentUserId().equals(query.getAuthorId())); baseMapper.getAuthorVideoPage(page, query); - for (WxVideoVO vo : page.getRecords()) { - if (VideoContentTypeEnum.VIDEO.getValue().equals(vo.getVideoContentType())) { - vo.setVideoUrl(cosUtil.getPreviewUrl(vo.getVideoFileKey())); - vo.setCoverUrl(cosUtil.getPreviewUrl(vo.getCoverFileKey())); - } else if (VideoContentTypeEnum.IMG.getValue().equals(vo.getVideoContentType()) && StringUtils.isNotBlank(vo.getVideoImgs())) { - vo.setImgs(JSON.parseArray(vo.getVideoImgs(), String.class).stream().map(fileKey -> cosUtil.getPreviewUrl(fileKey)).collect(Collectors.toList())); + List<String> videoIds = page.getRecords().stream().map(WxVideoVO::getId).collect(Collectors.toList()); + Map<String, List<SimpleVideoTagVO>> tagMap = videoTagRefService.getTagsByVideoIds(videoIds) + .stream() + .collect(Collectors.groupingBy(SimpleVideoTagVO::getVideoId)); + 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()); + if (CollectionUtils.isNotEmpty(page.getRecords())) { + for (WxVideoVO v : page.getRecords()) { + 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())); + } else if (VideoContentTypeEnum.IMG.getValue().equals(v.getVideoContentType()) && StringUtils.isNotBlank(v.getVideoImgs())) { + v.setImgs(JSON.parseArray(v.getVideoImgs(), String.class).stream().map(fileKey -> cosUtil.getPreviewUrl(fileKey)).collect(Collectors.toList())); + } + v.setOptions(VideoSupportOpEnum.getVideoOpByStatus(v.getStatus())); + if (CollectionUtils.isNotEmpty(v.getGoodsList())) { + v.getGoodsList().stream().forEach(goods -> { + goods.setThumbnail(cosUtil.getPreviewUrl(goods.getThumbnail())); + }); + } + v.setSubscribeThisAuthor(subscribes.contains(v.getAuthorId())); } - - - vo.setOptions(VideoSupportOpEnum.getVideoOpByStatus(vo.getStatus())); } return Result.ok().data(page.getRecords()).total(page.getTotal()); } @@ -565,14 +696,72 @@ public Result getAuthorCollectVideoPage(AuthorVideoQuery query) { IPage<WxVideoVO> page = PageUtil.getPage(query, WxVideoVO.class); baseMapper.getAuthorCollectVideoPage(page, query); - for (WxVideoVO vo : page.getRecords()) { - if (VideoContentTypeEnum.VIDEO.getValue().equals(vo.getVideoContentType())) { - vo.setVideoUrl(cosUtil.getPreviewUrl(vo.getVideoFileKey())); - vo.setCoverUrl(cosUtil.getPreviewUrl(vo.getCoverFileKey())); - } else if (VideoContentTypeEnum.IMG.getValue().equals(vo.getVideoContentType()) && StringUtils.isNotBlank(vo.getVideoImgs())) { - vo.setImgs(JSON.parseArray(vo.getVideoImgs(), String.class).stream().map(fileKey -> cosUtil.getPreviewUrl(fileKey)).collect(Collectors.toList())); + if (CollectionUtils.isNotEmpty(page.getRecords())) { + List<String> videoIds = page.getRecords().stream().map(WxVideoVO::getId).collect(Collectors.toList()); + Map<String, List<SimpleVideoTagVO>> tagMap = videoTagRefService.getTagsByVideoIds(videoIds) + .stream() + .collect(Collectors.groupingBy(SimpleVideoTagVO::getVideoId)); + Map<String, List<SimpleMyThumbsUpVO>> thumbsUpMap = thumbsUpRecordService.getThumbssByVideoIds(videoIds) + .stream() + .collect(Collectors.groupingBy(SimpleMyThumbsUpVO::getRefId)); + List<String> subscribes = mySubscribeService.getSubscribesByUserId(UserContext.getCurrentUserId()); + for (WxVideoVO v : page.getRecords()) { + v.setTagList(tagMap.get(v.getId())); + v.setCollected(Boolean.TRUE); + 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())); + } else if (VideoContentTypeEnum.IMG.getValue().equals(v.getVideoContentType()) && StringUtils.isNotBlank(v.getVideoImgs())) { + v.setImgs(JSON.parseArray(v.getVideoImgs(), String.class).stream().map(fileKey -> cosUtil.getPreviewUrl(fileKey)).collect(Collectors.toList())); + } + if (CollectionUtils.isNotEmpty(v.getGoodsList())) { + v.getGoodsList().stream().forEach(goods -> { + goods.setThumbnail(cosUtil.getPreviewUrl(goods.getThumbnail())); + }); + } + v.setSubscribeThisAuthor(subscribes.contains(v.getAuthorId())); } - vo.setCollected(Boolean.TRUE); + } + return Result.ok().data(page.getRecords()).total(page.getTotal()); + } + + @Override + public Result getAuthorLikeVideoPage(AuthorVideoQuery query) { + IPage<WxVideoVO> page = PageUtil.getPage(query, WxVideoVO.class); + baseMapper.getAuthorLikeVideoPage(page, query); + if (CollectionUtils.isNotEmpty(page.getRecords())) { + List<String> videoIds = page.getRecords().stream().map(WxVideoVO::getId).collect(Collectors.toList()); + Map<String, List<SimpleVideoTagVO>> tagMap = videoTagRefService.getTagsByVideoIds(videoIds) + .stream() + .collect(Collectors.groupingBy(SimpleVideoTagVO::getVideoId)); + Map<String, List<SimpleMyCollectVO>> collectMap = myCollectService.getCollectsByVideoIds(videoIds) + .stream() + .collect(Collectors.groupingBy(SimpleMyCollectVO::getRefId)); + List<String> subscribes = mySubscribeService.getSubscribesByUserId(UserContext.getCurrentUserId()); + for (WxVideoVO v : page.getRecords()) { + v.setTagList(tagMap.get(v.getId())); + v.setCollected(CollectionUtils.isNotEmpty(collectMap.get(v.getId()))); + v.setThumbsUp(Boolean.TRUE); + 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())); + } else if (VideoContentTypeEnum.IMG.getValue().equals(v.getVideoContentType()) && StringUtils.isNotBlank(v.getVideoImgs())) { + v.setImgs(JSON.parseArray(v.getVideoImgs(), String.class).stream().map(fileKey -> cosUtil.getPreviewUrl(fileKey)).collect(Collectors.toList())); + } + if (CollectionUtils.isNotEmpty(v.getGoodsList())) { + v.getGoodsList().stream().forEach(goods -> { + goods.setThumbnail(cosUtil.getPreviewUrl(goods.getThumbnail())); + }); + } + v.setSubscribeThisAuthor(subscribes.contains(v.getAuthorId())); + } } return Result.ok().data(page.getRecords()).total(page.getTotal()); } @@ -814,4 +1003,81 @@ .update(); } } + + @Override + public Result recreateEsIndex() { + String destination = rocketmqCustomProperties.getVideoTopic() + ":" + VideoTagsEnum.ES_RECREATE.name(); + // 娑堟伅浣撲笉鑳戒负绌猴紝闅忎究浼犱竴涓�1 + 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(); + } + } } diff --git a/framework/src/main/java/cn/lili/modules/search/repository/EsVideoIndexRepository.java b/framework/src/main/java/cn/lili/modules/search/repository/EsVideoIndexRepository.java new file mode 100644 index 0000000..1819a0d --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/repository/EsVideoIndexRepository.java @@ -0,0 +1,15 @@ +package cn.lili.modules.search.repository; + +import cn.lili.modules.lmk.domain.es.VideoIndex; +import cn.lili.modules.search.entity.dos.EsGoodsIndex; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +/** + * 瑙嗛绱㈠紩 + * + * @author paulG + * @since 2020/10/15 + **/ +public interface EsVideoIndexRepository extends ElasticsearchRepository<VideoIndex, String> { + +} diff --git a/framework/src/main/java/cn/lili/rocketmq/tags/VideoTagsEnum.java b/framework/src/main/java/cn/lili/rocketmq/tags/VideoTagsEnum.java index 03b5ea1..4b8ab2a 100644 --- a/framework/src/main/java/cn/lili/rocketmq/tags/VideoTagsEnum.java +++ b/framework/src/main/java/cn/lili/rocketmq/tags/VideoTagsEnum.java @@ -12,6 +12,11 @@ * 鏀惰棌 */ COLLECT("鏀惰棌"), + THUMBS_UP("鐐硅禐"), + ES_RECREATE("閲嶅缓瑙嗛绱㈠紩"), + ES_DOC_ADD_OR_UPDATE("鏂板鎴栧叏閲忎慨鏀硅棰�"), + ES_DOC_UPDATE_SOME_FIELD("淇敼瑙嗛鏌愪簺瀛楁"), + ES_DOC_DEL("鍒犻櫎瑙嗛"), ; diff --git a/framework/src/main/resources/es/video.json b/framework/src/main/resources/es/video.json new file mode 100644 index 0000000..bda78cd --- /dev/null +++ b/framework/src/main/resources/es/video.json @@ -0,0 +1,49 @@ +{ + "properties": { + "id": {"type": "keyword"}, + "title": { + "type": "text", + "analyzer": "ik_max_word" + }, + "authorId": {"type": "keyword"}, + "authorName": { + "type": "text", + "analyzer": "ik_max_word" + }, + "authorAvatar": {"type": "keyword"}, + "recommend": {"type": "boolean"}, + "coverFileKey": {"type": "keyword"}, + "videoFileKey": {"type": "keyword"}, + "videoContentType": {"type": "keyword"}, + "videoType": {"type": "keyword"}, + "videoImgs": {"type": "keyword"}, + "tagList": { + "type": "nested", + "properties": { + "id": {"type": "keyword"}, + "videoId": {"type": "keyword"}, + "tagName": { + "type": "text", + "analyzer": "ik_max_word" + } + } + }, + "videoDuration": {"type": "keyword"}, + "videoFit": {"type": "keyword"}, + "status": {"type": "keyword"}, + "goodsList": { + "type": "nested", + "properties": { + "id": {"type": "keyword"}, + "goodsId": {"type": "keyword"}, + "price": {"type": "keyword"}, + "thumbnail": {"type": "keyword"}, + "goodsNum": {"type": "keyword"}, + "goodsName": { + "type": "text", + "analyzer": "ik_max_word" + } + } + } + } +} diff --git a/framework/src/main/resources/mapper/lmk/ThumbsUpRecordMapper.xml b/framework/src/main/resources/mapper/lmk/ThumbsUpRecordMapper.xml index a0a28e7..48008b4 100644 --- a/framework/src/main/resources/mapper/lmk/ThumbsUpRecordMapper.xml +++ b/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> diff --git a/framework/src/main/resources/mapper/lmk/VideoMapper.xml b/framework/src/main/resources/mapper/lmk/VideoMapper.xml index 248411a..230ad1a 100644 --- a/framework/src/main/resources/mapper/lmk/VideoMapper.xml +++ b/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, @@ -431,6 +456,41 @@ LEFT JOIN li_member LM ON LV.author_id = LM.id WHERE LMC.delete_flag = 0 AND LMC.user_id = #{query.authorId} AND LMC.collect_type = 'video' AND LV.video_type = #{query.videoType} + ORDER BY + LMC.create_time DESC + </select> + + <select id="getAuthorLikeVideoPage" resultMap="WxResultMap"> + SELECT + LV.author_id, + LV.cover_url, + LV.video_fit, + LV.video_duration, + LV.video_file_key, + LV.title, + LV.goods_view_num, + LV.goods_order_num, + LV.recommend, + LV.status, + LV.play_num, + LV.comment_num, + LV.collect_num, + LV.thumbs_up_num, + LV.weight, + LV.audit_pass_time, + LV.update_time, + LV.video_content_type, + LV.video_type, + LV.video_imgs, + LV.id, + LM.nick_name as authorName, + LM.face as authorAvatar + FROM + lmk_thumbs_up_record LMC + INNER JOIN lmk_video LV ON LMC.ref_id = LV.id AND LV.delete_flag = 0 AND LV.status = '1' + LEFT JOIN li_member LM ON LV.author_id = LM.id + WHERE + LMC.delete_flag = 0 AND LMC.user_id = #{query.authorId} AND LMC.thumbs_up_type = 'video' AND LV.video_type = #{query.videoType} ORDER BY LMC.create_time DESC </select> @@ -479,6 +539,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 +581,7 @@ LV.play_num, LV.collect_num, LV.comment_num, + LV.thumbs_up_num, LV.weight, LV.audit_pass_time, LV.update_time, @@ -545,4 +607,69 @@ <if test="query.authorId != null and query.authorId != ''">AND LV.author_id = #{query.authorId}</if> <if test="query.status != null and query.status != ''">AND LV.status = #{query.status}</if> </select> + + <resultMap id="EsResultMap" type="cn.lili.modules.lmk.domain.es.VideoIndex"> + <id column="id" property="id"/> + <result column="author_id" property="authorId" /> + <result column="authorName" property="authorName" /> + <result column="authorAvatar" property="authorAvatar" /> + <result column="cover_url" property="coverFileKey" /> + <result column="video_file_key" property="videoFileKey" /> + <result column="video_fit" property="videoFit" /> + <result column="video_duration" property="videoDuration" /> + <result column="title" property="title" /> + <result column="status" property="status" /> + <result column="recommend" property="recommend" /> + <result column="video_content_type" property="videoContentType" /> + <result column="video_type" property="videoType" /> + <result column="video_imgs" property="videoImgs" /> + <collection property="goodsList" column="id" select="getVideoGoods" ofType="cn.lili.modules.lmk.domain.vo.VideoGoodsDetailVO"/> + <collection property="tagList" column="id" select="getVideoTags" ofType="cn.lili.modules.lmk.domain.vo.SimpleVideoTagVO"/> + </resultMap> + + <select id="getVideoTags" resultType="cn.lili.modules.lmk.domain.vo.SimpleVideoTagVO"> + SELECT + LVT.id, + LVT.tag_name as tagName + FROM + lmk_video_tag_ref LVTR + INNER JOIN lmk_video_tag LVT ON LVTR.video_tag_id = LVT.id AND LVT.delete_flag = 0 + WHERE + LVTR.video_id = #{id} + </select> + + <select id="getEsPage" parameterType="int" resultMap="EsResultMap"> + SELECT + LV.author_id, + LV.cover_url, + LV.video_fit, + LV.video_duration, + LV.video_file_key, + LV.title, + LV.goods_view_num, + LV.goods_order_num, + LV.recommend, + LV.status, + LV.play_num, + LV.comment_num, + LV.collect_num, + LV.thumbs_up_num, + LV.weight, + LV.audit_pass_time, + LV.update_time, + LV.create_time, + LV.video_content_type, + LV.video_type, + LV.video_imgs, + LV.id, + LM.nick_name as authorName, + LM.face as authorAvatar + FROM + lmk_video LV + LEFT JOIN li_member LM ON LV.author_id = LM.id + WHERE + LV.delete_flag = 0 + LIMIT #{start}, #{pageSize} + </select> + </mapper> diff --git a/lmk-job/src/main/java/cn/lili/job/VideoJob.java b/lmk-job/src/main/java/cn/lili/job/VideoJob.java index 15035f1..e2df6d1 100644 --- a/lmk-job/src/main/java/cn/lili/job/VideoJob.java +++ b/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); + } + } + } diff --git a/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java b/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java index b496f0d..364f2cd 100644 --- a/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java +++ b/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java @@ -1,5 +1,6 @@ package cn.lili.controller.lmk; +import cn.lili.elasticsearch.EsSuffix; import cn.lili.group.Update; import cn.lili.group.Add; import cn.lili.modules.lmk.domain.form.VideoAuditingForm; @@ -7,6 +8,8 @@ import cn.lili.modules.lmk.domain.form.VideoRecommendForm; import cn.lili.modules.lmk.domain.form.WxVideoForm; import cn.lili.modules.lmk.domain.query.ManagerVideoQuery; +import cn.lili.modules.lmk.service.EsService; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.validation.annotation.Validated; import lombok.RequiredArgsConstructor; import java.util.List; @@ -32,17 +35,8 @@ private final VideoService videoService; - @PostMapping - @ApiOperation(value = "娣诲姞", notes = "娣诲姞") - public Result add(@RequestBody @Validated(Add.class) WxVideoForm form) { - return videoService.add(form); - } - - @PutMapping - @ApiOperation(value = "淇敼", notes = "淇敼") - public Result update(@RequestBody @Validated(Update.class) WxVideoForm form) { - return videoService.update(form); - } + @Qualifier("videoEsServiceImpl") + private final EsService esService; @DeleteMapping("/{id}") @ApiOperation(value = "ID鍒犻櫎", notes = "ID鍒犻櫎") @@ -97,4 +91,10 @@ public Result down(@RequestBody @Validated VideoDownForm form) { return videoService.down(form); } + + @PostMapping("/recreate/es/index") + @ApiOperation(value = "閲嶅缓es绱㈠紩", notes = "閲嶅缓es绱㈠紩") + public Result recreateEsIndex() { + return videoService.recreateEsIndex(); + } } -- Gitblit v1.8.0