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

news2025/2/24 15:22:11

上传图片组件踩坑记录

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/619259.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux(信号产生中)代码来验证

我们应该如何理解我们调用系统接口并不是简单的调用系统接口这么简单就完事了---我们有时候也是需要使用由操作系统为我们提供的操作系统的层面的数据类型 sigset_t 我们来介绍一种类型&#xff0c;从我们之前学的图来看&#xff0c;每一个信号不管是在block表还是在pending表…

鄂尔多斯市政务协同办公平台,让全市政务更协同高效

近年来&#xff0c;国家高度重视数字政务建设&#xff0c;以数字化推进国家治理体系和治理能力现代化&#xff0c;助力建设人民满意的服务型政府。 2018年&#xff0c;国务院办公厅印发《进一步深化“互联网政务服务”推进政务服务“一网、一门、一次”改革实施方案》&#xf…

这份阿里巴巴内部Spring Cloud Alibaba全套笔记,几乎涵盖了所有操作

Spring Cloud Alibaba 是阿里巴巴提供的微服务开发一站式解决方案&#xff0c;是阿里巴巴开源中间件与 Spring Cloud 体系的融合。 Springcloud 和 Srpingcloud Alibaba 区别&#xff1f; SpringCloud&#xff1a; 部分组件停止维护和更新&#xff0c;给开发带来不便;SpringCl…

缓存数据一致性探究

缓存是一种较低成本提升系统性能的方式&#xff0c;自它面世第一天起就备受广大开发者的喜爱。然而正如《人月神话》中的那句经典的“没有银弹”中所说&#xff0c;软件工程的设计没有银弹。 就像每一次发布上线修复问题的同时&#xff0c;也极易引入新的问题&#xff0c;自缓存…

一文让你明白软件测试该怎样入门?

我认为入门软件测试需要四个方面的知识or技能&#xff0c;它们是&#xff1a;业务知识、职业素养、基础知识、技术知识。 职业素养是一切的根基&#xff0c;因为人在职场就必须拥有必要的职业素养&#xff0c;软件测试工程师也不例外。基础知识和技术知识是两大支柱&#xff0…

【正点原子STM32连载】 第二十九章 DMA实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十…

第26节:cesium 高程数据下载(含源码+视频)

本节主要讲解高程dem数据下载方式 下载网址1: http://srtm.csi.cgiar.org/download 下载较慢,含全球高程数据 下载网站2:地理空间数据云 下载速度快,中国科学院计算机网络信息中心公布数据,正式可靠 下面主要介绍地理空间数据云的下载方式。 1.登录 2.选择高级检索 3.选择数…

【改进的多同步挤压变换】基于改进多同步挤压的高分辨率时频分析工具,用于分析非平稳信号(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

一份配置轻松搞定表单渲染,配置式表单渲染器在袋鼠云的实现思路与实践

前段时间&#xff0c;袋鼠云离线开发产品接到改造数据同步表单的需求。 一方面&#xff0c;数据同步模块的代码可读性和可维护性较差&#xff0c;导致在数据同步模块开发新功能和定位问题的效率很低。另一方面&#xff0c;整体规划上&#xff0c;希望在对接新的数据源时&…

Mac版好用虚拟机CrossOver22.1.1,耗时时间少,加快办事效率

Mac系统仅适配自己的硬件&#xff0c;它的软件需要通过app store购买&#xff0c;所以很多Mac用户也为之烦恼。这种模式优点是稳定性与性能超强发挥&#xff0c;缺点也显而易见。 那该如何解决这一困扰呢&#xff1f;一般&#xff0c;我们会选择安装虚拟机软件&#xff0c;但这…

本地使用AutoML-nni进行超参数调优实验

目的&#xff1a;在自己的代码中NNI工具&#xff0c;进行超参数自动调优训练自己的项目&#xff0c;得到精度最高的一组超参数。 nni地址&#xff1a; GitHub - microsoft/nni: An open source AutoML toolkit for automate machine learning lifecycle, including feature e…

短视频矩阵视频智能剪辑源代码.源代码

短视频矩阵视频智能剪辑&#xff1a; * 添加/编辑视频 */ public function addVideoAction(){ $this->useLayout(dydqtshoppc-head.html); $id $this->request->getIntParam(id); //获取视频信息 $Video_model new App_Mod…

c++包管理器,不用每次都源码编译

pkg-config linux中的包管理器 例如opencv.pc文件&#xff0c;详细描述了库的使用依赖。cmake的find_package支持pc文件的查找 prefix/usr/local exec_prefix${prefix} includedir/usr/local/include libdir/usr/local/libName: OpenCV Description: Open Source Computer Vi…

矿工挖宝-第14届蓝桥杯国赛Scratch真题初中级组第4题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第146讲。 矿工挖宝&#xff0c;本题是2023年5月28日上午举行的第14届蓝桥杯国赛Scratch图形化编程初中级组真题第4题&…

MySQL(进阶篇3.0)

锁 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算机资源&#xff08;CPU、RAM、I/O&#xff09;的争用之外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…

十五、实例化

第一部分 概念&#xff1a; 1&#xff09;引入 OpenGL ES 实例化&#xff08;Instancing&#xff09;是一种只调用一次渲染函数就能绘制出很多物体的技术&#xff0c;可以实现将数据一次性发送给 GPU &#xff0c;告诉 OpenGL ES 使用一个绘制函数&#xff0c;将这些数据绘制…

练习:有限状态机测试

练习&#xff1a;有限状态机测试 1 FSM 示例 在练习中&#xff0c;我们将使用两个 FSM。 两者都有输入字母 X {a, b} 和输出字母 Y {0,1}。 第一个 FSM 将称为 M1 并由以下有向图表示。 对于上面给出的每个 FSM Mi&#xff1a; 1.确定以下值&#xff0c;显示您的工作。 (a…

[MySQL]不就是SQL语句

前言 本期主要的学习目标是SQl语句中的DDL和DML实现对数据库的操作和增删改功能&#xff0c;学习完本章节之后需要对SQL语句手到擒来。 1.SQL语句基本介绍 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系型数据库的编程语言。它允许用户在数据库中存…

AngularJs学习笔记--unit-testing

javascript是一门动态类型语言&#xff0c;这给她带来了很强的表现能力&#xff0c;但同时也使编译器几乎不能给开发者提供任何帮助。因为这个原因&#xff0c;我们感受到编写任何javascript代码都必须有一套强大完整的测试。angular拥有许多功能&#xff0c;让我们更加容易地测…

如何编写接口测试用例?测试工程师必备技能!

自动化始终只是辅助测试工作的一个手段&#xff0c;对于测试人员而言&#xff0c;测试基础和测试用例的设计才是核心。如果测试用例的覆盖率或者质量不高&#xff0c;那将这部分用例实现为自动化用例的意义也就不大了。 那么&#xff0c;接口测试用例应该怎么编写呢&#xff1f…