评论功能

This commit is contained in:
ronger 2020-03-07 21:18:22 +08:00
parent 38c54fbecf
commit afd0b2caf7
12 changed files with 262 additions and 5 deletions

View File

@ -10,4 +10,6 @@ public class NotificationConstant {
public static String Follow = "1"; public static String Follow = "1";
public static String Comment = "2";
} }

View File

@ -47,4 +47,6 @@ public class ArticleDTO {
private Author articleAuthor; private Author articleAuthor;
private List<ArticleTagDTO> tags; private List<ArticleTagDTO> tags;
private List<CommentDTO> articleComments;
} }

View File

@ -0,0 +1,40 @@
package com.rymcu.vertical.dto;
import lombok.Data;
import javax.persistence.Column;
import java.util.Date;
/**
* @author ronger
*/
@Data
public class CommentDTO {
private Integer idComment;
/** 评论内容 */
private String commentContent;
/** 作者 id */
private Integer commentAuthorId;
/** 文章 id */
private Integer commentArticleId;
/** 锚点 url */
private String commentSharpUrl;
/** 父评论 id */
private Integer commentOriginalCommentId;
/** 父评论作者头像 */
private String commentOriginalAuthorThumbnailURL;
/** 状态 */
private String commentStatus;
/** 0公开回帖1匿名回帖 */
private String commentAnonymous;
/** 回帖计数 */
private Integer commentReplyCount;
/** 0所有人可见1仅楼主和自己可见 */
private String commentVisible;
/** 创建时间 */
private Date createdTime;
private Author commenter;
private String timeAgo;
}

View File

