feat: BFI分页新增按totalCount推导总页数的翻页方法,避免固定页数截断

This commit is contained in:
刘泉佳
2026-10-29 12:53:16 +08:00
parent 4068d24ee9
commit 459d818724
3 changed files with 84 additions and 2 deletions
@@ -777,6 +777,7 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
/**
* A301-1 收款单查询:业务日期窗口全量翻页,窗口天数取 Nacos 配置 thirdParty.bfi.recBillSync.days(默认近 60 天)。
* 按 totalCount 推导总页数,避免窗口放大后受固定页数上限截断。
* 收款流水同步专用。
*/
private List<BfiRecBillVO> queryRecBills() {
@@ -792,7 +793,7 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
queryDTO.setBeginBizdate(beginBizdate);
queryDTO.setEndBizdate(endBizdate);
queryDTO.setPageSize(SYNC_PAGE_SIZE);
List<BfiRecBillVO> recBills = BfiUtil.queryAllPages(pageNo -> {
List<BfiRecBillVO> recBills = BfiUtil.queryAllPagesByTotal(pageNo -> {
queryDTO.setPageNo(pageNo);
return bfiService.queryRecBill(queryDTO);
});
@@ -25,6 +25,7 @@
*/
package org.springblade.thirdparty.bfi.util;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.thirdparty.bfi.pojo.dto.BfiBaseDTO;
@@ -44,6 +45,7 @@ import java.util.function.IntFunction;
*
* @author Chill
*/
@Slf4j
public class BfiUtil {
/**
@@ -56,6 +58,11 @@ public class BfiUtil {
*/
public static final int DEFAULT_MAX_PAGES = 50;
/**
* 按 totalCount 推导总页数时的兜底最大页数,仅防金蝶侧返回异常导致死循环
*/
public static final int DEFAULT_TOTAL_MAX_PAGES = 500;
private BfiUtil() {
}
@@ -139,4 +146,78 @@ public class BfiUtil {
}
return rows;
}
/**
* BFI 分页查询通用翻页:按首页返回的 totalCount 推导总页数,自动翻页汇总全量数据行
* <p>
* 与 {@link #queryAllPages(IntFunction)} 的区别:总页数由 totalCount 决定,固定页数仅作兜底,
* 适合业务日期窗口较长、数据量可能超过固定页数上限的查询场景;达到兜底上限或未取满 totalCount 时打印告警,避免静默截断
*
* @param pageFetcher 页码 -> 分页结果,lambda 内负责设置页码(必要时含页大小)并调用接口
* @param <T> 数据行类型
* @return 全量数据行
*/
public static <T> List<T> queryAllPagesByTotal(IntFunction<BfiPageVO<T>> pageFetcher) {
return queryAllPagesByTotal(pageFetcher, DEFAULT_TOTAL_MAX_PAGES);
}
/**
* BFI 分页查询通用翻页:按首页返回的 totalCount 推导总页数,自动翻页汇总全量数据行
* <p>
* 终止条件:返回页为空、数据行为空、lastPage=true、数据行不满一页(按返回 pageSize 判断)、取满推导出的总页数
* <p>
* totalCount 缺失或非正数时退化为 {@link #queryAllPages(IntFunction, int)} 的固定页数上限逻辑
*
* @param pageFetcher 页码 -> 分页结果,lambda 内负责设置页码(必要时含页大小)并调用接口
* @param maxPages 兜底最大页数,防止金蝶侧 totalCount/lastPage 返回异常时死循环
* @param <T> 数据行类型
* @return 全量数据行
*/
public static <T> List<T> queryAllPagesByTotal(IntFunction<BfiPageVO<T>> pageFetcher, int maxPages) {
List<T> rows = new ArrayList<>();
int totalPages = maxPages;
Integer totalCount = null;
for (int pageNo = 1; pageNo <= totalPages; pageNo++) {
BfiPageVO<T> page = pageFetcher.apply(pageNo);
if (page == null || Func.isEmpty(page.getRows())) {
return rows;
}
rows.addAll(page.getRows());
if (pageNo == 1) {
totalCount = page.getTotalCount();
totalPages = resolveTotalPages(page, maxPages);
}
if (Boolean.TRUE.equals(page.getLastPage())) {
return rows;
}
if (page.getPageSize() != null && page.getRows().size() < page.getPageSize()) {
return rows;
}
}
if (totalCount != null && rows.size() < totalCount) {
log.warn("BFI分页查询未取满,totalCount={},已汇总 {} 条,可能存在数据截断", totalCount, rows.size());
}
return rows;
}
/**
* 按首页 totalCount 与 pageSize 推导总页数,超过兜底上限时按上限截断并告警
*
* @param page 首页分页结果
* @param maxPages 兜底最大页数
* @return 总页数
*/
private static int resolveTotalPages(BfiPageVO<?> page, int maxPages) {
Integer totalCount = page.getTotalCount();
Integer pageSize = page.getPageSize();
if (totalCount == null || totalCount <= 0 || pageSize == null || pageSize <= 0) {
return maxPages;
}
int totalPages = (totalCount + pageSize - 1) / pageSize;
if (totalPages > maxPages) {
log.warn("BFI分页查询需要 {} 页(totalCount={}),超过兜底上限 {} 页,超出部分将被截断", totalPages, totalCount, maxPages);
return maxPages;
}
return totalPages;
}
}
@@ -65,7 +65,7 @@ A301-1 收款单查询(业务日期窗口取 `thirdParty.bfi.recBillSync.days`
### 3.2 收款流水同步:A301-2 → A301-1
`ReceiptFlowServiceImpl#sync()` 重写,`BfiUtil.queryAllPages` + `bfiService.queryRecBill` 全量翻页(pageSize 200),请求参数 `begin_bizdate` / `end_bizdate`(窗口天数取 Nacos `thirdParty.bfi.recBillSync.days`,默认 60)。
`ReceiptFlowServiceImpl#sync()` 重写,`BfiUtil.queryAllPagesByTotal`(按 totalCount 推导总页数,兜底 500 页)+ `bfiService.queryRecBill` 全量翻页(pageSize 200),请求参数 `begin_bizdate` / `end_bizdate`(窗口天数取 Nacos `thirdParty.bfi.recBillSync.days`,默认 60)。
**字段映射(A301-1 → blade_kingdee_receipt_flow)**: