303 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			303 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Vue
		
	
	
| <template>
 | |
|   <view class="uni-file-picker__container">
 | |
|     <view class="file-picker__box" v-for="(url, index) in list" :key="index" :style="boxStyle">
 | |
|       <view class="file-picker__box-content" :style="borderStyle">
 | |
|         <image
 | |
|           class="file-image"
 | |
|           :src="getImageUrl(url)"
 | |
|           mode="aspectFill"
 | |
|           @click.stop="previewImage(url, 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.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item, index)">
 | |
|           点击重试
 | |
|         </view> -->
 | |
|       </view>
 | |
|     </view>
 | |
|     <view v-if="list.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>
 | |
|   import sheep from '@/sheep';
 | |
|   export default {
 | |
|     name: 'uploadImage',
 | |
|     emits: ['uploadFiles', 'choose', 'delFile'],
 | |
|     props: {
 | |
|       filesList: {
 | |
|         type: [Array, String],
 | |
|         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: {
 | |
|       list() {
 | |
|         if (typeof this.filesList === 'string') {
 | |
|           return [this.filesList];
 | |
|         }
 | |
|         return this.filesList;
 | |
|       },
 | |
|       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: {
 | |
|       getImageUrl(url) {
 | |
|         if ('blob:http:' === url.substr(0, 10)) {
 | |
|           return url;
 | |
|         } else {
 | |
|           return sheep.$url.cdn(url);
 | |
|         }
 | |
|       },
 | |
|       uploadFiles(item, index) {
 | |
|         this.$emit('uploadFiles', item);
 | |
|       },
 | |
|       choose() {
 | |
|         this.$emit('choose');
 | |
|       },
 | |
|       delFile(index) {
 | |
|         this.$emit('delFile', index);
 | |
|       },
 | |
|       previewImage(img, index) {
 | |
|         let urls = [];
 | |
|         if (Number(this.limit) === 1 && this.disablePreview && !this.disabled) {
 | |
|           this.$emit('choose');
 | |
|         }
 | |
|         if (this.disablePreview) return;
 | |
|         this.list.forEach((i) => {
 | |
|           urls.push(this.getImageUrl(i));
 | |
|         });
 | |
| 
 | |
|         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>
 |