@ -19,7 +19,7 @@ public class Comment implements Serializable,Cloneable {
@Id @Id
@GeneratedValue(generator = "JDBC") @GeneratedValue(generator = "JDBC")
@Column(name = "id") @Column(name = "id")
private Integer id; private Integer idComment;
/** 评论内容 */ /** 评论内容 */
@Column(name = "comment_content") @Column(name = "comment_content")
private String commentContent; private String commentContent;

View File

@ -0,0 +1,36 @@
package com.rymcu.vertical.mapper;
import com.rymcu.vertical.core.mapper.Mapper;
import com.rymcu.vertical.dto.Author;
import com.rymcu.vertical.dto.CommentDTO;
import com.rymcu.vertical.entity.Comment;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CommentMapper extends Mapper<Comment> {
/**
* @param idArticle
* @return
*/
List<CommentDTO> selectArticleComments(@Param("idArticle") Integer idArticle);
/**
* @param commentAuthorId
* @return
*/
Author selectAuthor(@Param("commentAuthorId") Integer commentAuthorId);
/**
* @param commentOriginalCommentId
* @return
*/
Author selectCommentOriginalAuthor(@Param("commentOriginalCommentId") Integer commentOriginalCommentId);
/**
* @param idComment
* @param toString
* @return
*/
Integer updateCommentSharpUrl(@Param("idComment") Integer idComment, @Param("commentSharpUrl") String commentSharpUrl);
}

View File

@ -0,0 +1,16 @@
package com.rymcu.vertical.service;
import com.rymcu.vertical.core.service.Service;
import com.rymcu.vertical.dto.CommentDTO;
import com.rymcu.vertical.entity.Comment;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
public interface CommentService extends Service<Comment> {
List<CommentDTO> getArticleComments(Integer idArticle);
Map postComment(Comment comment, HttpServletRequest request);
}

View File

@ -5,12 +5,14 @@ import com.rymcu.vertical.core.service.AbstractService;
import com.rymcu.vertical.dto.ArticleDTO; import com.rymcu.vertical.dto.ArticleDTO;
import com.rymcu.vertical.dto.ArticleTagDTO; import com.rymcu.vertical.dto.ArticleTagDTO;
import com.rymcu.vertical.dto.Author; import com.rymcu.vertical.dto.Author;
import com.rymcu.vertical.dto.CommentDTO;
import com.rymcu.vertical.entity.Article; import com.rymcu.vertical.entity.Article;
import com.rymcu.vertical.entity.ArticleContent; import com.rymcu.vertical.entity.ArticleContent;
import com.rymcu.vertical.entity.Tag; import com.rymcu.vertical.entity.Tag;
import com.rymcu.vertical.entity.User; import com.rymcu.vertical.entity.User;
import com.rymcu.vertical.mapper.ArticleMapper; import com.rymcu.vertical.mapper.ArticleMapper;
import com.rymcu.vertical.service.ArticleService; import com.rymcu.vertical.service.ArticleService;
import com.rymcu.vertical.service.CommentService;
import com.rymcu.vertical.service.TagService; import com.rymcu.vertical.service.TagService;
import com.rymcu.vertical.service.UserService; import com.rymcu.vertical.service.UserService;
import com.rymcu.vertical.util.*; import com.rymcu.vertical.util.*;
@ -42,9 +44,13 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
private TagService tagService; private TagService tagService;
@Resource @Resource
private UserService userService; private UserService userService;
@Resource
private CommentService commentService;
@Value("${resource.domain}") @Value("${resource.domain}")
private static String domain; private String domain;
@Value("${env}")
private String env;
private static final int MAX_PREVIEW = 200; private static final int MAX_PREVIEW = 200;
@ -125,7 +131,9 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
newArticle.setArticlePermalink(domain + "/article/"+newArticle.getIdArticle()); newArticle.setArticlePermalink(domain + "/article/"+newArticle.getIdArticle());
newArticle.setArticleLink("/article/"+newArticle.getIdArticle()); newArticle.setArticleLink("/article/"+newArticle.getIdArticle());
articleMapper.insertArticleContent(newArticle.getIdArticle(),articleContent,articleContentHtml); articleMapper.insertArticleContent(newArticle.getIdArticle(),articleContent,articleContentHtml);
BaiDuUtils.sendSEOData(newArticle.getArticlePermalink()); if (!"dev".equals(env)) {
BaiDuUtils.sendSEOData(newArticle.getArticlePermalink());
}
} else { } else {
newArticle = articleMapper.selectByPrimaryKey(article.getIdArticle()); newArticle = articleMapper.selectByPrimaryKey(article.getIdArticle());
if(!user.getIdUser().equals(newArticle.getArticleAuthorId())){ if(!user.getIdUser().equals(newArticle.getArticleAuthorId())){
@ -144,7 +152,9 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
} }
newArticle.setUpdatedTime(new Date()); newArticle.setUpdatedTime(new Date());
articleMapper.updateArticleContent(newArticle.getIdArticle(),articleContent,articleContentHtml); articleMapper.updateArticleContent(newArticle.getIdArticle(),articleContent,articleContentHtml);
BaiDuUtils.updateSEOData(newArticle.getArticlePermalink()); if (!"dev".equals(env)) {
BaiDuUtils.updateSEOData(newArticle.getArticlePermalink());
}
} }
if (notification) { if (notification) {
@ -239,6 +249,8 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
String articlePreviewContent = articleContent.getArticleContentHtml().substring(0,length); String articlePreviewContent = articleContent.getArticleContentHtml().substring(0,length);
article.setArticlePreviewContent(Html2TextUtil.getContent(articlePreviewContent)); article.setArticlePreviewContent(Html2TextUtil.getContent(articlePreviewContent));
} }
List<CommentDTO> commentDTOList = commentService.getArticleComments(article.getIdArticle());
article.setArticleComments(commentDTOList);
return article; return article;
} }
} }

View File

