1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00
zhengkunwang 2023-10-15 22:08:15 -05:00 committed by GitHub
parent 51ca89daba
commit 8efe0c8bed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 147 additions and 153 deletions

View File

@ -24,6 +24,12 @@ func Exec(cmdStr string) (string, error) {
return "", buserr.New(constant.ErrCmdTimeout)
}
if err != nil {
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
}
func handleErr(stdout, stderr bytes.Buffer, err error) (string, error) {
errMsg := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
@ -37,8 +43,6 @@ func Exec(cmdStr string) (string, error) {
}
return errMsg, err
}
return stdout.String(), nil
}
func ExecWithTimeOut(cmdStr string, timeout time.Duration) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
@ -52,18 +56,7 @@ func ExecWithTimeOut(cmdStr string, timeout time.Duration) (string, error) {
return "", buserr.New(constant.ErrCmdTimeout)
}
if err != nil {
errMsg := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
}
if len(stdout.String()) != 0 {
if len(errMsg) != 0 {
errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String())
} else {
errMsg = fmt.Sprintf("stdout: %s", stdout.String())
}
}
return errMsg, err
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
}
@ -114,18 +107,7 @@ func Execf(cmdStr string, a ...interface{}) (string, error) {
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
errMsg := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
}
if len(stdout.String()) != 0 {
if len(errMsg) != 0 {
errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String())
} else {
errMsg = fmt.Sprintf("stdout: %s", stdout.String())
}
}
return errMsg, err
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
}
@ -137,18 +119,7 @@ func ExecWithCheck(name string, a ...string) (string, error) {
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
errMsg := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
}
if len(stdout.String()) != 0 {
if len(errMsg) != 0 {
errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String())
} else {
errMsg = fmt.Sprintf("stdout: %s", stdout.String())
}
}
return errMsg, err
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
}
@ -166,22 +137,20 @@ func ExecScript(scriptPath, workDir string) (string, error) {
return "", buserr.New(constant.ErrCmdTimeout)
}
if err != nil {
errMsg := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
}
if len(stdout.String()) != 0 {
if len(errMsg) != 0 {
errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String())
} else {
errMsg = fmt.Sprintf("stdout: %s", stdout.String())
}
}
return errMsg, err
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
}
func ExecCmd(cmdStr string) error {
cmd := exec.Command("bash", "-c", cmdStr)
err := cmd.Run()
if err != nil {
return err
}
return nil
}
func CheckIllegal(args ...string) bool {
if args == nil {
return false

View File

@ -312,83 +312,14 @@ func (f FileOp) CopyDir(src, dst string) error {
return err
}
dstDir := filepath.Join(dst, srcInfo.Name())
if err := f.Fs.MkdirAll(dstDir, srcInfo.Mode()); err != nil {
if err = f.Fs.MkdirAll(dstDir, srcInfo.Mode()); err != nil {
return err
}
dir, _ := f.Fs.Open(src)
obs, err := dir.Readdir(-1)
if err != nil {
return err
}
var errs []error
for _, obj := range obs {
fSrc := filepath.Join(src, obj.Name())
if obj.IsDir() {
err = f.CopyDir(fSrc, dstDir)
if err != nil {
errs = append(errs, err)
}
} else {
err = f.CopyFile(fSrc, dstDir)
if err != nil {
errs = append(errs, err)
}
}
}
var errString string
for _, err := range errs {
errString += err.Error() + "\n"
}
if errString != "" {
return errors.New(errString)
}
return nil
return cmd.ExecCmd(fmt.Sprintf("cp -rf %s %s", src, dst+"/"))
}
func (f FileOp) CopyFile(src, dst string) error {
srcFile, err := f.Fs.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
srcInfo, err := f.Fs.Stat(src)
if err != nil {
return err
}
dstPath := path.Join(dst, srcInfo.Name())
if src == dstPath {
return nil
}
err = f.Fs.MkdirAll(filepath.Dir(dst), 0666)
if err != nil {
return err
}
dstFile, err := f.Fs.OpenFile(dstPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
if err != nil {
return err
}
defer dstFile.Close()
if _, err = io.Copy(dstFile, srcFile); err != nil {
return err
}
info, err := f.Fs.Stat(src)
if err != nil {
return err
}
if err = f.Fs.Chmod(dstFile.Name(), info.Mode()); err != nil {
return err
}
return nil
return cmd.ExecCmd(fmt.Sprintf("cp -f %s %s", src, dst+"/"))
}
func (f FileOp) GetDirSize(path string) (float64, error) {

View File

@ -10,6 +10,7 @@ import (
"os/exec"
"path"
"path/filepath"
"sort"
"strconv"
"strings"
"syscall"
@ -52,6 +53,8 @@ type FileOption struct {
ShowHidden bool `json:"showHidden"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
SortBy string `json:"sortBy" validate:"oneof=name size modTime"`
SortOrder string `json:"sortOrder" validate:"oneof=ascending descending"`
}
type FileSearchInfo struct {
@ -90,7 +93,7 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
}
if op.Expand {
if file.IsDir {
if err := file.listChildren(op.Dir, op.ShowHidden, op.ContainSub, op.Search, op.Page, op.PageSize); err != nil {
if err := file.listChildren(op); err != nil {
return nil, err
}
return file, nil
@ -139,7 +142,42 @@ func (f *FileInfo) search(search string, count int) (files []FileSearchInfo, tot
return
}
func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string, page, pageSize int) error {
func sortFileList(list []FileSearchInfo, sortBy, sortOrder string) {
switch sortBy {
case "name":
if sortOrder == "ascending" {
sort.Slice(list, func(i, j int) bool {
return list[i].Name() < list[j].Name()
})
} else {
sort.Slice(list, func(i, j int) bool {
return list[i].Name() > list[j].Name()
})
}
case "size":
if sortOrder == "ascending" {
sort.Slice(list, func(i, j int) bool {
return list[i].Size() < list[j].Size()
})
} else {
sort.Slice(list, func(i, j int) bool {
return list[i].Size() > list[j].Size()
})
}
case "modTime":
if sortOrder == "ascending" {
sort.Slice(list, func(i, j int) bool {
return list[i].ModTime().Before(list[j].ModTime())
})
} else {
sort.Slice(list, func(i, j int) bool {
return list[i].ModTime().After(list[j].ModTime())
})
}
}
}
func (f *FileInfo) listChildren(option FileOption) error {
afs := &afero.Afero{Fs: f.Fs}
var (
files []FileSearchInfo
@ -147,8 +185,8 @@ func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string,
total int
)
if search != "" && containSub {
files, total, err = f.search(search, page*pageSize)
if option.Search != "" && option.ContainSub {
files, total, err = f.search(option.Search, option.Page*option.PageSize)
if err != nil {
return err
}
@ -157,34 +195,46 @@ func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string,
if err != nil {
return err
}
var (
dirs []FileSearchInfo
fileList []FileSearchInfo
)
for _, file := range dirFiles {
files = append(files, FileSearchInfo{
info := FileSearchInfo{
Path: f.Path,
FileInfo: file,
})
}
if file.IsDir() {
dirs = append(dirs, info)
} else {
fileList = append(fileList, info)
}
}
sortFileList(dirs, option.SortBy, option.SortOrder)
sortFileList(fileList, option.SortBy, option.SortOrder)
files = append(dirs, fileList...)
}
var items []*FileInfo
for _, df := range files {
if dir && !df.IsDir() {
if option.Dir && !df.IsDir() {
continue
}
name := df.Name()
fPath := path.Join(df.Path, df.Name())
if search != "" {
if containSub {
if option.Search != "" {
if option.ContainSub {
fPath = df.Path
name = strings.TrimPrefix(strings.TrimPrefix(fPath, f.Path), "/")
} else {
lowerName := strings.ToLower(name)
lowerSearch := strings.ToLower(search)
lowerSearch := strings.ToLower(option.Search)
if !strings.Contains(lowerName, lowerSearch) {
continue
}
}
}
if !showHidden && IsHidden(name) {
if !option.ShowHidden && IsHidden(name) {
continue
}
f.ItemTotal++
@ -228,11 +278,11 @@ func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string,
}
items = append(items, file)
}
if containSub {
if option.ContainSub {
f.ItemTotal = total
}
start := (page - 1) * pageSize
end := pageSize + start
start := (option.Page - 1) * option.PageSize
end := option.PageSize + start
var result []*FileInfo
if start < 0 || start > f.ItemTotal || end < 0 || start > end {
result = items

View File

@ -1,7 +1,7 @@
{
"name": "panel",
"name": "1Panel-Frontend",
"private": true,
"version": "1.3",
"version": "1.7",
"description": "1Panel 前端",
"scripts": {
"dev": "vite",

View File

@ -30,6 +30,8 @@ export namespace File {
dir?: boolean;
showHidden?: boolean;
containSub?: boolean;
sortBy?: string;
sortOrder?: string;
}
export interface SearchUploadInfo extends ReqPage {

View File

@ -75,9 +75,15 @@ function sort(prop: string, order: string) {
function clearSelects() {
tableRef.value.refElTable.clearSelection();
}
function clearSort() {
tableRef.value.refElTable.clearSort();
}
defineExpose({
clearSelects,
sort,
clearSort,
});
onMounted(() => {

View File

@ -952,6 +952,7 @@ const message = {
currentSelect: 'Current Select: ',
unsupportType: 'Unsupported file type',
deleteHelper: 'The following resources will be deleted, this operation cannot be rolled back, continue? ',
fileHeper: 'Note: 1. Sorting is not supported after searching 2. Folders are not supported by size sorting',
},
ssh: {
sshAlert:

View File

@ -916,6 +916,7 @@ const message = {
currentSelect: '當前選中: ',
unsupportType: '不支持的文件類型',
deleteHelper: '以下資源將被刪除此操作不可回滾是否繼續',
fileHeper: '注意1.搜尋之後不支援排序 2.依大小排序不支援資料夾',
},
ssh: {
sshAlert: '列表數據根據登錄時間排序但請註意切換時區或其他操作可能導致登錄日誌的時間出現偏差',

View File

@ -916,6 +916,7 @@ const message = {
currentSelect: '当前选中: ',
unsupportType: '不支持的文件类型',
deleteHelper: '以下资源将被删除此操作不可回滚是否继续',
fileHeper: '注意1.搜索之后不支持排序 2.按大小排序不支持文件夹',
},
ssh: {
sshAlert: '列表数据根据登录时间排序但请注意切换时区或其他操作可能导致登录日志的时间出现偏差',

View File

@ -40,6 +40,13 @@
/>
</div>
<LayoutContent :title="$t('file.file')" v-loading="loading">
<template #prompt>
<el-alert type="info" :closable="false">
<template #default>
<span><span v-html="$t('file.fileHeper')"></span></span>
</template>
</el-alert>
</template>
<template #toolbar>
<el-dropdown @command="handleCreate">
<el-button type="primary">
@ -111,9 +118,17 @@
ref="tableRef"
:data="data"
@search="search"
@sort-change="changeSort"
>
<el-table-column type="selection" width="30" />
<el-table-column :label="$t('commons.table.name')" min-width="250" fix show-overflow-tooltip>
<el-table-column
:label="$t('commons.table.name')"
min-width="250"
fix
show-overflow-tooltip
sortable
prop="name"
>
<template #default="{ row }">
<svg-icon v-if="row.isDir" className="table-icon" iconName="p-file-folder"></svg-icon>
<svg-icon v-else className="table-icon" :iconName="getIconName(row.extension)"></svg-icon>
@ -140,7 +155,7 @@
</el-link>
</template>
</el-table-column>
<el-table-column :label="$t('file.size')" prop="size" max-width="50">
<el-table-column :label="$t('file.size')" prop="size" max-width="50" sortable>
<template #default="{ row }">
<span v-if="row.isDir">
<el-button type="primary" link small @click="getDirSize(row)">
@ -156,15 +171,16 @@
<el-table-column
:label="$t('file.updateTime')"
prop="modTime"
min-width="150"
width="180"
:formatter="dateFormat"
show-overflow-tooltip
sortable
></el-table-column>
<fu-table-operations
:ellipsis="mobile ? 0 : 3"
:buttons="buttons"
:label="$t('commons.table.operate')"
:min-width="mobile ? 'auto' : 300"
:min-width="mobile ? 'auto' : 200"
:fixed="mobile ? false : 'right'"
fix
/>
@ -213,7 +229,6 @@ import Detail from './detail/index.vue';
import { useRouter } from 'vue-router';
import { Back, Refresh } from '@element-plus/icons-vue';
import { MsgSuccess, MsgWarning } from '@/utils/message';
// import { ElMessageBox } from 'element-plus';
import { useSearchable } from './hooks/searchable';
import { ResultData } from '@/api/interface';
import { GlobalStore } from '@/store';
@ -238,6 +253,8 @@ const initData = () => ({
pageSize: 100,
search: '',
containSub: false,
sortBy: 'name',
sortOrder: 'ascending',
});
let req = reactive(initData());
let loading = ref(false);
@ -288,6 +305,12 @@ const mobile = computed(() => {
const search = async () => {
loading.value = true;
if (req.search != '') {
req.sortBy = 'name';
req.sortOrder = 'ascending';
tableRef.value.clearSort();
}
req.page = paginationConfig.currentPage;
req.pageSize = paginationConfig.pageSize;
await GetFilesList(req)
@ -584,6 +607,16 @@ const openDetail = (row: File.File) => {
detailRef.value.acceptParams({ path: row.path });
};
const changeSort = ({ prop, order }) => {
req.sortBy = prop;
req.sortOrder = order;
req.search = '';
req.page = 1;
req.pageSize = paginationConfig.pageSize;
req.containSub = false;
search();
};
const buttons = [
{
label: i18n.global.t('file.open'),