Administrator
2025-07-22 48e926f7f767a6d65cab2b52a057d345c2ee7e0e
feat(mall): 为社交活动添加点赞和收藏功能

- 在 ClothesSocial 模型中添加 likeCnt 和 collectCnt 字段
- 实现点赞和收藏的 RabbitMQ 消息发送和接收逻辑- 更新社交活动详情接口,增加点赞和收藏数量
- 优化社交活动列表接口,移除冗余的点赞和收藏计算逻辑
13 files modified
244 ■■■■ changed files
src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java 32 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/ClothesSocial.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/HappyActivityService.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiClothesSocialServiceImpl.java 101 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ClothesTypeServiceImpl.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java 28 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java 14 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/ClothesSocialMapper.xml 1 ●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/clothesType/socialAdd.html 16 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/clothesType/socialUpdate.html 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
@@ -238,4 +238,36 @@
        return BindingBuilder.bind(activityOrderCheckQueue()).to(activityOrderCheckExchange()).with(RabbitQueueEnum.ACTIVITY_ORDER_ITEM_CHECK.getRoute());
    }
    @Bean
    public DirectExchange clothesAddLikeExchange() {
        return new DirectExchange(RabbitQueueEnum.CLOTHES_ADD_LIKE.getExchange());
    }
    @Bean
    public Queue clothesAddLikeQueue() {
        return new Queue(RabbitQueueEnum.CLOTHES_ADD_LIKE.getQueue());
    }
    @Bean
    public Binding clothesAddLikeBind() {
        return BindingBuilder.bind(clothesAddLikeQueue()).to(clothesAddLikeExchange()).with(RabbitQueueEnum.CLOTHES_ADD_LIKE.getRoute());
    }
    @Bean
    public DirectExchange clothesAddCollectExchange() {
        return new DirectExchange(RabbitQueueEnum.CLOTHES_ADD_COLLECT.getExchange());
    }
    @Bean
    public Queue clothesAddCollectQueue() {
        return new Queue(RabbitQueueEnum.CLOTHES_ADD_COLLECT.getQueue());
    }
    @Bean
    public Binding clothesAddCollectBind() {
        return BindingBuilder.bind(clothesAddCollectQueue()).to(clothesAddCollectExchange()).with(RabbitQueueEnum.CLOTHES_ADD_COLLECT.getRoute());
    }
}
src/main/java/cc/mrbird/febs/mall/entity/ClothesSocial.java
@@ -21,6 +21,8 @@
     `state` int(11) DEFAULT '0' COMMENT '状态 0-不展示 1-展示',
     `order_cnt` int(11) DEFAULT '0' COMMENT '排序',
     `comment_state` int(11) DEFAULT '0' COMMENT '是否允许评论 0-不允许 1-允许',
     `like_cnt` int(11) DEFAULT '0',
     `collect_cnt` int(11) DEFAULT '0',
     */
    private Long memberId;
    private String name;
@@ -32,6 +34,8 @@
    private Integer hotState;
    private Integer orderCnt;
    private Integer commentState;
    private Integer likeCnt;
    private Integer collectCnt;
    @TableField(exist = false)
    private String thumbs;
src/main/java/cc/mrbird/febs/mall/service/HappyActivityService.java
@@ -79,4 +79,8 @@
    FebsResponse addComment(ApiPayOrderAddCommentDto dto);
    List<ApiActivityCommentVo> commentByActivityId(ApiActivityCommentDto dto);
    void getAddLike(Long socialId);
    void getAddCollect(Long socialId);
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiClothesSocialServiceImpl.java
@@ -10,6 +10,7 @@
import cc.mrbird.febs.mall.service.ApiClothesSocialService;
import cc.mrbird.febs.mall.vo.activity.ApiScCategoryInfoVo;
import cc.mrbird.febs.mall.vo.clothes.*;
import cc.mrbird.febs.rabbit.producter.AgentProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
@@ -61,6 +62,7 @@
    private final ClothesLocationRemarkMapper clothesLocationRemarkMapper;
    private final ClothesPatternRemarkMapper clothesPatternRemarkMapper;
    private final ClothesSocialCommentMapper clothesSocialCommentMapper;
    private final AgentProducer agentProducer;
    @Override
