评论表
CREATE TABLE `comment` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int DEFAULT NULL,
`entity_type` int DEFAULT NULL, #对帖子的评论、对评论的评论、用户
`entity_id` int DEFAULT NULL, # 具体类型的id,如果评论的是帖子,则对应的是帖子的id
`target_id` int DEFAULT NULL, #记录评论指向哪个人, 如果评论的是回复,这个值才有,否则无
`content` text,
`status` int DEFAULT NULL, #0表示正常 1表示已经被删除
`create_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_user_id` (`user_id`) /*!80000 INVISIBLE */,
KEY `index_entity_id` (`entity_id`)
) ENGINE=InnoDB AUTO_INCREMENT=276 DEFAULT CHARSET=utf8
新建Comment实体类
package com.newcoder.community.entity;
import java.util.Date;
public class Comment {
private int id;
private int userId;
private int entityType;
private int entityId;
private int targetId;
private String content;
private int status;
private Date createTime;
}
数据访问组件-CommentMapper.java
@Mapper
public interface CommentMapper {
List<Comment> selectCommentByEntity(int entityType, int entityId, int offset, int limit);
int selectCountByEntity(int entityType, int entityId);
}
<sql id="selectFields">
id, user_id, entity_type, entity_id, target_id, content, status, create_time
</sql>
<select id="selectCommentByEntity" resultType="Comment">
select <include refid="selectFields"></include>
from comment
where status = 0
and entity_type = #{entityType}
and entity_id = #{entityId}
order by create_time asc
limit #{offset}, #{limit}
</select>
<select id="selectCountByEntity" resultType="int">
select count(id)
from comment
where status = 0
and entity_type = #{entityType}
and entity_id = #{entityId}
</select>
业务组件层-CommentService
public List<Comment> findCommentByEntity(int entityType, int entityId, int offset, int limit){
return commentMapper.selectCommentByEntity(entityType, entityId, offset, limit);
}
public int findCommentCount(int entityType, int entityId){
return commentMapper.selectCountByEntity(entityType, entityId);
}
表现层DiscussPostController层-查询帖子方法之中,同时查询帖子的评论
//只要是实体类,spring都会把这些实体类注入到model之中
@RequestMapping(path = "/detail/{discussPostId}", method = RequestMethod.GET)
public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page){
//帖子
DiscussPost post = discussPostService.findDiscussPostById(discussPostId);
model.addAttribute("post",post);
//作者
User user = userService.findUserById(post.getUserId());
model.addAttribute("user", user);
//评论分页信息
page.setLimit(5);
page.setPath("/discuss/detail/" + discussPostId);
page.setRows(post.getCommentCount());
//评论:给帖子的评论
//回复:给评论的评论
//评论列表
List<Comment> commentList = commentService.findCommentByEntity(
ENTITY_TYPE_POST, post.getId(), page.getOffset(), page.getLimit());
//评论VO列表
List<Map<String, Object>> commentVoList = new ArrayList<>();
if(commentList != null){
for(Comment comment: commentList){
//评论 VO View Object(显示的对象)
Map<String, Object> commentVo = new HashMap<>();
//评论
commentVo.put("comment", comment);
//作者
commentVo.put("user", userService.findUserById(comment.getUserId()));
//回复列表- 给评论的评论 - 每个Comment都由
List<Comment> replyList = commentService.findCommentByEntity(
ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE);
List<Map<String, Object>> replyVolist = new ArrayList<>();
if(replyList != null){
for(Comment reply : replyList){
Map<String, Object> replyVo = new HashMap<>();
//回复
replyVo.put("reply", reply);
//作者
replyVo.put("user", userService.findUserById(reply.getUserId()));
//回复目标
User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId());
replyVo.put("target", target);
replyVolist.add(replyVo);
}
}
commentVo.put("replys", replyVolist);
//回复数量
int replyCount = commentService.findCommentCount(ENTITY_TYPE_COMMENT, comment.getId());
commentVo.put("replyCount", replyCount);
commentVoList.add(commentVo);
}
}
model.addAttribute("comments", commentVoList);
return "/site/discuss-detail";
}
处理帖子详情页面 discuss-detail.html
<ul class="list-unstyled mt-4">
<!-- 第1条回帖 -->
<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="cvo:${comments}">
<a href="profile.html">
<img th:src="${cvo.user.headerUrl}" class="align-self-start mr-4 rounded-circle user-header" alt="用户头像" >
</a>
<div class="media-body">
<div class="mt-0">
<span class="font-size-12 text-success" th:utext="${cvo.user.username}">掉脑袋切切</span>
<span class="badge badge-secondary float-right floor">
<i th:text="${page.offset + cvoStat.count}"></i>#
</span>
</div>
<div class="mt-2" th:utext="${cvo.comment.content}">
这开课时间是不是有点晚啊。。。
</div>
<div class="mt-4 text-muted font-size-12">
<span>发布于 <b th:text="${#dates.format(cvo.comment.createTime, 'yyyy-mm-dd HH:mm:ss')}">2019-04-15 15:32:18</b></span>
<ul class="d-inline float-right">
<li class="d-inline ml-2">
<a href="javascript:;" th:onclick="|like(this,2,${cvo.comment.id},${cvo.comment.userId}), ${post.id};|" class="text-primary">
<b th:text="${cvo.likeStatus==1?'已赞':'赞'}">赞</b>(<i th:text="${cvo.likeCount}">1</i>)
</a>
</li>
<li class="d-inline ml-2">|</li>
<li class="d-inline ml-2"><a href="#" class="text-primary">回复(<i th:text="${cvo.replyCount}"> 2</i>)</a>
</ul>
</div>
<!-- 回复列表 -->
<ul class="list-unstyled mt-4 bg-gray p-3 font-size-12 text-muted">
<li class="pb-3 pt-3 mb-3 border-bottom" th:each="rvo:${cvo.replys}">
<div>
<span th:if="${rvo.target==null}">
<b class="text-info" th:text="${rvo.user.username}">寒江雪</b>
</span>
<span th:if="${rvo.target!=null}">
<i class="text-info" th:text="${rvo.user.username}">Sissi</i>回复
<b class="text-info" th:text="${rvo.target.username}">寒江雪</b>:
</span>
<span th:utext="${rvo.reply.content}">这个是直播时间哈,觉得晚的话可以直接看之前的完整录播的~</span>
</div>
<div class="mt-3">
<span th:text="${#dates.format(rvo.reply.createTime, 'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</span>
<ul class="d-inline float-right">
<li class="d-inline ml-2">
<a href="javascript:;" th:onclick="|like(this,2,${rvo.reply.id}, ${rvo.reply.userId}, ${post.id});|">
<b th:text="${rvo.likeStatus==1?'已赞':'赞'}">赞</b>(<i th:text="${rvo.likeCount}">1</i>)
</a>
</li>
<li class="d-inline ml-2">|</li>
<li class="d-inline ml-2"><a th:href="|#huifu-${rvoStat.count}|" data-toggle="collapse" class="text-primary">回复</a></li>
</ul>
<div th:id="|huifu-${rvoStat.count}|" class="mt-4 collapse">
<form method="post" th:action="@{|/comment/add/${post.id}|}">
<div>
<input type="text" class="input-size" name="content" th:placeholder="@{|回复${rvo.user.username}|}"/>
<input type="hidden" name="entityType" value="2">
<input type="hidden" name="entityId" th:value="${cvo.comment.id}">
<input type="hidden" name="targetId" th:value="${rvo.user.id}">
</div>
<div class="text-right mt-2">
<button type="submit" class="btn btn-primary btn-sm" > 回 复 </button>
</div>
</form>
</div>
</div>
</li>
<!-- 回复输入框 -->
<li class="pb-3 pt-3">
<form method="post" th:action="@{|/comment/add/${post.id}|}">
<div>
<input type="text" class="input-size" name="content" placeholder="请输入你的观点"/>
<input type="hidden" name="entityType" value="2">
<input type="hidden" name="entityId" th:value="${cvo.comment.id}">
</div>
<div class="text-right mt-2">
<button type="submit" class="btn btn-primary btn-sm"> 回 复 </button>
</div>
</form>
</li>
</ul>
</div>
</li>
</ul>
项目遇到的问题:STAR法则