ImportFileDialog.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <el-dialog
  3. custom-class="side-dialog"
  4. :visible.sync="modalIsShow"
  5. :title="dialogTitle"
  6. width="520px"
  7. :modal="false"
  8. append-to-body
  9. @open="visibleChange"
  10. >
  11. <el-upload
  12. ref="UploadComp"
  13. :action="uploadUrl"
  14. :headers="headers"
  15. :max-size="maxSize"
  16. :accept="accept"
  17. :format="format"
  18. :data="uploadDataDict"
  19. :on-error="handleError"
  20. :on-success="handleSuccess"
  21. :on-change="fileChange"
  22. :http-request="upload"
  23. :show-file-list="false"
  24. :disabled="loading"
  25. :auto-upload="false"
  26. >
  27. <el-button
  28. slot="trigger"
  29. size="small"
  30. type="primary"
  31. icon="icon icon-search-white"
  32. :disabled="loading"
  33. >
  34. 选择文件
  35. </el-button>
  36. <el-button
  37. size="small"
  38. type="primary"
  39. icon="icon icon-save-white"
  40. :loading="loading"
  41. :disabled="!fileValid"
  42. @click="submitUpload"
  43. >
  44. 确认上传
  45. </el-button>
  46. <el-button
  47. size="small"
  48. type="primary"
  49. icon="icon icon-delete-white"
  50. :disabled="loading"
  51. @click="removeFile"
  52. >
  53. 清空文件
  54. </el-button>
  55. <el-button
  56. v-if="templateUrl || templateDownloadHandle"
  57. size="small"
  58. type="primary"
  59. icon="icon icon-export-white"
  60. @click="exportFile"
  61. >
  62. 下载模板
  63. </el-button>
  64. </el-upload>
  65. <p v-if="filename" class="tips-info">{{ filename }}</p>
  66. <p v-if="!res.success" class="tips-info tips-error">{{ res.message }}</p>
  67. </el-dialog>
  68. </template>
  69. <script>
  70. import { fileMD5 } from "@/plugins/md5";
  71. import { $httpWithMsg } from "@/plugins/axios";
  72. export default {
  73. name: "ImportFileDialog",
  74. props: {
  75. dialogTitle: {
  76. type: String,
  77. default: "导入文件",
  78. },
  79. format: {
  80. type: Array,
  81. default() {
  82. return ["xlsx", "xls"];
  83. },
  84. },
  85. accept: {
  86. type: String,
  87. default: null,
  88. },
  89. uploadUrl: {
  90. type: String,
  91. required: true,
  92. },
  93. uploadData: {
  94. type: Object,
  95. default() {
  96. return {};
  97. },
  98. },
  99. maxSize: {
  100. type: Number,
  101. default: 20 * 1024 * 1024,
  102. },
  103. addFilenameParam: {
  104. type: String,
  105. default: "filename",
  106. },
  107. addFileParam: {
  108. type: String,
  109. default: "file",
  110. },
  111. templateUrl: {
  112. type: String,
  113. default: "",
  114. },
  115. templateDownloadHandle: {
  116. type: Function,
  117. default: null,
  118. },
  119. },
  120. data() {
  121. return {
  122. modalIsShow: false,
  123. headers: {
  124. md5: "",
  125. },
  126. res: {},
  127. loading: false,
  128. uploadDataDict: {},
  129. filename: "",
  130. fileValid: false,
  131. };
  132. },
  133. methods: {
  134. visibleChange() {
  135. this.res = {};
  136. this.loading = false;
  137. this.uploadDataDict = {};
  138. this.filename = "";
  139. this.fileValid = false;
  140. },
  141. cancel() {
  142. this.modalIsShow = false;
  143. },
  144. open() {
  145. this.modalIsShow = true;
  146. },
  147. checkFileFormat(fileType) {
  148. const _file_format = fileType.split(".").pop().toLowerCase();
  149. return this.format.length
  150. ? this.format.some((item) => item.toLowerCase() === _file_format)
  151. : true;
  152. },
  153. fileChange(fileObj) {
  154. if (fileObj.status === "ready") {
  155. this.handleBeforeUpload(fileObj.raw).catch(() => {});
  156. }
  157. },
  158. async handleBeforeUpload(file) {
  159. this.res = {};
  160. this.filename = file.name;
  161. this.uploadDataDict = {
  162. ...this.uploadData,
  163. };
  164. this.uploadDataDict[this.addFilenameParam] = file.name;
  165. if (!this.checkFileFormat(file.name)) {
  166. this.handleFormatError();
  167. this.fileValid = false;
  168. return Promise.reject();
  169. }
  170. if (file.size > this.maxSize) {
  171. this.handleExceededSize();
  172. this.fileValid = false;
  173. return Promise.reject();
  174. }
  175. const md5 = await fileMD5(file);
  176. this.headers["md5"] = md5;
  177. this.fileValid = true;
  178. return true;
  179. },
  180. upload(options) {
  181. if (!options.file) return Promise.reject("文件丢失");
  182. let formData = new FormData();
  183. Object.entries(options.data).forEach(([k, v]) => {
  184. formData.append(k, v);
  185. });
  186. formData.append(this.addFileParam, options.file);
  187. return $httpWithMsg.post(options.action, formData, {
  188. headers: options.headers,
  189. });
  190. },
  191. handleError(error) {
  192. this.loading = false;
  193. this.res = {
  194. success: false,
  195. message: error.response.data.desc,
  196. };
  197. this.uploadDataDict = {};
  198. this.filename = "";
  199. this.fileValid = false;
  200. this.$refs.UploadComp.clearFiles();
  201. },
  202. handleSuccess(res) {
  203. this.loading = false;
  204. this.res = {
  205. success: true,
  206. message: "导入成功!",
  207. };
  208. this.cancel();
  209. this.$emit("uploaded", res);
  210. },
  211. handleFormatError() {
  212. const content = "只支持文件格式为" + this.format.join("/");
  213. this.res = {
  214. success: false,
  215. message: content,
  216. };
  217. },
  218. handleExceededSize() {
  219. const content =
  220. "文件大小不能超过" + Math.floor(this.maxSize / (1024 * 1024)) + "M";
  221. this.res = {
  222. success: false,
  223. message: content,
  224. };
  225. },
  226. // action
  227. submitUpload() {
  228. if (this.loading) return;
  229. this.$refs.UploadComp.submit();
  230. this.loading = true;
  231. },
  232. removeFile() {
  233. if (this.loading) return;
  234. this.uploadDataDict = {};
  235. this.filename = "";
  236. this.fileValid = false;
  237. this.res = {};
  238. this.$refs.UploadComp.clearFiles();
  239. },
  240. exportFile() {
  241. if (this.templateUrl) {
  242. window.open(this.templateUrl);
  243. return;
  244. }
  245. if (this.templateDownloadHandle) {
  246. this.templateDownloadHandle();
  247. return;
  248. }
  249. },
  250. },
  251. };
  252. </script>