@@ -120,32 +122,32 @@
        // 调用Mapper方法获取活动分页数据
        Page<ApiAllSocialVo> voPage = clothesSocialMapper.selectPageInSocial(page, dto);
        List<ApiAllSocialVo> vos = voPage.getRecords();
        if (CollUtil.isNotEmpty(vos)) {
            Set<Long> socialIds = vos.stream()
                    .map(ApiAllSocialVo::getId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            if (CollUtil.isNotEmpty(socialIds)) {
                List<ClothesSocialFollow> clothesSocialFollows = clothesSocialFollowMapper.selectList(
                        Wrappers.lambdaQuery(ClothesSocialFollow.class)
                                .select(ClothesSocialFollow::getId, ClothesSocialFollow::getSourceId)
                                .in(ClothesSocialFollow::getSourceId, socialIds)
                                .eq(ClothesSocialFollow::getSourceType, SocialSourceTypeEnum.SOCIAL.getValue())
                );
                Map<Long, Long> likeCountBySocialIdMap = new HashMap<>();
                if (CollUtil.isNotEmpty(clothesSocialFollows)) {
                    likeCountBySocialIdMap = clothesSocialFollows.stream()
                            .collect(Collectors.groupingBy(ClothesSocialFollow::getSourceId, Collectors.counting()));
                }
                for (ApiAllSocialVo item : vos){
                    item.setLikeCnt(likeCountBySocialIdMap.getOrDefault(item.getId(), 0L).intValue());
                }
            }
        }
//        List<ApiAllSocialVo> vos = voPage.getRecords();
//        if (CollUtil.isNotEmpty(vos)) {
//            Set<Long> socialIds = vos.stream()
//                    .map(ApiAllSocialVo::getId)
//                    .filter(Objects::nonNull)
//                    .collect(Collectors.toSet());
//
//            if (CollUtil.isNotEmpty(socialIds)) {
//                List<ClothesSocialFollow> clothesSocialFollows = clothesSocialFollowMapper.selectList(
//                        Wrappers.lambdaQuery(ClothesSocialFollow.class)
//                                .select(ClothesSocialFollow::getId, ClothesSocialFollow::getSourceId)
//                                .in(ClothesSocialFollow::getSourceId, socialIds)
//                                .eq(ClothesSocialFollow::getSourceType, SocialSourceTypeEnum.SOCIAL.getValue())
//                );
//
//                Map<Long, Long> likeCountBySocialIdMap = new HashMap<>();
//                if (CollUtil.isNotEmpty(clothesSocialFollows)) {
//                    likeCountBySocialIdMap = clothesSocialFollows.stream()
//                            .collect(Collectors.groupingBy(ClothesSocialFollow::getSourceId, Collectors.counting()));
//                }
//
//                for (ApiAllSocialVo item : vos){
//                    item.setLikeCnt(likeCountBySocialIdMap.getOrDefault(item.getId(), 0L).intValue());
//                }
//            }
//        }
        return new FebsResponse().success().data(voPage);
    }
