初始化
This commit is contained in:
206
server/service/folder_service.go
Normal file
206
server/service/folder_service.go
Normal file
@@ -0,0 +1,206 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"seeyon-filesystem/config"
|
||||
"seeyon-filesystem/dto"
|
||||
"seeyon-filesystem/model"
|
||||
"seeyon-filesystem/repository"
|
||||
)
|
||||
|
||||
// FolderService 文件夹业务服务
|
||||
type FolderService struct {
|
||||
folderRepo *repository.FolderRepository
|
||||
fileRepo *repository.FileRepository
|
||||
}
|
||||
|
||||
// NewFolderService 创建文件夹服务实例
|
||||
func NewFolderService() *FolderService {
|
||||
return &FolderService{
|
||||
folderRepo: repository.NewFolderRepository(),
|
||||
fileRepo: repository.NewFileRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建文件夹
|
||||
func (s *FolderService) Create(req *dto.CreateFolderRequest, ownerID uint64) (*dto.FolderVO, error) {
|
||||
// 构建物化路径
|
||||
parentPath := "/"
|
||||
if req.ParentID > 0 {
|
||||
parent, err := s.folderRepo.FindByID(req.ParentID)
|
||||
if err != nil {
|
||||
return nil, errors.New("父文件夹不存在")
|
||||
}
|
||||
if parent.OwnerID != ownerID {
|
||||
return nil, errors.New("无权访问父文件夹")
|
||||
}
|
||||
parentPath = parent.Path
|
||||
}
|
||||
|
||||
// 检查同名文件夹
|
||||
existing, _ := s.folderRepo.FindByNameAndParent(req.Name, req.ParentID, ownerID)
|
||||
if existing != nil {
|
||||
return nil, errors.New("同名文件夹已存在")
|
||||
}
|
||||
|
||||
folder := &model.Folder{
|
||||
Name: req.Name,
|
||||
ParentID: req.ParentID,
|
||||
OwnerID: ownerID,
|
||||
Path: parentPath, // 先创建, 获取ID后再更新路径
|
||||
Status: 1,
|
||||
}
|
||||
|
||||
if err := s.folderRepo.Create(folder); err != nil {
|
||||
return nil, fmt.Errorf("创建文件夹失败: %w", err)
|
||||
}
|
||||
|
||||
// 更新物化路径
|
||||
folder.Path = fmt.Sprintf("%s%d/", parentPath, folder.ID)
|
||||
if err := s.folderRepo.Update(folder); err != nil {
|
||||
return nil, fmt.Errorf("更新文件夹路径失败: %w", err)
|
||||
}
|
||||
|
||||
return s.toFolderVO(folder), nil
|
||||
}
|
||||
|
||||
// GetByID 根据ID获取文件夹
|
||||
func (s *FolderService) GetByID(id uint64, ownerID uint64) (*dto.FolderVO, error) {
|
||||
folder, err := s.folderRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("文件夹不存在")
|
||||
}
|
||||
if folder.OwnerID != ownerID {
|
||||
return nil, errors.New("无权访问此文件夹")
|
||||
}
|
||||
return s.toFolderVO(folder), nil
|
||||
}
|
||||
|
||||
// ListChildren 获取文件夹的子项(文件+文件夹, 基于权限)
|
||||
func (s *FolderService) ListChildren(folderID uint64, userID uint64) (*dto.FileListVO, error) {
|
||||
// 获取用户角色IDs
|
||||
roleIDs := s.getUserRoleIDs(userID)
|
||||
|
||||
// 如果指定了文件夹ID, 验证访问权限
|
||||
if folderID > 0 {
|
||||
folder, err := s.folderRepo.FindByID(folderID)
|
||||
if err != nil {
|
||||
return nil, errors.New("文件夹不存在")
|
||||
}
|
||||
if folder.OwnerID != userID {
|
||||
return nil, errors.New("无权访问此文件夹")
|
||||
}
|
||||
}
|
||||
|
||||
// 查询子文件夹(暂时只查自己创建的)
|
||||
folders, err := s.folderRepo.ListByParent(folderID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询子文件(基于权限: 自己的 + 被授权的)
|
||||
files, err := s.fileRepo.ListByFolder(folderID, userID, roleIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 组装响应
|
||||
folderVOs := make([]dto.FolderVO, 0, len(folders))
|
||||
for _, f := range folders {
|
||||
folderVOs = append(folderVOs, *s.toFolderVO(&f))
|
||||
}
|
||||
|
||||
fileVOs := make([]dto.FileVO, 0, len(files))
|
||||
for _, f := range files {
|
||||
fileVOs = append(fileVOs, *s.toFileVO(&f))
|
||||
}
|
||||
|
||||
return &dto.FileListVO{
|
||||
Folders: folderVOs,
|
||||
Files: fileVOs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Rename 重命名文件夹(乐观锁)
|
||||
func (s *FolderService) Rename(id uint64, newName string, ownerID uint64, version int) error {
|
||||
folder, err := s.folderRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return errors.New("文件夹不存在")
|
||||
}
|
||||
if folder.OwnerID != ownerID {
|
||||
return errors.New("无权操作此文件夹")
|
||||
}
|
||||
|
||||
// 乐观锁检查
|
||||
if version > 0 && folder.Version != version {
|
||||
return fmt.Errorf("文件夹已被其他人修改, 当前版本: %d, 请刷新后重试", folder.Version)
|
||||
}
|
||||
|
||||
newVersion := folder.Version + 1
|
||||
result := config.DB.Model(&model.Folder{}).
|
||||
Where("id = ? AND version = ?", id, folder.Version).
|
||||
Updates(map[string]interface{}{
|
||||
"name": newName,
|
||||
"version": newVersion,
|
||||
})
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return fmt.Errorf("文件夹已被其他人修改, 请刷新后重试")
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
// Delete 删除文件夹(移入回收站)
|
||||
func (s *FolderService) Delete(id uint64, ownerID uint64) error {
|
||||
folder, err := s.folderRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return errors.New("文件夹不存在")
|
||||
}
|
||||
if folder.OwnerID != ownerID {
|
||||
return errors.New("无权操作此文件夹")
|
||||
}
|
||||
|
||||
return s.folderRepo.SoftDelete(id)
|
||||
}
|
||||
|
||||
// toFolderVO 转换为视图对象
|
||||
func (s *FolderService) toFolderVO(folder *model.Folder) *dto.FolderVO {
|
||||
return &dto.FolderVO{
|
||||
ID: folder.ID,
|
||||
Name: folder.Name,
|
||||
ParentID: folder.ParentID,
|
||||
Path: folder.Path,
|
||||
Version: folder.Version,
|
||||
CreatedAt: folder.CreatedAt,
|
||||
UpdatedAt: folder.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// getUserRoleIDs 获取用户的角色ID列表
|
||||
func (s *FolderService) getUserRoleIDs(userID uint64) []uint64 {
|
||||
var userRoles []model.UserRole
|
||||
config.DB.Where("user_id = ?", userID).Find(&userRoles)
|
||||
roleIDs := make([]uint64, 0, len(userRoles))
|
||||
for _, ur := range userRoles {
|
||||
roleIDs = append(roleIDs, ur.RoleID)
|
||||
}
|
||||
return roleIDs
|
||||
}
|
||||
|
||||
// toFileVO 转换为视图对象
|
||||
func (s *FolderService) toFileVO(file *model.File) *dto.FileVO {
|
||||
return &dto.FileVO{
|
||||
ID: file.ID,
|
||||
Name: file.Name,
|
||||
Extension: file.Extension,
|
||||
FolderID: file.FolderID,
|
||||
Size: file.Size,
|
||||
MimeType: file.MimeType,
|
||||
IsFavorite: file.IsFavorite,
|
||||
DownloadCount: file.DownloadCount,
|
||||
CreatedAt: file.CreatedAt,
|
||||
UpdatedAt: file.UpdatedAt,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user