导入优化

This commit is contained in:
陈红丽 2024-12-18 17:22:30 +08:00
parent e6c1599cb2
commit 7b001872a8
4 changed files with 283 additions and 289 deletions

View File

@ -5,17 +5,17 @@
<div class="upload-handle" @click.stop> <div class="upload-handle" @click.stop>
<div class="handle-icon" @click="handleEdit(index)" v-if="!self_disabled"> <div class="handle-icon" @click="handleEdit(index)" v-if="!self_disabled">
<n-icon size="20"> <n-icon size="20">
<EditOutlined/> <EditOutlined />
</n-icon> </n-icon>
</div> </div>
<div class="handle-icon" @click="onPreview(index)"> <div class="handle-icon" @click="onPreview(index)">
<n-icon size="20"> <n-icon size="20">
<ZoomInOutlined/> <ZoomInOutlined />
</n-icon> </n-icon>
</div> </div>
<div class="handle-icon" @click="handleRemove(index)" v-if="!self_disabled"> <div class="handle-icon" @click="handleRemove(index)" v-if="!self_disabled">
<n-icon size="20"> <n-icon size="20">
<DeleteOutlined/> <DeleteOutlined />
</n-icon> </n-icon>
</div> </div>
</div> </div>
@ -36,8 +36,8 @@
v-if="!self_disabled" v-if="!self_disabled"
:accept="props.fileType" :accept="props.fileType"
> >
<n-icon size="40" color="#666666" v-if="!loading" > <n-icon size="40" color="#666666" v-if="!loading">
<PlusOutlined/> <PlusOutlined />
</n-icon> </n-icon>
<n-progress type="circle" v-else :percentage="progress" /> <n-progress type="circle" v-else :percentage="progress" />
</n-upload> </n-upload>
@ -47,14 +47,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { generateUUID } from '@/utils/auth'; import { generateUUID } from '@/utils/auth';
import type { UploadFileInfo } from 'naive-ui' import type { UploadFileInfo } from 'naive-ui';
import { import { PlusOutlined, EditOutlined, DeleteOutlined, ZoomInOutlined } from '@vicons/antd';
PlusOutlined, import { useNotification } from 'naive-ui';
EditOutlined,
DeleteOutlined,
ZoomInOutlined,
} from '@vicons/antd';
import { useNotification } from 'naive-ui'
const uploadRef = ref(); const uploadRef = ref();
import { upload } from '@/api/common'; import { upload } from '@/api/common';
@ -112,7 +107,7 @@ import { useNotification } from 'naive-ui'
// id // id
const uuid = ref('id-' + generateUUID()); const uuid = ref('id-' + generateUUID());
const notification = useNotification() const notification = useNotification();
// //
const self_disabled = computed(() => { const self_disabled = computed(() => {
@ -120,14 +115,14 @@ import { useNotification } from 'naive-ui'
}); });
const fileList = computed({ const fileList = computed({
get: () => { get: () => {
console.log(props.fileLists) console.log(props.fileLists);
return props.fileLists; return props.fileLists;
}, },
set: (val) => { set: (val) => {
emit('update:modelValue', fileList.value); emit('update:modelValue', fileList.value);
}, },
}); });
let editIndex = ''; let editIndex = '';
const emit = defineEmits(['upload']); const emit = defineEmits(['upload']);
@ -165,13 +160,13 @@ import { useNotification } from 'naive-ui'
} catch (error) { } catch (error) {
notification.error({ notification.error({
message: '温馨提示', message: '温馨提示',
duration:2000, duration: 2000,
description: '上传文件失败!', description: '上传文件失败!',
}); });
if (props.multiple) { if (props.multiple) {
emit('upload', fileList.value, props.zIndex); emit('upload', fileList.value, props.zIndex);
} else { } else {
uploadRef.value!.clear(); uploadRef.value?.clear();
emit('upload', '', props.zIndex); emit('upload', '', props.zIndex);
} }
options.onError(error as any); options.onError(error as any);
@ -180,9 +175,9 @@ import { useNotification } from 'naive-ui'
loading.value = false; loading.value = false;
} }
}; };
const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> { const handleUploadChange = (data: { fileList: UploadFileInfo[] }) => {
handleHttpUpload(data) handleHttpUpload(data);
}; };
const onPreview = (index: any) => { const onPreview = (index: any) => {
window.open(fileList.value[index].filePath); window.open(fileList.value[index].filePath);
}; };
@ -201,7 +196,7 @@ const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> {
props.zIndex, props.zIndex,
); );
} else { } else {
uploadRef.value!.clear(); uploadRef.value?.clear();
emit('upload', '', props.zIndex); emit('upload', '', props.zIndex);
} }
}; };
@ -210,7 +205,7 @@ const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> {
if (props.limit) { if (props.limit) {
notification.warning({ notification.warning({
message: '温馨提示', message: '温馨提示',
duration:2000, duration: 2000,
description: `最多支持上传${props.limit}`, description: `最多支持上传${props.limit}`,
}); });
} }
@ -221,12 +216,12 @@ const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> {
* @param rawFile 选择的文件 * @param rawFile 选择的文件
* */ * */
const beforeUpload = (rawFile) => { const beforeUpload = (rawFile) => {
console.log(rawFile) console.log(rawFile);
const imgSize = rawFile.file.file.size / 1024 / 1024 < props.fileSize; const imgSize = rawFile.file.file.size / 1024 / 1024 < props.fileSize;
if (!imgSize) { if (!imgSize) {
notification.warning({ notification.warning({
message: '温馨提示', message: '温馨提示',
duration:2000, duration: 2000,
description: `上传文件大小不能超过 ${props.fileSize}M`, description: `上传文件大小不能超过 ${props.fileSize}M`,
}); });
return false; return false;
@ -239,7 +234,7 @@ const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> {
if (fileType.indexOf(substrName) == -1) { if (fileType.indexOf(substrName) == -1) {
notification.warning({ notification.warning({
message: '温馨提示', message: '温馨提示',
duration:2000, duration: 2000,
description: '上传文件不符合所需的格式!', description: '上传文件不符合所需的格式!',
}); });
return false; return false;
@ -281,10 +276,10 @@ const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> {
height: v-bind(height); height: v-bind(height);
overflow: hidden; overflow: hidden;
border-radius: 4px; border-radius: 4px;
border:1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
cursor: pointer; cursor: pointer;
.n-upload-trigger { .n-upload-trigger {
width:100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,30 +1,47 @@
<template> <template>
<div :class="isBtn?'file-upload-box2':'file-upload-box'"> <div :class="isBtn ? 'file-upload-box2' : 'file-upload-box'">
<n-upload action="#" :id="uuid" class="upload-demo my-upload-file" <n-upload
:class="fileList.length > 0 && !loading ? 'success-file' : ''" :multiple="multiple" ref="uploadRef" directory-dnd action="#"
:disabled="loading ? true : self_disabled" v-model:file-list="fileList" :id="uuid"
@change="handleUploadChange" @remove="handleRemove" @before-upload="beforeUpload" :show-file-list="showFileList" class="upload-demo my-upload-file"
:max="limit" > :class="fileList.length > 0 && !loading ? 'success-file' : ''"
:multiple="multiple"
ref="uploadRef"
directory-dnd
:disabled="loading ? true : self_disabled"
v-model:file-list="fileList"
@change="handleUploadChange"
@remove="handleRemove"
@before-upload="beforeUpload"
:show-file-list="showFileList"
:max="limit"
>
<template v-if="isBtn"> <template v-if="isBtn">
<n-tooltip v-if="isBtn && btnTip" class="box-item" effect="dark" :content="btnTip" placement="top"> <n-tooltip
v-if="isBtn && btnTip"
class="box-item"
effect="dark"
:content="btnTip"
placement="top"
>
<n-button icon="Upload" type="primary">点击上传</n-button> <n-button icon="Upload" type="primary">点击上传</n-button>
</n-tooltip> </n-tooltip>
<n-button v-else icon="Upload" type="primary">点击上传</n-button> <n-button v-else icon="Upload" type="primary">点击上传</n-button>
</template> </template>
<template v-else> <template v-else>
<n-upload-dragger> <n-upload-dragger>
<div> <div>
<n-icon size="40" color="#67c23a" v-if="fileList.length > 0 && !loading"> <n-icon size="40" color="#67c23a" v-if="fileList.length > 0 && !loading">
<FileDoneOutlined/> <FileDoneOutlined />
</n-icon> </n-icon>
<n-icon size="40" v-else> <n-icon size="40" v-else>
<CloudUploadOutlined/> <CloudUploadOutlined />
</n-icon> </n-icon>
</div> </div>
<div v-if="!self_disabled">{{ <div v-if="!self_disabled">{{
loading ? '上传中' : fileList.length > 0 ? '上传成功' : '点击或将文件拖拽到这里上传' loading ? '上传中' : fileList.length > 0 ? '上传成功' : '点击或将文件拖拽到这里上传'
}}</div> }}</div>
</n-upload-dragger> </n-upload-dragger>
</template> </template>
</n-upload> </n-upload>
<div v-if="!isBtn" class="n-upload__tip"> <div v-if="!isBtn" class="n-upload__tip">
@ -35,235 +52,235 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { import {
CloudUploadOutlined, CloudUploadOutlined,
FileDoneOutlined, FileDoneOutlined,
UploadOutlined, UploadOutlined,
PlusOutlined, PlusOutlined,
EditOutlined, EditOutlined,
DeleteOutlined, DeleteOutlined,
ZoomInOutlined, ZoomInOutlined,
} from '@vicons/antd'; } from '@vicons/antd';
import { useNotification } from 'naive-ui' import { useNotification } from 'naive-ui';
import type { UploadFileInfo } from 'naive-ui' import type { UploadFileInfo } from 'naive-ui';
import { generateUUID } from '@/utils/auth'; import { generateUUID } from '@/utils/auth';
const uploadRef = ref(); const uploadRef = ref();
import { upload } from '@/api/common'; import { upload } from '@/api/common';
// //
const props = defineProps({ const props = defineProps({
zIndex: { zIndex: {
default: -1, default: -1,
}, },
width: { width: {
default: '220px', default: '220px',
}, },
height: { height: {
default: '120px', default: '120px',
}, },
multiple: { multiple: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
isBtn: { isBtn: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
showFileList: { showFileList: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
btnTip: { btnTip: {
type: String, type: String,
default: '', default: '',
}, },
limit: { limit: {
type: Number, type: Number,
default: undefined, default: undefined,
}, },
fileLists: { fileLists: {
type: Array, type: Array,
required: true, required: true,
default: [], default: [],
}, },
disabled: { disabled: {
default: false, default: false,
}, },
fileSize: { fileSize: {
default: 200, default: 200,
}, },
orderNo: { orderNo: {
default: '', default: '',
}, },
fileType: { fileType: {
default: '', default: '',
}, },
name: { name: {
default: '', default: '',
}, },
autoUpload: { autoUpload: {
default: true, default: true,
}, },
}); });
// id // id
const uuid = ref('id-' + generateUUID()); const uuid = ref('id-' + generateUUID());
const delFlag= ref(false) const delFlag = ref(false);
const fileList = computed({ const fileList = computed({
get: () => { get: () => {
props.fileLists.map(item=>item.status='finished') props.fileLists.map((item) => (item.status = 'finished'));
return props.fileLists; return props.fileLists;
}, },
set: (val) => { set: (val) => {
emit('update:modelValue', fileList.value); emit('update:modelValue', fileList.value);
}, },
}); });
const notification = useNotification() const notification = useNotification();
// //
const self_disabled = computed(() => { const self_disabled = computed(() => {
return props.disabled; return props.disabled;
}); });
const emit = defineEmits(['upload']); const emit = defineEmits(['upload']);
const loading = ref(false); const loading = ref(false);
const handleHttpUpload = async (options) => { const handleHttpUpload = async (options) => {
if (!props.autoUpload) { if (!props.autoUpload) {
emit('upload', options); emit('upload', options);
return; return;
}
loading.value = true;
try {
const formData = new FormData();
formData.append('file', options.file.file);
formData.append('name', props.name);
const res = await upload(formData);
if (props.multiple) {
let list = JSON.parse(JSON.stringify(fileList.value));
list.push({
url: res.fileUrl,
name: res.originalName,
filePath: res.fileUrl,
fileName: res.originalName,
status:'finished'
});
emit('upload', list, props.zIndex);
} else {
emit('upload', res.fileUrl, res.originalName, props.zIndex);
} }
} catch (error) { loading.value = true;
notification.error({ try {
message: '温馨提示', const formData = new FormData();
duration:2000, formData.append('file', options.file.file);
description: '上传文件失败!', formData.append('name', props.name);
}); const res = await upload(formData);
if (props.multiple) {
let list = JSON.parse(JSON.stringify(fileList.value));
list.push({
url: res.fileUrl,
name: res.originalName,
filePath: res.fileUrl,
fileName: res.originalName,
status: 'finished',
});
emit('upload', list, props.zIndex);
} else {
emit('upload', res.fileUrl, res.originalName, props.zIndex);
}
} catch (error) {
notification.error({
message: '温馨提示',
duration: 2000,
description: '上传文件失败!',
});
if (props.multiple) {
emit('upload', fileList.value, props.zIndex);
} else {
uploadRef.value?.clear();
emit('upload', '', '', props.zIndex);
}
options.onError(error as any);
} finally {
loading.value = false;
}
};
const handleUploadChange = (data: { fileList: UploadFileInfo[] }) => {
console.log(data);
if (!delFlag.value) {
handleHttpUpload(data);
}
};
const handleRemove = (file: any) => {
delFlag.value = true;
if (props.multiple) { if (props.multiple) {
emit('upload', fileList.value, props.zIndex); emit(
'upload',
fileList.value.filter((f) => !(f.url === file.file.url)),
props.zIndex,
);
} else { } else {
uploadRef.value!.clear(); uploadRef.value?.clear();
emit('upload', '', '', props.zIndex); emit('upload', '', '', props.zIndex);
} }
options.onError(error as any); };
} finally {
loading.value = false;
}
};
const handleUploadChange= (data: { fileList: UploadFileInfo[] })=> {
console.log(data)
if(!delFlag.value) {
handleHttpUpload(data)
}
};
const handleRemove = (file: any) => { /**
delFlag.value = true * @description 文件上传之前判断
if (props.multiple) { * @param rawFile 选择的文件
emit( * */
'upload', const beforeUpload = (rawFile) => {
fileList.value.filter((f) => !(f.url === file.file.url)), const imgSize = rawFile.file.file.size / 1024 / 1024 < props.fileSize;
props.zIndex, if (!imgSize) {
);
} else {
uploadRef.value!.clear();
emit('upload', '', '', props.zIndex);
}
};
/**
* @description 文件上传之前判断
* @param rawFile 选择的文件
* */
const beforeUpload = (rawFile) => {
const imgSize = rawFile.file.file.size / 1024 / 1024 < props.fileSize;
if (!imgSize) {
notification.warning({
message: '温馨提示',
duration:2000,
description: `上传文件大小不能超过 ${props.fileSize}M`,
});
return false;
}
if (props.fileType) {
let fileType = props.fileType.replace(/\s/g, '');
fileType.split('.').join('|');
let fileIndex = rawFile.file.file.name.lastIndexOf('.');
let substrName = rawFile.file.file.name.substr(fileIndex);
if (fileType.indexOf(substrName) == -1) {
notification.warning({ notification.warning({
message: '温馨提示', message: '温馨提示',
duration:2000, duration: 2000,
description: '上传文件不符合所需的格式!', description: `上传文件大小不能超过 ${props.fileSize}M`,
}); });
return false; return false;
} }
} if (props.fileType) {
return true; let fileType = props.fileType.replace(/\s/g, '');
}; fileType.split('.').join('|');
</script> let fileIndex = rawFile.file.file.name.lastIndexOf('.');
<style lang="less" scoped> let substrName = rawFile.file.file.name.substr(fileIndex);
.file-upload-box { if (fileType.indexOf(substrName) == -1) {
flex:1; notification.warning({
:deep { message: '温馨提示',
.n-upload { duration: 2000,
>div.n-upload-trigger { description: '上传文件不符合所需的格式!',
width: v-bind(width); });
height: v-bind(height); return false;
}
}
return true;
};
</script>
<style lang="less" scoped>
.file-upload-box {
flex: 1;
:deep {
.n-upload {
> div.n-upload-trigger {
width: v-bind(width);
height: v-bind(height);
}
} }
} }
}
.n-upload__tip { .n-upload__tip {
line-height: 18px; line-height: 18px;
font-size: 12px; font-size: 12px;
margin-top: 12px; margin-top: 12px;
} }
} }
// .success-file.n-upload.n-upload-drag { // .success-file.n-upload.n-upload-drag {
// border-width: 3px; // border-width: 3px;
// border-color: #67c23a !important; // border-color: #67c23a !important;
// } // }
// .file-upload-box { // .file-upload-box {
// .my-upload-file.n-upload.n-upload-drag { // .my-upload-file.n-upload.n-upload-drag {
// height: 160px !important; // height: 160px !important;
// .n-upload { // .n-upload {
// display: flex; // display: flex;
// flex-direction: column; // flex-direction: column;
// align-items: center; // align-items: center;
// justify-content: center; // justify-content: center;
// } // }
// } // }
// .n-upload__tip { // .n-upload__tip {
// line-height: 18px; // line-height: 18px;
// font-size: 12px; // font-size: 12px;
// margin-top: 7px; // margin-top: 7px;
// } // }
// } // }
</style> </style>

View File

@ -1,14 +1,5 @@
<template> <template>
<n-modal <n-modal v-model:show="props.visible" preset="dialog" style="width: 450px" @close="dialogClose">
v-model:show="props.visible"
preset="dialog"
style="width: 450px"
@close="dialogClose"
positive-text="确定"
negative-text="取消"
@positive-click="dialogSubmit"
@negative-click="dialogClose"
>
<template #header> <template #header>
{{ dialogTitle }} {{ dialogTitle }}
</template> </template>
@ -17,7 +8,6 @@
:headers="uploadHeaders" :headers="uploadHeaders"
name="file" name="file"
ref="uploadRef" ref="uploadRef"
:default-upload="false"
@change="handleChange" @change="handleChange"
@before-upload="beforeUpload" @before-upload="beforeUpload"
v-model:file-list="fileList" v-model:file-list="fileList"
@ -39,7 +29,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getTemplateByCode } from '@/api/system/user'; import { getTemplateByCode } from '@/api/system/user';
import { computed, reactive, ref } from 'vue'; import { computed, reactive, ref, nextTick } from 'vue';
import { CloudUploadOutlined } from '@vicons/antd'; import { CloudUploadOutlined } from '@vicons/antd';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
@ -100,18 +90,19 @@
* 执行上传文件 * 执行上传文件
* @param param0 参数 * @param param0 参数
*/ */
const handleChange = ({ file }) => { const handleChange = async (file) => {
const status = file.status; if (file.file.status === 'finished') {
if (status === 'done') { let data = JSON.parse(file.event.target.response);
let data = file.response;
if (data.code != 0) { if (data.code != 0) {
await nextTick();
fileList.value = [];
message.error(data.msg || '导入失败'); message.error(data.msg || '导入失败');
} else { } else {
message.success('导入成功'); message.success('导入成功');
emit('update:visible', false); emit('update:visible', false);
emit('success'); emit('success');
} }
} else if (status === 'error') { } else if (file.file.status === 'error') {
message.error('导入失败'); message.error('导入失败');
} }
}; };

View File

@ -1,14 +1,5 @@
<template> <template>
<n-modal <n-modal v-model:show="props.visible" preset="dialog" style="width: 450px" @close="dialogClose">
v-model:show="props.visible"
preset="dialog"
style="width: 450px"
@close="dialogClose"
positive-text="确定"
negative-text="取消"
@positive-click="dialogSubmit"
@negative-click="dialogClose"
>
<template #header> <template #header>
{{ dialogTitle }} {{ dialogTitle }}
</template> </template>
@ -17,7 +8,6 @@
:headers="uploadHeaders" :headers="uploadHeaders"
name="file" name="file"
ref="uploadRef" ref="uploadRef"
:default-upload="false"
@change="handleChange" @change="handleChange"
@before-upload="beforeUpload" @before-upload="beforeUpload"
v-model:file-list="fileList" v-model:file-list="fileList"
@ -40,7 +30,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getTemplateByCode } from '@/api/system/user'; import { getTemplateByCode } from '@/api/system/user';
import { computed, reactive, ref } from 'vue'; import { computed, reactive, ref, nextTick } from 'vue';
import { CloudUploadOutlined } from '@vicons/antd'; import { CloudUploadOutlined } from '@vicons/antd';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
@ -101,18 +91,19 @@
* 执行上传文件 * 执行上传文件
* @param param0 参数 * @param param0 参数
*/ */
const handleChange = ({ file }) => { const handleChange = async (file) => {
const status = file.status; if (file.file.status === 'finished') {
if (status === 'done') { let data = JSON.parse(file.event.target.response);
let data = file.response;
if (data.code != 0) { if (data.code != 0) {
await nextTick();
fileList.value = [];
message.error(data.msg || '导入失败'); message.error(data.msg || '导入失败');
} else { } else {
message.success('导入成功'); message.success('导入成功');
emit('update:visible', false); emit('update:visible', false);
emit('success'); emit('success');
} }
} else if (status === 'error') { } else if (file.file.status === 'error') {
message.error('导入失败'); message.error('导入失败');
} }
}; };