Files
nl-video-api/internal/service/comment.go
2025-08-03 00:11:15 +08:00

429 lines
11 KiB
Go
Raw Permalink 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 service
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"nl-video-api/internal/dao"
"nl-video-api/utility/response"
)
// CommentService 评论服务
type CommentService struct{}
// NewCommentService 创建评论服务实例
func NewCommentService() *CommentService {
return &CommentService{}
}
// Add 添加评论
func (s *CommentService) Add(r *ghttp.Request) {
// 获取用户ID这里应该从JWT token中获取
userId := r.Get("user_id").Uint()
if userId == 0 {
response.Error(r, response.CodeUnauthorized, "用户未登录")
return
}
// 获取请求参数
movieId := r.Get("movie_id").Uint()
if movieId == 0 {
response.Error(r, response.CodeInvalidParam, "电影ID不能为空")
return
}
content := r.Get("content").String()
if content == "" {
response.Error(r, response.CodeInvalidParam, "评论内容不能为空")
return
}
parentId := r.Get("parent_id").Uint()
// 检查电影是否存在
movieCount, err := g.DB().Model("movie").Where("id", movieId).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if movieCount == 0 {
response.Error(r, response.CodeNotFound, "电影不存在")
return
}
// 如果是回复评论,检查父评论是否存在
if parentId > 0 {
parentCount, err := dao.Comment.Ctx(r.Context()).Where("id", parentId).Where("movie_id", movieId).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if parentCount == 0 {
response.Error(r, response.CodeNotFound, "父评论不存在")
return
}
}
// 创建评论
commentId, err := dao.Comment.Ctx(r.Context()).Data(g.Map{
"user_id": userId,
"movie_id": movieId,
"parent_id": parentId,
"content": content,
"like_count": 0,
"status": 1, // 默认通过审核
"created_at": gtime.Now(),
"updated_at": gtime.Now(),
}).InsertAndGetId()
if err != nil {
response.Error(r, response.CodeInternalError, "添加评论失败")
return
}
response.Success(r, g.Map{
"id": commentId,
})
}
// GetList 获取评论列表
func (s *CommentService) GetList(r *ghttp.Request) {
movieId := r.Get("movie_id").Uint()
if movieId == 0 {
response.Error(r, response.CodeInvalidParam, "电影ID不能为空")
return
}
page := r.Get("page", 1).Int()
size := r.Get("size", 10).Int()
parentId := r.Get("parent_id", 0).Uint()
// 构建查询条件
query := dao.Comment.Ctx(r.Context()).Where("movie_id", movieId).Where("status", 1)
if parentId > 0 {
query = query.Where("parent_id", parentId)
} else {
query = query.Where("parent_id", 0)
}
// 获取总数
total, err := query.Count()
if err != nil {
response.Error(r, response.CodeInternalError, "获取评论总数失败")
return
}
// 获取评论列表
var comments []g.Map
err = query.Order("created_at DESC").
Limit((page-1)*size, size).
Scan(&comments)
if err != nil {
response.Error(r, response.CodeInternalError, "获取评论列表失败")
return
}
// 获取用户信息
userIds := make([]interface{}, 0)
for _, comment := range comments {
userIds = append(userIds, comment["user_id"])
}
userMap := make(map[uint]g.Map)
if len(userIds) > 0 {
var users []g.Map
g.DB().Model("nl_user").WhereIn("id", userIds).Fields("id, username, avatar").Scan(&users)
for _, user := range users {
userMap[gconv.Uint(user["id"])] = user
}
}
// 组装返回数据
list := make([]g.Map, 0)
for _, comment := range comments {
userId := gconv.Uint(comment["user_id"])
user := userMap[userId]
item := g.Map{
"id": comment["id"],
"user_id": comment["user_id"],
"username": user["username"],
"avatar": user["avatar"],
"movie_id": comment["movie_id"],
"parent_id": comment["parent_id"],
"content": comment["content"],
"like_count": comment["like_count"],
"created_at": gconv.Int64(comment["created_at"]),
"replies": make([]g.Map, 0), // 子评论,如果需要可以递归获取
}
list = append(list, item)
}
response.Success(r, g.Map{
"list": list,
"total": total,
"page": page,
"size": size,
})
}
// Delete 删除评论
func (s *CommentService) Delete(r *ghttp.Request) {
// 获取用户ID
userId := r.Get("user_id").Uint()
if userId == 0 {
response.Error(r, response.CodeUnauthorized, "用户未登录")
return
}
commentId := r.Get("id").Uint()
if commentId == 0 {
response.Error(r, response.CodeInvalidParam, "评论ID不能为空")
return
}
// 检查评论是否存在且属于当前用户
var comment g.Map
err := dao.Comment.Ctx(r.Context()).Where("id", commentId).Where("user_id", userId).Scan(&comment)
if err != nil {
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if len(comment) == 0 {
response.Error(r, response.CodeNotFound, "评论不存在或无权限删除")
return
}
// 删除评论(软删除,更新状态)
_, err = dao.Comment.Ctx(r.Context()).Where("id", commentId).Data(g.Map{
"status": 0, // 0表示已删除
"updated_at": gtime.Now(),
}).Update()
if err != nil {
response.Error(r, response.CodeInternalError, "删除评论失败")
return
}
// 同时删除该评论的所有回复
_, err = dao.Comment.Ctx(r.Context()).Where("parent_id", commentId).Data(g.Map{
"status": 0,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
// 记录日志,但不影响主要操作
g.Log().Error(r.Context(), "删除子评论失败:", err)
}
response.Success(r, "删除成功")
}
// Like 点赞评论
func (s *CommentService) Like(r *ghttp.Request) {
// 获取用户ID
userId := r.Get("user_id").Uint()
if userId == 0 {
response.Error(r, response.CodeUnauthorized, "用户未登录")
return
}
commentId := r.Get("id").Uint()
if commentId == 0 {
response.Error(r, response.CodeInvalidParam, "评论ID不能为空")
return
}
// 检查评论是否存在
commentCount, err := dao.Comment.Ctx(r.Context()).Where("id", commentId).Where("status", 1).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if commentCount == 0 {
response.Error(r, response.CodeNotFound, "评论不存在")
return
}
// 检查是否已经点赞
likeCount, err := g.DB().Model("comment_like").Where("user_id", userId).Where("comment_id", commentId).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "系统错误")
return
}
if likeCount > 0 {
// 取消点赞
_, err = g.DB().Model("comment_like").Where("user_id", userId).Where("comment_id", commentId).Delete()
if err != nil {
response.Error(r, response.CodeInternalError, "取消点赞失败")
return
}
// 减少点赞数
_, err = dao.Comment.Ctx(r.Context()).Where("id", commentId).Data("like_count=like_count-1").Update()
if err != nil {
response.Error(r, response.CodeInternalError, "更新点赞数失败")
return
}
response.Success(r, g.Map{
"action": "unlike",
"message": "取消点赞成功",
})
} else {
// 添加点赞
_, err = g.DB().Model("comment_like").Data(g.Map{
"user_id": userId,
"comment_id": commentId,
"created_at": gtime.Now(),
}).Insert()
if err != nil {
response.Error(r, response.CodeInternalError, "点赞失败")
return
}
// 增加点赞数
_, err = dao.Comment.Ctx(r.Context()).Where("id", commentId).Data("like_count=like_count+1").Update()
if err != nil {
response.Error(r, response.CodeInternalError, "更新点赞数失败")
return
}
response.Success(r, g.Map{
"action": "like",
"message": "点赞成功",
})
}
}
// Report 举报评论
func (s *CommentService) Report(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
reason := r.Get("reason").String()
// 参数验证
if id == 0 {
response.Error(r, response.CodeInvalidParam, "评论ID不能为空")
return
}
if reason == "" {
response.Error(r, response.CodeInvalidParam, "举报原因不能为空")
return
}
// 检查评论是否存在
count, err := dao.Comment.Ctx(r.Context()).Where("id", id).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "检查评论失败")
return
}
if count == 0 {
response.Error(r, response.CodeNotFound, "评论不存在")
return
}
// 这里应该实现举报逻辑,创建举报记录
response.Success(r, "举报成功")
}
// Unlike 取消点赞评论
func (s *CommentService) Unlike(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
// 参数验证
if id == 0 {
response.Error(r, response.CodeInvalidParam, "评论ID不能为空")
return
}
// 检查评论是否存在
count, err := dao.Comment.Ctx(r.Context()).Where("id", id).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "检查评论失败")
return
}
if count == 0 {
response.Error(r, response.CodeNotFound, "评论不存在")
return
}
// 这里应该实现取消点赞逻辑
response.Success(r, "取消点赞成功")
}
// AdminList 管理员获取评论列表
func (s *CommentService) AdminList(r *ghttp.Request) {
s.AdminGetList(r)
}
// AdminUpdateStatus 管理员更新评论状态
func (s *CommentService) AdminUpdateStatus(r *ghttp.Request) {
// 获取请求参数
id := r.Get("id").Uint()
status := r.Get("status").Int()
// 参数验证
if id == 0 {
response.Error(r, response.CodeInvalidParam, "评论ID不能为空")
return
}
// 检查评论是否存在
count, err := dao.Comment.Ctx(r.Context()).Where("id", id).Count()
if err != nil {
response.Error(r, response.CodeInternalError, "检查评论失败")
return
}
if count == 0 {
response.Error(r, response.CodeNotFound, "评论不存在")
return
}
// 更新评论状态
_, err = dao.Comment.Ctx(r.Context()).Where("id", id).Data(g.Map{
"status": status,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
response.Error(r, response.CodeInternalError, "更新评论状态失败")
return
}
response.Success(r, "更新成功")
}
// AdminGetList 管理员获取评论列表
func (s *CommentService) AdminGetList(r *ghttp.Request) {
s.GetList(r)
}
// AdminBatchDelete 管理员批量删除评论
func (s *CommentService) AdminBatchDelete(r *ghttp.Request) {
// 获取请求参数
var ids []uint
r.Parse(&ids)
if len(ids) == 0 {
response.Error(r, response.CodeInvalidParam, "请选择要删除的评论")
return
}
// 批量删除评论(软删除)
_, err := dao.Comment.Ctx(r.Context()).WhereIn("id", ids).Data(g.Map{
"status": 0,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
response.Error(r, response.CodeInternalError, "批量删除评论失败")
return
}
response.Success(r, "批量删除成功")
}