二次封装a-upload组件,自定义上传预览

news2024/12/23 11:10:47

a-upload封装

    • 效果
    • 自定义上传customRequest
    • transformFile上传前修改文件流
    • 自定义预览
    • 调整props和a-uoload一致
    • install封装vue组件
    • 结束

效果

编辑
在这里插入图片描述
预览
不展示删除和上传
在这里插入图片描述
空数据
自定义图片样式
在这里插入图片描述

自定义上传customRequest

入参是本地上传的文件流

    async customRequest(file) {
      const form = new FormData()
      form.append('file', file.file)
      form.append('name', file.name)
      try {
        this.uploadLoading = true
        const res = await postAction(this.uploadActionUrl, form)
        if (res.success) {
          this.picUrl = true
          const length = this.fileList.length
          const url = getFileAccessHttpUrl(res.message)
          const type = res.message ? res.message.split('.')[res.message.split('.').length - 1] : 'null'
          const addFile = {
            uid: new Date().valueOf(),
            type: type,
            name: this.renderDisplayName(file.file.name),
            status: 'done',
            response: {
              status: 'done',
              message: res.message,
            },
            url: url,
            message: res.message,
            index: length,
          }
          this.fileList.push(addFile)
          this.$message.success('上传成功')
          this.$emit('change', this.fileList.map((item) => item.message).join(','))
        } else {
          this.$message.error('上传失败')
        }
        this.uploadLoading = false
      } catch (r) {
        this.uploadLoading = false
        this.$message.error('上传失败')
        console.warn(r)
      }
    }

transformFile上传前修改文件流

入参是本地上传的文件流
这里我修改文件流的名称,返回file的promise

    transformFile(file) {
      return new Promise((resolve) => {
        const currentTime = new Date()
        const type = file.type.split('/')
        const renameFile = new File([file], currentTime.valueOf() + '.' + type[1], { type: file.type })
        resolve(renameFile)
      })
    }

自定义预览

    handlePreview(file) {
      return new Promise((resolve, reject) => {
        try {
          resolve(this.previewFile(file))
        } catch (r) {
          reject(r)
        }
      })
    },

调整props和a-uoload一致

<template>
  <div style="display: inline-block">
    <div>
      <a-upload
        name="file"
        :accept="accept"
        :multiple="isMultiple"
        :disabled="disabled"
        :headers="headers"
        :fileList="[]"
        :customRequest="customRequest"
        :beforeUpload="beforeUpload"
        :remove="handleDelete"
        :transformFile="transformFile"
      >
        <a-button :loading="uploadLoading" v-if="!disabled && isMultiple && fileList.length < limit">
          <a-icon type="upload" /> {{text}}
        </a-button>
      </a-upload>
      <template v-if="fileList.length">
        <div v-for="(item, index) in fileList" :key="index" class="file-list-box">
          <img v-if="isImg(item.type)" :src="item.url" class="upload-icon-view" />
          <a-icon v-else-if="isPdf(item.type)" class="upload-icon-view" type="file" />
          <a-tooltip :title="item.name">
            <span class="upload-name-view">{{ item.name }}</span>
          </a-tooltip>
          <a-tooltip title="预览">
            <span style="color: #0071fc; margin: 0 20px"><a-icon type="eye" @click="handlePreview(item)" /></span>
          </a-tooltip>
          <a-tooltip title="删除">
            <span style="color: #f5222d" v-if="!disabled"><a-icon type="delete" @click="handleDelete(item)" /></span>
          </a-tooltip>
        </div>
      </template>
      <template v-else-if="disabled">
        <div style="text-align: left">
          <img :src="require('@/assets/gaoxinImgs/null-content.png')" alt="暂无数据" style="max-width: 100px" />
          <p style="text-align: center; width: 100px">暂无数据</p>
        </div>
      </template>
    </div>
    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
      <img alt="图片" style="width: 100%; height: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>

