mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 增加文件删除功能
This commit is contained in:
parent
f48ae22a15
commit
1dc20914ac
@ -48,3 +48,17 @@ func (b *BaseApi) CreateFile(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) DeleteFile(c *gin.Context) {
|
||||||
|
var req dto.FileDelete
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := fileService.Delete(req)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
@ -25,3 +25,8 @@ type FileCreate struct {
|
|||||||
IsDir bool
|
IsDir bool
|
||||||
Mode int64
|
Mode int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FileDelete struct {
|
||||||
|
Path string
|
||||||
|
IsDir bool
|
||||||
|
}
|
||||||
|
@ -55,6 +55,15 @@ func (f FileService) Create(op dto.FileCreate) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f FileService) Delete(op dto.FileDelete) error {
|
||||||
|
fo := files.NewFileOp()
|
||||||
|
if op.IsDir {
|
||||||
|
return fo.DeleteDir(op.Path)
|
||||||
|
} else {
|
||||||
|
return fo.DeleteFile(op.Path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getUuid() string {
|
func getUuid() string {
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
io.ReadFull(rand.Reader, b)
|
io.ReadFull(rand.Reader, b)
|
||||||
|
@ -32,5 +32,5 @@ var (
|
|||||||
ErrTypeInvalidParams = "ErrInvalidParams"
|
ErrTypeInvalidParams = "ErrInvalidParams"
|
||||||
ErrTypeToken = "ErrToken"
|
ErrTypeToken = "ErrToken"
|
||||||
ErrTypeTokenTimeOut = "ErrTokenTimeOut"
|
ErrTypeTokenTimeOut = "ErrTokenTimeOut"
|
||||||
ErrTypeNotLogin = "ErrNotLogin"
|
ErrTypeNotLogin = "ErrTypeNotLogin"
|
||||||
)
|
)
|
||||||
|
@ -18,6 +18,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
|
|||||||
fileRouter.POST("/search", baseApi.ListFiles)
|
fileRouter.POST("/search", baseApi.ListFiles)
|
||||||
fileRouter.POST("/tree", baseApi.GetFileTree)
|
fileRouter.POST("/tree", baseApi.GetFileTree)
|
||||||
fileRouter.POST("", baseApi.CreateFile)
|
fileRouter.POST("", baseApi.CreateFile)
|
||||||
|
fileRouter.POST("/del", baseApi.DeleteFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ func (f FileOp) CreateDir(dst string, mode fs.FileMode) error {
|
|||||||
return f.Fs.MkdirAll(dst, mode)
|
return f.Fs.MkdirAll(dst, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f FileOp) DeleteDir(dst string) error {
|
||||||
|
return f.Fs.RemoveAll(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FileOp) DeleteFile(dst string) error {
|
||||||
|
return f.Fs.Remove(dst)
|
||||||
|
}
|
||||||
|
|
||||||
func (f FileOp) WriteFile(dst string, in io.Reader, mode fs.FileMode) error {
|
func (f FileOp) WriteFile(dst string, in io.Reader, mode fs.FileMode) error {
|
||||||
dir, _ := path.Split(dst)
|
dir, _ := path.Split(dst)
|
||||||
if err := f.Fs.MkdirAll(dir, mode); err != nil {
|
if err := f.Fs.MkdirAll(dir, mode); err != nil {
|
||||||
|
@ -35,4 +35,9 @@ export namespace File {
|
|||||||
isDir: Boolean;
|
isDir: Boolean;
|
||||||
mode: number;
|
mode: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FileDelete {
|
||||||
|
path: string;
|
||||||
|
isDir: Boolean;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,3 +12,7 @@ export const GetFilesTree = (params: File.ReqFile) => {
|
|||||||
export const CreateFile = (form: File.FileCreate) => {
|
export const CreateFile = (form: File.FileCreate) => {
|
||||||
return http.post<File.File>('files', form);
|
return http.post<File.File>('files', form);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DeleteFile = (form: File.FileDelete) => {
|
||||||
|
return http.post<File.File>('files/del', form);
|
||||||
|
};
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
v-loading="treeLoading"
|
v-loading="treeLoading"
|
||||||
node-key="id"
|
node-key="id"
|
||||||
:default-expanded-keys="expandKeys"
|
:default-expanded-keys="expandKeys"
|
||||||
|
@node-click="clickNode"
|
||||||
>
|
>
|
||||||
<template #default="{ node }">
|
<template #default="{ node }">
|
||||||
<el-icon v-if="node.expanded"><FolderOpened /></el-icon>
|
<el-icon v-if="node.expanded"><FolderOpened /></el-icon>
|
||||||
@ -66,7 +67,7 @@
|
|||||||
<el-button type="primary" plain> {{ $t('file.terminal') }}</el-button>
|
<el-button type="primary" plain> {{ $t('file.terminal') }}</el-button>
|
||||||
<el-button type="primary" plain> {{ $t('file.shareList') }}</el-button>
|
<el-button type="primary" plain> {{ $t('file.shareList') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
<el-table-column :label="$t('commons.table.name')" min-width="120" fix>
|
<el-table-column :label="$t('commons.table.name')" min-width="150" fix>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<svg-icon v-if="row.isDir" className="table-icon" iconName="p-file-folder"></svg-icon>
|
<svg-icon v-if="row.isDir" className="table-icon" iconName="p-file-folder"></svg-icon>
|
||||||
<svg-icon v-else className="table-icon" iconName="p-file-normal"></svg-icon>
|
<svg-icon v-else className="table-icon" iconName="p-file-normal"></svg-icon>
|
||||||
@ -81,7 +82,7 @@
|
|||||||
:label="$t('file.updateTime')"
|
:label="$t('file.updateTime')"
|
||||||
prop="modTime"
|
prop="modTime"
|
||||||
:formatter="dateFromat"
|
:formatter="dateFromat"
|
||||||
min-width="150"
|
min-width="100"
|
||||||
>
|
>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@ -100,16 +101,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref } from '@vue/runtime-core';
|
import { onMounted, reactive, ref } from '@vue/runtime-core';
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { GetFilesList, GetFilesTree } from '@/api/modules/files';
|
import { GetFilesList, GetFilesTree, DeleteFile } from '@/api/modules/files';
|
||||||
import { dateFromat } from '@/utils/util';
|
import { dateFromat } from '@/utils/util';
|
||||||
import { File } from '@/api/interface/file';
|
import { File } from '@/api/interface/file';
|
||||||
import BreadCrumbs from '@/components/bread-crumbs/index.vue';
|
import BreadCrumbs from '@/components/bread-crumbs/index.vue';
|
||||||
import BreadCrumbItem from '@/components/bread-crumbs/bread-crumbs-item.vue';
|
import BreadCrumbItem from '@/components/bread-crumbs/bread-crumbs-item.vue';
|
||||||
import CreateFile from './create.vue';
|
import CreateFile from './create.vue';
|
||||||
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
|
|
||||||
let data = ref();
|
let data = ref();
|
||||||
let selects = ref<any>([]);
|
let selects = ref<any>([]);
|
||||||
@ -191,13 +193,19 @@ const getTree = async (req: File.ReqFile, node: File.FileTree | null) => {
|
|||||||
expandKeys.value = [];
|
expandKeys.value = [];
|
||||||
expandKeys.value.push(fileTree.value[0].id);
|
expandKeys.value.push(fileTree.value[0].id);
|
||||||
}
|
}
|
||||||
search(req);
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
treeLoading.value = false;
|
treeLoading.value = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clickNode = async (node: any) => {
|
||||||
|
if (node.path) {
|
||||||
|
req.path = node.path;
|
||||||
|
search(req);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadNode = (node: any, resolve: (data: File.FileTree[]) => void) => {
|
const loadNode = (node: any, resolve: (data: File.FileTree[]) => void) => {
|
||||||
if (!node.hasChildNodes) {
|
if (!node.hasChildNodes) {
|
||||||
if (node.data.path) {
|
if (node.data.path) {
|
||||||
@ -215,17 +223,33 @@ const handleCreate = (commnad: string) => {
|
|||||||
fileCreate.value.isDir = false;
|
fileCreate.value.isDir = false;
|
||||||
if (commnad === 'dir') {
|
if (commnad === 'dir') {
|
||||||
fileCreate.value.isDir = true;
|
fileCreate.value.isDir = true;
|
||||||
console.log(fileCreate.value);
|
|
||||||
}
|
}
|
||||||
console.log(commnad);
|
|
||||||
openCreate.value = true;
|
openCreate.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const delFile = async (row: File.File | null) => {
|
||||||
|
// let ids: Array<number> = [];
|
||||||
|
|
||||||
|
// if (row === null) {
|
||||||
|
// selects.value.forEach((item: File.File) => {
|
||||||
|
// ids.push(item.id);
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// ids.push(row.id);
|
||||||
|
// }
|
||||||
|
await useDeleteData(DeleteFile, row as File.FileDelete, 'commons.msg.delete');
|
||||||
|
search(req);
|
||||||
|
};
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
openCreate.value = false;
|
openCreate.value = false;
|
||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
search(req);
|
||||||
|
});
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
{
|
{
|
||||||
label: i18n.global.t('file.open'),
|
label: i18n.global.t('file.open'),
|
||||||
@ -242,6 +266,7 @@ const buttons = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('commons.button.delete'),
|
label: i18n.global.t('commons.button.delete'),
|
||||||
|
click: delFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('file.info'),
|
label: i18n.global.t('file.info'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user