在我们开发项目中,如果遇到文件上传时,这时候我们如果来回使用element-plus的文件上传,页面需要来回引入,这是可以自己进行手动封装文件上传的组件进行调用使用
限制上传类型只能为png、jpg

限制上传类型只能为pdf

调用接口上传成功

1、首先下载element-plus
npm install element-plus --save
2、在main.js引入并全局注册封装的上传文件组件
import { createApp, Vue } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import App from './App.vue';
const app = createApp(App)
import FileUpload from "@/components/FileUpload/fileIndex.vue";
app.component("FileUpload", FileUpload);
app.use(ElementPlus)
app.mount('#app')
3、封装组件代码:
<template>
<div class="upload-file">
<el-upload multiple :action="uploadFileUrl" :data="fileData" :before-upload="handleBeforeUpload"
:file-list="fileList" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed"
:on-success="handleUploadSuccess" :on-progress="handleProgress" :show-file-list="false" :headers="headers"
class="upload-file-uploader" ref="upload">
<slot>
<el-button type="primary">选取文件</el-button>
</slot>
</el-upload>
<div class="el-upload__tip" v-if="showTip">
请上传
<template v-if="fileSize">
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
</template>
<template v-if="fileType">
格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
</template>
的文件
</div>
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"
v-if="showFileList">
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content"
v-for="(file, index) in fileList">
<el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
<span class="document">
{{ getFileName(file.name) }}
</span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
</div>
</li>
</transition-group>
<div class="flex flex-direction justify-center align-center" v-if="upLoading"
style="position: fixed;top: 0;bottom: 0;left: 0;right: 0;height: 100vh;width: 100vw;z-index: 9999999;background-color: rgba(0,0,0,0.8);">
<div v-loading="upLoading" element-loading-text="" element-loading-background="rgba(0, 0, 0, 0)"
style="width: 10px;height: 10px;"></div>
<span style="font-size: 16px;color: var(--el-color-primary);margin-top: 40px;">上传进度:{{ upProgress }}%</span>
</div>
</div>
</template>
<script setup>
import { genFileId ,ElMessage } from 'element-plus'
import { computed, getCurrentInstance, reactive, ref, watch } from "vue";
const props = defineProps({
modelValue: [String, Object, Array],
limit: {
type: Number,
default: 0,
},
fileSize: {
type: Number,
default: 0,
},
fileType: {
type: Array,
default: ['pdf','png','jpg'],
},
isShowTip: {
type: Boolean,
default: false,
},
isExceed: {
type: Boolean,
default: false,
},
showFileList: {
type: Boolean,
default: true,
},
source: {
type: String,
default: "",
}
});
const { proxy } = getCurrentInstance();
const emit = defineEmits();
const upload = ref()
const num = ref(0);
const uploadList = ref([]);
const baseUrl = "";
const uploadFileUrl = "";
const headers = { Authorization: "Bearer " };
const fileList = ref();
const upLoading = ref(false)
const upProgress = ref(0)
const showTip = computed(
() => props.isShowTip && (props.fileType || props.fileSize)
);
const fileData = reactive({
'source': props.source
})
watch(
() => props.modelValue,
(val) => {
if (val) {
let temp = 1;
const list = Array.isArray(val)
? val
: (props.modelValue?.toString().split(","));
fileList.value = list.map((item) => {
if (typeof item === "string") {
item = { name: item, url: item };
}
item.uid = item.uid || new Date().getTime() + temp++;
return item;
});
} else {
fileList.value = [];
return [];
}
},
{ deep: true, immediate: true }
);
const handleBeforeUpload = (file) => {
if (props.fileType.length) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
const isTypeOk = props.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
if (!isTypeOk) {
ElMessage.error(
`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`
);
return false;
}
}
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
ElMessage.error(`上传文件大小不能超过 ${props.fileSize} MB!`);
return false;
}
}
upLoading.value = true;
num.value++;
return true;
};
const handleExceed = (files) => {
if (props.isExceed) {
upload.value.clearFiles()
const file = files[0]
file.uid = genFileId()
upload.value.handleStart(file)
upload.value.submit()
} else {
ElMessage.error(`上传文件数量不能超过 ${props.limit} 个!`);
}
};
const handleUploadError = (err) => {
upload.value = false
ElMessage.error("上传文件失败");
};
const handleUploadSuccess = (res, file) => {
if (res.code == 200) {
upLoading.value = false
uploadList.value.push({ name: res.fileName, url: res.fileName });
if (uploadList.value.length === num.value) {
fileList.value = fileList.value
.filter((f) => f.url !== undefined)
.concat(uploadList.value);
uploadList.value = [];
num.value = 0;
emit("update:modelValue", listToString(fileList.value));
emit("uploadSuccess");
ElMessage.closeLoading();
}
} else {
ElMessage.error(res.msg);
}
};
const handleProgress = (evt, uploadFile, uploadFiles) => {
upProgress.value = Math.round((evt.percent * 100)) / 100
}
const handleDelete = (index) => {
fileList.value.splice(index, 1);
emit("update:modelValue", listToString(fileList.value));
};
const getFileName = (name) => {
console.log('name', name);
if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1);
} else {
return "";
}
};
const listToString = (list, separator) => {
let strs = "";
separator = separator || ",";
for (let i in list) {
if (undefined !== list[i].url) {
strs += list[i].url + separator;
}
}
return strs !== "" ? strs.substring(0, strs.length - 1) : "";
};
</script>
<style scoped lang="scss">
.upload-file-uploader {
margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {
padding: 20px 0;
border: 1px solid #e4e7ed;
line-height: 2;
margin-bottom: 10px;
position: relative;
}
.upload-file-list .ele-upload-list__item-content {
display: flex;
justify-content: space-between;
align-items: center;
color: inherit;
padding: 2px 12px;
}
.ele-upload-list__item-content-action .el-link {
margin-left: 16px;
}
</style>
4、页面中引入使用:
<template>
<FileUpload v-model="projectFile" :fileType="['png','jpg']" :source="'sys_sys_upload_release'">
<el-button>+ 上传</el-button>
</FileUpload>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
const projectFile = ref<any>([])
</script>
<style lang="scss"></style>