222
This commit is contained in:
parent
90ecbd90cd
commit
1388d39376
@ -209,6 +209,7 @@ public class BanmaOrderController extends BaseController {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private String getTrackingInfo(String trackingNumber) {
|
||||
try {
|
||||
R<Map<String, Object>> sagawaResult = sagawaExpressController.getTrackingInfo(trackingNumber);
|
||||
if (sagawaResult != null && sagawaResult.getCode() == 200) {
|
||||
Map<String, Object> sagawaData = sagawaResult.getData();
|
||||
@ -223,6 +224,8 @@ public class BanmaOrderController extends BaseController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果从佐川获取失败,尝试从斑马API获取
|
||||
try {
|
||||
String url = String.format(TRACKING_URL, trackingNumber);
|
||||
ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
|
||||
@ -235,11 +238,17 @@ public class BanmaOrderController extends BaseController {
|
||||
.map(track -> (String) track.get("track"))
|
||||
.orElse(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("从斑马API获取物流信息失败: {}", e.getMessage());
|
||||
// 继续处理,不中断流程
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("获取物流信息失败: {}", e.getMessage());
|
||||
// 继续处理,不中断流程
|
||||
}
|
||||
|
||||
return null;
|
||||
// 如果所有尝试都失败,返回默认值
|
||||
return "暂无物流信息";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,7 +307,8 @@ public class BanmaOrderController extends BaseController {
|
||||
|
||||
// 计算分页信息
|
||||
int totalPages = (int) Math.ceil((double) totalCount / DEFAULT_PAGE_SIZE);
|
||||
boolean hasMore = orders.size() == DEFAULT_PAGE_SIZE;
|
||||
// 修改hasMore判断逻辑,根据当前页数和总页数判断
|
||||
boolean hasMore = totalCount > 0 && 1 < totalPages;
|
||||
|
||||
// 构建结果
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
@ -340,12 +350,26 @@ public class BanmaOrderController extends BaseController {
|
||||
@ApiParam("开始日期(yyyy-MM-dd)") @RequestParam(required = false) String startDate,
|
||||
@ApiParam("结束日期(yyyy-MM-dd)") @RequestParam(required = false) String endDate) {
|
||||
|
||||
DeferredResult<R<Map<String, Object>>> deferredResult = new DeferredResult<>(120000L);
|
||||
DeferredResult<R<Map<String, Object>>> deferredResult = new DeferredResult<>(999999999L);
|
||||
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
if (deferredResult.isSetOrExpired()) return;
|
||||
|
||||
// 获取总页数信息
|
||||
HttpEntity<String> entity = createHttpEntity();
|
||||
String url = buildApiUrl(1, DEFAULT_PAGE_SIZE, startDate, endDate);
|
||||
ResponseEntity<Map> countResponse = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class);
|
||||
Map<String, Object> countResponseBody = countResponse.getBody();
|
||||
int totalPages = 1;
|
||||
|
||||
if (countResponseBody != null && countResponseBody.containsKey("data")) {
|
||||
Map<String, Object> dataMap = (Map<String, Object>) countResponseBody.get("data");
|
||||
int totalCount = ((Number) dataMap.getOrDefault("total", 0)).intValue();
|
||||
totalPages = (int) Math.ceil((double) totalCount / DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 获取当前页数据
|
||||
R<List<Map<String, Object>>> pageResult = fetchOrdersFromApi(page, DEFAULT_PAGE_SIZE, startDate, endDate);
|
||||
|
||||
if (pageResult.getCode() != 200) {
|
||||
@ -355,10 +379,14 @@ public class BanmaOrderController extends BaseController {
|
||||
|
||||
List<Map<String, Object>> pageData = pageResult.getData();
|
||||
|
||||
// 修改hasMore判断逻辑,根据当前页数和总页数判断
|
||||
boolean hasMore = page < totalPages;
|
||||
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("orders", pageData);
|
||||
resultMap.put("hasMore", pageData != null && pageData.size() == DEFAULT_PAGE_SIZE);
|
||||
resultMap.put("hasMore", hasMore);
|
||||
resultMap.put("nextPage", page + 1);
|
||||
resultMap.put("totalPages", totalPages);
|
||||
|
||||
setDeferredResult(deferredResult, R.ok(resultMap));
|
||||
} catch (Exception e) {
|
||||
@ -369,7 +397,6 @@ public class BanmaOrderController extends BaseController {
|
||||
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
|
||||
return deferredResult;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,160 @@
|
||||
package com.ruoyi.web.controller.tool;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
import us.codecraft.webmagic.Page;
|
||||
import us.codecraft.webmagic.Site;
|
||||
import us.codecraft.webmagic.Spider;
|
||||
import us.codecraft.webmagic.processor.PageProcessor;
|
||||
|
||||
/**
|
||||
* 佐川急便物流查询控制器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api("佐川急便物流查询接口")
|
||||
@RestController
|
||||
@RequestMapping("/tool/sagawa")
|
||||
@Anonymous
|
||||
public class SagawaExpressController extends BaseController implements PageProcessor {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SagawaExpressController.class);
|
||||
|
||||
// 站点配置
|
||||
private final Site site = Site.me()
|
||||
.setRetryTimes(3)
|
||||
.setSleepTime(1000)
|
||||
.setTimeOut(99999999)
|
||||
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
|
||||
|
||||
// 查询结果
|
||||
private Map<String, Object> resultMap = new HashMap<>();
|
||||
@Override
|
||||
public void process(Page page) {
|
||||
try {
|
||||
String pageContent = page.getHtml().toString();
|
||||
|
||||
// 检查是否有包裹数据未登记的信息
|
||||
boolean hasNoData = pageContent.contains("お荷物データが登録されておりません");
|
||||
|
||||
if (hasNoData) {
|
||||
resultMap.put("status", "notFound");
|
||||
resultMap.put("message", "没有找到对应的包裹信息");
|
||||
return;
|
||||
}
|
||||
|
||||
String trackingTableRegex = "<table[^>]*class=\"table_basic table_okurijo_detail2\"[^>]*>\\s*<tbody>\\s*(?:<tr>.*?<th[^>]*>荷物状況</th>.*?</tr>.*?<tr>.*?</tr>.*?)+\\s*</tbody>\\s*</table>";
|
||||
Pattern pattern = Pattern.compile(trackingTableRegex, Pattern.DOTALL);
|
||||
Matcher matcher = pattern.matcher(pageContent);
|
||||
|
||||
if (matcher.find()) {
|
||||
String trackingTable = matcher.group(0);
|
||||
|
||||
// 提取表格中的最后一行
|
||||
String rowRegex = "<tr>\\s*<td>\\s*([^<]*?)\\s*</td>\\s*<td>\\s*([^<]*?)\\s*</td>\\s*<td>\\s*([^<]*?)\\s*</td>\\s*</tr>";
|
||||
Pattern rowPattern = Pattern.compile(rowRegex, Pattern.DOTALL);
|
||||
Matcher rowMatcher = rowPattern.matcher(trackingTable);
|
||||
|
||||
String status = "";
|
||||
String dateTime = "";
|
||||
String office = "";
|
||||
|
||||
// 找到所有匹配项,保留最后一个
|
||||
while (rowMatcher.find()) {
|
||||
status = rowMatcher.group(1).trim();
|
||||
dateTime = rowMatcher.group(2).trim();
|
||||
office = rowMatcher.group(3).trim();
|
||||
}
|
||||
|
||||
if (!status.isEmpty()) {
|
||||
Map<String, String> trackInfo = new HashMap<>();
|
||||
trackInfo.put("status", status);
|
||||
trackInfo.put("dateTime", dateTime);
|
||||
trackInfo.put("office", office);
|
||||
|
||||
resultMap.put("status", "success");
|
||||
resultMap.put("trackInfo", trackInfo);
|
||||
} else {
|
||||
resultMap.put("status", "noRecords");
|
||||
resultMap.put("message", "没有物流记录");
|
||||
}
|
||||
} else {
|
||||
resultMap.put("status", "noTable");
|
||||
resultMap.put("message", "未找到物流跟踪表格");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("解析页面失败", e);
|
||||
resultMap.put("status", "error");
|
||||
resultMap.put("message", "解析页面失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Site getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建佐川急便查询URL
|
||||
*/
|
||||
private String buildSagawaUrl(String trackingNumber) {
|
||||
return "https://k2k.sagawa-exp.co.jp/p/web/okurijosearch.do?okurijoNo=" + trackingNumber.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询佐川急便物流信息
|
||||
*/
|
||||
@ApiOperation("查询佐川急便物流信息")
|
||||
@GetMapping("/tracking/{trackingNumber}")
|
||||
public R<Map<String, Object>> getTrackingInfo(@PathVariable("trackingNumber") String trackingNumber) {
|
||||
try {
|
||||
if (trackingNumber == null || trackingNumber.trim().isEmpty()) {
|
||||
return R.fail("运单号不能为空");
|
||||
}
|
||||
|
||||
resultMap = new HashMap<>();
|
||||
String url = buildSagawaUrl(trackingNumber);
|
||||
|
||||
try {
|
||||
Spider spider = Spider.create(this)
|
||||
.addUrl(url)
|
||||
.thread(1);
|
||||
spider.run();
|
||||
} catch (Exception e) {
|
||||
logger.error("爬取物流信息失败,运单号:" + trackingNumber, e);
|
||||
Map<String, String> defaultTrackInfo = new HashMap<>();
|
||||
defaultTrackInfo.put("status", "处理中");
|
||||
defaultTrackInfo.put("dateTime", "");
|
||||
defaultTrackInfo.put("office", "");
|
||||
|
||||
resultMap.put("status", "success");
|
||||
resultMap.put("trackInfo", defaultTrackInfo);
|
||||
}
|
||||
|
||||
return R.ok(resultMap);
|
||||
} catch (Exception e) {
|
||||
logger.error("查询物流信息失败", e);
|
||||
Map<String, Object> errorResult = new HashMap<>();
|
||||
errorResult.put("status", "error");
|
||||
errorResult.put("message", "查询物流信息失败: " + e.getMessage());
|
||||
return R.ok(errorResult);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,11 +17,13 @@ const service = axios.create({
|
||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL: process.env.VUE_APP_BASE_API,
|
||||
// 超时
|
||||
timeout: 10000
|
||||
timeout: 99999999
|
||||
})
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(config => {
|
||||
config.timeout = 99999999;
|
||||
|
||||
// 是否需要设置 token
|
||||
const isToken = (config.headers || {}).isToken === false
|
||||
// 是否需要防止数据重复提交
|
||||
|
@ -84,8 +84,6 @@
|
||||
<div class="progress-container">
|
||||
<el-progress
|
||||
:percentage="loadProgress.percentage"
|
||||
:format="progressFormat"
|
||||
status="primary"
|
||||
:stroke-width="12"
|
||||
class="load-progress">
|
||||
</el-progress>
|
||||
@ -343,15 +341,23 @@ export default {
|
||||
timeout: 99999999
|
||||
}).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.orderData = [...this.orderData, ...response.data.orders];
|
||||
// 添加当前页数据
|
||||
this.orderData = [...this.orderData, ...(response.data.orders || [])];
|
||||
this.hasMore = response.data.hasMore;
|
||||
this.nextPage = response.data.nextPage;
|
||||
this.currentPage++;
|
||||
this.totalPages = response.data.totalPages || this.totalPages;
|
||||
|
||||
this.updateProgress();
|
||||
this.saveToCache();
|
||||
|
||||
if (this.hasMore) {
|
||||
console.log(`已加载第${this.currentPage}页,共${this.totalPages}页,hasMore=${this.hasMore}`);
|
||||
|
||||
// 如果hasMore为false,但当前页小于总页数,强制继续加载
|
||||
if (!this.hasMore && this.currentPage < this.totalPages) {
|
||||
this.hasMore = true;
|
||||
this.autoLoadNextPage();
|
||||
} else if (this.hasMore) {
|
||||
this.autoLoadNextPage();
|
||||
} else {
|
||||
this.loading = false;
|
||||
@ -362,8 +368,22 @@ export default {
|
||||
this.$message.error(response.msg || "获取更多订单失败");
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
this.nextPage++;
|
||||
this.currentPage++;
|
||||
|
||||
// 更新进度条,即使加载失败也显示进度
|
||||
this.updateProgress();
|
||||
this.saveToCache();
|
||||
|
||||
// 如果还有更多页,继续尝试加载
|
||||
if (this.currentPage < this.totalPages) {
|
||||
this.$message.warning(`加载第${this.currentPage}页失败,尝试继续加载后续页面`);
|
||||
this.autoLoadNextPage();
|
||||
} else {
|
||||
this.loading = false;
|
||||
this.$message.error("获取更多订单失败: " + (error.message || error));
|
||||
}
|
||||
});
|
||||
}, 300);
|
||||
},
|
||||
@ -373,8 +393,10 @@ export default {
|
||||
let percentage;
|
||||
if (this.totalRecords > 0) {
|
||||
percentage = Math.min(Math.round((this.orderData.length / this.totalRecords) * 100), 99);
|
||||
} else {
|
||||
} else if (this.totalPages > 1) {
|
||||
percentage = Math.min(Math.round((this.currentPage / this.totalPages) * 100), 99);
|
||||
} else {
|
||||
percentage = this.currentPage > 0 ? 50 : 10;
|
||||
}
|
||||
|
||||
this.loadProgress = {
|
||||
@ -384,10 +406,7 @@ export default {
|
||||
};
|
||||
},
|
||||
|
||||
/** 进度条格式化 */
|
||||
progressFormat(percentage) {
|
||||
return `已加载 ${this.currentPage}/${this.totalPages} 页,${this.orderData.length}/${this.totalRecords} 条数据`;
|
||||
},
|
||||
|
||||
|
||||
/** 导出Excel */
|
||||
handleExport() {
|
||||
@ -670,7 +689,7 @@ export default {
|
||||
request({
|
||||
url: '/tool/banma/refresh-token',
|
||||
method: 'get',
|
||||
timeout: 60000
|
||||
timeout: 99999999
|
||||
}).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.$message.success("Token刷新成功");
|
||||
|
@ -671,7 +671,7 @@ export default {
|
||||
url: '/tool/webmagic/batch',
|
||||
method: 'post',
|
||||
data: currentBatch,
|
||||
timeout: 9000000
|
||||
timeout: 99999999
|
||||
}).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.productData = [...this.productData, ...response.data];
|
||||
@ -735,7 +735,7 @@ export default {
|
||||
url: '/tool/webmagic/batch',
|
||||
method: 'post',
|
||||
data: failedAsins,
|
||||
timeout: 99999000
|
||||
timeout: 99999999
|
||||
}).then(response => {
|
||||
if (response.code === 200 && response.data) {
|
||||
// 更新失败的ASIN数据
|
||||
|
Loading…
x
Reference in New Issue
Block a user