201 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
		
		
			
		
	
	
			201 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
|   | <script> | ||
|  |   import ajax from './ajax'; | ||
|  |   import UploadDragger from './upload-dragger.vue'; | ||
|  |   export default { | ||
|  |     inject: ['uploader'], | ||
|  |     components: { | ||
|  |       UploadDragger | ||
|  |     }, | ||
|  |     props: { | ||
|  |       type: String, | ||
|  |       action: { | ||
|  |         type: String, | ||
|  |         required: true | ||
|  |       }, | ||
|  |       name: { | ||
|  |         type: String, | ||
|  |         default: 'file' | ||
|  |       }, | ||
|  |       data: Object, | ||
|  |       headers: Object, | ||
|  |       withCredentials: Boolean, | ||
|  |       multiple: Boolean, | ||
|  |       accept: String, | ||
|  |       onStart: Function, | ||
|  |       onProgress: Function, | ||
|  |       onSuccess: Function, | ||
|  |       onError: Function, | ||
|  |       beforeUpload: Function, | ||
|  |       drag: Boolean, | ||
|  |       onPreview: { | ||
|  |         type: Function, | ||
|  |         default: function() {} | ||
|  |       }, | ||
|  |       onRemove: { | ||
|  |         type: Function, | ||
|  |         default: function() {} | ||
|  |       }, | ||
|  |       fileList: Array, | ||
|  |       autoUpload: Boolean, | ||
|  |       listType: String, | ||
|  |       httpRequest: { | ||
|  |         type: Function, | ||
|  |         default: ajax | ||
|  |       }, | ||
|  |       disabled: Boolean, | ||
|  |       limit: Number, | ||
|  |       onExceed: Function | ||
|  |     }, | ||
|  |     data() { | ||
|  |       return { | ||
|  |         mouseover: false, | ||
|  |         reqs: {} | ||
|  |       }; | ||
|  |     }, | ||
|  |     methods: { | ||
|  |       isImage(str) { | ||
|  |         return str.indexOf('image') !== -1; | ||
|  |       }, | ||
|  |       handleChange(ev) { | ||
|  |         const files = ev.target.files; | ||
|  |         if (!files) return; | ||
|  |         this.uploadFiles(files); | ||
|  |       }, | ||
|  |       uploadFiles(files) { | ||
|  |         if (this.limit && this.fileList.length + files.length > this.limit) { | ||
|  |           this.onExceed && this.onExceed(files, this.fileList); | ||
|  |           return; | ||
|  |         } | ||
|  |         let postFiles = Array.prototype.slice.call(files); | ||
|  |         if (!this.multiple) { postFiles = postFiles.slice(0, 1); } | ||
|  |         if (postFiles.length === 0) { return; } | ||
|  |         postFiles.forEach(rawFile => { | ||
|  |           this.onStart(rawFile); | ||
|  |           if (this.autoUpload) this.upload(rawFile); | ||
|  |         }); | ||
|  |       }, | ||
|  |       upload(rawFile) { | ||
|  |         this.$refs.input.value = null; | ||
|  |         if (!this.beforeUpload) { | ||
|  |           return this.post(rawFile); | ||
|  |         } | ||
|  |         const before = this.beforeUpload(rawFile); | ||
|  |         if (before && before.then) { | ||
|  |           before.then(processedFile => { | ||
|  |             const fileType = Object.prototype.toString.call(processedFile); | ||
|  |             if (fileType === '[object File]' || fileType === '[object Blob]') { | ||
|  |               if (fileType === '[object Blob]') { | ||
|  |                 processedFile = new File([processedFile], rawFile.name, { | ||
|  |                   type: rawFile.type | ||
|  |                 }); | ||
|  |               } | ||
|  |               for (const p in rawFile) { | ||
|  |                 if (rawFile.hasOwnProperty(p)) { | ||
|  |                   processedFile[p] = rawFile[p]; | ||
|  |                 } | ||
|  |               } | ||
|  |               this.post(processedFile); | ||
|  |             } else { | ||
|  |               this.post(rawFile); | ||
|  |             } | ||
|  |           }, () => { | ||
|  |             this.onRemove(null, rawFile); | ||
|  |           }); | ||
|  |         } else if (before !== false) { | ||
|  |           this.post(rawFile); | ||
|  |         } else { | ||
|  |           this.onRemove(null, rawFile); | ||
|  |         } | ||
|  |       }, | ||
|  |       abort(file) { | ||
|  |         const { reqs } = this; | ||
|  |         if (file) { | ||
|  |           let uid = file; | ||
|  |           if (file.uid) uid = file.uid; | ||
|  |           if (reqs[uid]) { | ||
|  |             reqs[uid].abort(); | ||
|  |           } | ||
|  |         } else { | ||
|  |           Object.keys(reqs).forEach((uid) => { | ||
|  |             if (reqs[uid]) reqs[uid].abort(); | ||
|  |             delete reqs[uid]; | ||
|  |           }); | ||
|  |         } | ||
|  |       }, | ||
|  |       post(rawFile) { | ||
|  |         const { uid } = rawFile; | ||
|  |         const options = { | ||
|  |           headers: this.headers, | ||
|  |           withCredentials: this.withCredentials, | ||
|  |           file: rawFile, | ||
|  |           data: this.data, | ||
|  |           filename: this.name, | ||
|  |           action: this.action, | ||
|  |           onProgress: e => { | ||
|  |             this.onProgress(e, rawFile); | ||
|  |           }, | ||
|  |           onSuccess: res => { | ||
|  |             this.onSuccess(res, rawFile); | ||
|  |             delete this.reqs[uid]; | ||
|  |           }, | ||
|  |           onError: err => { | ||
|  |             this.onError(err, rawFile); | ||
|  |             delete this.reqs[uid]; | ||
|  |           } | ||
|  |         }; | ||
|  |         const req = this.httpRequest(options); | ||
|  |         this.reqs[uid] = req; | ||
|  |         if (req && req.then) { | ||
|  |           req.then(options.onSuccess, options.onError); | ||
|  |         } | ||
|  |       }, | ||
|  |       handleClick() { | ||
|  |         if (!this.disabled) { | ||
|  |           this.$refs.input.value = null; | ||
|  |           this.$refs.input.click(); | ||
|  |         } | ||
|  |       }, | ||
|  |       handleKeydown(e) { | ||
|  |         if (e.target !== e.currentTarget) return; | ||
|  |         if (e.keyCode === 13 || e.keyCode === 32) { | ||
|  |           this.handleClick(); | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     render(h) { | ||
|  |       let { | ||
|  |         handleClick, | ||
|  |         drag, | ||
|  |         name, | ||
|  |         handleChange, | ||
|  |         multiple, | ||
|  |         accept, | ||
|  |         listType, | ||
|  |         uploadFiles, | ||
|  |         disabled, | ||
|  |         handleKeydown | ||
|  |       } = this; | ||
|  |       const data = { | ||
|  |         class: { | ||
|  |           'el-upload': true | ||
|  |         }, | ||
|  |         on: { | ||
|  |           click: handleClick, | ||
|  |           keydown: handleKeydown | ||
|  |         } | ||
|  |       }; | ||
|  |       data.class[`el-upload--${listType}`] = true; | ||
|  |       return ( | ||
|  |         <div {...data} tabindex="0" > | ||
|  |       { | ||
|  |         drag | ||
|  |         ? <upload-dragger disabled={disabled} on-file={uploadFiles}>{this.$slots.default}</upload-dragger> | ||
|  |     : this.$slots.default | ||
|  |     } | ||
|  |     <input class="el-upload__input" type="file" ref="input" name={name} on-change={handleChange} multiple={multiple} accept={accept}></input> | ||
|  |         </div> | ||
|  |     ); | ||
|  |     } | ||
|  |   }; | ||
|  | </script> |