开始用el-upload,发现:file-list绑定的只是用来预览,并不是双向绑定(此处没有时间再继续深入研究)。
自己写了一个el-upload组件,用于多图片的增删改,最终返回promise对象,方便表单提交前用PromiseAll检查多个该组件全部上传成功后提交表单。
抛砖引玉欢迎大家指点(其实我还没怎么测)。
<template>
<div>
<el-upload
ref="imgUpload"
class="upload-img"
action=""
:class="{hide:hideUploadEdit}"
list-type="picture-card"
:on-remove="handleRemove"
:on-change="handleChange"
:auto-upload="false"
accept=".png, .jpg"
:limit="limit"
:on-exceed="handleExceed"
:multiple="true"
:file-list="previewObject"
>
<i class="el-icon-plus" />
<div slot="tip" class="el-upload__tip">{{ $t('product.SPCImgDrawUploadTip') }}</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import * as _ from 'lodash'
import axios from 'axios'
import { getToken } from '@/utils/auth'
export default {
name: 'ImgEditUpload',
props: {
// 要上传的链接
url: {
type: String,
required: true
},
// 限制文件数
limit: {
type: Number,
default: 1
},
// 图片预览拼接字符串,以"|"分割
previewUrlStr: {
type: String,
default: ''
},
// 最大文件大小:5M
maxFileSize: {
type: Number,
default: 5
}
},
data() {
return {
// 预览图片dialog开关
dialogVisible: false,
// 预览对象,用于显示已有文件
previewObject: [],
// 预览对象用于显示已有文件备份,用于重置后恢复
previewObjectBack: [],
// 是否到达最大文件,隐藏后面的上传栏
hideUploadEdit: false,
// 已上传文件数组
haveUploadedFileList: [],
// 预览图片dialog url
dialogImageUrl: ''
}
},
mounted() {
this.initUploadFileFormat()
},
methods: {
// 初始化文件格式
initUploadFileFormat() {
if (this.previewUrlStr === null || this.previewUrlStr === '') {
this.previewObject = []
} else {
const imgUrlStrArr = this.previewUrlStr.split('|')
const imgObjectArr = []
for (const urlStr of imgUrlStrArr) {
const tempImgObject = {}
// 未展示文件名,此处以后应使用正则
tempImgObject['name'] = 'test'
tempImgObject['url'] = urlStr
imgObjectArr.push(tempImgObject)
}
this.previewObject = imgObjectArr
// 防止出现过多的上传组件
this.hideUploadEdit = (imgObjectArr.length >= this.limit)
// 备份一份用于重置
this.previewObjectBack = _.cloneDeep(this.previewObject)
}
},
// The hook function of add product draw upload file
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
// The number of uploads exceeded the limit
handleExceed() {
this.$message.error(`目前最多只支持${this.limit}个`)
},
// THe hook function of remove product img upload file
handleRemove(file, fileList) {
this.haveUploadedFileList = fileList
this.hideUploadEdit = fileList.length >= this.limit
},
handleChange(file, fileList) {
this.haveUploadedFileList = fileList
this.hideUploadEdit = (fileList.length >= this.limit)
},
// Check the size of file and the type of file before the upload file
checkFile(fileRaw) {
const isJPG = fileRaw.type === 'image/jpeg' || fileRaw.type === 'image/png'
const isLt2M = fileRaw.size / 1024 / 1024 < this.maxFileSize
if (!isJPG) {
this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
return false
}
if (!isLt2M) {
this.$message.error(`上传图片大小不能超过${this.maxFileSize}MB!`)
return false
}
return isJPG && isLt2M
},
customSubmit() {
if (this.haveUploadedFileList.length !== 0) {
// 有上传的新文件,或者删除过上传过的文件
// 已经上传过的文件
const previewUrlArr = []
// 需要上传的文件raw
const needUploadUrlRawArr = []
for (const file of this.haveUploadedFileList) {
if (file['status'] === 'success') {
previewUrlArr.push(file['url'])
continue
}
// 检查文件失败
if (!this.checkFile(file.raw)) {
return false
} else {
// 加入需要上传数组
needUploadUrlRawArr.push(file.raw)
}
}
// 如果有新文件就上传
if (needUploadUrlRawArr.length !== 0) {
const formData = new FormData()
for (const raw of needUploadUrlRawArr) {
formData.append('fileList', raw)
}
return new Promise((resolve, reject) => {
axios({
url: this.url,
method: 'post',
data: formData,
headers: { 'Content-Type': 'multipart/form-data', 'X-Token': getToken() }
}).then(res => {
if (res.data.success === true) {
// 预览的图片和上传后的图片url数组返回
resolve({ type: 2, urlArr: [...previewUrlArr, ...(res.data.data.url)] })
} else {
reject(res.data.message)
}
})
})
} else {
// 没有新文件上传
return new Promise((resolve) => {
resolve({ type: 1, urlArr: [...previewUrlArr] })
})
}
} else if (this.haveUploadedFileList.length !== 0 && this.$refs.imgUpload.uploadFiles.length !== 0) {
// 没有修改过已预览图片
return new Promise((resolve) => {
resolve({ type: 0, urlArr: [] })
})
} else if ((this.haveUploadedFileList.length === 0 && this.$refs.imgUpload.uploadFiles.length === 0)) {
// 清空了所有图片
return new Promise((resolve) => {
resolve({ type: 3, urlArr: [] })
})
}
}
}
}
</script>
<style scoped lang="scss">
// 隐藏上传按钮
::v-deep .hide .el-upload--picture-card {
display: none;
}
// 添加/删除文件时去掉动画过渡
::v-deep .el-upload-list__item {
transition: none !important;
}
</style>