Files
ai_dianshang/server/internal/repository/comment.go
2025-11-28 15:18:10 +08:00

305 lines
8.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"fmt"
"gorm.io/gorm"
"dianshang/internal/model"
)
type CommentRepository struct {
db *gorm.DB
}
func NewCommentRepository(db *gorm.DB) *CommentRepository {
return &CommentRepository{db: db}
}
// Create 创建评论
func (r *CommentRepository) Create(comment *model.Comment) error {
return r.db.Create(comment).Error
}
// GetByID 根据ID获取评论
func (r *CommentRepository) GetByID(id uint) (*model.Comment, error) {
var comment model.Comment
err := r.db.Preload("User").Preload("Product").Preload("Order").Preload("Replies.User").First(&comment, id).Error
return &comment, err
}
// GetByProductID 根据商品ID获取评论列表
func (r *CommentRepository) GetByProductID(productID uint, offset, limit int, rating int) ([]model.Comment, int64, error) {
var comments []model.Comment
var total int64
query := r.db.Model(&model.Comment{}).Where("product_id = ? AND status = ?", productID, 1)
// 按评分筛选
if rating > 0 && rating <= 5 {
query = query.Where("rating = ?", rating)
}
// 获取总数
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// 获取评论列表
err := query.Preload("User").Preload("Replies", "status = ?", 1).Preload("Replies.User").
Order("created_at DESC").Offset(offset).Limit(limit).Find(&comments).Error
return comments, total, err
}
// GetByUserID 根据用户ID获取评论列表
func (r *CommentRepository) GetByUserID(userID uint, offset, limit int) ([]model.Comment, int64, error) {
var comments []model.Comment
var total int64
query := r.db.Model(&model.Comment{}).Where("user_id = ? AND status = ?", userID, 1)
// 获取总数
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// 获取评论列表
err := query.Preload("Product").Preload("Replies", "status = ?", 1).Preload("Replies.User").
Order("created_at DESC").Offset(offset).Limit(limit).Find(&comments).Error
return comments, total, err
}
// GetByOrderItemID 根据订单项ID获取评论
func (r *CommentRepository) GetByOrderItemID(orderItemID uint) (*model.Comment, error) {
var comment model.Comment
err := r.db.Where("order_item_id = ? AND status = ?", orderItemID, 1).First(&comment).Error
if err != nil {
return nil, err
}
return &comment, nil
}
// Update 更新评论
func (r *CommentRepository) Update(comment *model.Comment) error {
return r.db.Save(comment).Error
}
// Delete 删除评论(软删除)
func (r *CommentRepository) Delete(id uint) error {
return r.db.Model(&model.Comment{}).Where("id = ?", id).Update("status", 3).Error
}
// GetStats 获取商品评论统计
func (r *CommentRepository) GetStats(productID uint) (*model.CommentStats, error) {
var stats model.CommentStats
stats.ProductID = productID
// 获取总评论数和平均评分
err := r.db.Model(&model.Comment{}).
Select("COUNT(*) as total_count, AVG(rating) as average_rating").
Where("product_id = ? AND status = ?", productID, 1).
Scan(&stats).Error
if err != nil {
return nil, err
}
// 获取各星级评论数
var ratingCounts []struct {
Rating int `json:"rating"`
Count int `json:"count"`
}
err = r.db.Model(&model.Comment{}).
Select("rating, COUNT(*) as count").
Where("product_id = ? AND status = ?", productID, 1).
Group("rating").
Scan(&ratingCounts).Error
if err != nil {
return nil, err
}
// 填充各星级评论数
for _, rc := range ratingCounts {
switch rc.Rating {
case 1:
stats.Rating1Count = rc.Count
case 2:
stats.Rating2Count = rc.Count
case 3:
stats.Rating3Count = rc.Count
case 4:
stats.Rating4Count = rc.Count
case 5:
stats.Rating5Count = rc.Count
}
}
// 获取带图评论数
var hasImagesCount int64
err = r.db.Model(&model.Comment{}).
Where("product_id = ? AND status = ? AND images != '' AND images != '[]'", productID, 1).
Count(&hasImagesCount).Error
if err != nil {
return nil, err
}
stats.HasImagesCount = int(hasImagesCount)
return &stats, nil
}
// GetList 获取评论列表(管理端使用)
func (r *CommentRepository) GetList(offset, limit int, conditions map[string]interface{}) ([]model.Comment, int64, error) {
var comments []model.Comment
var total int64
query := r.db.Model(&model.Comment{})
// 添加查询条件
for key, value := range conditions {
switch key {
case "product_id":
query = query.Where("product_id = ?", value)
case "user_id":
query = query.Where("user_id = ?", value)
case "rating":
query = query.Where("rating = ?", value)
case "status":
query = query.Where("status = ?", value)
case "keyword":
query = query.Where("content LIKE ?", "%"+value.(string)+"%")
}
}
// 获取总数
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// 获取评论列表
err := query.Preload("User").Preload("Product").Preload("Order").
Order("created_at DESC").Offset(offset).Limit(limit).Find(&comments).Error
return comments, total, err
}
// CreateReply 创建评论回复
func (r *CommentRepository) CreateReply(reply *model.CommentReply) error {
tx := r.db.Begin()
// 创建回复
if err := tx.Create(reply).Error; err != nil {
tx.Rollback()
return err
}
// 更新评论回复数量
if err := tx.Model(&model.Comment{}).Where("id = ?", reply.CommentID).
UpdateColumn("reply_count", gorm.Expr("reply_count + ?", 1)).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
// GetHighRatingComments 获取高分评论(用于首页展示)
func (r *CommentRepository) GetHighRatingComments(limit int, minRating int) ([]model.Comment, error) {
var comments []model.Comment
// 获取评分>=minRating的评论按评分降序、创建时间降序排列
err := r.db.Model(&model.Comment{}).
Where("status = ? AND rating >= ?", 1, minRating).
Preload("User").
Preload("Product").
Order("rating DESC, created_at DESC").
Limit(limit).
Find(&comments).Error
return comments, err
}
// GetReplies 获取评论回复列表
func (r *CommentRepository) GetReplies(commentID uint) ([]model.CommentReply, error) {
var replies []model.CommentReply
err := r.db.Where("comment_id = ? AND status = ?", commentID, 1).
Preload("User").Order("created_at ASC").Find(&replies).Error
return replies, err
}
// LikeComment 点赞评论
func (r *CommentRepository) LikeComment(commentID, userID uint) error {
tx := r.db.Begin()
// 检查是否已点赞
var count int64
if err := tx.Model(&model.CommentLike{}).Where("comment_id = ? AND user_id = ?", commentID, userID).Count(&count).Error; err != nil {
tx.Rollback()
return err
}
if count > 0 {
tx.Rollback()
return fmt.Errorf("已经点赞过了")
}
// 创建点赞记录
like := &model.CommentLike{
CommentID: commentID,
UserID: userID,
}
if err := tx.Create(like).Error; err != nil {
tx.Rollback()
return err
}
// 更新评论点赞数量
if err := tx.Model(&model.Comment{}).Where("id = ?", commentID).
UpdateColumn("like_count", gorm.Expr("like_count + ?", 1)).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
// UnlikeComment 取消点赞评论
func (r *CommentRepository) UnlikeComment(commentID, userID uint) error {
tx := r.db.Begin()
// 删除点赞记录
if err := tx.Where("comment_id = ? AND user_id = ?", commentID, userID).Delete(&model.CommentLike{}).Error; err != nil {
tx.Rollback()
return err
}
// 更新评论点赞数量
if err := tx.Model(&model.Comment{}).Where("id = ?", commentID).
UpdateColumn("like_count", gorm.Expr("like_count - ?", 1)).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
// UpdateProductStats 更新商品评论统计
func (r *CommentRepository) UpdateProductStats(productID uint) error {
var stats struct {
Count int `json:"count"`
Rating float64 `json:"rating"`
}
err := r.db.Model(&model.Comment{}).
Select("COUNT(*) as count, AVG(rating) as rating").
Where("product_id = ? AND status = ?", productID, 1).
Scan(&stats).Error
if err != nil {
return err
}
return r.db.Model(&model.Product{}).Where("id = ?", productID).
Updates(map[string]interface{}{
"comment_count": stats.Count,
"average_rating": stats.Rating,
}).Error
}