New file |
| | |
| | | <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.url" 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", |
| | | emits:['uploadFiles','choose','delFile'], |
| | | 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 = {} |
| | | const widthDefaultValue = 1 |
| | | const radiusDefaultValue = 3 |
| | | if (typeof border === 'boolean') { |
| | | obj.border = border ? '1px #eee solid' : 'none' |
| | | } else { |
| | | let width = (border && border.width) || widthDefaultValue |
| | | width = this.value2px(width) |
| | | let radius = (border && border.radius) || radiusDefaultValue |
| | | 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.url) |
| | | }) |
| | | |
| | | 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 lang="scss"> |
| | | .uni-file-picker__container { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | flex-wrap: wrap; |
| | | margin: -5px; |
| | | } |
| | | |
| | | .file-picker__box { |
| | | position: relative; |
| | | // flex: 0 0 33.3%; |
| | | 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: 5px; |
| | | 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: 3px; |
| | | right: 3px; |
| | | 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> |