jinhui.wang

pdd数据查询增加导出功能,编辑详情返回关闭当前tag

...@@ -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.$router.go(-1); 1107 + this.$store.dispatch("tagsView/delView", this.$route).finally(() => {
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>
......