de539dd9b17875bc0f2293341824bd7d7f96b24694fdf38ad7ec880b371ccff068e697c2c6e8723ba6cdb46cb1395f723bb8f9d283c8aad0964babad82413f 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <script>
  2. import ajax from './ajax';
  3. import UploadDragger from './upload-dragger.vue';
  4. export default {
  5. inject: ['uploader'],
  6. components: {
  7. UploadDragger
  8. },
  9. props: {
  10. type: String,
  11. action: {
  12. type: String,
  13. required: true
  14. },
  15. name: {
  16. type: String,
  17. default: 'file'
  18. },
  19. data: Object,
  20. headers: Object,
  21. withCredentials: Boolean,
  22. multiple: Boolean,
  23. accept: String,
  24. onStart: Function,
  25. onProgress: Function,
  26. onSuccess: Function,
  27. onError: Function,
  28. beforeUpload: Function,
  29. drag: Boolean,
  30. onPreview: {
  31. type: Function,
  32. default: function() {}
  33. },
  34. onRemove: {
  35. type: Function,
  36. default: function() {}
  37. },
  38. fileList: Array,
  39. autoUpload: Boolean,
  40. listType: String,
  41. httpRequest: {
  42. type: Function,
  43. default: ajax
  44. },
  45. disabled: Boolean,
  46. limit: Number,
  47. onExceed: Function
  48. },
  49. data() {
  50. return {
  51. mouseover: false,
  52. reqs: {}
  53. };
  54. },
  55. methods: {
  56. isImage(str) {
  57. return str.indexOf('image') !== -1;
  58. },
  59. handleChange(ev) {
  60. const files = ev.target.files;
  61. if (!files) return;
  62. this.uploadFiles(files);
  63. },
  64. uploadFiles(files) {
  65. if (this.limit && this.fileList.length + files.length > this.limit) {
  66. this.onExceed && this.onExceed(files, this.fileList);
  67. return;
  68. }
  69. let postFiles = Array.prototype.slice.call(files);
  70. if (!this.multiple) { postFiles = postFiles.slice(0, 1); }
  71. if (postFiles.length === 0) { return; }
  72. postFiles.forEach(rawFile => {
  73. this.onStart(rawFile);
  74. if (this.autoUpload) this.upload(rawFile);
  75. });
  76. },
  77. upload(rawFile) {
  78. this.$refs.input.value = null;
  79. if (!this.beforeUpload) {
  80. return this.post(rawFile);
  81. }
  82. const before = this.beforeUpload(rawFile);
  83. if (before && before.then) {
  84. before.then(processedFile => {
  85. const fileType = Object.prototype.toString.call(processedFile);
  86. if (fileType === '[object File]' || fileType === '[object Blob]') {
  87. if (fileType === '[object Blob]') {
  88. processedFile = new File([processedFile], rawFile.name, {
  89. type: rawFile.type
  90. });
  91. }
  92. for (const p in rawFile) {
  93. if (rawFile.hasOwnProperty(p)) {
  94. processedFile[p] = rawFile[p];
  95. }
  96. }
  97. this.post(processedFile);
  98. } else {
  99. this.post(rawFile);
  100. }
  101. }, () => {
  102. this.onRemove(null, rawFile);
  103. });
  104. } else if (before !== false) {
  105. this.post(rawFile);
  106. } else {
  107. this.onRemove(null, rawFile);
  108. }
  109. },
  110. abort(file) {
  111. const { reqs } = this;
  112. if (file) {
  113. let uid = file;
  114. if (file.uid) uid = file.uid;
  115. if (reqs[uid]) {
  116. reqs[uid].abort();
  117. }
  118. } else {
  119. Object.keys(reqs).forEach((uid) => {
  120. if (reqs[uid]) reqs[uid].abort();
  121. delete reqs[uid];
  122. });
  123. }
  124. },
  125. post(rawFile) {
  126. const { uid } = rawFile;
  127. const options = {
  128. headers: this.headers,
  129. withCredentials: this.withCredentials,
  130. file: rawFile,
  131. data: this.data,
  132. filename: this.name,
  133. action: this.action,
  134. onProgress: e => {
  135. this.onProgress(e, rawFile);
  136. },
  137. onSuccess: res => {
  138. this.onSuccess(res, rawFile);
  139. delete this.reqs[uid];
  140. },
  141. onError: err => {
  142. this.onError(err, rawFile);
  143. delete this.reqs[uid];
  144. }
  145. };
  146. const req = this.httpRequest(options);
  147. this.reqs[uid] = req;
  148. if (req && req.then) {
  149. req.then(options.onSuccess, options.onError);
  150. }
  151. },
  152. handleClick() {
  153. if (!this.disabled) {
  154. this.$refs.input.value = null;
  155. this.$refs.input.click();
  156. }
  157. },
  158. handleKeydown(e) {
  159. if (e.target !== e.currentTarget) return;
  160. if (e.keyCode === 13 || e.keyCode === 32) {
  161. this.handleClick();
  162. }
  163. }
  164. },
  165. render(h) {
  166. let {
  167. handleClick,
  168. drag,
  169. name,
  170. handleChange,
  171. multiple,
  172. accept,
  173. listType,
  174. uploadFiles,
  175. disabled,
  176. handleKeydown
  177. } = this;
  178. const data = {
  179. class: {
  180. 'el-upload': true
  181. },
  182. on: {
  183. click: handleClick,
  184. keydown: handleKeydown
  185. }
  186. };
  187. data.class[`el-upload--${listType}`] = true;
  188. return (
  189. <div {...data} tabindex="0" >
  190. {
  191. drag
  192. ? <upload-dragger disabled={disabled} on-file={uploadFiles}>{this.$slots.default}</upload-dragger>
  193. : this.$slots.default
  194. }
  195. <input class="el-upload__input" type="file" ref="input" name={name} on-change={handleChange} multiple={multiple} accept={accept}></input>
  196. </div>
  197. );
  198. }
  199. };
  200. </script>