封装el-upload组件,用于上传图片和视频

使用环境 vue3+element-ui plus
需要根据后端返回结构修改的函数:onPreview onRemove onSuccess

组件使用

基本使用

在这里插入图片描述
源代码:

<script setup>
import AutoUploadFile from '@/components/auto-upload-file/index.vue'
function change(urls){
  console.log(urls)
}
</script>

<template>
  <AutoUploadFile @change="change"/>
</template>

<style lang="scss" scoped>
</style>

初始文件列表回显

在这里插入图片描述
源代码:

<script setup>
import AutoUploadFile from '@/components/auto-upload-file/index.vue'
import {ref} from "vue";

const initUrls = ref([
  'http://127.0.0.1:9090/file/local-plus/6700f235df13a72064bf9167.png'
])

function change(urls) {
  console.log(urls)
}
</script>

<template>
  <AutoUploadFile :init-file-urls="initUrls" accept=".jpg,.jpeg,.png" @change="change">
  </AutoUploadFile>
</template>

<style lang="scss" scoped>
</style>

定义上传格式

如果有mp4类型,文件展示列表就会变为text

在这里插入图片描述
源代码:

<script setup>
import AutoUploadFile from '@/components/auto-upload-file/index.vue'
function change(urls){
  console.log(urls)
}
</script>

<template>
  <AutoUploadFile accept=".jpg,.jpeg,.png,.mp4" :max-size="100" @change="change"/>
</template>

<style lang="scss" scoped>
</style>

自定义上传按钮样式

在这里插入图片描述
源代码:

<script setup>
import AutoUploadFile from '@/components/auto-upload-file/index.vue'
function change(urls){
  console.log(urls)
}
</script>

<template>
  <AutoUploadFile accept=".jpg,.jpeg,.png,.mp4" :max-size="100" @change="change">
    <el-button>自定义上传样式</el-button>
  </AutoUploadFile>
</template>

<style lang="scss" scoped>
</style>

组件属性

属性名属性类型默认值是否必填说明
initFileUrlsArray[]用于上传列表的回显,接收外部初始化url数组
listTypeStringpicture-card上传列表展示格式。可选项:picture-card/picture/text , 但是如果accept允许mp4,那么listType就会自动转化为text
actionString#上传文件时的接口服务
headersObject{}请求头
nameStringfile提交文件时的字段名
withCredentialsBooleantrue是否支持cookie凭证信息
showFileListBooleantrue是否展示上传列表
acceptString“.jpg,.jpeg,.png”可以上传的文件类型
limitNumber5允许上传的最大文件数量
maxSizeNumber5最大文件大小,单位MB
tipPrefixString“”提示信息前缀
showTipBooleantrue是否展示提示信息
showOverflowTooltipBooleantruetip过长是否使用省略号显示
multipleBooleantrue可以多选文件
autoUploadBooleantrue默认自动上传
sizeString100pxpicture-card的尺寸大小

组件事件

事件名事件参数列表说明
onProgress(e,file,fileList)用于监控文件上传进度
change(urls)上传列表改变时的回调

组件暴露方法

方法名参数列表说明
clearFiles()清空文件列表
submit()用于手动提交

组件插槽

插槽名插槽回显参数说明
default上传文件时的点击区域,用于自定义样式
file{ file }文件列表样式,用于自定义缩略图
trigger用于手动提交,只选择文件,不发起提交请求的插槽

组件源码:(auto-upload-file.vue)

<!--需要根据后端返回结构修改的函数:onPreview onRemove onSuccess -->
<script setup>
import {computed, onMounted, onUpdated, ref} from "vue";
import {ElMessage} from "element-plus";

const prop = defineProps({
  // 文件列表
  initFileUrls: {
    type: Array,
    default: []
  },
  // 展示格式
  listType: {
    type: String,
    default: 'picture-card'
  },
  // 上传文件的默认接口
  action: {
    type: String,
    default: 'http://localhost:9090/upload/file'
  },
  // 请求头(添加token等)
  headers: {
    type: Object,
    default: {}
  },
  // 上传时的文件名(需要与后端接收时的字段保持一致)
  name: {
    type: String,
    default: 'file'
  },
  // 默认支持cookie凭证信息
  withCredentials: {
    type: Boolean,
    default: true
  },
  // 默认展示上传文件列表
  showFileList: {
    type: Boolean,
    default: true
  },
  // 可接受文件的类型
  accept: {
    type: String,
    default: '.jpg,.jpeg,.png'
  },
  // 允许上传的最大文件数量
  limit: {
    type: Number,
    default: 5
  },
  // 单位MB
  maxSize: {
    type: Number,
    default: 5
  },
  // 提示前缀
  tipPrefix: {
    type: String,
    default: ''
  },
  // 是否展示提示
  showTip: {
    type: Boolean,
    default: true
  },
  // tip过长使用省略号显示
  showOverflowTooltip: {
    type: Boolean,
    default: true
  },
  // 可以多选文件
  multiple: {
    type: Boolean,
    default: true
  },
  // 默认自动上传
  autoUpload: {
    type: Boolean,
    default: true
  },
  // picture-card尺寸大小
  size: {
    type: String,
    default: '100px'
  }
})

