feat(admin): add comprehensive admin management system
- Add admin handlers and services for users, posts, comments, groups, and dashboard - Implement role permission management with ability to view and update permissions - Add database seeding for roles and Casbin permission policies - Upgrade Casbin from v2 to v3 with GORM adapter for persistent policy storage - Add admin-specific repository methods with filtering and pagination - Register new admin API routes under /api/v1/admin/*
This commit is contained in:
243
internal/service/admin_comment_service.go
Normal file
243
internal/service/admin_comment_service.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"carrot_bbs/internal/dto"
|
||||
"carrot_bbs/internal/model"
|
||||
"carrot_bbs/internal/repository"
|
||||
)
|
||||
|
||||
// AdminCommentService 管理端评论服务接口
|
||||
type AdminCommentService interface {
|
||||
// GetCommentList 获取评论列表(分页、搜索、状态筛选)
|
||||
GetCommentList(ctx context.Context, page, pageSize int, keyword, postID, authorID, status, startDate, endDate string) ([]dto.AdminCommentListResponse, int64, error)
|
||||
// GetCommentDetail 获取评论详情
|
||||
GetCommentDetail(ctx context.Context, commentID string) (*dto.AdminCommentDetailResponse, error)
|
||||
// DeleteComment 删除评论
|
||||
DeleteComment(ctx context.Context, commentID string) error
|
||||
// BatchDeleteComments 批量删除评论
|
||||
BatchDeleteComments(ctx context.Context, ids []string) (*dto.AdminBatchOperationResponse, error)
|
||||
// GetCommentsByPostID 获取帖子的评论列表
|
||||
GetCommentsByPostID(ctx context.Context, postID string, page, pageSize int) ([]dto.AdminCommentListResponse, int64, error)
|
||||
}
|
||||
|
||||
// adminCommentServiceImpl 管理端评论服务实现
|
||||
type adminCommentServiceImpl struct {
|
||||
commentRepo *repository.CommentRepository
|
||||
postRepo *repository.PostRepository
|
||||
}
|
||||
|
||||
// NewAdminCommentService 创建管理端评论服务
|
||||
func NewAdminCommentService(commentRepo *repository.CommentRepository, postRepo *repository.PostRepository) AdminCommentService {
|
||||
return &adminCommentServiceImpl{
|
||||
commentRepo: commentRepo,
|
||||
postRepo: postRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// GetCommentList 获取评论列表
|
||||
func (s *adminCommentServiceImpl) GetCommentList(ctx context.Context, page, pageSize int, keyword, postID, authorID, status, startDate, endDate string) ([]dto.AdminCommentListResponse, int64, error) {
|
||||
filter := repository.AdminCommentListFilter{
|
||||
Keyword: keyword,
|
||||
PostID: postID,
|
||||
AuthorID: authorID,
|
||||
Status: status,
|
||||
StartDate: startDate,
|
||||
EndDate: endDate,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
comments, total, err := s.commentRepo.GetAdminCommentList(filter)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
responses := make([]dto.AdminCommentListResponse, len(comments))
|
||||
for i, comment := range comments {
|
||||
responses[i] = s.convertCommentToAdminListResponse(comment)
|
||||
}
|
||||
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
// GetCommentDetail 获取评论详情
|
||||
func (s *adminCommentServiceImpl) GetCommentDetail(ctx context.Context, commentID string) (*dto.AdminCommentDetailResponse, error) {
|
||||
comment, err := s.commentRepo.GetAdminCommentByID(commentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.convertCommentToAdminDetailResponse(comment), nil
|
||||
}
|
||||
|
||||
// DeleteComment 删除评论
|
||||
func (s *adminCommentServiceImpl) DeleteComment(ctx context.Context, commentID string) error {
|
||||
return s.commentRepo.Delete(commentID)
|
||||
}
|
||||
|
||||
// BatchDeleteComments 批量删除评论
|
||||
func (s *adminCommentServiceImpl) BatchDeleteComments(ctx context.Context, ids []string) (*dto.AdminBatchOperationResponse, error) {
|
||||
failedIDs, err := s.commentRepo.BatchDelete(ids)
|
||||
if err != nil {
|
||||
return &dto.AdminBatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "批量删除失败",
|
||||
Failed: ids,
|
||||
}, err
|
||||
}
|
||||
|
||||
if len(failedIDs) == 0 {
|
||||
return &dto.AdminBatchOperationResponse{
|
||||
Success: true,
|
||||
Message: "批量删除成功",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &dto.AdminBatchOperationResponse{
|
||||
Success: true,
|
||||
Message: "部分评论删除成功",
|
||||
Failed: failedIDs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetCommentsByPostID 获取帖子的评论列表
|
||||
func (s *adminCommentServiceImpl) GetCommentsByPostID(ctx context.Context, postID string, page, pageSize int) ([]dto.AdminCommentListResponse, int64, error) {
|
||||
comments, total, err := s.commentRepo.GetCommentsByPostIDForAdmin(postID, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
responses := make([]dto.AdminCommentListResponse, len(comments))
|
||||
for i, comment := range comments {
|
||||
responses[i] = s.convertCommentToAdminListResponse(comment)
|
||||
}
|
||||
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
// convertCommentToAdminListResponse 转换评论为管理端列表响应
|
||||
func (s *adminCommentServiceImpl) convertCommentToAdminListResponse(comment *model.Comment) dto.AdminCommentListResponse {
|
||||
// 解析图片
|
||||
var images []dto.CommentImageResponse
|
||||
if comment.Images != "" {
|
||||
var urls []string
|
||||
if err := json.Unmarshal([]byte(comment.Images), &urls); err == nil {
|
||||
images = make([]dto.CommentImageResponse, len(urls))
|
||||
for i, url := range urls {
|
||||
images[i] = dto.CommentImageResponse{URL: url}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 作者信息
|
||||
var author *dto.UserResponse
|
||||
if comment.User != nil {
|
||||
author = &dto.UserResponse{
|
||||
ID: comment.User.ID,
|
||||
Username: comment.User.Username,
|
||||
Nickname: comment.User.Nickname,
|
||||
Email: comment.User.Email,
|
||||
Phone: comment.User.Phone,
|
||||
Avatar: comment.User.Avatar,
|
||||
Bio: comment.User.Bio,
|
||||
Website: comment.User.Website,
|
||||
Location: comment.User.Location,
|
||||
CreatedAt: comment.User.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
}
|
||||
}
|
||||
|
||||
// 帖子简要信息
|
||||
var postInfo *dto.AdminCommentPostInfo
|
||||
if comment.PostID != "" {
|
||||
postInfo = &dto.AdminCommentPostInfo{
|
||||
ID: comment.PostID,
|
||||
}
|
||||
// 尝试获取帖子标题
|
||||
post, err := s.postRepo.GetByID(comment.PostID)
|
||||
if err == nil && post != nil {
|
||||
postInfo.Title = post.Title
|
||||
}
|
||||
}
|
||||
|
||||
return dto.AdminCommentListResponse{
|
||||
ID: comment.ID,
|
||||
PostID: comment.PostID,
|
||||
UserID: comment.UserID,
|
||||
ParentID: comment.ParentID,
|
||||
RootID: comment.RootID,
|
||||
Content: comment.Content,
|
||||
Images: images,
|
||||
Status: string(comment.Status),
|
||||
LikesCount: comment.LikesCount,
|
||||
RepliesCount: comment.RepliesCount,
|
||||
CreatedAt: comment.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
UpdatedAt: comment.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
Author: author,
|
||||
Post: postInfo,
|
||||
}
|
||||
}
|
||||
|
||||
// convertCommentToAdminDetailResponse 转换评论为管理端详情响应
|
||||
func (s *adminCommentServiceImpl) convertCommentToAdminDetailResponse(comment *model.Comment) *dto.AdminCommentDetailResponse {
|
||||
// 解析图片
|
||||
var images []dto.CommentImageResponse
|
||||
if comment.Images != "" {
|
||||
var urls []string
|
||||
if err := json.Unmarshal([]byte(comment.Images), &urls); err == nil {
|
||||
images = make([]dto.CommentImageResponse, len(urls))
|
||||
for i, url := range urls {
|
||||
images[i] = dto.CommentImageResponse{URL: url}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 作者信息
|
||||
var author *dto.UserResponse
|
||||
if comment.User != nil {
|
||||
author = &dto.UserResponse{
|
||||
ID: comment.User.ID,
|
||||
Username: comment.User.Username,
|
||||
Nickname: comment.User.Nickname,
|
||||
Email: comment.User.Email,
|
||||
Phone: comment.User.Phone,
|
||||
Avatar: comment.User.Avatar,
|
||||
Bio: comment.User.Bio,
|
||||
Website: comment.User.Website,
|
||||
Location: comment.User.Location,
|
||||
CreatedAt: comment.User.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
}
|
||||
}
|
||||
|
||||
// 帖子简要信息
|
||||
var postInfo *dto.AdminCommentPostInfo
|
||||
if comment.PostID != "" {
|
||||
postInfo = &dto.AdminCommentPostInfo{
|
||||
ID: comment.PostID,
|
||||
}
|
||||
// 尝试获取帖子标题
|
||||
post, err := s.postRepo.GetByID(comment.PostID)
|
||||
if err == nil && post != nil {
|
||||
postInfo.Title = post.Title
|
||||
}
|
||||
}
|
||||
|
||||
return &dto.AdminCommentDetailResponse{
|
||||
ID: comment.ID,
|
||||
PostID: comment.PostID,
|
||||
UserID: comment.UserID,
|
||||
ParentID: comment.ParentID,
|
||||
RootID: comment.RootID,
|
||||
Content: comment.Content,
|
||||
Images: images,
|
||||
Status: string(comment.Status),
|
||||
LikesCount: comment.LikesCount,
|
||||
RepliesCount: comment.RepliesCount,
|
||||
CreatedAt: comment.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
UpdatedAt: comment.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
Author: author,
|
||||
Post: postInfo,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user