Files
filestoragesystem/go/internal/service/project.go
T
2026-08-23 00:48:10 +08:00

111 lines
3.1 KiB
Go

package service
import (
"fmt"
"os"
"path/filepath"
"filestoragesystem/internal/config"
"filestoragesystem/internal/model"
"filestoragesystem/internal/repository"
"filestoragesystem/pkg/apperr"
)
// ProjectService 项目服务
type ProjectService struct {
cfg *config.Config
projectRepo *repository.ProjectRepo
fileRepo *repository.FileRepo
settingRepo *repository.SettingRepo
opLogRepo *repository.OpLogRepo
webhookSvc *WebhookService
}
// Create 创建项目
func (s *ProjectService) Create(userID uint, name, description string, storageLimit int64) (*model.Project, error) {
if name == "" || len(name) > 100 {
return nil, fmt.Errorf("项目名称不能为空且不超过100字符")
}
if _, err := s.projectRepo.FindByName(userID, name); err == nil {
return nil, apperr.ErrProjectExists
}
if storageLimit <= 0 {
storageLimit = 5368709120 // 5GB
if v, err := s.settingRepo.GetValue("default_project_limit"); err == nil {
var n int64
if _, e := fmt.Sscanf(v, "%d", &n); e == nil && n > 0 {
storageLimit = n
}
}
}
p := &model.Project{
UserID: userID, Name: name, Description: description,
StorageLimit: storageLimit, Status: 1,
}
if err := s.projectRepo.Create(p); err != nil {
return nil, err
}
return p, nil
}
// List 项目列表,all=true时管理员查看全部
func (s *ProjectService) List(userID uint, keyword string, all bool, page, pageSize int) ([]model.Project, int64, error) {
return s.projectRepo.List(userID, keyword, all, page, pageSize)
}
// Get 项目详情(所有者或管理员)
func (s *ProjectService) Get(userID uint, id uint, isAdmin bool) (*model.Project, error) {
p, err := s.projectRepo.FindByID(id)
if err != nil {
return nil, apperr.ErrNotFound
}
if !isAdmin && p.UserID != userID {
return nil, apperr.ErrForbidden
}
return p, nil
}
// Update 更新项目
func (s *ProjectService) Update(userID uint, id uint, isAdmin bool, name, description string, storageLimit int64) (*model.Project, error) {
p, err := s.Get(userID, id, isAdmin)
if err != nil {
return nil, err
}
if name != "" && name != p.Name {
if _, err := s.projectRepo.FindByName(userID, name); err == nil {
return nil, apperr.ErrProjectExists
}
p.Name = name
}
if description != "" {
p.Description = description
}
if storageLimit > 0 {
p.StorageLimit = storageLimit
}
if err := s.projectRepo.Update(p); err != nil {
return nil, err
}
return p, nil
}
// Delete 删除项目及其全部文件(硬删除)
func (s *ProjectService) Delete(userID uint, id uint, isAdmin bool) error {
if _, err := s.Get(userID, id, isAdmin); err != nil {
return err
}
// 删除物理文件
files, _ := s.fileRepo.ListByProject(id)
seen := make(map[string]bool)
for _, f := range files {
if f.StoredPath != "" && !seen[f.StoredPath] {
seen[f.StoredPath] = true
_ = os.Remove(filepath.Join(s.cfg.Storage.Root, f.StoredPath))
}
}
_ = s.fileRepo.DB.Exec("DELETE FROM files WHERE project_id = ?", id).Error
_ = s.fileRepo.DB.Exec("DELETE FROM temp_links WHERE file_id IN (SELECT id FROM files WHERE project_id = ?)", id).Error
return s.projectRepo.Delete(id)
}