refactor: reorganize modules and add Linux build tooling

This commit is contained in:
2026-08-09 12:41:08 +08:00
parent 86024fa81d
commit 5cc5fd92ed
1461 changed files with 4054 additions and 4724 deletions

View File

@@ -0,0 +1,83 @@
package disk
import (
"context"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/bsm-sdk/engine/types"
)
// 复制文件
func CopyFile(ctx context.Context, in *pb.CopyFileRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request
if in.Id == 0 {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.NewName) == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var file models.CloudDiskFile
if err := impl.DBService.Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_files.id = ? AND cloud_disk_dirs.passport_id = ?", in.Id, auth.ID).
First(&file).Error; err != nil {
printer.Error("File not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查目标目录是否存在且属于当前用户
var targetDir models.CloudDiskDir
if err := impl.DBService.Where("id = ? AND passport_id = ?", in.TargetDirectoryId, auth.ID).First(&targetDir).Error; err != nil {
printer.Error("Target directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查目标目录下是否已存在同名文件
var existingFile models.CloudDiskFile
if err := impl.DBService.Where("name = ? AND directory_id = ?", in.NewName, in.TargetDirectoryId).First(&existingFile).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
// 创建文件副本
newFile := models.CloudDiskFile{
Std_IICUDS: types.Std_IICUDS{
Identity: utils.UUID(),
},
CloudBase: models.CloudBase{
CloudID: file.CloudID,
CloudIdentity: file.CloudIdentity,
},
DirectoryID: func() *uint { id := uint(in.TargetDirectoryId); return &id }(),
Name: in.NewName,
OriginalName: in.NewName,
Size: file.Size,
MimeType: file.MimeType,
StoragePath: file.StoragePath, // 注意:实际存储中可能需要复制文件内容
Hash: file.Hash,
}
if err := impl.DBService.Create(&newFile).Error; err != nil {
printer.Error("Copy file error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: newFile.Identity,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,85 @@
package disk
import (
"context"
"path/filepath"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/bsm-sdk/engine/types"
)
// 创建目录
func CreateDir(ctx context.Context, in *pb.CreateDirRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// valid code
if strings.TrimSpace(in.Name) == "" {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.CloudIdentity) == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
// 构建完整路径
var fullPath string
if in.ParentId > 0 {
var parentDir models.CloudDiskDir
if err := impl.DBService.Where("id = ? AND passport_id = ?", in.ParentId, auth.ID).First(&parentDir).Error; err != nil {
printer.Error("Parent directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
fullPath = filepath.Join(parentDir.Path, in.Name)
} else {
fullPath = "/" + in.Name
}
// 检查目录是否已存在
var existingDir models.CloudDiskDir
if err := impl.DBService.Where("path = ? AND passport_id = ?", fullPath, auth.ID).First(&existingDir).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
record := models.CloudDiskDir{
Std_IICUDS: types.Std_IICUDS{
Identity: utils.UUID(),
},
Std_Passport: types.Std_Passport{
PassportID: auth.ID,
PassportIdentity: auth.Identity,
},
CloudBase: models.CloudBase{
CloudID: uint(in.CloudId),
CloudIdentity: in.CloudIdentity,
},
Name: in.Name,
Path: fullPath,
}
if in.ParentId > 0 {
parentId := uint(in.ParentId)
record.ParentID = &parentId
}
if err := impl.DBService.Create(&record).Error; err != nil {
printer.Error("Create directory error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: record.Identity,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,74 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
)
// 删除目录
func DeleteDir(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var dir models.CloudDiskDir
query := impl.DBService.Where("passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("id = ?", in.Id)
} else {
query = query.Where("identity = ?", in.Identity)
}
if err := query.First(&dir).Error; err != nil {
printer.Error("Directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查是否有子目录
var subdirCount int64
if err := impl.DBService.Model(&models.CloudDiskDir{}).Where("parent_id = ?", dir.ID).Count(&subdirCount).Error; err != nil {
printer.Error("Check subdirectories error: %v", err)
return nil, errcode.ErrDB
}
if subdirCount > 0 {
return nil, errcode.ErrInvalidArgument
}
// 检查是否有文件
var fileCount int64
if err := impl.DBService.Model(&models.CloudDiskFile{}).Where("directory_id = ?", dir.ID).Count(&fileCount).Error; err != nil {
printer.Error("Check files error: %v", err)
return nil, errcode.ErrDB
}
if fileCount > 0 {
return nil, errcode.ErrInvalidArgument
}
// 删除目录
if err := impl.DBService.Delete(&dir).Error; err != nil {
printer.Error("Delete directory error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,55 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
)
// 删除文件
func DeleteFile(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var file models.CloudDiskFile
query := impl.DBService.Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_dirs.passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("cloud_disk_files.id = ?", in.Id)
} else {
query = query.Where("cloud_disk_files.identity = ?", in.Identity)
}
if err := query.First(&file).Error; err != nil {
printer.Error("File not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 删除文件
if err := impl.DBService.Delete(&file).Error; err != nil {
printer.Error("Delete file error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,102 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 获取目录详情
func GetDir(ctx context.Context, in *pb.IdentRequest) (reply *pb.CloudDiskDirItem, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var dir models.CloudDiskDir
query := impl.DBService.Where("passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("id = ?", in.Id)
} else {
query = query.Where("identity = ?", in.Identity)
}
if err := query.Preload("Parent").Preload("Subdirectories").Preload("Files").First(&dir).Error; err != nil {
printer.Error("Directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 转换子目录数据
var subdirs []*pb.CloudDiskDirItem
for _, subdir := range dir.Subdirectories {
subdirs = append(subdirs, &pb.CloudDiskDirItem{
Id: uint64(subdir.ID),
Identity: subdir.Identity,
ParentId: uint64(*subdir.ParentID),
Name: subdir.Name,
Path: subdir.Path,
CreatedAt: subdir.CreatedAt.Format(time.RFC3339),
UpdatedAt: subdir.UpdatedAt.Format(time.RFC3339),
})
}
// 转换文件数据
var files []*pb.CloudDiskFileItem
for _, file := range dir.Files {
files = append(files, &pb.CloudDiskFileItem{
Id: uint64(file.ID),
Identity: file.Identity,
DirectoryId: uint64(*file.DirectoryID),
Name: file.Name,
OriginalName: file.OriginalName,
Size: file.Size,
MimeType: file.MimeType,
StoragePath: file.StoragePath,
Hash: file.Hash,
CreatedAt: file.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.UpdatedAt.Format(time.RFC3339),
})
}
// 构建父目录信息
var parent *pb.CloudDiskDirItem
if dir.Parent != nil {
parent = &pb.CloudDiskDirItem{
Id: uint64(dir.Parent.ID),
Identity: dir.Parent.Identity,
Name: dir.Parent.Name,
Path: dir.Parent.Path,
CreatedAt: dir.Parent.CreatedAt.Format(time.RFC3339),
UpdatedAt: dir.Parent.UpdatedAt.Format(time.RFC3339),
}
}
reply = &pb.CloudDiskDirItem{
Id: uint64(dir.ID),
Identity: dir.Identity,
ParentId: uint64(*dir.ParentID),
Name: dir.Name,
Path: dir.Path,
CreatedAt: dir.CreatedAt.Format(time.RFC3339),
UpdatedAt: dir.UpdatedAt.Format(time.RFC3339),
Parent: parent,
Subdirectories: subdirs,
Files: files,
}
return reply, nil
}

View File

@@ -0,0 +1,108 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 获取目录树
func GetDirTree(ctx context.Context, in *pb.IdentRequest) (reply *pb.CloudDiskDirItem, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var dir models.CloudDiskDir
query := impl.DBService.Where("passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("id = ?", in.Id)
} else {
query = query.Where("identity = ?", in.Identity)
}
if err := query.Preload("Parent").Preload("Subdirectories").Preload("Files").First(&dir).Error; err != nil {
printer.Error("Directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 递归加载子目录树
var loadSubdirs func(*models.CloudDiskDir) []*pb.CloudDiskDirItem
loadSubdirs = func(d *models.CloudDiskDir) []*pb.CloudDiskDirItem {
var subdirs []*pb.CloudDiskDirItem
for _, subdir := range d.Subdirectories {
subdirItem := &pb.CloudDiskDirItem{
Id: uint64(subdir.ID),
Identity: subdir.Identity,
ParentId: uint64(*subdir.ParentID),
Name: subdir.Name,
Path: subdir.Path,
CreatedAt: subdir.CreatedAt.Format(time.RFC3339),
UpdatedAt: subdir.UpdatedAt.Format(time.RFC3339),
Subdirectories: loadSubdirs(&subdir),
}
subdirs = append(subdirs, subdirItem)
}
return subdirs
}
// 转换文件数据
var files []*pb.CloudDiskFileItem
for _, file := range dir.Files {
files = append(files, &pb.CloudDiskFileItem{
Id: uint64(file.ID),
Identity: file.Identity,
DirectoryId: uint64(*file.DirectoryID),
Name: file.Name,
OriginalName: file.OriginalName,
Size: file.Size,
MimeType: file.MimeType,
StoragePath: file.StoragePath,
Hash: file.Hash,
CreatedAt: file.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.UpdatedAt.Format(time.RFC3339),
})
}
// 构建父目录信息
var parent *pb.CloudDiskDirItem
if dir.Parent != nil {
parent = &pb.CloudDiskDirItem{
Id: uint64(dir.Parent.ID),
Identity: dir.Parent.Identity,
Name: dir.Parent.Name,
Path: dir.Parent.Path,
CreatedAt: dir.Parent.CreatedAt.Format(time.RFC3339),
UpdatedAt: dir.Parent.UpdatedAt.Format(time.RFC3339),
}
}
reply = &pb.CloudDiskDirItem{
Id: uint64(dir.ID),
Identity: dir.Identity,
ParentId: uint64(*dir.ParentID),
Name: dir.Name,
Path: dir.Path,
CreatedAt: dir.CreatedAt.Format(time.RFC3339),
UpdatedAt: dir.UpdatedAt.Format(time.RFC3339),
Parent: parent,
Subdirectories: loadSubdirs(&dir),
Files: files,
}
return reply, nil
}

View File

@@ -0,0 +1,73 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 获取文件详情
func GetFile(ctx context.Context, in *pb.IdentRequest) (reply *pb.CloudDiskFileItem, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var file models.CloudDiskFile
query := impl.DBService.Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_dirs.passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("cloud_disk_files.id = ?", in.Id)
} else {
query = query.Where("cloud_disk_files.identity = ?", in.Identity)
}
if err := query.Preload("Directory").First(&file).Error; err != nil {
printer.Error("File not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 构建目录信息
var directory *pb.CloudDiskDirItem
if file.Directory != nil {
directory = &pb.CloudDiskDirItem{
Id: uint64(file.Directory.ID),
Identity: file.Directory.Identity,
Name: file.Directory.Name,
Path: file.Directory.Path,
CreatedAt: file.Directory.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.Directory.UpdatedAt.Format(time.RFC3339),
}
}
reply = &pb.CloudDiskFileItem{
Id: uint64(file.ID),
Identity: file.Identity,
DirectoryId: uint64(*file.DirectoryID),
Name: file.Name,
OriginalName: file.OriginalName,
Size: file.Size,
MimeType: file.MimeType,
StoragePath: file.StoragePath,
Hash: file.Hash,
CreatedAt: file.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.UpdatedAt.Format(time.RFC3339),
Directory: directory,
}
return reply, nil
}

View File

@@ -0,0 +1,87 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/service"
)
// 获取目录列表
func ListDirs(ctx context.Context, in *pb.FetchRequest) (reply *pb.ListDirsResponse, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request page_no,page_size.
if in.GetPageNo() < 1 {
in.PageNo = 1
}
if in.GetPageSize() < 10 {
in.PageSize = 50
}
// logic code
var dirs []models.CloudDiskDir
var total int64
// 获取总数
if err := impl.DBService.Model(&models.CloudDiskDir{}).Where("passport_id = ?", auth.ID).Count(&total).Error; err != nil {
return nil, err
}
// 分页查询
offset := (in.PageNo - 1) * in.PageSize
if err := impl.DBService.Where("passport_id = ?", auth.ID).
Preload("Parent").
Order("created_at DESC").
Offset(int(offset)).
Limit(int(in.PageSize)).
Find(&dirs).Error; err != nil {
return nil, err
}
// 转换数据
var dirItems []*pb.CloudDiskDirItem
for _, dir := range dirs {
var parentId uint64
if dir.ParentID != nil {
parentId = uint64(*dir.ParentID)
}
var parent *pb.CloudDiskDirItem
if dir.Parent != nil {
parent = &pb.CloudDiskDirItem{
Id: uint64(dir.Parent.ID),
Identity: dir.Parent.Identity,
Name: dir.Parent.Name,
Path: dir.Parent.Path,
CreatedAt: dir.Parent.CreatedAt.Format(time.RFC3339),
UpdatedAt: dir.Parent.UpdatedAt.Format(time.RFC3339),
}
}
dirItems = append(dirItems, &pb.CloudDiskDirItem{
Id: uint64(dir.ID),
Identity: dir.Identity,
ParentId: parentId,
Name: dir.Name,
Path: dir.Path,
CreatedAt: dir.CreatedAt.Format(time.RFC3339),
UpdatedAt: dir.UpdatedAt.Format(time.RFC3339),
Parent: parent,
})
}
reply = &pb.ListDirsResponse{
Dirs: dirItems,
Total: total,
}
return reply, nil
}

View File

@@ -0,0 +1,91 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/service"
)
// 获取文件列表
func ListFiles(ctx context.Context, in *pb.FetchRequest) (reply *pb.ListFilesResponse, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request page_no,page_size.
if in.GetPageNo() < 1 {
in.PageNo = 1
}
if in.GetPageSize() < 10 {
in.PageSize = 50
}
// logic code
var files []models.CloudDiskFile
var total int64
// 获取总数
if err := impl.DBService.Model(&models.CloudDiskFile{}).
Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_dirs.passport_id = ?", auth.ID).
Count(&total).Error; err != nil {
return nil, err
}
// 分页查询
offset := (in.PageNo - 1) * in.PageSize
if err := impl.DBService.
Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_dirs.passport_id = ?", auth.ID).
Preload("Directory").
Order("cloud_disk_files.created_at DESC").
Offset(int(offset)).
Limit(int(in.PageSize)).
Find(&files).Error; err != nil {
return nil, err
}
// 转换数据
var fileItems []*pb.CloudDiskFileItem
for _, file := range files {
var directory *pb.CloudDiskDirItem
if file.Directory != nil {
directory = &pb.CloudDiskDirItem{
Id: uint64(file.Directory.ID),
Identity: file.Directory.Identity,
Name: file.Directory.Name,
Path: file.Directory.Path,
CreatedAt: file.Directory.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.Directory.UpdatedAt.Format(time.RFC3339),
}
}
fileItems = append(fileItems, &pb.CloudDiskFileItem{
Id: uint64(file.ID),
Identity: file.Identity,
DirectoryId: uint64(*file.DirectoryID),
Name: file.Name,
OriginalName: file.OriginalName,
Size: file.Size,
MimeType: file.MimeType,
StoragePath: file.StoragePath,
Hash: file.Hash,
CreatedAt: file.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.UpdatedAt.Format(time.RFC3339),
Directory: directory,
})
}
reply = &pb.ListFilesResponse{
Files: fileItems,
Total: total,
}
return reply, nil
}

View File

@@ -0,0 +1,108 @@
package disk
import (
"context"
"path/filepath"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
)
// 移动目录
func MoveDir(ctx context.Context, in *pb.MoveDirRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request
if in.Id == 0 {
return nil, errcode.ErrInvalidArgument
}
// logic code
var dir models.CloudDiskDir
if err := impl.DBService.Where("id = ? AND passport_id = ?", in.Id, auth.ID).First(&dir).Error; err != nil {
printer.Error("Directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查目标父目录是否存在
if in.NewParentId > 0 {
var parentDir models.CloudDiskDir
if err := impl.DBService.Where("id = ? AND passport_id = ?", in.NewParentId, auth.ID).First(&parentDir).Error; err != nil {
printer.Error("Parent directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查是否会形成循环引用
if dir.ID == parentDir.ID {
return nil, errcode.ErrInvalidArgument
}
// 检查目标路径是否已存在
newPath := filepath.Join(parentDir.Path, dir.Name)
var existingDir models.CloudDiskDir
if err := impl.DBService.Where("path = ? AND passport_id = ? AND id != ?", newPath, auth.ID, dir.ID).First(&existingDir).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
// 更新目录
oldPath := dir.Path
newParentId := uint(in.NewParentId)
dir.ParentID = &newParentId
dir.Path = newPath
if err := impl.DBService.Save(&dir).Error; err != nil {
printer.Error("Move directory error: %v", err)
return nil, errcode.ErrDB
}
// 更新所有子目录的路径
var subdirs []models.CloudDiskDir
if err := impl.DBService.Where("path LIKE ? AND passport_id = ?", oldPath+"%", auth.ID).Find(&subdirs).Error; err == nil {
for _, subdir := range subdirs {
newSubPath := strings.Replace(subdir.Path, oldPath, newPath, 1)
impl.DBService.Model(&subdir).Update("path", newSubPath)
}
}
} else {
// 移动到根目录
oldPath := dir.Path
dir.ParentID = nil
dir.Path = "/" + dir.Name
// 检查根目录下是否已存在同名目录
var existingDir models.CloudDiskDir
if err := impl.DBService.Where("path = ? AND passport_id = ? AND id != ?", dir.Path, auth.ID, dir.ID).First(&existingDir).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
if err := impl.DBService.Save(&dir).Error; err != nil {
printer.Error("Move directory error: %v", err)
return nil, errcode.ErrDB
}
// 更新所有子目录的路径
var subdirs []models.CloudDiskDir
if err := impl.DBService.Where("path LIKE ? AND passport_id = ?", oldPath+"%", auth.ID).Find(&subdirs).Error; err == nil {
for _, subdir := range subdirs {
newSubPath := strings.Replace(subdir.Path, oldPath, dir.Path, 1)
impl.DBService.Model(&subdir).Update("path", newSubPath)
}
}
}
return &pb.StatusReply{
Details: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,64 @@
package disk
import (
"context"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
)
// 移动文件
func MoveFile(ctx context.Context, in *pb.MoveFileRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request
if in.Id == 0 {
return nil, errcode.ErrInvalidArgument
}
// logic code
var file models.CloudDiskFile
if err := impl.DBService.Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_files.id = ? AND cloud_disk_dirs.passport_id = ?", in.Id, auth.ID).
First(&file).Error; err != nil {
printer.Error("File not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查目标目录是否存在且属于当前用户
var targetDir models.CloudDiskDir
if err := impl.DBService.Where("id = ? AND passport_id = ?", in.NewDirectoryId, auth.ID).First(&targetDir).Error; err != nil {
printer.Error("Target directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查目标目录下是否已存在同名文件
var existingFile models.CloudDiskFile
if err := impl.DBService.Where("name = ? AND directory_id = ? AND id != ?", file.Name, in.NewDirectoryId, file.ID).First(&existingFile).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
// 更新文件目录
newDirectoryId := uint(in.NewDirectoryId)
file.DirectoryID = &newDirectoryId
if err := impl.DBService.Save(&file).Error; err != nil {
printer.Error("Move file error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,98 @@
package disk
import (
"context"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/service"
)
// 搜索文件
func SearchFiles(ctx context.Context, in *pb.FetchRequest) (reply *pb.ListFilesResponse, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request page_no,page_size.
if in.GetPageNo() < 1 {
in.PageNo = 1
}
if in.GetPageSize() < 10 {
in.PageSize = 50
}
// logic code
var files []models.CloudDiskFile
var total int64
// 构建搜索查询
query := impl.DBService.Model(&models.CloudDiskFile{}).
Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_dirs.passport_id = ?", auth.ID)
// 添加搜索条件
if keyword, exists := in.Params["keyword"]; exists && keyword != "" {
searchKeyword := "%" + strings.ToLower(keyword) + "%"
query = query.Where("LOWER(cloud_disk_files.name) LIKE ? OR LOWER(cloud_disk_files.original_name) LIKE ?", searchKeyword, searchKeyword)
}
// 获取总数
if err := query.Count(&total).Error; err != nil {
return nil, err
}
// 分页查询
offset := (in.PageNo - 1) * in.PageSize
if err := query.
Preload("Directory").
Order("cloud_disk_files.created_at DESC").
Offset(int(offset)).
Limit(int(in.PageSize)).
Find(&files).Error; err != nil {
return nil, err
}
// 转换数据
var fileItems []*pb.CloudDiskFileItem
for _, file := range files {
var directory *pb.CloudDiskDirItem
if file.Directory != nil {
directory = &pb.CloudDiskDirItem{
Id: uint64(file.Directory.ID),
Identity: file.Directory.Identity,
Name: file.Directory.Name,
Path: file.Directory.Path,
CreatedAt: file.Directory.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.Directory.UpdatedAt.Format(time.RFC3339),
}
}
fileItems = append(fileItems, &pb.CloudDiskFileItem{
Id: uint64(file.ID),
Identity: file.Identity,
DirectoryId: uint64(*file.DirectoryID),
Name: file.Name,
OriginalName: file.OriginalName,
Size: file.Size,
MimeType: file.MimeType,
StoragePath: file.StoragePath,
Hash: file.Hash,
CreatedAt: file.CreatedAt.Format(time.RFC3339),
UpdatedAt: file.UpdatedAt.Format(time.RFC3339),
Directory: directory,
})
}
reply = &pb.ListFilesResponse{
Files: fileItems,
Total: total,
}
return reply, nil
}

View File

@@ -0,0 +1,89 @@
package disk
import (
"context"
"path/filepath"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
)
// 更新目录
func UpdateDir(ctx context.Context, in *pb.CloudDiskDirItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.Name) == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var dir models.CloudDiskDir
query := impl.DBService.Where("passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("id = ?", in.Id)
} else {
query = query.Where("identity = ?", in.Identity)
}
if err := query.First(&dir).Error; err != nil {
printer.Error("Directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 更新目录名称和路径
oldPath := dir.Path
dir.Name = in.Name
// 重新构建路径
if dir.ParentID != nil {
var parentDir models.CloudDiskDir
if err := impl.DBService.Where("id = ?", *dir.ParentID).First(&parentDir).Error; err == nil {
dir.Path = filepath.Join(parentDir.Path, in.Name)
}
} else {
dir.Path = "/" + in.Name
}
// 检查新路径是否已存在
var existingDir models.CloudDiskDir
if err := impl.DBService.Where("path = ? AND passport_id = ? AND id != ?", dir.Path, auth.ID, dir.ID).First(&existingDir).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
if err := impl.DBService.Save(&dir).Error; err != nil {
printer.Error("Update directory error: %v", err)
return nil, errcode.ErrDB
}
// 更新所有子目录的路径
if oldPath != dir.Path {
var subdirs []models.CloudDiskDir
if err := impl.DBService.Where("path LIKE ? AND passport_id = ?", oldPath+"%", auth.ID).Find(&subdirs).Error; err == nil {
for _, subdir := range subdirs {
newSubPath := strings.Replace(subdir.Path, oldPath, dir.Path, 1)
impl.DBService.Model(&subdir).Update("path", newSubPath)
}
}
}
return &pb.StatusReply{
Details: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,73 @@
package disk
import (
"context"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
)
// 更新文件
func UpdateFile(ctx context.Context, in *pb.CloudDiskFileItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.Name) == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
var file models.CloudDiskFile
query := impl.DBService.Joins("JOIN cloud_disk_dirs ON cloud_disk_files.directory_id = cloud_disk_dirs.id").
Where("cloud_disk_dirs.passport_id = ?", auth.ID)
if in.Id > 0 {
query = query.Where("cloud_disk_files.id = ?", in.Id)
} else {
query = query.Where("cloud_disk_files.identity = ?", in.Identity)
}
if err := query.First(&file).Error; err != nil {
printer.Error("File not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查新文件名是否已存在(在同一目录下)
if file.Name != in.Name {
var existingFile models.CloudDiskFile
if err := impl.DBService.Where("name = ? AND directory_id = ? AND id != ?", in.Name, file.DirectoryID, file.ID).First(&existingFile).Error; err == nil {
return nil, errcode.ErrAlreadyExists
}
}
// 更新字段
file.Name = in.Name
file.OriginalName = in.OriginalName
file.MimeType = in.MimeType
file.StoragePath = in.StoragePath
file.Hash = in.Hash
if err := impl.DBService.Save(&file).Error; err != nil {
printer.Error("Update file error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,87 @@
package disk
import (
"context"
"strings"
"time"
"bsm/full/module/base/cloud/internal/impl"
"bsm/full/module/base/cloud/internal/models"
pb "bsm/full/module/base/cloud/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/bsm-sdk/engine/types"
)
// 上传文件
func UploadFile(ctx context.Context, in *pb.CloudDiskFileRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// validate request
if in.DirectoryId == 0 {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.Name) == "" {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.StoragePath) == "" {
return nil, errcode.ErrInvalidArgument
}
if strings.TrimSpace(in.CloudIdentity) == "" {
return nil, errcode.ErrInvalidArgument
}
// logic code
// 验证目录是否存在且属于当前用户
var directory models.CloudDiskDir
if err := impl.DBService.Where("id = ? AND passport_id = ?", in.DirectoryId, auth.ID).First(&directory).Error; err != nil {
printer.Error("Directory not found: %v", err)
return nil, errcode.ErrInvalidArgument
}
// 检查文件是否已存在(基于文件名和目录)
var existingFile models.CloudDiskFile
if err := impl.DBService.Where("name = ? AND directory_id = ?", in.Name, in.DirectoryId).First(&existingFile).Error; err == nil {
// 文件已存在,可以选择覆盖或返回错误
return nil, errcode.ErrAlreadyExists
}
// 生成文件哈希(如果未提供)
fileHash := in.Hash
if fileHash == "" {
fileHash = utils.UUID() // 使用UUID作为默认哈希
}
record := models.CloudDiskFile{
Std_IICUDS: types.Std_IICUDS{
Identity: utils.UUID(),
},
CloudBase: models.CloudBase{
CloudID: uint(in.CloudId),
CloudIdentity: in.CloudIdentity,
},
DirectoryID: func() *uint { id := uint(in.DirectoryId); return &id }(),
Name: in.Name,
OriginalName: in.OriginalName,
Size: in.Size,
MimeType: in.MimeType,
StoragePath: in.StoragePath,
Hash: fileHash,
}
if err := impl.DBService.Create(&record).Error; err != nil {
printer.Error("Upload file error: %v", err)
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Details: record.Identity,
Timeseq: time.Now().UnixMilli(),
}, nil
}