@@ -165,6 +167,8 @@
            apiSocialInfoVo.setContent(clothesSocial.getContent());
            apiSocialInfoVo.setCreatedTime(clothesSocial.getCreatedTime());
            apiSocialInfoVo.setCommentState(clothesSocial.getCommentState());
            apiSocialInfoVo.setLikeCnt(clothesSocial.getLikeCnt());
            apiSocialInfoVo.setCollectCnt(clothesSocial.getCollectCnt());
            List<ClothesSocialFile> clothesSocialFiles = clothesSocialFileMapper.selectList(
                    Wrappers.lambdaQuery(ClothesSocialFile.class)
@@ -249,19 +253,24 @@
                apiSocialInfoVo.setMuse(apiSocialMuseVo);
                List<ClothesSocialFollow> clothesSocialFollows = clothesSocialFollowMapper.selectList(
                        Wrappers.lambdaQuery(ClothesSocialFollow.class)
                                .select(ClothesSocialFollow::getType)
                                .eq(ClothesSocialFollow::getSourceId, socialId)
                                .eq(ClothesSocialFollow::getSourceType, SocialSourceTypeEnum.SOCIAL.getValue())
                );
                if (CollUtil.isNotEmpty(clothesSocialFollows)){
                    Map<Integer, Long> collect = clothesSocialFollows.stream()
                            .collect(Collectors.groupingBy(ClothesSocialFollow::getType, Collectors.counting()));
                    apiSocialInfoVo.setLikeCnt(collect.getOrDefault(SocialTypeEnum.LIKE.getValue(), 0L).intValue());
                    apiSocialInfoVo.setCollectCnt(collect.getOrDefault(SocialTypeEnum.COLLECT.getValue(), 0L).intValue());
                }
//                Integer likeCnt = clothesSocial.getLikeCnt();
//                Integer collectCnt = clothesSocial.getCollectCnt();
//
//                List<ClothesSocialFollow> clothesSocialFollows = clothesSocialFollowMapper.selectList(
//                        Wrappers.lambdaQuery(ClothesSocialFollow.class)
//                                .select(ClothesSocialFollow::getType)
//                                .eq(ClothesSocialFollow::getSourceId, socialId)
//                                .eq(ClothesSocialFollow::getSourceType, SocialSourceTypeEnum.SOCIAL.getValue())
//                );
//                if (CollUtil.isNotEmpty(clothesSocialFollows)){
//
//                    Map<Integer, Long> collect = clothesSocialFollows.stream()
//                            .collect(Collectors.groupingBy(ClothesSocialFollow::getType, Collectors.counting()));
//                    likeCnt = likeCnt + collect.getOrDefault(SocialTypeEnum.LIKE.getValue(), 0L).intValue();
//                    collectCnt = collectCnt + collect.getOrDefault(SocialTypeEnum.COLLECT.getValue(), 0L).intValue();
//                }
//                apiSocialInfoVo.setLikeCnt(likeCnt);
//                apiSocialInfoVo.setCollectCnt(collectCnt);
                List<ClothesSocialComment> clothesSocialComments = clothesSocialCommentMapper.selectList(
                        Wrappers.lambdaQuery(ClothesSocialComment.class)
@@ -402,6 +411,8 @@
            clothesSocialFollow.setSourceId(socialId);
            clothesSocialFollow.setType(SocialTypeEnum.LIKE.getValue());
            clothesSocialFollowMapper.insert(clothesSocialFollow);
            agentProducer.sendAddLike(socialId);
        }
        return new FebsResponse().success().message("操作成功");
    }
@@ -419,6 +430,8 @@
            clothesSocialFollow.setSourceOptionId(dto.getCommentId());
            clothesSocialFollow.setType(SocialTypeEnum.LIKE.getValue());
            clothesSocialFollowMapper.insert(clothesSocialFollow);
            agentProducer.sendAddCollect(socialId);
        }
        return new FebsResponse().success().message("操作成功");
    }
