Ant Design Vue上传多个图片

news2024/9/30 5:30:51

模板代码:

在这里插入图片描述

定义变量:

在这里插入图片描述

文件限制的函数:

在这里插入图片描述

上传的函数:

在这里插入图片描述

样式函数:

在这里插入图片描述

完整代码:

<template>
  <div class="dialog-upload" v-if="showUploadDialog">
    <div class="dialog-upload__head">
      <div class="title">上传图片</div>
      <div class="close" @click="closeDialog"></div>
    </div>
    <div class="dialog-upload__body">
        <div class="upload-box">
          <span class="text">tab:</span>
          <div class="pic-box">
            <div v-for="(item,index) in cqImgUrl" :key="index" class="pic-box__single">
              <a-image class="pic" :src="item" />
              <div @click="deleteImg('tab',item)" class="pic-delete"></div>
            </div>
            <a-upload
              action="#"
              :multiple="true"
              list-type="picture"
              :before-upload="beforeUpload"
              :customRequest="handleChange"
              :show-upload-list="false"
            >
              <div v-if="!cqImgUrl.length || cqImgUrl.length <5" class="img" @click="uploadImg('tab')"></div>
            </a-upload>
          </div>
        </div>
        <div class="upload-box">
          <span class="text">tab1:</span>
          <div class="pic-box">
            <div v-for="(item,index) in nyImgUrl" :key="index" class="pic-box__single">
              <a-image class="pic" :src="item" />
              <div @click="deleteImg('tab1',item)" class="pic-delete"></div>
            </div>
            <a-upload
              action="#"
              :multiple="true"
              list-type="picture"
              :before-upload="beforeUpload"
              :customRequest="handleChange"
              :show-upload-list="false"
            >
              <div v-if="!nyImgUrl.length || nyImgUrl.length <5" class="img" @click="uploadImg('tab1')"></div>
            </a-upload>
          </div>
        </div>
    </div>
    <div class="dialog-upload__foot">
        <span class="sure" @click="sure">确定</span>
        <span class="cancle" @click="closeDialog">取消</span>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs, watch, nextTick } from 'vue'
import { message } from 'ant-design-vue'
import G from '@/request/G'
import axios from 'axios'

