最近在写一个论坛项目,想做一个评论区,但是在网上也搜不到写的比较好的,就寻思那自己构思写一个吧。
先上效果图:
这个评论区是仿知乎做的,虽然做的比较丑吧,日期也没有做个格式化,但是该有的东西应该是有了。其中点击评论图标,会将隐藏的评论框显示出来。
那么先上后台代码
数据库表分两个
root_comment
aid即文章id,uid即发布者的id,text即评论文本
son_comment
pid表示根评论的id,而psid表示这条评论是回复的哪一条子评论,为null表示回复的是根评论
还要用到用户信息表,展示头像和昵称要用到
user_information
那么,上后台代码
持久层mapper没什么可说的,由于使用的MP,很简单,省略
获取评论并传输至前端
先来写两个DO将根评论,子评论封装一下
RootCommentDO
import lombok.Data;
import java.util.Date;
@Data
public class RootCommentDO {
private Integer id;
private Integer aid;
private Date gmtCreate;
private String name;
private String headImg;
private String text;
}
SonCommentDO
package com.protal.community.DO;
import lombok.Data;
import java.util.Date;
@Data
public class SonCommentDO {
private Integer id;
private String pname;
private String text;
private Date gmtCreate;
private String name;
private String headImg;
}
然后写个DTO传输对象
ArticalCommentDTO
package com.protal.community.dto;
import com.protal.community.DO.RootCommentDO;
import com.protal.community.DO.SonCommentDO;
import lombok.Data;
import java.util.List;
@Data
public class ArticalCommentDTO {
private RootCommentDO rootCommentDO;
private List sonCommentList;
}
后台获取文章就直接按根评论最新在前,子评论最新在后排序
通过文章id获取评论的方法
getCommentByArticalId
@Override
public List getCommentByArticalId(Integer aid) {
List list = new ArrayList<>();
//选出根评论
QueryWrapper queryWrapper = new QueryWrapper();
Map params = new HashMap();
params.put("aid", aid);
queryWrapper.orderByDesc("gmt_create").allEq(params);
List rootComments = rootCommentMapper.selectList(queryWrapper);
List articalCommentDTOS = new ArrayList<>();
for (RootComment comment : rootComments) {
ArticalCommentDTO articalCommentDTO = new ArticalCommentDTO();
//把根评论加入列表
RootCommentDO rootCommentDO = new RootCommentDO();
UserInformation userInformation = userInformationMapper.selectById(comment.getUid());
rootCommentDO.setHeadImg(userInformation.getHeadImg());
rootCommentDO.setName(userInformation.getName());
rootCommentDO.setGmtCreate(comment.getGmtCreate());
rootCommentDO.setId(comment.getId());
rootCommentDO.setText(comment.getText());
rootCommentDO.setGmtCreate(comment.getGmtCreate());
articalCommentDTO.setRootCommentDO(rootCommentDO);
//将子评论按时间排序后加入列表
Map params1 = new HashMap();
List sonComments = new ArrayList<>();
params1.put("pid", comment.getId());
QueryWrapper queryWrapper1 = new QueryWrapper();
queryWrapper1.orderByAsc("gmt_create").allEq(params1);
sonComments = sonCommentMapper.selectList(queryWrapper1);
List list1 = new ArrayList<>();
for (SonComment sonComment : sonComments) {
UserInformation userInformation1 = userInformationMapper.selectById(sonComment.getUid());
SonCommentDO sonCommentDO = new SonCommentDO();
sonCommentDO.setHeadImg(userInformation1.getHeadImg());
sonCommentDO.setName(userInformation1.getName());
sonCommentDO.setGmtCreate(sonComment.getGmtCreate());
sonCommentDO.setText(sonComment.getText());
sonCommentDO.setId(sonComment.getId());
if (sonComment.getPsid() == null) {
Integer uid = rootCommentMapper.selectById(sonComment.getPid()).getUid();
String name = userInformationMapper.selectById(uid).getName();
sonCommentDO.setPname(name);
} else {
sonCommentDO.setPname(userInformationMapper.selectById(sonCommentMapper.selectById(sonComment.getPsid()).getUid()).getName());
}
list1.add(sonCommentDO);
}
articalCommentDTO.setRootCommentDO(rootCommentDO);
articalCommentDTO.setSonCommentList(list1);
articalCommentDTOS.add(articalCommentDTO);
}
return articalCommentDTOS;
}
controller获取articalCommentDTOS并传递给前端省略(命名为comment)
前端显示代码
()
()
@:
那么前台需要的一些js函数
function getThis(obj){
var pinglun = $(obj).next();
pinglun.css({'display':'block'});
}
function submitRootComment(obj){
var text = $(obj).parent().prev().val();
var aid = $("#articalId").attr("value");
$.ajax({
url: "http://localhost:8080/submitRootComment",
type: 'GET',
data:{
text: text,
aid:aid
},
success: function (data) {
$(".comment").html(data);
if ($(".error").attr("value") == '1'){
alert("评论请先登录");
}
}
})
}
function submitLevelOneComment(obj){
var text = $(obj).parent().prev().val();
var fatherId = $(obj).next().attr("value");
var aid = $("#articalId").attr("value");
$.ajax({
url: "http://localhost:8080/submitLevelOneComment",
type: 'GET',
data:{
text: text,
fatherId:fatherId,
aid:aid
},
success: function (data) {
$(".comment").html(data);
if ($(".error").attr("value") == '1'){
alert("评论请先登录");
}
}
})
}
function submitLevelTwoComment(obj){
var text = $(obj).parent().prev().val();
var fatherId = $(obj).next().attr("value");
var answerId = $(obj).next().next().attr("value");
var aid = $("#articalId").attr("value");
$.ajax({
url: "http://localhost:8080/submitLevelTwoComment",
type: 'GET',
data:{
text: text,
fatherId:fatherId,
aid:aid,
answerId:answerId
},
success: function (data) {
$(".comment").html(data);
if ($(".error").attr("value") == '1'){
alert("评论请先登录");
}
}
})
}
后台controller的对应处理办法
package com.protal.community.controller;
import com.protal.community.dto.ArticalCommentDTO;
import com.protal.community.pojo.ArticalInformation;
import com.protal.community.pojo.RootComment;
import com.protal.community.pojo.SonComment;
import com.protal.community.pojo.UserInformation;
import com.protal.community.service.ArticalInformationService;
import com.protal.community.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
@Controller
public class CommentController {
@Autowired
private CommentService commentService;
@Autowired
private ArticalInformationService articalInformationService;
@GetMapping("/submitRootComment")
public String submitRootComment(HttpServletRequest request, Model model) throws IOException {
String text = request.getParameter("text");
Integer aid = Integer.valueOf(request.getParameter("aid"));
if(request.getSession().getAttribute("userInformation") == null) {
model.addAttribute("error","1");
ArticalInformation articalInformation = articalInformationService.selectArticalInformationById(aid);
model.addAttribute("articalInformation",articalInformation);
List commentByArticalId = commentService.getCommentByArticalId(aid);
model.addAttribute("comment",commentByArticalId);
return "artical::comment";
}else {
UserInformation userInformation = (UserInformation) request.getSession().getAttribute("userInformation");
Integer uid = userInformation.getId();
RootComment comment = new RootComment();
comment.setAid(aid);
comment.setUid(uid);
comment.setText(text);
commentService.insertOneRootComment(comment);
//重新拉取评论并显示
List commentByArticalId = commentService.getCommentByArticalId(aid);
model.addAttribute("comment",commentByArticalId);
ArticalInformation articalInformation = articalInformationService.selectArticalInformationById(aid);
model.addAttribute("articalInformation",articalInformation);
return "artical::comment";
}
}
@GetMapping("/submitLevelOneComment")
public String submitLevelOneComment(HttpServletRequest request,Model model) {
Integer fatherId = Integer.valueOf(request.getParameter("fatherId"));
String text = request.getParameter("text");
Integer aid = Integer.valueOf(request.getParameter("aid"));
if (request.getSession().getAttribute("userInformation") == null) {
model.addAttribute("error", "1");
List commentByArticalId = commentService.getCommentByArticalId(aid);
model.addAttribute("comment", commentByArticalId);
return "artical::comment";
} else {
UserInformation userInformation = (UserInformation) request.getSession().getAttribute("userInformation");
Integer uid = userInformation.getId();
SonComment sonComment = new SonComment();
sonComment.setText(text);
sonComment.setUid(uid);
sonComment.setPid(fatherId);
commentService.insertOneSonComment(sonComment);
//重新拉取评论并显示
List commentByArticalId = commentService.getCommentByArticalId(aid);
model.addAttribute("comment",commentByArticalId);
ArticalInformation articalInformation = articalInformationService.selectArticalInformationById(aid);
model.addAttribute("articalInformation",articalInformation);
return "artical::comment";
}
}
@GetMapping("/submitLevelTwoComment")
public String submitLevelTwoComment(HttpServletRequest request,Model model){
Integer fatherId = Integer.valueOf(request.getParameter("fatherId"));
String text = request.getParameter("text");
Integer aid = Integer.valueOf(request.getParameter("aid"));
Integer answerId = Integer.valueOf(request.getParameter("answerId"));
if (request.getSession().getAttribute("userInformation") == null) {
model.addAttribute("error", "1");
List commentByArticalId = commentService.getCommentByArticalId(aid);
model.addAttribute("comment", commentByArticalId);
return "artical::comment";
}else {
UserInformation userInformation = (UserInformation) request.getSession().getAttribute("userInformation");
Integer uid = userInformation.getId();
SonComment sonComment = new SonComment();
sonComment.setText(text);
sonComment.setUid(uid);
sonComment.setPid(fatherId);
sonComment.setPsid(answerId);
commentService.insertOneSonComment(sonComment);
//重新拉取评论并显示
List commentByArticalId = commentService.getCommentByArticalId(aid);
model.addAttribute("comment",commentByArticalId);
ArticalInformation articalInformation = articalInformationService.selectArticalInformationById(aid);
model.addAttribute("articalInformation",articalInformation);
return "artical::comment";
}
}
}
@Override
public void insertOneRootComment(RootComment rootComment) {
rootCommentMapper.insert(rootComment);
}
@Override
public void insertOneSonComment(SonComment sonComment) {
sonCommentMapper.insert(sonComment);
}
然后可以优化的点:由于有“@某人”这个东西,导致查询的时候很费劲,为了这个昵称去查询一遍user_information感觉太得不偿失了,不如直接插入评论的时候直接插入这个名字,保留一定的冗余性,可以节省很多curd操作,所以更好的是在评论表里加一列信息,直接保存。
然后就是发表评论时每次都是重新从后台获取,或许前端可以直接实现,让后台边做事情,也不耽误前端使用,但是我前端太菜了,就没做,不过这个也是毕设的一个项目而已,先做完再想优化吧~



