ImportFileDialog.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <template>
  2. <el-dialog
  3. custom-class="import-file-dialog"
  4. :visible.sync="modalIsShow"
  5. :title="dialogTitle"
  6. width="480px"
  7. :modal="true"
  8. append-to-body
  9. @open="visibleChange"
  10. @close="dialogClose"
  11. >
  12. <div class="tpl-download">
  13. <span>模板下载:</span>
  14. <svg-btn
  15. name="daoru"
  16. color="#6D5FF6"
  17. hoverBgColor="#fff"
  18. @click="exportFile"
  19. >下载</svg-btn
  20. >
  21. </div>
  22. <el-upload
  23. ref="UploadComp"
  24. drag
  25. :action="uploadUrl"
  26. :headers="headers"
  27. :max-size="maxSize"
  28. :accept="accept"
  29. :format="format"
  30. :data="uploadDataDict"
  31. :on-error="handleError"
  32. :on-success="handleSuccess"
  33. :on-change="fileChange"
  34. :http-request="upload"
  35. :disabled="loading"
  36. :auto-upload="false"
  37. :multiple="false"
  38. :before-remove="beforeRemove"
  39. style="text-align: center"
  40. >
  41. <i class="el-icon-upload"></i>
  42. <div class="el-upload__text">
  43. {{ `点击或将文件拖拽到这里上传(只能上传${format.join("、")}文件)` }}
  44. </div>
  45. <!-- <el-button
  46. slot="trigger"
  47. size="small"
  48. type="primary"
  49. icon="icon icon-search-white"
  50. :disabled="loading"
  51. >
  52. 选择文件
  53. </el-button>
  54. <el-button
  55. size="small"
  56. type="primary"
  57. icon="icon icon-save-white"
  58. :loading="loading"
  59. :disabled="!fileValid"
  60. @click="submitUpload"
  61. >
  62. 确认上传
  63. </el-button>
  64. <el-button
  65. size="small"
  66. type="primary"
  67. icon="icon icon-delete-white"
  68. :disabled="loading"
  69. @click="removeFile"
  70. >
  71. 清空文件
  72. </el-button>
  73. <el-button
  74. v-if="templateUrl || templateDownloadHandle"
  75. size="small"
  76. type="primary"
  77. icon="icon icon-export-white"
  78. :loading="downloading"
  79. @click="exportFile"
  80. >
  81. 下载模板
  82. </el-button> -->
  83. </el-upload>
  84. <!-- <p v-if="filename" class="tips-info">{{ filename }}</p> -->
  85. <p v-if="!res.success" class="tips-info tips-error">{{ res.message }}</p>
  86. <div slot="footer">
  87. <el-button type="primary" @click="submitUpload" :disabled="!filename"
  88. >确认</el-button
  89. >
  90. <el-button @click="cancel">取消</el-button>
  91. </div>
  92. </el-dialog>
  93. </template>
  94. <script>
  95. import { fileMD5 } from "@/plugins/md5";
  96. import { $httpWithMsg } from "@/plugins/axios";
  97. import { downloadByApi } from "@/plugins/download";
  98. export default {
  99. name: "ImportFileDialog",
  100. props: {
  101. dialogTitle: {
  102. type: String,
  103. default: "导入文件",
  104. },
  105. format: {
  106. type: Array,
  107. default() {
  108. return ["xlsx", "xls"];
  109. },
  110. },
  111. accept: {
  112. type: String,
  113. default: null,
  114. },
  115. uploadUrl: {
  116. type: String,
  117. required: true,
  118. },
  119. uploadData: {
  120. type: Object,
  121. default() {
  122. return {};
  123. },
  124. },
  125. maxSize: {
  126. type: Number,
  127. default: 20 * 1024 * 1024,
  128. },
  129. addFilenameParam: {
  130. type: String,
  131. default: "filename",
  132. },
  133. addFileParam: {
  134. type: String,
  135. default: "file",
  136. },
  137. templateUrl: {
  138. type: String,
  139. default: "",
  140. },
  141. templateDownloadHandle: {
  142. type: Function,
  143. default: null,
  144. },
  145. },
  146. data() {
  147. return {
  148. modalIsShow: false,
  149. headers: {
  150. md5: "",
  151. },
  152. res: {},
  153. loading: false,
  154. uploadDataDict: {},
  155. filename: "",
  156. fileValid: false,
  157. downloading: false,
  158. };
  159. },
  160. methods: {
  161. dialogClose() {
  162. this.res = {};
  163. this.loading = false;
  164. this.uploadDataDict = {};
  165. this.filename = "";
  166. this.fileValid = false;
  167. this.$refs.UploadComp.clearFiles();
  168. },
  169. visibleChange() {},
  170. cancel() {
  171. this.modalIsShow = false;
  172. },
  173. open() {
  174. this.modalIsShow = true;
  175. },
  176. checkFileFormat(fileType) {
  177. const _file_format = fileType.split(".").pop().toLowerCase();
  178. return this.format.length
  179. ? this.format.some((item) => item.toLowerCase() === _file_format)
  180. : true;
  181. },
  182. beforeRemove() {
  183. this.dialogClose();
  184. return true;
  185. },
  186. fileChange(fileObj, fileList) {
  187. if (fileObj.status === "ready") {
  188. this.handleBeforeUpload(fileObj.raw).catch(() => {});
  189. if (fileList.length > 1) {
  190. fileList[0] = fileList[1];
  191. fileList.splice(1, 1);
  192. }
  193. }
  194. },
  195. async handleBeforeUpload(file) {
  196. this.res = {};
  197. console.log("handleBeforeUpload");
  198. this.filename = file.name;
  199. this.uploadDataDict = {
  200. ...this.uploadData,
  201. };
  202. this.uploadDataDict[this.addFilenameParam] = file.name;
  203. if (!this.checkFileFormat(file.name)) {
  204. this.handleFormatError();
  205. this.fileValid = false;
  206. return Promise.reject();
  207. }
  208. if (file.size > this.maxSize) {
  209. this.handleExceededSize();
  210. this.fileValid = false;
  211. return Promise.reject();
  212. }
  213. const md5 = await fileMD5(file);
  214. this.headers["md5"] = md5;
  215. this.fileValid = true;
  216. return true;
  217. },
  218. upload(options) {
  219. if (!options.file) return Promise.reject("文件丢失");
  220. let formData = new FormData();
  221. Object.entries(options.data).forEach(([k, v]) => {
  222. formData.append(k, v);
  223. });
  224. formData.append(this.addFileParam, options.file);
  225. return $httpWithMsg.post(options.action, formData, {
  226. headers: options.headers,
  227. });
  228. },
  229. handleError(error) {
  230. this.loading = false;
  231. this.res = {
  232. success: false,
  233. message: error.response.data.message,
  234. };
  235. console.log("err", error.response);
  236. this.uploadDataDict = {};
  237. this.filename = "";
  238. this.fileValid = false;
  239. this.$refs.UploadComp.clearFiles();
  240. },
  241. handleSuccess(res) {
  242. this.loading = false;
  243. this.res = {
  244. success: true,
  245. message: "导入成功!",
  246. };
  247. this.cancel();
  248. this.$emit("uploaded", res);
  249. },
  250. handleFormatError() {
  251. const content = "只支持文件格式为" + this.format.join("/");
  252. this.res = {
  253. success: false,
  254. message: content,
  255. };
  256. },
  257. handleExceededSize() {
  258. const content =
  259. "文件大小不能超过" + Math.floor(this.maxSize / (1024 * 1024)) + "M";
  260. this.res = {
  261. success: false,
  262. message: content,
  263. };
  264. },
  265. // action
  266. submitUpload() {
  267. if (this.loading) return;
  268. this.$refs.UploadComp.submit();
  269. this.loading = true;
  270. },
  271. // removeFile() {
  272. // if (this.loading) return;
  273. // this.uploadDataDict = {};
  274. // this.filename = "";
  275. // this.fileValid = false;
  276. // this.res = {};
  277. // this.$refs.UploadComp.clearFiles();
  278. // },
  279. exportFile() {
  280. if (this.templateUrl) {
  281. this.toDownload();
  282. return;
  283. }
  284. if (this.templateDownloadHandle) {
  285. this.toHandleDownload();
  286. }
  287. },
  288. async toDownload() {
  289. if (this.downloading) return;
  290. this.downloading = true;
  291. const res = await downloadByApi(() => {
  292. return $httpWithMsg.get(this.templateUrl, {
  293. responseType: "blob",
  294. });
  295. }).catch((e) => {
  296. this.$message.error(e || "下载失败,请重新尝试!");
  297. });
  298. this.downloading = false;
  299. if (!res) return;
  300. this.$message.success("下载成功!");
  301. },
  302. async toHandleDownload() {
  303. if (this.downloading) return;
  304. this.downloading = true;
  305. await this.templateDownloadHandle().catch(() => {});
  306. this.downloading = false;
  307. },
  308. },
  309. };
  310. </script>
  311. <style lang="scss">
  312. .import-file-dialog {
  313. .el-dialog__body {
  314. background-color: #f0f0f0;
  315. padding-top: 15px;
  316. padding-bottom: 10px;
  317. .tpl-download {
  318. display: flex;
  319. align-items: center;
  320. margin-bottom: 15px;
  321. }
  322. .el-upload.el-upload--text {
  323. width: 100%;
  324. .el-upload-dragger {
  325. width: 100%;
  326. }
  327. }
  328. }
  329. }
  330. </style>