feature/post_v2 #2
|
@ -9,7 +9,8 @@ message OKResp {}
|
|||
message NoneReq {}
|
||||
|
||||
// 分頁信息
|
||||
message Pager {
|
||||
message Pager
|
||||
{
|
||||
int64 total = 1; // 總數量
|
||||
int64 size = 2; // 每頁數量
|
||||
int64 index = 3; // 當前頁碼
|
||||
|
@ -18,7 +19,8 @@ message Pager {
|
|||
// ========== 貼文區 ===========
|
||||
|
||||
// ------ NewPost 新增貼文--------
|
||||
message NewPostReq {
|
||||
message NewPostReq
|
||||
{
|
||||
string uid = 1; // 發佈貼文的用戶ID
|
||||
string content = 2; // 貼文內容
|
||||
repeated string tags = 3; // 貼文相關標籤
|
||||
|
@ -26,26 +28,30 @@ message NewPostReq {
|
|||
bool is_ad = 5; // 是否為廣告
|
||||
}
|
||||
|
||||
message Media {
|
||||
message Media
|
||||
{
|
||||
string type = 1;
|
||||
string url = 2;
|
||||
}
|
||||
|
||||
// 貼文回應
|
||||
message PostResp {
|
||||
message PostResp
|
||||
{
|
||||
string post_id = 1; // 創建成功的貼文ID
|
||||
}
|
||||
|
||||
// ------ DeletePost 刪除貼文 ------
|
||||
|
||||
// 刪除貼文的請求
|
||||
message DeletePostsReq {
|
||||
message DeletePostsReq
|
||||
{
|
||||
repeated string post_id = 1; // 貼文ID
|
||||
}
|
||||
|
||||
// ------ UpdatePost 更新貼文 ------
|
||||
// 更新貼文的請求
|
||||
message UpdatePostReq {
|
||||
message UpdatePostReq
|
||||
{
|
||||
string post_id = 1; // 貼文ID
|
||||
repeated string tags = 2; // 新的標籤列表
|
||||
repeated Media media = 3; // 這筆文章的所有 Media URL
|
||||
|
@ -56,7 +62,8 @@ message UpdatePostReq {
|
|||
|
||||
// ------ListPosts 查詢貼文 ------
|
||||
// 查詢貼文的請求
|
||||
message QueryPostsReq {
|
||||
message QueryPostsReq
|
||||
{
|
||||
repeated string uid = 1; // 可選:根據用戶ID篩選貼文
|
||||
repeated string post_id = 2; // 可選:根據貼文ID篩選貼文
|
||||
optional int32 only_ads = 3; // 可選:是否只顯示廣告 0 不篩選 1 只顯示廣告 2 不顯示廣告
|
||||
|
@ -65,7 +72,8 @@ message QueryPostsReq {
|
|||
}
|
||||
|
||||
// 貼文詳情
|
||||
message PostDetailItem {
|
||||
message PostDetailItem
|
||||
{
|
||||
string post_id = 1; // 貼文ID
|
||||
string uid = 2; // 發佈用戶ID
|
||||
string content = 3; // 貼文內容
|
||||
|
@ -79,12 +87,14 @@ message PostDetailItem {
|
|||
}
|
||||
|
||||
// 貼文列表回應
|
||||
message ListPostsResp {
|
||||
message ListPostsResp
|
||||
{
|
||||
repeated PostDetailItem posts = 1; // 貼文列表
|
||||
Pager page = 2;
|
||||
}
|
||||
|
||||
message ModifyLikeDislikeCountReq {
|
||||
message ModifyLikeDislikeCountReq
|
||||
{
|
||||
string post_id = 1; // 貼文的 ID
|
||||
int64 reaction_type = 2; // 用戶的反應類型,可能是讚或不讚
|
||||
bool is_increment = 3; // 表示是否增加(true 表示增加,false 表示減少)
|
||||
|
@ -92,7 +102,8 @@ message ModifyLikeDislikeCountReq {
|
|||
}
|
||||
|
||||
// ========== 定義貼文服務(最基本單位,不要把邏輯放進來,也考慮是否要做快取) ==========
|
||||
service PostService {
|
||||
service PostService
|
||||
{
|
||||
// CreatePost 新增貼文
|
||||
rpc CreatePost(NewPostReq) returns (PostResp);
|
||||
// DeletePost 刪除貼文
|
||||
|
@ -102,3 +113,72 @@ service PostService {
|
|||
// ListPosts 查詢貼文
|
||||
rpc ListPosts(QueryPostsReq) returns (ListPostsResp);
|
||||
}
|
||||
|
||||
// =================================================================================================
|
||||
|
||||
// ------------ 評論貼文的請求 ------------
|
||||
message CommentPostReq
|
||||
{
|
||||
string post_id = 1; // 貼文ID
|
||||
string uid = 2; // 評論者ID
|
||||
string content = 3; // 評論內容
|
||||
}
|
||||
|
||||
message CommentPostResp
|
||||
{
|
||||
string comment_id = 1; // 回應ID
|
||||
}
|
||||
|
||||
// ------------ 查詢評論的請求 ------------
|
||||
message GetCommentsReq
|
||||
{
|
||||
string post_id = 1; // 貼文ID
|
||||
int32 page_index = 2; // 分頁頁碼
|
||||
int32 page_size = 3; // 每頁顯示數量
|
||||
}
|
||||
|
||||
// 評論詳情
|
||||
message CommentDetail
|
||||
{
|
||||
string comment_id = 1; // 評論ID
|
||||
string uid = 2; // 評論者ID
|
||||
string content = 3; // 評論內容
|
||||
int64 created_at = 4; // 創建時間
|
||||
int64 like_count = 5; // 讚數
|
||||
int64 dislike_count = 6; // 不喜歡數量
|
||||
}
|
||||
|
||||
// 評論列表回應
|
||||
message GetCommentsResp
|
||||
{
|
||||
repeated CommentDetail comments = 1; // 評論列表
|
||||
Pager page = 2;
|
||||
}
|
||||
|
||||
// ------------ 刪除評論請求 ------------
|
||||
message DeleteCommentReq
|
||||
{
|
||||
repeated string comment_id = 1; // 評論ID
|
||||
}
|
||||
|
||||
// 更新評論請求
|
||||
message UpdateCommentReq
|
||||
{
|
||||
string comment_id = 1; // 評論ID
|
||||
string content = 2; // 更新後的評論內容
|
||||
optional int64 like_count = 3; // 讚數
|
||||
optional int64 dislike_count = 4; // 不喜歡數量
|
||||
}
|
||||
|
||||
// 定義評論服務
|
||||
service CommentService
|
||||
{
|
||||
// NewComment 發表評論
|
||||
rpc NewComment(CommentPostReq) returns (CommentPostResp);
|
||||
// GetComments 查詢評論
|
||||
rpc GetComments(GetCommentsReq) returns (GetCommentsResp);
|
||||
// DeleteComment 刪除評論
|
||||
rpc DeleteComment(DeleteCommentReq) returns (OKResp);
|
||||
// UpdateComment 更新評論
|
||||
rpc UpdateComment(UpdateCommentReq) returns (OKResp);
|
||||
}
|
|
@ -1,5 +1,13 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
ers "code.30cm.net/digimon/library-go/errs"
|
||||
"code.30cm.net/digimon/library-go/errs/code"
|
||||
"fmt"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ErrorCode uint32
|
||||
|
||||
func (e ErrorCode) ToUint32() uint32 {
|
||||
|
@ -15,3 +23,25 @@ const (
|
|||
UpdatePostError
|
||||
ListPostError
|
||||
)
|
||||
|
||||
const (
|
||||
CommentFoundErrorCode ErrorCode = iota + 10
|
||||
CommentInsertErrorCode
|
||||
CommentDeleteErrorCode
|
||||
CommentUpdateErrorCode
|
||||
CommentListErrorCode
|
||||
)
|
||||
|
||||
func CommentError(ec ErrorCode, s ...string) *ers.LibError {
|
||||
return ers.NewError(code.CloudEPTweeting, code.DBError,
|
||||
ec.ToUint32(),
|
||||
fmt.Sprintf("%s", strings.Join(s, " ")))
|
||||
}
|
||||
|
||||
func CommentErrorL(ec ErrorCode,
|
||||
l logx.Logger, filed []logx.LogField, s ...string) *ers.LibError {
|
||||
e := CommentError(ec, s...)
|
||||
l.WithCallerSkip(1).WithFields(filed...).Error(e.Error())
|
||||
|
||||
return e
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package commentservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-tweeting-service/internal/domain"
|
||||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type DeleteCommentLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewDeleteCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCommentLogic {
|
||||
return &DeleteCommentLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteComment 刪除評論
|
||||
func (l *DeleteCommentLogic) DeleteComment(in *tweeting.DeleteCommentReq) (*tweeting.OKResp, error) {
|
||||
_, err := l.svcCtx.CommentModel.DeleteMany(l.ctx, in.GetCommentId()...)
|
||||
if err != nil {
|
||||
e := domain.CommentErrorL(
|
||||
domain.CommentDeleteErrorCode,
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "req", Value: in},
|
||||
{Key: "func", Value: "CommentModel.DeleteMany"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to del comment").Wrap(err)
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &tweeting.OKResp{}, nil
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package commentservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-tweeting-service/internal/domain"
|
||||
model "app-cloudep-tweeting-service/internal/model/mongo"
|
||||
ers "code.30cm.net/digimon/library-go/errs"
|
||||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetCommentsLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewGetCommentsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCommentsLogic {
|
||||
return &GetCommentsLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// 只列出要驗證的資料
|
||||
type listReq struct {
|
||||
PostID string `json:"post_id" validate:"required"`
|
||||
PageSize int64 `json:"page_size" validate:"required"`
|
||||
PageIndex int64 `json:"page_index" validate:"required"`
|
||||
}
|
||||
|
||||
// 將單個 Post 轉換為 PostDetailItem
|
||||
func convertToCommentDetailItem(item *model.Comment) *tweeting.CommentDetail {
|
||||
return &tweeting.CommentDetail{
|
||||
CommentId: item.ID.Hex(),
|
||||
Uid: item.UID,
|
||||
Content: item.Content,
|
||||
CreatedAt: item.CreateAt,
|
||||
LikeCount: int64(item.LikeCount),
|
||||
DislikeCount: int64(item.DisLikeCount),
|
||||
}
|
||||
}
|
||||
|
||||
// GetComments 查詢評論
|
||||
// 目前應該是沒有需求是要看 uid 在哪裡留過言,如果未來業務邏輯有再新增
|
||||
func (l *GetCommentsLogic) GetComments(in *tweeting.GetCommentsReq) (*tweeting.GetCommentsResp, error) {
|
||||
// 將 PageSize 和 PageIndex 提前轉換為 int64
|
||||
pageSize := int64(in.GetPageSize())
|
||||
pageIndex := int64(in.GetPageIndex())
|
||||
|
||||
// 驗證資料
|
||||
if err := l.svcCtx.Validate.ValidateAll(&listReq{
|
||||
PageSize: pageSize,
|
||||
PageIndex: pageIndex,
|
||||
PostID: in.GetPostId(),
|
||||
}); err != nil {
|
||||
// 錯誤代碼 05-011-00
|
||||
return nil, ers.InvalidFormat(err.Error())
|
||||
}
|
||||
|
||||
// 構建查詢條件
|
||||
query := &model.QueryCommentModelReq{
|
||||
PostID: in.GetPostId(),
|
||||
PageSize: pageSize,
|
||||
PageIndex: pageIndex,
|
||||
}
|
||||
|
||||
// 執行查詢
|
||||
find, count, err := l.svcCtx.CommentModel.Find(l.ctx, query)
|
||||
if err != nil {
|
||||
e := domain.CommentErrorL(
|
||||
domain.CommentListErrorCode,
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "query", Value: query},
|
||||
{Key: "func", Value: "CommentModel.Find"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to find comment").Wrap(err)
|
||||
return nil, e
|
||||
}
|
||||
|
||||
// 將查詢結果轉換為 API 回應格式
|
||||
result := make([]*tweeting.CommentDetail, 0, count)
|
||||
for _, item := range find {
|
||||
result = append(result, convertToCommentDetailItem(item))
|
||||
}
|
||||
|
||||
// 返回結果
|
||||
return &tweeting.GetCommentsResp{
|
||||
Comments: result,
|
||||
Page: &tweeting.Pager{
|
||||
Total: count,
|
||||
Index: pageIndex,
|
||||
Size: pageSize,
|
||||
},
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package commentservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/domain"
|
||||
model "app-cloudep-tweeting-service/internal/model/mongo"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
ers "code.30cm.net/digimon/library-go/errs"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type NewCommentLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewNewCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NewCommentLogic {
|
||||
return &NewCommentLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// 輸入的定義 -> 檢查用
|
||||
type newCommentReq struct {
|
||||
UID string `json:"uid" validate:"required"`
|
||||
Content string `json:"content" validate:"required,lte=500"` // 貼文限制 500 字內
|
||||
PostID string `json:"post_id" validate:"required"`
|
||||
}
|
||||
|
||||
// NewComment 發表評論
|
||||
func (l *NewCommentLogic) NewComment(in *tweeting.CommentPostReq) (*tweeting.CommentPostResp, error) {
|
||||
// 驗證資料
|
||||
if err := l.svcCtx.Validate.ValidateAll(&newCommentReq{
|
||||
UID: in.GetUid(),
|
||||
Content: in.GetContent(),
|
||||
PostID: in.GetPostId(),
|
||||
}); err != nil {
|
||||
// 錯誤代碼 05-011-00
|
||||
return nil, ers.InvalidFormat(err.Error())
|
||||
}
|
||||
|
||||
// 檢查是否有這個文章
|
||||
_, err := l.svcCtx.PostModel.FindOne(l.ctx, in.GetPostId())
|
||||
if err != nil {
|
||||
if errors.Is(model.ErrNotFound, err) {
|
||||
// 錯誤代碼 05-031-00
|
||||
return nil, ers.ResourceNotFound("failed to find post: ", in.GetPostId())
|
||||
}
|
||||
// 錯誤代碼 05-021-10
|
||||
e := domain.CommentErrorL(
|
||||
domain.CommentFoundErrorCode,
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "req", Value: in},
|
||||
{Key: "func", Value: "PostModel.FindOne"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to find post:", in.GetPostId()).Wrap(err)
|
||||
|
||||
return nil, e
|
||||
}
|
||||
|
||||
data := &model.Comment{
|
||||
PostID: in.GetPostId(),
|
||||
UID: in.GetUid(),
|
||||
Content: in.GetContent(),
|
||||
LikeCount: 0,
|
||||
DisLikeCount: 0,
|
||||
}
|
||||
err = l.svcCtx.CommentModel.Insert(l.ctx, data)
|
||||
if err != nil {
|
||||
// 錯誤代碼 05-021-11
|
||||
e := domain.CommentErrorL(
|
||||
domain.CommentInsertErrorCode,
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "req", Value: in},
|
||||
{Key: "func", Value: "CommentModel.Insert"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to insert comment:", in.GetPostId()).Wrap(err)
|
||||
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &tweeting.CommentPostResp{
|
||||
CommentId: data.ID.Hex(),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package commentservicelogic
|
|
@ -0,0 +1,81 @@
|
|||
package commentservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/domain"
|
||||
model "app-cloudep-tweeting-service/internal/model/mongo"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
ers "code.30cm.net/digimon/library-go/errs"
|
||||
"context"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type UpdateCommentLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewUpdateCommentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateCommentLogic {
|
||||
return &UpdateCommentLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
type checkCommentId struct {
|
||||
CommentId string `validate:"required"`
|
||||
Content string `json:"content,omitempty" validate:"lte=500"`
|
||||
}
|
||||
|
||||
// UpdateComment 更新評論
|
||||
func (l *UpdateCommentLogic) UpdateComment(in *tweeting.UpdateCommentReq) (*tweeting.OKResp, error) {
|
||||
// 驗證資料
|
||||
if err := l.svcCtx.Validate.ValidateAll(&checkCommentId{
|
||||
CommentId: in.GetCommentId(),
|
||||
Content: in.GetContent(),
|
||||
}); err != nil {
|
||||
// 錯誤代碼 05-011-00
|
||||
return nil, ers.InvalidFormat(err.Error())
|
||||
}
|
||||
// 沒有就沒有,有就走全覆蓋
|
||||
update := model.Comment{}
|
||||
oid, err := primitive.ObjectIDFromHex(in.GetCommentId())
|
||||
if err != nil {
|
||||
// 錯誤代碼 05-011-00
|
||||
return nil, ers.InvalidFormat("failed to get correct comment id")
|
||||
}
|
||||
update.ID = oid
|
||||
update.Content = in.GetContent()
|
||||
// 因為 0 也有意義,所以如果是真的沒帶進來,用 -1 帶進去表示不作動
|
||||
if in.LikeCount == nil {
|
||||
update.LikeCount = -1
|
||||
} else {
|
||||
update.LikeCount = in.GetLikeCount()
|
||||
}
|
||||
if in.DislikeCount == nil {
|
||||
update.DisLikeCount = -1
|
||||
} else {
|
||||
update.DisLikeCount = in.GetDislikeCount()
|
||||
}
|
||||
|
||||
_, err = l.svcCtx.CommentModel.UpdateOptional(l.ctx, &update)
|
||||
if err != nil {
|
||||
// 錯誤代碼 05-021-13
|
||||
e := domain.CommentErrorL(
|
||||
domain.CommentUpdateErrorCode,
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "req", Value: in},
|
||||
{Key: "func", Value: "CommentModel.UpdateOptional"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to update comment:", in.CommentId).Wrap(err)
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &tweeting.OKResp{}, nil
|
||||
}
|
|
@ -80,8 +80,19 @@ func (l *UpdatePostLogic) UpdatePost(in *tweeting.UpdatePostReq) (*tweeting.OKRe
|
|||
}
|
||||
update.MediaURL = media
|
||||
update.Content = in.GetContent()
|
||||
update.Like = uint64(in.GetLikeCount())
|
||||
update.DisLike = uint64(in.GetDislikeCount())
|
||||
|
||||
// 因為 0 也有意義,所以如果是真的沒帶進來,用 -1 帶進去表示不作動
|
||||
if in.LikeCount == nil {
|
||||
update.Like = -1
|
||||
} else {
|
||||
update.Like = in.GetLikeCount()
|
||||
}
|
||||
|
||||
if in.DislikeCount == nil {
|
||||
update.DisLike = -1
|
||||
} else {
|
||||
update.DisLike = in.GetDislikeCount()
|
||||
}
|
||||
|
||||
_, err = l.svcCtx.PostModel.UpdateOptional(l.ctx, &update)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
package model
|
||||
|
||||
import "github.com/zeromicro/go-zero/core/stores/mon"
|
||||
import (
|
||||
"context"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ CommentModel = (*customCommentModel)(nil)
|
||||
|
||||
|
@ -9,13 +17,27 @@ type (
|
|||
// and implement the added methods in customCommentModel.
|
||||
CommentModel interface {
|
||||
commentModel
|
||||
DeleteMany(ctx context.Context, id ...string) (int64, error)
|
||||
UpdateOptional(ctx context.Context, data *Comment) (*mongo.UpdateResult, error)
|
||||
Find(ctx context.Context, param *QueryCommentModelReq) ([]*Comment, int64, error)
|
||||
}
|
||||
|
||||
customCommentModel struct {
|
||||
*defaultCommentModel
|
||||
}
|
||||
|
||||
QueryCommentModelReq struct {
|
||||
PostID string
|
||||
PageSize int64
|
||||
PageIndex int64
|
||||
}
|
||||
)
|
||||
|
||||
func (xw customCommentModel) Find(ctx context.Context, param *QueryCommentModelReq) ([]*Comment, int64, error) {
|
||||
// TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// NewCommentModel returns a model for the mongo.
|
||||
func NewCommentModel(url, db, collection string) CommentModel {
|
||||
conn := mon.MustNewModel(url, db, collection)
|
||||
|
@ -23,3 +45,56 @@ func NewCommentModel(url, db, collection string) CommentModel {
|
|||
defaultCommentModel: newDefaultCommentModel(conn),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultCommentModel) DeleteMany(ctx context.Context, id ...string) (int64, error) {
|
||||
objectIDs := make([]primitive.ObjectID, 0, len(id))
|
||||
|
||||
// prepare
|
||||
for _, item := range id {
|
||||
oid, err := primitive.ObjectIDFromHex(item)
|
||||
if err != nil {
|
||||
logx.WithCallerSkip(1).WithFields(
|
||||
logx.Field("func", "defaultPostModel.DeleteMany"),
|
||||
logx.Field("id", item),
|
||||
).Error(err.Error())
|
||||
|
||||
continue
|
||||
}
|
||||
objectIDs = append(objectIDs, oid)
|
||||
}
|
||||
|
||||
// 檢查是否有有效的 ObjectIDs
|
||||
if len(objectIDs) == 0 {
|
||||
return 0, ErrNotFound
|
||||
}
|
||||
|
||||
// 刪除文檔
|
||||
res, err := m.conn.DeleteMany(ctx, bson.M{"_id": bson.M{"$in": objectIDs}})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (m *defaultCommentModel) UpdateOptional(ctx context.Context, data *Comment) (*mongo.UpdateResult, error) {
|
||||
update := bson.M{"$set": bson.M{}}
|
||||
|
||||
if data.Content != "" {
|
||||
update["$set"].(bson.M)["content"] = data.Content
|
||||
}
|
||||
|
||||
if data.LikeCount != -1 {
|
||||
update["$set"].(bson.M)["like_count"] = data.LikeCount
|
||||
}
|
||||
|
||||
if data.DisLikeCount != -1 {
|
||||
update["$set"].(bson.M)["dis_like_count"] = data.DisLikeCount
|
||||
}
|
||||
|
||||
// UpdateAt 是每次都需要更新的,不用檢查
|
||||
update["$set"].(bson.M)["updateAt"] = time.Now().UTC().UnixNano()
|
||||
res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, update)
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ func newDefaultCommentModel(conn *mon.Model) *defaultCommentModel {
|
|||
func (m *defaultCommentModel) Insert(ctx context.Context, data *Comment) error {
|
||||
if data.ID.IsZero() {
|
||||
data.ID = primitive.NewObjectID()
|
||||
data.CreateAt = time.Now()
|
||||
data.UpdateAt = time.Now()
|
||||
data.CreateAt = time.Now().UTC().UnixNano()
|
||||
data.UpdateAt = time.Now().UTC().UnixNano()
|
||||
}
|
||||
|
||||
_, err := m.conn.InsertOne(ctx, data)
|
||||
|
@ -57,7 +57,7 @@ func (m *defaultCommentModel) FindOne(ctx context.Context, id string) (*Comment,
|
|||
}
|
||||
|
||||
func (m *defaultCommentModel) Update(ctx context.Context, data *Comment) (*mongo.UpdateResult, error) {
|
||||
data.UpdateAt = time.Now()
|
||||
data.UpdateAt = time.Now().UTC().UnixNano()
|
||||
|
||||
res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data})
|
||||
return res, err
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type Comment struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
|
||||
// TODO: Fill your own fields
|
||||
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
|
||||
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
|
||||
PostID string `bson:"post_id" json:"post_id"`
|
||||
UID string `bson:"uid" json:"uid"` // 留下留言的人
|
||||
Content string `bson:"content" json:"content"` // 留言內容
|
||||
LikeCount int64 `bson:"like_count" json:"like_count"` // 喜歡這則留言的人
|
||||
DisLikeCount int64 `bson:"dis_like_count" json:"dis_like_count"` // 不喜歡這則留言的人
|
||||
UpdateAt int64 `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
|
||||
CreateAt int64 `bson:"createAt,omitempty" json:"createAt,omitempty"`
|
||||
}
|
||||
|
||||
func (c Comment) CollectionName() string {
|
||||
return "comment"
|
||||
}
|
||||
|
||||
// 照邏輯,應該需要建立的索引有
|
||||
// 複合索引:(PostID + CreateAt)
|
||||
|
|
|
@ -106,11 +106,11 @@ func (m *defaultPostModel) UpdateOptional(ctx context.Context, data *Post) (*mon
|
|||
update["$set"].(bson.M)["media_url"] = data.MediaURL
|
||||
}
|
||||
|
||||
if data.Like != 0 {
|
||||
if data.Like != -1 {
|
||||
update["$set"].(bson.M)["like"] = data.Like
|
||||
}
|
||||
|
||||
if data.DisLike != 0 {
|
||||
if data.DisLike != -1 {
|
||||
update["$set"].(bson.M)["dislike"] = data.DisLike
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ type Post struct {
|
|||
IsAd bool `bson:"is_ad" json:"is_ad"` // 此則貼文是否為廣告貼文 -> 過濾條件
|
||||
Tags []string `bson:"tags" json:"tags"` // 本則貼文的標籤,不提供搜尋,僅提供顯示(存名字,ID 建立之後就不提供修改與刪除)
|
||||
MediaURL []Media `bson:"media_url" json:"media_url"` // 網址
|
||||
Like uint64 `bson:"like" json:"like"` // 讚數量
|
||||
DisLike uint64 `bson:"dislike" json:"dislike"` // 不讚數量
|
||||
Like int64 `bson:"like" json:"like"` // 讚數量
|
||||
DisLike int64 `bson:"dislike" json:"dislike"` // 不讚數量
|
||||
UpdateAt int64 `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
|
||||
CreateAt int64 `bson:"createAt,omitempty" json:"createAt,omitempty"` // -> 排序條件
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
// Source: tweeting.proto
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/logic/commentservice"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
)
|
||||
|
||||
type CommentServiceServer struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
tweeting.UnimplementedCommentServiceServer
|
||||
}
|
||||
|
||||
func NewCommentServiceServer(svcCtx *svc.ServiceContext) *CommentServiceServer {
|
||||
return &CommentServiceServer{
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewComment 發表評論
|
||||
func (s *CommentServiceServer) NewComment(ctx context.Context, in *tweeting.CommentPostReq) (*tweeting.CommentPostResp, error) {
|
||||
l := commentservicelogic.NewNewCommentLogic(ctx, s.svcCtx)
|
||||
return l.NewComment(in)
|
||||
}
|
||||
|
||||
// GetComments 查詢評論
|
||||
func (s *CommentServiceServer) GetComments(ctx context.Context, in *tweeting.GetCommentsReq) (*tweeting.GetCommentsResp, error) {
|
||||
l := commentservicelogic.NewGetCommentsLogic(ctx, s.svcCtx)
|
||||
return l.GetComments(in)
|
||||
}
|
||||
|
||||
// DeleteComment 刪除評論
|
||||
func (s *CommentServiceServer) DeleteComment(ctx context.Context, in *tweeting.DeleteCommentReq) (*tweeting.OKResp, error) {
|
||||
l := commentservicelogic.NewDeleteCommentLogic(ctx, s.svcCtx)
|
||||
return l.DeleteComment(in)
|
||||
}
|
||||
|
||||
// UpdateComment 更新評論
|
||||
func (s *CommentServiceServer) UpdateComment(ctx context.Context, in *tweeting.UpdateCommentReq) (*tweeting.OKResp, error) {
|
||||
l := commentservicelogic.NewUpdateCommentLogic(ctx, s.svcCtx)
|
||||
return l.UpdateComment(in)
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
postservicelogic "app-cloudep-tweeting-service/internal/logic/postservice"
|
||||
"app-cloudep-tweeting-service/internal/logic/postservice"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
)
|
||||
|
||||
|
@ -45,9 +45,3 @@ func (s *PostServiceServer) ListPosts(ctx context.Context, in *tweeting.QueryPos
|
|||
l := postservicelogic.NewListPostsLogic(ctx, s.svcCtx)
|
||||
return l.ListPosts(in)
|
||||
}
|
||||
|
||||
// ModifyLikeDislikeCount 調整讚或不讚數量
|
||||
func (s *PostServiceServer) ModifyLikeDislikeCount(ctx context.Context, in *tweeting.ModifyLikeDislikeCountReq) (*tweeting.OKResp, error) {
|
||||
l := postservicelogic.NewModifyLikeDislikeCountLogic(ctx, s.svcCtx)
|
||||
return l.ModifyLikeDislikeCount(in)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,14 @@ func mustMongoConnectUrl(c config.Config) string {
|
|||
)
|
||||
}
|
||||
|
||||
// TODO 思考快取做在那邊
|
||||
|
||||
func MustPostModel(c config.Config) model.PostModel {
|
||||
postCollection := model.Post{}
|
||||
return model.NewPostModel(mustMongoConnectUrl(c), c.Mongo.Database, postCollection.CollectionName())
|
||||
}
|
||||
|
||||
func MustCommentModel(c config.Config) model.CommentModel {
|
||||
m := model.Comment{}
|
||||
return model.NewCommentModel(mustMongoConnectUrl(c), c.Mongo.Database, m.CollectionName())
|
||||
}
|
||||
|
|
|
@ -12,13 +12,14 @@ type ServiceContext struct {
|
|||
Validate vi.Validate
|
||||
|
||||
PostModel model.PostModel
|
||||
CommentModel model.CommentModel
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
Validate: vi.MustValidator(),
|
||||
|
||||
PostModel: MustPostModel(c),
|
||||
CommentModel: MustCommentModel(c),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue