父组件
<!-- 文件上传组件 -->
<template>
<div>
<el-upload
:class="{ hide: props.fileList?.length>=props.limit }"
:action="uploadUrl"
:accept="accept"
v-model:file-list="waitFileList"
list-type="picture-card"
:before-upload="beforeUploadHandle"
:on-success="successHandle"
:on-preview="handlePictureCardPreview"
:on-error="handleError"
:on-remove="handleRemove"
>
<el-icon class="avatar-uploader-icon"><Plus /></el-icon>
<template v-if="tip" #tip>
<span class="tip"> {{ tip }}</span>
</template>
</el-upload>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getToken } from '@/utils/cache'
import { useAppStore } from '@/store'
import { IObject } from "@/types/interface";
// 租户id和code
const store = useAppStore()
const { state } = store
const uploadUrl = computed(() => {
return `${import.meta.env.VITE_APP_API}/sys/oss/upload?token=${getToken()`
})
/**
* accept 文件类型
* limit 文件数量限制
* tip 提示文案
*/
const props = defineProps({
fileList: {
default: [],
type: Array
},
accept: {
type: String,
default: 'image/jpeg,image/jpg,image/png'
},
limit: {
type: Number,
default: 5
},
tip: String
})
let waitFileList:any = ref([])
waitFileList.value = props.fileList
watch(
() => props.fileList,
() => {
waitFileList.value = props.fileList
}
)
const emit = defineEmits(["uploadSuccess","uploadChange"])
const getUrlParams = (url:string) => {
let urlStr = url.split('?')[1]
const urlSearchParams = new URLSearchParams(urlStr)
const result = Object.fromEntries(urlSearchParams.entries())
return result
}
// 校验文件类型
const beforeUploadHandle = (rawFile:any) => {
if (rawFile.type !== 'image/jpeg'&&rawFile.type !== 'image/jpg'&&rawFile.type !== 'image/png') {
ElMessage.error('请上传jpeg或jpg或png格式的图片!')
return false
} else if (rawFile.size / 1024 / 1024 > 10) {
ElMessage.error('上传图片大小不能超过 10MB!')
return false
}
return true
}
// 上传成功
const successHandle = (res: IObject, file: IObject, list: IObject[]) => {
if (res.code !== 0) {
waitFileList.value.pop()
return ElMessage.error(res.msg)
}
emit("uploadSuccess", {
name: getUrlParams(res.data.src).filename,
url: res.data.src
})
ElMessage.success({
message: '上传成功'
})
}
const handleError = ()=>{
ElMessage.error('上传失败')
}
const handleRemove = (uploadFile:any,uploadFiles:any)=>{
const obj = props.fileList.filter((item:any)=>item.name!==uploadFile.name)
emit("uploadChange", obj)
}
// 显示图片
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const handlePictureCardPreview = (uploadFile:IObject) => {
dialogImageUrl.value = uploadFile.url
dialogVisible.value = true
}
</script>
<style lang="less" scoped>
:deep(.el-upload-list__item.is-success:focus:not(:hover)){
display: none !important;
}
:deep(.hide .el-upload--picture-card) {
display: none;
}
.tip{
color: #999999;
font-size: 14px;
padding-left: 12px;
display: inline-block;
transform: translateY(15px);
}
</style>
子组件
<vpImgUpload :fileList="replyImg" @uploadSuccess="handleUploadSuccess" @uploadChange="handleUploadChange"></vpImgUpload>
const handleUploadSuccess = (file:any)=>{
replyImg.value.push(file)
}
const handleUploadChange = (files:any)=>{
replyImg.value = files
}