341 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			341 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
| <script>
 | |
| import UploadList from './upload-list';
 | |
| import Upload from './upload';
 | |
| import ElProgress from 'element-ui/packages/progress';
 | |
| import Migrating from 'element-ui/src/mixins/migrating';
 | |
| 
 | |
| function noop() {}
 | |
| 
 | |
| export default {
 | |
|   name: 'ElUpload',
 | |
| 
 | |
|   mixins: [Migrating],
 | |
| 
 | |
|   components: {
 | |
|     ElProgress,
 | |
|     UploadList,
 | |
|     Upload
 | |
|   },
 | |
| 
 | |
|   provide() {
 | |
|     return {
 | |
|       uploader: this
 | |
|     };
 | |
|   },
 | |
| 
 | |
|   inject: {
 | |
|     elForm: {
 | |
|       default: ''
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   props: {
 | |
|     action: {
 | |
|       type: String,
 | |
|       required: true
 | |
|     },
 | |
|     headers: {
 | |
|       type: Object,
 | |
|       default() {
 | |
|         return {};
 | |
|       }
 | |
|     },
 | |
|     data: Object,
 | |
|     multiple: Boolean,
 | |
|     name: {
 | |
|       type: String,
 | |
|       default: 'file'
 | |
|     },
 | |
|     drag: Boolean,
 | |
|     dragger: Boolean,
 | |
|     withCredentials: Boolean,
 | |
|     showFileList: {
 | |
|       type: Boolean,
 | |
|       default: true
 | |
|     },
 | |
|     accept: String,
 | |
|     type: {
 | |
|       type: String,
 | |
|       default: 'select'
 | |
|     },
 | |
|     beforeUpload: Function,
 | |
|     beforeRemove: Function,
 | |
|     onRemove: {
 | |
|       type: Function,
 | |
|       default: noop
 | |
|     },
 | |
|     onChange: {
 | |
|       type: Function,
 | |
|       default: noop
 | |
|     },
 | |
|     onPreview: {
 | |
|       type: Function
 | |
|     },
 | |
|     onSuccess: {
 | |
|       type: Function,
 | |
|       default: noop
 | |
|     },
 | |
|     onProgress: {
 | |
|       type: Function,
 | |
|       default: noop
 | |
|     },
 | |
|     onError: {
 | |
|       type: Function,
 | |
|       default: noop
 | |
|     },
 | |
|     fileList: {
 | |
|       type: Array,
 | |
|       default() {
 | |
|         return [];
 | |
|       }
 | |
|     },
 | |
|     autoUpload: {
 | |
|       type: Boolean,
 | |
|       default: true
 | |
|     },
 | |
|     listType: {
 | |
|       type: String,
 | |
|       default: 'text' // text,picture,picture-card
 | |
|     },
 | |
|     httpRequest: Function,
 | |
|     disabled: Boolean,
 | |
|     limit: Number,
 | |
|     onExceed: {
 | |
|       type: Function,
 | |
|       default: noop
 | |
|     }
 | |
|   },
 | |
|   mounted() {
 | |
|     console.log('自定义上传组件', this)
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       uploadFiles: [],
 | |
|       dragOver: false,
 | |
|       draging: false,
 | |
|       tempIndex: 1
 | |
|     };
 | |
|   },
 | |
| 
 | |
|   computed: {
 | |
|     uploadDisabled() {
 | |
|       return this.disabled || (this.elForm || {}).disabled;
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   watch: {
 | |
|     listType(type) {
 | |
|       if (type === 'picture-card' || type === 'picture') {
 | |
|         this.uploadFiles = this.uploadFiles.map(file => {
 | |
|           if (!file.url && file.raw) {
 | |
|             try {
 | |
|               file.url = URL.createObjectURL(file.raw);
 | |
|             } catch (err) {
 | |
|               console.error('[Element Error][Upload]', err);
 | |
|             }
 | |
|           }
 | |
|           return file;
 | |
|         });
 | |
|       }
 | |
|     },
 | |
|     fileList: {
 | |
|       immediate: true,
 | |
|       handler(fileList) {
 | |
|         this.uploadFiles = fileList.map(item => {
 | |
|           item.uid = item.uid || (Date.now() + this.tempIndex++);
 | |
|           item.status = item.status || 'success';
 | |
|           return item;
 | |
|         });
 | |
|       }
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   methods: {
 | |
|     handleStart(rawFile) {
 | |
|       rawFile.uid = Date.now() + this.tempIndex++;
 | |
|       let file = {
 | |
|         status: 'ready',
 | |
|         name: rawFile.name,
 | |
|         size: rawFile.size,
 | |
|         percentage: 0,
 | |
|         uid: rawFile.uid,
 | |
|         raw: rawFile
 | |
|       };
 | |
| 
 | |
|       if (this.listType === 'picture-card' || this.listType === 'picture') {
 | |
|         try {
 | |
|           file.url = URL.createObjectURL(rawFile);
 | |
|         } catch (err) {
 | |
|           console.error('[Element Error][Upload]', err);
 | |
|           return;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       this.uploadFiles.push(file);
 | |
|       this.onChange(file, this.uploadFiles);
 | |
|     },
 | |
|     handleProgress(ev, rawFile) {
 | |
|       const file = this.getFile(rawFile);
 | |
|       this.onProgress(ev, file, this.uploadFiles);
 | |
|       file.status = 'uploading';
 | |
|       file.percentage = ev.percent || 0;
 | |
|     },
 | |
|     handleSuccess(res, rawFile) {
 | |
|       const file = this.getFile(rawFile);
 | |
| 
 | |
|       if (file) {
 | |
|         file.status = 'success';
 | |
|         file.response = res;
 | |
| 
 | |
|         this.onSuccess(res, file, this.uploadFiles);
 | |
|         this.onChange(file, this.uploadFiles);
 | |
|       }
 | |
|     },
 | |
|     handleError(err, rawFile) {
 | |
|       const file = this.getFile(rawFile);
 | |
|       const fileList = this.uploadFiles;
 | |
| 
 | |
|       file.status = 'fail';
 | |
| 
 | |
|       fileList.splice(fileList.indexOf(file), 1);
 | |
| 
 | |
|       this.onError(err, file, this.uploadFiles);
 | |
|       this.onChange(file, this.uploadFiles);
 | |
|     },
 | |
|     handleRemove(file, raw) {
 | |
|       if (raw) {
 | |
|         file = this.getFile(raw);
 | |
|       }
 | |
|       let doRemove = () => {
 | |
|         this.abort(file);
 | |
|         let fileList = this.uploadFiles;
 | |
|         fileList.splice(fileList.indexOf(file), 1);
 | |
|         this.onRemove(file, fileList);
 | |
|       };
 | |
| 
 | |
|       if (!this.beforeRemove) {
 | |
|         doRemove();
 | |
|       } else if (typeof this.beforeRemove === 'function') {
 | |
|         const before = this.beforeRemove(file, this.uploadFiles);
 | |
|         if (before && before.then) {
 | |
|           before.then(() => {
 | |
|             doRemove();
 | |
|           }, noop);
 | |
|         } else if (before !== false) {
 | |
|           doRemove();
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     getFile(rawFile) {
 | |
|       let fileList = this.uploadFiles;
 | |
|       let target;
 | |
|       fileList.every(item => {
 | |
|         target = rawFile.uid === item.uid ? item : null;
 | |
|         return !target;
 | |
|       });
 | |
|       return target;
 | |
|     },
 | |
|     abort(file) {
 | |
|       this.$refs['upload-inner'].abort(file);
 | |
|     },
 | |
|     clearFiles() {
 | |
|       this.uploadFiles = [];
 | |
|     },
 | |
|     submit() {
 | |
|       this.uploadFiles
 | |
|         .filter(file => file.status === 'ready')
 | |
|         .forEach(file => {
 | |
|           this.$refs['upload-inner'].upload(file.raw);
 | |
|         });
 | |
|     },
 | |
|     getMigratingConfig() {
 | |
|       return {
 | |
|         props: {
 | |
|           'default-file-list': 'default-file-list is renamed to file-list.',
 | |
|           'show-upload-list': 'show-upload-list is renamed to show-file-list.',
 | |
|           'thumbnail-mode': 'thumbnail-mode has been deprecated, you can implement the same effect according to this case: http://element.eleme.io/#/zh-CN/component/upload#yong-hu-tou-xiang-shang-chuan'
 | |
|         }
 | |
|       };
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   beforeDestroy() {
 | |
|     this.uploadFiles.forEach(file => {
 | |
|       if (file.url && file.url.indexOf('blob:') === 0) {
 | |
|         URL.revokeObjectURL(file.url);
 | |
|       }
 | |
|     });
 | |
|   },
 | |
| 
 | |
|   render(h) {
 | |
|     let uploadList;
 | |
| 
 | |
|     if (this.showFileList) {
 | |
|       uploadList = (
 | |
|         <UploadList
 | |
|           disabled={this.uploadDisabled}
 | |
|           listType={this.listType}
 | |
|           files={this.uploadFiles}
 | |
|           on-remove={this.handleRemove}
 | |
|           handlePreview={this.onPreview}>
 | |
|           {
 | |
|             (props) => {
 | |
|               if (this.$scopedSlots.file) {
 | |
|                 return this.$scopedSlots.file({
 | |
|                   file: props.file
 | |
|                 });
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         </UploadList>
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     const uploadData = {
 | |
|       props: {
 | |
|         type: this.type,
 | |
|         drag: this.drag,
 | |
|         action: this.action,
 | |
|         multiple: this.multiple,
 | |
|         'before-upload': this.beforeUpload,
 | |
|         'with-credentials': this.withCredentials,
 | |
|         headers: this.headers,
 | |
|         name: this.name,
 | |
|         data: this.data,
 | |
|         accept: this.accept,
 | |
|         fileList: this.uploadFiles,
 | |
|         autoUpload: this.autoUpload,
 | |
|         listType: this.listType,
 | |
|         disabled: this.uploadDisabled,
 | |
|         limit: this.limit,
 | |
|         'on-exceed': this.onExceed,
 | |
|         'on-start': this.handleStart,
 | |
|         'on-progress': this.handleProgress,
 | |
|         'on-success': this.handleSuccess,
 | |
|         'on-error': this.handleError,
 | |
|         'on-preview': this.onPreview,
 | |
|         'on-remove': this.handleRemove,
 | |
|         'http-request': this.httpRequest
 | |
|       },
 | |
|       ref: 'upload-inner'
 | |
|     };
 | |
| 
 | |
|     const trigger = this.$slots.trigger || this.$slots.default;
 | |
|     const uploadComponent = <upload {...uploadData}>{trigger}</upload>;
 | |
| 
 | |
|     return (
 | |
|       <div>
 | |
|         { this.listType === 'picture-card' ? uploadList : ''}
 | |
|         {
 | |
|           this.$slots.trigger
 | |
|             ? [uploadComponent, this.$slots.default]
 | |
|             : uploadComponent
 | |
|         }
 | |
|         {this.$slots.tip}
 | |
|         { this.listType !== 'picture-card' ? uploadList : ''}
 | |
|       </div>
 | |
|     );
 | |
|   }
 | |
| };
 | |
| </script>
 |