@ -0,0 +1,97 @@
package com.rymcu.vertical.service.impl;
import com.rymcu.vertical.core.constant.NotificationConstant;
import com.rymcu.vertical.core.service.AbstractService;
import com.rymcu.vertical.dto.Author;
import com.rymcu.vertical.dto.CommentDTO;
import com.rymcu.vertical.entity.Article;
import com.rymcu.vertical.entity.Comment;
import com.rymcu.vertical.mapper.CommentMapper;
import com.rymcu.vertical.service.ArticleService;
import com.rymcu.vertical.service.CommentService;
import com.rymcu.vertical.util.Html2TextUtil;
import com.rymcu.vertical.util.NotificationUtils;
import com.rymcu.vertical.util.Utils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@Service
public class CommentServiceImpl extends AbstractService<Comment> implements CommentService {
@Resource
private CommentMapper commentMapper;
@Resource
private ArticleService articleService;
private static final int MAX_PREVIEW = 200;
@Override
public List<CommentDTO> getArticleComments(Integer idArticle) {
List<CommentDTO> commentDTOList = commentMapper.selectArticleComments(idArticle);
commentDTOList.forEach(commentDTO -> {
commentDTO.setTimeAgo(Utils.getTimeAgo(commentDTO.getCreatedTime()));
if (commentDTO.getCommentAuthorId() != null) {
Author author = commentMapper.selectAuthor(commentDTO.getCommentAuthorId());
if (author != null) {
commentDTO.setCommenter(author);
}
}
if (commentDTO.getCommentOriginalCommentId() != null) {
Author commentOriginalAuthor = commentMapper.selectCommentOriginalAuthor(commentDTO.getCommentOriginalCommentId());
if (commentOriginalAuthor != null) {
commentDTO.setCommentOriginalAuthorThumbnailURL(commentOriginalAuthor.getUserAvatarURL());
}
}
});
return commentDTOList;
}
@Override
public Map postComment(Comment comment, HttpServletRequest request) {
Map map = new HashMap(1);
if(comment.getCommentArticleId() == null){
map.put("message","非法访问,文章主键异常!");
return map;
}
if(comment.getCommentAuthorId() == null){
map.put("message","非法访问,用户未登录!");
return map;
}
if(StringUtils.isBlank(comment.getCommentContent())){
map.put("message","回帖内容不能为空!");
return map;
}
Article article = articleService.findById(comment.getCommentArticleId().toString());
if (article == null) {
map.put("message","文章不存在!");
return map;
}
String ip = Utils.getIpAddress(request);
String ua = request.getHeader("user-agent");
comment.setCommentIP(ip);
comment.setCommentUA(ua);
comment.setCreatedTime(new Date());
commentMapper.insertSelective(comment);
StringBuilder commentSharpUrl = new StringBuilder(article.getArticlePermalink());
commentSharpUrl.append("/comment/").append(comment.getIdComment());
commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl.toString());
String commentContent = comment.getCommentContent();
if(StringUtils.isNotBlank(commentContent)){
Integer length = commentContent.length();
if(length > MAX_PREVIEW){
length = 200;
}
String commentPreviewContent = commentContent.substring(0,length);
commentContent = Html2TextUtil.getContent(commentPreviewContent);
}
NotificationUtils.saveNotification(article.getArticleAuthorId(),comment.getIdComment(), NotificationConstant.Comment, commentContent);
return map;
}
}

View File

