CommentService.java 10.3 KB
package com.tanpu.community.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.tanpu.biz.common.enums.community.CommentTypeEnum;
import com.tanpu.biz.common.enums.community.ReportStatusEnum;
import com.tanpu.common.exception.BizException;
import com.tanpu.common.uuid.UuidGenHelper;
import com.tanpu.community.api.beans.qo.ThemeQo;
import com.tanpu.community.api.beans.req.theme.ForwardThemeReq;
import com.tanpu.community.api.beans.vo.feign.fatools.UserInfoResp;
import com.tanpu.community.api.enums.DeleteTagEnum;
import com.tanpu.community.cache.RedisCache;
import com.tanpu.community.dao.entity.community.CommentEntity;
import com.tanpu.community.dao.entity.community.TimesCountEntity;
import com.tanpu.community.dao.mapper.community.CommentMapper;
import com.tanpu.community.util.ConvertUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.tanpu.community.api.constants.RedisKeyConstant.*;

@Service
public class CommentService {

    @Resource
    private CommentMapper commentMapper;

    @Resource
    private UuidGenHelper uuidGenHelper;

    @Resource
    private RedisCache redisCache;
    @Resource
    private FeignService feignService;

    @Transactional
    public void insertComment(CommentEntity commentEntity) {
        commentEntity.setCommentId(uuidGenHelper.getUuidStr());
        commentMapper.insert(commentEntity);
        //失效缓存
        evictThemeCache(commentEntity.getThemeId());

    }


    public CommentEntity queryByIdIncludeDelete(String commmentId) {
        return commentMapper.selectOne(new LambdaQueryWrapper<CommentEntity>()
                .eq(CommentEntity::getCommentId, commmentId));
    }