export default defineComponent({
  name: 'SmartDialog',
  props: {
    showUploadDialog: {
      // 是否显示当前弹窗
      type: Boolean,
      default: false
    },
    activeTab: {
      type: String,
      default: 'tab'
    },
    imgUrl: {
      type: Array,
      default: () => {
        return []
      }
    },
    qyStoreId: { // 拿到的Id
      type: String,
      default: ''
    }
  },
  setup (props, { emit }) {
    interface FileItem {
      uid: string;
      name?: string;
      status?: string;
      response?: string;
      url?: string;
      percent?:number;
      type?:string;
    }
    interface FileInfo {
      file: FileItem;
      fileList: FileItem[];
    }
    const data = reactive({
      dialogVisible: false, // 是否显示弹窗
      cqImgUrl: [] as Array<string> | any,
      nyImgUrl: [] as Array<string> | any,
      cqImgList: [] as any,
      nyImgList: [] as any,
      uploadType: '', // 当前上传文件的归属
      limitError: false
    })

    // 监听当前的弹窗是否显示
    watch(
      () => props.showUploadDialog,
      (val: boolean) => {
        data.dialogVisible = !!val
      },
      {
        immediate: true,
        deep: true
      }
    )

    watch(
      () => props.activeTab,
      (val: string) => {
        const type = val === 'tab' ? 2 : 1
        if (props.qyStoreId) {
          nextTick(() => {
            getPicUrl(type)
          })
        }
      },
      {
        immediate: true,
        deep: true
      }
    )

    // 文件上传
    const handleChange = (info: FileInfo) => {
      if (!data.limitError) {
        const formData = new FormData()
        formData.append('file', info.file as any) // 添加文件对象
        let params = {
          biz: 'energy',
          _api: 'el.image.upload',
          _v: '1.0'
        } as any
        params = G.buildInputs(params)
        params._at = G.buildAt(params)
        Object.keys(params).forEach(key => {
          formData.append(key, params[key])
        })
        axios.post('/upload', formData).then((res: any) => {
          if (res.data && res.data.success && res.data.model) {
            if (res.data.model[0]) {
              let url = res.data.model[0].authUrl
              if (data.uploadType === 'tab') {
                data.cqImgUrl.push(url)
              }
              if (data.uploadType === 'tab1') {
                data.nyImgUrl.push(url)
              }
            }
          } else {
            message.error(res.data.msgInfo)
          }
        })
      }
    }

    // 获取另一个tab的图,用于回显
    const getPicUrl = (val:number) => {
      let params = {
        _api: 'el.energy.storeDraw',
        storeId: props.qyStoreId,
        drawType: val,
        _v: '1.0'
      } as any
      params = G.buildInputs(params)
      G.baseAjax({
        type: 'POST',
        data: G.param(params) + '&_at=' + G.buildAt(params)
      }).then((res:any) => {
        const { success, model } = res
        if (success) {
          if (props.activeTab === 'tab') {
            data.nyImgUrl = model.split(',')
          }

          if (props.activeTab === 'tab1') {
            data.cqImgUrl = model.split(',')
          }
        }
      }).finally(() => {
        if (props.activeTab === 'tab') {
            data.cqImgUrl = JSON.parse(JSON.stringify(props.imgUrl))
          } else if (props.activeTab === 'tab1') {
            data.nyImgUrl = JSON.parse(JSON.stringify(props.imgUrl))
          }
      })
    }

    // 关闭弹窗
    const closeDialog = () => {
      emit('closeDialog', false)
    }

    // 当前上传的是哪个文件
    const uploadImg = (type:string) => {
      data.uploadType = type
    }

    const deleteImg = (type:string, item:string) => {
      if (type === 'tab') {
        if (data.cqImgUrl && data.cqImgUrl.length) {
          let index = data.cqImgUrl.indexOf(item)
          data.cqImgUrl.splice(index,1)
        }
      }
      if (type === 'tab1') {
        if (data.nyImgUrl && data.nyImgUrl.length) {
          let index = data.nyImgUrl.indexOf(item)
          data.nyImgUrl.splice(index,1)
        }
      }
    }

    const beforeUpload = (file: FileItem) => {
      // const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/jpg'
      // if (!isJpgOrPng) {
      //   message.error('请上传正确的图片格式!')
      // }
      let sizeLimit = false
      if (data.uploadType === 'tab') {
        data.cqImgList.push(file)
        sizeLimit = (data.cqImgList.concat(...data.cqImgUrl)).length <= 5
      }
      if (data.uploadType === 'tab1') {
        data.nyImgList.push(file)
        sizeLimit = (data.nyImgList.concat(...data.nyImgUrl)).length <= 5
      }
      if (!sizeLimit && !data.limitError) {
        data.limitError = true
        if (data.uploadType === 'tab') {
          data.cqImgList = []
        }
        if (data.uploadType === 'tab1') {
          data.nyImgList = []
        }
        message.error('至多上传五张图片!')
        return false
      }
      data.limitError = false
      return sizeLimit
    }

    const sure = () => {
      let params = {
        _api: 'el.energy.addImage',
        storeId: props.qyStoreId,
        factoryDraw: data.cqImgUrl.join(','),
        energyDraw: data.nyImgUrl.join(','),
        _v: '1.0'
      } as any
      params = G.buildInputs(params)
      G.baseAjax({
        type: 'POST',
        data: G.param(params) + '&_at=' + G.buildAt(params)
      }).then((res:any) => {
        const { success } = res
        if (success) {
          message.success('上传成功!')
        } else {
          message.error(res.msgInfo)
        }
      }).finally(() => {
        emit('submitDialog', {
          cqImgUrl: data.cqImgUrl,
          nyImgUrl: data.nyImgUrl
        })
      })
    }

    return {
      ...toRefs(data),
      closeDialog,
      uploadImg,
      sure,
      handleChange,
      beforeUpload,
      deleteImg
    }
  }
})
</script>

