租售同体的书屋项目——书籍系统(二)——第三部分(评论)

一、概述

书籍系统框架如图:

书籍系统.png

文件内容持续更新在GitHub上,可自行查看。

本篇主要是介绍:评论和阅读量中的评论

二、评论

思路

1.对文章的评论

2.对评论的回复

3.让数据呈现树状结构

数据库设计

评论数据表设计.png

parent_id指向父评论id,如果是文章的评论默认为0.

代码

1.因为评论是树状结构,所以在微服务部分做了树数据的嵌套。

action.proto

syntax = "proto3";

package action;

option go_package = "action";

message Request {
  string ping = 1;
}

message Response {
  bool ok = 1;
  string message = 2;
}

message CommentReq{
  int64 Id = 1;
  int64 ParentId = 2;
  int64 BookContentId = 3;
  string Comment = 4;
  int64 CommentByUserId = 5;
  string CommentByNickname = 6;
  int64 CommentToUserId = 7;
  string CommentToNickname = 8;
}

message CommentResp{
  int64 Id = 1;
  int64 ParentId = 2;
  int64 BookContentId = 3;
  string Comment = 4;
  int64 CommentByUserId = 5;
  string CommentByNickname = 6;
  int64 CommentToUserId = 7;
  string CommentToNickname = 8;
}

message CommentsNodeResp{
  CommentResp Comments = 1;
  repeated CommentsNodeResp CommentsNode = 2;
}

message CommentsTreeResp{
  repeated CommentsNodeResp CommentsTree = 1;
}

service Action {
  //Comments
  rpc GetCommentsByBookContentId(CommentReq) returns(CommentsTreeResp);
  rpc CreateComment(CommentReq) returns(Response);
  rpc UpdateComment(CommentReq) returns(Response);
  rpc DeleteComment(CommentReq) returns(Response);
}
复制代码

2.在逻辑代码中把数据库中的数据组合成树数据

getcommentsbybookcontentidlogic.go

// Comments
func (l *GetCommentsByBookContentIdLogic) GetCommentsByBookContentId(in *action.CommentReq) (*action.CommentsTreeResp, error) {
	comments, err := l.svcCtx.CommentModel.FindCommentsByBookContentId(in.BookContentId)
	if err != nil {
		return nil, err
	}
	fmt.Println("comments", comments)

	f := func(cs []*model.Comment) *action.CommentsTreeResp {
		//树结构
		var res = action.CommentsTreeResp{
			CommentsTree: make([]*action.CommentsNodeResp, 0),
		}
		for i := 0; i < len(cs); i++ {
			if cs[i].ParentId == 0 {
				res.CommentsTree = append(res.CommentsTree, &action.CommentsNodeResp{
					Comments: &action.CommentResp{
						Id:                cs[i].Id,
						ParentId:          cs[i].ParentId,
						BookContentId:     cs[i].BookContentId,
						Comment:           cs[i].Comment,
						CommentByUserId:   cs[i].CommentByUserId,
						CommentByNickname: cs[i].CommentByNickname,
						CommentToUserId:   cs[i].CommentToUserId,
						CommentToNickname: cs[i].CommentToNickname,
					},
				})
			} else {
				node := FindCommentNodeByParentId(res.CommentsTree, cs[i].ParentId)
				if node != nil {
					node.CommentsNode = append(node.CommentsNode, &action.CommentsNodeResp{
						Comments: &action.CommentResp{
							Id:                cs[i].Id,
							ParentId:          cs[i].ParentId,
							BookContentId:     cs[i].BookContentId,
							Comment:           cs[i].Comment,
							CommentByUserId:   cs[i].CommentByUserId,
							CommentByNickname: cs[i].CommentByNickname,
							CommentToUserId:   cs[i].CommentToUserId,
							CommentToNickname: cs[i].CommentToNickname,
						},
					})
				}
			}
		}
		return &res
	}
	return f(comments), nil
}

//找到id对应的节点
func FindCommentNodeByParentId(res []*action.CommentsNodeResp, id int64) *action.CommentsNodeResp {
	for i := 0; i < len(res); i++ {
		if id == res[i].Comments.Id {
			return res[i]
		} else {
			if r := FindCommentNodeByParentId(res[i].CommentsNode, id); r != nil {
				return r
			}
		}
	}
	return nil
}
复制代码

3.在做前端的时候,发现评论一般都是只有父子两级,所以在WebApi中把所有的对评论的回复又组合成子级。--!有苦说不出。

get_comment_handler.go

package action

import (
	"WebApi/Pb/action"
	"WebApi/Svc"
	"context"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
)

