Vue2移动端(H5项目)项目基于vant封装图片上传组件(支持批量上传、单个上传、回显、删除、预览、最大上传数等功能)---解决批量上传问题

news2024/9/22 1:45:01

一、最终效果

在这里插入图片描述

二、参数配置

1、代码示例:

<t-upload
   @fileList="fileList"
    :showFileList="showFileList"
    @showFile="showFile"
    :showFileUrl="showFileUrl"
  />

2、配置参数(TUpload Attributes)继承van-uploader的属性

参数说明类型默认值
limitSize限制上传文件大小Number10MB
fileType限制上传的文件类型String.jpg,.jpeg,.png
totalLimit最多上传个数限制Number5
showFileList回显文件的list(内含:url–>对应完整路径)Array-
showFileUrl上传组件回显图片–相对路径数据(后台需要)Array-
savePath服务器上传地址String自己的上传地址

3、events 事件继承van-uploader的事件

事件名说明返回值
fileList上传成功或删除成功触发返回最终上传数据
showFile回显list删除后触发返回回显上传没有删除的数据

三、具体页面使用

<template>
  <div class="initial_Judgment">
    <div class="img_box">
        <div class="img_title">
          终判图
        </div>
        <t-upload
          :showFileUrl="showFileUrl"
          :showFileList="showFileList"
          @fileList="fileList"
          @showFile="showFile"
        />
      </div>
  </div>
</template>
<script>
export default {
  name: 'initialJudgment',
  data() {
    return {
      formData: {
        images: [], //上传图片
      },
      showFileList: [], // 上传组件--回显内含url且是完整地址
      showFileUrl: [], // 上传组件回显图片--相对路径数据
    }
  },
  created() {
    this.getFinalInfo()
  },
  methods: {
    // 获取详情信息
    async getFinalInfo() {
      const res = await this.$api.getFinalInfo(this.$route.query.id)
      console.log('详情数据', res)
      if (res.success) {
        if (res.data.finalImages.length > 0) {
          this.showFileList = res.data.finalImages || []
          this.showFileUrl = res.data.finalImages.map(item => item.relativeUrl)
        }
      }
    },
    // 回显数据删除触发
    showFile(list) {
      this.showFileUrl = list
    },
    // 上传成功或删除触发
    fileList(list) {
      this.formData.images = list
    },
    // 点击确认
    async handlerConfirm() {
      const { warehouseSpaceId, receveMethod, images } = this.formData;
      const requiredFields = [
        { field: warehouseSpaceId, message: '请先选择卸货料垛' },
        { field: receveMethod, message: '请先选择收货方式' },
        { field: images.length || this.showFileUrl.length, message: '请先上传图片' }
      ];
      const hasEmptyFields = requiredFields.some(field => !field.field);
      if (hasEmptyFields) {
        this.$toast(requiredFields.find(field => !field.field).message);
        return;
      }
      let params = {
        ...this.formData,
      }
      params.images = [...this.showFileUrl, ...this.formData.images]
      console.log('最终参数---图片相对路径', params.images)
      // console.log('最终参数---', params)
      // return
      this.$dialog
        .confirm({
          message: '是否确认终判?'
        })
        .then(async () => {
          const res = await this.$api.finalConfirm(params)
          if (res.success) {
            this.$toast.success('确认成功')
            this.$router.push({ path: '/endJudgingScrapSteel' })
          }
        })
        .catch(() => {
          console.log('取消')
        })
    }
  },
};
</script>

四、源码

<template>
  <van-uploader
    class="t-upload"
    v-model="fileList"
    v-bind="uploadAttrs"
    v-on="$listeners"
    :before-read="beforeRead"
    :before-delete="delImg"
    :after-read="afterRead"
  />
</template>

<script>
import axios from 'axios'
import { getToken } from '@/utils/auth'
export default {
  name: 'TUpload',
  props: {
    // 限制上传文件大小默认10MB
    limitSize: {
      type: [Number, String],
      default: 10
    },
    // 限制上传的文件类型
    fileType: {
      type: String,
      default: '.jpg,.jpeg,.png'
    },
    // 最多上传个数限制
    totalLimit: {
      type: Number,
      default: 5
    },
    // 回显文件的list(内含:url-->对应完整路径)
    showFileList: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 上传组件回显图片--相对路径数据
    showFileUrl: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 服务器上传地址
    savePath: {
      type: String,
      default: `${process.env.VUE_APP_API_URL}/scmpda/file/upload`
    },
  },
  data() {
    return {
      fileList: [],
      fileUrls: [],
      showUrl: this.showFileUrl
    }
  },
  computed: {
    uploadAttrs() {
      return {
        'max-count': this.totalLimit,
        multiple: true,
        ...this.$attrs
      }
    }
  },
  watch: {
    showFileList: {
      handler(val) {
        this.fileList = val
      }
    },
    showFileUrl: {
      handler(val) {
        this.showUrl = val
      }
    }
  },
  methods: {
    beforeRead(file) {
      // console.log('上传前', file)
      if (file instanceof Array) {
        file.forEach(item => {
          const isNotMatchType = this.fileType.indexOf('.' + item.name.slice(item.name.lastIndexOf('.') + 1).toLocaleLowerCase()) === -1
          if (isNotMatchType) {
            this.$toast.fail('请上传jpg或png格式的图片')
            return false
          }
          const overSize = item.size / (1024 * 1024) > this.limitSize
          if (overSize) {
            this.$toast.fail(`上传文件不得大于${this.limitSize}MB`)
            return false
          }
        })
      } else {
        const isNotMatchType = this.fileType.indexOf('.' + file.name.slice(file.name.lastIndexOf('.') + 1).toLocaleLowerCase()) === -1
        if (isNotMatchType) {
          this.$toast.fail('请上传jpg或png格式的图片')
          return false
        }
        const overSize = file.size / (1024 * 1024) > this.limitSize
        if (overSize) {
          this.$toast.fail(`上传文件不得大于${this.limitSize}MB`)
          return false
        }
      }
      if (file.length >= this.totalLimit) {
        this.$toast.fail(`最多上传${this.totalLimit}个文件`)
        return false
      }
      return true
    },
    delImg(fileMsg) {
      const delIndex = this.fileList.findIndex(item => item === fileMsg);
      if (delIndex > -1) {
        this.fileList.splice(delIndex, 1);
        const showIndex = delIndex - this.showFileList.length;
        if (fileMsg.url) {
          this.showUrl.splice(showIndex, 1);
        } else {
          this.fileUrls.splice(showIndex, 1);
        }
      }
      this.$emit(fileMsg.url ? 'showFile' : 'fileList', fileMsg.url ? this.showUrl : this.fileUrls);
    },
    afterRead(file) {
      if (file instanceof Array) {
        file.forEach(f => {
          f.status = 'uploading'
          f.message = '上传中...'
          this.uploadFile(f)
        })
      } else {
        file.status = 'uploading'
        file.message = '上传中...'
        this.uploadFile(file)
      }
    },
    async uploadFile(file) {
      const formDataFile = new FormData()
      formDataFile.append('file', file.file)
      const res = await axios({
        url: this.savePath,
        method: 'post',
        headers: {
          'Content-Type': 'multipart/form-data',
          Authorization: getToken()
        },
        data: formDataFile
      })
      if (res.data.success) {
        file.status = 'done'
        file.message = '上传成功'
        this.fileUrls.push(res.data.data)
        this.$toast('图片上传成功!')
        this.$emit('fileList', this.fileUrls)
      } else {
        file.status = 'failed'
        file.message = '上传失败'
        this.$toast('照片上传失败,请重新上传!')
      }
    }
  }
}
</script>

相关文章

基于ElementUi再次封装基础组件文档


基于ant-design-vue再次封装基础组件文档


vue3+ts基于Element-plus再次封装基础组件文档

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

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

相关文章

vulnhub系列:DC-1

vulnhub系列&#xff1a;DC-1 靶机下载 一、信息收集 nmap 扫描存活&#xff0c;根据 mac 地址寻找 IP nmap 192.168.23.0/24nmap 扫描端口 nmap 192.168.23.141 -p- -Pn -sV -Odirsearch 目录扫描 python3 dirsearch.py -u http://192.168.23.141/访问80端口 查看 wappa…

数据资产三次入表理论

数据资产三次入表理论 数据资产入表三大阶段详见图。 初次入表&#xff1a;底层资产入表 初次入表主要指的是企业将已实际形成的底层原始数据资源&#xff0c;按照《企业数据资源相关会计处理暂行规定》的要求&#xff0c;首次纳入会计层面的企业资产库。这一阶段工作的完成&am…

8.16 day bug

bug1 题目没看仔细 额外知识 在 Bash shell 中&#xff0c;! 符号用于历史扩展功能。当你在命令行中输入 ! 后跟一些文本时&#xff0c;Bash 会尝试从你的命令历史中查找与该文本相匹配的命令。这是一种快速重用之前执行过的命令的方法。 如何使用历史扩展 基本用法: !strin…

进程间通信—无名管道

gg shiftg快速对齐 加锁顺序问题时&#xff0c;如果解锁了&#xff0c;两个同时申请抢锁&#xff0c;谁抢到了运行谁&#xff0c;循环迭代时释放锁也是同时申请锁&#xff0c;循环部分如果没抢到锁就进入循环等待 总结: IPC 进程间通信 interprocess communicate //signal…

【阿卡迈防护分析】Vueling航空Akamai破盾实战

文章目录 1. 写在前面2. 风控分析3. 破盾实战 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…

Elasticsearch新增和删除索引中的字段

在ES中&#xff0c;增加字段相对比较容易&#xff0c;因为ES支持动态映射&#xff08;Dynamic Mapping&#xff09;。 当索引中新增文档时&#xff0c;ES可以根据文档中的字段自动创建对应的映射关系。如果新字段类型与已有字段类型不同&#xff0c;ES会自动将已有字段类型转换…