@ -1,9 +1,11 @@
package com.rymcu.vertical.service.impl; package com.rymcu.vertical.service.impl;
import com.rymcu.vertical.core.service.AbstractService; import com.rymcu.vertical.core.service.AbstractService;
import com.rymcu.vertical.dto.ArticleTagDTO;
import com.rymcu.vertical.entity.Article; import com.rymcu.vertical.entity.Article;
import com.rymcu.vertical.entity.Tag; import com.rymcu.vertical.entity.Tag;
import com.rymcu.vertical.entity.User; import com.rymcu.vertical.entity.User;
import com.rymcu.vertical.mapper.ArticleMapper;
import com.rymcu.vertical.mapper.TagMapper; import com.rymcu.vertical.mapper.TagMapper;
import com.rymcu.vertical.service.TagService; import com.rymcu.vertical.service.TagService;
import com.rymcu.vertical.util.UserUtils; import com.rymcu.vertical.util.UserUtils;
@ -29,6 +31,8 @@ public class TagServiceImpl extends AbstractService<Tag> implements TagService {
@Resource @Resource
private TagMapper tagMapper; private TagMapper tagMapper;
@Resource
private ArticleMapper articleMapper;
@Override @Override
@Transactional(rollbackFor = { UnsupportedEncodingException.class,BaseApiException.class }) @Transactional(rollbackFor = { UnsupportedEncodingException.class,BaseApiException.class })
@ -43,6 +47,7 @@ public class TagServiceImpl extends AbstractService<Tag> implements TagService {
Tag tag = new Tag(); Tag tag = new Tag();
tag.setTagTitle(tags[i]); tag.setTagTitle(tags[i]);
tag = tagMapper.selectOne(tag); tag = tagMapper.selectOne(tag);
List<ArticleTagDTO> articleTagDTOList = articleMapper.selectTags(article.getIdArticle());
if(tag == null){ if(tag == null){
tag = new Tag(); tag = new Tag();
tag.setTagTitle(tags[i]); tag.setTagTitle(tags[i]);

View File

@ -42,7 +42,7 @@ public class NotificationUtils {
},executor); },executor);
} }
private static void saveNotification(Integer idUser, Integer dataId, String dataType, String dataSummary) { public static void saveNotification(Integer idUser, Integer dataId, String dataType, String dataSummary) {
ExecutorService executor= new ThreadPoolExecutor(1,1,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); ExecutorService executor= new ThreadPoolExecutor(1,1,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
CompletableFuture.supplyAsync(()-> { CompletableFuture.supplyAsync(()-> {
try { try {

View File

@ -3,7 +3,9 @@ package com.rymcu.vertical.web.api.article;
import com.rymcu.vertical.core.result.GlobalResult; import com.rymcu.vertical.core.result.GlobalResult;
import com.rymcu.vertical.core.result.GlobalResultGenerator; import com.rymcu.vertical.core.result.GlobalResultGenerator;
import com.rymcu.vertical.dto.ArticleDTO; import com.rymcu.vertical.dto.ArticleDTO;
import com.rymcu.vertical.dto.CommentDTO;
import com.rymcu.vertical.service.ArticleService; import com.rymcu.vertical.service.ArticleService;
import com.rymcu.vertical.service.CommentService;
import com.rymcu.vertical.web.api.exception.BaseApiException; import com.rymcu.vertical.web.api.exception.BaseApiException;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -11,6 +13,7 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -22,6 +25,8 @@ public class ArticleController {
@Resource @Resource
private ArticleService articleService; private ArticleService articleService;
@Resource
private CommentService commentService;
@ -51,4 +56,12 @@ public class ArticleController {
return GlobalResultGenerator.genSuccessResult(map); return GlobalResultGenerator.genSuccessResult(map);
} }
@GetMapping("/{id}/comments")
public GlobalResult<Map<String, Object>> commons(@PathVariable Integer id){
List<CommentDTO> commentDTOList = commentService.getArticleComments(id);
Map map = new HashMap<>(1);
map.put("comments", commentDTOList);
return GlobalResultGenerator.genSuccessResult(map);
}
} }

View File

@ -0,0 +1,34 @@
package com.rymcu.vertical.web.api.comment;
import com.rymcu.vertical.core.result.GlobalResult;
import com.rymcu.vertical.core.result.GlobalResultGenerator;
import com.rymcu.vertical.dto.ArticleDTO;
import com.rymcu.vertical.entity.Comment;
import com.rymcu.vertical.service.CommentService;
import com.rymcu.vertical.web.api.exception.BaseApiException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* @author ronger
*/
@RestController
@RequestMapping("/api/v1/comment")
public class CommentController {
@Resource
private CommentService commentService;
@PostMapping("/post")
public GlobalResult postComment(@RequestBody Comment comment, HttpServletRequest request) throws BaseApiException, UnsupportedEncodingException {
Map map = commentService.postComment(comment,request);
return GlobalResultGenerator.genSuccessResult(map);
}
}