Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 文件管理编辑文件增加左侧目录树 #5594

Merged
merged 2 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions backend/app/dto/response/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ type UploadInfo struct {
}

type FileTree struct {
ID string `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Children []FileTree `json:"children"`
ID string `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
IsDir bool `json:"isDir"`
Extension string `json:"extension"`
Children []FileTree `json:"children"`
}

type DirSizeRes struct {
Expand Down
80 changes: 68 additions & 12 deletions backend/app/service/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"golang.org/x/net/html/charset"
"golang.org/x/sys/unix"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"

Expand Down Expand Up @@ -51,6 +52,10 @@ type IFileService interface {
ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error)
}

var filteredPaths = []string{
"/.1panel_clash",
}

func NewIFileService() IFileService {
return &FileService{}
}
Expand Down Expand Up @@ -100,27 +105,78 @@ func (f *FileService) SearchUploadWithPage(req request.SearchUploadWithPage) (in

func (f *FileService) GetFileTree(op request.FileOption) ([]response.FileTree, error) {
var treeArray []response.FileTree
if _, err := os.Stat(op.Path); err != nil && os.IsNotExist(err) {
return treeArray, nil
}
info, err := files.NewFileInfo(op.FileOption)
if err != nil {
return nil, err
}
node := response.FileTree{
ID: common.GetUuid(),
Name: info.Name,
Path: info.Path,
}
for _, v := range info.Items {
if v.IsDir {
node.Children = append(node.Children, response.FileTree{
ID: common.GetUuid(),
Name: v.Name,
Path: v.Path,
})
}
ID: common.GetUuid(),
Name: info.Name,
Path: info.Path,
IsDir: info.IsDir,
Extension: info.Extension,
}
err = f.buildFileTree(&node, info.Items, op, 2)
if err != nil {
return nil, err
}
return append(treeArray, node), nil
}

func shouldFilterPath(path string) bool {
cleanedPath := filepath.Clean(path)
for _, filteredPath := range filteredPaths {
cleanedFilteredPath := filepath.Clean(filteredPath)
if cleanedFilteredPath == cleanedPath || strings.HasPrefix(cleanedPath, cleanedFilteredPath+"/") {
return true
}
}
return false
}

// 递归构建文件树(只取当前目录以及当前目录下的第一层子节点)
func (f *FileService) buildFileTree(node *response.FileTree, items []*files.FileInfo, op request.FileOption, level int) error {
for _, v := range items {
if shouldFilterPath(v.Path) {
global.LOG.Info("File Tree: Skipping %s due to filter\n", v.Path)
continue
}
childNode := response.FileTree{
ID: common.GetUuid(),
Name: v.Name,
Path: v.Path,
IsDir: v.IsDir,
Extension: v.Extension,
}
if level > 1 && v.IsDir {
if err := f.buildChildNode(&childNode, v, op, level); err != nil {
return err
}
}

node.Children = append(node.Children, childNode)
}
return nil
}

func (f *FileService) buildChildNode(childNode *response.FileTree, fileInfo *files.FileInfo, op request.FileOption, level int) error {
op.Path = fileInfo.Path
subInfo, err := files.NewFileInfo(op.FileOption)
if err != nil {
if os.IsPermission(err) || errors.Is(err, unix.EACCES) {
global.LOG.Info("File Tree: Skipping %s due to permission denied\n", fileInfo.Path)
return nil
}
global.LOG.Errorf("File Tree: Skipping %s due to error: %s\n", fileInfo.Path, err.Error())
return nil
}

return f.buildFileTree(childNode, subInfo.Items, op, level-1)
}

func (f *FileService) Create(op request.FileCreate) error {
if files.IsInvalidChar(op.Path) {
return buserr.New("ErrInvalidChar")
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const message = {
user: 'User',
title: 'Title',
port: 'Port',
forward: 'Forward',
protocol: 'Protocol',
tableSetting: 'Table setting',
refreshRate: 'Rate',
Expand Down Expand Up @@ -139,6 +140,8 @@ const message = {
remove: 'Remove',
backupHelper: 'The current operation will back up {0}. Do you want to proceed?',
recoverHelper: 'Restoring from {0} file. This operation is irreversible. Do you want to continue?',
refreshSuccess: 'Refresh successful',
rootInfoErr: "It's already the root directory",
},
login: {
username: 'UserName',
Expand Down Expand Up @@ -1219,6 +1222,7 @@ const message = {
refresh: 'Refresh',
openWithVscode: 'Open with VS Code',
vscodeHelper: 'Please make sure that VS Code is installed locally and the SSH Remote plugin is configured',
up: 'Go back',
},
ssh: {
autoStart: 'Auto Start',
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/lang/modules/tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const message = {
user: '用戶',
title: '標題',
port: '端口',
forward: '轉發',
protocol: '協議',
tableSetting: '列表設置',
refreshRate: '刷新頻率',
Expand Down Expand Up @@ -139,6 +140,8 @@ const message = {
remove: '移出',
backupHelper: '當前操作將對 {0} 進行備份,是否繼續?',
recoverHelper: '將從 {0} 文件進行恢復,該操作不可回滾,是否繼續?',
refreshSuccess: '重繪成功',
rootInfoErr: '已經是根目錄了',
},
login: {
username: '用戶名',
Expand Down Expand Up @@ -1149,12 +1152,13 @@ const message = {
'下載時忽略不可信證書可能導致數據洩露或篡改。請謹慎使用此選項,僅在信任下載源的情況下啟用',
uploadOverLimit: '文件數量超過 1000! 請壓縮後上傳',
clashDitNotSupport: '檔名禁止包含 .1panel_clash',
clashDleteAlert: '回收站資料夾不能刪除',
clashDeleteAlert: '回收站資料夾不能刪除',
clashOpenAlert: '回收站目錄請點選【回收站】按鈕開啟',
right: '前進',
back: '後退',
top: '返回上一層',
refresh: '重新整理',
up: '上一層',
openWithVscode: 'VS Code 打開',
vscodeHelper: '請確保本地已安裝 VS Code 並配置了 SSH Remote 插件',
},
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ const message = {
remove: '移出',
backupHelper: '当前操作将对 {0} 进行备份,是否继续?',
recoverHelper: '将从 {0} 文件进行恢复,该操作不可回滚,是否继续?',
refreshSuccess: '刷新成功',
rootInfoErr: '已经是根目录了',
},
login: {
username: '用户名',
Expand Down Expand Up @@ -1151,12 +1153,13 @@ const message = {
'下载时忽略不可信证书可能导致数据泄露或篡改。请谨慎使用此选项,仅在信任下载源的情况下启用',
uploadOverLimit: '文件数量超过 1000!请压缩后上传',
clashDitNotSupport: '文件名禁止包含 .1panel_clash',
clashDleteAlert: '回收站文件夹不能删除',
clashDeleteAlert: '回收站文件夹不能删除',
clashOpenAlert: '回收站目录请点击【回收站】按钮打开',
right: '前进',
back: '后退',
top: '返回上一级',
refresh: '刷新',
up: '上一级',
openWithVscode: 'VS Code 打开',
vscodeHelper: '请确保本地已安装 VS Code 并配置了 SSH Remote 插件',
},
Expand Down
Loading
Loading