Files
backend/internal/service/texture_service.go
lafay 801f1b1397 refactor: Implement dependency injection for handlers and services
- Refactored AuthHandler, UserHandler, TextureHandler, ProfileHandler, CaptchaHandler, and YggdrasilHandler to use dependency injection.
- Removed direct instantiation of services and repositories within handlers, replacing them with constructor injection.
- Updated the container to initialize service instances and provide them to handlers.
- Enhanced code structure for better testability and adherence to Go best practices.
2025-12-02 19:47:04 +08:00

216 lines
5.3 KiB
Go

package service
import (
"carrotskin/internal/model"
"carrotskin/internal/repository"
"errors"
"fmt"
"go.uber.org/zap"
)
// textureServiceImpl TextureService的实现
type textureServiceImpl struct {
textureRepo repository.TextureRepository
userRepo repository.UserRepository
logger *zap.Logger
}
// NewTextureService 创建TextureService实例
func NewTextureService(
textureRepo repository.TextureRepository,
userRepo repository.UserRepository,
logger *zap.Logger,
) TextureService {
return &textureServiceImpl{
textureRepo: textureRepo,
userRepo: userRepo,
logger: logger,
}
}
func (s *textureServiceImpl) Create(uploaderID int64, name, description, textureType, url, hash string, size int, isPublic, isSlim bool) (*model.Texture, error) {
// 验证用户存在
user, err := s.userRepo.FindByID(uploaderID)
if err != nil || user == nil {
return nil, ErrUserNotFound
}
// 检查Hash是否已存在
existingTexture, err := s.textureRepo.FindByHash(hash)
if err != nil {
return nil, err
}
if existingTexture != nil {
return nil, errors.New("该材质已存在")
}
// 转换材质类型
textureTypeEnum, err := parseTextureTypeInternal(textureType)
if err != nil {
return nil, err
}
// 创建材质
texture := &model.Texture{
UploaderID: uploaderID,
Name: name,
Description: description,
Type: textureTypeEnum,
URL: url,
Hash: hash,
Size: size,
IsPublic: isPublic,
IsSlim: isSlim,
Status: 1,
DownloadCount: 0,
FavoriteCount: 0,
}
if err := s.textureRepo.Create(texture); err != nil {
return nil, err
}
return texture, nil
}
func (s *textureServiceImpl) GetByID(id int64) (*model.Texture, error) {
texture, err := s.textureRepo.FindByID(id)
if err != nil {
return nil, err
}
if texture == nil {
return nil, ErrTextureNotFound
}
if texture.Status == -1 {
return nil, errors.New("材质已删除")
}
return texture, nil
}
func (s *textureServiceImpl) GetByUserID(uploaderID int64, page, pageSize int) ([]*model.Texture, int64, error) {
page, pageSize = NormalizePagination(page, pageSize)
return s.textureRepo.FindByUploaderID(uploaderID, page, pageSize)
}
func (s *textureServiceImpl) Search(keyword string, textureType model.TextureType, publicOnly bool, page, pageSize int) ([]*model.Texture, int64, error) {
page, pageSize = NormalizePagination(page, pageSize)
return s.textureRepo.Search(keyword, textureType, publicOnly, page, pageSize)
}
func (s *textureServiceImpl) Update(textureID, uploaderID int64, name, description string, isPublic *bool) (*model.Texture, error) {
// 获取材质并验证权限
texture, err := s.textureRepo.FindByID(textureID)
if err != nil {
return nil, err
}
if texture == nil {
return nil, ErrTextureNotFound
}
if texture.UploaderID != uploaderID {
return nil, ErrTextureNoPermission
}
// 更新字段
updates := make(map[string]interface{})
if name != "" {
updates["name"] = name
}
if description != "" {
updates["description"] = description
}
if isPublic != nil {
updates["is_public"] = *isPublic
}
if len(updates) > 0 {
if err := s.textureRepo.UpdateFields(textureID, updates); err != nil {
return nil, err
}
}
return s.textureRepo.FindByID(textureID)
}
func (s *textureServiceImpl) Delete(textureID, uploaderID int64) error {
// 获取材质并验证权限
texture, err := s.textureRepo.FindByID(textureID)
if err != nil {
return err
}
if texture == nil {
return ErrTextureNotFound
}
if texture.UploaderID != uploaderID {
return ErrTextureNoPermission
}
return s.textureRepo.Delete(textureID)
}
func (s *textureServiceImpl) ToggleFavorite(userID, textureID int64) (bool, error) {
// 确保材质存在
texture, err := s.textureRepo.FindByID(textureID)
if err != nil {
return false, err
}
if texture == nil {
return false, ErrTextureNotFound
}
isFavorited, err := s.textureRepo.IsFavorited(userID, textureID)
if err != nil {
return false, err
}
if isFavorited {
// 已收藏 -> 取消收藏
if err := s.textureRepo.RemoveFavorite(userID, textureID); err != nil {
return false, err
}
if err := s.textureRepo.DecrementFavoriteCount(textureID); err != nil {
return false, err
}
return false, nil
}
// 未收藏 -> 添加收藏
if err := s.textureRepo.AddFavorite(userID, textureID); err != nil {
return false, err
}
if err := s.textureRepo.IncrementFavoriteCount(textureID); err != nil {
return false, err
}
return true, nil
}
func (s *textureServiceImpl) GetUserFavorites(userID int64, page, pageSize int) ([]*model.Texture, int64, error) {
page, pageSize = NormalizePagination(page, pageSize)
return s.textureRepo.GetUserFavorites(userID, page, pageSize)
}
func (s *textureServiceImpl) CheckUploadLimit(uploaderID int64, maxTextures int) error {
count, err := s.textureRepo.CountByUploaderID(uploaderID)
if err != nil {
return err
}
if count >= int64(maxTextures) {
return fmt.Errorf("已达到最大上传数量限制(%d)", maxTextures)
}
return nil
}
// parseTextureTypeInternal 解析材质类型
func parseTextureTypeInternal(textureType string) (model.TextureType, error) {
switch textureType {
case "SKIN":
return model.TextureTypeSkin, nil
case "CAPE":
return model.TextureTypeCape, nil
default:
return "", errors.New("无效的材质类型")
}
}