最初的写法如下,在本地跑的时候每上传一张图片调一次接口,虽然图片回显正常了,但是每次都会自动多调一个如下图所示的apply-login
报错404,部署到测试环境后,就是每次都报错,图片也不会正常回显。
<el-upload
ref="uploadImgRef"
action="#"
v-model:file-list="list"
list-type="picture-card"
:multiple="multiple"
:accept="acceptType"
:before-upload="beforeUpload"
:on-preview="handlePreview"
:on-remove="handleRemove"
:disabled="disabled"
:class="{ disabled: uploadDisabled }"
>
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
if (Number(props.size) && rawFile.size / 1024 / 1024 > Number(props.size)) {
ElMessage.error('上传的图片不能大于' + props.size + 'M')
return false
}
handleUpload(rawFile)
}
在网上百度了一下后,改为手动上传,并把之前绑定before-upload方法改成绑定on-change方法,倒是不再出现上述的 apply-login
了,可是又遇到了新的问题,就是使用on-change后上传单张图片却执行了两次,代码和效果图如下:
<el-upload
ref="uploadImgRef"
action="#"
v-model:file-list="list"
list-type="picture-card"
:multiple="multiple"
:accept="acceptType"
:auto-upload="false"
:on-change="handleChange"
:on-preview="handlePreview"
:on-remove="handleRemove"
:disabled="disabled"
:class="{ disabled: uploadDisabled }"
>
// 上传
const handleChange = (files: any, fileList: any) => {
if (Number(props.size) && files.size / 1024 / 1024 > Number(props.size)) {
ElMessage.error('上传的图片不能大于' + props.size + 'M')
return false
}
handleUpload(files.raw)
}
将 v-model:file-list
改为 :file-list
,这样就解决了上传一张图片却出现重复的两张图的问题,但是需要注意的是去掉 v-model
后,上传一张图片然后再删除这张图片时,会出现图片删了但是绑定的数组list长度并未更新的问题,所以删除图片那里需要再额外处理一下。
调整后的完整代码如下:
<template>
<div class="custom-upload-img">
<el-upload
ref="uploadImgRef"
action=""
:file-list="list"
list-type="picture-card"
:multiple="multiple"
:accept="acceptType"
:auto-upload="false"
:on-change="handleChange"
:on-preview="handlePreview"
:on-remove="handleRemove"
:disabled="disabled"
:class="{ disabled: uploadDisabled }"
>
<div class="upload-box">
<img class="upload-img" src="~@/assets/img/icon-add.png" alt="" />
<div class="upload-title">上传图片div>
div>
el-upload>
<el-dialog v-model="dialogVisible">
<div class="preview-img-box"><img w-full class="preview-img" :src="dialogImageUrl" alt="Preview Image" />div>
el-dialog>
div>
template>
<script lang="ts" setup>
import { ref, computed, PropType } from 'vue'
import { ElMessage } from 'element-plus'
import type { UploadProps, UploadUserFile } from 'element-plus'
import { simpleSystemUploadResFile } from '@/api/common'
const props = defineProps({
acceptType: {
type: String,
default: 'image/*'
},
multiple: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
size: {
type: [String, Number],
default: ''
},
list: {
type: Array as PropType<UploadUserFile[]>,
default: () => []
}
})
const uploadImgRef = ref<any>()
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
// 抛出事件
const emits = defineEmits(['changeFile', 'removeFile'])
// 监听禁用
const uploadDisabled = computed(() => {
return props.disabled
})
// 上传
const handleChange = (files: any, fileList: any) => {
if (Number(props.size) && files.size / 1024 / 1024 > Number(props.size)) {
ElMessage.error('上传的图片不能大于' + props.size + 'M')
return false
}
handleUpload(files.raw)
}
// 移除
const handleRemove: UploadProps['onRemove'] = (uploadFile: any, uploadFiles) => {
emits('removeFile', uploadFile, uploadFiles)
}
// 预览
const handlePreview: UploadProps['onPreview'] = uploadFile => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
// 上传附件
const handleUpload = (e: any) => {
let params = new FormData()
params.append('file', e)
params.append('systemKey', 'lecturer')
simpleSystemUploadResFile(params)
.then(res => {
let imgList: any = props.list || []
imgList.push({
uid: e.uid,
url: res.data.url,
name: res.data.objectName
})
emits('changeFile', imgList)
})
.catch(err => {})
}
script>
<style lang="scss">
.custom-upload-img {
width: 100%;
.ep-upload--picture-card {
width: 112px;
height: 112px;
border: 1px solid $border-color;
border-radius: 0;
background-color: #f2f3f5;
}
.ep-upload-list__item {
width: 112px;
height: 112px;
border-radius: 0;
}
.ep-upload-list--picture-card .ep-upload-list__item-thumbnail {
object-fit: cover;
}
.ep-icon--close-tip {
display: none;
}
.ep-upload-list__item.is-success:focus:not(:hover) .ep-icon--close-tip {
display: none;
}
// 隐藏上传以及删除时得效果
.disabled {
.ep-upload--picture-card {
display: none !important;
}
.el-upload-list__item {
transition: none !important;
}
}
.ep-overlay-dialog .ep-dialog .ep-dialog__body {
margin: 16px;
font-size: 0;
}
}
style>
<style lang="scss" scoped>
.custom-upload-img {
.upload-box {
font-size: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.upload-title {
font-size: 14px;
color: #86909c;
line-height: 22px;
margin-top: 8px;
}
.upload-img {
width: 24px;
height: 24px;
}
}
.preview-img-box {
display: flex;
justify-content: center;
align-items: center;
.preview-img {
width: 100%;
object-fit: cover;
}
}
}
style>
<el-form ref="certificateFormRef" :inline="true" label-width="88px" :model="certificateForm" :rules="certificateRules">
<el-form-item label="荣誉证书" prop="honorCertificate">
<CustomUploadImg :list="certificateForm.honorCertificate" multiple @changeFile="changeHonorFile" @removeFile="removeHonorFile" />
el-form-item>
el-form>
const certificateForm = reactive({
honorCertificate: []
})
// 上传荣誉证书
const changeHonorFile = (data: any) => {
certificateForm.honorCertificate = data
}
// 移除荣誉证书
const removeHonorFile = (file: any, files: any) => {
let id = file.uid
let arr = certificateForm.honorCertificate || []
if (id && arr.length) {
arr.map((item: any, index: number) => {
if (item.uid && item.uid === id) {
certificateForm.honorCertificate.splice(index, 1)
}
})
}
}