子组件(图片压缩自行npm下载)
<template>
<div :class="{ 'hide': fileLength >= limit }">
<!-- 图片上传 -->
<el-upload ref="uploadImg" name="upload" class="uploadImg" :class="{ uploadImgSmall: size == 'small' }"
:action="actionUrl" :disabled="componentDisabled" :list-type="listType" :show-file-list="showFileList"
:limit="limit" :multiple="multiple" :file-list="bindFileList" :before-upload="beforeAvatarUpload"
:on-change="handlePictureChange" :on-success="handlePictureSuccess" :on-error="handlePictureError"
:on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-exceed="handleExceed">
<!-- 富文本上传图片 -->
<div v-if="viewType == 'richtText'">
<el-button :loading="componentLoading" icon="el-icon-upload" size="mini" type="primary">上传图片</el-button>
</div>
<!-- 表单上传图片 -->
<div v-if="viewType == 'picture'">
<i class="el-icon-plus" />
</div>
</el-upload>
<!-- 图片预览 -->
<el-dialog :visible.sync="dialogVisible" append-to-body>
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import * as imageConversion from 'image-conversion'
export default {
props: {
value: {
type: [Array, String],
default: []
},
// 是否多选
multiple: {
type: Boolean,
default: false
},
// 最多选择多少张
limit: {
type: Number,
default: 20
},
// 上传路径
action: {
type: String,
default: ''
},
// 是否禁用
disabled: {
type: Boolean,
default: false
},
// 是否显示已上传文件列表
showFileList: {
type: Boolean,
default: true
},
// 文件列表的类型 text/picture/picture-card
listType: {
type: String,
default: 'picture-card'
},
// 图片路径前缀
target: {
type: String,
default: ''
},
// 显示样式
viewType: {
type: String,
default: 'picture'
},
// 组件大小控制 默认不传
// 可选值 [small]
size: {
type: String,
default: ''
}
},
data() {
return {
// 绑定值类型
valueTypeof: this.value ? typeof this.value : 'string',
// 上传api路径
actionUrl: 'http://admin.qiuxiangjk.com:8087/admin/common/upload',
// 上传文件显示
bindFileList: [],
// 上传文件记录
propsList: [],
// 图片预览
dialogVisible: false,
dialogImageUrl: '',
// 组件loading
componentLoading: false,
// 当前的文件长度
fileLength: 0,
// 上传图片状态记录
uploadState: {
checkedFileLength: 0, // 选择的图片数量
fulfilFileLength: 0 // 上传完成的图片数量
},
// Element notify通知 Promise 对象
notifyPromise: Promise.resolve()
}
},
watch: {
value(e) {
// let tempValue = this.value || ''
// console.log('图片1111',tempValue)
// if (this.valueTypeof === 'string') {
// tempValue = tempValue ? tempValue.split(',') : []
// console.log('图片222',tempValue)
// }
// this.fileLength = tempValue.length
// tempValue.forEach((item, index) => {
// this.bindFileList.push({
// name: item,
// url: this.target + item,
// response: {
// code: 1,
// data: item
// }
// })
// })
},
},
computed: {
componentDisabled() {
console.log('图片', this.componentLoading + '----' + this.disabled)
return this.componentLoading || this.disabled
}
},
created() {
// 数据处理
let tempValue = this.value || ''
if (this.valueTypeof === 'string') {
tempValue = tempValue ? tempValue.split(',') : []
console.log('图片', tempValue)
}
this.fileLength = tempValue.length
tempValue.forEach((item, index) => {
this.bindFileList.push({
name: item,
url: this.target + item,
response: {
code: 1,
data: item
}
})
})
},
methods: {
// 重置数据
reset_data() {
console.log('重置图片')
// 数据处理
this.$refs.uploadImg.clearFiles()
},
// 图片上传限制
beforeAvatarUpload(file) {
const fileSize = file.size / 1024 // 单位KB
const isImg = file.type == 'image/jpeg' || file.type == 'image/jpg' || file.type == 'image/png' || file.type == 'image/gif' || file.type == 'image/webp'
if (!isImg) {
this.notifyPromise = this.notifyPromise.then(() => {
this.$notify.error({ title: '错误提示', message: file.name + '格式错误' })
})
return false
}
if (fileSize < 2) {
this.notifyPromise = this.notifyPromise.then(() => {
this.$notify.error({ title: '错误提示', message: file.name + '不能小于 2KB!' })
})
return false
}
this.componentLoading = true
this.uploadState.checkedFileLength++
if (fileSize / 1024 > 2) {
return new Promise((resolve, reject) => {
imageConversion.compressAccurately(file, 500).then(res => {
resolve(res)
})
})
}
return true
},
// 文件状态改变时
handlePictureChange(file, fileList) {
this.fileLength = fileList.length
},
// 图片上传成功
handlePictureSuccess(response, file, fileList) {
this.uploadState.fulfilFileLength++
if (this.uploadState.fulfilFileLength === this.uploadState.checkedFileLength) {
this.emitInputFun(fileList)
}
},
// 图片上传失败
handlePictureError(err, file, fileList) {
this.uploadState.fulfilFileLength++
this.notifyPromise = this.notifyPromise.then(() => {
this.$notify.error({ title: '错误提示', message: file.name + '上传失败' })
})
if (this.uploadState.fulfilFileLength === this.uploadState.checkedFileLength) {
this.emitInputFun(fileList)
}
},
// 图片删除
handleRemove(file, fileList) {
this.fileLength = fileList.length
if (this.uploadState.fulfilFileLength === this.uploadState.checkedFileLength) {
this.emitInputFun(fileList)
}
},
// list图片预览
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
// 图片超出数量限制
handleExceed() {
this.$message.error('图片超过限制')
},
// 响应数据
emitInputFun(fileList) {
let tempValue = []
fileList.forEach(item => {
if (item.response && item.response.code === 0) {
tempValue.push(item.response.result)
}
})
if (this.valueTypeof == 'string') {
tempValue = tempValue.join(',')
}
this.$emit('input', tempValue)
// 通知父级执行form验证
this.$emit('callBack')
this.componentLoading = false
}
}
}
</script>
<style scoped>
.hide>>>.el-upload {
display: none;
}
.el-button+.el-button {
margin-left: 0;
}
/*small组件*/
.uploadImgSmall>>>.el-upload-list--picture-card .el-upload-list__item {
width: 80px;
height: 80px;
}
.uploadImgSmall>>>.el-upload--picture-card {
width: 80px;
height: 80px;
line-height: 88px;
}
</style>
全局引用main.js
// 上传图片
import UploadImage from '@/components/UploadImage/index';
// 全局组件挂载
Vue.component('UploadImage', UploadImage)
父组件(表单提交为防止新增的时候出现图片回显添加重置上传图片方法 this.$refs.reset.reset_data())
<UploadImg
v-if="!pageLoading"
v-model="postForm.img_url"
action="/service/webPCBack/imgUploading.ashx?par=BannerUploadimg"
:limit="1"
@callBack="$refs.postForm.validateField('img_url')"
ref="reset"
/>
提交的时候重置上传图片数据防止新增的时候回显图片
this.$refs.reset.reset_data()