func GetCommentsByBookContentIdHandler(c *gin.Context) {
	bookContentId, err := strconv.ParseInt(c.Query("bookContentId"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	ctx := context.Background()
	//树状结构(评论)
	res, err := Svc.SvcContext.Grpc.ActionGrpc.GetCommentsByBookContentId(ctx, &action.CommentReq{
		BookContentId: bookContentId,
	})
	//树状结构 平铺为 只有父子节点结构(评论)  方便前端使用
	tn := func(t *action.CommentsTreeResp) action.CommentsTreeResp {
		var tree = action.CommentsTreeResp{}
		for i := 0; i < len(t.CommentsTree); i++ {
			//组合父节点
			tree.CommentsTree = append(tree.CommentsTree, &action.CommentsNodeResp{
				Comments: t.CommentsTree[i].Comments,
			})
			//组合父节点下所有的节点
			combChildComment(t.CommentsTree[i].CommentsNode, &tree.CommentsTree[i].CommentsNode)
		}
		return tree
	}

	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	} else {
		c.JSON(http.StatusOK, tn(res))
	}
}

func combChildComment(src []*action.CommentsNodeResp, dest *[]*action.CommentsNodeResp) {
	for i := 0; i < len(src); i++ {
		*dest = append(*dest, &action.CommentsNodeResp{
			Comments: src[i].Comments,
		})
		if src[i].CommentsNode != nil {
			combChildComment(src[i].CommentsNode, dest)
		}
	}

}
复制代码

4.POSTman的结果展示

{
    "CommentsTree": [
        {
            "Comments": {
                "Id": 1,
                "BookContentId": 2,
                "Comment": "写得好。",
                "CommentByUserId": 1,
                "CommentByNickname": "书店老板",
                "CommentToUserId": 1,
                "CommentToNickname": "书店老板"
            },
            "CommentsNode": [
                {
                    "Comments": {
                        "Id": 3,
                        "ParentId": 1,
                        "BookContentId": 2,
                        "Comment": "马屁精。",
                        "CommentByUserId": 2,
                        "CommentByNickname": "张三",
                        "CommentToUserId": 1,
                        "CommentToNickname": "书店老板"
                    }
                },
                {
                    "Comments": {
                        "Id": 4,
                        "ParentId": 3,
                        "BookContentId": 2,
                        "Comment": "来来来,笔给你,你来写",
                        "CommentByUserId": 3,
                        "CommentByNickname": "李四",
                        "CommentToUserId": 2,
                        "CommentToNickname": "张三"
                    }
                }
            ]
        },
        {
            "Comments": {
                "Id": 5,
                "BookContentId": 2,
                "Comment": "写得好1。",
                "CommentByUserId": 1,
                "CommentByNickname": "书店老板",
                "CommentToUserId": 1,
                "CommentToNickname": "书店老板"
            },
            "CommentsNode": [
                {
                    "Comments": {
                        "Id": 8,
                        "ParentId": 5,
                        "BookContentId": 2,
                        "Comment": "不好",
                        "CommentByUserId": 4,
                        "CommentByNickname": "王五",
                        "CommentToUserId": 1,
                        "CommentToNickname": "书店老板"
                    }
                },
                {
                    "Comments": {
                        "Id": 9,
                        "ParentId": 8,
                        "BookContentId": 2,
                        "Comment": "不好才怪",
                        "CommentByUserId": 4,
                        "CommentByNickname": "王五",
                        "CommentToUserId": 4,
                        "CommentToNickname": "王五"
                    }
                }
            ]
        },
        {
            "Comments": {
                "Id": 10,
                "BookContentId": 2,
                "Comment": "我是第一",
                "CommentByUserId": 4,
                "CommentByNickname": "王五",
                "CommentToUserId": 4,
                "CommentToNickname": "王五"
            }
        },
        {
            "Comments": {
                "Id": 11,
                "BookContentId": 2,
                "Comment": "第二",
                "CommentByUserId": 4,
                "CommentByNickname": "王五",
                "CommentToUserId": 4,
                "CommentToNickname": "王五"
            }
        },
        {
            "Comments": {
                "Id": 12,
                "BookContentId": 2,
                "Comment": "文章YYDS。",
                "CommentByUserId": 1,
                "CommentByNickname": "书店老板",
                "CommentToUserId": 1,
                "CommentToNickname": "书店老板"
            }
        }
    ]
}
复制代码

5.前端成果展示

评论.png

三、Tips

最近工作中忙了起来,更新可能会比之前慢一些,请多多包涵。

猜你喜欢

转载自juejin.im/post/7032073536709591048