fix: 提交预检先带受理部门快照;导出列序与原顺序兼容并批量取实例
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
i.approve_time,
|
i.approve_time,
|
||||||
i.archive_time,
|
i.archive_time,
|
||||||
i.archivist_name,
|
i.archivist_name,
|
||||||
i.title,
|
COALESCE(i.title, f.name, co.title) AS title,
|
||||||
f.implement_org,
|
f.implement_org,
|
||||||
f.fee,
|
f.fee,
|
||||||
f.service_content,
|
f.service_content,
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public class ApprovalExportService {
|
|||||||
/** 单次导出上限,超过即要求缩小筛选范围。 */
|
/** 单次导出上限,超过即要求缩小筛选范围。 */
|
||||||
public static final int MAX_EXPORT_ROWS = 5000;
|
public static final int MAX_EXPORT_ROWS = 5000;
|
||||||
|
|
||||||
|
/** 批量取实例的 IN 分块大小。 */
|
||||||
|
private static final int INSTANCE_BATCH = 500;
|
||||||
|
|
||||||
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
/** 一期 16 列顺序保持不变,二期三列追加在末尾(ADR 0004 / 0003)。 */
|
/** 一期 16 列顺序保持不变,二期三列追加在末尾(ADR 0004 / 0003)。 */
|
||||||
@@ -187,14 +190,15 @@ public class ApprovalExportService {
|
|||||||
header.createCell(i).setCellValue(HEADERS[i]);
|
header.createCell(i).setCellValue(HEADERS[i]);
|
||||||
}
|
}
|
||||||
Map<Long, List<ApprovalNode>> nodeCache = new HashMap<>();
|
Map<Long, List<ApprovalNode>> nodeCache = new HashMap<>();
|
||||||
// 批量取实例,避免逐行往返(5000 行导出时 N+1 会拖到分钟级)
|
// 批量取实例(分块 IN),避免逐行往返;5000 行导出时 N+1 会拖到分钟级
|
||||||
Map<Long, ApprovalInstance> instances = new HashMap<>();
|
Map<Long, ApprovalInstance> instances = new HashMap<>();
|
||||||
List<Long> instanceIds = new ArrayList<>();
|
List<Long> instanceIds = new ArrayList<>();
|
||||||
for (ApprovalExportRow row : rows) {
|
for (ApprovalExportRow row : rows) {
|
||||||
instanceIds.add(row.getId());
|
instanceIds.add(row.getId());
|
||||||
}
|
}
|
||||||
if (!instanceIds.isEmpty()) {
|
for (int start = 0; start < instanceIds.size(); start += INSTANCE_BATCH) {
|
||||||
for (ApprovalInstance instance : instanceMapper.selectBatchIds(instanceIds)) {
|
List<Long> chunk = instanceIds.subList(start, Math.min(start + INSTANCE_BATCH, instanceIds.size()));
|
||||||
|
for (ApprovalInstance instance : instanceMapper.selectBatchIds(chunk)) {
|
||||||
instances.put(instance.getId(), instance);
|
instances.put(instance.getId(), instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +216,7 @@ public class ApprovalExportService {
|
|||||||
BigDecimal amountTotal = type == null ? null : amountCache.computeIfAbsent(cacheKey,
|
BigDecimal amountTotal = type == null ? null : amountCache.computeIfAbsent(cacheKey,
|
||||||
k -> documentRegistry.lineAmountTotal(type, instance));
|
k -> documentRegistry.lineAmountTotal(type, instance));
|
||||||
String progress = instance == null ? "" : progressCache.computeIfAbsent(cacheKey,
|
String progress = instance == null ? "" : progressCache.computeIfAbsent(cacheKey,
|
||||||
k -> countersignProgress(instance));
|
k -> countersignProgress(instance, nodeCache));
|
||||||
SXSSFRow dataRow = sheet.createRow(rowNum++);
|
SXSSFRow dataRow = sheet.createRow(rowNum++);
|
||||||
String[] values = toValues(row, nodeCache, lineCount, amountTotal, progress);
|
String[] values = toValues(row, nodeCache, lineCount, amountTotal, progress);
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
@@ -256,9 +260,14 @@ public class ApprovalExportService {
|
|||||||
/**
|
/**
|
||||||
* 会签进度列:仅会签节点有组时填「已签 N/M」,其余为空。
|
* 会签进度列:仅会签节点有组时填「已签 N/M」,其余为空。
|
||||||
*/
|
*/
|
||||||
private String countersignProgress(ApprovalInstance instance) {
|
private String countersignProgress(ApprovalInstance instance,
|
||||||
List<ApprovalNode> nodes = flowService.parseNodes(instance.getDefinitionId());
|
Map<Long, List<ApprovalNode>> nodeCache) {
|
||||||
|
List<ApprovalNode> nodes = nodeCache.computeIfAbsent(instance.getDefinitionId(),
|
||||||
|
flowService::parseNodes);
|
||||||
List<String> parts = new ArrayList<>();
|
List<String> parts = new ArrayList<>();
|
||||||
|
if (nodes.stream().noneMatch(node -> node.getGroups() != null && !node.getGroups().isEmpty())) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
for (ApprovalNode node : nodes) {
|
for (ApprovalNode node : nodes) {
|
||||||
if (node.getGroups() == null || node.getGroups().isEmpty()) {
|
if (node.getGroups() == null || node.getGroups().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -133,6 +133,12 @@ public class ApprovalInstanceService {
|
|||||||
}
|
}
|
||||||
// 协调单的受理部门在提交时快照到实例;外部流程的分管领导按受理部门解析
|
// 协调单的受理部门在提交时快照到实例;外部流程的分管领导按受理部门解析
|
||||||
ApprovalOrganizationVO acceptOrganization = preflightAcceptOrganization(type, instance);
|
ApprovalOrganizationVO acceptOrganization = preflightAcceptOrganization(type, instance);
|
||||||
|
// 预检要在内存里先带上受理部门快照:节点解析器(acceptOrgLeader/acceptOrgDeputy)读的是实例字段,
|
||||||
|
// 而快照在 doSubmit 才落库
|
||||||
|
if (acceptOrganization != null) {
|
||||||
|
instance.setAcceptOrgId(acceptOrganization.getOrganizationId());
|
||||||
|
instance.setAcceptOrgName(acceptOrganization.getOrganizationName());
|
||||||
|
}
|
||||||
// 附件分类与逐节点逐组审批人解析(ADR 0003 / 0005)
|
// 附件分类与逐节点逐组审批人解析(ADR 0003 / 0005)
|
||||||
documentService.preflight(instance, flowService.parseNodes(instance.getDefinitionId()));
|
documentService.preflight(instance, flowService.parseNodes(instance.getDefinitionId()));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user