mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-08 01:20:07 +08:00
feat: 增加文件下载功能
This commit is contained in:
parent
7719f028fb
commit
9d6e232d0f
@ -155,7 +155,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
|
|||||||
helper.SuccessWithMsg(c, fmt.Sprintf("%d files upload success", success))
|
helper.SuccessWithMsg(c, fmt.Sprintf("%d files upload success", success))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) ChangeName(c *gin.Context) {
|
func (b *BaseApi) ChangeFileName(c *gin.Context) {
|
||||||
var req dto.FileRename
|
var req dto.FileRename
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
@ -168,20 +168,20 @@ func (b *BaseApi) ChangeName(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) Download(c *gin.Context) {
|
func (b *BaseApi) WgetFile(c *gin.Context) {
|
||||||
var req dto.FileDownload
|
var req dto.FileWget
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := fileService.Download(req); err != nil {
|
if err := fileService.Wget(req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) Move(c *gin.Context) {
|
func (b *BaseApi) MoveFile(c *gin.Context) {
|
||||||
var req dto.FileMove
|
var req dto.FileMove
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
@ -193,3 +193,17 @@ func (b *BaseApi) Move(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) Download(c *gin.Context) {
|
||||||
|
var req dto.FileDownload
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
filePath, err := fileService.FileDownload(req)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.File(filePath)
|
||||||
|
}
|
||||||
|
@ -58,7 +58,7 @@ type FileRename struct {
|
|||||||
NewName string
|
NewName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileDownload struct {
|
type FileWget struct {
|
||||||
Url string `json:"url" validate:"required"`
|
Url string `json:"url" validate:"required"`
|
||||||
Path string `json:"path" validate:"required"`
|
Path string `json:"path" validate:"required"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
@ -69,3 +69,9 @@ type FileMove struct {
|
|||||||
OldPaths []string `json:"oldPaths" validate:"required"`
|
OldPaths []string `json:"oldPaths" validate:"required"`
|
||||||
NewPath string `json:"newPath" validate:"required"`
|
NewPath string `json:"newPath" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FileDownload struct {
|
||||||
|
Paths []string `json:"paths" validate:"required"`
|
||||||
|
Type string `json:"type" validate:"required"`
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
}
|
||||||
|
@ -9,8 +9,10 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileService struct {
|
type FileService struct {
|
||||||
@ -94,18 +96,18 @@ func (f FileService) DeCompress(c dto.FileDeCompress) error {
|
|||||||
return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type))
|
return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) GetContent(c dto.FileOption) (dto.FileInfo, error) {
|
func (f FileService) GetContent(op dto.FileOption) (dto.FileInfo, error) {
|
||||||
info, err := files.NewFileInfo(c.FileOption)
|
info, err := files.NewFileInfo(op.FileOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dto.FileInfo{}, err
|
return dto.FileInfo{}, err
|
||||||
}
|
}
|
||||||
return dto.FileInfo{*info}, nil
|
return dto.FileInfo{*info}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) SaveContent(c dto.FileEdit) error {
|
func (f FileService) SaveContent(edit dto.FileEdit) error {
|
||||||
|
|
||||||
info, err := files.NewFileInfo(files.FileOption{
|
info, err := files.NewFileInfo(files.FileOption{
|
||||||
Path: c.Path,
|
Path: edit.Path,
|
||||||
Expand: false,
|
Expand: false,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,30 +115,30 @@ func (f FileService) SaveContent(c dto.FileEdit) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fo := files.NewFileOp()
|
fo := files.NewFileOp()
|
||||||
return fo.WriteFile(c.Path, strings.NewReader(c.Content), info.FileMode)
|
return fo.WriteFile(edit.Path, strings.NewReader(edit.Content), info.FileMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) ChangeName(c dto.FileRename) error {
|
func (f FileService) ChangeName(re dto.FileRename) error {
|
||||||
fo := files.NewFileOp()
|
fo := files.NewFileOp()
|
||||||
return fo.Rename(c.OldName, c.NewName)
|
return fo.Rename(re.OldName, re.NewName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) Download(c dto.FileDownload) error {
|
func (f FileService) Wget(w dto.FileWget) error {
|
||||||
fo := files.NewFileOp()
|
fo := files.NewFileOp()
|
||||||
return fo.DownloadFile(c.Url, filepath.Join(c.Path, c.Name))
|
return fo.DownloadFile(w.Url, filepath.Join(w.Path, w.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileService) MvFile(c dto.FileMove) error {
|
func (f FileService) MvFile(m dto.FileMove) error {
|
||||||
fo := files.NewFileOp()
|
fo := files.NewFileOp()
|
||||||
if c.Type == "cut" {
|
if m.Type == "cut" {
|
||||||
return fo.Cut(c.OldPaths, c.NewPath)
|
return fo.Cut(m.OldPaths, m.NewPath)
|
||||||
}
|
}
|
||||||
var errs []error
|
var errs []error
|
||||||
if c.Type == "copy" {
|
if m.Type == "copy" {
|
||||||
for _, src := range c.OldPaths {
|
for _, src := range m.OldPaths {
|
||||||
if err := fo.Copy(src, c.NewPath); err != nil {
|
if err := fo.Copy(src, m.NewPath); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
global.LOG.Errorf("copy file [%s] to [%s] failed, err: %s", src, c.NewPath, err.Error())
|
global.LOG.Errorf("copy file [%s] to [%s] failed, err: %s", src, m.NewPath, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,6 +154,19 @@ func (f FileService) MvFile(c dto.FileMove) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f FileService) FileDownload(d dto.FileDownload) (string, error) {
|
||||||
|
tempPath := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().UnixNano()))
|
||||||
|
if err := os.MkdirAll(tempPath, os.ModePerm); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
fo := files.NewFileOp()
|
||||||
|
if err := fo.Compress(d.Paths, tempPath, d.Name, files.CompressType(d.Type)); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
filePath := filepath.Join(tempPath, d.Name)
|
||||||
|
return filePath, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getUuid() string {
|
func getUuid() string {
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
io.ReadFull(rand.Reader, b)
|
io.ReadFull(rand.Reader, b)
|
||||||
|
@ -25,9 +25,10 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
|
|||||||
fileRouter.POST("/content", baseApi.GetContent)
|
fileRouter.POST("/content", baseApi.GetContent)
|
||||||
fileRouter.POST("/save", baseApi.SaveContent)
|
fileRouter.POST("/save", baseApi.SaveContent)
|
||||||
fileRouter.POST("/upload", baseApi.UploadFiles)
|
fileRouter.POST("/upload", baseApi.UploadFiles)
|
||||||
fileRouter.POST("/rename", baseApi.ChangeName)
|
fileRouter.POST("/rename", baseApi.ChangeFileName)
|
||||||
|
fileRouter.POST("/wget", baseApi.WgetFile)
|
||||||
|
fileRouter.POST("/move", baseApi.MoveFile)
|
||||||
fileRouter.POST("/download", baseApi.Download)
|
fileRouter.POST("/download", baseApi.Download)
|
||||||
fileRouter.POST("/move", baseApi.Move)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,9 @@ class RequestHttp {
|
|||||||
delete<T>(url: string, params?: any, _object = {}): Promise<ResultData<T>> {
|
delete<T>(url: string, params?: any, _object = {}): Promise<ResultData<T>> {
|
||||||
return this.service.delete(url, { params, ..._object });
|
return this.service.delete(url, { params, ..._object });
|
||||||
}
|
}
|
||||||
|
download<BlobPart>(url: string, params?: object, _object = {}): Promise<BlobPart> {
|
||||||
|
return this.service.post(url, params, _object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new RequestHttp(config);
|
export default new RequestHttp(config);
|
||||||
|
@ -71,7 +71,7 @@ export namespace File {
|
|||||||
newName: string;
|
newName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileDownload {
|
export interface FileWget {
|
||||||
path: string;
|
path: string;
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
@ -82,4 +82,10 @@ export namespace File {
|
|||||||
newPath: string;
|
newPath: string;
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FileDownload {
|
||||||
|
paths: string[];
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,14 @@ export const RenameRile = (params: File.FileRename) => {
|
|||||||
return http.post<File.File>('files/rename', params);
|
return http.post<File.File>('files/rename', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DownloadFile = (params: File.FileDownload) => {
|
export const WgetFile = (params: File.FileWget) => {
|
||||||
return http.post<File.File>('files/download', params);
|
return http.post<File.File>('files/wget', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MoveFile = (params: File.FileMove) => {
|
export const MoveFile = (params: File.FileMove) => {
|
||||||
return http.post<File.File>('files/move', params);
|
return http.post<File.File>('files/move', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DownloadFile = (params: File.FileDownload) => {
|
||||||
|
return http.download<BlobPart>('files/download', params, { responseType: 'blob' });
|
||||||
|
};
|
||||||
|
@ -48,3 +48,14 @@ export function dateFromat(row: number, col: number, dataStr: any) {
|
|||||||
second = second < 10 ? `0${String(second)}` : second;
|
second = second < 10 ? `0${String(second)}` : second;
|
||||||
return `${String(y)}-${String(m)}-${String(d)} ${String(h)}:${String(minute)}:${String(second)}`;
|
return `${String(y)}-${String(m)}-${String(d)} ${String(h)}:${String(minute)}:${String(second)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRandomStr(e: number): string {
|
||||||
|
const t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
||||||
|
const a = t.length;
|
||||||
|
let n = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < e; i++) {
|
||||||
|
n += t.charAt(Math.floor(Math.random() * a));
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
@ -1,71 +1,69 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="open" :before-close="handleClose" :title="$t('file.download')" width="30%" @open="onOpen">
|
<el-dialog
|
||||||
<el-form
|
v-model="open"
|
||||||
ref="fileForm"
|
:title="$t('file.download')"
|
||||||
label-position="left"
|
:before-close="handleClose"
|
||||||
:model="addForm"
|
width="30%"
|
||||||
label-width="100px"
|
@open="onOpen"
|
||||||
:rules="rules"
|
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
>
|
>
|
||||||
<el-form-item :label="$t('file.downloadUrl')" prop="url">
|
<el-form ref="fileForm" label-position="left" :model="addForm" label-width="100px" :rules="rules">
|
||||||
<el-input v-model="addForm.url" />
|
<el-form-item :label="$t('file.compressType')" prop="type">
|
||||||
</el-form-item>
|
<el-select v-model="addForm.type">
|
||||||
<el-form-item :label="$t('file.path')" prop="path">
|
<el-option v-for="item in options" :key="item" :label="item" :value="item" />
|
||||||
<el-input v-model="addForm.path">
|
</el-select>
|
||||||
<template #append> <FileList :path="path" @choose="getPath"></FileList> </template
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('file.name')" prop="name">
|
<el-form-item :label="$t('file.name')" prop="name">
|
||||||
<el-input v-model="addForm.name"></el-input>
|
<el-input v-model="addForm.name">
|
||||||
|
<template #append>{{ extension }}</template></el-input
|
||||||
|
>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
<el-button type="primary" @click="submit(fileForm)" :disabled="loading">{{
|
<el-button type="primary" @click="submit(fileForm)">{{ $t('commons.button.confirm') }}</el-button>
|
||||||
$t('commons.button.confirm')
|
|
||||||
}}</el-button>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script setup lang="ts">
|
||||||
|
import { FormInstance, FormRules } from 'element-plus';
|
||||||
|
import { CompressExtention, CompressType } from '@/enums/files';
|
||||||
|
import { computed, PropType, reactive, ref, toRefs } from 'vue';
|
||||||
import { DownloadFile } from '@/api/modules/files';
|
import { DownloadFile } from '@/api/modules/files';
|
||||||
|
import { File } from '@/api/interface/file';
|
||||||
import { Rules } from '@/global/form-rues';
|
import { Rules } from '@/global/form-rues';
|
||||||
import i18n from '@/lang';
|
|
||||||
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
|
||||||
import { reactive, ref, toRefs } from 'vue';
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
open: {
|
open: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
path: {
|
paths: {
|
||||||
|
type: Array as PropType<string[]>,
|
||||||
|
default: function () {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { open } = toRefs(props);
|
|
||||||
const fileForm = ref<FormInstance>();
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
name: [Rules.requiredInput],
|
name: [Rules.requiredInput],
|
||||||
path: [Rules.requiredInput],
|
type: [Rules.requiredInput],
|
||||||
url: [Rules.requiredInput],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const addForm = reactive({
|
const { open } = toRefs(props);
|
||||||
url: '',
|
const fileForm = ref<FormInstance>();
|
||||||
path: '',
|
const options = ref<string[]>([]);
|
||||||
name: '',
|
let loading = ref(false);
|
||||||
});
|
|
||||||
|
|
||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
if (fileForm.value) {
|
if (fileForm.value) {
|
||||||
fileForm.value.resetFields();
|
fileForm.value.resetFields();
|
||||||
@ -73,12 +71,27 @@ const handleClose = () => {
|
|||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPath = (path: string) => {
|
let addForm = ref({
|
||||||
addForm.path = path;
|
paths: [] as string[],
|
||||||
};
|
type: '',
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const extension = computed(() => {
|
||||||
|
return CompressExtention[addForm.value.type];
|
||||||
|
});
|
||||||
|
|
||||||
const onOpen = () => {
|
const onOpen = () => {
|
||||||
addForm.path = props.path;
|
addForm.value = {
|
||||||
|
type: 'zip',
|
||||||
|
paths: props.paths,
|
||||||
|
name: props.name,
|
||||||
|
};
|
||||||
|
console.log(addForm);
|
||||||
|
options.value = [];
|
||||||
|
for (const t in CompressType) {
|
||||||
|
options.value.push(CompressType[t]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const submit = async (formEl: FormInstance | undefined) => {
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
@ -87,10 +100,19 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let addItem = {};
|
||||||
|
Object.assign(addItem, addForm.value);
|
||||||
|
addItem['name'] = addForm.value.name + extension.value;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
DownloadFile(addForm)
|
DownloadFile(addItem as File.FileDownload)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
ElMessage.success(i18n.global.t('file.downloadStart'));
|
const downloadUrl = window.URL.createObjectURL(new Blob([res]));
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.style.display = 'none';
|
||||||
|
a.href = downloadUrl;
|
||||||
|
a.download = addItem['name'];
|
||||||
|
const event = new MouseEvent('click');
|
||||||
|
a.dispatchEvent(event);
|
||||||
handleClose();
|
handleClose();
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
@ -59,13 +59,19 @@
|
|||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<el-button type="primary" plain @click="openUpload"> {{ $t('file.upload') }}</el-button>
|
<el-button type="primary" plain @click="openUpload"> {{ $t('file.upload') }}</el-button>
|
||||||
<!-- <el-button type="primary" plain> {{ $t('file.search') }}</el-button> -->
|
<!-- <el-button type="primary" plain> {{ $t('file.search') }}</el-button> -->
|
||||||
<el-button type="primary" plain @click="openDownload"> {{ $t('file.remoteFile') }}</el-button>
|
<el-button type="primary" plain @click="openWget"> {{ $t('file.remoteFile') }}</el-button>
|
||||||
<el-button type="primary" plain @click="openMove('copy')" :disabled="selects.length === 0">
|
<el-button type="primary" plain @click="openMove('copy')" :disabled="selects.length === 0">
|
||||||
{{ $t('file.copy') }}</el-button
|
{{ $t('file.copy') }}</el-button
|
||||||
>
|
>
|
||||||
<el-button type="primary" plain @click="openMove('cut')" :disabled="selects.length === 0">
|
<el-button type="primary" plain @click="openMove('cut')" :disabled="selects.length === 0">
|
||||||
{{ $t('file.move') }}</el-button
|
{{ $t('file.move') }}</el-button
|
||||||
>
|
>
|
||||||
|
<el-button type="primary" plain @click="openCompress(selects)" :disabled="selects.length === 0">
|
||||||
|
{{ $t('file.compress') }}</el-button
|
||||||
|
>
|
||||||
|
<el-button type="primary" plain @click="openDownload" :disabled="selects.length === 0">
|
||||||
|
{{ $t('file.download') }}</el-button
|
||||||
|
>
|
||||||
<!-- <el-button type="primary" plain> {{ $t('file.sync') }}</el-button>
|
<!-- <el-button type="primary" plain> {{ $t('file.sync') }}</el-button>
|
||||||
<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> -->
|
||||||
@ -138,20 +144,28 @@
|
|||||||
@close="closeRename"
|
@close="closeRename"
|
||||||
></FileRename>
|
></FileRename>
|
||||||
<Upload :open="uploadPage.open" :path="uploadPage.path" @close="closeUpload"></Upload>
|
<Upload :open="uploadPage.open" :path="uploadPage.path" @close="closeUpload"></Upload>
|
||||||
<FileDown :open="downloadPage.open" :path="downloadPage.path" @close="closeDownload"></FileDown>
|
<Wget :open="wgetPage.open" :path="wgetPage.path" @close="closeWget"></Wget>
|
||||||
<Move :open="movePage.open" :oldPaths="movePage.oldPaths" :type="movePage.type" @close="clodeMove"></Move>
|
<Move :open="movePage.open" :oldPaths="movePage.oldPaths" :type="movePage.type" @close="clodeMove"></Move>
|
||||||
|
<Download
|
||||||
|
:open="downloadPage.open"
|
||||||
|
:paths="downloadPage.paths"
|
||||||
|
:name="downloadPage.name"
|
||||||
|
@close="closeDownload"
|
||||||
|
></Download>
|
||||||
</el-row>
|
</el-row>
|
||||||
</LayoutContent>
|
</LayoutContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, reactive, ref } from '@vue/runtime-core';
|
import { onMounted, reactive, ref } from '@vue/runtime-core';
|
||||||
|
import { GetFilesList, GetFilesTree, DeleteFile, GetFileContent, SaveFileContent } from '@/api/modules/files';
|
||||||
|
import { dateFromat, getRandomStr } from '@/utils/util';
|
||||||
|
import { File } from '@/api/interface/file';
|
||||||
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
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, DeleteFile, GetFileContent, SaveFileContent } from '@/api/modules/files';
|
|
||||||
import { dateFromat } from '@/utils/util';
|
|
||||||
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/index.vue';
|
import CreateFile from './create/index.vue';
|
||||||
@ -160,20 +174,19 @@ import Compress from './compress/index.vue';
|
|||||||
import Decompress from './decompress/index.vue';
|
import Decompress from './decompress/index.vue';
|
||||||
import Upload from './upload/index.vue';
|
import Upload from './upload/index.vue';
|
||||||
import FileRename from './rename/index.vue';
|
import FileRename from './rename/index.vue';
|
||||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
|
||||||
import CodeEditor from './code-editor/index.vue';
|
import CodeEditor from './code-editor/index.vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import Wget from './wget/index.vue';
|
||||||
import FileDown from './download/index.vue';
|
|
||||||
import Move from './move/index.vue';
|
import Move from './move/index.vue';
|
||||||
|
import Download from './download/index.vue';
|
||||||
|
|
||||||
let data = ref();
|
const data = ref();
|
||||||
let selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
let req = reactive({ path: '/', expand: true });
|
const req = reactive({ path: '/', expand: true });
|
||||||
let loading = ref(false);
|
const loading = ref(false);
|
||||||
let treeLoading = ref(false);
|
const treeLoading = ref(false);
|
||||||
let paths = ref<string[]>([]);
|
const paths = ref<string[]>([]);
|
||||||
let fileTree = ref<File.FileTree[]>([]);
|
const fileTree = ref<File.FileTree[]>([]);
|
||||||
let expandKeys = ref<string[]>([]);
|
const expandKeys = ref<string[]>([]);
|
||||||
|
|
||||||
const filePage = reactive({ open: false, createForm: { path: '/', isDir: false, mode: 0o755 } });
|
const filePage = reactive({ open: false, createForm: { path: '/', isDir: false, mode: 0o755 } });
|
||||||
const modePage = reactive({ open: false, modeForm: { path: '/', isDir: false, mode: 0o755 } });
|
const modePage = reactive({ open: false, modeForm: { path: '/', isDir: false, mode: 0o755 } });
|
||||||
@ -183,8 +196,9 @@ const editorPage = reactive({ open: false, content: '', loading: false });
|
|||||||
const codeReq = reactive({ path: '', expand: false });
|
const codeReq = reactive({ path: '', expand: false });
|
||||||
const uploadPage = reactive({ open: false, path: '' });
|
const uploadPage = reactive({ open: false, path: '' });
|
||||||
const renamePage = reactive({ open: false, path: '', oldName: '' });
|
const renamePage = reactive({ open: false, path: '', oldName: '' });
|
||||||
const downloadPage = reactive({ open: false, path: '' });
|
const wgetPage = reactive({ open: false, path: '' });
|
||||||
const movePage = reactive({ open: false, oldPaths: [''], type: '' });
|
const movePage = reactive({ open: false, oldPaths: [''], type: '' });
|
||||||
|
const downloadPage = reactive({ open: false, paths: [''], name: '' });
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
children: 'children',
|
children: 'children',
|
||||||
@ -237,9 +251,13 @@ const jump = async (index: number) => {
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
const jPaths = paths.value.slice(0, index + 1);
|
const jPaths = paths.value.slice(0, index + 1);
|
||||||
for (let i in jPaths) {
|
for (let i in jPaths) {
|
||||||
|
if (path.endsWith('/')) {
|
||||||
|
path = path + jPaths[i];
|
||||||
|
} else {
|
||||||
path = path + '/' + jPaths[i];
|
path = path + '/' + jPaths[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
req.path = path;
|
req.path = path;
|
||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
@ -311,10 +329,18 @@ const closeMode = () => {
|
|||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openCompress = (item: File.File) => {
|
const openCompress = (items: File.File[]) => {
|
||||||
compressPage.open = true;
|
compressPage.open = true;
|
||||||
compressPage.files = [item.path];
|
const paths = [];
|
||||||
compressPage.name = item.name;
|
for (const item of items) {
|
||||||
|
paths.push(item.path);
|
||||||
|
}
|
||||||
|
compressPage.files = paths;
|
||||||
|
if (paths.length === 1) {
|
||||||
|
compressPage.name = items[0].name;
|
||||||
|
} else {
|
||||||
|
compressPage.name = getRandomStr(6);
|
||||||
|
}
|
||||||
compressPage.dst = req.path;
|
compressPage.dst = req.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,13 +385,13 @@ const closeUpload = () => {
|
|||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openDownload = () => {
|
const openWget = () => {
|
||||||
downloadPage.open = true;
|
wgetPage.open = true;
|
||||||
downloadPage.path = req.path;
|
wgetPage.path = req.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeDownload = () => {
|
const closeWget = () => {
|
||||||
downloadPage.open = false;
|
wgetPage.open = false;
|
||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -382,12 +408,12 @@ const closeRename = () => {
|
|||||||
|
|
||||||
const openMove = (type: string) => {
|
const openMove = (type: string) => {
|
||||||
movePage.type = type;
|
movePage.type = type;
|
||||||
movePage.open = true;
|
|
||||||
const oldpaths = [];
|
const oldpaths = [];
|
||||||
for (const s of selects.value) {
|
for (const s of selects.value) {
|
||||||
oldpaths.push(s['path']);
|
oldpaths.push(s['path']);
|
||||||
}
|
}
|
||||||
movePage.oldPaths = oldpaths;
|
movePage.oldPaths = oldpaths;
|
||||||
|
movePage.open = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const clodeMove = () => {
|
const clodeMove = () => {
|
||||||
@ -395,6 +421,21 @@ const clodeMove = () => {
|
|||||||
search(req);
|
search(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openDownload = () => {
|
||||||
|
const paths = [];
|
||||||
|
for (const s of selects.value) {
|
||||||
|
paths.push(s['path']);
|
||||||
|
}
|
||||||
|
downloadPage.paths = paths;
|
||||||
|
downloadPage.name = getRandomStr(6);
|
||||||
|
downloadPage.open = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDownload = () => {
|
||||||
|
downloadPage.open = false;
|
||||||
|
search(req);
|
||||||
|
};
|
||||||
|
|
||||||
const saveContent = (content: string) => {
|
const saveContent = (content: string) => {
|
||||||
editorPage.loading = true;
|
editorPage.loading = true;
|
||||||
SaveFileContent({ path: codeReq.path, content: content }).finally(() => {
|
SaveFileContent({ path: codeReq.path, content: content }).finally(() => {
|
||||||
@ -429,7 +470,9 @@ const buttons = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('file.compress'),
|
label: i18n.global.t('file.compress'),
|
||||||
click: openCompress,
|
click: (row: File.File) => {
|
||||||
|
openCompress([row]);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('file.deCompress'),
|
label: i18n.global.t('file.deCompress'),
|
||||||
|
101
frontend/src/views/file-management/wget/index.vue
Normal file
101
frontend/src/views/file-management/wget/index.vue
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="open" :before-close="handleClose" :title="$t('file.download')" width="30%" @open="onOpen">
|
||||||
|
<el-form
|
||||||
|
ref="fileForm"
|
||||||
|
label-position="left"
|
||||||
|
:model="addForm"
|
||||||
|
label-width="100px"
|
||||||
|
:rules="rules"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-form-item :label="$t('file.downloadUrl')" prop="url">
|
||||||
|
<el-input v-model="addForm.url" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('file.path')" prop="path">
|
||||||
|
<el-input v-model="addForm.path">
|
||||||
|
<template #append> <FileList :path="path" @choose="getPath"></FileList> </template
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('file.name')" prop="name">
|
||||||
|
<el-input v-model="addForm.name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit(fileForm)" :disabled="loading">{{
|
||||||
|
$t('commons.button.confirm')
|
||||||
|
}}</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { WgetFile } from '@/api/modules/files';
|
||||||
|
import { Rules } from '@/global/form-rues';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
||||||
|
import { reactive, ref, toRefs } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
open: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { open } = toRefs(props);
|
||||||
|
const fileForm = ref<FormInstance>();
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const rules = reactive<FormRules>({
|
||||||
|
name: [Rules.requiredInput],
|
||||||
|
path: [Rules.requiredInput],
|
||||||
|
url: [Rules.requiredInput],
|
||||||
|
});
|
||||||
|
|
||||||
|
const addForm = reactive({
|
||||||
|
url: '',
|
||||||
|
path: '',
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const em = defineEmits(['close']);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
if (fileForm.value) {
|
||||||
|
fileForm.value.resetFields();
|
||||||
|
}
|
||||||
|
em('close', open);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPath = (path: string) => {
|
||||||
|
addForm.path = path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOpen = () => {
|
||||||
|
addForm.path = props.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
WgetFile(addForm)
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success(i18n.global.t('file.downloadStart'));
|
||||||
|
handleClose();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
Loading…
x
Reference in New Issue
Block a user