目录
设计思路
分析
首先需要设计评论信息的实体类(对应评论表)
@Data
public class CommentInfo {
private Integer id; // 评论 id
private Integer aid; // 文章 id
private Integer uid; // 发布评论的用户 id
private String nickname; // 该用户的昵称
private String photo; //该用户的头像
private String comment; //评论信息
//格式化时间处理
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime createtime; //评论发布的时间
}
主要分为以下三个功能:
- 显示所有评论:当我们进入文章详情页的时候,页面就会通过 ajax 发送请求给服务器,这个请求中就带有这篇文章的 id ,服务器就可以通过文章的 id 获取评论数据,最后返回给客户端。
- 增加评论:当用户在评论框中输入评论,点击评论按钮就会触发 ajax 请求,请求中就带有这篇文章的 id 和用户评论的信息,服务器接收到请求后,通过 session 获取用户的 id 数据,将 用户 id 、文章 id 、评论信息,这三个数据增加到评论表中的一条数据中,最后通过 js 刷新页面,重新展示评论信息。
- 删除评论:如果用户点击删除评论按钮,就会触发 ajax 请求,请求中带有的数据是要删除评论的 id(这是展示显示所有评论信息的时候,从后端的时候得到的) 和这篇文章作者的 id ,服务器接收到请求后,通过 session 获取当前登录用户信息,在使用文章作者 id 获取文章作者的信息,接着通过评论 id 获取评论详细信息,若评论信息中的用户 id 不等于当前登录用户的 id、或者是评论信息中的作者 id 不等于当前登录用户的 id 时,则不能删除评论(删除评论的人只能是该文章的作者,或者是这个评论的发布人),否则进行删除评论操作,最后通过 js 刷新页面,重新展示评论信息。
前后端交互接口
显示评论请求
POST /comment/show
Content-Type: application/json
{
"aid": id //文章 id
}
显示评论响应
HTTP/1.1 200 OK
Content-Type: application/json
{
"list": commentinfoList //所有评论信息
}
添加评论请求
POST /comment/add
Content-Type: application/json
{
"aid": id, //文章 id
"comment": inputComment.val() //评论信息
}
添加评论响应
HTTP/1.1 200 OK
Content-Type: application/json
{
"commentinfo": commentinfo //文章信息
}
删除评论请求
POST /comment/del
Content-Type: application/json
{
"id": id, //评论 id
"autid": autid //文章作者 id
}
删除评论响应
HTTP/1.1 200 OK
Content-Type: application/json
{
"code": 200, //状态码
"msg": "", //状态信息
"data": 1 //数据
}
代码实现和详细注释
数据库设计
评论表设计如下:
create table commentinfo(
id int primary key auto_increment,
aid int references articleinfo(id),
uid int references userinfo(id),
nickname varchar(50) not null,
photo varchar(500) default '',
comment varchar(1000),
createtime timestamp default current_timestamp
);
前后端交互
客户端开发
js代码如下:
//展示评论信息
function showComment() {
jQuery.ajax({
type: "POST",
url: "/comment/show",
data: {
"aid": id,
},
success: function (result) {
if (result != null && result.code == 200) {
var CommentListDiv = "";
for (var i = 0; i < result.data.length; i++) {
var CommentInfo = result.data[i];
CommentListDiv += '<div class="card">';
CommentListDiv += '<img src="' + CommentInfo.photo + '" alt="">';
CommentListDiv += '<span class="reviewer"><strong>' + CommentInfo.nickname + ':</strong></span>';
CommentListDiv += '<span id="createtime">' + CommentInfo.createtime + '</span>'
CommentListDiv += '<p class="comment">';
CommentListDiv += CommentInfo.comment;
CommentListDiv += '</p>';
CommentListDiv += '<a href="javascript:delComment(' + CommentInfo.id + ')"class="detail">删除评论</a>';
CommentListDiv += '</div>';
}
//将 html 填充进去
jQuery("#commentDiv").html(CommentListDiv);
} else {
alert("评论信息获取失败!");
}
}
});
}
showComment();
//删除评论
function delComment(id) {
if (confirm("确定删除该评论?")) {
jQuery.ajax({
type: "POST",
url: "/comment/del",
data: {
"id": id,
"autId": autId
},
success: function (result) {
if (result != null && result.code == 200 && result.data == 1) {
alert("评论删除成功!");
//刷新页面
location.href = location.href;
} else {
alert(result.msg);
}
}
});
}
}
//增加评论
function subComment() {
//非空校验
var inputComment = jQuery("#input-comment");
if (inputComment.val() == "") {
alert("评论不能为空!");
inputComment.focus();
return;
}
jQuery.ajax({
type: "POST",
url: "/comment/add",
data: {
"aid": id,
"comment": inputComment.val()
},
success: function (result) {
if (result != null && result.code == 200 && result.data == 1) {
alert("评论成功!");
//刷新当前页面
location.href = location.href;
} else {
alert(result.msg);
}
}
});
}
服务器开发
@RestController
@RequestMapping("/comment")
public class CommentController {
@Autowired
private CommentService commentService;
@Autowired
private UserService userService;
@Autowired
private ArticleService articleService;
@RequestMapping("/add")
public AjaxResult add(HttpServletRequest request, CommentInfo commentInfo) {
//非空校验
if(commentInfo == null || !StringUtils.hasLength(commentInfo.getComment())) {
return AjaxResult.fail(403, "参数错误!");
}
//获取当前用户 id
UserInfo userInfo = UserSessionUtils.getUser(request);
if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
!StringUtils.hasLength(userInfo.getPassword())) {
return AjaxResult.fail(403, "请登录后评论!");
}
//设置 uid、nickname、photo 后存储评论数据
commentInfo.setUid(userInfo.getId());
commentInfo.setNickname(userInfo.getNickname());
commentInfo.setPhoto(userInfo.getPhoto());
return AjaxResult.success(commentService.add(commentInfo));
}
@RequestMapping("/show")
public AjaxResult show(Integer aid) {
//非空校验
if(aid == null) {
return AjaxResult.fail(403, "参数错误!");
}
//通过文章 id 获取所有该文章的评论
return AjaxResult.success(commentService.showCommentByAid(aid));
}
@RequestMapping("/del")
public AjaxResult del(HttpServletRequest request, Integer id, Integer autId) {
//非空校验
if(id == null || autId == null) {
return AjaxResult.fail(403, "您无权删除该评论!");
}
//评论能被删除需要具备以下两个条件其中之一:
//1.当前用户 id 等于 评论 uid
//2.当前文章作者信息的 id 需要等于 当前用户的 id
//获取当前用户信息
UserInfo curUserInfo = UserSessionUtils.getUser(request);
if(curUserInfo == null || !StringUtils.hasLength(curUserInfo.getUsername()) ||
!StringUtils.hasLength(curUserInfo.getPassword())) {
return AjaxResult.fail(403, "您无权删除该评论!");
}
//获取作者信息
UserInfo autUserInfo = userService.getUserById(autId);
if(autUserInfo == null || !StringUtils.hasLength(autUserInfo.getUsername()) ||
!StringUtils.hasLength(autUserInfo.getPassword())) {
return AjaxResult.fail(403, "您无权删除该评论!");
}
//获取评论信息
CommentInfo commentInfo = commentService.getCommentInfoById(id);
if(commentInfo == null || !StringUtils.hasLength(commentInfo.getNickname()) ||
!StringUtils.hasLength(commentInfo.getComment())) {
return AjaxResult.fail(403, "您无权删除该评论!");
}
//只要满足条件即可删除
if(curUserInfo.getId().equals(commentInfo.getUid()) ||
autUserInfo.getId().equals(curUserInfo.getId())) {
//可以进行删除
return AjaxResult.success(commentService.delCommentByid(id));
} else {
//不可以进行删除
return AjaxResult.fail(403, "您无权删除该评论!");
}
}
}