This commit is contained in:
xujiang
2025-07-10 18:09:11 +08:00
parent 5cbdc5af73
commit 604b9e59ba
95 changed files with 23709 additions and 19 deletions

View File

@ -0,0 +1,233 @@
package service
import (
"context"
"errors"
"photography-backend/internal/model/entity"
"photography-backend/internal/repository/interfaces"
"go.uber.org/zap"
)
type CategoryService struct {
categoryRepo interfaces.CategoryRepository
logger *zap.Logger
}
func NewCategoryService(categoryRepo interfaces.CategoryRepository, logger *zap.Logger) *CategoryService {
return &CategoryService{
categoryRepo: categoryRepo,
logger: logger,
}
}
// GetCategories 获取分类列表
func (s *CategoryService) GetCategories(ctx context.Context, parentID *uint) ([]*entity.Category, error) {
categories, err := s.categoryRepo.List(ctx, parentID)
if err != nil {
s.logger.Error("Failed to get categories", zap.Error(err))
return nil, err
}
return categories, nil
}
// GetCategoryTree 获取分类树
func (s *CategoryService) GetCategoryTree(ctx context.Context) ([]*entity.CategoryTree, error) {
tree, err := s.categoryRepo.GetTree(ctx)
if err != nil {
s.logger.Error("Failed to get category tree", zap.Error(err))
return nil, err
}
return tree, nil
}
// GetCategoryByID 根据ID获取分类
func (s *CategoryService) GetCategoryByID(ctx context.Context, id uint) (*entity.Category, error) {
category, err := s.categoryRepo.GetByID(ctx, id)
if err != nil {
s.logger.Error("Failed to get category by ID", zap.Error(err), zap.Uint("id", id))
return nil, err
}
return category, nil
}
// GetCategoryBySlug 根据slug获取分类
func (s *CategoryService) GetCategoryBySlug(ctx context.Context, slug string) (*entity.Category, error) {
category, err := s.categoryRepo.GetBySlug(ctx, slug)
if err != nil {
s.logger.Error("Failed to get category by slug", zap.Error(err), zap.String("slug", slug))
return nil, err
}
return category, nil
}
// CreateCategory 创建分类
func (s *CategoryService) CreateCategory(ctx context.Context, req *entity.CreateCategoryRequest) (*entity.Category, error) {
// 验证slug唯一性
if err := s.categoryRepo.ValidateSlugUnique(ctx, req.Slug, 0); err != nil {
return nil, err
}
// 验证父分类存在性
if req.ParentID != nil {
if err := s.categoryRepo.ValidateParentCategory(ctx, 0, *req.ParentID); err != nil {
return nil, err
}
}
// 获取排序顺序
sortOrder, err := s.categoryRepo.GetNextSortOrder(ctx, req.ParentID)
if err != nil {
return nil, err
}
category := &entity.Category{
Name: req.Name,
Slug: req.Slug,
Description: req.Description,
ParentID: req.ParentID,
SortOrder: sortOrder,
IsActive: true,
}
if err := s.categoryRepo.Create(ctx, category); err != nil {
s.logger.Error("Failed to create category", zap.Error(err))
return nil, err
}
s.logger.Info("Category created successfully", zap.Uint("id", category.ID))
return category, nil
}
// UpdateCategory 更新分类
func (s *CategoryService) UpdateCategory(ctx context.Context, id uint, req *entity.UpdateCategoryRequest) (*entity.Category, error) {
// 检查分类是否存在
category, err := s.categoryRepo.GetByID(ctx, id)
if err != nil {
s.logger.Error("Failed to get category", zap.Error(err), zap.Uint("id", id))
return nil, err
}
// 验证slug唯一性
if req.Slug != nil && *req.Slug != category.Slug {
if err := s.categoryRepo.ValidateSlugUnique(ctx, *req.Slug, id); err != nil {
return nil, err
}
}
// 验证父分类(防止循环引用)
if req.ParentID != nil {
// 检查是否有变更
if (category.ParentID == nil && *req.ParentID != 0) || (category.ParentID != nil && *req.ParentID != *category.ParentID) {
if err := s.categoryRepo.ValidateParentCategory(ctx, id, *req.ParentID); err != nil {
return nil, err
}
}
}
// 更新字段
if req.Name != nil {
category.Name = *req.Name
}
if req.Slug != nil {
category.Slug = *req.Slug
}
if req.Description != nil {
category.Description = *req.Description
}
if req.ParentID != nil {
if *req.ParentID == 0 {
category.ParentID = nil
} else {
category.ParentID = req.ParentID
}
}
if req.SortOrder != nil {
category.SortOrder = *req.SortOrder
}
if req.IsActive != nil {
category.IsActive = *req.IsActive
}
// 保存更新
if err := s.categoryRepo.Update(ctx, category); err != nil {
s.logger.Error("Failed to update category", zap.Error(err))
return nil, err
}
s.logger.Info("Category updated successfully", zap.Uint("id", id))
return category, nil
}
// DeleteCategory 删除分类
func (s *CategoryService) DeleteCategory(ctx context.Context, id uint) error {
// 检查分类是否存在
_, err := s.categoryRepo.GetByID(ctx, id)
if err != nil {
s.logger.Error("Failed to get category", zap.Error(err), zap.Uint("id", id))
return err
}
// 检查是否有子分类
children, err := s.categoryRepo.GetChildren(ctx, id)
if err != nil {
return err
}
if len(children) > 0 {
return errors.New("cannot delete category with subcategories")
}
// 直接删除分类在Repository层检查照片关联
if err := s.categoryRepo.Delete(ctx, id); err != nil {
s.logger.Error("Failed to delete category", zap.Error(err))
return err
}
s.logger.Info("Category deleted successfully", zap.Uint("id", id))
return nil
}
// ReorderCategories 重新排序分类
func (s *CategoryService) ReorderCategories(ctx context.Context, parentID *uint, categoryIDs []uint) error {
if len(categoryIDs) == 0 {
return nil
}
// 重新排序分类
if err := s.categoryRepo.Reorder(ctx, parentID, categoryIDs); err != nil {
s.logger.Error("Failed to reorder categories", zap.Error(err))
return err
}
s.logger.Info("Categories reordered successfully", zap.Int("count", len(categoryIDs)))
return nil
}
// GetCategoryStats 获取分类统计信息
func (s *CategoryService) GetCategoryStats(ctx context.Context) (*entity.CategoryStats, error) {
stats, err := s.categoryRepo.GetStats(ctx)
if err != nil {
s.logger.Error("Failed to get category stats", zap.Error(err))
return nil, err
}
return stats, nil
}
// GenerateSlug 生成唯一slug
func (s *CategoryService) GenerateSlug(ctx context.Context, name string) (string, error) {
slug, err := s.categoryRepo.GenerateUniqueSlug(ctx, name)
if err != nil {
s.logger.Error("Failed to generate unique slug", zap.Error(err))
return "", err
}
return slug, nil
}