需求:
vue后台项目实现图片上传;
代码:
先安装组件
<el-form-item label="轮播图">
<div v-if="imageListArr.length != 0" class="mainDrawing">主图</div>
<div class="draggableBox">
<draggable v-model="imageListArr" @update="datadragEnd(0)">
<transition-group>
<!-- 使用 before-upload 限制用户上传的图片格式和大小。上传文件之前的钩子,参数为上传的文件
http-request覆盖默认的上传行为,可以自定义上传的实现-->
<div class="mh-up-w" v-for="(item, idx) of imageListArr" @click="setItemIdx(idx, 0)" :key="item.imgUrl">
<el-upload class="avatar-uploader" action="" :show-file-list="false"
:before-upload="imageUploadRegForMore" :http-request="emitUploadForMore">
<div v-loading="detailImageUploadLoading && currentUpFileIdx == idx">
<img v-if="item.imgUrl" :src="item.imgUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</div>
</el-upload>
<div class="mh-up-h-w" v-if="item.imgUrl && item.imgUrl != ''">
<span class="up-h-i" @click="deleteUpFile(idx, 0)"><i class="el-icon-delete"></i></span>
<span class="up-h-i"><i class="el-icon-rank"></i></span>
</div>
</div>
</transition-group>
</draggable>
<div class="tip-txt-w">
<span>提示:支持JPG或PNG两种格式,图片大小不超过1M;最多上传10张;拖动调整顺序;默认第一张图为主图;上传商品图片同步全区域。</span>
</div>
</div>
</el-form-item>
<script>
import Draggable from 'vuedraggable'
data() {
return {
// 商品图临时使用 imgUrl: 图片地址 sortNum: 序号
imageListArr: [
{
imgUrl: '',
sortNum: ''
}
],
detailImageUploadLoading: false,
currentUpFileIdx: -1,
}
},
components: {
'draggable': Draggable,
},
methods: {
/**
* [datadragEnd 拖拽结束]
* @return {[type]} [description]
*/
datadragEnd (evt) {
// 拖拽图片更换位置 并重新从1开始排序
this.imageListArr.forEach((item, index) => {
item.sortNum = index + 1
})
this.imageListArr = this.imageListArr.filter(item => {
return item.imgUrl != ''
});
let imageListItem = {
imgUrl: '',
sortNum: ''
}
this.imageListArr.push(imageListItem)
},
// 设置当前选中索引
setItemIdx (idx, type) {
if (this.detailImageUploadLoading) return
this.currentUpFileIdx = idx
},
// 删除当前图片
deleteUpFile (_idx, type) {
this.$confirm('确定删除当前图片吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.imageListArr = this.imageListArr.filter((item, idx) => {
return idx != _idx
})
this.imageListArr.forEach((item, index) => {
item.sortNum = index + 1
})
})
},
// 校验上传图片格式大小
imageUploadRegForMore (file) {
const isPic = file.type.indexOf('image/') !== -1
const isJPG = (file.type === 'image/jpeg' || file.type === 'image/png')
const isSizeNum = file.size <= 1 * 1024 * 1024
if (!isPic) {
this.$message.error('支持JPG或PNG两种格式,图片大小不超过1M;最多上传10张;拖动调整顺序;上传商品图片同步全区域。')
return false
}
if (!isJPG) {
this.$message.error('支持JPG或PNG两种格式,图片大小不超过1M;最多上传10张;拖动调整顺序;上传商品图片同步全区域。')
return false
}
if (!isSizeNum) {
this.$message.error('支持JPG或PNG两种格式,图片大小不超过1M;最多上传10张;拖动调整顺序;上传商品图片同步全区域。')
return false
}
return isPic && isJPG && isSizeNum
},
// 上传到服务器,并对图片数组做处理
emitUploadForMore (e) {
if (this.imageListArr.length > 10 && this.currentUpFileIdx != -1) {
this.$message.error('最多可添加10张')
return
}
this.detailImageUploadLoading = true
let loginInfo = Storage.get('loginInfo') || {}
let formdata = new FormData()
let file = e.file
formdata.append('file', file)
this.$http.post(url.goodsMgt.uploadFile + '?baseDir=web/bazzarIcon&fileType=img&systemName=bazzar_web', formdata, {
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': `${loginInfo.token_type} ${loginInfo.access_token}`
}
})
.then((res) => {
this.detailImageUploadLoading = false
let urlImage = res.data.url;
this.setImgUrl(this.currentUpFileIdx, urlImage, 0)
if (this.currentUpFileIdx != -1) {
let hash = {}
let imageListItem = {
// imgType: 22,
imgUrl: '',
sortNum: ''
}
this.imageListArr.push(imageListItem)
// 去重 防止多个空对象
this.imageListArr = this.imageListArr.reduceRight((item, next) => {
hash[next.imgUrl] ? '' : hash[next.imgUrl] = true && item.push(next)
return item
}, [])
this.imageListArr.reverse()
}
})
.catch((err) => {
this.detailImageUploadLoading = false
})
},
// 将上传的图片放入数组里
setImgUrl (_idx, _imgUrl, type) {
let urlImage = _imgUrl
let currentIdx = _idx
this.imageListArr.forEach((item, index) => {
if (index === currentIdx) {
this.imageListArr[index].imgUrl = urlImage
this.imageListArr[index].sortNum = parseInt(currentIdx) + 1
}
})
},
// 获取详情
getGoodsDetail(id) {
this.$http.post(url.goodsMgt.goodsDetail, { id }).then((res) => {
if (res.code == 0) {
this.goodsInfo = res.data,
this.imageListArr = res.data.goodsSquareImgList || []
let imageListItem = {
imgUrl: '',
sortNum: ''
}
// 初始化图片,将空塞入最后一项作为➕号展示
this.imageListArr.push(imageListItem)
}
})
},
// 保存
save() {
this.goodsInfo.goodsSquareImgList = this.imageListArr.filter(item => {
return item.imgUrl
})
this.$http
.post(url.goodsMgt.updateGoods, {
...this.goodsInfo,
id: this.id
})
.then((response) => {
this.loading = false
if (response.code === 0) {
this.$notify.success('保存成功')
this.back()
return
}
throw new Error(response.msg)
})
.catch((e) => {
this.loading = false
this.$message.error(e.message)
})
},
}
</script>
<style>
/* 轮播图 */
/* @import '../../../../assets/file_upload.css'; */
.mh-up-w {
float: left;
margin-left: 10px;
}
.mh-up-w:first-child {
margin-left: 0;
}
.mh-up-h-w {
padding: 0 5px;
line-height: 0;
margin-top: -8px;
margin-bottom: 8px;
text-align: center;
}
.up-h-i {
cursor: pointer;
padding-left: 6px;
padding-right: 6px;
}
.up-h-i:hover {
color: #3080fe;
}
.draggableBox {
width: 600px;
}
.avatar-uploader {
width: 110px;
height: 110px;
display: inline-block;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
/* .tip-txt-w {
display: inline-block;
margin-left: 10px;
vertical-align: top;
} */
.avatar-uploader:hover {
border-color: #409EFF;
}
</style>