const emit = defineEmits(['onProgress', 'change'])
defineExpose({
  clearFiles,
  submit
})

// el-upload使用的文件列表
const fileList = ref(prop.initFileUrls.map(item => {
  return {
    name: getFileName(item),
    url: item
  }
}))

const uploadRef = ref()

// 存放后端返回的url,及初始化url
const urls = ref([...prop.initFileUrls])

// 如果允许上传视频,则默认只能使用text显示上传列表
const listTypeCmp = computed(() => {
  return prop.accept.indexOf('mp4') !== -1 ? 'text' : prop.listType
})

// 提示信息
const tip = computed(() => {
  return `${prop.tipPrefix ? prop.tipPrefix + ',' : ''}文件类型:
  ${prop.accept.replaceAll(',', '/').replaceAll('.', '')}
  ,文件大小不能超过:${prop.maxSize}MB`
})

// 文件上传之前的钩子
function beforeUpload(e) {
  const MB = e.size / (1024 * 1024)
  if (MB > prop.maxSize) {
    ElMessage.error(`文件的大小不能超过:${prop.maxSize}MB`)
    return false
  }
}

// 上传成功的回调(根据后端返回值不同需要略作修改)
function onSuccess(e, file) {
  urls.value.push(e)
  emit('change', urls.value)
}

const dialogFileUrl = ref()
const dialogVisible = ref(false)

// 预览图片(根据后端返回值不同需要略作修改)
function onPreview(e) {
  dialogFileUrl.value = e.response || e.url
  dialogVisible.value = true
}

// 移除文件(根据后端返回值不同需要略作修改)
function onRemove(e) {
  urls.value = urls.value.filter(item => item !== (e.response || e.url))
  emit('change', urls.value)
}

// 超出最大文件限制时,执行的钩子函数
function onExceed(e) {
  ElMessage.error(`超出要求的文件最大数量:${prop.limit}`)
}

// 文件上传失败时的回调
function onError() {
  ElMessage.error('文件上传失败')
}

// 上传进度回调
function onProgress(e, file, fileList) {
  emit('onProgress', e, file, fileList)
}

// 清空文件列表
function clearFiles() {
  uploadRef.value.clearFiles()
  urls.value = []
  emit('change', urls.value)
}

// 手动提交
function submit() {
  uploadRef.value.submit()
}

// 获取后缀
function getSuffix(url) {
  return url.substring(url.lastIndexOf('.') + 1)
}

// 获取文件名
function getFileName(url) {
  return url.substring(url.lastIndexOf('/') + 1)
}

// 阻止点击tip时触发的上传行为
function preventClick(event) {
  event.stopPropagation()
}

// 初始化picture-card大小
function initSize() {
  const uploadListItem = document.querySelector('.el-upload-list--picture-card')
  const uploadPictureCard = document.querySelector('.el-upload--picture-card')
  if (uploadListItem) {
    uploadListItem.style.setProperty('--el-upload-list-picture-card-size', prop.size)
  }
  if (uploadPictureCard) {
    uploadPictureCard.style.setProperty('--el-upload-picture-card-size', prop.size)
  }
}

// 动态处理展示样式
function handleStyle() {
  initSize()
  const dom = document.querySelector('.el-upload-list')
  if (prop.showTip && dom && listTypeCmp !== 'picture-card') {
    dom.style.margin = '30px 0 0'
  } else {
    dom.style.margin = '10px 0 0'
  }
}

onUpdated(() => {
  handleStyle()
})
onMounted(() => {
  handleStyle()
})

</script>