    //统计主题集合的评论量
    public Integer getTotalCountByThemeIds(List<String> themeIds) {
        if (CollectionUtils.isEmpty(themeIds)) {
            return 0;
        }
        return commentMapper.selectList((new LambdaQueryWrapper<CommentEntity>()
                .in(CommentEntity::getThemeId, themeIds))
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED))
                .size();
    }

    //统计主题集合的评论量
    public Integer getCommentCountByThemeId(String themeId) {
        return commentMapper.selectCount((new LambdaQueryWrapper<CommentEntity>()
                .eq(CommentEntity::getThemeId, themeId))
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED));
    }

    public Integer getCommentCountByThemeIds(List<String> themeIds) {
        if (CollectionUtils.isEmpty(themeIds)) {
            return 0;
        }
        return commentMapper.selectCount((new LambdaQueryWrapper<CommentEntity>()
                .in(CommentEntity::getThemeId, themeIds))
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED));
    }

    public Integer getCommentCountByThemeIds(List<String> themeIds, Date startDate, Date endDate) {
        return commentMapper.selectCount((new LambdaQueryWrapper<CommentEntity>()
                .in(CommentEntity::getThemeId, themeIds))
                .gt(CommentEntity::getCreateTime, startDate)
                .lt(CommentEntity::getCreateTime, endDate)
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED));
    }


    //统计主题集合的评论量
    public Map<String, Integer> getCountMapByThemeIds(List<String> themeIds) {
        if (CollectionUtils.isEmpty(themeIds)) {
            return new HashMap<>();
        }
        LambdaQueryWrapper<CommentEntity> wrapper = (new LambdaQueryWrapper<CommentEntity>()
                .in(CommentEntity::getThemeId, themeIds))
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED)
                .groupBy(CommentEntity::getThemeId);
        return commentMapper.selectCountByThemeIds(wrapper).stream()
                .collect(Collectors.toMap(TimesCountEntity::getId, TimesCountEntity::getTimes));
    }

    /**
     * 获取单个帖子的所有评论
     *
     * @param themeId
     * @return
     */
    public List<CommentEntity> selectByThemeId(String themeId) {
        return redisCache.getList(StringUtils.joinWith("_", CACHE_COMMENT_THEMEID, themeId),
                60, () -> {
                    LambdaQueryWrapper<CommentEntity> queryWrapper = new LambdaQueryWrapper<CommentEntity>()
                            .eq(CommentEntity::getThemeId, themeId)
                            .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode())
                            .orderByDesc(CommentEntity::getCreateTime);
                    return commentMapper.selectList(queryWrapper);
                }, new TypeReference<List<CommentEntity>>() {
                });
    }


    public List<CommentEntity> queryCommentsByUserId(String userId, String lastId, Integer pageSize) {
        LambdaQueryWrapper<CommentEntity> queryWrapper = new LambdaQueryWrapper<CommentEntity>()
                .eq(CommentEntity::getAuthorId, userId)
                .eq(CommentEntity::getCommentType, CommentTypeEnum.THEME.getCode())
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode())
                .orderByDesc(CommentEntity::getCreateTime);
        if (StringUtils.isNotEmpty(lastId)) {
            CommentEntity commentEntity = commentMapper.selectOne(new LambdaQueryWrapper<CommentEntity>()
                    .eq(CommentEntity::getCommentId, lastId));
            if (commentEntity == null) throw new BizException("评论未找到,id:" + lastId);
            queryWrapper.lt(CommentEntity::getCreateTime, commentEntity.getCreateTime());
        }
        if (pageSize != null) {
            queryWrapper.last("limit " + pageSize);
        }
        return commentMapper.selectList(queryWrapper);
    }

    //修改举报状态,可修改已删除
    public void updateReportStatus(String commentId) {
        CommentEntity commentEntity = queryByIdIncludeDelete(commentId);
        if (commentEntity == null) {
            throw new BizException("评论未找到,id:" + commentId);
        }
        commentEntity.setReportStatus(ReportStatusEnum.REPORTED.getCode());
        commentMapper.updateById(commentEntity);
        //失效缓存
        evictThemeCache(commentEntity.getThemeId());

    }

    //删除评论
    @Transactional
    public CommentEntity delete(String commentId, String userId) {
        CommentEntity commentEntity = this.queryByIdIncludeDelete(commentId);
        if (commentEntity == null || !commentEntity.getAuthorId().equals(userId)) {
            throw new BizException("删除评论与用户不匹配,commentId:" + commentId + ",userId:" + userId);
        }
        commentEntity.setDeleteTag(DeleteTagEnum.DELETED.getCode());
        commentMapper.updateById(commentEntity);
        //失效缓存
        evictThemeCache(commentEntity.getThemeId());
        return commentEntity;
    }

    // 失效关联主题缓存
    private void evictThemeCache(String themeId) {
        // 评论内容
        redisCache.evict(StringUtils.joinWith("_", CACHE_COMMENT_THEMEID, themeId));
        // 主题内容
        redisCache.evict(StringUtils.joinWith("_", CACHE_THEME_ID, themeId));
        // 评论数
        redisCache.evict(StringUtils.joinWith("_", THEME_COMMENT_COUNT, themeId));
    }

    public List<CommentEntity> queryAll() {
        return commentMapper.selectList(new LambdaQueryWrapper<CommentEntity>()
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode())
                .orderByAsc(CommentEntity::getCreateTime));
    }

    public CommentEntity queryByCommentId(String commentId) {
        return commentMapper.selectOne(new LambdaQueryWrapper<CommentEntity>().eq(CommentEntity::getCommentId, commentId));
    }

    public String forwardSyncComment(ForwardThemeReq req, String userId) {
        CommentEntity commentEntity = CommentEntity.builder()
                .themeId(req.getFormerThemeId())
                .authorId(userId)
                .content(req.getContent().get(0).getValue())
                .commentType(CommentTypeEnum.THEME.getCode())
                .build();

        this.insertComment(commentEntity);

        return commentEntity.getCommentId();


    }

    public void queryRecentComments(List<ThemeQo> themes) {
        if (CollectionUtils.isEmpty(themes)) return;

        List<String> themeIds = themes.stream().map(ThemeQo::getThemeId).collect(Collectors.toList());

        List<CommentEntity> commentEntities = commentMapper.selectList(new LambdaQueryWrapper<CommentEntity>()
                .in(CommentEntity::getThemeId, themeIds)
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode())
                .orderByDesc(CommentEntity::getCreateTime));

        LinkedHashMap<String, List<CommentEntity>> collect = commentEntities.stream().collect(Collectors.groupingBy(CommentEntity::getThemeId, LinkedHashMap::new, Collectors.toList()));
        // 查询用户信息
        List<String> authorIds = new ArrayList<>(commentEntities.stream().map(CommentEntity::getAuthorId).collect(Collectors.toSet()));
        List<UserInfoResp> queryUsersListNew = feignService.getUserList(authorIds);
        Map<String, String> nameMap = queryUsersListNew.stream().collect(Collectors.toMap(UserInfoResp::getUserId, UserInfoResp::getNickName));

        for (ThemeQo theme : themes) {
            if (collect.containsKey(theme.getThemeId())) {
                List<CommentEntity> comments = collect.get(theme.getThemeId());
                theme.setRecentComments(ConvertUtil.comment2Simple(comments.subList(0, Math.min(comments.size(), 3)), nameMap));
            }
        }

    }

    /**
     * 获取对该评论的回复,如果没有则返回空对象
     * @param commentId
     * @return
     */
    public List<CommentEntity> queryReplyForComment(String commentId) {
        List<CommentEntity> replies = commentMapper.selectList(new LambdaQueryWrapper<CommentEntity>()
                .eq(CommentEntity::getReplyId, commentId)
                .eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED));
        return replies;
    }
}