199 lines
5.9 KiB
Vue
Executable File
199 lines
5.9 KiB
Vue
Executable File
<template>
|
|
<div class="upload-img-box">
|
|
<el-upload class="avatar-uploader" action="'string'" name="upload" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :on-error="uploadError" accept="image/jpeg,image/png,image/jpg, image/gif, image/webp" :on-change="handleCrop" :style="{width: width,height: height}" :auto-upload="false" :http-request="upload" ref="multipleUpload" list-type="picture">
|
|
<img v-if="cover" :src="imgUrl + cover" class="avatar" />
|
|
<i v-else class="el-icon-plus avatar-uploader-icon" :style="{lineHeight: height}"></i>
|
|
</el-upload>
|
|
<p class="desc">图片大小不能超过1M,且宽高度为{{wSize + '*' + hSize}}</p>
|
|
<el-dialog :visible.sync="cropperModel" width="1100px" class="dialog-popup" append-to-body :title="'图片裁剪大小' + wSize + '*' + hSize">
|
|
<Cropper :img-file="imgFile" ref="vueCropper" :fixedNumber="[wSize,hSize]" @upload="upload">
|
|
</Cropper>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
// import { mapGetters } from 'vuex'
|
|
import baseConfig from '@/utils/serverUrlConfig'
|
|
import Cropper from './cropper'
|
|
import api from '@/api'
|
|
export default {
|
|
data() {
|
|
return {
|
|
imgUrl: baseConfig.imgUrl,
|
|
cropperModel: false,
|
|
// 当前选中的文件(未压缩裁剪之前)
|
|
checkedFile: '',
|
|
// 传递到裁剪框中的图片路径
|
|
imgFile: '',
|
|
}
|
|
},
|
|
props: ['cover', 'action', 'width', 'height', 'id', 'wSize', 'hSize'],
|
|
components: {
|
|
Cropper
|
|
},
|
|
methods: {
|
|
// 图片选择过后
|
|
handleCrop(file) {
|
|
this.cropperModel = true
|
|
this.imgFile = URL.createObjectURL(file.raw)
|
|
this.checkedFile = file
|
|
},
|
|
// 图片上传前验证
|
|
beforeAvatarUpload(file) {
|
|
const isLt3M = file.size / 1024 / 1024 < 1.024;
|
|
if (!isLt3M) {
|
|
this.$message.error("封面上传大小不能超过1M");
|
|
return false
|
|
}
|
|
//const isSize = new Promise(function (resolve, reject) {
|
|
// let width = this.wSize;
|
|
// let height = this.hSize;
|
|
// let _URL = window.URL || window.webkitURL;
|
|
// let img = new Image();
|
|
// img.onload = function () {
|
|
// let valid = img.width === width && img.height === height;
|
|
// valid ? resolve() : reject();
|
|
// }
|
|
// img.src = _URL.createObjectURL(file);
|
|
//}).then(() => {
|
|
// return file;
|
|
//}, () => {
|
|
// this.$message.error('上传的图片宽高必须为' + this.wSize + '*' + this.hSize + '!');
|
|
// return Promise.reject();
|
|
//});
|
|
//return isSize;
|
|
},
|
|
// 视频封面上传成功回掉
|
|
handleAvatarSuccess(res) {
|
|
if (res.code === 200) {
|
|
this.$emit("successCallback", res)
|
|
} else {
|
|
this.$message.error('上传封面图失败')
|
|
}
|
|
},
|
|
// 图片上传错误
|
|
uploadError() {
|
|
this.$message.error('上传封面图失败')
|
|
},
|
|
// 图片上传
|
|
upload(data) {
|
|
this.cropperModel = false;
|
|
let img = new Image();
|
|
img.src = data;
|
|
img.onload = async () => {
|
|
// 将base64转换成blob
|
|
let blob = this.dataURItoBlob(data);
|
|
let formData = new FormData();
|
|
formData.append('upload', blob, this.checkedFile.name); // 有的后台需要传文件名,不然会报错
|
|
if (this.id) {
|
|
formData.append('id', this.id)
|
|
}
|
|
// 判断图片大小 超过500kb自动打包
|
|
if (formData.get('upload').size / 1024 / 1024 > 1.024) {
|
|
this.compress(img)
|
|
} else {
|
|
this.imgUpload(formData);
|
|
}
|
|
};
|
|
},
|
|
async imgUpload(formData) {
|
|
api.uploadImg(formData).then(res => {
|
|
if (res.code === 200) {
|
|
this.$emit("successCallback", res)
|
|
this.$message({
|
|
message: '上传成功',
|
|
type: 'success'
|
|
});
|
|
} else {
|
|
this.$message.error('上传失败');
|
|
}
|
|
this.uploading = false;
|
|
this.$refs.vueCropper.flag = false;
|
|
}).catch(() => {
|
|
this.uploading = false;
|
|
this.$message.error('上传失败');
|
|
});
|
|
},
|
|
// 压缩图片
|
|
compress(img) {
|
|
let canvas = document.createElement('canvas');
|
|
let ctx = canvas.getContext('2d');
|
|
// let initSize = img.src.length;
|
|
let width = img.width;
|
|
let height = img.height;
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
// 铺底色
|
|
ctx.fillStyle = '#fff';
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
ctx.drawImage(img, 0, 0, width, height);
|
|
// 进行压缩
|
|
let ndata = canvas.toDataURL('image/jpeg', 0.98);
|
|
this.upload(ndata)
|
|
},
|
|
// base64转成bolb对象
|
|
dataURItoBlob(base64Data) {
|
|
let byteString;
|
|
if (base64Data.split(',')[0].indexOf('base64') >= 0) { byteString = atob(base64Data.split(',')[1]); } else { byteString = unescape(base64Data.split(',')[1]); }
|
|
let mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
|
|
let ia = new Uint8Array(byteString.length);
|
|
for (let i = 0; i < byteString.length; i++) {
|
|
ia[i] = byteString.charCodeAt(i);
|
|
}
|
|
return new Blob([ia], { type: mimeString });
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss">
|
|
.dialog-popup {
|
|
.el-dialog {
|
|
margin-top: 0px !important;
|
|
}
|
|
}
|
|
.upload-img-box {
|
|
.avatar-uploader {
|
|
width: 150px;
|
|
height: 150px;
|
|
}
|
|
.el-icon-plus {
|
|
height: 100% !important;
|
|
}
|
|
img {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.el-upload {
|
|
width: 100%;
|
|
height: 100%;
|
|
border: 1px dashed #d9d9d9;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
position: relative;
|
|
overflow: hidden;
|
|
&:hover {
|
|
border: 1px dashed #e63765;
|
|
}
|
|
}
|
|
.desc {
|
|
line-height: 1;
|
|
margin-top: 10px;
|
|
color: #999;
|
|
font-size: 12px;
|
|
}
|
|
.avatar-uploader-icon {
|
|
width: 100%;
|
|
height: 100%;
|
|
font-size: 28px;
|
|
color: #8c939d;
|
|
line-height: 150px;
|
|
text-align: center;
|
|
&:hover {
|
|
color: 1px dashed #e63765 !important;
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
|