<template>
<div class="wrapper">
<div class="picture">
<scroller lock-y scrollbar-x>
<div class="scroll-wrapper" :style="{width:( imgList.length * 75 )+'px'}">
<div class="cuspic" v-for="(item,index) of imgList" :key="index">
<img :src="item" @click="show(index)"/>
<span class="del-icon" @click="del(index)" ></span>
</div>
</div>
</scroller>
<div class="up-wrapper">
<div class="file-icon" v-show="imgList.length<max">
<img @click="clickFile" src="../../../common/assets/icon/apply/Group 70@3x.png"/>
<input ref="fileinput"
type="file"
accept="image/*"
capture="camera"
fieldName="file"
multiple="multiple"
@change="selectFiles"
class="fileinput"
/>
</div>
<div class="pic-hint">
<div class="max-message">上传检查报告或患处照片(最多9张)</div>
<div class="g-pic">照片仅自己和医生可见</div>
</div>
</div>
</div>
<div>
<loading :show="loadingShow" text="上传中"></loading>
</div>
<div v-transfer-dom>
<previewer :list="previewList" ref="previewer" :options="options">
<template slot="button-before">
</template>
</previewer>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import {Badge, Loading, TransferDomDirective as TransferDom, Previewer,Grid, GridItem,Scroller } from 'vux'
import {uploadFile} from '@network/Api'
import {mapState,mapMutations} from 'vuex'
export default {
name: 'imageUpload',
directives: {
TransferDom
},
components: {
Badge, Loading, Previewer,Grid, GridItem,Scroller
},
props: {
multiple: {
type: Boolean,
default: true,
},
value: {
type: [Boolean, String, Number, Array],
default: false
},
max: {
type: [Boolean, String, Number, Array],
default: 9
}
},
data() {
return {
files: null,
imgList: [],
imgListBig: [],
formData: null,
fileUrl: [],
loadingShow: false,
options: {
getThumbBoundsFn(index) {
let thumbnail = document.querySelectorAll('.cuspic')[index]
let pageYScroll = window.pageYOffset || document.documentElement.scrollTop
let rect = thumbnail.getBoundingClientRect()
return {x: rect.left, y: rect.top + pageYScroll, w: rect.width}
},
isClickableElement: function (el) {
return /previewer-delete-icon/.test(el.className)
},
tapToToggleControls: false,
},
directives: {
TransferDom
},
}
},
watch: {
imgList(val) {
this.$emit('input', val)
},
bigPictureUrls(){
this.imgListBig = this.bigPictureUrls
}
},
computed:{
...mapState({
bigPictureUrls: state => state.bigPictureUrls
}),
previewList(){
let array = [];
this.imgListBig.map((item, index) => {
array.push({
src: item
})
})
console.log('array---缓存大图',array)
return array
}
},
methods: {
...mapMutations(['saveBigPictureUrl']),
compressImage(src) {
return new Promise(function (resolve, reject) {
let _this = this, imgType
let img = new Image()
if (src) {
imgType = src.split(';')[0]
if (imgType) {
imgType = imgType.split(':')[1]
}
}
img.src = src
img.onload = function () {
let goalWidth = 1080,
goalHeight = 1080,
imgWidth = img.naturalWidth,
imgHeight = img.naturalHeight,
tempWidth = imgWidth,
tempHeight = imgHeight,
r = imgWidth / imgHeight,
quality = 0.5
if (imgWidth < goalWidth && imgHeight < goalHeight) {
}
else if (imgWidth > goalHeight && imgWidth > goalHeight) {
if (r > 1) {
tempHeight = goalHeight
tempWidth = goalHeight * r
}
else {
tempHeight = goalWidth / r
tempWidth = goalWidth
}
}
else {
if (r > 2) {
tempWidth = imgWidth
tempHeight = imgHeight
}
else if (r < 0.5) {
tempWidth = imgWidth
tempHeight = imgHeight
}
else if (r > 1) {
tempWidth = goalWidth
tempHeight = goalWidth / r
}
else {
tempHeight = goalHeight
tempWidth = goalHeight * r
}
}
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = tempWidth
canvas.height = tempHeight
ctx.drawImage(img, 0, 0, tempWidth, tempHeight)
canvas.toBlob(function (blob) {
resolve(blob)
}, imgType || 'image/jpeg')
}
})
},
compressImageWithFiles(files) {
let fileProms = [];
for (let file of files) {
let fp = new Promise((resolve, reject) => {
let vueInst = this;
let reader = new FileReader()
reader.onload = function (e) {
let pro = vueInst.compressImage(e.target.result);
resolve(pro)
}
reader.readAsDataURL(file);
})
fileProms.push(fp);
}
return Promise.all(fileProms)
},
async selectFiles(e) {
const maxCount = this.max
const files = e.target.files
if (!files.length) {
return
}
console.log('------image size------',files[0].size)
let count = this.imgList.length + files.length
if (count > maxCount) {
this.$alert.error({
content: `最多上传${maxCount}张`, confirmText: '好的', onConfirm() {
}
})
return
}
let filesFilter = await this.converImgList(files);
if (filesFilter == null || filesFilter.length == 0) {
return
}
filesFilter = await this.compressImageWithFiles(filesFilter);
this.formData = new FormData()
if (this.multiple) {
for (let i = 0; i < filesFilter.length; i += 1) {
this.formData.append('file', filesFilter[i])
}
this.formData.append('userid', shareInst.store.state.user.uid)
this.formData.append('ext', '80')
this.formData.append('module', 1)
} else {
this.file = filesFilter[0]
this.formData.append('userid', shareInst.store.state.user.uid)
this.formData.append('file', this.file)
this.formData.append('ext', '80')
this.formData.append('module', 1)
}
this.upload()
let ele = document.querySelector('.scroll-wrapper')
if(this.imgList.length >=4){
console.log('this.imgList.length------ ',this.imgList.length )
ele.style.transform =`translate(${-90 * (this.imgList.length - 4) }px,0px)`
}
},
async converImgList(files) {
let maxSize = '10MB';
let allowed = [".jpg", ".gif", ".png", ".jpeg"];
let _this = this;
let errFile = []
for (let i = 0; i < files.length; i++) {
let file = files[i]
if (!this.checkType(file, allowed)) {
errFile.push({
index: i,
lable: file.name,
type: 'type'
})
continue
}
if (!this.limitFileSize(file, maxSize)) {
errFile.push({
index: i,
lable: file.name,
type: 'size'
})
continue
}
}
if (errFile.length) {
let sizeErr = ''
let typeErr = ''
let errIndex = []
errFile.map(item => {
if (item.type == 'size') {
sizeErr += item.lable + ' | '
}
if (item.type == 'type') {
typeErr += item.lable + '| '
}
errIndex.push(item.index)
})
let content = '';
if (sizeErr) {
sizeErr = sizeErr.substring(0, sizeErr.length - 2)
content += `单文件大小超出[${maxSize}]:${sizeErr}`;
}
if (typeErr) {
sizeErr = typeErr.substring(0, typeErr.length - 2)
content += `类型只允许[${allowed}]:${typeErr}`;
}
this.$alert.error({
content: `${content},请重新上传`, confirmText: '好的', onConfirm() {
}
})
this.$refs.fileinput.value = ''
return null
}
return files;
},
upload() {
uploadFile(this.formData).then((res) => {
if (res && res.length) {
res.map(item => {
let str1 = this.insertStr(item.filepath, item.filepath.lastIndexOf('/'), '/thumb')
let str2 = this.insertStr(str1, str1.lastIndexOf('_'), '_thumb')
this.imgList.push(str2)
console.log('str2---',str2)
this.imgListBig.push(item.filepath)
this.$store.commit('saveBigPictureUrl', this.imgListBig)
console.log(' this.imgListBig-----', this.imgListBig)
})
}
}).catch((e) => {
})
this.$refs.fileinput.value = ''
},
dataURLToBlob(dataurl) {
var arr = dataurl.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime});
},
clickFile() {
this.$refs.fileinput.click()
},
limitFileSize(file, limitSize) {
var arr = ["KB", "MB", "GB"]
var limit = limitSize.toUpperCase();
var limitNum = 0;
for (var i = 0; i < arr.length; i++) {
var leval = limit.indexOf(arr[i]);
if (leval > -1) {
limitNum = parseInt(limit.substr(0, leval)) * Math.pow(1024, (i + 1))
break
}
}
if (file.size > limitNum) {
return false
}
return true
},
insertStr(soure, start, newStr) {
return soure.slice(0, start) + newStr + soure.slice(start);
},
checkType(file, allowed) {
const fileName = file.name;
const seat = fileName.lastIndexOf(".");
const extension = fileName.substring(seat).toLowerCase();
return this.contains(allowed, extension)
},
contains(arr, obj) {
let i = arr.length;
while (i--) {
if (arr[i] == obj) {
return true;
}
}
return false;
},
del(index) {
this.imgList.splice(index, 1);
this.imgListBig.splice(index, 1);
},
show(index) {
this.$refs.previewer.show(index)
},
},
created() {
this.imgList = this.value
this.imgListBig = this.bigPictureUrls
},
}
</script>
<style lang="scss" type="text/scss" scoped>
.wrapper {
width: 100%;
overflow: hidden;
.scroll-wrapper{
overflow: auto;
}
.picture {
width: auto;
.cuspic {
display: inline-block;
margin-right: 15px;
margin-top: 10px;
position: relative;
.del-icon{
position: absolute;
right: -8px;
top: -8px;
display: inline-block;
width: 20px;
height: 20px;
background-size:100% 100%;
background-position:center ;
background-image: url("../../../common/assets/icon/apply/del@3x.png");
}
}
.file-icon {
position: relative;
display: inline-block;
margin-right: 10px;
input {
position: absolute;
left: 0;
top: 24px;
opacity: 0;
}
}
img {
width: 60px;
height: 60px;
/* margin-right: 9px;*/
margin-left: 0px;
/* margin-top: 5px;*/
border-radius: 3px;
object-fit:cover;
}
}
/deep/ .weui-grids:before {
height: 0px;
border-top: none;
}
/deep/ .weui-grid:after {
height: 0px;
border-bottom: none;
}
.pic-hint{
height: 60px;
display: inline-flex;
justify-content: center;
flex-direction: column;
align-content: center;
vertical-align: middle;
}
.g-pic{
color: $subtitle-color;
}
.max-message{
}
.up-wrapper{
display: flex;
justify-content: flex-start;
align-content: center;
margin-top: 10px;
}
/deep/ .weui-grid{
padding: 10px;
}
}
</style>