Showing
5 changed files
with
255 additions
and
26 deletions
| ... | @@ -5,7 +5,7 @@ VUE_APP_BASE_ENV = "dev" | ... | @@ -5,7 +5,7 @@ VUE_APP_BASE_ENV = "dev" |
| 5 | 5 | ||
| 6 | VUE_APP_Version = '1.0.11' | 6 | VUE_APP_Version = '1.0.11' |
| 7 | 7 | ||
| 8 | -VUE_APP_BASE_URL = 'http://101.132.100.41:7008/EcomExp' | 8 | +VUE_APP_BASE_URL = 'http://101.132.100.41:7001/EcomExp' |
| 9 | # FedEx 在线申报工具/开发环境 | 9 | # FedEx 在线申报工具/开发环境 |
| 10 | # http://101.132.100.41:7001/EcomExp | 10 | # http://101.132.100.41:7001/EcomExp |
| 11 | VUE_APP_BASE_API = /EcomExp | 11 | VUE_APP_BASE_API = /EcomExp | ... | ... |
| ... | @@ -29,3 +29,12 @@ export function getResend({ id }) { | ... | @@ -29,3 +29,12 @@ export function getResend({ id }) { |
| 29 | method: "get", | 29 | method: "get", |
| 30 | }); | 30 | }); |
| 31 | } | 31 | } |
| 32 | + | ||
| 33 | +//提交广州客户申报数据异步导出任务 | ||
| 34 | +export function getSubmitExportTask(data) { | ||
| 35 | + return request({ | ||
| 36 | + url: `/bus-customer/customerDeclareData/submitExportTask`, | ||
| 37 | + method: "post", | ||
| 38 | + data: data, | ||
| 39 | + }); | ||
| 40 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -2,7 +2,7 @@ import axios from "axios"; | ... | @@ -2,7 +2,7 @@ import axios from "axios"; |
| 2 | import store from "@/store"; | 2 | import store from "@/store"; |
| 3 | import { getToken } from "@/utils/auth"; | 3 | import { getToken } from "@/utils/auth"; |
| 4 | import { getDownLoadFileStatus } from "@/utils/iClearExp.js"; | 4 | import { getDownLoadFileStatus } from "@/utils/iClearExp.js"; |
| 5 | -import { alertWarningMsg } from "@/utils/index.js"; | 5 | +import { alertWarningMsg, formatDateNew } from "@/utils/index.js"; |
| 6 | 6 | ||
| 7 | const mimeMap = { | 7 | const mimeMap = { |
| 8 | xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", | 8 | xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| ... | @@ -91,6 +91,96 @@ export function downLoadZip(urlStatus, str, filename, type, method, data) { | ... | @@ -91,6 +91,96 @@ export function downLoadZip(urlStatus, str, filename, type, method, data) { |
| 91 | }); | 91 | }); |
| 92 | }); | 92 | }); |
| 93 | } | 93 | } |
| 94 | + | ||
| 95 | +// 按 taskId 下载异步导出文件,支持 10103 状态重试 | ||
| 96 | +export function downloadAsyncExportByTaskId(taskId, options = {}) { | ||
| 97 | + const { | ||
| 98 | + retryCount = 0, | ||
| 99 | + maxRetry = 50, | ||
| 100 | + retryDelay = 5000, | ||
| 101 | + mimeType = mimeMap.xlsx, | ||
| 102 | + onRetryExhausted, | ||
| 103 | + onWarning, | ||
| 104 | + onSuccess, | ||
| 105 | + } = options; | ||
| 106 | + | ||
| 107 | + const warningHandler = onWarning || alertWarningMsg; | ||
| 108 | + const url = `${baseUrl}${apiUrl.customDownloadXls}/${taskId}`; | ||
| 109 | + | ||
| 110 | + return axios({ | ||
| 111 | + method: "get", | ||
| 112 | + url, | ||
| 113 | + responseType: "blob", | ||
| 114 | + headers: { | ||
| 115 | + Authorization: "Bearer " + getToken(), | ||
| 116 | + Ver: process.env.VUE_APP_APIVERSION, | ||
| 117 | + }, | ||
| 118 | + }) | ||
| 119 | + .then((res) => { | ||
| 120 | + const aLink = document.createElement("a"); | ||
| 121 | + const blob = new Blob([res.data], { type: mimeType }); | ||
| 122 | + if (blob.size < 500) { | ||
| 123 | + return new Promise((resolve, reject) => { | ||
| 124 | + const reader = new FileReader(); | ||
| 125 | + reader.readAsText(blob, "utf-8"); | ||
| 126 | + reader.onloadend = () => { | ||
| 127 | + if (reader.result && reader.result != null && reader.result != "") { | ||
| 128 | + try { | ||
| 129 | + const jsonData = JSON.parse(reader.result); | ||
| 130 | + if (jsonData.code == "10103") { | ||
| 131 | + if (retryCount < maxRetry) { | ||
| 132 | + setTimeout(() => { | ||
| 133 | + downloadAsyncExportByTaskId(taskId, { | ||
| 134 | + ...options, | ||
| 135 | + retryCount: retryCount + 1, | ||
| 136 | + }) | ||
| 137 | + .then(resolve) | ||
| 138 | + .catch(reject); | ||
| 139 | + }, retryDelay); | ||
| 140 | + } else { | ||
| 141 | + if (typeof onRetryExhausted === "function") { | ||
| 142 | + onRetryExhausted(); | ||
| 143 | + } else { | ||
| 144 | + warningHandler("导出失败"); | ||
| 145 | + } | ||
| 146 | + reject(new Error("Async export retry exceeded.")); | ||
| 147 | + } | ||
| 148 | + return; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + warningHandler(jsonData.message || "文件无法下载,请重新生成后再试!"); | ||
| 152 | + reject(new Error(jsonData.message || "Download failed.")); | ||
| 153 | + } catch (error) { | ||
| 154 | + warningHandler("文件无法下载,请重新生成后再试!"); | ||
| 155 | + reject(error); | ||
| 156 | + } | ||
| 157 | + } else { | ||
| 158 | + warningHandler("文件无法下载,请重新生成后再试!"); | ||
| 159 | + reject(new Error("Blob response is empty.")); | ||
| 160 | + } | ||
| 161 | + }; | ||
| 162 | + reader.onerror = () => { | ||
| 163 | + warningHandler("文件无法下载,请重新生成后再试!"); | ||
| 164 | + reject(new Error("Blob read failed.")); | ||
| 165 | + }; | ||
| 166 | + }); | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + const fileName = `${formatDateNew(new Date())}.xlsx`; | ||
| 170 | + aLink.href = URL.createObjectURL(blob); | ||
| 171 | + aLink.setAttribute("download", fileName); | ||
| 172 | + document.body.appendChild(aLink); | ||
| 173 | + aLink.click(); | ||
| 174 | + document.body.removeChild(aLink); | ||
| 175 | + if (typeof onSuccess === "function") { | ||
| 176 | + onSuccess(); | ||
| 177 | + } | ||
| 178 | + return res; | ||
| 179 | + }) | ||
| 180 | + .catch((error) => { | ||
| 181 | + return Promise.reject(error); | ||
| 182 | + }); | ||
| 183 | +} | ||
| 94 | /** | 184 | /** |
| 95 | * 解析blob响应内容并下载 | 185 | * 解析blob响应内容并下载 |
| 96 | * @param {*} res blob响应内容 | 186 | * @param {*} res blob响应内容 | ... | ... |
| ... | @@ -1104,7 +1104,9 @@ export default { | ... | @@ -1104,7 +1104,9 @@ export default { |
| 1104 | this.logtableType = !this.logtableType; | 1104 | this.logtableType = !this.logtableType; |
| 1105 | }, | 1105 | }, |
| 1106 | back() { | 1106 | back() { |
| 1107 | + this.$store.dispatch("tagsView/delView", this.$route).finally(() => { | ||
| 1107 | this.$router.go(-1); | 1108 | this.$router.go(-1); |
| 1109 | + }); | ||
| 1108 | }, | 1110 | }, |
| 1109 | 1111 | ||
| 1110 | //添加新商品 | 1112 | //添加新商品 | ... | ... |
| ... | @@ -125,7 +125,17 @@ | ... | @@ -125,7 +125,17 @@ |
| 125 | </el-col> | 125 | </el-col> |
| 126 | </el-row> | 126 | </el-row> |
| 127 | </el-form> | 127 | </el-form> |
| 128 | - <div style="height: 20px"></div> | 128 | + <div style="text-align: right; padding: 5px"> |
| 129 | + <el-button | ||
| 130 | + class="entrySaveButton" | ||
| 131 | + size="small" | ||
| 132 | + icon="el-icon-download" | ||
| 133 | + :loading="loadings.exportDeclareLoading" | ||
| 134 | + @click="downloadData" | ||
| 135 | + > | ||
| 136 | + 导出 | ||
| 137 | + </el-button> | ||
| 138 | + </div> | ||
| 129 | <Table | 139 | <Table |
| 130 | class="fedexDetialTable fedexSreachTable" | 140 | class="fedexDetialTable fedexSreachTable" |
| 131 | ref="entryTable" | 141 | ref="entryTable" |
| ... | @@ -140,9 +150,11 @@ | ... | @@ -140,9 +150,11 @@ |
| 140 | :totalCount="page.total" | 150 | :totalCount="page.total" |
| 141 | @sizeChange="sizeChange" | 151 | @sizeChange="sizeChange" |
| 142 | @currentChange="currentChange" | 152 | @currentChange="currentChange" |
| 143 | - :selection="false" | 153 | + :selection="true" |
| 144 | :selectFixed="false" | 154 | :selectFixed="false" |
| 145 | :rowSelectDataType="false" | 155 | :rowSelectDataType="false" |
| 156 | + @tableSelect="tableSelect" | ||
| 157 | + @tableSelectAll="tableSelectAll" | ||
| 146 | > | 158 | > |
| 147 | <template v-slot:logisticsNo="scope"> | 159 | <template v-slot:logisticsNo="scope"> |
| 148 | <el-button type="text" @click="view(scope.row)">{{ | 160 | <el-button type="text" @click="view(scope.row)">{{ |
| ... | @@ -167,7 +179,9 @@ | ... | @@ -167,7 +179,9 @@ |
| 167 | </template> | 179 | </template> |
| 168 | 180 | ||
| 169 | <script> | 181 | <script> |
| 170 | -import { getPddInfo, getResend } from "@/api/pdd-info"; | 182 | +import { getPddInfo, getResend, getSubmitExportTask } from "@/api/pdd-info"; |
| 183 | +import { getTaskStatus } from "@/api/exportList-api.js"; | ||
| 184 | +import { downloadAsyncExportByTaskId } from "@/utils/zipdownload"; | ||
| 171 | export default { | 185 | export default { |
| 172 | name: "PddList", | 186 | name: "PddList", |
| 173 | components: {}, | 187 | components: {}, |
| ... | @@ -187,7 +201,6 @@ export default { | ... | @@ -187,7 +201,6 @@ export default { |
| 187 | total: 0, | 201 | total: 0, |
| 188 | }, | 202 | }, |
| 189 | tableData: [], | 203 | tableData: [], |
| 190 | - | ||
| 191 | headerData: [ | 204 | headerData: [ |
| 192 | { | 205 | { |
| 193 | name: "物流运单编号", | 206 | name: "物流运单编号", |
| ... | @@ -248,8 +261,14 @@ export default { | ... | @@ -248,8 +261,14 @@ export default { |
| 248 | ], | 261 | ], |
| 249 | loadings: { | 262 | loadings: { |
| 250 | searchLoading: false, | 263 | searchLoading: false, |
| 264 | + exportDeclareLoading: false, | ||
| 251 | }, | 265 | }, |
| 252 | tableMaxheight: null, | 266 | tableMaxheight: null, |
| 267 | + selected: [], | ||
| 268 | + currentTaskId: null, | ||
| 269 | + pollTimer: null, | ||
| 270 | + isPolling: false, | ||
| 271 | + pollInterval: 5000, // 轮询间隔(5秒) | ||
| 253 | }; | 272 | }; |
| 254 | }, | 273 | }, |
| 255 | created() { | 274 | created() { |
| ... | @@ -290,6 +309,32 @@ export default { | ... | @@ -290,6 +309,32 @@ export default { |
| 290 | }; | 309 | }; |
| 291 | this.originalLogisticsNo = ""; | 310 | this.originalLogisticsNo = ""; |
| 292 | }, | 311 | }, |
| 312 | + //导出 | ||
| 313 | + downloadData() { | ||
| 314 | + let obj = { | ||
| 315 | + ...this.searchInfo(JSON.parse(JSON.stringify(this.sreachFormData))), | ||
| 316 | + ids: [], | ||
| 317 | + }; | ||
| 318 | + obj.ids = this.selected.map((item) => item.id); | ||
| 319 | + this.loadings.exportDeclareLoading = true; | ||
| 320 | + | ||
| 321 | + this.$confirm(`正在导出中,请稍候!`, "提示", { | ||
| 322 | + confirmButtonText: "确定", | ||
| 323 | + cancelButtonText: "取消", | ||
| 324 | + type: "warning", | ||
| 325 | + }) | ||
| 326 | + .then(() => { | ||
| 327 | + getSubmitExportTask(obj).then((res) => { | ||
| 328 | + if (res.code === "200") { | ||
| 329 | + this.currentTaskId = res.data; | ||
| 330 | + this.startPolling(); | ||
| 331 | + } | ||
| 332 | + }); | ||
| 333 | + }) | ||
| 334 | + .catch(() => { | ||
| 335 | + this.loadings.exportDeclareLoading = false; | ||
| 336 | + }); | ||
| 337 | + }, | ||
| 293 | showAgain(row) { | 338 | showAgain(row) { |
| 294 | this.$confirm("是否确认操作重新发送?", "提示", { | 339 | this.$confirm("是否确认操作重新发送?", "提示", { |
| 295 | confirmButtonText: "确定", | 340 | confirmButtonText: "确定", |
| ... | @@ -314,7 +359,27 @@ export default { | ... | @@ -314,7 +359,27 @@ export default { |
| 314 | if (val == 0) { | 359 | if (val == 0) { |
| 315 | this.page.pageIndex = 1; | 360 | this.page.pageIndex = 1; |
| 316 | } | 361 | } |
| 317 | - let obj = { ...this.sreachFormData }; // 使用对象展开运算符复制 sreachFormData | 362 | + let obj = this.searchInfo(JSON.parse(JSON.stringify(this.sreachFormData))); |
| 363 | + getPddInfo(obj) | ||
| 364 | + .then((res) => { | ||
| 365 | + if (res.code === "200") { | ||
| 366 | + this.tableData = res.data.value; | ||
| 367 | + this.page.total = res.data.totalItems; | ||
| 368 | + this.tableData.forEach((item, idx) => { | ||
| 369 | + item.index = idx; | ||
| 370 | + }); | ||
| 371 | + } else { | ||
| 372 | + this.alertWarningMsg(res.message); | ||
| 373 | + } | ||
| 374 | + this.loadings.searchLoading = false; | ||
| 375 | + }) | ||
| 376 | + .catch((err) => { | ||
| 377 | + console.log(err); | ||
| 378 | + this.loadings.searchLoading = false; | ||
| 379 | + }); | ||
| 380 | + }, | ||
| 381 | + | ||
| 382 | + searchInfo(obj) { | ||
| 318 | obj.pageIndex = this.page.pageIndex; | 383 | obj.pageIndex = this.page.pageIndex; |
| 319 | obj.pageSize = this.page.pageSize; | 384 | obj.pageSize = this.page.pageSize; |
| 320 | obj.logisticsNo = this.originalLogisticsNo; | 385 | obj.logisticsNo = this.originalLogisticsNo; |
| ... | @@ -334,26 +399,8 @@ export default { | ... | @@ -334,26 +399,8 @@ export default { |
| 334 | obj.startTime = obj.createTime[0]; | 399 | obj.startTime = obj.createTime[0]; |
| 335 | obj.endTime = obj.createTime[1]; | 400 | obj.endTime = obj.createTime[1]; |
| 336 | } | 401 | } |
| 337 | - | 402 | + return obj; |
| 338 | - getPddInfo(obj) | ||
| 339 | - .then((res) => { | ||
| 340 | - if (res.code === "200") { | ||
| 341 | - this.tableData = res.data.value; | ||
| 342 | - this.page.total = res.data.totalItems; | ||
| 343 | - this.tableData.forEach((item, idx) => { | ||
| 344 | - item.index = idx; | ||
| 345 | - }); | ||
| 346 | - } else { | ||
| 347 | - this.alertWarningMsg(res.message); | ||
| 348 | - } | ||
| 349 | - this.loadings.searchLoading = false; | ||
| 350 | - }) | ||
| 351 | - .catch((err) => { | ||
| 352 | - console.log(err); | ||
| 353 | - this.loadings.searchLoading = false; | ||
| 354 | - }); | ||
| 355 | }, | 403 | }, |
| 356 | - | ||
| 357 | //分页 | 404 | //分页 |
| 358 | currentChange(val) { | 405 | currentChange(val) { |
| 359 | this.page.pageIndex = val.page; | 406 | this.page.pageIndex = val.page; |
| ... | @@ -366,6 +413,87 @@ export default { | ... | @@ -366,6 +413,87 @@ export default { |
| 366 | input() { | 413 | input() { |
| 367 | this.$forceUpdate(); | 414 | this.$forceUpdate(); |
| 368 | }, | 415 | }, |
| 416 | + tableSelect(selection, row) { | ||
| 417 | + this.selected = selection.selection; | ||
| 418 | + }, | ||
| 419 | + tableSelectAll(selection) { | ||
| 420 | + this.selected = selection; | ||
| 421 | + }, | ||
| 422 | + // 轮询查询状态 | ||
| 423 | + async pollStatus() { | ||
| 424 | + try { | ||
| 425 | + const result = await getTaskStatus({ taskId: this.currentTaskId }); | ||
| 426 | + if (+result.code === 200) { | ||
| 427 | + // PENDING, PROCESSING, COMPLETED, FAILED | ||
| 428 | + if (result.data.status === "COMPLETED") { | ||
| 429 | + this.stopPolling(); // 停止轮询 | ||
| 430 | + await this.callOtherApi(); // 调用其他接口 | ||
| 431 | + } else if (result.data.status === "FAILED") { | ||
| 432 | + this.stopPolling(); | ||
| 433 | + this.handleFailure(); | ||
| 434 | + this.alertWarningMsg(result.data.errorMessage); | ||
| 435 | + } else { | ||
| 436 | + this.startPolling(); // 启动轮询 | ||
| 437 | + } | ||
| 438 | + } else { | ||
| 439 | + this.stopPolling(); | ||
| 440 | + this.handleFailure(); | ||
| 441 | + } | ||
| 442 | + // 其他状态继续轮询 | ||
| 443 | + } catch (error) { | ||
| 444 | + console.error("轮询查询失败:", error); | ||
| 445 | + this.stopPolling(); | ||
| 446 | + } | ||
| 447 | + }, | ||
| 448 | + // 启动轮询 | ||
| 449 | + startPolling() { | ||
| 450 | + if (this.isPolling) return; | ||
| 451 | + | ||
| 452 | + this.isPolling = true; | ||
| 453 | + this.pollTimer = setInterval(() => { | ||
| 454 | + this.pollStatus(); | ||
| 455 | + }, this.pollInterval); | ||
| 456 | + }, | ||
| 457 | + // 停止轮询 | ||
| 458 | + stopPolling() { | ||
| 459 | + if (this.pollTimer) { | ||
| 460 | + clearInterval(this.pollTimer); | ||
| 461 | + this.pollTimer = null; | ||
| 462 | + } | ||
| 463 | + this.isPolling = false; | ||
| 464 | + this.loadings.searchLoading = false; | ||
| 465 | + }, | ||
| 466 | + // 查询成功后调用的其他接口 | ||
| 467 | + async callOtherApi() { | ||
| 468 | + try { | ||
| 469 | + this.downLoadZip(); | ||
| 470 | + // const fileName = `${formatDateNew(new Date())}.xlsx`; | ||
| 471 | + // this.fileDownload | ||
| 472 | + // .downLoadZip("task", "customDownloadXls", fileName, "xlsx", "get", { | ||
| 473 | + // taskId: this.currentTaskId, | ||
| 474 | + // }) | ||
| 475 | + // .finally(() => { | ||
| 476 | + // // this.cancelDownload(); | ||
| 477 | + // this.loadings.searchLoading = false; | ||
| 478 | + // }); | ||
| 479 | + } catch (error) { | ||
| 480 | + console.error("后续接口调用失败:", error); | ||
| 481 | + } | ||
| 482 | + }, | ||
| 483 | + downLoadZip() { | ||
| 484 | + downloadAsyncExportByTaskId(this.currentTaskId, { | ||
| 485 | + maxRetry: 50, | ||
| 486 | + retryDelay: 5000, | ||
| 487 | + onRetryExhausted: () => { | ||
| 488 | + this.alertWarningMsg("导出失败"); | ||
| 489 | + }, | ||
| 490 | + onWarning: (msg) => { | ||
| 491 | + this.alertWarningMsg(msg); | ||
| 492 | + }, | ||
| 493 | + }).finally(() => { | ||
| 494 | + this.loadings.searchLoading = false; | ||
| 495 | + }); | ||
| 496 | + }, | ||
| 369 | }, | 497 | }, |
| 370 | }; | 498 | }; |
| 371 | </script> | 499 | </script> | ... | ... |
-
Please register or login to post a comment