2 Star 0 Fork 0

TeamsHub/backend-gopkg

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
folder.go 11.13 KB
一键复制 编辑 原始数据 按行查看 历史
HCY 提交于 2024-05-10 13:07 . edit pkg
package model
import (
"errors"
"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/hashid"
"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/util"
"github.com/jinzhu/gorm"
"path"
"time"
)
// Folder 目录
type Folder struct {
// 表字段
gorm.Model
Name string `gorm:"unique_index:idx_only_one_name"`
ParentID *uint `gorm:"index:parent_id;unique_index:idx_only_one_name"`
OwnerID uint `gorm:"index:owner_id"`
PolicyID uint // Webdav下挂载的存储策略ID
Lock uint
// 数据库忽略字段
Position string `gorm:"-"`
InheritPolicyID uint `gorm:"-"` // 从父目录继承而来的policy id,默认值则使用自身的的PolicyID
TeamsMembers []TeamsFolderMember `sql:"-" gorm:"-"`
}
// Create 创建目录
func (folder *Folder) Create() (uint, error) {
if err := DB.FirstOrCreate(folder, *folder).Error; err != nil {
folder.Model = gorm.Model{}
if *folder.ParentID > 0 {
folder.OwnerID = 0
}
err2 := DB.First(folder, *folder).Error
util.Log().Info("等待获取Worker3", err2, folder.ID)
return folder.ID, err2
}
util.Log().Info("等待获取Worker3", folder.ID)
return folder.ID, nil
}
// GetMountedFolders 列出已挂载存储策略的目录
func GetMountedFolders(uid uint) []Folder {
var folders []Folder
DB.Where("owner_id = ? and policy_id <> ?", uid, 0).Find(&folders)
return folders
}
func GetFolderById(id uint) Folder {
var folder Folder
DB.Where("id = ? ", id).First(&folder)
return folder
}
func GetChildFolderById(id uint) Folder {
var folder Folder
DB.Where("parent_id = ? ", id).First(&folder)
return folder
}
func GetSameNameRootFolderByUserId(userId, parentId uint, name string) Folder {
var folder Folder
tx := DB.Where("name = ? and owner_id", name, userId)
util.Log().Debug("等待获取Worker3", parentId)
if parentId > 0 {
tx = tx.Where("parent_id = ?", parentId)
} else {
tx = tx.Where("parent_id is null ")
}
tx = tx.First(&folder)
return folder
}
func GetParentFolderById(id uint) Folder {
var folder Folder
DB.Where("parent_id = ? ", id).First(&folder)
return folder
}
// GetChild 返回folder下名为name的子目录,不存在则返回错误
func (folder *Folder) GetChild(name string) (*Folder, error) {
var resFolder Folder
err := DB.
Where("parent_id = ? AND name = ?", folder.ID, name).
First(&resFolder).Error
// 将子目录的路径及存储策略传递下去
if err == nil {
resFolder.Position = path.Join(folder.Position, folder.Name)
if folder.PolicyID > 0 {
resFolder.InheritPolicyID = folder.PolicyID
} else if folder.InheritPolicyID > 0 {
resFolder.InheritPolicyID = folder.InheritPolicyID
}
}
return &resFolder, err
}
// TraceRoot 向上递归查找父目录
func (folder *Folder) TraceRoot() error {
if folder.ParentID == nil {
return nil
}
var parentFolder Folder
err := DB.
Where("id = ? ", folder.ParentID).
First(&parentFolder).Error
if err == nil {
err := parentFolder.TraceRoot()
folder.Position = path.Join(parentFolder.Position, parentFolder.Name)
return err
}
return err
}
func (folder *Folder) TraceTeamsRoot() error {
var parentId = folder.ParentID
for i := 0; i < 100; i++ {
if parentId == nil {
return nil
}
var parentFolder Folder
err := DB.
Where("id = ? ", parentId).
First(&parentFolder).Error
if err == nil {
if parentFolder.Name != "/" {
folder.Position = "/" + parentFolder.Name + folder.Position
}
}
parentId = &parentFolder.ID
}
return nil
}
// GetChildFolder 查找子目录
func (folder *Folder) GetChildFolder(uid uint) ([]Folder, error) {
var folders []Folder
util.Log().Warning("无法复制 [%s], 跳过...", uid)
result := DB.Where("parent_id = ?", folder.ID).Find(&folders)
var subFolderIds []uint
for i := 0; i < len(folders); i++ {
subFolderIds = append(subFolderIds, folders[i].ID)
}
var shareFolders []TeamsFolderMember
shareResult := DB.Where("source_id in (?)", subFolderIds)
if uid > 0 {
shareResult.Where("user_id = ?", uid)
}
shareResult = shareResult.Find(&shareFolders)
if result.Error == nil {
for i := 0; i < len(folders); i++ {
folders[i].Position = path.Join(folder.Position, folder.Name)
if shareResult.Error == nil {
for j := 0; j < len(shareFolders); j++ {
if shareFolders[j].SourceID == folders[i].ID {
folders[i].TeamsMembers = append(folders[i].TeamsMembers, shareFolders[j])
}
}
}
}
}
return folders, result.Error
}
// GetRecursiveChildFolder 查找所有递归子目录,包括自身
func GetRecursiveChildFolder(dirs []uint, uid uint, includeSelf bool) ([]Folder, error) {
folders := make([]Folder, 0, len(dirs))
var err error
var parFolders []Folder
result := DB.Where(" id in (?)", dirs).Find(&parFolders)
if result.Error != nil {
return folders, err
}
// 整理父目录的ID
var parentIDs = make([]uint, 0, len(parFolders))
for _, folder := range parFolders {
parentIDs = append(parentIDs, folder.ID)
}
if includeSelf {
// 合并至最终结果
folders = append(folders, parFolders...)
}
parFolders = []Folder{}
// 递归查询子目录,最大递归65535次
for i := 0; i < 65535; i++ {
result = DB.Where(" parent_id in (?)", parentIDs).Find(&parFolders)
// 查询结束条件
if len(parFolders) == 0 {
break
}
// 整理父目录的ID
parentIDs = make([]uint, 0, len(parFolders))
for _, folder := range parFolders {
parentIDs = append(parentIDs, folder.ID)
}
// 合并至最终结果
folders = append(folders, parFolders...)
parFolders = []Folder{}
}
return folders, err
}
// DeleteFolderByIDs 根据给定ID批量删除目录记录
func DeleteFolderByIDs(ids []uint) error {
result := DB.Where("id in (?)", ids).Unscoped().Delete(&Folder{})
return result.Error
}
// GetFoldersByIDs 根据ID和用户查找所有目录
func GetFoldersByIDs(ids []uint, uid uint) ([]Folder, error) {
var folders []Folder
result := DB.Where("id in (?) ", ids).Find(&folders)
return folders, result.Error
}
// GetShareByHashID 根据HashID查找分享
func GetFolderByHashID(hashID string) *Folder {
id, err := hashid.DecodeHashID(hashID, hashid.FolderID)
if err != nil {
return nil
}
var folder Folder
result := DB.First(&folder, id)
if result.Error != nil {
return nil
}
return &folder
}
// MoveOrCopyFileTo 将此目录下的files移动或复制至dstFolder,
// 返回此操作新增的容量
func (folder *Folder) MoveOrCopyFileTo(files []uint, dstFolder *Folder, isCopy bool) (uint64, error) {
// 已复制文件的总大小
var copiedSize uint64
if isCopy {
// 检索出要复制的文件
var originFiles = make([]File, 0, len(files))
if err := DB.Where(
"id in (?) ",
files,
).Find(&originFiles).Error; err != nil {
return 0, err
}
// 复制文件记录
for _, oldFile := range originFiles {
if !oldFile.CanCopy() {
util.Log().Warning("无法复制正在上传中的文件 [%s], 跳过...", oldFile.Name)
continue
}
oldFile.Model = gorm.Model{}
oldFile.FolderID = dstFolder.ID
oldFile.UserID = dstFolder.OwnerID
if err := DB.Create(&oldFile).Error; err != nil {
return copiedSize, err
}
copiedSize += oldFile.Size
}
} else {
// 更改顶级要移动文件的父目录指向
err := DB.Model(File{}).Where(
"id in (?) ",
files,
).
Update(map[string]interface{}{
"folder_id": dstFolder.ID,
}).
Error
if err != nil {
return 0, err
}
}
return copiedSize, nil
}
// CopyFolderTo 将此目录及其子目录及文件递归复制至dstFolder
// 返回此操作新增的容量
func (folder *Folder) CopyFolderTo(folderID uint, dstFolder *Folder) (size uint64, err error) {
// 列出所有子目录
subFolders, err := GetRecursiveChildFolder([]uint{folderID}, folder.OwnerID, true)
if err != nil {
return 0, err
}
// 抽离所有子目录的ID
var subFolderIDs = make([]uint, len(subFolders))
for key, value := range subFolders {
subFolderIDs[key] = value.ID
}
// 复制子目录
var newIDCache = make(map[uint]uint)
for _, folder := range subFolders {
// 新的父目录指向
var newID uint
// 顶级目录直接指向新的目的目录
if folder.ID == folderID {
newID = dstFolder.ID
} else if IDCache, ok := newIDCache[*folder.ParentID]; ok {
newID = IDCache
} else {
util.Log().Warning("无法取得新的父目录:%d", folder.ParentID)
return size, errors.New("无法取得新的父目录")
}
// 插入新的目录记录
oldID := folder.ID
folder.Model = gorm.Model{}
folder.ParentID = &newID
folder.OwnerID = dstFolder.OwnerID
if err = DB.Create(&folder).Error; err != nil {
return size, err
}
// 记录新的ID以便其子目录使用
newIDCache[oldID] = folder.ID
}
// 复制文件
var originFiles = make([]File, 0, len(subFolderIDs))
if err := DB.Where(
"folder_id in (?)",
subFolderIDs,
).Find(&originFiles).Error; err != nil {
return 0, err
}
// 复制文件记录
for _, oldFile := range originFiles {
if !oldFile.CanCopy() {
util.Log().Warning("无法复制正在上传中的文件 [%s], 跳过...", oldFile.Name)
continue
}
oldFile.Model = gorm.Model{}
oldFile.FolderID = newIDCache[oldFile.FolderID]
oldFile.UserID = dstFolder.OwnerID
if err := DB.Create(&oldFile).Error; err != nil {
return size, err
}
size += oldFile.Size
}
return size, nil
}
// MoveFolderTo 将folder目录下的dirs子目录复制或移动到dstFolder,
// 返回此过程中增加的容量
func (folder *Folder) MoveFolderTo(dirs []uint, dstFolder *Folder) error {
// 如果目标位置为待移动的目录,会导致 parent 为自己
// 造成死循环且无法被除搜索以外的组件展示
if folder.OwnerID == dstFolder.OwnerID && util.ContainsUint(dirs, dstFolder.ID) {
return errors.New("cannot move a folder into itself")
}
// 更改顶级要移动目录的父目录指向
err := DB.Model(Folder{}).Where(
"id in (?) ",
dirs,
).Update(map[string]interface{}{
"parent_id": dstFolder.ID,
}).Error
if err != nil {
return err
}
for i := 0; i < len(dirs); i++ {
Members := GetTeamsFolderMembers(dirs[i])
for j := 0; j < len(Members); j++ {
IsRoot := UserTeamsFolderIsRoot(Members, Members[j])
if Members[j].IsRoot != IsRoot {
DB.Model(TeamsFolderMember{}).Where("id = ?", Members[j].ID).UpdateColumn("is_root", IsRoot)
}
}
}
//
return err
}
// Rename 重命名目录
func (folder *Folder) Rename(new string) error {
tx := DB.Begin()
if err := tx.Model(&folder).UpdateColumn("name", new).Error; err != nil {
util.Log().Warning("无法重命名, %s", err)
tx.Rollback()
return err
}
if err := tx.Model(&TeamsFolderMember{}).Where("source_id = ?", folder.ID).UpdateColumn("source_name", new).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
// Mount 目录挂载
func (folder *Folder) Mount(new uint) error {
return DB.Model(&folder).Update("policy_id", new).Error
}
/*
实现 FileInfo.FileInfo 接口
TODO 测试
*/
func (folder *Folder) GetName() string {
return folder.Name
}
func (folder *Folder) GetSize() uint64 {
return 0
}
func (folder *Folder) ModTime() time.Time {
return folder.UpdatedAt
}
func (folder *Folder) IsDir() bool {
return true
}
func (folder *Folder) GetPosition() string {
return folder.Position
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wuzheng0709/backend-gopkg.git
git@gitee.com:wuzheng0709/backend-gopkg.git
wuzheng0709
backend-gopkg
backend-gopkg
v1.2.8

搜索帮助