mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-01 11:04:29 +08:00
feat: 增加文件搜索功能
This commit is contained in:
parent
05f2c4661c
commit
292dbf58c5
5 changed files with 108 additions and 21 deletions
|
@ -4,9 +4,11 @@ import (
|
|||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
|
@ -39,6 +41,7 @@ type FileInfo struct {
|
|||
type FileOption struct {
|
||||
Path string `json:"path"`
|
||||
Search string `json:"search"`
|
||||
ContainSub bool `json:"containSub"`
|
||||
Expand bool `json:"expand"`
|
||||
Dir bool `json:"dir"`
|
||||
ShowHidden bool `json:"showHidden"`
|
||||
|
@ -46,6 +49,11 @@ type FileOption struct {
|
|||
PageSize int `json:"pageSize"`
|
||||
}
|
||||
|
||||
type FileSearchInfo struct {
|
||||
Path string `json:"path"`
|
||||
fs.FileInfo
|
||||
}
|
||||
|
||||
func NewFileInfo(op FileOption) (*FileInfo, error) {
|
||||
var appFs = afero.NewOsFs()
|
||||
|
||||
|
@ -75,7 +83,7 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
|
|||
}
|
||||
if op.Expand {
|
||||
if file.IsDir {
|
||||
if err := file.listChildren(op.Dir, op.ShowHidden, op.Page, op.PageSize); err != nil {
|
||||
if err := file.listChildren(op.Dir, op.ShowHidden, op.ContainSub, op.Search, op.Page, op.PageSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return file, nil
|
||||
|
@ -88,12 +96,59 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
|
|||
return file, nil
|
||||
}
|
||||
|
||||
func (f *FileInfo) listChildren(dir, showHidden bool, page, pageSize int) error {
|
||||
afs := &afero.Afero{Fs: f.Fs}
|
||||
files, err := afs.ReadDir(f.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
func (f *FileInfo) search(dir, showHidden bool, af afero.Afero, search string, count int) ([]FileSearchInfo, error) {
|
||||
var files []FileSearchInfo
|
||||
if err := afero.Walk(af, f.Path, func(path string, info fs.FileInfo, err error) error {
|
||||
if info != nil {
|
||||
|
||||
if dir && !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if !showHidden && IsHidden(info.Name()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
lowerName := strings.ToLower(info.Name())
|
||||
lowerSearch := strings.ToLower(search)
|
||||
if strings.Contains(lowerName, lowerSearch) {
|
||||
files = append(files, FileSearchInfo{
|
||||
Path: path,
|
||||
FileInfo: info,
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string, page, pageSize int) error {
|
||||
afs := &afero.Afero{Fs: f.Fs}
|
||||
var (
|
||||
files []FileSearchInfo
|
||||
err error
|
||||
)
|
||||
|
||||
if search != "" && containSub {
|
||||
files, err = f.search(dir, showHidden, *afs, search, page*pageSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
dirFiles, err := afs.ReadDir(f.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range dirFiles {
|
||||
files = append(files, FileSearchInfo{
|
||||
Path: f.Path,
|
||||
FileInfo: file,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
f.ItemTotal = 0
|
||||
|
||||
var items []*FileInfo
|
||||
|
@ -103,7 +158,20 @@ func (f *FileInfo) listChildren(dir, showHidden bool, page, pageSize int) error
|
|||
}
|
||||
|
||||
name := df.Name()
|
||||
fPath := path.Join(f.Path, df.Name())
|
||||
fPath := path.Join(df.Path, df.Name())
|
||||
|
||||
if search != "" {
|
||||
if containSub {
|
||||
fPath = df.Path
|
||||
name = strings.TrimPrefix(strings.TrimPrefix(fPath, f.Path), "/")
|
||||
} else {
|
||||
lowerName := strings.ToLower(name)
|
||||
lowerSearch := strings.ToLower(search)
|
||||
if !strings.Contains(lowerName, lowerSearch) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !showHidden && IsHidden(name) {
|
||||
continue
|
||||
|
@ -115,7 +183,7 @@ func (f *FileInfo) listChildren(dir, showHidden bool, page, pageSize int) error
|
|||
isSymlink = true
|
||||
info, err := f.Fs.Stat(fPath)
|
||||
if err == nil {
|
||||
df = info
|
||||
df.FileInfo = info
|
||||
} else {
|
||||
isInvalidLink = true
|
||||
}
|
||||
|
@ -137,6 +205,7 @@ func (f *FileInfo) listChildren(dir, showHidden bool, page, pageSize int) error
|
|||
Group: GetGroup(df.Sys().(*syscall.Stat_t).Gid),
|
||||
MimeType: GetMimeType(fPath),
|
||||
}
|
||||
|
||||
if isSymlink {
|
||||
file.LinkPath = GetSymlink(fPath)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ export namespace File {
|
|||
expand: boolean;
|
||||
dir?: boolean;
|
||||
showHidden?: boolean;
|
||||
containSub?: boolean;
|
||||
}
|
||||
|
||||
export interface FileTree {
|
||||
|
|
|
@ -652,7 +652,7 @@ export default {
|
|||
upload: '上传',
|
||||
download: '下载',
|
||||
fileName: '文件名',
|
||||
search: '查找',
|
||||
search: '在当前目录下查找',
|
||||
mode: '权限',
|
||||
owner: '所有者',
|
||||
file: '文件',
|
||||
|
|
|
@ -231,6 +231,10 @@
|
|||
.el-input__wrapper {
|
||||
border-radius: 50px;
|
||||
}
|
||||
.el-input-group__prepend {
|
||||
border-top-left-radius: 50px;
|
||||
border-bottom-left-radius: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
// drawer头部增加按钮
|
||||
|
|
|
@ -60,16 +60,18 @@
|
|||
<el-button plain @click="openDownload" :disabled="selects.length === 0">
|
||||
{{ $t('file.download') }}
|
||||
</el-button>
|
||||
<!-- <div class="search-button">
|
||||
<el-input
|
||||
clearable
|
||||
@clear="search()"
|
||||
suffix-icon="Search"
|
||||
@keyup.enter="search()"
|
||||
@blur="search()"
|
||||
:placeholder="$t('commons.button.search')"
|
||||
></el-input>
|
||||
</div> -->
|
||||
<div class="search search-button">
|
||||
<el-input
|
||||
v-model="req.search"
|
||||
clearable
|
||||
@clear="search()"
|
||||
suffix-icon="Search"
|
||||
@blur="search()"
|
||||
:placeholder="$t('file.search')"
|
||||
>
|
||||
<template #prepend><el-checkbox v-model="req.containSub">包含子目录</el-checkbox></template>
|
||||
</el-input>
|
||||
</div>
|
||||
</template>
|
||||
<template #main>
|
||||
<ComplexTable
|
||||
|
@ -175,7 +177,15 @@ interface FilePaths {
|
|||
const router = useRouter();
|
||||
const data = ref();
|
||||
let selects = ref<any>([]);
|
||||
let req = reactive({ path: '/', expand: true, showHidden: false, page: 1, pageSize: 100 });
|
||||
let req = reactive({
|
||||
path: '/',
|
||||
expand: true,
|
||||
showHidden: false,
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
search: '',
|
||||
containSub: false,
|
||||
});
|
||||
let loading = ref(false);
|
||||
const paths = ref<FilePaths[]>([]);
|
||||
let pathWidth = ref(0);
|
||||
|
@ -258,6 +268,8 @@ const handlePath = () => {
|
|||
|
||||
const jump = async (url: string) => {
|
||||
req.path = url;
|
||||
req.containSub = false;
|
||||
req.search = '';
|
||||
await search();
|
||||
getPaths(req.path);
|
||||
nextTick(function () {
|
||||
|
@ -482,8 +494,9 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
|
||||
.search-button {
|
||||
.search {
|
||||
float: right;
|
||||
display: inline;
|
||||
width: 20%;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Add table
Reference in a new issue