mirror of https://github.com/ElemeFE/element
				
				
				
			update upload
							parent
							
								
									2ceff8709e
								
							
						
					
					
						commit
						0aaf2df436
					
				|  | @ -7,33 +7,6 @@ | |||
|   .demo-box { | ||||
|     margin-bottom: 24px; | ||||
|   } | ||||
|   .el-draggeer__uploaded-image__btns { | ||||
|     margin-top: 45px; | ||||
|     color: #fff; | ||||
|     font-size: 14px; | ||||
| 
 | ||||
|     & .btn { | ||||
|       display: inline-block; | ||||
| 
 | ||||
|       & span { | ||||
|         opacity: 0; | ||||
|         transition: opacity .15s linear; | ||||
|       } | ||||
| 
 | ||||
|       &:not(:first-child) { | ||||
|         margin-left: 35px; | ||||
|       } | ||||
| 
 | ||||
|       &:hover span { | ||||
|         opacity: 1; | ||||
|       } | ||||
|     } | ||||
|     & i { | ||||
|       display: block; | ||||
|       font-size: 26px; | ||||
|       margin-bottom: 5px; | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| <script> | ||||
|   export default { | ||||
|  | @ -43,6 +16,16 @@ | |||
|       }, | ||||
|       handleRemove(file, fileList) { | ||||
|         console.log(file, fileList); | ||||
|       }, | ||||
|       beforeUpload(file) { | ||||
|         if (file.size > 40000000) { | ||||
|           console.warn(file.name + ' is too large!'); | ||||
|           return false; | ||||
|         } | ||||
|         return true; | ||||
|       }, | ||||
|       handlePreview(file) { | ||||
|         console.log(file); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | @ -51,31 +34,66 @@ | |||
| ## 基础使用 | ||||
| 
 | ||||
| <div class="demo-box"> | ||||
|   <el-upload action="http://127.0.0.1:9000/upload" @filechange="handleChange" @fileremove="handleRemove"> | ||||
|   <el-upload action="http://element.alpha.elenet.me/upload" :on-preview="handlePreview" :on-remove="handleRemove"> | ||||
|     <el-button size="small" type="primary">点击上传</el-button> | ||||
|     <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> | ||||
|   </el-upload> | ||||
| </div> | ||||
| 
 | ||||
| ```html | ||||
| <el-upload action="http://127.0.0.1:9000/upload" @filechange="handleChange" @fileremove="handleRemove"> | ||||
| <el-upload action="http://element.alpha.elenet.me/upload" :on-preview="handlePreview" :on-remove="handleRemove"> | ||||
|   <el-button size="small" type="primary">点击上传</el-button> | ||||
|   <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> | ||||
| </el-upload> | ||||
| 
 | ||||
| <script> | ||||
|   export default { | ||||
|     methods: { | ||||
|       handleRemove(file, fileList) { | ||||
|         console.log(file, fileList); | ||||
|       }, | ||||
|       handlePreview(file) { | ||||
|         console.log(file); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
| ``` | ||||
| 
 | ||||
| ## 拖拽文件上传 | ||||
| 
 | ||||
| <div class="demo-box"> | ||||
|   <el-upload action="http://127.0.0.1:9000/upload" type="drag" :multiple="true"> | ||||
|   <el-upload | ||||
|     action="http://element.alpha.elenet.me/upload" | ||||
|     type="drag" | ||||
|     :multiple="true" | ||||
|     :on-preview="handlePreview" | ||||
|     :on-remove="handleRemove"> | ||||
|     <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> | ||||
|   </el-upload> | ||||
| </div> | ||||
| 
 | ||||
| ```html | ||||
| <el-upload action="http://127.0.0.1:9000/upload" type="drag" :multiple="true"> | ||||
| <el-upload | ||||
|   action="http://element.alpha.elenet.me/upload" | ||||
|   type="drag" | ||||
|   :multiple="true" | ||||
|   :on-preview="handlePreview" | ||||
|   :on-remove="handleRemove"> | ||||
|   <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> | ||||
| </el-upload> | ||||
| <script> | ||||
|   export default { | ||||
|     methods: { | ||||
|       handleRemove(file, fileList) { | ||||
|         console.log(file, fileList); | ||||
|       }, | ||||
|       handlePreview(file) { | ||||
|         console.log(file); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
| ``` | ||||
| 
 | ||||
| ## 图片缩略图模式 | ||||
|  | @ -83,23 +101,39 @@ | |||
| 上传文件类型限制为只能上传图片,并可展示本地缩略图,该模式暂不支持多选 | ||||
| 
 | ||||
| <div class="demo-box"> | ||||
|   <el-upload action="http://127.0.0.1:9000/upload" type="drag" mode="image"> | ||||
|     <div class="el-draggeer__uploaded-image__btns" slot="interact"> | ||||
|       <span class="btn"><i class="el-icon-share"></i><span>分享图片</span></span> | ||||
|       <span class="btn"><i class="el-icon-delete"></i><span>删除</span></span> | ||||
|     </div> | ||||
|   <el-upload | ||||
|     action="http://element.alpha.elenet.me/upload" | ||||
|     type="drag" | ||||
|     :thumbnail-mode="true" | ||||
|     :on-preview="handlePreview" | ||||
|     :on-remove="handleRemove" | ||||
|   > | ||||
|     <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> | ||||
|   </el-upload> | ||||
| </div> | ||||
| 
 | ||||
| ```html | ||||
| <el-upload action="http://127.0.0.1:9000/upload" type="drag" mode="image"> | ||||
|   <div class="el-draggeer__uploaded-image__btns" slot="interact"> | ||||
|     <span class="btn"><i class="el-icon-share"></i><span>分享图片</span></span> | ||||
|     <span class="btn"><i class="el-icon-delete"></i><span>删除</span></span> | ||||
|   </div> | ||||
| <el-upload | ||||
|   action="http://element.alpha.elenet.me/upload" | ||||
|   type="drag" | ||||
|   :thumbnail-mode="true" | ||||
|   :on-preview="handlePreview" | ||||
|   :on-remove="handleRemove" | ||||
| > | ||||
|   <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> | ||||
| </el-upload> | ||||
| <script> | ||||
|   export default { | ||||
|     methods: { | ||||
|       handleRemove(file, fileList) { | ||||
|         console.log(file, fileList); | ||||
|       }, | ||||
|       handlePreview(file) { | ||||
|         console.log(file); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
| ``` | ||||
| 
 | ||||
| ## API | ||||
|  | @ -113,6 +147,8 @@ | |||
| | showUploadList | 是否显示已上传文件列表 | boolean | | true | | ||||
| | type | 上传控件类型 | string | select,drag | select | | ||||
| | accept | 可选参数, 接受上传的[文件类型](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-accept), 拖拽文件上传时不受此参数影响 | string |  |  | | ||||
| | filechange | 可选参数, 上传文件改变时的回调 | function(file, fileList, event) |  |  | | ||||
| | fileremove | 可选参数, 文件列表移除文件时的回调 | function(file, fileList) |  |  | | ||||
| | onPreview | 可选参数, 点击已上传的文件链接时的钩子 | function(file) |  |  | | ||||
| | onRemove | 可选参数, 文件列表移除文件时的钩子 | function(file, fileList) |  |  | | ||||
| | beforeUpload | 可选参数, 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传。 | function(file) |  |  | | ||||
| | thumbnailMode | 是否设置为图片模式,该模式下会显示图片缩略图 | boolean | | false | | ||||
| | type | 上传控件类型 | string | select,drag | select | | ||||
|  |  | |||
|  | @ -1,25 +1,24 @@ | |||
| @charset "UTF-8"; | ||||
| @import './var.css'; | ||||
| 
 | ||||
| .fade-in-transition { | ||||
|   opacity: 1; | ||||
|   transition: var(--fade-transition); | ||||
| } | ||||
| 
 | ||||
| .fade-in-linear-enter-active { | ||||
|   opacity: 1; | ||||
| .fade-in-linear-enter-active, | ||||
| .fade-in-linear-leave-active { | ||||
|   transition: var(--fade-linear-transition); | ||||
| } | ||||
| 
 | ||||
| .fade-in-linear-enter, | ||||
| .fade-in-linear-leave, | ||||
| .fade-in-linear-leave-active { | ||||
|   opacity: 0; | ||||
|   transition: var(--fade-linear-transition); | ||||
| } | ||||
| 
 | ||||
| .fade-in-enter-active, | ||||
| .fade-in-leave-active { | ||||
|   transition: all .3s cubic-bezier(.55,0,.1,1); | ||||
| } | ||||
| 
 | ||||
| .fade-in-enter, | ||||
| .fade-in-leave, | ||||
| .fade-in-linear-enter, | ||||
| .fade-in-linear-leave { | ||||
| .fade-in-leave-active { | ||||
|   opacity: 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -96,28 +95,19 @@ | |||
|   transition: opacity .3s cubic-bezier(.645,.045,.355,1); | ||||
| } | ||||
| .fade-enter, | ||||
| .fade-leave, | ||||
| .fade-leave-active { | ||||
|   opacity: 0; | ||||
| } | ||||
| 
 | ||||
| .slide-in-bottom-enter { | ||||
|   animation: slideInBottomEnter .3s; | ||||
| .list-move, .list-enter-active, .list-leave-active { | ||||
|   transition: all .5s cubic-bezier(.55,0,.1,1); | ||||
| } | ||||
| .slide-in-bottom-leave { | ||||
|   animation: slideInBottomLeave .3s; | ||||
| } | ||||
| 
 | ||||
| @keyframes slideInBottomEnter { | ||||
|   0% { | ||||
|     opacity: 0; | ||||
|     transform: translate3d(0,50%,0); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes slideInBottomLeave { | ||||
|   to { | ||||
|     opacity: 0; | ||||
|     transform: translate3d(0,50%,0); | ||||
|   } | ||||
| .list-enter, .list-leave-active { | ||||
|   opacity: 0; | ||||
|   transform: translate(0, -30px); | ||||
| } | ||||
| /*.list-leave-active { | ||||
|   position: absolute; | ||||
|   opacity: 0; | ||||
|   transform: scaleY(0.01) translate(30px, 0); | ||||
| }*/ | ||||
|  |  | |||
|  | @ -23,6 +23,11 @@ | |||
|   --color-black: #000; | ||||
|   --color-grey: #C0CCDA; | ||||
| 
 | ||||
|   /* Link | ||||
|   -------------------------- */ | ||||
|   --link-color: #475669; | ||||
|   --link-hover-color: var(--color-primary); | ||||
| 
 | ||||
|   /* Border | ||||
|   -------------------------- */ | ||||
|   --border-width-base: 1px; | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
|       margin-bottom: 10px; | ||||
|     } | ||||
|     @e file { | ||||
|       transition: all .5s cubic-bezier(.55,0,.1,1); | ||||
|       font-size: 14px; | ||||
|       color: #475669; | ||||
|       line-height: 32px; | ||||
|  | @ -33,21 +34,16 @@ | |||
|       text-overflow: ellipsis; | ||||
|       position: relative; | ||||
| 
 | ||||
|       a { | ||||
|         color: #475669; | ||||
|         transition: color .3s; | ||||
|       } | ||||
|       [class^="el-icon"] { | ||||
|         color: #99a9bf; | ||||
|         margin-right: 7px; | ||||
|         height: 100%; | ||||
|         line-height: inherit; | ||||
|       } | ||||
| 
 | ||||
|       &:hover { | ||||
|         background-color: #eff2f7; | ||||
| 
 | ||||
|         .el-upload__btn-delete { | ||||
|           display: block; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|       } | ||||
|       & .el-progress { | ||||
|         position: absolute; | ||||
|         bottom: 0; | ||||
|  | @ -61,6 +57,21 @@ | |||
|         top: 0; | ||||
|         height: 100%; | ||||
|       } | ||||
|       &:hover { | ||||
|         background-color: #eff2f7; | ||||
|       } | ||||
|       @when finished { | ||||
|         & a:hover { | ||||
|           color: var(--link-hover-color); | ||||
|           cursor: pointer; | ||||
|         } | ||||
|         &:hover { | ||||
|           .el-upload__btn-delete { | ||||
|             display: block; | ||||
|             cursor: pointer; | ||||
|           }    | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     @e tip { | ||||
|       font-size: 12px; | ||||
|  | @ -125,6 +136,7 @@ | |||
|       height: 100%; | ||||
|       overflow: hidden; | ||||
|       z-index: 10; | ||||
|       cursor: default; | ||||
| 
 | ||||
|       & img { | ||||
|         display: block; | ||||
|  | @ -140,6 +152,45 @@ | |||
|         height: 100%; | ||||
|         background-color: rgba(#000, .72); | ||||
|         text-align: center; | ||||
| 
 | ||||
|         & .btn { | ||||
|           display: inline-block; | ||||
|           color: #fff; | ||||
|           font-size: 14px; | ||||
|           cursor: pointer; | ||||
|           vertical-align: middle; | ||||
|           transition: var(--md-fade-transition); | ||||
|           margin-top: 60px; | ||||
| 
 | ||||
|           & i { | ||||
|             margin-top: 0; | ||||
|           } | ||||
| 
 | ||||
|           & span { | ||||
|             opacity: 0; | ||||
|             transition: opacity .15s linear; | ||||
|           } | ||||
| 
 | ||||
|           &:not(:first-child) { | ||||
|             margin-left: 35px; | ||||
|           } | ||||
| 
 | ||||
|           &:hover { | ||||
|             transform: translateY(-13px); | ||||
| 
 | ||||
|             & span { | ||||
|               opacity: 1; | ||||
|             } | ||||
|           } | ||||
| 
 | ||||
|           & i { | ||||
|             color: #fff; | ||||
|             display: block; | ||||
|             font-size: 24px; | ||||
|             line-height: inherit; | ||||
|             margin: 0 auto 5px; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       @e title { | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| const Upload = require('./src/upload'); | ||||
| const Upload = require('./src/index'); | ||||
| 
 | ||||
| Upload.install = function(Vue) { | ||||
|   Vue.component(Upload.name, Upload); | ||||
|  |  | |||
|  | @ -0,0 +1,204 @@ | |||
| <script> | ||||
| import UploadList from './upload-list'; | ||||
| import Upload from './upload'; | ||||
| import ElProgress from 'packages/progress/index.js'; | ||||
| 
 | ||||
| function noop() { | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
|   name: 'el-upload', | ||||
| 
 | ||||
|   // extends: typeof FormData !== 'undefined' ? ajaxUpload : iframeUpload, | ||||
|   // extends: iframeUpload, | ||||
| 
 | ||||
|   components: { | ||||
|     ElProgress, | ||||
|     UploadList, | ||||
|     Upload | ||||
|   }, | ||||
| 
 | ||||
|   props: { | ||||
|     action: { | ||||
|       type: String, | ||||
|       required: true | ||||
|     }, | ||||
|     headers: { | ||||
|       type: Object, | ||||
|       default() { | ||||
|         return { | ||||
|           // 'Access-Control-Request-Methods': 'GET, PUT, POST, DELETE, OPTIONS', | ||||
|           // 'Access-Control-Request-Headers': 'Content-Type, Content-Range, Content-Disposition, Content-Description' | ||||
|         }; | ||||
|       } | ||||
|     }, | ||||
|     multiple: { | ||||
|       type: Boolean, | ||||
|       default: false | ||||
|     }, | ||||
|     name: { | ||||
|       type: String, | ||||
|       default: 'file' | ||||
|     }, | ||||
|     withCredentials: { | ||||
|       type: Boolean, | ||||
|       default: false | ||||
|     }, | ||||
|     thumbnailMode: Boolean, | ||||
|     showUploadList: { | ||||
|       type: Boolean, | ||||
|       default: true | ||||
|     }, | ||||
|     accept: String, | ||||
|     type: { | ||||
|       type: String, | ||||
|       default: 'select' | ||||
|     }, | ||||
|     beforeUpload: Function, | ||||
|     onRemove: { | ||||
|       type: Function, | ||||
|       default: noop | ||||
|     }, | ||||
|     onChange: { | ||||
|       type: Function, | ||||
|       default: noop | ||||
|     }, | ||||
|     onPreview: { | ||||
|       type: Function, | ||||
|       default: noop | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   data() { | ||||
|     return { | ||||
|       uploadedFiles: [], | ||||
|       dragOver: false, | ||||
|       draging: false, | ||||
|       tempIndex: 1 | ||||
|     }; | ||||
|   }, | ||||
| 
 | ||||
|   methods: { | ||||
|     onStart(file) { | ||||
|       file.uid = Date.now() + this.tempIndex++; | ||||
|       let _file = { | ||||
|         status: 'uploading', | ||||
|         name: file.name, | ||||
|         size: file.size, | ||||
|         percentage: 0, | ||||
|         uid: file.uid, | ||||
|         showProgress: true | ||||
|       }; | ||||
| 
 | ||||
|       if (this.thumbnailMode) { | ||||
|         try { | ||||
|           _file.url = URL.createObjectURL(file); | ||||
|         } catch (err) { | ||||
|           console.log(err); | ||||
|           return; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       this.uploadedFiles.push(_file); | ||||
|     }, | ||||
|     onProgress(ev, file) { | ||||
|       var _file = this.getFile(file); | ||||
|       _file.percentage = ev.percent; | ||||
|     }, | ||||
|     onSuccess(res, file) { | ||||
|       var _file = this.getFile(file); | ||||
| 
 | ||||
|       _file.status = 'finished'; | ||||
|       _file.response = res; | ||||
| 
 | ||||
|       setTimeout(() => { | ||||
|         _file.showProgress = false; | ||||
|       }, 1000); | ||||
|     }, | ||||
|     onError(err, file) { | ||||
|       var _file = this.getFile(file); | ||||
|       var fileList = this.uploadedFiles; | ||||
| 
 | ||||
|       _file.status = 'fail'; | ||||
| 
 | ||||
|       fileList.splice(fileList.indexOf(_file), 1); | ||||
|       this.$emit('error', _file, fileList, err); | ||||
|     }, | ||||
|     handleRemove(file) { | ||||
|       var fileList = this.uploadedFiles; | ||||
|       fileList.splice(fileList.indexOf(file), 1); | ||||
|       this.onRemove(file, fileList); | ||||
|     }, | ||||
|     getFile(file) { | ||||
|       var fileList = this.uploadedFiles; | ||||
|       var target; | ||||
|       fileList.every(item => { | ||||
|         target = file.uid === item.uid ? item : null; | ||||
|         return !target; | ||||
|       }); | ||||
|       return target; | ||||
|     }, | ||||
|     handlePreview(file) { | ||||
|       if (file.status === 'finished') { | ||||
|         this.onPreview(file); | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   render(h) { | ||||
|     var uploadList; | ||||
|     if (this.showUploadList && !this.thumbnailMode) { | ||||
|       uploadList = ( | ||||
|         <UploadList | ||||
|           files={this.uploadedFiles} | ||||
|           on-remove={this.handleRemove} | ||||
|           on-preview={this.handlePreview}> | ||||
|         </UploadList> | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     var props = { | ||||
|       props: { | ||||
|         action: this.action, | ||||
|         multiple: this.multiple, | ||||
|         'before-upload': this.beforeUpload, | ||||
|         'with-credentials': this.withCredentials, | ||||
|         name: this.name, | ||||
|         accept: this.thumbnailMode ? 'image/*' : this.accept, | ||||
|         'on-start': this.onStart, | ||||
|         'on-progress': this.onProgress, | ||||
|         'on-success': this.onSuccess, | ||||
|         'on-error': this.onError, | ||||
|         'on-preview': this.handlePreview, | ||||
|         'on-remove': this.handleRemove | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     if (this.type === 'select') { | ||||
|       return ( | ||||
|         <div class="el-upload"> | ||||
|           {uploadList} | ||||
|           <upload {...props}> | ||||
|             {this.$slots.default} | ||||
|           </upload> | ||||
|           {this.$slots.tip} | ||||
|         </div> | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     if (this.type === 'drag') { | ||||
|       props.props.type = 'drag'; | ||||
| 
 | ||||
|       return ( | ||||
|         <div class="el-upload"> | ||||
|           <upload {...props}> | ||||
|             {this.$slots.default} | ||||
|           </upload> | ||||
|           {this.$slots.tip} | ||||
|           {uploadList} | ||||
|         </div> | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
|  | @ -0,0 +1,37 @@ | |||
| <template> | ||||
|   <transition-group tag="ul" class="el-upload__files" name="list"> | ||||
|     <li | ||||
|       v-for="file in files" | ||||
|       class="el-upload__file" | ||||
|       :class="{ | ||||
|         'is-finished': file.status === 'finished' | ||||
|       }" | ||||
|       :key="file" | ||||
|       @click="$emit('clickFile', file)" | ||||
|     > | ||||
|       <a class="el-upload__file__name" @click="$emit('preview', file)"> | ||||
|         <i class="el-icon-document"></i>{{file.name}} | ||||
|       </a> | ||||
|       <i class="el-icon-check" v-if="file.status === 'finished' && file.showProgress"></i> | ||||
|       <span class="el-upload__btn-delete" @click="$emit('remove', file)" v-show="file.status === 'finished'">删除</span> | ||||
|       <el-progress | ||||
|         v-if="file.showProgress" | ||||
|         size="small" | ||||
|         :percentage="file.percentage" | ||||
|         :type="file.status === 'finished' ? 'green' : 'blue'"> | ||||
|       </el-progress> | ||||
|     </li> | ||||
|   </transition-group> | ||||
| </template> | ||||
| <script> | ||||
|   export default { | ||||
|     props: { | ||||
|       files: { | ||||
|         type: Array, | ||||
|         default() { | ||||
|           return []; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
| </script> | ||||
|  | @ -1,187 +1,103 @@ | |||
| <template> | ||||
|   <div class="el-upload"> | ||||
|     <!-- 选择类型 --> | ||||
|     <template v-if="type === 'select'"> | ||||
|       <ul class="el-upload__files" v-show="showUploadList && uploadedFiles.length > 0" transition="slide-in-bottom"> | ||||
|         <li class="el-upload__file" v-for="file in uploadedFiles" transition="slide-in-bottom"> | ||||
|           <i class="el-icon-document"></i>{{file.name}} | ||||
|           <i class="el-icon-check" v-show="file.status === 'success'"></i> | ||||
|           <span class="el-upload__btn-delete" @click="removeFile(file)" v-show="file.status === 'finished'">删除</span> | ||||
|           <el-progress | ||||
|             v-if="file.status === 'success' || file.status === 'uploading'" | ||||
|             size="small" | ||||
|             :percentage="file.percentage" | ||||
|             :type="file.status === 'success' ? 'green' : 'blue'"> | ||||
|           </el-progress> | ||||
|         </li> | ||||
|       </ul> | ||||
|       <component :is="uploadComponent" | ||||
|         :action="action", | ||||
|         :multiple="multiple", | ||||
|         :with-credentials="withCredentials", | ||||
|         :name="name", | ||||
|         :accept="accept", | ||||
|         :on-start="onStart", | ||||
|         :on-progress="onProgress", | ||||
|         :on-success="onSuccess", | ||||
|         :on-error="onError" | ||||
|       > | ||||
|         <slot></slot> | ||||
|       </component> | ||||
|       <slot name="tip"></slot> | ||||
|   <div class="el-upload__inner" | ||||
|     :class="{ | ||||
|       'el-dragger': type === 'drag', | ||||
|       'is-dragOver': dragOver, | ||||
|       'is-hover': mouseover, | ||||
|       'is-showImage': showThumbnail | ||||
|     }" | ||||
|     @click="$refs.input.click()" | ||||
|     @drop.prevent="onDrop" | ||||
|     @dragover.prevent="dragOver = true" | ||||
|     @dragleave.prevent="dragOver = false" | ||||
|     @mouseenter="mouseover = true" | ||||
|     @mouseleave="mouseover = false" | ||||
|   > | ||||
|     <slot></slot> | ||||
|     <template v-if="type === 'drag' && !showThumbnail"> | ||||
|       <i class="el-icon-upload"></i> | ||||
|       <div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div> | ||||
|     </template> | ||||
| 
 | ||||
|     <!-- 拖拽类型 --> | ||||
|     <template v-if="type === 'drag'"> | ||||
|       <div class="el-dragger" | ||||
|         :class="{ | ||||
|           'is-dragOver': dragOver, | ||||
|           'is-draging': draging, | ||||
|           'is-hover': mouseover, | ||||
|           'is-showImage': showImageBlock | ||||
|         }" | ||||
|         @drop.prevent="dragOver = false" | ||||
|         @dragOver.prevent="dragOver = true" | ||||
|         @dragLeave.prevent="dragOver = false" | ||||
|         @mouseenter="mouseover = true" | ||||
|         @mouseleave="mouseover = false" | ||||
|       > | ||||
|     <template v-if="thumbnailMode"> | ||||
|       <transition name="fade-in"> | ||||
|         <el-progress | ||||
|           class="el-dragger__progress" | ||||
|           v-if="mode === 'image' && (image.status === 'success' || image.status === 'uploading')" | ||||
|           v-if="lastestFile.showProgress" | ||||
|           size="large" | ||||
|           :percentage="image.percentage" | ||||
|           :type="image.status === 'success' ? 'green' : 'blue'"> | ||||
|           :percentage="lastestFile.percentage" | ||||
|           :type="lastestFile.status === 'finished' ? 'green' : 'blue'"> | ||||
|         </el-progress> | ||||
|         <div class="el-dragger__uploaded-image" | ||||
|           v-if="mode === 'image' && image.status === 'finished'" | ||||
|           transition="slide-in-bottom" | ||||
|         > | ||||
|           <img :src="image.url"> | ||||
|           <div v-show="mouseover" class="el-dragger__uploaded-image__interact" transition="fade-in"> | ||||
|             <slot name="interact"></slot> | ||||
|       </transition> | ||||
|       <div class="el-dragger__uploaded-image" v-if="lastestFile.status === 'finished'" @click.stop> | ||||
|         <img :src="lastestFile.url"> | ||||
|         <transition name="fade-in"> | ||||
|           <div v-show="mouseover" class="el-dragger__uploaded-image__interact"> | ||||
|             <div class="el-draggeer__uploaded-image__btns"> | ||||
|               <span class="btn" @click="$refs.input.click()"><i class="el-icon-upload"></i><span>继续上传</span></span> | ||||
|               <span class="btn" @click="onPreview(lastestFile)"><i class="el-icon-search"></i><span>查看图片</span></span> | ||||
|               <span class="btn" @click="onRemove(lastestFile)"><i class="el-icon-delete"></i><span>删除</span></span> | ||||
|             </div> | ||||
|           </div> | ||||
|           <h4 v-show="mouseover" class="el-dragger__uploaded-image__title" transition="slide-in-bottom">{{image.name}}</h4> | ||||
|         </div> | ||||
|         <component :is="uploadComponent" | ||||
|           :action="action", | ||||
|           :multiple="multiple", | ||||
|           :with-credentials="withCredentials", | ||||
|           :name="name", | ||||
|           :accept="accept", | ||||
|           :on-start="onStart", | ||||
|           :on-progress="onProgress", | ||||
|           :on-success="onSuccess", | ||||
|           :on-error="onError" | ||||
|         > | ||||
|           <slot></slot> | ||||
|         </component> | ||||
|         </transition> | ||||
|         <transition name="md-fade-top"> | ||||
|           <h4 v-show="mouseover" class="el-dragger__uploaded-image__title">{{lastestFile.name}}</h4> | ||||
|         </transition> | ||||
|       </div> | ||||
| 
 | ||||
|       <slot name="tip" class="el-dragger__tip"></slot> | ||||
| 
 | ||||
|       <ul class="el-upload__files" | ||||
|         v-if="mode !== 'image' && showUploadList" | ||||
|         v-show="uploadedFiles.length > 0" | ||||
|         transition="slide-in-bottom" | ||||
|       > | ||||
|         <li class="el-upload__file" v-for="file in uploadedFiles" transition="slide-in-bottom"> | ||||
|           <i class="el-icon-document"></i>{{file.name}} | ||||
|           <i class="el-icon-check" v-show="file.status === 'success'"></i> | ||||
|           <span class="el-upload__btn-delete" @click="removeFile(file)" v-show="file.status === 'finished'">删除</span> | ||||
|           <el-progress | ||||
|             v-if="file.status === 'success' || file.status === 'uploading'" | ||||
|             size="small" | ||||
|             :percentage="file.percentage" | ||||
|             :type="file.status === 'success' ? 'green' : 'blue'"> | ||||
|           </el-progress> | ||||
|         </li> | ||||
|       </ul> | ||||
|     </template> | ||||
|     <input class="el-upload__input" type="file" ref="input" @change="handleChange" :multiple="multiple" :accept="accept"> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import AjaxUpload from './ajax-upload'; | ||||
| import IframeUpload from './iframe-upload'; | ||||
| import ElProgress from 'packages/progress/index.js'; | ||||
| import ajax from './ajax'; | ||||
| 
 | ||||
| export default { | ||||
|   name: 'el-upload', | ||||
| 
 | ||||
|   // extends: typeof FormData !== 'undefined' ? ajaxUpload : iframeUpload, | ||||
|   // extends: iframeUpload, | ||||
| 
 | ||||
|   components: { | ||||
|     ElProgress, | ||||
|     AjaxUpload, | ||||
|     IframeUpload | ||||
|   }, | ||||
| 
 | ||||
|   props: { | ||||
|     type: String, | ||||
|     action: { | ||||
|       type: String, | ||||
|       required: true | ||||
|     }, | ||||
|     headers: { | ||||
|       type: Object, | ||||
|       default() { | ||||
|         return { | ||||
|           // 'Access-Control-Request-Methods': 'GET, PUT, POST, DELETE, OPTIONS', | ||||
|           // 'Access-Control-Request-Headers': 'Content-Type, Content-Range, Content-Disposition, Content-Description' | ||||
|         }; | ||||
|       } | ||||
|     }, | ||||
|     multiple: false, | ||||
|     name: { | ||||
|       type: String, | ||||
|       default: 'file' | ||||
|     }, | ||||
|     withCredentials: { | ||||
|       type: Boolean, | ||||
|       default: false | ||||
|     }, | ||||
|     showUploadList: { | ||||
|       type: Boolean, | ||||
|       default: true | ||||
|     }, | ||||
|     withCredentials: Boolean, | ||||
|     multiple: Boolean, | ||||
|     accept: String, | ||||
|     type: { | ||||
|       type: String, | ||||
|       default: 'select' | ||||
|     onStart: Function, | ||||
|     onProgress: Function, | ||||
|     onSuccess: Function, | ||||
|     onError: Function, | ||||
|     beforeUpload: Function, | ||||
|     onPreview: { | ||||
|       type: Function, | ||||
|       default: function() {} | ||||
|     }, | ||||
|     mode: String | ||||
|     onRemove: { | ||||
|       type: Function, | ||||
|       default: function() {} | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   data() { | ||||
|     return { | ||||
|       uploading: false, | ||||
|       percentage: 0, | ||||
|       uploadedFiles: [], | ||||
|       filename: '', | ||||
|       success: false, | ||||
|       dragOver: false, | ||||
|       draging: false, | ||||
|       mouseover: false, | ||||
|       tempIndex: 1 | ||||
|       mouseover: false | ||||
|     }; | ||||
|   }, | ||||
| 
 | ||||
|   computed: { | ||||
|     uploadComponent() { | ||||
|       return typeof FormData !== 'undefined' ? 'AjaxUpload' : 'IframeUpload'; | ||||
|     lastestFile() { | ||||
|       var uploadedFiles = this.$parent.uploadedFiles; | ||||
|       return uploadedFiles.length > 0 ? uploadedFiles[uploadedFiles.length - 1] : {}; | ||||
|     }, | ||||
|     image() { | ||||
|       return this.uploadedFiles.length > 0 ? this.uploadedFiles[this.uploadedFiles.length - 1] : {}; | ||||
|     showThumbnail() { | ||||
|       var file = this.lastestFile; | ||||
|       return this.thumbnailMode && file.status && file.status !== 'fail'; | ||||
|     }, | ||||
|     showImageBlock() { | ||||
|       return this.mode === 'image' && this.image.status && this.image.status !== 'fail'; | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   ready() { | ||||
|     if (this.mode === 'image') { | ||||
|       this.accept = 'image/*'; | ||||
|     thumbnailMode() { | ||||
|       return this.$parent.thumbnailMode; | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|  | @ -189,59 +105,76 @@ export default { | |||
|     isImage(str) { | ||||
|       return str.indexOf('image') !== -1; | ||||
|     }, | ||||
|     removeFile(file) { | ||||
|       this.uploadedFiles.$remove(file); | ||||
|       this.$dispatch('fileremove', file, this.uploadedFiles); | ||||
|     handleChange(ev) { | ||||
|       const files = ev.target.files; | ||||
| 
 | ||||
|       if (!files) { | ||||
|         return; | ||||
|       } | ||||
|       this.uploadFiles(files); | ||||
|     }, | ||||
|     onStart(files) { | ||||
|       files.forEach(file => { | ||||
|     uploadFiles(files) { | ||||
|       let postFiles = Array.prototype.slice.call(files); | ||||
|       if (!this.multiple) { postFiles = postFiles.slice(0, 1); } | ||||
| 
 | ||||
|       if (postFiles.length === 0) { return; } | ||||
| 
 | ||||
|       postFiles.forEach(file => { | ||||
|         let isImage = this.isImage(file.type); | ||||
|         let uid = Date.now() + this.tempIndex++; | ||||
|         let _file = { | ||||
|           status: 'uploading', | ||||
|           name: file.name, | ||||
|           size: file.size, | ||||
|           percentage: 0, | ||||
|           uid: uid | ||||
|         }; | ||||
|         if (this.mode === 'image') { | ||||
|           if (!isImage) { | ||||
|             this.tempIndex--; | ||||
|             return; | ||||
|           } else { | ||||
|             _file.url = URL.createObjectURL(file); | ||||
|           } | ||||
| 
 | ||||
|         if (this.thumbnailMode && !isImage) { | ||||
|           return; | ||||
|         } else { | ||||
|           this.upload(file); | ||||
|         } | ||||
| 
 | ||||
|         this.uploadedFiles.push(_file); | ||||
| 
 | ||||
|         file.index = this.uploadedFiles.length - 1; | ||||
|       }); | ||||
|     }, | ||||
|     onProgress(ev, file) { | ||||
|       this.uploadedFiles[file.index].percentage = ev.percent; | ||||
|     }, | ||||
|     onSuccess(res, file) { | ||||
|       var _file = this.uploadedFiles[file.index]; | ||||
|     upload(file) { | ||||
|       if (!this.beforeUpload) { | ||||
|         return this.post(file); | ||||
|       } | ||||
| 
 | ||||
|       _file.status = 'success'; | ||||
|       setTimeout(() => { | ||||
|         _file.status = 'finished'; | ||||
|         this.reset(); | ||||
|       }, 1000); | ||||
|       const before = this.beforeUpload(file); | ||||
|       if (before && before.then) { | ||||
|         before.then(processedFile => { | ||||
|           if (Object.prototype.toString.call(processedFile) === '[object File]') { | ||||
|             this.post(processedFile); | ||||
|           } else { | ||||
|             this.post(file); | ||||
|           } | ||||
|         }, () => { | ||||
|           // this.$emit('cancel', file); | ||||
|         }); | ||||
|       } else if (before !== false) { | ||||
|         this.post(file); | ||||
|       } else { | ||||
|         // this.$emit('cancel', file); | ||||
|       } | ||||
|     }, | ||||
|     onError(err, file) { | ||||
|       var _file = this.uploadedFiles[file.index]; | ||||
|     post(file) { | ||||
|       this.onStart(file); | ||||
|       let formData = new FormData(); | ||||
|       formData.append(this.name, file); | ||||
| 
 | ||||
|       _file.status = 'finished'; | ||||
|       this.uploadedFiles.$remove(_file); | ||||
|       this.reset(); | ||||
|       console.log(err); | ||||
|       ajax(this.action, { | ||||
|         headers: this.headers, | ||||
|         withCredentials: this.withCredentials, | ||||
|         file: file, | ||||
|         filename: this.name, | ||||
|         onProgress: e => { | ||||
|           this.onProgress(e, file); | ||||
|         }, | ||||
|         onSuccess: res => { | ||||
|           this.onSuccess(res, file); | ||||
|         }, | ||||
|         onError: err => { | ||||
|           this.onError(err, file); | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     reset() { | ||||
|       this.uploading = false; | ||||
|       this.percent = 0; | ||||
|       this.filename = ''; | ||||
|     onDrop(e) { | ||||
|       this.dragOver = false; | ||||
|       this.uploadFiles(e.dataTransfer.files); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 baiyaaaaa
						baiyaaaaa