package com.tanpu.community.manager; import com.tanpu.common.exception.BizException; import com.tanpu.common.util.JsonUtil; import com.tanpu.community.api.beans.qo.ESThemeQo; import com.tanpu.community.api.beans.qo.FormerThemeQo; import com.tanpu.community.api.beans.qo.ThemeContentQo; import com.tanpu.community.api.beans.qo.ThemeQo; import com.tanpu.community.api.beans.req.homepage.QueryRecordThemeReq; import com.tanpu.community.api.beans.req.theme.*; import com.tanpu.community.api.beans.resp.CreateThemeResp; import com.tanpu.community.api.beans.resp.ThemeFullSearchResp; import com.tanpu.community.api.enums.*; import com.tanpu.community.dao.entity.community.*; import com.tanpu.community.dao.entity.user.UserInfoEntity; import com.tanpu.community.service.*; import com.tanpu.community.service.base.ESService; import com.tanpu.community.util.ConvertUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service public class ThemeManager { @Resource private ThemeService themeService; @Autowired private CollectionService collectionService; @Autowired private CommentService commentService; @Autowired private FollowRelService followRelService; @Autowired private BlackListService blackListService; @Autowired private UserInfoService userInfoService; @Autowired private ThemeAttachmentService themeAttachmentService; @Resource private BatchFeignCallService batchFeignCallService; @Autowired private VisitSummaryService visitSummaryService; @Autowired private RankService rankService; @Autowired private ESService esService; public ThemeFullSearchResp themeFullSearch(String keyword, Integer pageNo, Integer pageSize, List<String> excludeIds, String userId) { Integer from = (pageNo - 1) * pageSize; ThemeFullSearchResp resp = new ThemeFullSearchResp(); // 按时间倒叙查询 // todo redis List<ESThemeQo> esIds = esService.queryThemeIdByContentAndTitle(keyword, from, pageSize * 5); if (esIds.isEmpty()) { return resp; } // 排除已经展示过的id List<String> filterEsIds = esIds.stream().map(ESThemeQo::getThemeId).filter(tId -> { return !excludeIds.contains(tId); }).limit(pageSize).collect(Collectors.toList()); resp.themes = convertEntityToQo(themeService.queryByThemeIds(filterEsIds), userId); resp.excludeIds.addAll(filterEsIds); return resp; } @Transactional public CreateThemeResp publishTheme(CreateThemeReq req, String userId) { //TODO 敏感词过滤 //保存主题表 ThemeEntity themeEntity = new ThemeEntity(); BeanUtils.copyProperties(req, themeEntity); themeEntity.setAuthorId(userId); themeEntity.setContent(JsonUtil.toJson(req.getContent())); if (StringUtils.isEmpty(req.getEditThemeId())) { //新建 themeService.insertTheme(themeEntity); } else { //修改 themeService.update(themeEntity, req.getEditThemeId()); themeEntity.setThemeId(req.getEditThemeId()); } //保存附件表 List<ThemeAttachmentEntity> themeAttachments = ConvertUtil.themeReqToAttachmentList(req, themeEntity.getThemeId()); if (StringUtils.isNotEmpty(req.getEditThemeId())) { //修改需要刪除 themeAttachmentService.deleteByThemeId(req.getEditThemeId()); } themeAttachmentService.insertList(themeAttachments); try { esService.insertOrUpdateTheme(ConvertUtil.convert(themeEntity)); } catch (Exception e) { log.error("error in save theme to ES. themeId:{}, error:{}", themeEntity.getThemeId(), ExceptionUtils.getStackTrace(e)); } return CreateThemeResp.builder().themeId(themeEntity.getThemeId()).build(); } /** * 返回主题列表 * * @param req * @param userId * @return */ public List<ThemeQo> queryThemes(ThemeListReq req, String userId) { List<ThemeEntity> themeEntities = new ArrayList<>(); if (ThemeListTypeEnum.RECOMMEND.getCode().equals(req.getType())) { // TODO:推荐 // themeEntities = themeService.selectExcludeUser(userId, req.getLastId(), req.getPageSize()); List<String> recommendThemeIds = rankService.getHotAndNewThemes(100, 100); themeEntities = themeService.queryByThemeIdsExcludeUser( recommendThemeIds,userId, req.getLastId(), req.getPageSize()); } else if (ThemeListTypeEnum.FOLLOW.getCode().equals(req.getType())) { //根据关注列表查询 List<String> fansList = followRelService.queryFansByFollowerId(userId); themeEntities = themeService.queryByUserIds(fansList, req.getLastId(), req.getPageSize()); } else if (ThemeListTypeEnum.TOPIC_HOT.getCode().equals(req.getType())) { //TODO 根据话题查询热门 if (StringUtils.isEmpty(req.getTopicId())) throw new BizException("TopicId为空"); themeEntities = themeService.queryByTopic(req.getTopicId(), req.getLastId(), req.getPageSize()); } else if (ThemeListTypeEnum.TOPIC_LATEST.getCode().equals(req.getType())) { //TODO 根据话题查询最新 if (StringUtils.isEmpty(req.getTopicId())) throw new BizException("TopicId为空"); themeEntities = themeService.queryByTopic(req.getTopicId(), req.getLastId(), req.getPageSize()); } //组装详情 return convertEntityToQo(themeEntities, userId); } public List<ThemeQo> searchThemes(ThemeSearchReq req, String userId) { List<ThemeEntity> themeEntities = themeService.search(req.getKeyword(), req.getLastId(), req.getPageSize()); return convertEntityToQo(themeEntities, userId); } // 返回用户发布、回复、收藏的主题列表 public List<ThemeQo> queryThemesByUser(QueryRecordThemeReq req, String userId) { List<ThemeEntity> themeEntities = Collections.emptyList(); switch (req.getRecordType()) { case 1://发布 themeEntities = themeService.queryThemesByUserId(req.getUserId(), req.getLastId(), req.getPageSize()); break; case 2://回复 List<ThemeQo> commentThemeList = new ArrayList<>(); //评论列表 List<CommentEntity> commentEntities = commentService.queryThemesByUserId(req.getUserId(), req.getLastId(), req.getPageSize()); //当前用户信息 UserInfoEntity userInfoEntity = userInfoService.queryUserById(req.getUserId()); Set<String> replyThemeIds = commentEntities.stream().map(CommentEntity::getThemeId).collect(Collectors.toSet()); if (CollectionUtils.isEmpty(replyThemeIds)) { return commentThemeList; } themeEntities = themeService.queryByThemeIds(new ArrayList<>(replyThemeIds)); List<ThemeQo> themeQos = convertEntityToQo(themeEntities, userId); //组装附件 batchFeignCallService.getAttachDetailByBatch(themeQos); //主题列表 Map<String, ThemeQo> themeMap = themeQos.stream() .collect(Collectors.toMap(ThemeQo::getThemeId, o -> o)); //主题+评论封装转发对象 for (CommentEntity commentEntity : commentEntities) { String themeId = commentEntity.getThemeId(); //评论内容包装到ThemeContentQo里 ThemeContentQo commentContent = ThemeContentQo.builder() .type(RelTypeEnum.TEXT.type) .value(commentEntity.getContent()) .build(); //原主题包装到FormerThemeQo中 ThemeQo themeQo = themeMap.get(themeId); FormerThemeQo f = ConvertUtil.themeQo2FormerThemeQo(themeQo); //ThemeContentQo和原主题包装到FormerThemeQo中包装到ThemeQo中 ThemeQo commentThemeQo = ThemeQo.builder() .authorId(userInfoEntity.getId()) .nickName(userInfoEntity.getUiUsernameMp()) .userImg(userInfoEntity.getUiHeadimgMp()) .content(Arrays.asList(commentContent)) .formerTheme(f) .commentId(commentEntity.getCommentId()) .themeType(ThemeTypeEnum.RES_COMMENT.getCode()) .build(); commentThemeList.add(commentThemeQo); } return commentThemeList; case 3://点赞 Set<String> likeThemeIds = collectionService.getListByUser(req.getLastId(), CollectionTypeEnum.LIKE_THEME); themeEntities = themeService.queryByThemeIds(new ArrayList<>(likeThemeIds), req.getLastId(), req.getPageSize()); break; case 4://收藏 Set<String> collectThemeIds = collectionService.getListByUser(req.getLastId(), CollectionTypeEnum.COLLECT_THEME); themeEntities = themeService.queryByThemeIds(new ArrayList<>(collectThemeIds), req.getLastId(), req.getPageSize()); break; } List<ThemeQo> themeQos = convertEntityToQo(themeEntities, userId); return themeQos; } //查询正文 public ThemeQo getDetail(String themeId, String userId) { ThemeEntity themeEntity = themeService.queryByThemeId(themeId); if (themeEntity == null) { throw new BizException("找不到帖子id:" + themeId); } ThemeQo themeQo = ConvertUtil.themeEntityToQo(themeEntity); batchFeignCallService.getAttachDetail(themeQo); buildThemeQoExtraInfo(userId, themeQo); return themeQo; } // 点赞/取消点赞 public void like(LikeThemeReq req, String userId) { if (OperationTypeEnum.CONFIRM.getCode().equals(req.getType())) { collectionService.addIfNotExist(req.getThemeId(), userId, CollectionTypeEnum.LIKE_THEME); } else if (OperationTypeEnum.CANCEL.getCode().equals(req.getType())) { collectionService.delete(req.getThemeId(), userId, CollectionTypeEnum.LIKE_THEME); } } //收藏/取消收藏 public void collect(CollectThemeReq req, String userId) { if (OperationTypeEnum.CONFIRM.getCode().equals(req.getType())) { collectionService.addIfNotExist(req.getThemeId(), userId, CollectionTypeEnum.COLLECT_THEME); } else if (OperationTypeEnum.CANCEL.getCode().equals(req.getType())) { collectionService.delete(req.getThemeId(), userId, CollectionTypeEnum.COLLECT_THEME); } } //转发 public CreateThemeResp forward(ForwardThemeReq req, String userId) { ThemeEntity targetTheme = themeService.queryByThemeId(req.getFormerThemeId()); ThemeEntity themeEntity = ThemeEntity.builder() .content(JsonUtil.toJson(req.getContent())) .topicId(req.getTopicId()) .formerThemeId(req.getFormerThemeId()) .authorId(userId) .themeType(ThemeTypeEnum.FORWARD.getCode()) .build(); if (StringUtils.isEmpty(req.getEditThemeId()) || req.getEditThemeId() == req.getFormerThemeId()) { //新建 themeService.insertTheme(themeEntity); } else { //修改 themeService.update(themeEntity, req.getEditThemeId()); themeEntity.setThemeId(req.getEditThemeId()); } return CreateThemeResp.builder().themeId(themeEntity.getThemeId()).build(); } // 屏蔽(用户) public void blockUser(String blockUser, String userId) { BlackListEntity selectOne = blackListService.selectOne(blockUser, userId, BlockTypeEnum.USER.getCode()); if (selectOne == null) { blackListService.addBlock(blockUser, userId, BlockTypeEnum.USER); } } // 解除屏蔽(用户) public void unblockUser(String blockUser, String userId) { //todo } // 屏蔽(主题) public void blockTheme(String themeId, String userId) { blackListService.addBlock(themeId, userId, BlockTypeEnum.THEME); BlackListEntity selectOne = blackListService.selectOne(themeService.queryByThemeId(themeId).getAuthorId(), userId, BlockTypeEnum.USER.getCode()); if (selectOne == null) { blackListService.addBlock(themeService.queryByThemeId(themeId).getAuthorId(), userId, BlockTypeEnum.USER); } } // 解除屏蔽(主题) public void unblockTheme(String themeId, String userId) { blackListService.removeBlackList(themeId, userId, BlockTypeEnum.USER); } //主题Entity转QO private List<ThemeQo> convertEntityToQo(List<ThemeEntity> themeEntities, String userId) { //Entity转Qo List<ThemeQo> themeQos = ConvertUtil.themeEntitiesToDTOs(themeEntities); //批量查询附件detail batchFeignCallService.getAttachDetailByBatch(themeQos); //其他信息 for (ThemeQo themeQO : themeQos) { buildThemeQoExtraInfo(userId, themeQO); } return themeQos; } //组装主题详情 private void buildThemeQoExtraInfo(String userId, ThemeQo themeQo) { //封装转发对象 buildFormerTheme(themeQo); String themeId = themeQo.getThemeId(); //是否关注作者 String authorId = themeQo.getAuthorId(); Set<String> fansSet = new HashSet<>(followRelService.queryFansByFollowerId(userId)); themeQo.setFollow(fansSet.contains(authorId)); //是否点赞 CollectionEntity likeEntity = collectionService.getNotDeleteTargetCollection(themeId, userId, CollectionTypeEnum.LIKE_THEME); themeQo.setHasLiked(likeEntity != null); //是否转发 Integer forwardCountByUser = themeService.getForwardCountByUser(themeId, userId); themeQo.setHasForward(forwardCountByUser > 0); //是否收藏 CollectionEntity collectionEntity = collectionService.getNotDeleteTargetCollection(themeId, userId, CollectionTypeEnum.COLLECT_THEME); themeQo.setHasCollect(collectionEntity != null); //点赞,收藏,转发 Integer likeCount = collectionService.getCountByTypeAndId(themeId, CollectionTypeEnum.LIKE_THEME); // Integer bookCount = collectionService.getCountByTypeAndId(themeId, CollectionTypeEnum.COLLECT_THEME); Integer commentCount = commentService.getCommentCountByThemeId(themeId); Integer forwardCount = themeService.getForwardCountById(themeId); themeQo.setCommentCount(commentCount); themeQo.setLikeCount(likeCount); themeQo.setForwardCount(forwardCount); } //组装被转发主题 private void buildFormerTheme(ThemeQo themeQo) { String formerThemeId = themeQo.getFormerThemeId(); if (StringUtils.isNotEmpty(formerThemeId)) { ThemeQo formerTheme = ConvertUtil.themeEntityToQo(themeService.queryByThemeId(formerThemeId)); if (formerTheme != null) { //单个查询详情 batchFeignCallService.getAttachDetail(formerTheme); FormerThemeQo f = ConvertUtil.themeQo2FormerThemeQo(formerTheme); themeQo.setFormerTheme(f); } } } //逻辑删除 public void delete(String themeId) { themeService.deleteById(themeId); } //投诉(主题) public void complaint(String themeId, String user) { //TODO } public Integer getFollowUpdateCount(String userId) { LocalDateTime lastViewTime = visitSummaryService.queryLatestViewFollow(userId); List<String> fansList = followRelService.queryFansByFollowerId(userId); return themeService.queryCountFromLastTime(fansList, lastViewTime); } }