uploader.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <template>
  2. <div class="nut-uploader">
  3. <slot></slot>
  4. <input type="file" :name="name" @change="upload($event)" class="uploader" :multiple="multiple">
  5. </div>
  6. </template>
  7. <script>
  8. import Uploader from "../../utils/uploader.js";
  9. import locale from "../../mixins/locale";
  10. export default {
  11. name: "nut-uploader",
  12. mixins: [locale],
  13. props: {
  14. name: {
  15. type: String,
  16. default: ""
  17. },
  18. url: {
  19. type: String,
  20. default: ""
  21. },
  22. multiple: {
  23. type: Boolean,
  24. default: false
  25. },
  26. isPreview: {
  27. type: Boolean,
  28. default: false
  29. },
  30. maxSize: {
  31. type: Number,
  32. default: 5242880
  33. },
  34. acceptType: {
  35. type: Array,
  36. default() {
  37. return ["image/jpeg", "image/png", "image/gif", "image/bmp"];
  38. }
  39. },
  40. selfData:{
  41. type:Object,
  42. default(){
  43. return {}
  44. }
  45. },
  46. attach: {
  47. type: Object,
  48. default() {
  49. return {};
  50. }
  51. },
  52. headers:{
  53. type: Object,
  54. default() {
  55. return {};
  56. }
  57. },
  58. changeEvtCallback: {
  59. type: Function
  60. },
  61. beforeUpload:{
  62. type: Function
  63. },
  64. xhrState: {
  65. type: Number,
  66. default: 200
  67. },
  68. clearInput: {
  69. type: Boolean,
  70. default: false
  71. },
  72. xmlError: {
  73. type: String,
  74. default: ''
  75. },
  76. typeError: {
  77. type: String,
  78. default: ''
  79. },
  80. limitError: {
  81. type: String,
  82. default: ''
  83. },
  84. withCredentials: {
  85. type: Boolean,
  86. default: false
  87. }
  88. },
  89. data() {
  90. return {};
  91. },
  92. methods: {
  93. createUploaderOpts() {
  94. const _this = this;
  95. return {
  96. $el: {},
  97. url: this.url, //图片上传地址
  98. formData: null,
  99. headers: {}, //自定义headers
  100. isPreview: this.isPreview, //是否开启本地预览
  101. previewData: null,
  102. maxSize: this.maxSize, //允许上传的文件最大字节
  103. acceptType: this.acceptType, //允许上传的文件类型
  104. xhrState: this.xhrState,
  105. clearInput: this.clearInput,
  106. withCredentials: this.withCredentials,//支持发送 cookie 凭证信息
  107. xmlError: this.xmlError || this.nutTranslate('lang.uploader.xmlError'),
  108. typeError: this.typeError || this.nutTranslate('lang.uploader.typeError'),
  109. limitError: this.limitError || this.nutTranslate('lang.uploader.limitError'),
  110. onStart() {
  111. _this.$emit("start");
  112. },
  113. onProgress(file, loaded, total) {
  114. _this.$emit("progress", file, loaded, total);
  115. },
  116. onPreview(previewFile) {
  117. _this.$emit("preview", previewFile);
  118. },
  119. onSuccess(file, responseTxt) {
  120. _this.$emit("success", file, responseTxt);
  121. },
  122. onFailure(file, responseTxt) {
  123. _this.$emit("failure", file, responseTxt);
  124. }
  125. };
  126. },
  127. uploadData($event,selfData={}){
  128. const tar = $event.target;
  129. if (!this.url) {
  130. this.$emit("showMsg", "请先配置上传url");
  131. this.$emit("afterChange", tar, $event);
  132. return;
  133. }
  134. const formData = new FormData();
  135. const opt = this.createUploaderOpts();
  136. opt.$el = tar;
  137. if (this.isPreview) {
  138. opt.previewData = tar.files[0];
  139. }
  140. if (this.multiple) {
  141. for (let i = 0; i < tar.files.length; i++) {
  142. if (tar.files[i]) {
  143. if (this.acceptType.indexOf(tar.files[i].type) == -1) {
  144. this.$emit("showMsg", opt.typeError);
  145. return;
  146. }
  147. }
  148. }
  149. } else {
  150. if (tar.files[0]) {
  151. if (this.acceptType.indexOf(tar.files[0].type) == -1) {
  152. this.$emit("showMsg", opt.typeError);
  153. return;
  154. }
  155. }
  156. }
  157. formData.append(tar.name, tar.files[0]);
  158. for (let key of Object.keys(this.attach)) {
  159. formData.append(key, this.attach[key]);
  160. }
  161. let finialyOutData = Object.assign(this.selfData,selfData);
  162. if(finialyOutData){
  163. for(let key in finialyOutData){
  164. formData.append(key, finialyOutData[key]);
  165. }
  166. }
  167. opt.formData = formData;
  168. opt.headers = this.headers || {};
  169. opt.showMsgFn = msg => {
  170. this.$emit("showMsg", msg);
  171. };
  172. new Uploader(opt);
  173. this.$emit("afterChange", tar, $event);
  174. },
  175. async upload($event) {
  176. if(typeof this.beforeUpload === 'function'){
  177. let promise =new Promise((reslove,reject)=>{
  178. reslove(this.beforeUpload($event))
  179. })
  180. let resData = await promise;
  181. if(typeof resData === 'object' && typeof resData.event === 'object'){
  182. this.uploadData(resData.event,resData.data)
  183. }else{
  184. console.warn('resData: 必须包含 event字段且为input $event 的事件对象')
  185. }
  186. }else{
  187. this.uploadData($event)
  188. }
  189. }
  190. }
  191. };
  192. </script>