UploadButton.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <template>
  2. <div>
  3. <!-- <el-input
  4. v-if="!autoUpload"
  5. :style="{ width: inputWidth, marginRight: '10px' }"
  6. v-model.trim="filename"
  7. placeholder="文件名称"
  8. readonly
  9. ></el-input> -->
  10. <el-upload
  11. :action="uploadUrl"
  12. :headers="headers"
  13. :max-size="maxSize"
  14. :format="format"
  15. :accept="accept"
  16. :data="uploadDataDict"
  17. :on-error="handleError"
  18. :on-success="handleSuccess"
  19. :on-change="fileChange"
  20. :http-request="upload"
  21. :disabled="disabled || loading"
  22. :auto-upload="autoUpload"
  23. :show-file-list="false"
  24. style="display: inline-block"
  25. ref="UploadComp"
  26. >
  27. <el-button
  28. :type="btnType"
  29. :icon="btnIcon"
  30. :loading="loading"
  31. :disabled="disabled || loading"
  32. >{{ btnContent }}</el-button
  33. >
  34. </el-upload>
  35. </div>
  36. </template>
  37. <script>
  38. import { fileMD5 } from "@/plugins/md5";
  39. import { $httpWithMsg } from "@/plugins/axios";
  40. export default {
  41. name: "UploadButton",
  42. props: {
  43. inputWidth: {
  44. type: String,
  45. default: "203px",
  46. },
  47. btnIcon: {
  48. type: String,
  49. },
  50. btnType: {
  51. type: String,
  52. default: "default",
  53. },
  54. btnContent: {
  55. type: String,
  56. },
  57. accept: {
  58. type: String,
  59. },
  60. format: {
  61. type: Array,
  62. default() {
  63. return ["xlsx", "xls"];
  64. },
  65. },
  66. uploadUrl: {
  67. type: String,
  68. required: true,
  69. },
  70. uploadData: {
  71. type: Object,
  72. default() {
  73. return {};
  74. },
  75. },
  76. maxSize: {
  77. type: Number,
  78. default: 20 * 1024 * 1024,
  79. },
  80. addFileParam: {
  81. type: String,
  82. default: "file",
  83. },
  84. addFilenameParam: {
  85. type: String,
  86. default: "filename",
  87. },
  88. autoUpload: { type: Boolean, default: true },
  89. disabled: { type: Boolean, default: false },
  90. },
  91. data() {
  92. return {
  93. headers: {
  94. md5: "",
  95. },
  96. res: {},
  97. loading: false,
  98. uploadDataDict: {},
  99. filename: "",
  100. fileValid: false,
  101. };
  102. },
  103. methods: {
  104. checkFileFormat(fileType) {
  105. const _file_format = fileType.split(".").pop().toLocaleLowerCase();
  106. return this.format.length
  107. ? this.format.some((item) => item.toLocaleLowerCase() === _file_format)
  108. : false;
  109. },
  110. async fileChange(fileObj, fileList) {
  111. if (fileObj.status === "ready") {
  112. if (fileList.length > 1) {
  113. fileList[0] = fileList[1];
  114. fileList.splice(1, 1);
  115. }
  116. let res = await this.handleBeforeUpload(fileObj.raw).catch(() => {});
  117. if (res) {
  118. this.submit();
  119. }
  120. }
  121. },
  122. async handleBeforeUpload(file) {
  123. this.res = {};
  124. this.filename = file.name;
  125. this.uploadDataDict = {
  126. ...this.uploadData,
  127. };
  128. this.uploadDataDict[this.addFilenameParam] = file.name;
  129. if (!this.checkFileFormat(file.name)) {
  130. this.handleFormatError();
  131. this.fileValid = false;
  132. // return Promise.reject();
  133. return false;
  134. }
  135. if (file.size > this.maxSize) {
  136. this.handleExceededSize();
  137. this.fileValid = false;
  138. // return Promise.reject();
  139. return false;
  140. }
  141. const md5 = await fileMD5(file);
  142. this.headers["md5"] = md5;
  143. this.fileValid = true;
  144. if (this.autoUpload) {
  145. this.loading = true;
  146. return true;
  147. }
  148. return true;
  149. },
  150. submit() {
  151. if (!this.fileValid) {
  152. this.$message.error("文件错误,请重新选择文件!");
  153. return;
  154. }
  155. this.loading = true;
  156. this.$refs.UploadComp.submit();
  157. },
  158. upload(options) {
  159. if (!options.file) return Promise.reject("文件丢失");
  160. let formData = new FormData();
  161. Object.entries(options.data).forEach(([k, v]) => {
  162. formData.append(k, v);
  163. });
  164. formData.append(this.addFileParam, options.file);
  165. this.$emit("uploading");
  166. return $httpWithMsg.post(options.action, formData, {
  167. headers: options.headers,
  168. });
  169. },
  170. handleError(error) {
  171. this.loading = false;
  172. this.res = {
  173. success: false,
  174. message: error.response.data.message,
  175. };
  176. this.uploadDataDict = {};
  177. this.filename = "";
  178. this.fileValid = false;
  179. this.$refs.UploadComp.clearFiles();
  180. this.$emit("upload-error", error.response);
  181. },
  182. handleSuccess(res) {
  183. this.loading = false;
  184. this.res = {
  185. success: true,
  186. message: "导入成功!",
  187. };
  188. this.$emit("upload-success", res);
  189. },
  190. handleFormatError() {
  191. const content = "只支持文件格式为" + this.format.join("/");
  192. this.res = {
  193. success: false,
  194. message: content,
  195. };
  196. this.$emit("valid-error", this.res);
  197. },
  198. handleExceededSize() {
  199. const content =
  200. "文件大小不能超过" + Math.floor(this.maxSize / (1024 * 1024)) + "M";
  201. this.res = {
  202. success: false,
  203. message: content,
  204. };
  205. this.$emit("valid-error", this.res);
  206. },
  207. },
  208. };
  209. </script>