导入优化

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

View File

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

View File

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

View File

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