Vue3 图片上传组件
基于 vue3 element-plus 图片上传组件封装,兄弟姐妹们,将就看一下吧,上代码,ImageUpload.vue:
<template>
<div class="component-upload-image">
<el-upload
:limit="limit"
:action="uploadFileSignleUrl"
list-type="picture-card"
ref="imageUploadRef"
:multiple="limit > 1"
:before-upload="handleBeforeUpload"
:on-preview="handlePictureCardPreview"
:http-request="uploadImg"
:on-remove="handleRemove"
:on-exceed="handleExceed"
v-model:file-list="fileList"
:class="{ hide: fileList.length >= limit }">
<el-icon class="avatar-uploader-icon"><plus /></el-icon>
</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>
<template v-if="showTipButton">
<el-button link type="primary" @click="showDiagram = !showDiagram" icon="InfoFilled">查看示意图</el-button>
</template>
<el-image class="tip-img" :src="diagram" fit="contain" :preview-src-list="[diagram]" v-if="showDiagram" :preview-teleported="true"></el-image>
<el-dialog
v-model="dialogVisible"
title="预览"
width="800px"
append-to-body
>
<img
:src="dialogImageUrl"
style="display: block; max-width: 100%; margin: 0 auto"
/>
</el-dialog>
</div>
</template>
<script setup name="ImageUpload">
import { uploadFileSignleUrl, uploadSingleFile } from '@/api/upload.js'
const props = defineProps({
// 是否显示示意图
showTipButton: {
type: Boolean,
default: false
},
// 示意图
diagram: {
type: String,
default: '',
},
modelValue: {
type:Array,
default:[]
},
// 图片数量限制
limit: {
type: Number,
default: 5,
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 5,
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["png", "jpg", "jpeg"],
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
},
});
const { proxy } = getCurrentInstance();
const emits = defineEmits(['update:modelValue']);
const showDiagram = ref(false)
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const imageUploadRef = ref(null)
const showTip = computed(
() => props.isShowTip && (props.fileType || props.fileSize)
);
const fileList = computed({
get: () => props.modelValue,
set: (val) => {
emits('update:modelValue', val)
}
});
// 格式化
const getFormData = (filename,file) =>{
const formData = new FormData();
// const name = file.name.replace(/\.[a-zA-Z]+$/g,'') + '_'+ new Date().getTime() // 带上时间戳,避免文件地址重复被覆盖
// formData.append('name', name);
formData.append(filename, file);
return formData
}
// 文件上传
const uploadImg = (file)=>{
proxy.$modal.loading("上传中")
const data = getFormData(file.filename,file.file)
uploadSingleFile(data).then(res=>{
if(res.code == 200 && res.data){
if(res.data.url){
let current = fileList.value.find(z=>z.uid == file.file.uid)
current.status = 'success'
current.url = res.data.url
current.ossId = res.data.ossId
current.fileName = res.data.fileName
}
}else{
const index = fileList.value.findIndex(z=>z.uid == file.file.uid)
fileList.value.splice(index,1)
proxy.$modal.msgError(res.msg || '发生错误,请稍后重试!')
}
proxy.$modal.closeLoading()
}).catch(error=>{
const index = fileList.value.findIndex(z=>z.uid == file.file.uid)
fileList.value.splice(index,1)
proxy.$modal.closeLoading()
proxy.$modal.msgError(
error && typeof error == 'object'
? error.statusText || error.message || JSON.stringify(error)
: error || '发生错误,请稍后重试!'
)
})
}
// 上传前loading加载
function handleBeforeUpload(file) {
try {
let isImg = false;
if (props.fileType.length) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
isImg = props.fileType.some(type => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
} else {
isImg = file.type.indexOf("image") > -1;
}
if (!isImg) {
proxy.$modal.msgError(
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
);
return false;
}
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
return false;
}
}
proxy.$modal.loading("正在上传图片,请稍候...");
} catch (error) {
proxy.$modal.closeLoading();
console.log(error)
}
}
// 文件个数超出
function handleExceed() {
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
}
// 预览
function handlePictureCardPreview(file) {
dialogImageUrl.value = file.url;
dialogVisible.value = true;
}
// 文件删除回调
const handleRemove = (file) => {
}
// 格式化文件
const fileStringToList =(fileStr)=>{
if(fileStr && fileStr.length >0){
return fileStr.split(',').map(url=>{
return { name : url.split('/').pop(), url : url }
})
}else{
return []
}
}
const fileListToString = (fileList)=>{
if(fileList && fileList.length >0){
return fileList.map(z=>z.url).join(',')
}else{
return ''
}
}
defineExpose({
fileStringToList,
fileListToString
})
</script>
<style scoped lang="scss">
:deep(.hide .el-upload--picture-card) {
display: none;
}
</style>
作者:胡倩倩0903
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
posted on 2023-05-08 14:44 kitty20180903suzhou 阅读(619) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)