一 需求描述
1. 当分享发布一条头条消息后,当前用户可在指定消息内评论头条;
2. 评论完成后能够在当前页面显示以及评论数的改变
效果描述:
二 具体实现
1. DB
DROP TABLE IF EXISTS `comment`; CREATE TABLE `comment`( `id` int NOT NULL AUTO_INCREMENT, `content` TEXT NOT NULL comment '评论内容', `entity_id` INT NOT NULL comment '实体id', `entity_type` INT NOT NULL comment '实体类型', `created_date` DATETIME NOT NULL comment '创建日期', `user_id` INT NOT NULL comment '评论用户id', `status` INT NOT NULL DEFAULT 0 comment '评论会话状态', PRIMARY KEY(`id`), INDEX `entity_index `(`entity_id` ASC ,`entity_type` ASC ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='评论中心';
2. Model
package com.nowcoder.model; import org.springframework.stereotype.Component; import java.util.Date; /** * Created by Administrator on 2017/4/29. */ @Component public class Comment { private int id; private String content; private int entityId; private int entityType; private Date createdDate; private int userId; private int status; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public int getEntityId() { return entityId; } public void setEntityId(int entityId) { this.entityId = entityId; } public int getEntityType() { return entityType; } public void setEntityType(int entityType) { this.entityType = entityType; } public Date getCreatedDate() { return createdDate; } public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } }
3. Dao:
int addCommnet(Comment comment); 添加评论 List<Comment> selectByEntity(@Param("entityId") int entityId, @Param("entityType") int entityType); : 根据entityId查询所有评论; int getCommentCount(@Param("entityId") int entityId, @Param("entityType") int entityType); : 获取所有评论数量 void updateStatus(@Param("entityId") int entityId, @Param("entityType") int entityType, @Param("status") int status); 删除评论
有两个点要说一下: entityId 和entityType 一起 代表一个咨询。这里type即为news,而entityId 即为newsId.假如还有news,topics等等别的可以直接套用。
第二个就是删除评论,并不是直接删除,而是将status设置为1.
package com.nowcoder.dao; import com.nowcoder.model.Comment; import org.apache.ibatis.annotations.*; import java.util.List; /** * Created by Administrator on 2017/4/29. */ @Mapper public interface CommentDao { String TABLE_NAME = "comment"; String INSERT_FIELDS = "content, entity_id, entity_type, created_date, user_id, status"; String SELECT_FIELDS = "id," + INSERT_FIELDS; @Insert({"insert into", TABLE_NAME, "(", INSERT_FIELDS, ") values(#{content}, #{entityId}, #{entityType}, #{createdDate}, #{userId}, #{status})" }) int addCommnet(Comment comment); @Select({"select", SELECT_FIELDS, "from", TABLE_NAME, "where entity_id = #{entityId} and entity_type=#{entityType} order by id desc"}) List<Comment> selectByEntity(@Param("entityId") int entityId, @Param("entityType") int entityType); @Select({"select count(id) from", TABLE_NAME, "where entity_id = #{entityId} and entity_type=#{entityType}"}) int getCommentCount(@Param("entityId") int entityId, @Param("entityType") int entityType); @Update({"update", TABLE_NAME, "set status=#{status} where entity_id = #{entityId} and entity_type=#{entityType}"}) void updateStatus(@Param("entityId") int entityId, @Param("entityType") int entityType, @Param("status") int status); }
4. Service:
package com.nowcoder.service; import com.nowcoder.dao.CommentDao; import com.nowcoder.model.Comment; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * Created by Administrator on 2017/4/29. */ @Service public class CommentService { @Autowired CommentDao commentDao; public List<Comment> getCommentsByEntity(int entityId, int entityType){ return commentDao.selectByEntity(entityId, entityType); } public int addComment(Comment comment){ return commentDao.addCommnet(comment); } public int getCommentCount(int entityId, int entityType){ return commentDao.getCommentCount(entityId, entityType); } public void deleteComment(int entityId, int entityType){ //模拟删除评论,status=1表示会话失效即被删除不显示 commentDao.updateStatus(entityId, entityType, 1); } }
5.Controller:
(1)增加评论:
/** * 增加评论 * @param newsId * @param content * @return */ @RequestMapping(path = {"/addComment"}, method = {RequestMethod.POST}) public String addComment(@RequestParam("newsId") int newsId, @RequestParam("content") String content){ try{ //防止评论中有转义字符 content = HtmlUtils.htmlEscape(content); //过滤评论内容content Comment comment = new Comment(); comment.setUserId(hostHolder.getUser().getId()); comment.setEntityId(newsId); comment.setEntityType(EntityType.ENTITY_NEWS); comment.setContent(content); comment.setCreatedDate(new Date()); comment.setStatus(0);//0 有效,1 表示评论被删除 commentService.addComment(comment); //更新评论数量 int count = commentService.getCommentCount(comment.getEntityId(), comment.getEntityType()); newsService.updateCommentCount(comment.getEntityId(), count); //异步化更新数量 }catch (Exception e){ logger.error("增加评论失败!" + e.getMessage()); } return "redirect:/news/" + String.valueOf(newsId); }
(2)显示评论:
/** * 查看资讯详情页 * @param newsId * @param model * @return */ @RequestMapping(path = {"/news/{newsId}"}, method = {RequestMethod.GET}) public String newsDetail(@PathVariable("newsId") int newsId, Model model){ News news = newsService.getById(newsId); //显示评论内容 if(news != null){ List<Comment> commentList = commentService.getCommentsByEntity(news.getId(), EntityType.ENTITY_NEWS); List<ViewObject> commentVOs = new ArrayList<>(); for(Comment comment : commentList){ ViewObject vo = new ViewObject(); vo.set("comment", comment); vo.set("user", userService.getUser(comment.getUserId())); commentVOs.add(vo); } model.addAttribute("comments", commentVOs); } //评论 model.addAttribute("news", news); model.addAttribute("owner", userService.getUser(news.getUserId())); return "detail"; }
6.HTML: detail.html
#parse("header.html") <div id="main"> <div class="container"> <div class="post detail"> <div class="votebar"> #if($like>0) <button class="click-like up pressed" data-id="$!{news.id}" title="赞同"><i class="vote-arrow"></i><span class="count">$!{news.likeCount}</span></button> #else <button class="click-like up" data-id="$!{news.id}" title="赞同"><i class="vote-arrow"></i><span class="count">$!{news.likeCount}</span></button> #end #if($like<0) <button class="click-dislike down pressed" data-id="$!{news.id}" title="反对"><i class="vote-arrow"></i></button> #else <button class="click-dislike down" data-id="$!{news.id}" title="反对"><i class="vote-arrow"></i></button> #end </div> <div class="content"> <div class="content-img"> <img src="$!{news.image}" alt=""> </div> <div class="content-main"> <h3 class="title"> <a target="_blank" rel="external nofollow" href="$!{news.link}">$!{news.title}</a> </h3> <div class="meta"> $!{news.link} <span> <i class="fa icon-comment"></i> $!{news.commentCount} </span> </div> </div> </div> <div class="user-info"> <div class="user-avatar"> <a href="/user/$!{owner.id}"><img width="32" class="img-circle" src="$!{owner.headUrl}"></a> </div> </div> <div class="subject-name">来自 <a href="/user/$!{owner.id}">$!{owner.name}</a></div> </div> <div class="post-comment-form"> #if($user) <span>评论 ($!{news.commentCount})</span> <form method="post" action="/addComment"> <input name="newsId" type="hidden" value="$!{news.id}"> <div class="form-group text required comment_content"> <label class="text required sr-only"> <abbr title="required">*</abbr> 评论</label> <textarea rows="5" class="text required comment-content form-control" name="content" id="content"></textarea> </div> <div class="text-right"> <input type="submit" name="commit" value="提 交" class="btn btn-default btn-info"> </div> </form> #else <div class="login-actions"> <a class="btn btn-success" href="/?pop=1">登录后评论</a> </div> #end </div> <div id="comments" class="comments"> #foreach($commentvo in $comments) <div class="media"> <a class="media-left" href="/user/$!{commentvo.user.id}"> <img src="$!{commentvo.user.headUrl}"> </a> <div class="media-body"> <h4 class="media-heading"> <small class="date">$date.format('yyyy-MM-dd HH:mm:ss', $!{commentvo.comment.createdDate}) </small> </h4> <div>$!{commentvo.comment.content}</div> </div> </div> #end </div> </div> <script type="text/javascript"> $(function(){ // If really is weixin $(document).on('WeixinJSBridgeReady', function() { $('.weixin-qrcode-dropdown').show(); var options = { "img_url": "", "link": "http://nowcoder.com/j/wt2rwy", "desc": "", "title": "读《Web 全栈工程师的自我修养》" }; WeixinJSBridge.on('menu:share:appmessage', function (argv){ WeixinJSBridge.invoke('sendAppMessage', options, function (res) { // _report('send_msg', res.err_msg) }); }); WeixinJSBridge.on('menu:share:timeline', function (argv) { WeixinJSBridge.invoke('shareTimeline', options, function (res) { // _report('send_msg', res.err_msg) }); }); // $(window).on('touchmove scroll', function() { // if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { // $('div.backdrop').show(); // $('div.share-help').show(); // } else { // $('div.backdrop').hide(); // $('div.share-help').hide(); // } // }); }); }) </script> <script type="text/javascript" src="/scripts/main/site/detail.js"></script> </div> #parse("footer.html")