<!--
|
* @Date: 2019-08-30 18:04:49
|
* @LastEditors: 小明丶
|
* @LastEditTime: 2020-12-25 11:16:31
|
* @Description:
|
-->
|
<template>
|
<div class="component-photo-upload">
|
<!--title 和上传按钮的图标-->
|
<div class="pic-title">
|
<p>{{ title }}
|
<span style="font-size:12px;color:rgba(255,102,102,1);">{{tips}}</span>
|
</p>
|
|
</div>
|
<!--图片上传列表,删除即重新上传-->
|
<div class="photo-list">
|
<!--图片上传列表-->
|
<div
|
class="pic-item-box"
|
v-for="(item, index) in picList"
|
v-if="picList instanceof Array && picList.length"
|
:key="index"
|
>
|
<div class="close-div">
|
<div class="close-div-box">
|
<van-icon name="clear" color="#FC8349" v-if="picList.length > 1" @click="deletPhoto(item,index)" />
|
</div>
|
</div>
|
<img :src="item.fileUrl" @click="handleDeletePicture(index)" />
|
</div>
|
<!--上传按钮-->
|
<div class="pic-item-box" @click="handleUploadPicture" v-if="showUploadBtn">
|
<!-- <i class="iconfont iconzhaoxiang" style="color:#FC8349"></i> -->
|
<img v-if="isCard == 1 " src="../../../assets/img/idcardz.png">
|
<img v-if="isCard == 2 " src="../../../assets/img/idcardf.png">
|
<img v-if="isCard == 0 " src="../../../assets/img/img_upload.png">
|
</div>
|
</div>
|
<!-- 真正的上传按钮-->
|
<div>
|
<input
|
style="display: none"
|
type="file"
|
ref="androidInputFileImage"
|
@change="handlePhotoChange($event)"
|
accept="image/*"
|
/>
|
<input
|
style="display: none"
|
type="file"
|
ref="androidInputFileCapture"
|
@change="handlePhotoChange($event)"
|
accept="image/*"
|
capture="camera"
|
/>
|
</div>
|
<!--选择上传图片还是拍照-->
|
|
<van-action-sheet
|
v-model="selectModel"
|
:close-on-click-overlay="false"
|
cancel-text="取消"
|
:actions="nav"
|
@select="handleMenuSelect"
|
></van-action-sheet>
|
</div>
|
</template>
|
|
<script>
|
import { SET_APP_LOADING } from "@/store/mutations-types";
|
import { mapMutations } from "vuex";
|
import EXIF from "exif-js";
|
|
import { _imgCompress, _fileToBase64 } from "@/utils/index";
|
import Vue from "vue";
|
import { Icon } from "vant";
|
|
Vue.use(Icon);
|
export default {
|
name: "sceneUploadFile",
|
data() {
|
return {
|
selectModel: false, // 模态窗选择拍照还是相册
|
deleteIndex: -1, // 删除图片的index
|
nav: [{ name: "拍照" }, { name: "从手机相册选择" }]
|
};
|
},
|
props: [
|
"title",
|
"fileType", // 文件类型
|
"picList",
|
"sourceType",
|
"typeId",
|
"tips",
|
"isCard",//确定是否为身份证0-其他 1-正面 2-反面
|
],
|
computed: {
|
showUploadBtn() {
|
let num = Number(this.fileType),
|
isArray = Array.isArray(this.picList);
|
|
// 这里只能上传一张
|
if (
|
num === 0 ||
|
num === 2 ||
|
num === 3 ||
|
num === 8 ||
|
num === 9 ||
|
num === 11 ||
|
num === 14 ||
|
num === 21 ||
|
num === 22 ||
|
num === 25
|
) {
|
return isArray && this.picList.length < 1;
|
} else if (num === 10 || num === 13) {
|
// 这个类型,只能上传两张
|
return isArray && this.picList.length < 2;
|
} else {
|
return isArray && this.picList.length < 3;
|
}
|
}
|
},
|
methods: {
|
...mapMutations([SET_APP_LOADING]),
|
//删除照片
|
deletPhoto(item, i) {
|
//console.log(item);
|
this.picList.splice(i, 1);
|
},
|
// 处理图片上传的事件(deleteIndex---删除图片的索引)
|
handlePhotoChange: function(evt) {
|
let that = this;
|
that.SET_APP_LOADING(true);
|
// 图片是单选还是多选
|
const files = Array.prototype.slice.call(evt.target.files);
|
// 图片的处理
|
files.forEach(function(file, i) {
|
// 图片的拍摄方向
|
var orientation;
|
// 格式是否支持的判断
|
if (!/\/(?:jpg|jpeg|png)/i.test(file.type)) {
|
that.$vux.toast.text("仅支持jpg|png图片格式", "middle");
|
that.SET_APP_LOADING(false);
|
return;
|
}
|
if(file.size > 1024*1024*10){
|
that.$tool.toast("上传图片不可大于10M,请重新选择图片");
|
that.SET_APP_LOADING(false);
|
return
|
}
|
// 读取图片的元信息
|
EXIF.getData(file, function() {
|
orientation = EXIF.getTag(this, "Orientation");
|
});
|
// 获取文件内容
|
let reader = new FileReader();
|
reader.onload = function() {
|
that.$refs.androidInputFileCapture.value = null;
|
that.$refs.androidInputFileImage.value = null;
|
// 使用exif,处理图片的旋转问题,然后执行回调函数
|
that.getImgData(this.result, orientation, function(data) {
|
// 这里可以使用校正后的图片data了
|
|
var img = new Image();
|
img.src = data;
|
|
// 图片加载完毕之后进行压缩,然后上传
|
if (img.complete) {
|
callback();
|
} else {
|
img.onload = callback;
|
}
|
// 图片的路径获取成功后
|
function callback() {
|
console.log(img.width,img.height)
|
// 压缩后的图片的base64字符串
|
let data = that.compress(img);
|
console.log(that.getFile(data))
|
|
// 调取接口上传图片
|
that.submitUploadImg(that.fileType, data, that.deleteIndex);
|
}
|
});
|
};
|
reader.readAsDataURL(file);
|
});
|
},
|
// base64转file对象判断压缩后大小
|
getFile(data,filename){
|
var arr = data.split(','),
|
mime = arr[0].match(/:(.*?);/)[1],
|
bstr = atob(arr[1]),
|
n = bstr.length,
|
u8arr = new Uint8Array(n);
|
while(n--){
|
u8arr[n] = bstr.charCodeAt(n);
|
}
|
return new File([u8arr], filename, {type:mime});
|
},
|
// type文件上传的路径,data图片的base64字符串(删除图片即重新上传)
|
submitUploadImg: function(type, base64, deleteIndex) {
|
let that = this;
|
var str = base64.replace('data:image/png;base64,', '');//这里根据自己上传图片的格式进行相应修改
|
var strLength = str.length;
|
var fileLength = parseInt(strLength - (strLength / 8) * 2);
|
// 由字节转换为MB
|
var size = "";
|
size = (fileLength / 1024 / 1024).toFixed(2);
|
|
if(parseInt(size)>2){
|
that.$tool.toast("图片过大,请重新上传");
|
that.SET_APP_LOADING(false);
|
return
|
}
|
|
// 防止操作的模态窗
|
let submitInfo = {
|
base64Data: base64.split(",")[1], // 文件base64
|
fileType: type,
|
suffix: base64
|
.split(",")[0]
|
.split(";")
|
["0"].split("/")[1]
|
};
|
if (that.typeId == "200011") {
|
this.$api.uploadXygPhoto(submitInfo).then(
|
res => {
|
// 如果存在删除图片索引
|
if (deleteIndex >= 0) {
|
// 删除以前的那张照片,然后添加新上传的图片
|
this.picList.splice(deleteIndex, 1, {
|
fileUrl: res.body.fileUrl,
|
id: res.body.id
|
});
|
// 将删除索引重置为-1,即当前状态重置为新增,而非删除状态
|
this.deleteIndex = -1;
|
} else {
|
this.picList.unshift({
|
fileUrl: res.body.fileUrl,
|
id: res.body.id
|
});
|
}
|
// 如果是支付二维码的话,需要调取检查授权
|
if (Number(this.fileType) === 8) {
|
this.checkAuth(res.body.id);
|
}
|
that.SET_APP_LOADING(false);
|
// 提交整个图片列表
|
this.$emit("on-change-pic", this.picList);
|
},
|
error => {
|
this.SET_APP_LOADING(false);
|
}
|
);
|
} else {
|
this.$api
|
.merUploadPhoto({
|
...submitInfo,
|
sourceType: that.sourceType
|
})
|
.then(
|
res => {
|
// 如果存在删除图片索引
|
if (deleteIndex >= 0) {
|
// 删除以前的那张照片,然后添加新上传的图片
|
this.picList.splice(deleteIndex, 1, {
|
fileUrl: res.body.fileUrl,
|
id: res.body.id
|
});
|
// 将删除索引重置为-1,即当前状态重置为新增,而非删除状态
|
this.deleteIndex = -1;
|
} else {
|
this.picList.unshift({
|
fileUrl: res.body.fileUrl,
|
id: res.body.id
|
});
|
}
|
// 如果是支付二维码的话,需要调取检查授权
|
if (Number(this.fileType) === 8) {
|
this.checkAuth(res.body.id);
|
}
|
that.SET_APP_LOADING(false);
|
// 提交整个图片列表
|
this.$emit("on-change-pic", this.picList);
|
},
|
error => {
|
this.SET_APP_LOADING(false);
|
}
|
);
|
}
|
},
|
// 图片旋转处理
|
getImgData: function(img, dir, next) {
|
// @param {string} img 图片的base64
|
// @param {int} dir exif获取的方向信息
|
// @param {function} next 回调方法,返回校正方向后的base64
|
var image = new Image();
|
let canvas = document.createElement("canvas");
|
let ctx = canvas.getContext("2d");
|
image.onload = function() {
|
let resultWidth = 0;
|
let resultHeight = 0;
|
let maxWidthOrHeight = 1024;
|
let drawWidth = this.naturalWidth;
|
let drawHeight = this.naturalHeight;
|
console.log(drawWidth,drawHeight)
|
// 以下改变图片大小,控制最大宽度为1024
|
var maxSide = Math.max(drawWidth, drawHeight);
|
if (maxSide > maxWidthOrHeight) {
|
|
let minSide = Math.min(drawWidth, drawHeight);
|
minSide = (minSide / maxSide) * maxWidthOrHeight;
|
maxSide = maxWidthOrHeight;
|
if (drawWidth > drawHeight) {
|
resultWidth = maxSide;
|
resultHeight = minSide;
|
} else {
|
resultWidth = minSide;
|
resultHeight = maxSide;
|
}
|
} else {
|
resultWidth = drawWidth;
|
resultHeight = drawHeight;
|
}
|
|
if (dir === 3) {
|
canvas.width = resultWidth;
|
canvas.height = resultHeight;
|
ctx.translate(resultWidth, resultHeight);
|
ctx.rotate(Math.PI);
|
} else if (dir === 6) {
|
canvas.width = resultHeight;
|
canvas.height = resultWidth;
|
ctx.translate(resultHeight, 0);
|
ctx.rotate(Math.PI / 2);
|
} else if (dir === 8) {
|
canvas.width = resultHeight;
|
canvas.height = resultWidth;
|
ctx.translate(0, resultWidth);
|
ctx.rotate(-Math.PI / 2);
|
} else {
|
canvas.width = resultWidth;
|
canvas.height = resultHeight;
|
}
|
ctx.drawImage(this, 0, 0, resultWidth, resultHeight);
|
// 返回校正图片
|
next(canvas.toDataURL("image/jpg", 0.8));
|
|
console.log(image.width,image.height)
|
};
|
image.src = img;
|
|
},
|
compress(img) {
|
let quality = 0.92, //压缩比例
|
w = img.width,
|
h = img.height,
|
canvas = document.createElement("canvas"),
|
ctx = canvas.getContext("2d");
|
canvas.width = w;
|
canvas.height = h;
|
ctx.drawImage(img, 0, 0, w, h);
|
return canvas.toDataURL("image/jpg", quality);
|
},
|
checkAuth(id) {
|
// authStatus: 0 未授权 1授权---用户授权后才能执行下一步
|
this.$api
|
.checkAuth({
|
fileId: id
|
})
|
.then(res => {
|
if (res.body.authStatus === 1) {
|
this.$emit("on-check-auth", "下一步");
|
}
|
});
|
},
|
// 点击上传按钮
|
handleUploadPicture() {
|
this.selectModel = true;
|
},
|
// 选择拍照或者相册选项
|
handleMenuSelect(item, index) {
|
if (index === 0) {
|
this.$refs.androidInputFileCapture.click();
|
} else {
|
this.$refs.androidInputFileImage.click();
|
}
|
this.selectModel = false;
|
},
|
// 处理图片的删除
|
handleDeletePicture(index) {
|
this.deleteIndex = index;
|
this.selectModel = true;
|
}
|
}
|
};
|
</script>
|
|
<style lang="less" scoped >
|
.component-photo-upload {
|
.pic-title {
|
margin-bottom: 10px;
|
h4 {
|
padding: 10px 0;
|
font-size: 15px;
|
line-height: 1;
|
color: #333;
|
font-weight: normal;
|
}
|
}
|
|
.photo-list {
|
display: flex;
|
padding-bottom: 20px;
|
flex-wrap: wrap;
|
|
.pic-item-box {
|
position: relative;
|
height: 100px;
|
width: 100px;
|
margin-right: 10px;
|
margin-bottom: 10px;
|
line-height: 100px;
|
text-align: center;
|
background-color: #fff;
|
//border: 1px dashed #d9d9d9;
|
img{
|
width: 100%;
|
height: 100%;
|
}
|
.close-div {
|
position: absolute;
|
top: -45px;
|
right: -10px;
|
//border: 1px red solid;
|
//border-radius:50% ;
|
height: 20px;
|
width: 20px;
|
.close-div-box {
|
//border: 1px red solid;
|
//border-radius:50% ;
|
height: 20px;
|
width: 20px;
|
i {
|
font-size: 20px;
|
}
|
}
|
}
|
img {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
}
|
}
|
</style>
|