2024-2025年最值得选的Java计算机毕业设计选题大全:800个热门选题

一、前言 博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ…

选择排序(附动图)

1.思路 基本思想&#xff1a; 每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完 。 1.1双向选择排序&#xff08;升序&#xff09; 头尾指针&#xff08;索引&#xf…

Excel求和方法之

一 SUM&#xff08;&#xff09;&#xff0c;选择要相加的数,回车即可 二 上面的方法还不够快。用下面这个 就成功了 三 还有一种一样快的 选中之后&#xff0c;按下Alt键和键&#xff08;即Alt&#xff09;

三种生成模型

三种生成模型&#xff08;GAN,VAE,FLOW&#xff09; 什么是生成模型&#xff1f; 图像、文本、语音等数据&#xff0c;都可以看做是从一个复杂分布中采样得到的。 一个简单的分布随机分布,经过一系列复杂的变换(Generator)之后变成复杂分布. 从简单分布中随机采样一个z,经过G后…

新版本源2.0大模型发布:Yuan2-2B-July-hf

​ 引言 近日&#xff0c;浪潮信息的新一代基础语言大模型源2.0 迎来了重要更新。浪潮信息正式发布了 Yuan2-2B-July-hf 模型&#xff0c;标志着源2.0系列模型在性能和功能上的进一步提升。这一版本将为开发者和研究人员提供更强大的工具&#xff0c;以满足各种语言处理需求。…

武汉流星汇聚:携手亚马逊,全球电商中破浪前行,跨境业务加速崛起

在全球电商的浩瀚星空中&#xff0c;亚马逊无疑是最耀眼的星辰之一&#xff0c;其无与伦比的市场规模、卓越的用户体验以及强大的品牌影响力&#xff0c;为全球卖家铺设了一条通往成功的康庄大道。而在这条道路上&#xff0c;武汉流星汇聚电子商务有限公司作为一颗迅速崛起的新…

libnl教程(1):订阅内核的netlink广播通知

文章目录 前言目标netlink kernel multicast notifications订阅内核的链路(link)变化通知示例代码函数使用难点问题 前言 我之前整理过&#xff1a;netlink 简介。 netlink 是 libnl 的基础。 在开始之前&#xff0c;需要先翻看一遍官方文档&#xff1a;Netlink Library (li…

centos从home分区分配空间到根分区

在安装centos系统时如果采用默认自动分区&#xff0c;则会默认只给根分区分配50G空间&#xff0c;其余多余的会被分配到home分区&#xff0c;而作为家用服务器或仅个人使用的话&#xff0c;为了方便往往根分区会不够用而home分区几乎没使用。 先看下现在的磁盘结构和容量(xfs文…

第八篇 WAV文件格式

WAVE PCM soundfile format WAV即WAVE&#xff0c;WAVE文件是计算机领域最常用的数字化声音文件格式之一&#xff0c;它是微软专门为Windows系统定义的波形文件格式&#xff08;Waveform Audio&#xff09;&#xff0c;其扩展名为"*.wav"。 最基本的WAVE文件…

【Linux】进程概念的铺垫

进程概念的铺垫 先谈硬件——冯诺依曼体系结构冯诺依曼体系结构的5大部件输入输出设备存储器中央处理器&#xff08;CPU&#xff09; 冯诺依曼体系结构示意图 再谈软件——操作系统操作系统的 目的 和 定位如何理解 "管理"总结系统调用 - system call 先谈硬件——冯…

LINUX原始机安装JDK

文章目录 下载 JDK压缩包创建jdk文件夹sftp 远程上传解压缩 tar -zxvf 包名配置环境变量刷新 环境变量验证是否安装成功安装JAVA 依赖yum更新及替换镜像curl 命令下载更新更新yum依赖判断repo文件是否存在生成缓存、启用阿里云镜像 重新下载java依赖再次验证hello world 下载 J…

Java | Leetcode Java题解之第341题扁平化嵌套列表迭代器

题目&#xff1a; 题解&#xff1a; public class NestedIterator implements Iterator<Integer> {private List<Integer> vals;private Iterator<Integer> cur;public NestedIterator(List<NestedInteger> nestedList) {vals new ArrayList<Inte…

用数据分析找到神奇公式-《股市稳赚》读后感

格林布拉特的这本书介绍了一种简单的方法&#xff0c;核心是用神奇公式寻找到高资本收益率和高股票收益率的最佳投资组合。作者对其背后原理的普遍性充满自信&#xff0c;神奇公式寻找经营良好且价格低于平均水平的公司&#xff0c;买进质优价低的公司&#xff0c;这个公式&…

C++ 设计模式——简单工厂模式

简单工厂模式 简单工厂模式主要组成部分代码实现简单工厂模式模式的 UML 图UML图解析类与方法优点和缺点适用场景 简单工厂模式 简单工厂模式是一种创建型设计模式&#xff0c;通过一个工厂类来负责对象的实例。这种模式将对象创建的细节封装在工厂类中&#xff0c;客户端无需…