feat: 添加了评论功能并注册

This commit is contained in:
Leon
2025-12-16 18:51:50 +08:00
parent ef47d5e2de
commit b9fe48a328
6 changed files with 236 additions and 2 deletions

View File

@@ -23,7 +23,7 @@ func NewDB(dbcfg config.DatabaseConfig) (*gorm.DB, error) {
}
func AutoMigrate(db *gorm.DB) error {
return db.AutoMigrate(&account.Account{}, &video.Video{}, &video.Like{})
return db.AutoMigrate(&account.Account{}, &video.Video{}, &video.Like{}, &video.Comment{})
}
func CloseDB(db *gorm.DB) error {

View File

@@ -59,12 +59,26 @@ func SetRouter(db *gorm.DB) *gin.Engine {
protectedLikeGroup.POST("/unlike", likeHandler.Unlike)
protectedLikeGroup.POST("/isLiked", likeHandler.IsLiked)
}
// comment
commentRepository := video.NewCommentRepository(db)
commentService := video.NewCommentService(commentRepository, videoRepository)
commentHandler := video.NewCommentHandler(commentService, accountService)
commentGroup := r.Group("/comment")
{
commentGroup.POST("/listAll", commentHandler.GetAllComments)
}
protectedCommentGroup := commentGroup.Group("")
protectedCommentGroup.Use(middleware.JWTAuth(accountRepository))
{
protectedCommentGroup.POST("/publish", commentHandler.PublishComment)
protectedCommentGroup.POST("/delete", commentHandler.DeleteComment)
}
// feed
feedRepository := feed.NewFeedRepository(db)
feedService := feed.NewFeedService(feedRepository, likeRepository)
feedHandler := feed.NewFeedHandler(feedService)
feedGroup := r.Group("/feed")
feedGroup.Use(middleware.SoftJWTAuth(accountRepository))
{
feedGroup.POST("/listLatest", feedHandler.ListLatest)
feedGroup.POST("/listLikesCount", feedHandler.ListLikesCount)

View File

@@ -0,0 +1,25 @@
package video
import "time"
type Comment struct {
ID uint `gorm:"primaryKey" json:"id"`
Username string `gorm:"index" json:"username"`
VideoID uint `gorm:"index" json:"video_id"`
AuthorID uint `gorm:"index" json:"author_id"`
Content string `gorm:"type:text" json:"content"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
}
type PublishCommentRequest struct {
VideoID uint `json:"video_id"`
Content string `json:"content"`
}
type DeleteCommentRequest struct {
CommentID uint `json:"comment_id"`
}
type GetAllCommentsRequest struct {
VideoID uint `json:"video_id"`
}

View File

@@ -0,0 +1,93 @@
package video
import (
"feedsystem_video_go/internal/account"
"feedsystem_video_go/internal/middleware"
"github.com/gin-gonic/gin"
)
type CommentHandler struct {
service *CommentService
accountService *account.AccountService
}
func NewCommentHandler(service *CommentService, accountService *account.AccountService) *CommentHandler {
return &CommentHandler{service: service, accountService: accountService}
}
func (h *CommentHandler) PublishComment(c *gin.Context) {
var req PublishCommentRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if req.Content == "" {
c.JSON(400, gin.H{"error": "content is required"})
return
}
if req.VideoID <= 0 {
c.JSON(400, gin.H{"error": "video_id is required"})
return
}
authorId, err := middleware.GetAccountID(c)
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
user, err := h.accountService.FindByID(c.Request.Context(), authorId)
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
comment := &Comment{
Username: user.Username,
VideoID: req.VideoID,
AuthorID: authorId,
Content: req.Content,
}
if err := h.service.Publish(c.Request.Context(), comment); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "comment published successfully"})
}
func (h *CommentHandler) DeleteComment(c *gin.Context) {
var req DeleteCommentRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
accountID, err := middleware.GetAccountID(c)
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if req.CommentID <= 0 {
c.JSON(400, gin.H{"error": "comment_id is required"})
return
}
if err := h.service.Delete(c.Request.Context(), req.CommentID, accountID); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "comment deleted successfully"})
}
func (h *CommentHandler) GetAllComments(c *gin.Context) {
var req GetAllCommentsRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if req.VideoID == 0 {
c.JSON(400, gin.H{"error": "video_id is required"})
return
}
comments, err := h.service.GetAll(c.Request.Context(), req.VideoID)
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, comments)
}

View File

@@ -0,0 +1,51 @@
package video
import (
"context"
"gorm.io/gorm"
)
type CommentRepository struct {
db *gorm.DB
}
func NewCommentRepository(db *gorm.DB) *CommentRepository {
return &CommentRepository{db: db}
}
func (r *CommentRepository) CreateComment(ctx context.Context, comment *Comment) error {
return r.db.WithContext(ctx).Create(comment).Error
}
func (r *CommentRepository) DeleteComment(ctx context.Context, comment *Comment) error {
return r.db.WithContext(ctx).Delete(comment).Error
}
func (r *CommentRepository) GetAllComments(ctx context.Context, videoID uint) ([]Comment, error) {
var comments []Comment
err := r.db.WithContext(ctx).Where("video_id = ?", videoID).Find(&comments).Error
return comments, err
}
func (r *CommentRepository) IsExist(ctx context.Context, id uint) (bool, error) {
var comment Comment
if err := r.db.WithContext(ctx).First(&comment, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return false, nil
}
return false, err
}
return true, nil
}
func (r *CommentRepository) GetByID(ctx context.Context, id uint) (*Comment, error) {
var comment Comment
if err := r.db.WithContext(ctx).First(&comment, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, err
}
return &comment, nil
}

View File

@@ -0,0 +1,51 @@
package video
import (
"context"
"errors"
)
type CommentService struct {
repo *CommentRepository
VideoRepository *VideoRepository
}
func NewCommentService(repo *CommentRepository, videoRepo *VideoRepository) *CommentService {
return &CommentService{repo: repo, VideoRepository: videoRepo}
}
func (s *CommentService) Publish(ctx context.Context, comment *Comment) error {
exists, err := s.VideoRepository.IsExist(ctx, comment.VideoID)
if err != nil {
return err
}
if !exists {
return errors.New("video not found")
}
return s.repo.CreateComment(ctx, comment)
}
func (s *CommentService) Delete(ctx context.Context, commentID uint, accountID uint) error {
comment, err := s.repo.GetByID(ctx, commentID)
if err != nil {
return err
}
if comment == nil {
return errors.New("comment not found")
}
if comment.AuthorID != accountID {
return errors.New("permission denied")
}
return s.repo.DeleteComment(ctx, comment)
}
func (s *CommentService) GetAll(ctx context.Context, videoID uint) ([]Comment, error) {
exists, err := s.VideoRepository.IsExist(ctx, videoID)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.New("video not found")
}
return s.repo.GetAllComments(ctx, videoID)
}