@@ -430,6 +443,16 @@
        Long socialId = dto.getSocialId();
        ClothesSocial clothesSocial = clothesSocialMapper.selectById(socialId);
        if(ObjectUtil.isNotNull(clothesSocial)){
            List<ClothesSocialFollow> clothesSocialFollows = clothesSocialFollowMapper.selectList(
                    Wrappers.lambdaQuery(ClothesSocialFollow.class)
                            .eq(ClothesSocialFollow::getMemberId, memberId)
                            .eq(ClothesSocialFollow::getSourceType, SocialSourceTypeEnum.SOCIAL.getValue())
                            .eq(ClothesSocialFollow::getSourceId, socialId)
                            .eq(ClothesSocialFollow::getType, SocialTypeEnum.COLLECT.getValue())
            );
            if (CollUtil.isNotEmpty(clothesSocialFollows)){
                return new FebsResponse().success().message("已收藏");
            }
            ClothesSocialFollow clothesSocialFollow = new ClothesSocialFollow();
            clothesSocialFollow.setMemberId(memberId);
            clothesSocialFollow.setSourceType(SocialSourceTypeEnum.SOCIAL.getValue());
src/main/java/cc/mrbird/febs/mall/service/impl/ClothesTypeServiceImpl.java
@@ -977,6 +977,8 @@
        entity.setContent(dto.getContent());
        entity.setIndexFile(dto.getIndexFile());
        entity.setOrderCnt(dto.getOrderCnt());
        entity.setLikeCnt(dto.getLikeCnt());
        entity.setCollectCnt(dto.getCollectCnt());
        clothesSocialMapper.updateById(entity);
src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java
@@ -29,6 +29,7 @@
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
@@ -62,6 +63,7 @@
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final HappyMemberLevelMapper happyMemberLevelMapper;
    private final IMallMoneyFlowService mallMoneyFlowService;
    private final ClothesSocialMapper clothesSocialMapper;
    @Override
    public FebsResponse activityList(ApiActivityInfoDto dto) {
@@ -1117,6 +1119,32 @@
    }
    @Override
    public void getAddLike(Long socialId) {
        ClothesSocial clothesSocial = clothesSocialMapper.selectById(socialId);
        if (ObjectUtil.isNotNull(clothesSocial)){
            clothesSocialMapper.update(null,
                    Wrappers.lambdaUpdate(ClothesSocial.class)
                    .set(ClothesSocial::getLikeCnt, clothesSocial.getLikeCnt()+1)
                    .eq(ClothesSocial::getId, socialId)
                    );
        }
    }
    @Override
    public void getAddCollect(Long socialId) {
        ClothesSocial clothesSocial = clothesSocialMapper.selectById(socialId);
        if (ObjectUtil.isNotNull(clothesSocial)){
            clothesSocialMapper.update(null,
                    Wrappers.lambdaUpdate(ClothesSocial.class)
                            .set(ClothesSocial::getCollectCnt, clothesSocial.getCollectCnt()+1)
                            .eq(ClothesSocial::getId, socialId)
            );
        }
    }
    @Override
    public FebsResponse voteActivityHot(Long id) {
        ApiVoteActivityHotVo apiVoteActivityHotVo = new ApiVoteActivityHotVo();
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -20,4 +20,6 @@
    ;
    public static final String CLOTHES_ORDER_CANCEL_DELAY = "queue_order_delay_qay_clothes";
    public static final String CLOTHES_ADD_LIKE = "queue_clothes_add_like";
    public static final String CLOTHES_ADD_COLLECT = "queue_clothes_add_collect";
}
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
@@ -138,4 +138,24 @@
            log.error("核销活动门票异常", e);
        }
    }
    @RabbitListener(queues = QueueConstants.CLOTHES_ADD_LIKE)
    public void getAddLike(Long socialId) {
        log.info("点赞:{}", socialId);
        try {
            happyActivityService.getAddLike(socialId);
        } catch (Exception e) {
            log.error("点赞异常", e);
        }
    }
    @RabbitListener(queues = QueueConstants.CLOTHES_ADD_COLLECT)
    public void getAddCollect(Long socialId) {
        log.info("收藏:{}", socialId);
        try {
            happyActivityService.getAddCollect(socialId);
        } catch (Exception e) {
            log.error("收藏异常", e);
        }
    }
}
src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
@@ -7,6 +7,8 @@
public enum RabbitQueueEnum {
    CLOTHES_ADD_COLLECT("exchange_clothes_add_collect", "route_key_clothes_add_collect", QueueConstants.CLOTHES_ADD_COLLECT),
    CLOTHES_ADD_LIKE("exchange_clothes_add_like", "route_key_clothes_add_like", QueueConstants.CLOTHES_ADD_LIKE),
    ACTIVITY_ORDER_ITEM_CHECK("exchange_activity_order_item_check", "route_key_activity_order_item_check", QueueConstants.ACTIVITY_ORDER_ITEM_CHECK),
    DEFAULT("exchange_default_qay", "route_key_default_qay", "queue_default_qay"),
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -122,4 +122,18 @@
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitQueueEnum.ACTIVITY_ORDER_ITEM_CHECK.getExchange(), RabbitQueueEnum.ACTIVITY_ORDER_ITEM_CHECK.getRoute(), orderId, correlationData);
    }
    public void sendAddLike(Long socialId) {
        log.info("点赞:{}", socialId);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitQueueEnum.CLOTHES_ADD_LIKE.getExchange(), RabbitQueueEnum.CLOTHES_ADD_LIKE.getRoute(), socialId, correlationData);
    }
    public void sendAddCollect(Long socialId) {
        log.info("收藏:{}", socialId);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitQueueEnum.CLOTHES_ADD_COLLECT.getExchange(), RabbitQueueEnum.CLOTHES_ADD_COLLECT.getRoute(), socialId, correlationData);
    }
}
src/main/resources/mapper/modules/ClothesSocialMapper.xml
@@ -38,6 +38,7 @@
        b.avatar as memberAvatar,
        a.id as id,
        a.name as name,
        a.like_cnt as likeCnt,
        a.index_file as indexFile
        from clothes_social a
        left join mall_member b on a.member_id = b.id
