Vue中图片上传组件封装-antd的a-upload二次封装-案例

Posted JackieDYH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue中图片上传组件封装-antd的a-upload二次封装-案例相关的知识,希望对你有一定的参考价值。

a-upload组件

api

const publicApi = 
  UploadImage: '/common/uploadImage',
  DeleteImage: '/common/deleteImage',


/**
 * 上传图片
 * @param * parameter
 * @returns
 */
export function UploadImage(parameter) 
  return request(
    url: publicApi.UploadImage,
    method: 'post',
    data: parameter
  )


/**
 * 删除图片 :name
 * @param * parameter
 * @returns
 */
export function DeleteImage(parameter) 
  return request(
    url: `$publicApi.DeleteImage/$parameter`,
    method: 'delete'
    // params: parameter
  )

组件封装

<template>
  <div class="upbase">
    <!-- 进度条-->
    <div v-show="progressVisible" class="progress-container">
      <div class="progress-bar"></div>
    </div>
    <a-upload
      v-if="!uploadType"
      :beforeUpload="beforeImageUpload"
      list-type="picture-card"
      :file-list="imageList"
      :multiple="multiple"
      :disabled="disabled"
      @change="handleImageChange"
      @preview="handlePreview"
      :custom-request="customRequest"
    >
      <div v-if="imageList.length < limitNum && !disabled">
        <a-icon type="plus" />
        <div class="ant-upload-text">上传</div>
      </div>
    </a-upload>

    <a-upload
      v-else
      name="file"
      :file-list="imageList"
      :beforeUpload="beforeImageUpload"
      :multiple="multiple"
      :disabled="disabled"
      :custom-request="customRequest"
      @change="handleImageChange"
    >
      <!-- list-type="picture" -->
      <div v-if="imageList.length < limitNum && !disabled">
        <a-button> <a-icon type="upload" /> 上传 </a-button>
      </div>
    </a-upload>

    <!-- 图片预览 -->
    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
      <img alt="example" style="width: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>

<script>
import  UploadImage, DeleteImage  from '@/api/public'

function getBase64(file) 
  return new Promise((resolve, reject) => 
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (error) => reject(error)
  )


function getName(url) 
  const list = url.split('/')
  return list[list.length - 1].split('.')[0]


export default 
  name: 'UpBase64',
  props: 
    defaultImageList: 
      type: Array,
      default: function () 
        return []
      ,
      required: true,
    ,
    // 组件展示样式
    uploadType: 
      type: Boolean,
      default: false,
      required: false,
    ,
    // 文件类型列表
    fileTypeList: 
      type: Array,
      default: function () 
        return []
      ,
      required: false,
    ,
    // 容量大小
    limitSize: 
      type: Number,
      default: 2,
      required: false,
    ,
    // 个数
    limitNum: 
      type: Number,
      default: 20,
      required: false,
    ,
    // 是否支持多选
    multiple: 
      type: Boolean,
      default: false,
      required: false,
    ,
    // 是否禁用
    disabled: 
      type: Boolean,
      default: false,
      required: false,
    ,
    dwidth: 
      type: Number,
      default: 0,
      require: false,
    ,
    dheight: 
      type: Number,
      default: 0,
      require: false,
    ,
  ,

  data() 
    return 
      previewVisible: false,
      progressVisible: false,
      progressValue: 10,
      previewImage: '',
      imageList: [],
    
  ,

  watch: 
    defaultImageList(newVal) 
      this.imageList = this.handleData(newVal)
    ,
  ,

  created() 
    this.imageList = this.handleData(this.defaultImageList)
  ,

  methods: 
    // ---------------------------------------------img--start
    // 上传格式限制
    beforeImageUpload(file) 
      return new Promise((resolve, reject) => 
        if (this.fileTypeList.length != 0) 
          const index = this.fileTypeList.indexOf(file.type)
          if (index <= -1) 
            this.$message.error(`您只能上传$this.fileTypeList文件`)
            return reject(new Error(`您只能上传$this.fileTypeList文件,不能传$file.type文件`))
          
        
        const limitSize = file.size / 1024 / 1024 < this.limitSize
        if (!limitSize) 
          this.$message.error(`文件大小不能大于$this.limitSizeMB`)
          return reject(new Error(`文件大小不能大于$this.limitSizeMB`))
        
        const checkSize = this.checkImageWH(file, this.dwidth, this.dheight)
        return Promise.resolve(checkSize)
          .then(() => resolve())
          .catch((e) => 
            reject(e)
          )
      )
    ,
    checkImageWH(file, width, height) 
      // 参数分别是上传的file,想要限制的宽,想要限制的高
      const that = this
      return new Promise(function (resolve, reject) 
        let filereader = new FileReader()
        filereader.onload = (e) => 
          let src = e.target.result
          const image = new Image()
          image.onload = function () 
            if ((width && this.width !== width) || (height && this.height !== height)) 
              // 上传图片的宽高与传递过来的限制宽高作比较,超过限制则调用失败回调
              const message = `图片宽高不满足,需要:宽 $width || '不限制',高 $height || '不限制'\\n,当前图片宽:$
                this.width
              ,高:$this.height`
              that.$message.error(message)
              reject(new Error(message))
             else 
              resolve( width: this.width, height: this.height )
            
          
          image.onerror = reject
          image.src = src
        
        filereader.readAsDataURL(file)
      )
    ,

    async handlePreview(file) 
      if (!file.url && !file.preview) 
        file.preview = await getBase64(file.originFileObj)
      
      this.previewImage = file.url || file.preview
      this.previewVisible = true
    ,

    handleCancel() 
      this.previewVisible = false
    ,
    // 自定义上传逻辑
    customRequest( action, file, onSuccess, onError, onProgress ) 
      this.progressVisible = true
      new Promise((resolve) => 
        const fileReader = new FileReader()
        // 转化为base64
        fileReader.readAsDataURL(file)
        fileReader.onload = async () => 
          let index = 
            uid: this.genId(5),
            name: file.name,
            status: 'done',
            url: fileReader.result,
          
          let params = 
            name: index.uid,
            data: index.url,
          
          try 
            let res = await UploadImage(params)
            index.url = res.result.url
            if (res.status == 1) 
              setTimeout(() => 
                this.imageList = [...this.imageList.filter((item) => item.status === 'done'), index]
                this.$message.success('文件上传成功!')
                this.progressVisible = false
                this.handleChange()
                resolve(fileReader.result)
              , 2000)
             else 
              this.imageList = [...this.imageList.filter((item) => item.status === 'done')]
              this.$message.success(res.msg)
              this.handleChange()
              resolve(fileReader.result)
            
           catch (error) 
            console.log('upimg:', error)
           finally 
          
        
      )
    ,
    // 处理事件
    async handleImageChange(info) 
      try 
        // 删除图片
        let res = await DeleteImage(getName(info.file.url))
        console.log(res, 89)
        if (res.status == 1) 
          this.$message.success('删除成功!')
         else 
          this.$message.error('删除失败!')
        
       catch (error) 
        // console.log('delimg:', error)
       finally 
        let fileList = [...info.fileList]
        this.imageList = fileList
        this.handleChange()
      
    ,

    handleChange() 
      let index = this.imageList
        .filter((item) => item.url)
        .map((item) => 
          return item.url
        )
      // if (index?.length <= 0) return
      this.$emit('change', index ? index : [])
    ,

    genId(length) 
      return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)
    ,

    handleData(list) 
      return list.map((item) => 
        let index = this.genId(5)
        return 
          uid: index,
          name: index,
          status: 'done',
          url: item,
        
      )
    ,

    // ---------------------------------------------img--end
  ,

</script>

<style lang="less" scoped>
.ant-upload-select-picture-card i 
  font-size: 32px;
  color: #999;


.ant-upload-select-picture-card .ant-upload-text 
  margin-top: 8px;
  color: #666;

</style>

<style>
.progress-container 
  width: 100px;
  height: 7px;
  background-color: #ffffff;
  border-radius: 5px;


.progress-bar 
  height: 100%;
  border-radius: 5px;
  animation-fill-mode: forwards;
  animation-name: progressBar;
  animation-iteration-count: infinite;
  background-color: #44cef6;
  animation-duration: 2s;
  animation-iteration-count: 1;


@keyframes progressBar 
  0% 
    width: 0%;
  

  100% 
    width: 100%;
  

</style>

使用

<template>
  <page-header-wrapper>
    <div class="khdztps">
      <div class="container">
        <div class="left">
          <div class="wrap">
            <div class="title">
              <h2>客户端底图上传</h2>
            </div>
            <span class="tips">*上传格式为“.jpg 和.png“,大小不得超过1M,(375*665)</span>
            <b-upload-image-base64
              ref="bUploadImageBase641"
              :limitNum="1"
              @change="imageChange($event, 'inviteBgImageList')"
              :defaultImageList="inviteBgImageList"
              :dwidth="375"
              :dheight="665"
            />
          </div>
          <div class="wrap">
            <div class="title">
              <h2>客户端ICON替换</h2>
            </div>
            <span class="tips">*上传格式只能为“.png”,大小不得超过300k,(24*24)x3</span>
            <div class="icon">
              <div class="wxz">
                <span class="title">未选中</span>
                <div class="imgBox">
                  <b-upload-image-base64
                    ref="bUploadImageBase642"
                    :limitNum="1"
                    @change="imageChange($event, 'inviteHomeImageList')"
                    :defaultImageList="inviteHomeImageList"
                    :dwidth="24 * 3"
                    :dheight="24 * 3"
                  />
                  
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <a-button type="primary" @click="saveSubmit">保存并预览</a-button>
    </div>
  </page-header-wrapper>
</template>

<script>
import  commitCustomConfigure, queryCustomConfigure  from '@/api/feedback'
import bUploadImageBase64 from '@/components/Plug/BUploadImageBase64.vue'

export default 
  name: 'Khdztps',
  components: 
    bUploadImageBase64,
  ,

  data() 
    return 
      inviteBgImageList: [],
      inviteHomeImageList: [],
      dataList: 
        BGUrl: '',
        HomeUrl: '',
      ,
    
  ,
  created() ,
  mounted() 
    this.queryCustomConfigure()
  ,
  methods: 
    saveSubmit() 
      this.commitCustomConfigure()
    ,
    // 保存
    async commitCustomConfigure() 
      try 
        let res = await commitCustomConfigure(this.dataList)
        console.log(res, 89)
        if (res.status == 1) 
          this.$message.success('设置成功!')
         else 
          this.$message.error(res.msg)
        
       catch (error) 
        console.log('sub:', error)
      
    ,
    // 获取 - 数据回填
    async queryCustomConfigure() 
      try 
        let res = await queryCustomConfigure()
        console.log(res, 89)
        if (res.status == 1) 
          // this.$message.success('成功!')
          this.dataList = res.result

          if (res.result.BGUrl) 
            this.inviteBgImageList.push(res.result.BGUrl)
          
          if (res.result.HomeUrl) 
            this.inviteHomeImageList.push(res.result.HomeUrl)
          
         else 
          this.$message.error(res.msg)
        
       catch (error) 
        console.log('sub:', error)
      
    ,
    // 图片上传成功赋值
    imageChange(e, key) 
      console.log(e, key)
      switch (key) 
        // 图片
        case 'inviteBgImageList':
          this.dataList.BGUrl = e[0] || ''
          break
        case 'inviteHomeImageList':
          this.dataList.Unselect.Home = e[0] || ''
          break
        default:
          break
      
    ,
  ,
  destroyed() ,
  activated() ,
  deactivated() ,

</script>

以上是关于Vue中图片上传组件封装-antd的a-upload二次封装-案例的主要内容,如果未能解决你的问题,请参考以下文章

antd引用<Upload>组件上传图片后再次上传清除缓存

react--封装上传组件

AntD框架的upload组件上传图片时使用customRequest方法自定义上传行为

antd 封装弹窗编辑组件 分页组件

antd vue里面 a-table再次封装,slot-scope如何跨组件传递?

二次封装antd-mobile组件库