字段的设计:
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_dynamic_comment")
public class DynamicComment {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@TableField("dynamic_id")
private Integer dynamicId;
@TableField("user_id")
private Integer userId;
//回复的人的id
@TableField("father_id")
private Integer fatherId;
/*//最上级的评论
@TableField("origin_Id")
private Integer originId;*/
@NotBlank(message = "内容不能为空")
private String context;
//后台可以自己设置
private String publicTime;
//等级
@NotNull(message = "等级不能为空")
private Integer level;
}
前端传递过来的参数里面的level是指当前回复是在评论中的等级(如主评论是第1级,评论的回复或者二级评论就是第2级)
发布评论:
controller层
//发布评论
@RequestMapping("/commitCom")
public ResultVo commitCom(@RequestBody @Validated DynamicComment dynamicComment,BindingResult bindingResult) {
return dynamicService.commitCom(dynamicComment);
}
service层
//发布评论
@Override
public ResultVo commitCom(DynamicComment dynamicComment) {
//先进行参数的判断
if (Objects.isNull(dynamicComment)) {
return new ResultVo(1002, "参数不合法", null);
}
//获取时间
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String format = simpleDateFormat.format(date);
dynamicComment.setPublicTime(format);
//设置用户的id
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User user = (User) authentication.getPrincipal();
dynamicComment.setUserId(user.getId());
//添加评论
int insert = dynamicCommentMapper.insert(dynamicComment);
if (insert <= 0) {
return new ResultVo(500, "内部服务器出错", null);
} else {
return new ResultVo(200, "操作成功", null);
}
}
查看评论:
使用了树这种结构来实现
定义返回的数据类型
public class DynamicCommentVo {
private Integer id;
private Integer dynamicId;
private Integer userId;
//回复的人的id
private Integer fatherId;
/*//最上级的评论
private Integer originId;*/
private String context;
//等级
private Integer level;
private String publicTime;
//评论的人的信息
private User commentUser;
//被回复评论的人的昵称(到时候前端可以进行某某@某某)
private String fatherName;
//嵌套(子评论)
private List<DynamicCommentVo> children;
}
controller层
//查看评论
@RequestMapping("/look")
public ResultVo lookComment(@RequestParam Integer dynamicId){
return dynamicService.lookComment(dynamicId);
}
service:
//查看评论
@Override
public ResultVo lookComment(Integer dynamicId) {
//根据动态的id先把所有相关的数据查询出来
QueryWrapper<DynamicComment> qw=new QueryWrapper<>();
qw.lambda().eq(DynamicComment::getDynamicId,dynamicId);
List<DynamicComment> dynamicComments = dynamicCommentMapper.selectList(qw);
if(dynamicComments.size()==0){
return new ResultVo(200,"暂无评论",null);
}
//返回的数据类型
List<DynamicCommentVo> dynamicCommentVos=new ArrayList<>();
//补充评论的内容copy属性转换为vo
for (DynamicComment dynamicComment : dynamicComments) {
DynamicCommentVo dynamicCommentVo=new DynamicCommentVo();
BeanUtils.copyProperties(dynamicComment,dynamicCommentVo);
//作者的信息
User user = userMapper.selectById(dynamicComment.getUserId());
dynamicCommentVo.setCommentUser(user);
//toUser信息 level>1 说明有回复对象
if(dynamicComment.getLevel()>1){
//查询回复的用户的信息
//System.out.println("进来了"+dynamicComment.getLevel());
User user1 = userMapper.selectById(dynamicComment.getFatherId());
dynamicCommentVo.setFatherName(user1.getName());
//System.out.println("昵称"+dynamicCommentVo.getFatherName());
}
dynamicCommentVos.add(dynamicCommentVo);
}
//很重要的一步!!!
//构造树
MyTreeNode myTreeNode = treeUtils.buildTree(dynamicCommentVos);
System.out.println(myTreeNode.toString());
//根节点的子节点(即level为1的评论 )
List<MyTreeNode> children = myTreeNode.getChildren();
List<DynamicCommentVo> level1DynamicCommentVo=new ArrayList<>();
for (MyTreeNode child : children) {
System.out.println(child.getContent());
System.out.println(child.getChildren());
level1DynamicCommentVo.add(child.getContent());
}
return new ResultVo(200,"操作成功",level1DynamicCommentVo);
}
定义树的结点类:
public class MyTreeNode {
private Integer parentId;
private Integer Id;
//子节点
private List<MyTreeNode> commentVoList;
//内容
private DynamicCommentVo content;
//创建节点
public static MyTreeNode buildNode(DynamicCommentVo commentVo) {
MyTreeNode node=new MyTreeNode();
node.setId(commentVo.getId());
node.setParentId(commentVo.getFatherId());
node.setContent(commentVo);
return node;
}
public static MyTreeNode buildRoot() {
MyTreeNode node=new MyTreeNode();
node.setId(0);
node.setParentId(-999);
node.setContent(null);
ArrayList<MyTreeNode> children=new ArrayList<>();
node.setChildren(children);
return node;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public Integer getId() {
return Id;
}
public void setId(Integer id) {
Id = id;
}
public List<MyTreeNode> getChildren() {
return commentVoList;
}
public void setChildren(List<MyTreeNode> commentVoList) {
this.commentVoList = commentVoList;
}
public DynamicCommentVo getContent() {
return content;
}
public void setContent(DynamicCommentVo content) {
this.content = content;
}
}
树的工具类:
//实现多级评论,将此篇文章的全部评论封装成为一棵树
@Component
public class TreeUtils {
public MyTreeNode buildTree(List<DynamicCommentVo> commentVoList){
//创建根节点 id为0
MyTreeNode root = MyTreeNode.buildRoot();
//根节点的子节点列表
List<MyTreeNode> rootChildren=new ArrayList<>();
//将评论封装为树的节点
List<MyTreeNode> nodes=new ArrayList<>();
for (DynamicCommentVo commentVo : commentVoList) {
MyTreeNode TreeNode = MyTreeNode.buildNode(commentVo);
nodes.add(TreeNode);
}
for (MyTreeNode node : nodes) {
MyTreeNode parentNode=findParentNode(node,nodes);
if(parentNode!=null){
//不为空,说明有父节点
if(parentNode.getChildren()==null){
//说明这个节点是父节点的第一个子节点,创建一个子节点数组
List<MyTreeNode> children=new ArrayList<>();
children.add(node);
parentNode.setChildren(children);
}else{
parentNode.getChildren().add(node);
}
}else{
//为空,说明父节点为根节点
//父节点添加子节点
rootChildren.add(node);
//子节点添加父节点id
node.setParentId(root.getId());
}
root.setChildren(rootChildren);
}
return root;
}
//找到子节点的父节点
public MyTreeNode findParentNode(MyTreeNode childNode,List<MyTreeNode> allNodes){
for (MyTreeNode node : allNodes) {
if(node.getId().equals(childNode.getParentId())){
//将子评论的内容添加到父评论的children列表中。
//如果父评论(CommentVo)的子评论列表为null,则新建一个列表。
List<DynamicCommentVo> fatherCommentVoList = node.getContent().getChildren();
if(fatherCommentVoList==null){
fatherCommentVoList=new ArrayList<>();
fatherCommentVoList.add(childNode.getContent());
node.getContent().setChildren(fatherCommentVoList);
}else{
node.getContent().getChildren().add(childNode.getContent());
}
//System.out.println("孩子的结点数"+node.getContent().getChildren().size());
//添加此节点的父亲节点
childNode.setParentId(node.getId());
return node;
}
}
return null;
}
}