zhanbo.xu

feat: 开发功能

...@@ -313,3 +313,29 @@ export function getOperationLogByBillNo(data) { ...@@ -313,3 +313,29 @@ export function getOperationLogByBillNo(data) {
313 data: data, 313 data: data,
314 }); 314 });
315 } 315 }
316 +
317 +// 查询导出的任务ID
318 +
319 +// POST
320 +// /exportList/submitExportTask
321 +export function getSubmitExportTask(data) {
322 + return request({
323 + url: "/bus-customer/declareData/submitExportTask",
324 + method: "post",
325 + data: data,
326 + });
327 +}
328 +// /asyncExport/taskStatus/{taskId}
329 +export function getTaskStatus(data) {
330 + return request({
331 + url: "/bus-customer/asyncExport/taskStatus/" + data.taskId,
332 + method: "get",
333 + });
334 +}
335 +// /asyncExport/download/{taskId}
336 +export function getDownload(data) {
337 + return request({
338 + url: "/bus-customer/asyncExport/download/" + data.taskId,
339 + method: "get",
340 + });
341 +}
......
...@@ -51,6 +51,7 @@ router.beforeEach((to, from, next) => { ...@@ -51,6 +51,7 @@ router.beforeEach((to, from, next) => {
51 "RETURN_STATUS", 51 "RETURN_STATUS",
52 "FORWARD_STATUS", 52 "FORWARD_STATUS",
53 "DATA_SOURCE_IMPORT", 53 "DATA_SOURCE_IMPORT",
54 + "DECLARE_TRAFMODE",
54 ]); 55 ]);
55 // 根据roles权限生成可访问的路由表 56 // 根据roles权限生成可访问的路由表
56 router.addRoutes(accessRoutes); // 动态添加可访问路由表 57 router.addRoutes(accessRoutes); // 动态添加可访问路由表
......
...@@ -20,13 +20,13 @@ const user = { ...@@ -20,13 +20,13 @@ const user = {
20 permissions: [], 20 permissions: [],
21 linkList: [], 21 linkList: [],
22 dict: { 22 dict: {
23 - DECLARE_TRAFMODE: [ 23 + // DECLARE_TRAFMODE: [
24 - { 24 + // {
25 - itemCode: "DECLARE_TRAFMODE_AVIATION", 25 + // itemCode: "DECLARE_TRAFMODE_AVIATION",
26 - itemChineseName: "航空运输", 26 + // itemChineseName: "航空运输",
27 - itemValue: "5", 27 + // itemValue: "5",
28 - }, 28 + // },
29 - ], 29 + // ],
30 }, 30 },
31 loading: { 31 loading: {
32 type: false, 32 type: false,
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
244 </el-row> 244 </el-row>
245 <el-row :gutter="5"> 245 <el-row :gutter="5">
246 <!-- 申报状态 --> 246 <!-- 申报状态 -->
247 - <el-col :span="6"> 247 + <el-col :span="3">
248 <Formitem label="主要货物信息" prop="mainGoodsInfo"> 248 <Formitem label="主要货物信息" prop="mainGoodsInfo">
249 <el-input 249 <el-input
250 type="text" 250 type="text"
...@@ -272,9 +272,55 @@ ...@@ -272,9 +272,55 @@
272 ></el-input> 272 ></el-input>
273 </Formitem> 273 </Formitem>
274 </el-col> 274 </el-col>
275 - <!-- 申报日期 --> 275 + <!-- 出口口岸 -->
276 + <el-col :span="3">
277 + <Formitem label="出口口岸" prop="exportPortCode">
278 + <el-input
279 + type="text"
280 + class="inputShadow"
281 + id="inputInner--exportPortCode"
282 + resize="none"
283 + v-model="formData.exportPortCode"
284 + clearable
285 + placeholder=""
286 + ></el-input>
287 + </Formitem>
288 + </el-col>
289 + <!-- 运输方式 -->
290 + <el-col :span="3">
291 + <Formitem label="运输方式" prop="transportMode">
292 + <el-select
293 + type="text"
294 + id="inputInner--transportMode"
295 + v-model="formData.transportMode"
296 + clearable
297 + placeholder=""
298 + >
299 + <el-option
300 + v-for="(item, index) in $store.getters.dict.DECLARE_TRAFMODE"
301 + :key="index"
302 + :label="item.itemChineseName"
303 + :value="item.itemValue"
304 + ></el-option>
305 + </el-select>
306 + </Formitem>
307 + </el-col>
308 + <!-- 运输工具名称 -->
309 + <el-col :span="3">
310 + <Formitem label="运输工具名称" prop="transportVehicleName">
311 + <el-input
312 + type="text"
313 + class="inputShadow"
314 + id="inputInner--transportVehicleName"
315 + resize="none"
316 + v-model="formData.transportVehicleName"
317 + clearable
318 + placeholder=""
319 + ></el-input>
320 + </Formitem>
321 + </el-col>
276 <el-col :span="3"> 322 <el-col :span="3">
277 - <Formitem label="航班号" prop="flightNumber"> 323 + <Formitem label="航班航次号" prop="flightNumber">
278 <el-input 324 <el-input
279 type="text" 325 type="text"
280 class="inputShadow" 326 class="inputShadow"
...@@ -313,6 +359,8 @@ ...@@ -313,6 +359,8 @@
313 ></el-input> 359 ></el-input>
314 </Formitem> 360 </Formitem>
315 </el-col> 361 </el-col>
362 + </el-row>
363 + <el-row :gutter="5">
316 <el-col :span="3"> 364 <el-col :span="3">
317 <Formitem label="监管场所代码" prop="regulatoryVenueCode"> 365 <Formitem label="监管场所代码" prop="regulatoryVenueCode">
318 <el-input 366 <el-input
...@@ -339,8 +387,6 @@ ...@@ -339,8 +387,6 @@
339 ></el-input> 387 ></el-input>
340 </Formitem> 388 </Formitem>
341 </el-col> 389 </el-col>
342 - </el-row>
343 - <el-row :gutter="5">
344 <el-col :span="3"> 390 <el-col :span="3">
345 <Formitem label="运抵国(地区)" prop="destinationCountryRegion"> 391 <Formitem label="运抵国(地区)" prop="destinationCountryRegion">
346 <el-select 392 <el-select
...@@ -445,6 +491,8 @@ ...@@ -445,6 +491,8 @@
445 ></el-input> 491 ></el-input>
446 </Formitem> 492 </Formitem>
447 </el-col> 493 </el-col>
494 + </el-row>
495 + <el-row :gutter="5">
448 <el-col :span="3"> 496 <el-col :span="3">
449 <Formitem label="保费币制" prop="insuredfeeCurrency"> 497 <Formitem label="保费币制" prop="insuredfeeCurrency">
450 <el-select 498 <el-select
...@@ -482,8 +530,6 @@ ...@@ -482,8 +530,6 @@
482 </el-select> 530 </el-select>
483 </Formitem> 531 </Formitem>
484 </el-col> 532 </el-col>
485 - </el-row>
486 - <el-row :gutter="5">
487 <el-col :span="3"> 533 <el-col :span="3">
488 <Formitem label="包装种类代码" prop="packageTypeCode"> 534 <Formitem label="包装种类代码" prop="packageTypeCode">
489 <el-select 535 <el-select
......
...@@ -31,7 +31,11 @@ ...@@ -31,7 +31,11 @@
31 ></el-option> 31 ></el-option>
32 </el-select> 32 </el-select>
33 </Formitem> 33 </Formitem>
34 - <Formitem label="修改内容" prop="modifyContent"> 34 + <Formitem
35 + label="修改内容"
36 + prop="modifyContent"
37 + v-if="batchModifyFormData.modifyData !== 'TRANSPORT_MODE'"
38 + >
35 <el-input 39 <el-input
36 type="text" 40 type="text"
37 class="inputShadow" 41 class="inputShadow"
...@@ -41,6 +45,24 @@ ...@@ -41,6 +45,24 @@
41 placeholder="请输入修改内容" 45 placeholder="请输入修改内容"
42 ></el-input> 46 ></el-input>
43 </Formitem> 47 </Formitem>
48 + <!-- -->
49 + <Formitem label="运输方式" prop="modifyContent" v-else>
50 + <el-select
51 + type="text"
52 + id="inputInner--modifyContent"
53 + v-model="batchModifyFormData.modifyContent"
54 + clearable
55 + placeholder="请选择运输方式"
56 + >
57 + <el-option
58 + v-for="(item, index) in $store.getters.dict.DECLARE_TRAFMODE"
59 + :key="index"
60 + :label="item.itemChineseName"
61 + :value="item.itemValue"
62 + ></el-option>
63 + </el-select>
64 + </Formitem>
65 + <!-- -->
44 </el-form> 66 </el-form>
45 </div> 67 </div>
46 <div class="dialogOption entrySave revokeOperation"> 68 <div class="dialogOption entrySave revokeOperation">
...@@ -81,7 +103,11 @@ export default { ...@@ -81,7 +103,11 @@ export default {
81 { required: true, message: "请选择修改数据", trigger: "change" }, 103 { required: true, message: "请选择修改数据", trigger: "change" },
82 ], 104 ],
83 modifyContent: [ 105 modifyContent: [
84 - { required: true, message: "请输入修改内容", trigger: "blur" }, 106 + {
107 + required: true,
108 + message: "请输入修改内容",
109 + trigger: "blur",
110 + },
85 ], 111 ],
86 }, 112 },
87 modifyDataList: [ 113 modifyDataList: [
...@@ -90,6 +116,7 @@ export default { ...@@ -90,6 +116,7 @@ export default {
90 ], 116 ],
91 }; 117 };
92 }, 118 },
119 +
93 watch: { 120 watch: {
94 showDialog(val) { 121 showDialog(val) {
95 if (val) { 122 if (val) {
...@@ -98,6 +125,16 @@ export default { ...@@ -98,6 +125,16 @@ export default {
98 this.batchModifyFormData.modifyContent = ""; 125 this.batchModifyFormData.modifyContent = "";
99 } 126 }
100 }, 127 },
128 + "batchModifyFormData.modifyData"(newVal, oldVal) {
129 + this.$set(this.batchModifyFormRules, "modifyContent", [
130 + {
131 + required: true,
132 + message:
133 + newVal !== "TRANSPORT_MODE" ? "请输入修改内容" : "请选择运输方式",
134 + trigger: "blur",
135 + },
136 + ]);
137 + },
101 }, 138 },
102 created() { 139 created() {
103 this.getModifyDataList(); 140 this.getModifyDataList();
......
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
252 class="entrySaveButton" 252 class="entrySaveButton"
253 size="small" 253 size="small"
254 icon="el-icon-download" 254 icon="el-icon-download"
255 - v-loading="loadings.exportDeclareLoading" 255 + v-loading="isPolling || loadings.exportDeclareLoading"
256 @click="downloadData" 256 @click="downloadData"
257 > 257 >
258 导出 258 导出
...@@ -453,14 +453,35 @@ ...@@ -453,14 +453,35 @@
453 </el-tooltip> 453 </el-tooltip>
454 </template> 454 </template>
455 </vxe-column> 455 </vxe-column>
456 - <vxe-column field="flightNumber" title="航班号" width="80"></vxe-column> 456 + <vxe-column
457 + field="flightNumber"
458 + title="航班航次号"
459 + width="110"
460 + ></vxe-column>
461 + <vxe-column
462 + field="exportPortCode"
463 + title="出口口岸"
464 + width="110"
465 + ></vxe-column>
466 + <vxe-column
467 + field="transportMode"
468 + title="运输方式"
469 + width="110"
470 + ></vxe-column>
471 + <vxe-column
472 + field="transportVehicleName"
473 + title="运输工具名称"
474 + width="110"
475 + ></vxe-column>
457 <vxe-column 476 <vxe-column
458 field="regulatoryVenueCode" 477 field="regulatoryVenueCode"
459 title="监管场所代码" 478 title="监管场所代码"
479 + width="110"
460 ></vxe-column> 480 ></vxe-column>
461 <vxe-column 481 <vxe-column
462 field="ecomEntName" 482 field="ecomEntName"
463 title="电商企业名称" 483 title="电商企业名称"
484 + width="110"
464 :show-overflow="true" 485 :show-overflow="true"
465 > 486 >
466 <template #default="{ row }"> 487 <template #default="{ row }">
...@@ -479,7 +500,11 @@ ...@@ -479,7 +500,11 @@
479 title="申报业务类型" 500 title="申报业务类型"
480 width="100" 501 width="100"
481 ></vxe-column> 502 ></vxe-column>
482 - <vxe-column field="createTime" title="创建时间"></vxe-column> 503 + <vxe-column
504 + field="createTime"
505 + title="创建时间"
506 + width="150"
507 + ></vxe-column>
483 <vxe-column 508 <vxe-column
484 field="orderReceiptStatus" 509 field="orderReceiptStatus"
485 title="订单回执" 510 title="订单回执"
...@@ -908,7 +933,8 @@ import { ...@@ -908,7 +933,8 @@ import {
908 getLogisticsReceipt, 933 getLogisticsReceipt,
909 getDeclarationLog, 934 getDeclarationLog,
910 arrivalInReceipt, 935 arrivalInReceipt,
911 - exportDeclareData, 936 + getSubmitExportTask,
937 + getTaskStatus,
912 } from "@/api/declareData-api.js"; 938 } from "@/api/declareData-api.js";
913 import DialogVue from "./dialog.vue"; 939 import DialogVue from "./dialog.vue";
914 import RevokeDialog from "./revokeDialog.vue"; 940 import RevokeDialog from "./revokeDialog.vue";
...@@ -1031,6 +1057,12 @@ export default { ...@@ -1031,6 +1057,12 @@ export default {
1031 declareId: "", 1057 declareId: "",
1032 data: {}, 1058 data: {},
1033 }, 1059 },
1060 + //
1061 + pollTimer: null, // 定时器实例
1062 + pollInterval: 5000, // 轮询间隔(5秒)
1063 + isPolling: false, // 轮询状态标识
1064 + currentTaskId: null,
1065 + pollCount: 0,
1034 }; 1066 };
1035 }, 1067 },
1036 beforeCreate() {}, 1068 beforeCreate() {},
...@@ -1060,6 +1092,8 @@ export default { ...@@ -1060,6 +1092,8 @@ export default {
1060 watch: { 1092 watch: {
1061 $route(val, oldval) { 1093 $route(val, oldval) {
1062 this.popoverClose(); 1094 this.popoverClose();
1095 + this.popoverClose();
1096 + this.stopPolling(); // 组件销毁前清理定时器
1063 }, 1097 },
1064 }, 1098 },
1065 beforeRouteEnter(to, from, next) { 1099 beforeRouteEnter(to, from, next) {
...@@ -1284,6 +1318,121 @@ export default { ...@@ -1284,6 +1318,121 @@ export default {
1284 console.log(err); 1318 console.log(err);
1285 }); 1319 });
1286 }, 1320 },
1321 + callOtherApi(retryCount = 0) {
1322 + const baseUrl = process.env.VUE_APP_BASE_API;
1323 + console.log(this.currentTaskId);
1324 + axios({
1325 + method: "get",
1326 + url: `${baseUrl}/bus-customer/asyncExport/download/${this.currentTaskId}`,
1327 + responseType: "blob",
1328 + headers: {
1329 + Authorization: "Bearer " + getToken(),
1330 + Ver: process.env.VUE_APP_APIVERSION,
1331 + },
1332 + })
1333 + .then((res) => {
1334 + debugger;
1335 + console.log(res);
1336 + const mimeType =
1337 + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
1338 +
1339 + const aLink = document.createElement("a");
1340 + var blob = new Blob([res.data], { type: mimeType });
1341 + if (blob.size < 500) {
1342 + var reader = new FileReader();
1343 + reader.readAsText(blob, "utf-8");
1344 + reader.onloadend = () => {
1345 + // 获取文本内容并将其转换为JSON格式
1346 + if (
1347 + reader.result &&
1348 + reader.result != null &&
1349 + reader.result != ""
1350 + ) {
1351 + if (JSON.parse(reader.result)) {
1352 + debugger;
1353 + let jsonData = JSON.parse(reader.result);
1354 + if (jsonData.code == "10103") {
1355 + // 检查重试次数
1356 + if (retryCount < 50) {
1357 + // 延迟后重试
1358 + setTimeout(() => {
1359 + this.callOtherApi(retryCount + 1);
1360 + }, 5000); // 5秒后重试
1361 + } else {
1362 + this.alertWarningMsg("导出失败");
1363 + this.loadings.exportDeclareLoading = false;
1364 + }
1365 +
1366 + return;
1367 + }
1368 + this.alertWarningMsg(jsonData.message);
1369 + } else {
1370 + this.alertWarningMsg("文件无法下载,请重新生成后再试!");
1371 + }
1372 + } else {
1373 + this.alertWarningMsg("文件无法下载,请重新生成后再试!");
1374 + }
1375 + };
1376 + } else {
1377 + const fileName = `${formatDateNew(new Date())}.xlsx`;
1378 + aLink.href = URL.createObjectURL(blob);
1379 + aLink.setAttribute("download", fileName); // 设置下载文件名称
1380 + document.body.appendChild(aLink);
1381 + aLink.click();
1382 + document.body.removeChild(aLink);
1383 + this.loadings.exportDeclareLoading = false;
1384 + }
1385 + })
1386 + .catch((error) => {
1387 + console.log("失败", error);
1388 + this.loadings.exportDeclareLoading = false;
1389 + });
1390 + },
1391 + // 轮询查询状态
1392 + async pollStatus() {
1393 + try {
1394 + const result = await getTaskStatus({ taskId: this.currentTaskId });
1395 + if (+result.code === 200) {
1396 + // PENDING, PROCESSING, COMPLETED, FAILED
1397 + if (result.data.status === "COMPLETED") {
1398 + this.stopPolling(); // 停止轮询
1399 + await this.callOtherApi(); // 调用其他接口
1400 + } else if (result.data.status === "FAILED") {
1401 + this.stopPolling();
1402 + // this.handleFailure();
1403 + this.alertWarningMsg(result.data.errorMessage);
1404 + } else {
1405 + this.startPolling(); // 启动轮询
1406 + }
1407 + } else {
1408 + this.stopPolling();
1409 + // this.handleFailure();
1410 + }
1411 + // 其他状态继续轮询
1412 + } catch (error) {
1413 + console.error("轮询查询失败:", error);
1414 + this.stopPolling();
1415 + }
1416 + },
1417 +
1418 + // 启动轮询
1419 + startPolling() {
1420 + if (this.isPolling) return;
1421 +
1422 + this.isPolling = true;
1423 + this.pollTimer = setInterval(() => {
1424 + this.pollStatus();
1425 + }, this.pollInterval);
1426 + },
1427 + // 停止轮询
1428 + stopPolling() {
1429 + if (this.pollTimer) {
1430 + clearInterval(this.pollTimer);
1431 + this.pollTimer = null;
1432 + }
1433 + this.isPolling = false;
1434 + this.loadings.exportDeclareLoading = false;
1435 + },
1287 1436
1288 datasDownload(dataSource) { 1437 datasDownload(dataSource) {
1289 let obj = { 1438 let obj = {
...@@ -1300,24 +1449,46 @@ export default { ...@@ -1300,24 +1449,46 @@ export default {
1300 obj.endCreateTime = obj.createTime[1]; 1449 obj.endCreateTime = obj.createTime[1];
1301 } 1450 }
1302 obj.declareId = this.selected.map((item) => item.declareId); 1451 obj.declareId = this.selected.map((item) => item.declareId);
1303 - exportDeclareData(obj) 1452 + const _that = this;
1453 +
1454 + _that
1455 + .$confirm(`正在导出中,请稍候!`, "提示", {
1456 + confirmButtonText: "确定",
1457 + cancelButtonText: "取消",
1458 + type: "warning",
1459 + })
1460 + .then(() => {
1461 + getSubmitExportTask(obj)
1304 .then((res) => { 1462 .then((res) => {
1305 - // if (res.code === "200") { 1463 + if (+res.code === 200) {
1306 - // // this.alertSuccessMsg(res.message); 1464 + console.log(res);
1307 - // } else { 1465 + _that.currentTaskId = res.data;
1308 - // console.log(res.message); 1466 + _that.datasExportVisible = false;
1309 - // this.alertWarningMsg(res.message); 1467 + _that.$refs.exportDialog.datasExportVisible = false;
1310 - // } 1468 + _that.startPolling();
1469 + }
1311 }) 1470 })
1312 .catch((err) => { 1471 .catch((err) => {
1313 console.log(err); 1472 console.log(err);
1314 - this.alertErrorMsg(err); 1473 + });
1315 }) 1474 })
1316 - .finally((res) => { 1475 + .catch(() => {
1317 - this.loadings.exportDeclareLoading = false; 1476 + _that.loadings.exportDeclareLoading = false;
1318 - this.datasExportVisible = false; 1477 + _that.datasExportVisible = false;
1319 - this.$refs.exportDialog.datasExportVisible = false; 1478 + _that.$refs.exportDialog.datasExportVisible = false;
1320 }); 1479 });
1480 +
1481 + // exportDeclareData(obj)
1482 + // .then((res) => {})
1483 + // .catch((err) => {
1484 + // console.log(err);
1485 + // this.alertErrorMsg(err);
1486 + // })
1487 + // .finally((res) => {
1488 + // this.loadings.exportDeclareLoading = false;
1489 + // this.datasExportVisible = false;
1490 + // this.$refs.exportDialog.datasExportVisible = false;
1491 + // });
1321 }, 1492 },
1322 //导出 1493 //导出
1323 downloadData() { 1494 downloadData() {
......