You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
5.7 KiB
287 lines
5.7 KiB
<template> |
|
<view class="uni-file-picker__container"> |
|
<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle"> |
|
<view class="file-picker__box-content" :style="borderStyle"> |
|
<image class="file-image" :src="item.path" mode="aspectFill" @click.stop="prviewImage(item,index)"></image> |
|
<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)"> |
|
<view class="icon-del"></view> |
|
<view class="icon-del rotate"></view> |
|
</view> |
|
<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress"> |
|
<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4" :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" /> |
|
</view> |
|
<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)"> |
|
点击重试 |
|
</view> |
|
</view> |
|
</view> |
|
<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle"> |
|
<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose"> |
|
<slot> |
|
<view class="icon-add"></view> |
|
<view class="icon-add rotate"></view> |
|
</slot> |
|
</view> |
|
</view> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
export default { |
|
name: "uploadImage", |
|
props: { |
|
filesList: { |
|
type: Array, |
|
default () { |
|
return [] |
|
} |
|
}, |
|
disabled: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
disablePreview: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
limit: { |
|
type: [Number, String], |
|
default: 9 |
|
}, |
|
imageStyles: { |
|
type: Object, |
|
default () { |
|
return { |
|
width: 'auto', |
|
height: 'auto', |
|
border: {} |
|
} |
|
} |
|
}, |
|
delIcon: { |
|
type: Boolean, |
|
default: true |
|
}, |
|
readonly: { |
|
type: Boolean, |
|
default: false |
|
} |
|
}, |
|
computed: { |
|
styles() { |
|
let styles = { |
|
width: 'auto', |
|
height: 'auto', |
|
border: {} |
|
} |
|
return Object.assign(styles, this.imageStyles) |
|
}, |
|
boxStyle() { |
|
const { |
|
width = 'auto', |
|
height = 'auto' |
|
} = this.styles |
|
let obj = {} |
|
if (height === 'auto') { |
|
if (width !== 'auto') { |
|
obj.height = this.value2px(width) |
|
obj['padding-top'] = 0 |
|
} else { |
|
obj.height = 0 |
|
} |
|
} else { |
|
obj.height = this.value2px(height) |
|
obj['padding-top'] = 0 |
|
} |
|
|
|
if (width === 'auto') { |
|
if (height !== 'auto') { |
|
obj.width = this.value2px(height) |
|
} else { |
|
obj.width = '33.3%' |
|
} |
|
} else { |
|
obj.width = this.value2px(width) |
|
} |
|
|
|
let classles = '' |
|
for (let i in obj) { |
|
classles += `${i}:${obj[i]};` |
|
} |
|
return classles |
|
}, |
|
borderStyle() { |
|
let { |
|
border |
|
} = this.styles |
|
let obj = {} |
|
if (typeof border === 'boolean') { |
|
obj.border = border ? '1px #eee solid' : 'none' |
|
} else { |
|
let width = (border && border.width) || 1 |
|
width = this.value2px(width) |
|
let radius = (border && border.radius) || 5 |
|
radius = this.value2px(radius) |
|
obj = { |
|
'border-width': width, |
|
'border-style': (border && border.style) || 'solid', |
|
'border-color': (border && border.color) || '#eee', |
|
'border-radius': radius |
|
} |
|
} |
|
let classles = '' |
|
for (let i in obj) { |
|
classles += `${i}:${obj[i]};` |
|
} |
|
return classles |
|
} |
|
}, |
|
methods: { |
|
uploadFiles(item, index) { |
|
this.$emit("uploadFiles", item) |
|
}, |
|
choose() { |
|
this.$emit("choose") |
|
}, |
|
delFile(index) { |
|
this.$emit('delFile', index) |
|
}, |
|
prviewImage(img, index) { |
|
let urls = [] |
|
if (Number(this.limit) === 1 && this.disablePreview && !this.disabled) { |
|
this.$emit("choose") |
|
} |
|
if (this.disablePreview) return |
|
this.filesList.forEach(i => { |
|
urls.push(i.path) |
|
}) |
|
|
|
uni.previewImage({ |
|
urls: urls, |
|
current: index |
|
}); |
|
}, |
|
value2px(value) { |
|
if (typeof value === 'number') { |
|
value += 'px' |
|
} else { |
|
if (value.indexOf('%') === -1) { |
|
value = value.indexOf('px') !== -1 ? value : value + 'px' |
|
} |
|
} |
|
return value |
|
} |
|
} |
|
} |
|
</script> |
|
|
|
<style scoped> |
|
.uni-file-picker__container { |
|
/* #ifndef APP-NVUE */ |
|
display: flex; |
|
box-sizing: border-box; |
|
/* #endif */ |
|
flex-wrap: wrap; |
|
margin: -5px; |
|
} |
|
|
|
.file-picker__box { |
|
position: relative; |
|
width: 33.3%; |
|
height: 0; |
|
padding-top: 33.33%; |
|
/* #ifndef APP-NVUE */ |
|
box-sizing: border-box; |
|
/* #endif */ |
|
} |
|
|
|
.file-picker__box-content { |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
bottom: 0; |
|
left: 0; |
|
margin: 5px; |
|
border: 1px #eee solid; |
|
border-radius: 8px; |
|
overflow: hidden; |
|
} |
|
|
|
.file-picker__progress { |
|
position: absolute; |
|
bottom: 0; |
|
left: 0; |
|
right: 0; |
|
/* border: 1px red solid; */ |
|
z-index: 2; |
|
} |
|
|
|
.file-picker__progress-item { |
|
width: 100%; |
|
} |
|
|
|
.file-picker__mask { |
|
/* #ifndef APP-NVUE */ |
|
display: flex; |
|
/* #endif */ |
|
justify-content: center; |
|
align-items: center; |
|
position: absolute; |
|
right: 0; |
|
top: 0; |
|
bottom: 0; |
|
left: 0; |
|
color: #fff; |
|
font-size: 12px; |
|
background-color: rgba(0, 0, 0, 0.4); |
|
} |
|
|
|
.file-image { |
|
width: 100%; |
|
height: 100%; |
|
} |
|
|
|
.is-add { |
|
/* #ifndef APP-NVUE */ |
|
display: flex; |
|
/* #endif */ |
|
align-items: center; |
|
justify-content: center; |
|
} |
|
|
|
.icon-add { |
|
width: 50px; |
|
height: 5px; |
|
background-color: #f1f1f1; |
|
border-radius: 2px; |
|
} |
|
|
|
.rotate { |
|
position: absolute; |
|
transform: rotate(90deg); |
|
} |
|
|
|
.icon-del-box { |
|
/* #ifndef APP-NVUE */ |
|
display: flex; |
|
/* #endif */ |
|
align-items: center; |
|
justify-content: center; |
|
position: absolute; |
|
top: 5px; |
|
right: 5px; |
|
height: 26px; |
|
width: 26px; |
|
border-radius: 50%; |
|
background-color: rgba(0, 0, 0, 0.5); |
|
z-index: 2; |
|
transform: rotate(-45deg); |
|
} |
|
|
|
.icon-del { |
|
width: 15px; |
|
height: 2px; |
|
background-color: #fff; |
|
border-radius: 2px; |
|
} |
|
</style> |