|
| 1 | +# 重构评论排序 |
| 2 | + |
| 3 | +现有评论排序——按照评论时间升序,需要新增:按时间降序、按热度(赞数)降序 |
| 4 | + |
| 5 | +1. dao |
| 6 | + |
| 7 | +CommentMapper更新: |
| 8 | + |
| 9 | +```java |
| 10 | +//分页查询评论 |
| 11 | +// orderMode 0时间升序 1时间降序 2赞数降序 |
| 12 | +List<Comment> selectCommentsByEntity(int entityType, int entityId, int offset, int limit, int orderMode); |
| 13 | +``` |
| 14 | + |
| 15 | +sql实现: |
| 16 | + |
| 17 | +```xml |
| 18 | +<select id="selectCommentsByEntity" resultType="Comment"> |
| 19 | +select <include refid="selectFields"></include> |
| 20 | +from comment |
| 21 | +where status = 0 |
| 22 | +and entity_type = #{entityType} |
| 23 | +and entity_id = #{entityId} |
| 24 | +<if test="orderMode==0"> |
| 25 | +order by create_time asc |
| 26 | +</if> |
| 27 | +<if test="orderMode==1"> |
| 28 | + order by create_time desc |
| 29 | +</if> |
| 30 | +limit #{offset}, #{limit} |
| 31 | +</select> |
| 32 | +``` |
| 33 | + |
| 34 | +2. service: |
| 35 | + |
| 36 | +```java |
| 37 | +public List<Comment> findCommentsByEntity(int entityType, int entityId, int offset, int limit, int orderMode){ |
| 38 | + if(orderMode != 2){ |
| 39 | + return commentMapper.selectCommentsByEntity(entityType, entityId, offset, limit, orderMode); |
| 40 | + }else{ |
| 41 | + // 获取所有评论 |
| 42 | + List<Comment> comments = commentMapper.selectCommentsByEntity(entityType, entityId, 0, Integer.MAX_VALUE, 1); |
| 43 | + |
| 44 | + // 对每条评论获取其赞数,并存储在一个Map中 |
| 45 | + Map<Comment, Integer> likeCountMap = new HashMap<>(); |
| 46 | + for(Comment comment : comments){ |
| 47 | + int likeCount = (int) likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId()); |
| 48 | + likeCountMap.put(comment, likeCount); |
| 49 | + } |
| 50 | + |
| 51 | + // 按赞数对评论进行降序排序 |
| 52 | + comments.sort((c1, c2) -> likeCountMap.get(c2) - likeCountMap.get(c1)); |
| 53 | + |
| 54 | + // 返回指定范围内的评论 |
| 55 | + int toIndex = Math.min(offset + limit, comments.size()); |
| 56 | + return comments.subList(offset, toIndex); |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +3. DiscussPostController: |
| 62 | + |
| 63 | +```java |
| 64 | +//帖子详情 |
| 65 | +@RequestMapping(path = "/detail/{discussPostId}", method = RequestMethod.GET) |
| 66 | +public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page |
| 67 | +,@RequestParam(name = "orderMode", defaultValue = "0")int orderMode){ |
| 68 | + //帖子 |
| 69 | + DiscussPost discussPost = discussPostService.findDiscussPostById(discussPostId); |
| 70 | + User user = hostHolder.getUser(); |
| 71 | + if(discussPost.getStatus() == 2 && (user == null || user.getType() != 1)){ |
| 72 | + return "/error/404"; // 非管理员无法查看已删除帖子 |
| 73 | + } |
| 74 | + String content = HtmlUtils.htmlUnescape(discussPost.getContent()); // 内容反转义,不然 markdown 格式无法显示 |
| 75 | + discussPost.setContent(content); |
| 76 | + model.addAttribute("post", discussPost); |
| 77 | + |
| 78 | + //作者 |
| 79 | + user = userService.findUserById(discussPost.getUserId()); |
| 80 | + model.addAttribute("user", user); |
| 81 | + |
| 82 | + // 赞 |
| 83 | + long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId); |
| 84 | + model.addAttribute("likeCount", likeCount); |
| 85 | + int likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_POST, discussPostId); |
| 86 | + model.addAttribute("likeStatus", likeStatus); |
| 87 | + |
| 88 | + //评论分页信息 |
| 89 | + page.setLimit(5); |
| 90 | + page.setPath("/discuss/detail/" + discussPostId); |
| 91 | + page.setRows(discussPost.getCommentCount()); |
| 92 | + List<Comment> commentList = commentService. |
| 93 | + findCommentsByEntity(ENTITY_TYPE_POST, discussPost.getId(), page.getOffset(), page.getLimit(), orderMode); |
| 94 | + |
| 95 | + //找到评论的用户 |
| 96 | + List<Map<String, Object>> commentVoList = new ArrayList<>(); // Vo = view objects 显示对象 |
| 97 | + if(commentList != null){ |
| 98 | + for(Comment comment : commentList){ |
| 99 | + Map<String, Object> commentVo = new HashMap<>(); |
| 100 | + // 评论 |
| 101 | + commentVo.put("comment", comment); |
| 102 | + // 作者 |
| 103 | + commentVo.put("user", userService.findUserById(comment.getUserId())); |
| 104 | + // 赞 |
| 105 | + likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId()); |
| 106 | + commentVo.put("likeCount", likeCount); |
| 107 | + likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId()); |
| 108 | + commentVo.put("likeStatus", likeStatus); |
| 109 | + |
| 110 | + //评论的评论——回复 |
| 111 | + List<Comment> replyList = commentService. |
| 112 | + findCommentsByEntity(ENTITY_TYPE_COMMENT, |
| 113 | + comment.getId(), 0, Integer.MAX_VALUE,0); // 回复就不需要分页了,就一页显示所有评论,且按回复顺序显示 |
| 114 | + |
| 115 | + //找到回复的用户 |
| 116 | + List<Map<String, Object>> replyVoList = new ArrayList<>(); |
| 117 | + if(replyList != null){ |
| 118 | + for(Comment reply : replyList){ |
| 119 | + Map<String, Object> replyVo = new HashMap<>(); |
| 120 | + // 回复 |
| 121 | + replyVo.put("reply", reply); |
| 122 | + // 作者 |
| 123 | + replyVo.put("user", userService.findUserById(reply.getUserId())); |
| 124 | + // 赞 |
| 125 | + likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId()); |
| 126 | + replyVo.put("likeCount", likeCount); |
| 127 | + likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId()); |
| 128 | + replyVo.put("likeStatus", likeStatus); |
| 129 | + |
| 130 | + //回复的目标 |
| 131 | + User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId()); |
| 132 | + |
| 133 | + replyVo.put("target", target); |
| 134 | + replyVoList.add(replyVo); |
| 135 | + } |
| 136 | + } |
| 137 | + commentVo.put("replys", replyVoList); |
| 138 | + |
| 139 | + int replycnt = commentService.findCommentCount(ENTITY_TYPE_COMMENT, comment.getId()); |
| 140 | + commentVo.put("replyCount", replycnt); |
| 141 | + |
| 142 | + commentVoList.add(commentVo); |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | + model.addAttribute("comments", commentVoList); |
| 147 | + |
| 148 | + // 增加帖子访问量 |
| 149 | + discussPostService.updatePostReadCount(discussPostId); |
| 150 | + String redisKey = RedisKeyUtil.getPostReadKey(discussPostId); |
| 151 | + if(redisKey != null){ |
| 152 | + model.addAttribute("postReadCount", redisTemplate.opsForValue().get(redisKey)); |
| 153 | + }else { |
| 154 | + model.addAttribute("postReadCount", discussPost.getReadCount()); |
| 155 | + } |
| 156 | + |
| 157 | + model.addAttribute("orderMode", orderMode); |
| 158 | + |
| 159 | + return "/site/discuss-detail"; |
| 160 | +} |
| 161 | +``` |
| 162 | + |
| 163 | +4. discuss-detail前端: |
| 164 | + |
| 165 | +```html |
| 166 | +<!-- 回帖数量 --> |
| 167 | +<div class="row"> |
| 168 | + <div class="col-8"> |
| 169 | + <h6><b class="square"></b> <i th:text="${post.commentCount}">30</i>条评论</h6> |
| 170 | + </div> |
| 171 | + <div class="col-4 text-right"> |
| 172 | + <a href="#replyform" class="btn btn-primary btn-sm"> 评 论 </a> |
| 173 | + </div> |
| 174 | +</div> |
| 175 | +<!-- 添加排序选项 --> |
| 176 | +<ul class="nav nav-tabs mb-3"> |
| 177 | + <li class="nav-item"> |
| 178 | + <a th:class="|nav-link ${orderMode==1?'active':''}|" th:href="@{/discuss/detail/{discussPostId}(discussPostId=${post.id}, orderMode=1)}">最新</a> |
| 179 | + </li> |
| 180 | + <li class="nav-item"> |
| 181 | + <a th:class="|nav-link ${orderMode==0?'active':''}|" th:href="@{/discuss/detail/{discussPostId}(discussPostId=${post.id}, orderMode=0)}">默认</a> |
| 182 | + </li> |
| 183 | + <li class="nav-item"> |
| 184 | + <a th:class="|nav-link ${orderMode==2?'active':''}|" th:href="@{/discuss/detail/{discussPostId}(discussPostId=${post.id}, orderMode=2)}">最热</a> |
| 185 | + </li> |
| 186 | +</ul> |
| 187 | + |
| 188 | +<span class="badge badge-secondary float-right floor" th:if="${orderMode==0}"> |
| 189 | + <i th:text="${page.offset + cvoStat.count}">1</i> <!--当前楼层数 = 当前页起始楼 + 当前页循环数--> |
| 190 | + 楼 |
| 191 | +</span> |
| 192 | +``` |
0 commit comments