Commit 6645416a authored by 张辰's avatar 张辰

Merge branch 'v2.3.1' of http://47.100.44.39:10001/tp-backend/tanpu-community into v2.3.1

# Conflicts:
#	community-service/src/main/java/com/tanpu/community/manager/CommentManager.java
parents a3548a7d 145cccc1
......@@ -51,6 +51,8 @@ public class ThemeNotifyQo {
private String content;
@ApiModelProperty(value = "评论Id")
private String commentId;
@ApiModelProperty(value = "回复的评论Id")
private String replyCommentId;
@ApiModelProperty(value = "转发类型-主题id")
private String forwardThemeId;
......
......@@ -45,6 +45,9 @@ public class ThemeQo implements Serializable {
@ApiModelProperty(value = "话题名称")
public String topicTitle;
@ApiModelProperty(value = "话题是否需要权限")
public Integer topicSpecialPermission;
@ApiModelProperty(value = "昵称")
public String nickName;
......@@ -135,4 +138,8 @@ public class ThemeQo implements Serializable {
// 使用关键词搜索时,在列表页展示的简要内容,内容带关键字.
public String briefContent4FullSearch;
public void evictTop() {
this.isTop = 0;
}
}
......@@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
public class NotifyQueryReq {
@ApiModelProperty(value = "1:转发 2:点赞(主题点赞+评论点赞) 3:评论 4:关注 0:全部")
@ApiModelProperty(value = "1:转发 2:点赞(主题点赞+评论点赞) 3:评论(评论主题+回复评论) 4:关注 0:全部")
private Integer type;
@ApiModelProperty(value = "最后一条通知")
......
......@@ -24,6 +24,9 @@ public class FundInfoBaseResp {
@ApiModelProperty("基金名称")
private String productName;
@ApiModelProperty("基金名称")
private String fundName;
@ApiModelProperty("产品类型")
private Integer productType;
......
......@@ -5,7 +5,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* 通用操作类型枚举,包括点赞/取消点赞,收藏/取消收藏,关注/取消关注
* 消息通知类型
*/
public enum NotificationTypeEnum {
FORWARD(1,"转发"),
......@@ -13,6 +13,9 @@ public enum NotificationTypeEnum {
COMMENT(3,"评论"),
FOLLOW(4,"关注"),
COMMENT_LIKE(5,"点赞评论"),
COMMENT_REPLY(6,"回复评论"),
TOPIC_IN(7,"加入话题"),
TOPIC_OUT(8,"退出话题"),
ALL(0,"全部");
private Integer code;
......
package com.tanpu.community.dao.mapper.community;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
......@@ -8,6 +9,7 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
/**
......@@ -23,14 +25,22 @@ public interface ThemeMapper extends BaseMapper<ThemeEntity> {
@Select("select former_theme_id as id, count(1) as times from theme ${ew.customSqlSegment}")
List<TimesCountEntity> selectCountByThemeIds(@Param(Constants.WRAPPER) LambdaQueryWrapper wrapper);
ThemeEntity queryOneByTopicIdOrderByUpdateTimeDesc(@Param("topicId") String topicId);
ThemeEntity queryOneByTopicIdOrderByUpdateTimeDesc(@Param("topicId")String topicId);
Integer countByTopicIdAndCreateTimeAfter(@Param("topicId") String topicId, @Param("minCreateTime") LocalDateTime minCreateTime);
Integer countByTopicIdAndCreateTimeAfter(@Param("topicId")String topicId,@Param("minCreateTime")LocalDateTime minCreateTime);
List<ThemeEntity> queryRecentdaysOrHasTopic(@Param("deleteTag") Integer deleteTag, @Param("minCreateTime") LocalDateTime minCreateTime, @Param("notTopicId") String notTopicId);
List<ThemeEntity> queryRecentdaysOrHasTopic(@Param("deleteTag")Integer deleteTag,@Param("minCreateTime")LocalDateTime minCreateTime,@Param("notTopicId")String notTopicId);
/**
* 关注人+关注话题下的帖子,带分页
*
* @param followUsers
* @param followTopics
* @return
*/
List<ThemeEntity> queryFollowList(@Param("authorIdCollection") Collection<String> followUsers, @Param("topicIdCollection") Collection<String> followTopics,
@Param("pageStart") Integer pageStart, @Param("pageSize") Integer pageSize);
......
......@@ -38,8 +38,9 @@ public interface FeignClientForCourse {
@GetMapping("/course/getStudyCourseCount")
CommonResp<Integer> getStudyCourseCount(@ApiParam(value = "用户id") @RequestParam(value = "userId",required = false) String userId);
@ApiOperation("课程包列表查询 含价格")
@GetMapping("/course/getCoursePackageSimpleRespList")
@ApiOperation("课程包列表查询 含价格,不用登陆")
@GetMapping("/inner/getCoursePackageSimpleRespList")
CommonResp<List<CoursePackageSimpleResp>> getCoursePackageListByUserId(@RequestParam("list") List<String> list);
}
......@@ -24,9 +24,16 @@ public class FeignBackClientForProducts implements FallbackFactory<FeignClientFo
}
@Override
public CommonResp<List<ProductInfoVO>> getProductInfoByIds(List<String> ids) {
public CommonResp<List<ProductInfoVO>> getProductInfoByIds(List<String> fundIds) {
log.error("请求信息", throwable);
log.error("FeignClientForProducts.getProductInfoByIds-查询产品ids:{}", ids);
log.error("FeignClientForProducts.getProductInfoByIds-查询产品ids:{}", fundIds);
return null;
}
@Override
public CommonResp<List<ProductInfoVO>> getProductInfoByIdsNew(List<String> fundIds) {
log.error("请求信息", throwable);
log.error("FeignClientForProducts.getProductInfoByIdsNew-查询私募产品ids:{}", fundIds);
return null;
}
......
......@@ -21,9 +21,13 @@ public interface FeignClientForProducts {
CommonResp<ProductInfoVO> getProductDetailInfo(@ApiParam("产品id") @RequestParam("id") String id);
@ApiOperation("批量获取私募产品详情")
@ApiOperation("批量获取私募产品详情(旧),Theme详情用")
@GetMapping("/getProductInfoByIds")
CommonResp<List<ProductInfoVO>> getProductInfoByIds(@ApiParam("产品id") @RequestParam("fundIds") List<String> fundIds);
CommonResp<List<ProductInfoVO>> getProductInfoByIds(@ApiParam("筛选条件对象") @RequestParam("fundIds") List<String> fundIds);
@ApiOperation("批量获取私募产品详情(新),Topic详情用")
@GetMapping("/getProductInfoByIdsNew")
CommonResp<List<ProductInfoVO>> getProductInfoByIdsNew(@ApiParam("筛选条件对象") @RequestParam("fundIds") List<String> fundIds);
@ApiOperation("基金公司-简单信息")
@GetMapping("/fund/companyInfoSimple")
......
......@@ -35,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
......@@ -108,8 +109,17 @@ public class CommentManager {
throw new BizException(ErrorCodeConstant.UNREACHABLE);
}
notificationService.insert(userId, themeEntity.getAuthorId(), NotificationTypeEnum.COMMENT, commentEntity.getCommentId(), req.getComment());
notificationService.putNotifyCache(themeEntity.getAuthorId(), userId, NotificationTypeEnum.COMMENT);
// 一级回复通知发帖人,二级回复通知一级评论人
if (StringUtils.isNotBlank(req.getReplyUserId())) {
notificationService.insert(userId, req.getReplyUserId(), NotificationTypeEnum.COMMENT_REPLY, commentEntity.getCommentId(), req.getComment());
notificationService.putNotifyCache(req.getReplyUserId(), userId, NotificationTypeEnum.COMMENT_REPLY);
} else {
notificationService.insert(userId, themeEntity.getAuthorId(), NotificationTypeEnum.COMMENT, commentEntity.getCommentId(), req.getComment());
notificationService.putNotifyCache(themeEntity.getAuthorId(), userId, NotificationTypeEnum.COMMENT);
}
// 评论同步转发并消息通知
if (req.getSyncForward() == BizConstant.SyncForwardType.SYNC_FORWARD) {
......@@ -233,10 +243,21 @@ public class CommentManager {
if (StringUtils.isBlank(commentId)) {
throw new BizException("commentId不能为空");
}
commentService.delete(commentId, userId);
CommentEntity commentEntity = commentService.queryByIdIncludeDelete(commentId);
ThemeEntity themeEntity = themeService.queryByThemeId(commentEntity.getThemeId());
notificationService.deleteCommentNotify(themeEntity.getAuthorId(), userId, commentId, commentEntity.getCreateTime());
ArrayDeque<CommentEntity> queue = new ArrayDeque<>();
queue.add(commentService.queryByIdIncludeDelete(commentId));
// 循环删除二级评论的一级评论
while (!queue.isEmpty()) {
CommentEntity pop = queue.pop();
// 逻辑删除comment
CommentEntity commentEntity = commentService.delete(pop.getCommentId(), pop.getAuthorId());
// 删除站内信
ThemeEntity themeEntity = themeService.queryByThemeId(commentEntity.getThemeId());
notificationService.deleteCommentNotify(themeEntity.getAuthorId(), userId, commentId, commentEntity.getCreateTime());
// 递归
queue.addAll(commentService.queryReplyForComment(commentEntity.getCommentId()));
}
}
......
......@@ -31,55 +31,60 @@ import com.tanpu.community.service.NotificationService;
import com.tanpu.community.service.ThemeService;
import com.tanpu.community.service.TopicService;
import com.tanpu.community.util.ConvertUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.tanpu.community.api.constants.RedisKeyConstant.CACHE_FEIGN_USER_INFO;
@Service
public class NotificationManager {
@Autowired
@Resource
private NotificationService notificationService;
@Autowired
@Resource
private TopicService topicService;
@Autowired
@Resource
private ThemeService themeService;
@Resource
private BatchFeignCallService batchFeignCallService;
@Autowired
@Resource
private FeignClientForFatools feignClientForFatools;
@Autowired
@Resource
private CommentService commentService;
@Autowired
@Resource
private FollowRelService followRelService;
@Autowired
@Resource
private CollectionService collectionService;
@Autowired
@Resource
private RedisCache redisCache;
public List<ThemeNotifyQo> queryList(NotifyQueryReq req, String userId) {
List<NotificationEntity> query = notificationService.query(userId, req.getType(), req.getLastId(), req.getPageSize());
if (CollectionUtils.isEmpty(query)){
return Collections.emptyList();
}
List<ThemeNotifyQo> themeNotifyQos = ConvertUtil.notificationEntitiy2ThemeQos(query);
UserInfoResp currentUser = redisCache.getObject(StringUtils.joinWith("_", CACHE_FEIGN_USER_INFO, userId),
60, () -> this.getUserInfo(userId), UserInfoResp.class);
Set<String> followUserIds = followRelService.queryIdolsByFansId(userId).stream().collect(Collectors.toSet());
Set<String> followUserIds = new HashSet<>(followRelService.queryIdolsByFansId(userId));
for (ThemeNotifyQo themeNotifyQo : themeNotifyQos) {
// 用户信息
......@@ -96,17 +101,17 @@ public class NotificationManager {
// 评论根据commentEntity找到ThemeId
if (NotificationTypeEnum.COMMENT.getCode().equals(themeNotifyQo.getMessageType()) ||
NotificationTypeEnum.COMMENT_LIKE.getCode().equals(themeNotifyQo.getMessageType())) {
NotificationTypeEnum.COMMENT_LIKE.getCode().equals(themeNotifyQo.getMessageType()) ||
NotificationTypeEnum.COMMENT_REPLY.getCode().equals(themeNotifyQo.getMessageType())) {
// 评论类型将commentId替换为themeId
CommentEntity commentEntity = commentService.queryByCommentId(themeNotifyQo.getCommentId());
if (commentEntity != null) {
themeNotifyQo.setFormerThemeId(commentEntity.getThemeId());
themeNotifyQo.setReplyCommentId(commentEntity.getReplyId());
if (NotificationTypeEnum.COMMENT_LIKE.getCode().equals(themeNotifyQo.getMessageType())) {
themeNotifyQo.setContent(commentEntity.getContent());
}
}
}
// 封装引用对象
......@@ -135,6 +140,20 @@ public class NotificationManager {
if (StringUtils.isNotBlank(themeNotifyQo.getTopicId())) {
themeNotifyQo.setTopicTitle(topicService.queryTitleById(themeNotifyQo.getTopicId()));
}
// 加入退出话题
if (NotificationTypeEnum.TOPIC_IN.getCode().equals(themeNotifyQo.getMessageType()) ||
NotificationTypeEnum.TOPIC_OUT.getCode().equals(themeNotifyQo.getMessageType())) {
themeNotifyQo.setContent(MessageFormat.format(themeNotifyQo.getContent(), themeNotifyQo.getTopicTitle()));
}
// 评论的评论
if (NotificationTypeEnum.COMMENT_REPLY.getCode().equals(themeNotifyQo.getMessageType())) {
CommentEntity commentEntity = commentService.queryByCommentId(themeNotifyQo.getReplyCommentId());
if (commentEntity != null) {
themeNotifyQo.setFormerContent(commentEntity.getContent());
}
}
// 点赞聚合
if (themeNotifyQo.getLikeUserCount() != null && themeNotifyQo.getLikeUserCount() > 1) {
List<UserBriefInfoQO> likeUsers = themeNotifyQo.getLikeUsers();
......
......@@ -424,6 +424,9 @@ public class ThemeManager {
// 转发主题
public CreateThemeResp forward(ForwardThemeReq req, String userId) {
// 校验
themeService.checkForwardSpecialPermission(req.getFormerThemeId());
ThemeEntity themeEntity = ThemeEntity.builder()
.content(JsonUtil.toJson(req.getContent()))
.topicId(req.getTopicId())
......@@ -516,14 +519,15 @@ public class ThemeManager {
} else if (ThemeListTypeEnum.FOLLOW.getCode().equals(req.getType())) {
if (StringUtils.isEmpty(req.getUserId())) {
if (StringUtils.isEmpty(userId)) {
// 未登录情况下返回空数组
themes = Lists.newArrayListWithCapacity(0);
} else {
// 根据关注列表查询,按时间倒序
List<String> fansList = followRelService.queryIdolsByFansId(req.getUserId());
fansList.add(userId); // 保证fansList不为空
// 权限控制,筛选出当前用户有权限的话题
// 权限控制,筛选出当前用户关注的话题
Set<String> userPermitTopics = topicService.getUserPermitTopics(userId);
// 查库
......@@ -541,12 +545,21 @@ public class ThemeManager {
if (StringUtils.isEmpty(req.getTopicId())) {
throw new BizException("TopicId为空");
}
// 话题下的置顶
List<ThemeEntity> topThemes = themeService.queryTopByTopic(req.getTopicId());
excludeIds.addAll(topThemes.stream().map(ThemeEntity::getThemeId).collect(Collectors.toList()));
List<String> rankThemeIds = rankService.getRankThemeListByTopic(req.getTopicId(), excludeIds);
rankThemeIds = BizUtils.subList(rankThemeIds, pageStart, pageSize);
themes = themeService.queryByThemeIds(rankThemeIds);
themes = RankUtils.sortThemeEntityByIds(themes, rankThemeIds);
// 置顶
if (pageStart == 0) {
topThemes.addAll(themes);
themes = topThemes;
}
} else if (ThemeListTypeEnum.TOPIC_LATEST.getCode().equals(req.getType())) {
//根据话题查询最新
......@@ -563,12 +576,17 @@ public class ThemeManager {
// todo 测试性能
commentService.queryRecentComments(resp.themes);
// 讨论区添加是否管理员,是否顶置
// 讨论区添加是否管理员
if (ThemeListTypeEnum.TOPIC_LATEST.getCode().equals(req.getType())
|| ThemeListTypeEnum.TOPIC_HOT.getCode().equals(req.getType())) {
topicService.checkManager(req.getTopicId(), resp.themes);
}
// 非讨论区热门擦除顶置状态
if (!ThemeListTypeEnum.TOPIC_HOT.getCode().equals(req.getType())) {
resp.themes.stream().forEach(ThemeQo::evictTop);
}
// 保存缓存、记录已浏览
excludeIds.addAll(resp.themes.stream().map(ThemeQo::getThemeId).collect(Collectors.toList()));
redisCache.put("queryThemes_" + req.ident, excludeIds, 60 * 60 * 6);
......@@ -759,6 +777,9 @@ public class ThemeManager {
if (StringUtils.isNotEmpty(userId)) {
buildThemeExtraInfoByUser(userId, themeQo);
}
// 是否管理员
topicService.checkManager(themeQo.getTopicId(), themeQo);
return CommonResp.success(themeQo);
}
......
......@@ -194,6 +194,9 @@ public class TopicManager {
BeanUtils.copyProperties(collect.get(0),result);
if (result.getDisscussCount()!=null && result.getDisscussCount()>99){
result.setFormatDisscussCount("99+");
}
// 最新讨论
List<ThemeEntity> themeEntities = themeService.queryNewestByTopic(topicEntity.getTopicId(), 0, 3, Collections.emptyList());
......
......@@ -105,7 +105,7 @@ public class BatchFeignCallService {
// 图片信息
Map<String, FileRecordEntity> imgMap = Maps.newHashMap();
// 话题标题
Map<String, String> topicMap = Maps.newHashMap();
Map<String, TopicEntity> topicMap = Maps.newHashMap();
// 图片信息
Map<String, UserInfoResp> userMap = Maps.newHashMap();
// 批量查询资源信息,将不同类型的id抽取,并通过ids查询并存放到id-对象Map中
......@@ -131,7 +131,7 @@ public class BatchFeignCallService {
Map<String, ZhiboListResp> zhiboMap,
Map<String, FundInfoBaseResp> fundMap,
Map<String, OfflineActivitySimpleResp> activityMap, Map<String, FileRecordEntity> imgMap,
Map<String, String> topicMap,
Map<String, TopicEntity> topicMap,
Map<String, UserInfoResp> userMap,
List<ThemeQo> themeQos
) {
......@@ -249,7 +249,7 @@ public class BatchFeignCallService {
topicService.queryByIds(setToList(topicIds));
if (!CollectionUtils.isEmpty(topicEntities)) {
topicMap.putAll(topicEntities.stream().collect(Collectors
.toMap(TopicEntity::getTopicId, TopicEntity::getTopicTitle)));
.toMap(TopicEntity::getTopicId, o->o)));
}
}
if (!CollectionUtils.isEmpty(userIds)) {
......@@ -288,10 +288,11 @@ public class BatchFeignCallService {
// .fundIds(Lists.newArrayList(tanpuFundIds))
// .build();
// 探普产品
List<ProductInfoVO> list = feignService.getProductInfoByIds(setToList(tanpuFundIds));
List<ProductInfoVO> list = feignService.getProductInfoByIdsForTheme(setToList(tanpuFundIds));
List<FundInfoBaseResp> fundInfoBaseRespList = list.stream().map(item -> {
FundInfoBaseResp fundInfoBaseResp = FundInfoBaseResp.builder().build();
BeanUtils.copyProperties(item, fundInfoBaseResp);
fundInfoBaseResp.setProductName(item.getFundName());
return fundInfoBaseResp;
}).collect(Collectors.toList());
tampFundMap = fundInfoBaseRespList.stream().collect(Collectors.toMap(FundInfoBaseResp::getFundId, item -> item));
......@@ -307,6 +308,7 @@ public class BatchFeignCallService {
List<FundInfoBaseResp> fundInfoBaseRespList = list.stream().map(item -> {
FundInfoBaseResp fundInfoBaseResp = FundInfoBaseResp.builder().build();
BeanUtils.copyProperties(item, fundInfoBaseResp);
fundInfoBaseResp.setProductName(item.getFundName());
return fundInfoBaseResp;
}).collect(Collectors.toList());
privateFundMap = fundInfoBaseRespList.stream().collect(Collectors.toMap(FundInfoBaseResp::getFundId, item -> item));
......@@ -322,6 +324,7 @@ public class BatchFeignCallService {
List<FundInfoBaseResp> fundInfoBaseRespList = list.stream().map(item -> {
FundInfoBaseResp fundInfoBaseResp = FundInfoBaseResp.builder().build();
BeanUtils.copyProperties(item, fundInfoBaseResp);
fundInfoBaseResp.setProductName(item.getFundName());
return fundInfoBaseResp;
}).collect(Collectors.toList());
ifaFundMap = fundInfoBaseRespList.stream().collect(Collectors.toMap(FundInfoBaseResp::getFundId, item -> item));
......@@ -338,6 +341,7 @@ public class BatchFeignCallService {
List<FundInfoBaseResp> fundInfoBaseRespList = list.stream().map(item -> {
FundInfoBaseResp fundInfoBaseResp = FundInfoBaseResp.builder().build();
BeanUtils.copyProperties(item, fundInfoBaseResp);
fundInfoBaseResp.setProductName(item.getFundName());
return fundInfoBaseResp;
}).collect(Collectors.toList());
publicFundMap = fundInfoBaseRespList.stream().collect(Collectors.toMap(FundInfoBaseResp::getFundId, item -> item));
......@@ -376,11 +380,13 @@ public class BatchFeignCallService {
Map<String, FundInfoBaseResp> fundMap,
Map<String, OfflineActivitySimpleResp> activityMap, Map<String, FileRecordEntity> imgUrlMap,
Map<String, UserInfoResp> userMap,
Map<String, String> topicMap) {
Map<String, TopicEntity> topicMap) {
for (ThemeQo themeQo : themeQos) {
if (!StringUtils.isEmpty(themeQo.getTopicId()) && topicMap.containsKey(themeQo.getTopicId())) {
//话题标题
themeQo.setTopicTitle(topicMap.get(themeQo.getTopicId()));
TopicEntity topicEntity = topicMap.get(themeQo.getTopicId());
themeQo.setTopicTitle(topicEntity.getTopicTitle());
themeQo.setTopicSpecialPermission(topicEntity.getSpecialPermission());
}
if (!StringUtils.isEmpty(themeQo.getAuthorId()) && userMap.containsKey(themeQo.getAuthorId())) {
//用户信息
......
......@@ -72,11 +72,13 @@ public class CommentService {
.eq(CommentEntity::getThemeId, themeId))
.eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED));
}
public Integer getCommentCountByThemeIds(List<String> themeIds) {
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))
......@@ -151,7 +153,7 @@ public class CommentService {
//删除评论
@Transactional
public void delete(String commentId, String userId) {
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);
......@@ -160,6 +162,7 @@ public class CommentService {
commentMapper.updateById(commentEntity);
//失效缓存
evictThemeCache(commentEntity.getThemeId());
return commentEntity;
}
// 失效关联主题缓存
......@@ -204,6 +207,7 @@ public class CommentService {
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()));
......@@ -215,9 +219,21 @@ public class CommentService {
for (ThemeQo theme : themes) {
if (collect.containsKey(theme.getThemeId())) {
List<CommentEntity> comments = collect.get(theme.getThemeId());
theme.setRecentComments(ConvertUtil.comment2Simple(comments, nameMap));
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;
}
}
......@@ -139,8 +139,20 @@ public class FeignService {
});
}
public List<ProductInfoVO> getProductInfoByIds(List<String> fundIds) {
return batchExecute("getProductInfoByIds_", fundIds, ProductInfoVO.class,
public List<ProductInfoVO> getProductInfoByIdsForTopic(List<String> fundIds) {
return batchExecute("getProductInfoByIdsForTopic_", fundIds, ProductInfoVO.class,
ProductInfoVO::getFundId, ids -> {
CommonResp<List<ProductInfoVO>> resp = feignForProduct.getProductInfoByIds(ids);
if (resp.isSuccess()) {
return resp.getData();
} else {
return new ArrayList<>();
}
});
}
public List<ProductInfoVO> getProductInfoByIdsForTheme(List<String> fundIds) {
return batchExecute("getProductInfoByIdsForTheme_", fundIds, ProductInfoVO.class,
ProductInfoVO::getFundId, ids -> {
CommonResp<List<ProductInfoVO>> resp = feignForProduct.getProductInfoByIds(ids);
if (resp.isSuccess()) {
......
......@@ -165,12 +165,19 @@ public class NotificationService {
.eq(NotificationEntity::getNotificationId, lastId));
queryWrapper.lt(NotificationEntity::getUpdateTime, lastOne.getCreateTime());
}
if (!NotificationTypeEnum.ALL.getCode().equals(type) && !NotificationTypeEnum.LIKE.getCode().equals(type)) {
queryWrapper.eq(NotificationEntity::getMessageType, type);
} else if (NotificationTypeEnum.LIKE.getCode().equals(type)) {
// 类型2点赞返回评论点赞和主题点赞
queryWrapper.in(NotificationEntity::getMessageType,
Arrays.asList(NotificationTypeEnum.LIKE.getCode(), NotificationTypeEnum.COMMENT_LIKE.getCode()));
if (!NotificationTypeEnum.ALL.getCode().equals(type)) {
if (NotificationTypeEnum.LIKE.getCode().equals(type)) {
// 类型2点赞返回评论点赞和主题点赞
queryWrapper.in(NotificationEntity::getMessageType,
Arrays.asList(NotificationTypeEnum.LIKE.getCode(), NotificationTypeEnum.COMMENT_LIKE.getCode()));
} else if (NotificationTypeEnum.COMMENT.getCode().equals(type)) {
// 类型3返回 回复主题和回复评论
queryWrapper.in(NotificationEntity::getMessageType,
Arrays.asList(NotificationTypeEnum.COMMENT.getCode(), NotificationTypeEnum.COMMENT_REPLY.getCode()));
}else {
queryWrapper.eq(NotificationEntity::getMessageType, type);
}
}
return notificationMapper.selectList(queryWrapper);
}
......@@ -220,6 +227,8 @@ public class NotificationService {
redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "点赞了你的评论", 60 * 60 * 24 * 30);
} else if (NotificationTypeEnum.FOLLOW.equals(type)) {
redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "关注了你", 60 * 60 * 24 * 30);
} else if (NotificationTypeEnum.COMMENT_REPLY.equals(type)) {
redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, "您有一条评论被回复啦,快去看看吧~", 60 * 60 * 24 * 30);
} else {
redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + type.getType() + "了你的内容", 60 * 60 * 24 * 30);
}
......@@ -237,7 +246,7 @@ public class NotificationService {
NotificationEntity last = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>().eq(NotificationEntity::getNotifiedUserId, notifyUserId)
.orderByDesc(NotificationEntity::getUpdateTime)
.last("limit 1"));
if (commentNotify==null || last==null){
if (commentNotify == null || last == null) {
return;
}
notificationMapper.deleteById(commentNotify.getId());
......
......@@ -25,6 +25,7 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
@Service
......@@ -218,11 +219,11 @@ public class RankService {
.collect(Collectors.toList());
//落库
if (redisCache.setIfAbsent("logTopicRank", "1", 60)) {
int i = new Random().nextInt(3);
if (i==1 && redisCache.setIfAbsent("logTopicRank", "1", 60)) {
rankLogService.logTopicRank(rankList, start, TimeUtils.calMillisTillNow(start));
redisCache.evict("logTopicRank");
}
return;
}
/**
......
......@@ -4,8 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.tanpu.biz.common.enums.RelTypeEnum;
import com.tanpu.biz.common.enums.community.ReportStatusEnum;
import com.tanpu.common.constant.ErrorCodeConstant;
import com.tanpu.common.exception.BizException;
import com.tanpu.common.redis.RedisHelper;
import com.tanpu.common.util.JsonUtil;
import com.tanpu.common.uuid.UuidGenHelper;
import com.tanpu.community.api.beans.qo.ThemeQo;
......@@ -14,11 +14,14 @@ import com.tanpu.community.api.beans.req.comment.CreateCommentReq;
import com.tanpu.community.api.beans.req.theme.ThemeContentReq;
import com.tanpu.community.api.beans.vo.feign.fatools.UserInfoResp;
import com.tanpu.community.api.enums.DeleteTagEnum;
import com.tanpu.community.api.enums.StatusEnum;
import com.tanpu.community.api.enums.ThemeTypeEnum;
import com.tanpu.community.dao.entity.community.ThemeEntity;
import com.tanpu.community.dao.entity.community.TimesCountEntity;
import com.tanpu.community.dao.entity.community.TopicEntity;
import com.tanpu.community.dao.entity.community.VisitLogEntity;
import com.tanpu.community.dao.mapper.community.ThemeMapper;
import com.tanpu.community.dao.mapper.community.TopicMapper;
import com.tanpu.community.dao.mapper.community.VisitLogMapper;
import com.tanpu.community.util.ConvertUtil;
import com.tanpu.community.util.TimeUtils;
......@@ -28,7 +31,14 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Service
......@@ -41,7 +51,7 @@ public class ThemeService {
private UuidGenHelper uuidGenHelper;
@Resource
private RedisHelper redisHelper;
private TopicMapper topicMapper;
@Resource
private VisitLogMapper visitLogMapper;
@Resource
......@@ -217,18 +227,11 @@ public class ThemeService {
* @return
*/
public List<ThemeEntity> queryByUserIdsCreateDesc(List<String> userIds, Integer pageStart, Integer pageSize, Set<String> userPermitTopics) {
if (CollectionUtils.isEmpty(userIds)) {
if (CollectionUtils.isEmpty(userIds) && CollectionUtils.isEmpty(userPermitTopics)) {
return Collections.emptyList();
}
// 权限控制,添加主题为空的情况
userPermitTopics.add("");
LambdaQueryWrapper<ThemeEntity> queryWrapper = new LambdaQueryWrapper<ThemeEntity>()
.in(ThemeEntity::getAuthorId, userIds)
.in(ThemeEntity::getTopicId, userPermitTopics)
.last("limit " + pageStart + ", " + pageSize)
.orderByDesc(ThemeEntity::getCreateTime)
.eq(ThemeEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode());
return themeMapper.selectList(queryWrapper);
userPermitTopics.remove("");
return themeMapper.queryFollowList(userIds, userPermitTopics, pageStart, pageSize);
}
......@@ -316,6 +319,8 @@ public class ThemeService {
}
public String commentSyncForward(CreateCommentReq req, String userId) {
checkForwardSpecialPermission(req.getThemeId());
// 评论构造theme content
List<ThemeContentReq> themeContentReqs = Arrays.asList(ThemeContentReq.builder().type(RelTypeEnum.TEXT.type).value(req.getComment()).build());
ThemeContentReq.builder().type(RelTypeEnum.TEXT.type).value(req.getComment()).build();
......@@ -330,6 +335,19 @@ public class ThemeService {
return themeEntity.getThemeId();
}
/**
* 专属话题不允许转发
*/
public void checkForwardSpecialPermission(String themeId) {
ThemeEntity themeEntity = queryByThemeId(themeId);
if (themeEntity!=null && StringUtils.isNotBlank(themeEntity.getTopicId())){
TopicEntity topicEntity = topicMapper.selectOne(new LambdaQueryWrapper<TopicEntity>().eq(TopicEntity::getTopicId, themeEntity.getTopicId()));
if (topicEntity!=null && topicEntity.getSpecialPermission()==1){
throw new BizException(ErrorCodeConstant.TOPIC_FORWARD_ABORT.getCode(),"专属话题不允许转发");
}
}
}
public void queryCommentForTopic(List<TopicFollowQo> topicQos, String userId) {
......@@ -348,13 +366,13 @@ public class ThemeService {
// 查询更新条数
VisitLogEntity visitLogEntity = visitLogMapper.queryLastByVisitorIdAndRefId(userId, topicId);
Integer updates;
if (visitLogEntity != null) {
Integer updates = themeMapper.countByTopicIdAndCreateTimeAfter(topicId, visitLogEntity.getUpdateTime());
topic.setUpdateCount(updates);
updates = themeMapper.countByTopicIdAndCreateTimeAfter(topicId, visitLogEntity.getUpdateTime());
} else {
topic.setUpdateCount(0);
updates = themeMapper.countByTopicIdAndCreateTimeAfter(topicId, null);
}
topic.setUpdateCount(updates);
}
......@@ -367,4 +385,13 @@ public class ThemeService {
}
return "理财师";
}
public List<ThemeEntity> queryTopByTopic(String topicId) {
LambdaQueryWrapper<ThemeEntity> queryWrapper = new LambdaQueryWrapper<ThemeEntity>()
.eq(ThemeEntity::getTopicId, topicId)
.eq(ThemeEntity::getDeleteTag, StatusEnum.FALSE.getCode())
.eq(ThemeEntity::getIsTop, StatusEnum.TRUE.getCode())
.orderByDesc(ThemeEntity::getSetTopTime);
return themeMapper.selectList(queryWrapper);
}
}
......@@ -29,6 +29,7 @@ import com.tanpu.community.dao.mapper.community.TopicSubjectMapper;
import com.tanpu.community.util.ConvertUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Service;
......@@ -54,6 +55,8 @@ public class TopicService {
private FeignService feignService;
@Resource
private TopicSubjectMapper topicSubjectMapper;
@Value("${msg.kefu.telephone:021-65681889}")
private String kefuTelephone;
public List<TopicEntity> queryAll() {
......@@ -137,7 +140,9 @@ public class TopicService {
public boolean addFollowTopic(String topicId, String userId) {
TopicFollowRelEntity searchResult = topicFollowRelMapper.queryOneByTopicIdAndUserId(topicId, userId);
TopicFollowRelEntity searchResult = topicFollowRelMapper.selectOne(new LambdaQueryWrapper<TopicFollowRelEntity>()
.eq(TopicFollowRelEntity::getUserId, userId)
.eq(TopicFollowRelEntity::getTopicId, topicId));
if (searchResult == null) {
TopicFollowRelEntity entity = TopicFollowRelEntity.builder()
.topicId(topicId)
......@@ -200,9 +205,7 @@ public class TopicService {
public String getPermissionToast(String topicId) {
String permission = "专业版会员";
return "暂无权限参与此话题~您可联系官方客服 021- 了解详情";
return "暂无权限参与此话题~您可联系官方客服" + kefuTelephone + "了解详情";
// return "该话题仅限" + permission + "可参与哦~";
}
......@@ -235,38 +238,47 @@ public class TopicService {
List<ProductInfoVO> fund = Collections.emptyList();
// 基金
if (entity.getSubjectSubType() == ProductTypeEnum.PRIVATE.type || entity.getSubjectSubType() == ProductTypeEnum.TAMP.type) {
fund = feignService.getProductInfoByIds(Collections.singletonList(entity.getSubjectId()));
fund = feignService.getProductInfoByIdsForTopic(Collections.singletonList(entity.getSubjectId()));
} else if (entity.getSubjectSubType() == ProductTypeEnum.PUBLIC.type) {
fund = feignService.getPublicFundList(Collections.singletonList(entity.getSubjectId()));
} else {
fund = Arrays.asList(new ProductInfoVO());
}
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.FUND.type)
.subType(String.valueOf(entity.getSubjectSubType()))
.detail(TopicAttachmentDetail.builder().fund(fund.get(0)).build()).build();
attachements.add(attach);
if (CollectionUtils.isNotEmpty(fund)) {
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.FUND.type)
.subType(String.valueOf(entity.getSubjectSubType()))
.detail(TopicAttachmentDetail.builder().fund(fund.get(0)).build()).build();
attachements.add(attach);
}
} else if (RelTypeEnum.FUND_COMPANY.type.equals(entity.getSubjectType().toString())) {
// 资管人
List<FundCompanyVO> fundCompany = feignService.getFundCompany(Collections.singletonList(entity.getSubjectId()));
FundCompanyVO company = fundCompany.get(0);
company.setType(String.valueOf(entity.getSubjectSubType())); // 公司类型
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.FUND_COMPANY.type)
.detail(TopicAttachmentDetail.builder().fundCompany(company).build()).build();
attachements.add(attach);
if (CollectionUtils.isNotEmpty(fundCompany)) {
FundCompanyVO company = fundCompany.get(0);
company.setType(String.valueOf(entity.getSubjectSubType())); // 公司类型
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.FUND_COMPANY.type)
.detail(TopicAttachmentDetail.builder().fundCompany(company).build()).build();
attachements.add(attach);
}
} else if (RelTypeEnum.NEW_COURSE_WARE.type.equals(entity.getSubjectType().toString())) {
// 课程包
List<CoursePackageSimpleResp> coursePackage = feignService.getCoursePackageList(Collections.singletonList(entity.getSubjectId()));
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.NEW_COURSE_WARE.type)
.detail(TopicAttachmentDetail.builder().coursePackage(coursePackage.get(0)).build()).build();
attachements.add(attach);
if (CollectionUtils.isNotEmpty(coursePackage)){
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.NEW_COURSE_WARE.type)
.detail(TopicAttachmentDetail.builder().coursePackage(coursePackage.get(0)).build()).build();
attachements.add(attach);
}
} else if (RelTypeEnum.OFFLINE_ACTIVITY.type.equals(entity.getSubjectType().toString())) {
// 线下活动
List<OfflineActivitySimpleResp> activitySimpleList = feignService.getActivitySimpleList(Collections.singletonList(entity.getSubjectId()));
TopicAttachmentDetail detailVo = TopicAttachmentDetail.builder().activity(activitySimpleList.get(0)).build();
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.OFFLINE_ACTIVITY.type).detail(detailVo).build();
attachements.add(attach);
if (CollectionUtils.isNotEmpty(activitySimpleList)){
TopicAttachmentDetail detailVo = TopicAttachmentDetail.builder().activity(activitySimpleList.get(0)).build();
TopicAttachment attach = TopicAttachment.builder().type(RelTypeEnum.OFFLINE_ACTIVITY.type).detail(detailVo).build();
attachements.add(attach);
}
}
}
......@@ -291,6 +303,10 @@ public class TopicService {
}
}
public void checkManager(String topicId, ThemeQo theme) {
checkManager(topicId, Collections.singletonList(theme));
}
public List<TopicManagerEntity> getManagersByTopic(String topicId) {
return topicManagerMapper.selectList(new LambdaQueryWrapper<TopicManagerEntity>().eq(TopicManagerEntity::getTopicId, topicId));
}
......@@ -330,7 +346,7 @@ public class TopicService {
public Set<String> getUserPermitTopics(String userId) {
// 公开权限的话题
List<TopicEntity> openTopics = topicMapper.selectList(new LambdaQueryWrapper<TopicEntity>()
.eq(TopicEntity::getSpecialPermission, StatusEnum.TRUE.getCode())
.eq(TopicEntity::getSpecialPermission, StatusEnum.FALSE.getCode())
.eq(TopicEntity::getDeleteTag, StatusEnum.FALSE.getCode())
.eq(TopicEntity::getIsConceal, StatusEnum.FALSE.getCode()));
......
......@@ -301,10 +301,16 @@ public class ConvertUtil {
}
// 评、点赞评论 评论Id
if (entity.getMessageType().equals(NotificationTypeEnum.COMMENT_LIKE.getCode()) ||
entity.getMessageType().equals(NotificationTypeEnum.COMMENT.getCode())
entity.getMessageType().equals(NotificationTypeEnum.COMMENT.getCode()) ||
entity.getMessageType().equals(NotificationTypeEnum.COMMENT_REPLY.getCode())
) {
themeNotifyQo.setCommentId(entity.getTargetId());
}
// 主题加入退出
if (NotificationTypeEnum.TOPIC_IN.getCode().equals(entity.getMessageType()) ||
NotificationTypeEnum.TOPIC_OUT.getCode().equals(entity.getMessageType())) {
themeNotifyQo.setTopicId(entity.getTargetId());
}
// 转发有话题信息
if (entity.getMessageType().equals(NotificationTypeEnum.FORWARD.getCode())) {
themeNotifyQo.setFormerThemeId(entity.getTargetId());
......
......@@ -142,4 +142,8 @@ pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
\ No newline at end of file
params: count=countSql
msg:
kefu:
telephone: 021-65681889
\ No newline at end of file
......@@ -48,14 +48,8 @@
</select>
<!--auto generated by MybatisCodeHelper on 2022-02-17-->
<select id="countByTopicIdAndCreateTimeAfter" resultType="java.lang.Integer">
select count(1)
from theme
where topic_id = #{topicId}
and create_time <![CDATA[>]]> #{minCreateTime}
</select>
<!--auto generated by MybatisCodeHelper on 2022-02-22-->
<!--auto generated by MybatisCodeHelper on 2022-02-22-->
<select id="queryRecentdaysOrHasTopic" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
......@@ -64,4 +58,39 @@
and ( create_time <![CDATA[>]]> #{minCreateTime}
or topic_id <![CDATA[<>]]> #{notTopicId})
</select>
<!--auto generated by MybatisCodeHelper on 2022-02-23-->
<select id="queryFollowList" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from theme
where delete_tag=0 and (
<if test="authorIdCollection != null and authorIdCollection.size() > 0">
author_id in
<foreach item="item" index="index" collection="authorIdCollection"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="topicIdCollection != null and topicIdCollection.size() > 0">
or topic_id in
<foreach item="item" index="index" collection="topicIdCollection"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
) order by create_time desc limit #{pageStart}, #{pageSize}
</select>
<!--auto generated by MybatisCodeHelper on 2022-02-23-->
<select id="countByTopicIdAndCreateTimeAfter" resultType="java.lang.Integer">
select count(1)
from theme
<where>
topic_id=#{topicId}
<if test="minCreateTime != null">
and create_time <![CDATA[>]]> #{minCreateTime}
</if>
</where>
</select>
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment