Bootstrap

第一次的upload记录

首先是整体代码
这个项目是用了v-for的多个上传,分别进行各自的上传,预览,回显。
可以适当无视v-if等

<el-upload
:ref="'upload'+item.whNo"
:class="[{disabled:fileMap.get(item.whNo)!==undefined},{disabled:item.receiptStatus==='正常'},'uploadclass']"
:action="uploadUrl"
:file-list="photoList[i]"
:data="getuploadP(item)"
list-type="picture-card"
:on-success="function (response, file, fileList){ return uploadSuccess(response, file, fileList, i)}"
:on-remove="handleRemove"
:before-upload="beforeAvatarUpload"
:on-error="uploadError"
accept=".jpg,.png,.BMP"
:on-change="function (file, fileList) { return changePic(file, fileList, item.whNo)}"
>
<img src="@/assets/img/numberBack/tp.png" style="padding-top: 30px">
<div slot="file" slot-scope="{file}">
  <img
    class="el-upload-list__item-thumbnail"
    :src="file.url"
  >
  <span class="el-upload-list__item-actions">
    <span
      class="el-upload-list__item-preview"
      @click="handlePictureCardPreview(file)"
    >
      <i class="el-icon-zoom-in" />
    </span>
    <span
      v-if="!disabled&&shangyibudaohegui!=='2'&&quanxianxx==='1'&&quxiaobtnxy"
      class="el-upload-list__item-delete"
      @click="handleRemove(file,item.whNo)"
    >
      <i class="el-icon-delete" />
    </span>
  </span>
</div>
</el-upload>
<!--放大用的-->
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<div class="uploadbtn">
<!-- <el-button size="mini" icon="el-icon-full-screen" @click="yulan(i)">预览</el-button>-->
<el-button v-if="fileMap.get(item.whNo)===undefined&&item.receiptStatus!=='正常'&&quanxianxx==='1'" class="cxscbtn" icon="el-icon-upload2" size="mini" style="width: 70px" main @click="cxsc('upload'+item.whNo, 0)">上传</el-button>
<el-button v-else-if="fileMap.get(item.whNo)!==undefined&&item.receiptStatus==='正常'&&shangyibudaohegui!=='2'&&quanxianxx==='1'&&quxiaobtnxy" class="cxscbtn" icon="el-icon-refresh-left" size="mini" main @click="cxsc('upload'+item.whNo, 1)">重新上传</el-button>
<p  class="tsp">支持jpg/png/bmp等格式,不超过5M</p>
<!-- <p class="tsp" v-if="quanxianxx==='1'" style="color: red">图片上传,请勿重复上传</p> -->
</div>

然后是data

//这个uploadUrl知道咋回事得了
uploadUrl: '.' + process.env.VUE_APP_BASE_API + '/api/complianceCheck/uploadFile',
fileMap: new Map(),
dialogImageUrl: '',
dialogVisible: false,
photoList: [],

先进行el-upload的记录

<el-upload
 	:ref="'upload'+item.whNo" // $refs来区分每一个上传。 item.whNo我需在意,是项目一个参数
  	:class="[{disabled:fileMap.get(item.whNo)!==undefined},{disabled:item.receiptStatus==='正	常'},'uploadclass']"    //项目上传样式状态的改变
  	:action="uploadUrl"   //必传参数,是地址
 	:file-list="photoList[i]"    //做回显时才添加的,记录了页面初次进入调用接口获取的回显数据。i不用说,就是v-for的下标
  	:data="getuploadP(item)"   //附带参数,,没啥说的
  	list-type="picture-card"   
 	:on-success="function (response, file, fileList){ return uploadSuccess(response, file, fileList, i)}"//成功回调,这个写法学到了
  	:on-remove="handleRemove"    //文件列表移除文件时的钩子
  	:before-upload="beforeAvatarUpload"    //上传文件之前的钩子
  	:on-error="uploadError"    //失败回调
  	accept=".jpg,.png,.BMP"   //接受上传的文件类型
  	:on-change="function (file, fileList) { return changePic(file, fileList, item.whNo)}" //文件状态改变时的钩子,在这里做了一些事情
>     
<img src="@/assets/img/numberBack/tp.png" style="padding-top: 30px"> //组件哪个加号图片,随便换
<div slot="file" slot-scope="{file}">
   <img
     class="el-upload-list__item-thumbnail"
     :src="file.url"   //上传,回显的图片都显示在这里了
   >
   <span class="el-upload-list__item-actions">
     <span
       class="el-upload-list__item-preview"
       @click="handlePictureCardPreview(file)"   //组件自带放大预览
     >
       <i class="el-icon-zoom-in" />
     </span>
     <span
       v-if="!disabled&&shangyibudaohegui!=='2'&&quanxianxx==='1'&&quxiaobtnxy"
       class="el-upload-list__item-delete"
       @click="handleRemove(file,item.whNo)"   图片删除功能
     >
       <i class="el-icon-delete" />
     </span>
   </span>
 </div>
 </el-upload>
<!--放大用的-->    就是那个自带的预览
                <el-dialog :visible.sync="dialogVisible">
                  <img width="100%" :src="dialogImageUrl" alt="">
                </el-dialog>
                <div class="uploadbtn">
<div class="uploadbtn">
	<!-- <el-button size="mini" icon="el-icon-full-screen" @click="yulan(i)">预览</el-button>--> 没有了,自己琢磨吧
	<el-button v-if="fileMap.get(item.whNo)===undefined&&item.receiptStatus!=='正常'&&quanxianxx==='1'" class="cxscbtn" icon="el-icon-upload2" size="mini" style="width: 70px" main @click="cxsc('upload'+item.whNo, 0)">上传</el-button> //无视v-if,这不就用上ref了么
	<el-button v-else-if="fileMap.get(item.whNo)!==undefined&&item.receiptStatus==='正常'&&shangyibudaohegui!=='2'&&quanxianxx==='1'&&quxiaobtnxy" class="cxscbtn" icon="el-icon-refresh-left" size="mini" main @click="cxsc('upload'+item.whNo, 1)">重新上传</el-button>
	<p  class="tsp">支持jpg/png/bmp等格式,不超过5M</p>
</div>

methods

getuploadP(item) {      // :data的,上传时附带的额外参数
  return {
    uploadType: 1,
    dcNo: item.dcNo,
    whNo: item.whNo,
    receiptConsignLetterAddress: item.receiptConsignLetterAddress,
    projectid: this.projectid
  }
},
uploadSuccess(response, file, fileList, index) { //上传成功后有用的信息扔到form里了
  console.log(response)
  this.sxcg.push(response.data.imgUrl)
  this.form[index].objKey = response.data.objKey
  this.form[index].receiptStatus = response.data.receiptStatus
  this.form[index].imgUrl = response.data.imgUrl
  this.form.push({})
  this.form.pop()
},    
beforeAvatarUpload(file) {  //这不就上传前的验证嘛,讲真,还没有测试过,不知道有效了没。。
  const isJPG = file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/BMP'
  const isLt2M = file.size / 1024 / 1024 < 5

  if (!isJPG) {
    this.$message.error('上传图片只能是 JPG,PNG,BMP 格式!')
  }
  if (!isLt2M) {
    this.$message.error('文件大小不能超过5M')
  }
  return isJPG && isLt2M
},
uploadError() {      //失败
      this.$message.error('上传失败,请重新上传')
    },
handlePictureCardPreview(file) {     自带的预览功能
      this.dialogImageUrl = file.url    
      this.dialogVisible = true
    },    

下面几个我自认需要学习一下

handleRemove(file, id) {    //图片的删除
  this.$refs['upload' + id][0].clearFiles()  //组件方法
  this.fileMap.delete(id)
  this.$forceUpdate()  //vue强制更新
},
changePic(file, fileList, id) {        //on-change方法
      if (fileList.length > 1) {
        fileList.shift()
      }
      this.fileMap.set(id, { file: file, disSign: true })
      this.$forceUpdate()
    },
hqwthxx() {    页面初次加载,获取页面数据,回显也在这里,应用了base64的转换
// 别删
  const body = []   发送给后端的参数,依照项目多种情况的判断,可无视
  if (this.mainidnum || this.mainIdd) {
    if (this.mainidnum) {
      if (this.dcno && this.whno) {
        console.log('this.dcno && this.whno', this.dcno && this.whno)
        body.push({
          dcNo: this.dcno,
          whNo: this.whno,
          mainId: this.mainidnum
        })
      }
    } else {
      if (this.dcno && this.whno) {
        console.log('this.dcno && this.whno', this.dcno && this.whno)
        body.push({
          dcNo: this.dcno1,
          whNo: this.whno1,
          mainId: this.mainIdd
        })
      }
    }
  } else {
    if (this.bcfs === '2') {
      console.log('this.bcfs')
      body.push({
        dcNo: this.pszx,
        whNo: this.qcMdc
      })
    } else {
      this.target.forEach(item => {
        console.log('target.forEach', this.target)
        body.push({
          dcNo: this.pszx,
          whNo: item.id
        })
      })
    }
  }
  Axios.post('/api/complianceCheck/getReceiptConsignList', body).then(res => {
    res.data.receiptConsignVoList.forEach((item, index) => {
      this.photoList.push([])     //这里,回显信息放到photoList,([])是组件要求,需要是[]
      this.toBase64(item.receiptConsignAddress, item.whNo, index)   //base64转换,参数是图片地址,项目应用信息一个,index下标,
    })
    this.form = res.data.receiptConsignVoList  //信息放到form里了
  })
},

base64,没啥说的,但是this.$set的用法你不学一下么

toBase64(imgUrl, kfzxh, index) {
      let imageUrl = ''
      console.log('toBase64')
      if (imgUrl !== null && imgUrl !== '') {
        console.log('toBase64->imgUrl is not null')
        imageUrl = imgUrl.replace('http://storage.jd.local', '/getJssImage')
      }
      console.log('imageUrl->' + imageUrl)

      // 一定要设置为let,不然图片不显示
      const image = new Image()
      // 解决跨域问题
      image.crossOrigin = ''
      image.setAttribute('crossOrigin', 'anonymous')
      image.src = imageUrl
      // image.onload为异步加载
      image.onload = () => {
        var canvas = document.createElement('canvas')
        canvas.width = image.width
        canvas.height = image.height
        var context = canvas.getContext('2d')
        context.drawImage(image, 0, 0, image.width, image.height)
        var quality = 0.8
        // 这里的dataurl就是base64类型
        // 使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
        const dataurl = canvas.toDataURL('image/jpeg', quality)
        this.$set(this.photoList, index, [new Photo(kfzxh, dataurl)])//放到photoList里,替换掉第index个,替换内容为[new Photo(kfzxh, dataurl)]
      }
    },

对了,别忘了这个

class Photo {
  constructor(name, url) {
    this.name = name
    this.url = url
  }
}

export default {  //写哪知道了吧。。。

然后是上传按钮和重新上传按钮
百度发现了$refs[‘upload-inner’].handleClick()

cxsc(id, sign) {
      if (sign === 0) { // 上传
        this.$refs[id][0].$refs['upload-inner'].handleClick()
      } else { // 重新上传
        this.$refs[id][0].$refs['upload-inner'].handleClick()
      }
      console.log('cxsc')
    }

差个小样式,不要丢了
图片上传一个后none掉上传框

.disabled >>> .el-upload--picture-card {
  display: none;
}
;