<script>
import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { postAction, getFileAccessHttpUrl, getAction } from '@/api/manage'
const uidGenerator = () => {
  return '-' + parseInt(Math.random() * 10000 + 1, 10)
}
const getFileName = (path) => {
  if (path.lastIndexOf('\\') >= 0) {
    let reg = new RegExp('\\\\', 'g')
    path = path.replace(reg, '/')
  }
  return path.substring(path.lastIndexOf('/') + 1)
}
export default {
  name: 'JFileUpload',
  data() {
    return {
      url: window._CONFIG['pdfDomainURL'],
      staticUrl: window._CONFIG['pdfPreviewURL'],
      id: 'pdfFilePreviewIframeId',
      fileName: '',
      uploadAction: window._CONFIG['domianURL'] + '/sys/common/upload',
      uploadActionUrl: '/sys/common/upload',
      uploadLoading: false,
      picUrl: false,
      headers: {},
      token: {},
      fileList: [],
      previewImage: '',
      previewVisible: false,
    }
  },
  props: {
    accept: {
      type: String,
      default: () => 'image/*,.pdf',
    },
    limit: {
      type: Number,
      default: 10,
    },
    text: {
      type: String,
      required: false,
      default: '上传附件(图片、pdf)',
    },
    /*这个属性用于控制文件上传的业务路径*/
    bizPath: {
      type: String,
      required: false,
      default: 'temp',
    },
    value: {
      type: [String, Array],
      required: false,
    },
    disabled: {
      type: Boolean,
      required: false,
      default: false,
    },
    isMultiple: {
      type: Boolean,
      required: false,
      default: true,
    },
  },
  watch: {
    value: {
      deep: true,
      handler(val) {
        this.initFile(val)
      },
    },
  },
  created() {
    const token = Vue.ls.get(ACCESS_TOKEN)
    this.token = token
    this.headers = { 'X-Access-Token': token }
    this.initFile(this.value)
  },
  methods: {
    initFile(val) {
      if (val instanceof Array) {
        this.initFileList(val.join(','))
      } else {
        this.initFileList(val)
      }
    },
    isWord(fileType) {
      const wordTypeArray = ['doc', 'docx']
      const isWord = wordTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isWord
    },
    isExcel(fileType) {
      const excelTypeArray = ['XLS', 'XLSX', 'XLSB', 'XLSM', 'XLST', 'sheet']
      const isExcel = excelTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isExcel
    },
    isImg(fileType) {
      const imgTypeArray = ['BMP', 'JPG', 'JPEG', 'PNG', 'GIF']
      const isImgType = imgTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isImgType
    },
    isPdf(fileType) {
      const pdfTypeArray = ['PDF']
      const isPdfType = pdfTypeArray.some((type) => {
        return fileType.toString().toUpperCase().includes(type.toString().toUpperCase())
      })
      return isPdfType
    },
    renderDisplayName(name) {
      return name
    },
    async customRequest(file) {
      const form = new FormData()
      form.append('file', file.file)
      form.append('biz', this.bizPath)
      try {
        this.uploadLoading = true
        const res = await postAction(this.uploadActionUrl, form)
        if (res.success) {
          this.picUrl = true
          const length = this.fileList.length
          const url = getFileAccessHttpUrl(res.message)
          const type = res.message ? res.message.split('.')[res.message.split('.').length - 1] : 'null'
          const addFile = {
            uid: uidGenerator(),
            type: type,
            name: this.renderDisplayName(file.file.name),
            status: 'done',
            response: {
              status: 'done',
              message: res.message,
            },
            url: url,
            message: res.message,
            index: length,
          }
          this.fileList.push(addFile)
          this.$message.success('上传成功')
          this.$emit('change', this.fileList.map((item) => item.message).join(','))
        } else {
          this.$message.error('上传失败')
        }
        this.uploadLoading = false
      } catch (r) {
        this.uploadLoading = false
        this.$message.error('上传失败')
        console.warn(r)
      }
    },
    transformFile(file) {
      return new Promise((resolve) => {
        const currentTime = new Date()
        const type = file.type.split('/')
        const renameFile = new File([file], currentTime.valueOf() + '.' + type[1], { type: file.type })
        resolve(renameFile)
      })
    },
    previewPdf(file) {
      const prefixUrl = this.staticUrl
      const path = file.response.message
      const fileUrl = prefixUrl + path
      return getAction(`/mybiz/myfile/preview/${fileUrl}`).then((previewUrl) => {
        if (previewUrl.toString().indexOf('http://') === 0) {
          const page = window.open(previewUrl)
          console.warn('page', page)
        } else {
          const page = window.open('http://' + previewUrl)
          console.warn('page', page)
        }
      })
    },
    previewImg(file) {
      this.previewImage = file.url
      this.previewVisible = true
    },
    previewExcel(file) {
      console.log('previewExcel', file)
      // 创建blob对象,解析流数据
    },
    previewFile(file) {
      const fileType = file.type
      console.log('fileType', fileType)
      if (this.isImg(fileType)) {
        return this.previewImg(file)
      } else {
        return this.previewPdf(file)
      }
    },
    initFileList(paths) {
      this.fileList = []
      if (!paths || paths.length === 0) {
        return 0
      }
      paths.split(',').forEach((item, index) => {
        const url = getFileAccessHttpUrl(item)
        const name = getFileName(item)
        const type = name && name.split('.').length ? name.split('.')[name.split('.').length - 1] : 'null'
        this.fileList.push({
          uid: uidGenerator(),
          name: this.renderDisplayName(name),
          type: type,
          status: 'done',
          url: url,
          response: {
            status: 'history',
            message: item,
          },
          message: item,
          index: index,
        })
      })
    },
    beforeUpload(file) {
      console.log('file', file)
      const fileType = file.name.split('.')[file.name.split('.').length - 1]
      // console.log('fileType', fileType)
      if (!this.isImg(fileType) && !this.isPdf(fileType)) {
        this.$message.warning('请上传图片或PDF')
        return false
      }
    },
    // 自定义预览
    handlePreview(file) {
      return new Promise((resolve, reject) => {
        try {
          resolve(this.previewFile(file))
        } catch (r) {
          reject(r)
        }
      })
    },
    handleDelete(file) {
      this.fileList = this.fileList.filter((item) => item.uid!== file.uid)
    },
    handleCancel() {
      this.close()
    },
    close() {
      this.previewImage = ''
      this.previewVisible = false
    },
  },
  model: {
    prop: 'value',
    event: 'change',
  },
}
</script>

<style scoped>
.upload-name-view {
  max-width: 80px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.upload-icon-view {
  position: relative;
  max-height: 48px;
  min-height: 48px;
  font-size: 32px;
  padding: 2px 10px 2px 2px;
  color: #0071fc;
}
.after-icon {
  line-height: 48px;
}
.file-list-box {
  position: relative;
  height: 66px;
  line-height: 48px;
  padding: 8px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  margin-top: 10px;
  width: fit-content;
}
</style>

install封装vue组件

抛出去install在入口调用即可

import JFileUpload from './JFileUpload.vue'

export default {
  install(Vue) {
    Vue.component(JFileUpload.name, JFileUpload)
  },
}

结束

在这里插入图片描述

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

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

相关文章

Java笔记之线程池详解

文章目录一、线程池是什么&#xff1f;二、为什么要使用线程池&#xff1f;三、jdk自带的四种线程池1. 线程池参数2.工作队列3.拒绝策略4.四种线程池一些示例四、自定义线程池一、线程池是什么&#xff1f; 一种线程使用模式&#xff0c;是一种多线程处理形式&#xff0c;处理…

FineReport表格软件-CSS动态切换年月日查询报表

1. 概述 1.1 版本 报表服务器版本 功能变更 11.0 -- 1.1 预期效果 由于业务的需要&#xff0c;很多情况下需要当满足某个条件时&#xff0c;某些查询条件才显示出来&#xff0c;如下图所示&#xff1a; 1.2 实现思路 由于业务的需要&#xff0c;很多情况下需要当满足某个…

[Flask]环境配置和项目框架的构建

一、配置flask 在Python环境下使用控制台的pip install命令进行安装 pip install Flask2.1.0 &#xff01;&#xff01;&#xff01;安装版本必须是2.x以上&#xff0c;否则可能出现错误&#xff1a;cannot import name escape from jinja2 &#xff08;flask 2.x放弃了对jinj…

CloudCompare 的简单的使用说明

File open&#xff1a;打开 save&#xff1a;保存 Global Shift settings&#xff1a;设置最大绝对坐标&#xff0c;最大实体对角线 Primitive Factory&#xff1a;对点云进行原始加工&#xff0c;改变原始点云的形状 3D mouse&#xff1a;对3D鼠标&#xff08;如3Dconnexion&a…

二叉树的绘制

目录 一、知乎方法 二、动手实践 DOT 语言 无向图 有向图 绘制二叉树 设置属性 如何绘制优美的二叉树 一、知乎方法 知乎上的大佬提供了一系列画图的方法&#xff0c;感兴趣的朋友可以自行去看看 用 Graphviz 绘制一棵漂亮的二叉树 - 南浦月 二叉搜索树&#xff0c…

庖丁解牛式讲解并发编程,GitHub高星最新开源阿里Java进阶必备手册

最近看到粉丝群里讨论最多的问题是现在Java这么卷&#xff0c;担心年龄大了以后会被裁员或者清退&#xff0c;要怎么做才能保住自己的“饭碗”。楼主认为不论是阅读优秀源码、领略设计思路&#xff0c;还是学习优秀架构、代码设计等等&#xff0c;都是加薪升职的正确路径&#…

安全分析开发环境 技术背景

安全分析开发环境一键部署 Gartner 报告中指出 [7]&#xff0c;Platfor m Ops for AI 是一种编排和扩展运营人工智能的方法&#xff0c;利用跨数据、机器学习、人工智能和应用程序 开发管道的多种最佳实践&#xff0c;为基于人工智能的系统创建一个高效的交付模型。Platform O…

RV1126笔记十七:吸烟行为检测及部署<四>

若该文为原创文章&#xff0c;转载请注明原文出处。 转换成onnx模型(windows) 一、查看pt文件 准备好训练好的pt文件,可以用Netron打开看看大概长啥样: 二、模型转换 主要的目的是想把训练好的pt文件转成onnx模型&#xff0c;为后面RV1126的部署做铺垫。 我们是在py38的con…

ChatGPT怎么突然变得这么强?华人博士万字长文深度拆解GPT-3.5能力起源

文章目录一、2020 版初代 GPT-3 与大规模预训练二、从 2020 版 GPT-3 到 2022 版 ChatGPT三、Code-Davinci-002和 Text-Davinci-002&#xff0c;在代码上训练&#xff0c;在指令上微调四、text-davinci-003 和 ChatGPT&#xff0c;基于人类反馈的强化学习的威力五、总结当前阶段…

SAP MM SPED输出报错-No authorization for delivery from shipping point US##-之对策

SAP MM SPED输出报错-No authorization for delivery from shipping point US##-之对策 前日收到某客户业务人员上报的一个问题&#xff0c;说是发现某个公司间STO单据的外向交货单里SPED 这个output不成功&#xff0c;不能成功触发inbound delivery单据。 相关报错信息如下&am…

项目实战之旅游网(四)后台角色管理(上)

目录 一.角色列表 二.新增角色 三.修改角色 四.删除角色 一.角色列表 接下来我们编写角色管理功能&#xff0c;首先查询角色列表: 1.编写RoleService Service public class RoleService {Autowiredprivate RoleMapper roleMapper;public Page<Role> findPage(int …

【无线通信】鲸鱼优化算法及其在无线网络资源分配中的应用(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

腾讯云Linux 轻量应用服务器如何搭建 FTP 服务?

Vsftpd&#xff08;very secure FTP daemon&#xff09;是众多 Linux 发行版中默认的 FTP 服务器。本文以 CentOS 7.6 64位操作系统的轻量应用服务器为例&#xff0c;使用 vsftpd 软件搭建 Linux 轻量应用服务器的 FTP 服务。 本文搭建 FTP 服务组成版本如下&#xff1a; Lin…

node.js+uni计算机毕设项目基于微信点餐系统小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

Allegro如何设置格点操作指导

Allegro如何设置格点操作指导 在PCB设计的时候,格点是一个很好用的工具,Allegro可以设置格点 具体操作如下 选择Setup-GirdsNon-Etch和All Etch中的X和Y都输入5,代表都是5的格点

CTF-MISC(入门|笔记|工具)

文章目录音频隐写直接隐写频谱隐写流量分析第一种流量包修复第二种是协议分析第三种数据提取图片分析zstegBMPPNGforemost 工具binwalksteghidestegslovetweakpngJPGF5-steganographystegdetect压缩包分析zip伪加密crc32zip包明文攻击其它条形码扫描pyc反编译数据转换到ASCII乱…

2022年安徽建筑施工电工(建筑特种作业)模拟试题及答案

百分百题库提供特种工&#xff08;电工&#xff09;考试试题、特种工&#xff08;电工&#xff09;考试真题、特种工&#xff08;电工&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 149.使⽤绝缘操作杆时&#xff0c;下列…

NTZ改机原理全公开(二)-- 实现篇

最核心的逻辑就是代码hook了,找这些hook点可不是一件容易的事情,但是借鉴这个事情就容易得多。这批文章就将这些hook列出来,帮大家节省时间。 主要的hook点为: 音频build属性连接上下文文件访问位置信息其他包管理传感器设置磁盘信息系统时钟系统属性电话相关wifi信息wifi…

uniapp微信小程序 引入腾讯视频插件

参考&#xff1a;微信小程序&#xff08;或uniapp&#xff09;引入腾讯视频插件播放视频_苏苏哇哈哈的博客-CSDN博客_微信小程序播放腾讯视频1.在manifest.json里面 "plugins": { "tencentvideo": { …

计算机图形学 着色(shader) 学习笔记

画家算法&#xff1a;从远到近的光栅化&#xff0c;近的物体的着色覆盖远的物体的着色&#xff0c;近的物体的RGB优先 实际计算机图形学使用的是Z-Buffer深度缓冲 先看地板&#xff0c;地板要渲染的像素先放进二位数组内&#xff0c;接下来要看正方体&#xff0c;正方体与之前…