<template>
  <el-upload
      ref="uploadRef"
      class="upload-box"
      v-model:file-list="fileList"
      :list-type="listTypeCmp"
      :action="action"
      :headers="headers"
      :with-credentials="withCredentials"
      :name="name"
      :show-file-list="showFileList"
      :before-upload="beforeUpload"
      :on-success="onSuccess"
      :on-remove="onRemove"
      :on-preview="onPreview"
      :accept="accept"
      :limit="limit"
      :on-exceed="onExceed"
      :on-error="onError"
      :on-progress="onProgress"
      :auto-upload="autoUpload"
      :multiple="multiple"
  >
    <template #default v-if="autoUpload">
      <div class="upload">
        <div class="upload-default">
          <slot>
            <el-icon v-if="listTypeCmp==='picture-card'"
                     style="width: 100%;height: 100%;font-size: 30px;color: #888888">
              <Plus/>
            </el-icon>
            <el-button v-else>上传文件</el-button>
          </slot>
        </div>
        <div class="upload-tip" v-if="showTip" @click="preventClick">
          <div class="tip-div" :title="tip"
               :class="{'text-overflow-ellipsis':showOverflowTooltip}">
            <span>{{ tip }}</span>
          </div>
        </div>
      </div>
    </template>
    <!--    自定义缩略图-->
    <template #file="{file}">
      <slot name="file" :file="file"></slot>
    </template>
    <template #trigger v-if="!autoUpload">
      <slot name="trigger"></slot>
    </template>
  </el-upload>
  <!--文件预览-->
  <el-dialog v-model="dialogVisible" width="80%">
    <video style="height: 100%;width: 100%" v-if="getSuffix(dialogFileUrl)==='mp4'" :src="dialogFileUrl" controls/>
    <el-image v-else style="height: 80vh" w-full :src="dialogFileUrl" alt="Preview Image"/>
  </el-dialog>
</template>

<style lang="scss" scoped>

.upload-box {
  box-sizing: border-box;
  height: 50px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;


  .upload {
    position: relative;
    height: 100%;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;

    .upload-tip {
      width: 100%;
      position: absolute;
      bottom: -30px;
      left: 0;

      .tip-div {
        width: 100%;
        cursor: pointer;
        color: red;
        font-weight: 200;
        font-size: 12px;
      }

      .text-overflow-ellipsis {
        display: inline-block;
        overflow: hidden;
        white-space: nowrap; /* 不换行 */
        text-overflow: ellipsis; /* 超出部分显示为省略号 */
      }
    }
  }

}

</style>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

金智维KRPA之Excel自动化

Excel自动化操作概述 Excel自动化主要用于帮助各种类型的企业用户实现Excel数据处理自动化&#xff0c;Excel自动化是可以从单元格、列、行或范围中读取数据&#xff0c;向其他电子表格或工作簿写入数据等活动。 通过相关命令&#xff0c;还可以对数据进行排序、进行格式…

javaScript数组(16个案例+代码+效果图)

目录 1.数组的概念 2.创建数组 1.通过数组字面量创建数组 1.代码 2.效果 2.通过new Array()创建数组 1.代码 2.效果 3.数组的基本操作 1.获取数组的长度 案例:获取数组的长度 1.代码 2.效果 2.修改数组的长度 1.代码 2.效果 4.访问数组 案例:访问数组 1.代码 2.效果 5.遍历数组…

【EXCEL数据处理】000013 案例 EXCEL筛选与高级筛选。

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【EXCEL数据处理】000013 案例 EXCEL筛选与高级筛选。使用的软件&#…

一个真实可用的登录界面!

需要工具&#xff1a; MySQL数据库、vscode上的php插件PHP Server等 项目结构&#xff1a; login | --backend | --database.sql |--login.php |--welcome.php |--index.html |--script.js |--style.css 项目开展 index.html&#xff1a; 首先需要一个静态网页&#x…

【HTML5】html5开篇基础(4)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

React 解释常见的 hooks: useState / useRef / useContext / useReducer

前言 如果对 re-render 概念还不清楚&#xff0c;建议先看 React & 理解 re-render 的作用、概念&#xff0c;并提供详细的例子解释 再回头看本文。 如果对 React 基础语法还不熟练&#xff0c;建议先看 React & JSX 日常用法与基本原则 再回头看本文。 useState useS…

虚拟机 VMware 安装 macOS

macOS 界面 MAC OS IOS下载&#xff1a; amacOS Monterey by Techrechard.comwmacOS Monterey by Techrechard.com 下载&#xff1a;Unlocker-v2.0.1-x64 Mac OS X 虚拟机中更改屏幕分辨率 终端输入命令&#xff1a; sudo defaults write /Library/Preferences/com.apple.w…

[图形学]在半球面上均匀采样和cos加权采样

一、简介 本文介绍了如何在半球表面上进行半球面均匀采样、半球面cos加权采样采样。 给出了相关公式推导和python代码实现。 二、在半球上采样 0.预备知识 1).球面坐标系与笛卡尔坐标系 在半球面上采样时&#xff0c;常使用球面坐标系。先采样球面坐标系下的坐标参数 ( θ…

