1、img-upload.vue
可以设置拖拽上传、点击上传、限制上传数量、大小、上传方法、多选、预览等
<template>
<div>
<!-- 拖拽上传 -->
<div v-if="isDrag">
<el-upload :action="uploadUrl" :file-list="imgList" class="upload-demo" list-type="picture" drag
:show-file-list="true" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError"
:on-change="changeFile" :before-upload="beforeUpload" :multiple="isMultiple" :limit="limit"
:on-exceed="handleExceed" :class="{ dragDisabled: fileLimit }">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
<div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
</div>
<!-- 点击上传 -->
<div v-else>
<el-upload :action="uploadUrl" :file-list="imgList" list-type="picture-card" :show-file-list="true"
:on-preview="handlePreview" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError"
:on-change="changeFile" :before-upload="beforeUpload" :limit="limit" :on-exceed="handleExceed"
:multiple="isMultiple" :class="{ disabled: fileLimit }">
<i class="el-icon-plus"></i>
<div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
</el-upload>
</div>
<!-- 预览图片 -->
<el-dialog :visible.sync="showDialog" title="图片预览">
<img :src="imgUrl" alt="" style="width:100%">
</el-dialog>
</div>
</template>
<script>
import { uploadImg } from '@/utils/request'
export default {
props: {
isDrag: {
type: Boolean,
default: false
},
isMultiple: {
type: Boolean,
default: true
},
limit: {
type: Number,
default: 9
},
propsList: {
type: [String, Array],
default: () => []
}
},
data() {
return {
uploadUrl: process.env.VUE_APP_IMG_API,
imgList: [],
imgUrl: '',
showDialog: false
}
},
computed: {
// 隐藏上传按钮
fileLimit() {
return this.imgList.length === this.limit
}
},
methods: {
// 上传成功
handleSuccess(response, file, fileList) {
this.imgList.push({
url: response.data
})
this.$emit('updateImg', this.imgList)
this.$emit('handleSuccess', response)
},
handlePreview(file) {
this.imgUrl = file.url
this.showDialog = true
},
// 图片变更
changeFile(file, fileList) {
// this.fileList = [...fileList]
// this.fileList = fileList.map(item => item)
},
// 删除图片
handleRemove(file) {
this.imgList = this.imgList.filter(item => item.uid !== file.uid)
this.$emit('updateImg', this.imgList)
},
handleError(e) {
console.log(e);
},
// 上传前操作
beforeUpload(file) {
const isImage = /\.(jpg|jpeg|png|bmp)$/i.test(file.name);
const isLt2M = file.size / 1024 / 1024 < 5;
if (!isImage) {
this.$message.error('上传文件只能是jpg、jpeg、png或bmp格式!');
return false;
}
if (!isLt2M) {
this.$message.error('上传文件大小不能超过 5MB!');
return false;
}
return true;
},
handleExceed(file, fileList) {
this.$message.error(`只能上传${this.limit}张图片`);
}
},
watch: {
propsList(newVal) {
if (typeof newVal === 'string' && newVal.trim().length) {
let arr = newVal.split(',')
arr.map(item => {
this.fileList.push({
url: item
})
})
} else if (Array.isArray(newVal)) {
this.fileList = newVal;
} else {
this.fileList = []
}
}
}
}
</script>
<style lang="scss" scoped>
.dragDisabled> :nth-child(1) {
display: none;
}
.disabled> :nth-child(2) {
display: none;
}
</style>
2、自定义上传方法(这里使用自己的七牛云,免费哦)
<template>
<div>
<!-- 拖拽上传 -->
<div v-if="isDrag">
<el-upload :http-request="upload" action="#" :file-list="fileList" class="upload-demo" list-type="picture" drag
:show-file-list="true" :on-remove="handleRemove" :on-error="handleError" :before-upload="beforeUpload"
:multiple="isMultiple" :limit="limit" :on-exceed="handleExceed" :class="{ dragDisabled: fileLimit }">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
<div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
</div>
<!-- 点击上传 -->
<div v-else>
<el-upload :http-request="upload" action="#" :file-list="fileList" list-type="picture-card" :show-file-list="true"
:on-preview="handlePreview" :on-remove="handleRemove" :on-error="handleError" :before-upload="beforeUpload"
:limit="limit" :on-exceed="handleExceed" :multiple="isMultiple" :class="{ disabled: fileLimit }">
<i class="el-icon-plus"></i>
<div class="el-upload__tip" slot="tip">只能上传{{ limit }}张图片,且不超过5M</div>
</el-upload>
</div>
<el-progress :percentage="uploadProgress" v-if="uploadProgress" :stroke-width="15" :text-inside="true"
status="success"></el-progress>
<!-- 预览图片 -->
<el-dialog :visible.sync="showDialog" title="图片预览">
<img :src="imgUrl" alt="" style="width:100%">
</el-dialog>
</div>
</template>
<script>
import * as qiniu from 'qiniu-js';
import { mapGetters } from 'vuex';
export default {
props: {
isDrag: {
type: Boolean,
default: false
},
isMultiple: {
type: Boolean,
default: false
},
limit: {
type: Number,
default: 9
},
propsList: {
type: [String, Array],
default: () => []
}
},
data() {
return {
fileList: [], // 所有图片
imgUrl: '', // 预览图片地址
showDialog: false, // 预览图片弹框
baseUrl: process.env.VUE_APP_IMG_API, // 七牛云地址
uploadProgress: 0, // 进度条
observable: null, // 上传实例
}
},
computed: {
...mapGetters(['qiNiuToken']),
// 隐藏上传按钮
fileLimit() {
return this.fileList.length === this.limit
}
},
methods: {
handlePreview(file) {
this.imgUrl = file.url;
this.showDialog = true;
},
// 删除图片
handleRemove(file) {
this.fileList = this.fileList.filter(item => item.uid !== file.uid)
this.$emit('updateImg', this.fileList)
},
handleError(e) {
console.log(e);
},
// 上传前操作
beforeUpload(file) {
const isImage = /\.(jpg|jpeg|png|bmp)$/i.test(file.name);
const isLt2M = file.size / 1024 / 1024 < 10;
if (!isImage) {
this.$message.error('上传文件只能是jpg、jpeg、png或bmp格式!');
return false;
}
if (!isLt2M) {
this.$message.error('上传文件大小不能超过10MB!');
return false;
}
return true;
},
handleExceed(file, fileList) {
this.$message.error(`最多只能上传${this.limit}张图片`);
},
// 构建七牛云上传配置
uploadConfig(file) {
const config = {
useCdnDomain: true,
region: qiniu.region.z2 // 选择七牛云存储区域
};
let putExtra = {}
// 创建七牛云上传实例
this.observable = qiniu.upload(file, file.name, this.qiNiuToken, putExtra, config);
// 返回一个Promise对象,用于处理上传成功或失败的回调
return new Promise((resolve, reject) => {
this.observable.subscribe({
next: (response) => {
// 设置上传进度
this.uploadProgress = Number(response.total.percent.toFixed(0));
},
error: (err) => {
reject(err);
},
complete: (response) => {
resolve(response);
}
});
});
},
// 自定义上传
async upload(params) {
let { file } = params;
try {
const response = await this.uploadConfig(file);
let url = this.baseUrl + '/' + response.key;
this.$emit('handleSuccess', { url }); // 富文本回调,只传当前上传的图片
this.fileList.push({ url });
this.$emit('updateImg', this.fileList); // 表单回调,回传所有图片
} catch (error) {
// 上传失败,可以做一些错误处理
console.error(error);
this.$message.error('文件上传失败!');
} finally {
// 清空上传进度
setTimeout(() => {
this.uploadProgress = 0;
}, 1000);
}
},
},
watch: {
propsList(newVal) {
if (typeof newVal === 'string' && newVal.trim().length) {
let arr = newVal.split(',')
arr.map(item => {
this.fileList.push({
url: item
})
})
} else if (Array.isArray(newVal)) {
this.fileList = newVal;
} else {
this.fileList = []
}
}
}
}
</script>
<style lang="scss" scoped>
.dragDisabled> :nth-child(1) {
display: none;
}
.disabled> :nth-child(2) {
display: none;
}
</style>
3、使用方法
<ImgUpload :propsList="imgList" @updateImg="updateImg"></ImgUpload>
// 图片添加删除
updateImg(imgList) {
let arr = imgList.map(item => item.url)
this.formData.images = arr.join(',')
},