src/main/resources/templates/febs/views/modules/clothesType/socialAdd.html
@@ -97,6 +97,22 @@
                                        </div>
                                    </div>
                                </div>
                                <div class="layui-row layui-col-space10 layui-form-item">
                                    <div class="layui-col-lg6">
                                        <label class="layui-form-label febs-form-item-require">点赞:</label>
                                        <div class="layui-input-block">
                                            <input type="text" name="likeCnt" lay-verify="required"
                                                   placeholder="" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-col-lg6">
                                        <label class="layui-form-label febs-form-item-require">收藏:</label>
                                        <div class="layui-input-block">
                                            <input type="text" name="collectCnt" lay-verify="required"
                                                   placeholder="" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                </div>
                                <div class="layui-form-item">
                                    <label class="layui-form-label febs-form-item-require">内容:</label>
                                    <div class="layui-input-block">
src/main/resources/templates/febs/views/modules/clothesType/socialUpdate.html
@@ -107,6 +107,22 @@
                                        </div>
                                    </div>
                                </div>
                                <div class="layui-row layui-col-space10 layui-form-item">
                                    <div class="layui-col-lg6">
                                        <label class="layui-form-label febs-form-item-require">点赞:</label>
                                        <div class="layui-input-block">
                                            <input type="text" name="likeCnt" lay-verify="required"
                                                   placeholder="" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-col-lg6">
                                        <label class="layui-form-label febs-form-item-require">收藏:</label>
                                        <div class="layui-input-block">
                                            <input type="text" name="collectCnt" lay-verify="required"
                                                   placeholder="" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                </div>
                                <div class="layui-form-item">
                                    <label class="layui-form-label febs-form-item-require">内容:</label>
                                    <div class="layui-input-block">
@@ -364,6 +380,8 @@
                "name": activity.name,
                "orderCnt": activity.orderCnt,
                "indexFile": activity.indexFile,
                "likeCnt": activity.likeCnt,
                "collectCnt": activity.collectCnt,
                "thumbs": thumbs
            });