<style lang="scss" scoped>
.dialog-upload {
  width: 1056px;
  height: 947px;
  // height: 788px;
  z-index: 200;
  position: absolute;
  top: 20%;
  left: 40%;
  background: url("@/assets/images/uploadDialog.png") no-repeat;
  background-size: 100% 100%;
  overflow: auto;
  &::-webkit-scrollbar {
    display: none;
  }
  &__head {
    position: relative;
    .title {
      padding: 32px 0 77px 48px;
      font-size: 44px;
      font-weight: 600;
      color: #ffffff;
      line-height: 62px;
    }
    .close {
      position: absolute;
      top: 24px;
      right: 24px;
      cursor: pointer;
      width: 32px;
      height: 32px;
      background: url("@/assets/images/close.png") no-repeat;
      background-size: 32px auto;
    }
  }
  &__body {
    display: flex;
    flex-direction: column;
    .upload-box {
        display: flex;
        margin-bottom: 32px;
        .text {
          display: inline-block;
          white-space: nowrap;
          width: 236px;
          flex: 1;
          font-size: 28px;
          font-weight: 400;
          color: #fff;
          text-align: right;
        }
        .img {
            cursor: pointer;
            width: 200px;
            height: 122px;
            background: url("@/assets/images/upload.png") no-repeat;
            background-size: 200px auto;
        }
    }
    .pic-box {
      display: flex;
      flex-wrap: wrap;
      flex: 3;
      &__single {
        position: relative;
        width: 200px;
        height: 122px;
        border: 2px dashed #4E93F8;
        border-radius: 8px;
        margin: 0 20px 24px 0;
        .pic  {
          width: 200px;
          height: 122px;
          object-fit: contain;
          border-radius: 8px;
        }
        .pic-delete {
          cursor: pointer;
          z-index: 200;
          position: absolute;
          z-index: 50;
          top: -16px;
          right: -12px;
          width: 30px;
          height: 30px;
          background: url("@/assets/images/deleteImg.png") no-repeat;
          background-size: 30px auto;
        }
      }
    }
  }
  &__foot {
    position: absolute;
    bottom: 40px;
    left: 50%;
    transform: translateX(-50%);
    .sure {
        cursor: pointer;
        display: inline-block;
        background: #3196FA;
        border: 2px solid #3196FA;
        border-radius: 8px;
        padding: 12px 41px;
        margin-right: 44px;
        font-size: 28px;
        color: #fff;
    }
    .cancle {
        cursor: pointer;
        display: inline-block;
        border: 2px solid #FFFFFF;
        border-radius: 8px;
        padding: 12px 41px;
        font-size: 28px;
        color: #fff;
    }
  }
}
</style>
<style lang="scss">
.dialog-upload {
  .ant-image {
    width: 196px;
    height: 118px;
    border-radius: 8px;
  }
  .ant-image-img {
    width: 196px;
    height: 118px;
    object-fit: contain;
    border-radius: 8px;
  }
  .ant-image-mask-info {
   // 将div下的所有元素隐藏文字大小为0
    visibility: hidden;
    font-size: 0; 
  }
  .ant-image-mask-info span{
   // 再单独给span标签添加样式 让其显示并且给出文字大小
    visibility: visible;
    font-size: 48px;
  }
}
</style>

最终效果:

在这里插入图片描述

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

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

相关文章

2018年认证杯SPSSPRO杯数学建模A题(第二阶段)海豚与沙丁鱼全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 基于聚类分析的海豚捕食合作策略 A题 海豚与沙丁鱼 原题再现&#xff1a; 沙丁鱼以聚成大群的方式来对抗海豚的捕食。由于水下光线很暗&#xff0c;所以在距离较远时&#xff0c;海豚只能使用回声定位方法来判断鱼群的整体位置&#xff0c;难…

python|写一个简单的http服务器

本篇文章的python版本为: 什么是http http是一个应用层协议&#xff0c;准确的来说是基于TCP/IP4层网络协议中的传输层中的TCP应用层协议。 额&#xff0c;4层模型大概是这样的: 在网络通信中&#xff0c;用户的数据是以报文来传输的&#xff0c;但是在实际通信中&#xff0…

密码学学习笔记(二十四):TCP/IP协议栈

TCP/IP协议栈的基础结构包括应用层、传输层、网络层、数据链路层和物理层。 应用层 应用层位于TCP/IP协议栈的最顶层&#xff0c;是用户与网络通信的接口。这一层包括了各种高级应用协议&#xff0c;如HTTP&#xff08;用于网页浏览&#xff09;、FTP&#xff08;用于文件传输…

【安全篇 / FortiGuard】(7.4) ❀ 02. 独立VDOM下的FortiGuard服务升级 ❀ FortiGate 防火墙

【简介】由于业务的需要&#xff0c;创建两个独立VDOM&#xff0c;每个VDOM有各自的宽带&#xff0c;但是FortiGuard服务却无法升级&#xff0c;有什么办法解决吗&#xff1f; VDOM概念 首先我们看看什么是VDOM。 ① VDOM将你的FortiGate划分为多个逻辑设备&#xff0c;并将一个…

深入理解Linux文件系统

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;晴る—ヨルシカ 0:20━━━━━━️&#x1f49f;──────── 4:30 &#x1f504; ◀️ ⏸ ▶️ ☰ &…

力扣精选算法100题——长度最小的子数组(滑动窗口专题)

本题链接——长度最小的子数组 第一步&#xff1a;了解题意 给定一个数组&#xff0c;要求在这个数组中找到一个必须是连续的子数组并且这个子数组每个元素加起来>target并从找到的这些数组中取一个最短的数组。 第二步&#xff1a;算法原理 滑动窗口是一种在序列&#xff…

【开源】基于JAVA语言的河南软件客服系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理人员2.2 业务操作人员 三、系统展示四、核心代码4.1 查询客户4.2 新增客户跟进情况4.3 查询客户历史4.4 新增服务派单4.5 新增客户服务费 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的河…

中仕公考:贵州省统一面向社会公开招录公务员公告

