mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-30 18:00:56 +01:00
optimized file upload
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div :style="style" class="pie-chart">
|
||||
<div v-if="isEmpty" class="empty-placeholder">
|
||||
No Data Available
|
||||
</div>
|
||||
<div ref="elRef" class="echarts-element"></div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -46,8 +49,16 @@ export default defineComponent({
|
||||
const elRef = ref<HTMLDivElement>();
|
||||
const chart = ref<ECharts>();
|
||||
|
||||
const isEmpty = computed<boolean>(() => {
|
||||
const {config} = props;
|
||||
const {data} = config;
|
||||
if (!data) return true;
|
||||
return data.length === 0;
|
||||
|
||||
});
|
||||
|
||||
const getSeriesData = (data: StatsResult[], key?: string) => {
|
||||
const {valueKey, labelKey, config} = props;
|
||||
const {valueKey, labelKey} = props;
|
||||
const _valueKey = !key ? valueKey : key;
|
||||
|
||||
if (_valueKey) {
|
||||
@@ -69,7 +80,7 @@ export default defineComponent({
|
||||
|
||||
const seriesItem = {
|
||||
type: 'pie',
|
||||
data: getSeriesData(data),
|
||||
data: getSeriesData(data || []),
|
||||
radius: ['40%', '70%'],
|
||||
alignTo: 'labelLine',
|
||||
} as EChartSeries;
|
||||
@@ -119,6 +130,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
return {
|
||||
isEmpty,
|
||||
style,
|
||||
elRef,
|
||||
render,
|
||||
@@ -128,7 +140,22 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../styles/variables";
|
||||
|
||||
.pie-chart {
|
||||
position: relative;
|
||||
|
||||
.empty-placeholder {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.echarts-element {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
175
frontend/src/components/file/FileUpload.vue
Normal file
175
frontend/src/components/file/FileUpload.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div class="file-upload">
|
||||
<div class="mode-select">
|
||||
<el-radio-group v-model="internalMode" @change="onModeChange">
|
||||
<el-radio
|
||||
v-for="{value, label} in modeOptions"
|
||||
:key="value"
|
||||
:label="value"
|
||||
>
|
||||
{{ label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<template v-if="mode === FILE_UPLOAD_MODE_FILES">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:on-change="onFileChange"
|
||||
:http-request="() => {}"
|
||||
drag
|
||||
multiple
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">Drag files here, or <em>click to upload</em></div>
|
||||
</el-upload>
|
||||
<input v-bind="getInputProps()">
|
||||
</template>
|
||||
<template v-else-if="mode === FILE_UPLOAD_MODE_DIR">
|
||||
<div class="folder-upload">
|
||||
<Button @click="open">
|
||||
<i class="fa fa-folder"></i>
|
||||
Click to Select Folder to Upload
|
||||
</Button>
|
||||
<template v-if="!!dirInfo?.dirName && dirInfo?.fileCount">
|
||||
<Tag
|
||||
type="primary"
|
||||
class="info-tag"
|
||||
:label="dirInfo?.dirName"
|
||||
:icon="['fa', 'folder']"
|
||||
tooltip="Folder Name"
|
||||
/>
|
||||
<Tag
|
||||
type="success"
|
||||
class="info-tag"
|
||||
:label="dirInfo?.fileCount"
|
||||
:icon="['fa', 'hashtag']"
|
||||
tooltip="Files Count"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<input v-bind="getInputProps()" webkitdirectory>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent, onBeforeMount, ref, watch} from 'vue';
|
||||
import {FILE_UPLOAD_MODE_DIR, FILE_UPLOAD_MODE_FILES} from '@/constants/file';
|
||||
import {ElUpload} from 'element-plus/lib/el-upload/src/upload.type';
|
||||
import {UploadFile} from 'element-plus/packages/upload/src/upload.type';
|
||||
import Button from '@/components/button/Button.vue';
|
||||
import Tag from '@/components/tag/Tag.vue';
|
||||
import {plainClone} from '@/utils/object';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FileUpload',
|
||||
components: {
|
||||
Tag,
|
||||
Button,
|
||||
},
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
},
|
||||
getInputProps: {
|
||||
type: Function,
|
||||
},
|
||||
open: {
|
||||
type: Function,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'mode-change',
|
||||
'files-change',
|
||||
],
|
||||
setup(props: FileUploadProps, {emit}) {
|
||||
const modeOptions: FileUploadModeOption[] = [
|
||||
{
|
||||
label: 'Files',
|
||||
value: FILE_UPLOAD_MODE_FILES,
|
||||
},
|
||||
{
|
||||
label: 'Folder',
|
||||
value: FILE_UPLOAD_MODE_DIR,
|
||||
},
|
||||
];
|
||||
const internalMode = ref<string>();
|
||||
|
||||
const uploadRef = ref<ElUpload>();
|
||||
|
||||
const dirPath = ref<string>();
|
||||
|
||||
watch(() => props.mode, () => {
|
||||
internalMode.value = props.mode;
|
||||
uploadRef.value?.clearFiles();
|
||||
});
|
||||
|
||||
const onFileChange = (file: UploadFile, fileList: UploadFile[]) => {
|
||||
emit('files-change', fileList.map(f => f.raw));
|
||||
};
|
||||
|
||||
const clearFiles = () => {
|
||||
uploadRef.value?.clearFiles();
|
||||
};
|
||||
|
||||
const onModeChange = (mode: string) => {
|
||||
emit('mode-change', mode);
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
const {mode} = props;
|
||||
internalMode.value = mode;
|
||||
});
|
||||
|
||||
const dirInfo = ref<FileUploadDirInfo>();
|
||||
|
||||
const setDirInfo = (info: FileUploadDirInfo) => {
|
||||
console.debug(info);
|
||||
dirInfo.value = plainClone(info);
|
||||
};
|
||||
|
||||
return {
|
||||
uploadRef,
|
||||
FILE_UPLOAD_MODE_FILES,
|
||||
FILE_UPLOAD_MODE_DIR,
|
||||
modeOptions,
|
||||
internalMode,
|
||||
dirPath,
|
||||
onFileChange,
|
||||
clearFiles,
|
||||
onModeChange,
|
||||
dirInfo,
|
||||
setDirInfo,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.file-upload {
|
||||
.mode-select {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-upload {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.folder-upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.file-upload >>> .el-upload,
|
||||
.file-upload >>> .el-upload .el-upload-dragger {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-upload >>> .folder-upload .info-tag {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -15,8 +15,16 @@
|
||||
<!-- ./Input -->
|
||||
|
||||
<!-- Button -->
|
||||
<Button v-if="buttonLabel" :disabled="disabled" :size="size" :type="buttonType" class="button" no-margin>
|
||||
<Icon v-if="buttonIcon" :icon="buttonIcon"/>
|
||||
<Button
|
||||
v-if="buttonLabel"
|
||||
:disabled="disabled"
|
||||
:size="size"
|
||||
:type="buttonType"
|
||||
class="button"
|
||||
no-margin
|
||||
@click="onClick"
|
||||
>
|
||||
<Icon v-if="buttonIcon" :icon="buttonIcon" />
|
||||
{{ buttonLabel }}
|
||||
</Button>
|
||||
<template v-else-if="buttonIcon">
|
||||
@@ -27,6 +35,7 @@
|
||||
:size="size"
|
||||
:type="buttonType"
|
||||
class="button"
|
||||
@click="onClick"
|
||||
/>
|
||||
<IconButton
|
||||
v-else
|
||||
@@ -35,6 +44,7 @@
|
||||
:size="size"
|
||||
:type="buttonType"
|
||||
class="button"
|
||||
@click="onClick"
|
||||
/>
|
||||
</template>
|
||||
<!-- ./Button -->
|
||||
|
||||
Reference in New Issue
Block a user