Element-Plus el-upload组件批量上传图片问题记录

上传图片组件踩坑记录

1. 第一次尝试

最初的写法如下,在本地跑的时候每上传一张图片调一次接口,虽然图片回显正常了,但是每次都会自动多调一个如下图所示的apply-login 报错404,部署到测试环境后,就是每次都报错,图片也不会正常回显。

1.1 初始代码

<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)
}

1.2 初始效果

在这里插入图片描述

2. 第二次尝试

在网上百度了一下后,改为手动上传,并把之前绑定before-upload方法改成绑定on-change方法,倒是不再出现上述的 apply-login 了,可是又遇到了新的问题,就是使用on-change后上传单张图片却执行了两次,代码和效果图如下:

2.1 第二次代码

<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)
}

2.2 第二次效果

在这里插入图片描述

2.3 解决方法

v-model:file-list 改为 :file-list,这样就解决了上传一张图片却出现重复的两张图的问题,但是需要注意的是去掉 v-model 后,上传一张图片然后再删除这张图片时,会出现图片删了但是绑定的数组list长度并未更新的问题,所以删除图片那里需要再额外处理一下。

3. 第三次尝试

调整后的完整代码如下:

组件代码:

<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)
            }
        })
    }
}

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>