2024年1月22日至1月25日期间,每日10:00、14:00及19:00对报名情况进行更新,供报考者参考。 资格初审时间为2024年1月22日9:00至1月28日17:00。 网上缴费时间为2024年1月22日9:00至1月29日17:00。 打印准考证时间2024年3月11日9:00至3月14日17:00。 公共科目笔试时间为: 202…

深度学习(2)--卷积神经网络(CNN)

卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;是一种深度学习模型或类似于人工神经网络的多层感知器&#xff0c;常用来分析视觉图像。 一.卷积神经网络基础概念 传统网络是二维的&#xff0c;而卷积网络是三维的。 例如32x32x3的图片&#xff0c;在传…

Pure-admin框架 Pure-table中获取所选中的内容的信息

最近在尝试使用Pure-admin框架来进行开发&#xff0c;正好遇到了多选表格需要获取选中项的id的情况&#xff0c;因为平台介绍说是二次封装 element-plus 的 Table &#xff0c;直接拿el-table的方法来试 在table上设置属性ref"multipleTableRef" let idArr [];mult…

为什么需要放行回源IP

为什么需要放行回源IP 网站以“独享模式”成功接入WAF后&#xff0c;所有网站访问请求将先经过独享引擎配置的ELB然后流转到独享引擎实例进行监控&#xff0c;经独享引擎实例过滤后再返回到源站服务器&#xff0c;流量经独享引擎实例返回源站的过程称为回源。在服务器看来&…

从“渲个锤子”,浅析影视动画渲染的困难与挑战!

提起“雷神之锤”&#xff0c;相信大家都不陌生。它是漫威电影宇宙中“雷神”托尔所使用的武器。传说中&#xff0c;这把圣器可以承载魔法咒语&#xff0c;召唤风、雨、雷、电四种自然元素。它能在使用者的意念下对目标进行攻击&#xff0c;无视与使用者之间的距离和障碍物&…

C++进阶(五)二叉搜索树

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、二叉搜索树概念二、二叉搜索树操作三、二叉搜索树的实现四、二叉搜索树的应用五、二叉搜索…

(人才测评)招聘数据分析师的入职测评方案

现在是一个大数据的时代&#xff0c;我们的车载导航、淘宝购物、包括人才招聘、都是大数据的产物&#xff0c;然而光靠数据堆积是没用的&#xff0c;所以如何高效的进行数据挖掘与分析&#xff0c;就成了每一件企业思考的问题。 一、 数据分析师的基本工作标准 1、 平时需要…

【vue2】状态管理之 Vuex

文章目录 一、介绍1、概念 2、工作示意图3、安装4、简单示例 二、核心1、State1.1 组件中获取 Vuex 的状态1.2 mapState 辅助函数1.3 对象展开运算符 2、Getter2.1 基本使用2.2 通过属性访问2.3 通过方法访问2.4 mapGetters 辅助函数 3、Mutation3.1 定义 mutation3.2 commit 提…

C++初阶类与对象(三):详解复制构造函数和运算符重载

上次介绍了构造函数和析构函数&#xff1a;C初阶类与对象&#xff08;二&#xff09;&#xff1a;详解构造函数和析构函数 今天就来接着介绍新的内容&#xff1a; 文章目录 1.拷贝构造函数1.1引入和概念1.2特性 2.赋值运算符重载2.1运算符重载2.2放在哪里2.3运算符重载示例2.3.…

WebRTC视频会议/视频客服系统EasyRTC进入会议室密码验证的开发与实现

基于WebRTC技术的EasyRTC视频会议系统&#xff0c;建设目标是让用户随时随地、快捷方便地进行视频会议&#xff0c;并根据行业需求有针对性地提供多样化、个性化功能&#xff0c;该系统是覆盖全球的实时音视频开发平台&#xff0c;支持一对一、一对多等视频通话&#xff0c;极大…

Vray渲染效果图材质参数设置

渲染是创造出引人入胜视觉效果的关键步骤&#xff0c;在视觉艺术领域尤为重要。不过&#xff0c;渲染作为一个资源密集型的过程&#xff0c;每当面对它时&#xff0c;我们往往都会遭遇到时间消耗和资源利用的巨大挑战。幸运的是&#xff0c;有几种方法能够帮助我们优化渲染&…

mac PyCharm 使用conda环境

1 使用conda创建虚拟环境 conda create -n test6 python3.9 -y conda activate test62 选择conda环境 本地 选择已经存在的conda环境 右下角会显示现在的环境。

Android中矩阵Matrix实现平移,旋转,缩放和翻转的用法详细介绍

一&#xff0c;矩阵Matrix的数学原理 矩阵的数学原理涉及到矩阵的运算和变换&#xff0c;是高等代数学中的重要概念。在图形变换中&#xff0c;矩阵起到关键作用&#xff0c;通过矩阵的变换可以改变图形的位置、形状和大小。矩阵的运算是数值分析领域的重要问题&#xff0c;对…