如何使用 Python 读取数据量庞大的 excel 文件

使用 pandas.read_excel 读取大文件时&#xff0c;的确会遇到性能瓶颈&#xff0c;特别是对于10万行20列这种规模的 .xlsx 文件&#xff0c;常规的 pandas 方法可能会比较慢。 要提高读取速度&#xff0c;关键是找到更高效的方式处理 Excel 文件&#xff0c;特别是在 Python 的…

51单片机学习第六课---B站UP主江协科技

DS18B20 1、基本知识讲解 2、DS18B20读取温度值 main.c #include<regx52.h> #include"delay.h" #include"LCD1602.h" #include"key.h" #include"DS18B20.h"float T; void main () {LCD_Init();LCD_ShowString(1,1,"temp…

Qt之TCP收发图片的例子

一.效果 二.实现 1.发图片 void MainWindow::slotSendImage() {matrix.rotate(90);QPixmap tempPixmap = pixmap.transformed(matrix);QBuffer buffer;tempPixmap.save(&buffer,"jpg");ui->labelImage->setPixmap(tempPixmap);int dataLength = buffer.d…

软考鸭微信小程序:助力软考备考的便捷工具

一、软考鸭微信小程序的功能 “软考鸭”微信小程序是一款针对软考考生的备考辅助工具&#xff0c;提供了丰富的备考资源和功能&#xff0c;帮助考生提高备考效率&#xff0c;顺利通过考试。其主要功能包括&#xff1a; 历年试题库&#xff1a;小程序内集成了历年软考试题&…

HarmonyOs 查看官方文档使用弹窗

1. 学会查看官方文档 HarmonyOS跟上网上的视频学习一段时间后&#xff0c;基本也就入门了&#xff0c;但是有一些操作网上没有找到合适教学的视频&#xff0c;这时&#xff0c;大家就需要养成参考官方文档的习惯了&#xff0c;因为官方的开发文档是我们学习深度任何一门语言或…

004集—— txt格式坐标写入cad(CAD—C#二次开发入门)

如图所示原始坐标格式&#xff0c;xy按空格分开&#xff0c;将坐标按顺序在cad中画成多段线&#xff1a; 坐标xy分开并按行重新输入txt&#xff0c;效果如下&#xff1a; 代码如下 &#xff1a; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; us…

AI模型部署初认识

AI部署这个词儿大家肯定不陌生&#xff0c;可能有些小伙伴还不是很清楚这个是干嘛的&#xff0c;但总归是耳熟能详了。 近些年来&#xff0c;在深度学习算法已经足够卷卷卷之后&#xff0c;深度学习的另一个偏向于工程的方向–部署工业落地&#xff0c;才开始被谈论的多了起来…

Pikachu-File Inclusion-远程文件包含

远程文件包含漏洞 是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的&#xff0c;因此漏洞一旦存在&#xff0c;危害性会很大。但远程文件包含漏洞的利用条件较为苛刻&#xff1b;因此&#xff0c;在web应用系统的功能设计上尽量不要让前端用户直接传变…

水下声呐数据集,带标注

水下声呐数据集&#xff0c;带标注 水下声呐数据集 数据集名称 水下声呐数据集 (Underwater Sonar Dataset) 数据集概述 本数据集是一个专门用于训练和评估水下目标检测与分类模型的数据集。数据集包含大量的水下声呐图像&#xff0c;每张图像都经过专业标注&#xff0c;标明…

银河麒麟桌面操作系统修改默认Shell为Bash

银河麒麟桌面操作系统修改默认Shell为Bash &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 在银河麒麟桌面操作系统&#xff08;ARM版&#xff09;中&#xff0c;若要将默认Shell从Dash改为Bash&#xff0c;可执行以下步骤&#xff1a; 打开…

记一次炉石传说记牌器 Crash 排查经历

大家好这里是 Geek技术前线。最近在打炉石过程中遇到了HSTracker记牌器的一个闪退问题&#xff0c;尝试性排查了下原因。这里简单记录一下 最近炉石国服回归&#xff1b;由于设备限制&#xff0c;我基本只会在 Mac 上打炉石。并且由于主要打竞技场&#xff0c;所以记牌器是必不…

河南移动:核心营业系统稳定运行超300天,数据库分布式升级实践|OceanBase案例

河南移动&#xff0c;作为电信全业务运营企业&#xff0c;不仅拥有庞大的客户群体和业务规模&#xff0c;还引领着业务产品与服务体系的创新发展。河南移动的原有核心营业系统承载着超过6000万的庞大用户量&#xff0c;管理着超过80TB的海量数据&#xff0c;因此也面临着数据规…