From 86bedc5f3c9f1796ae693894965f3ce8e04f1ec0 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 28 May 2025 19:54:30 +0800 Subject: [PATCH 1/2] add merge flow --- .../example-app-cmd-domain/pom.xml | 2 +- .../example-app/example-app-cmd-meta/pom.xml | 2 +- example/example-app/example-app-query/pom.xml | 2 +- example/example-app/pom.xml | 2 +- .../example-domain-leave/pom.xml | 2 +- .../example-domain-user/pom.xml | 2 +- example/example-domain/pom.xml | 2 +- .../example-infra/example-infra-flow/pom.xml | 2 +- .../infra/flow/convert/FlowNodeConvertor.java | 2 ++ .../flow/convert/FlowRecordConvertor.java | 2 ++ .../infra/flow/entity/FlowNodeEntity.java | 5 +++ .../infra/flow/entity/FlowRecordEntity.java | 5 +++ .../flow/jpa/FlowRecordEntityRepository.java | 10 +++++- .../repository/FlowRecordRepositoryImpl.java | 5 +++ .../example-infra/example-infra-jpa/pom.xml | 2 +- .../example-infra-security/pom.xml | 2 +- example/example-infra/pom.xml | 2 +- example/example-interface/pom.xml | 2 +- example/example-server/pom.xml | 2 +- example/pom.xml | 2 +- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- springboot-starter-flow/pom.xml | 2 +- .../flow/build/FlowWorkBuilder.java | 34 +++++++++++-------- .../springboot/flow/build/SchemaReader.java | 3 +- .../springboot/flow/domain/FlowNode.java | 11 ++++++ .../springboot/flow/pojo/FlowDetail.java | 9 +++++ .../springboot/flow/record/FlowMerge.java | 14 ++++++++ .../springboot/flow/record/FlowRecord.java | 6 ++++ .../flow/repository/FlowRecordRepository.java | 10 ++++++ .../serializable/FlowNodeSerializable.java | 7 +++- .../flow/service/impl/FlowDetailService.java | 13 ++++++- .../repository/FlowRecordRepositoryImpl.java | 11 ++++++ .../springboot/flow/test/ErrorTest.java | 4 +-- .../springboot/flow/test/FlowTest.java | 2 +- .../springboot/flow/test/ScriptBuildTest.java | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- .../src/main/resources/banner.txt | 2 +- 40 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java diff --git a/example/example-app/example-app-cmd-domain/pom.xml b/example/example-app/example-app-cmd-domain/pom.xml index 5b7a1e74..5e3ccc60 100644 --- a/example/example-app/example-app-cmd-domain/pom.xml +++ b/example/example-app/example-app-cmd-domain/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-app - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-app/example-app-cmd-meta/pom.xml b/example/example-app/example-app-cmd-meta/pom.xml index b2729b1b..12baf9b8 100644 --- a/example/example-app/example-app-cmd-meta/pom.xml +++ b/example/example-app/example-app-cmd-meta/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-app - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-app/example-app-query/pom.xml b/example/example-app/example-app-query/pom.xml index 64072c74..b345ff99 100644 --- a/example/example-app/example-app-query/pom.xml +++ b/example/example-app/example-app-query/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-app - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-app/pom.xml b/example/example-app/pom.xml index 3c0e1e9b..7be2f63b 100644 --- a/example/example-app/pom.xml +++ b/example/example-app/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-example - 3.3.70 + 3.4.0 ../pom.xml pom diff --git a/example/example-domain/example-domain-leave/pom.xml b/example/example-domain/example-domain-leave/pom.xml index 00b62073..66e35998 100644 --- a/example/example-domain/example-domain-leave/pom.xml +++ b/example/example-domain/example-domain-leave/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-domain - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-domain/example-domain-user/pom.xml b/example/example-domain/example-domain-user/pom.xml index 66e2ab94..9f201b24 100644 --- a/example/example-domain/example-domain-user/pom.xml +++ b/example/example-domain/example-domain-user/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-domain - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-domain/pom.xml b/example/example-domain/pom.xml index ed671301..5d5430d8 100644 --- a/example/example-domain/pom.xml +++ b/example/example-domain/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-example - 3.3.70 + 3.4.0 ../pom.xml 4.0.0 diff --git a/example/example-infra/example-infra-flow/pom.xml b/example/example-infra/example-infra-flow/pom.xml index c3dd7a34..59c261c5 100644 --- a/example/example-infra/example-infra-flow/pom.xml +++ b/example/example-infra/example-infra-flow/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot example-infra - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowNodeConvertor.java b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowNodeConvertor.java index 467d49b4..6345c52d 100644 --- a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowNodeConvertor.java +++ b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowNodeConvertor.java @@ -21,6 +21,7 @@ public static FlowNodeEntity convert(FlowNode flowNode, long workId){ entity.setCode(flowNode.getCode()); entity.setName(flowNode.getName()); entity.setEditable(flowNode.isEditable()); + entity.setMergeable(flowNode.isMergeable()); entity.setCreateTime(flowNode.getCreateTime()); entity.setType(flowNode.getType().name()); entity.setTimeout(flowNode.getTimeout()); @@ -52,6 +53,7 @@ public static FlowNode convert(FlowNodeEntity entity){ ApprovalType.parser(entity.getApprovalType()), new OperatorMatcher(entity.getOperatorMatcher()), entity.getEditable(), + entity.getMergeable(), entity.getCreateTime(), entity.getUpdateTime(), entity.getTimeout(), diff --git a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowRecordConvertor.java b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowRecordConvertor.java index acaf6df8..94bc4f78 100644 --- a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowRecordConvertor.java +++ b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/convert/FlowRecordConvertor.java @@ -21,6 +21,7 @@ public static FlowRecordEntity convert(FlowRecord flowRecord) { entity.setWorkId(flowRecord.getWorkId()); entity.setProcessId(flowRecord.getProcessId()); entity.setNodeCode(flowRecord.getNodeCode()); + entity.setMergeable(flowRecord.isMergeable()); entity.setTitle(flowRecord.getTitle()); entity.setCurrentOperatorId(flowRecord.getCurrentOperator().getUserId()); entity.setFlowType(flowRecord.getFlowType().name()); @@ -71,6 +72,7 @@ public static FlowRecord convert(FlowRecordEntity entity, FlowOperatorRepository flowRecord.setWorkId(entity.getWorkId()); flowRecord.setProcessId(entity.getProcessId()); flowRecord.setNodeCode(entity.getNodeCode()); + flowRecord.setMergeable(entity.getMergeable()); flowRecord.setTitle(entity.getTitle()); flowRecord.setCurrentOperator(flowUserRepository.getFlowOperatorById(entity.getCurrentOperatorId())); flowRecord.setFlowType(FlowType.parser(entity.getFlowType())); diff --git a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowNodeEntity.java b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowNodeEntity.java index aba9ca96..5f5471ae 100644 --- a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowNodeEntity.java +++ b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowNodeEntity.java @@ -67,6 +67,11 @@ public class FlowNodeEntity { */ private Boolean editable; + /** + * 是否合并审批 + */ + private Boolean mergeable; + /** * 创建时间 */ diff --git a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowRecordEntity.java b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowRecordEntity.java index 5a1ec6fc..2dba9381 100644 --- a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowRecordEntity.java +++ b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/entity/FlowRecordEntity.java @@ -41,6 +41,11 @@ public class FlowRecordEntity { */ private String nodeCode; + /** + * 是否可合并 + */ + private Boolean mergeable; + /** * 流程标题 */ diff --git a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/jpa/FlowRecordEntityRepository.java b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/jpa/FlowRecordEntityRepository.java index 6d8f95e0..1426dfbf 100644 --- a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/jpa/FlowRecordEntityRepository.java +++ b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/jpa/FlowRecordEntityRepository.java @@ -23,9 +23,17 @@ public interface FlowRecordEntityRepository extends FastRepository findTodoFlowRecordByProcessId(String processId); - @Query(value = "select r from FlowRecordEntity r where r.currentOperatorId = ?1 and r.flowType = 'TODO' and r.flowStatus = 'RUNNING' order by r.id desc") + @Query(value = "select r from FlowRecordEntity r" + + " LEFT JOIN (select min(m.id) as id from FlowRecordEntity m where m.currentOperatorId = ?1 and m.flowType = 'TODO' and m.flowStatus = 'RUNNING' and m.mergeable = true ) debup " + + "on r.id = debup.id" + + " where r.currentOperatorId = ?1 and r.flowType = 'TODO' and r.flowStatus = 'RUNNING'" + + " and (r.mergeable !=true or debup.id is NOT null ) order by r.id desc") Page findTodoByOperatorId(long operatorId, PageRequest pageRequest); + @Query(value = "select r from FlowRecordEntity r where r.currentOperatorId = ?1 and r.workCode = ?2 and r.nodeCode = ?3" + + " and r.mergeable = true and r.flowType = 'TODO' and r.flowStatus = 'RUNNING' order by r.id desc") + List findMergeFlowRecordById(long currentOperatorId,String workCode, String nodeCode); + @Query(value = "select r from FlowRecordEntity r where r.currentOperatorId = ?1 and r.workCode = ?2 and r.flowType = 'TODO' and r.flowStatus = 'RUNNING' order by r.id desc") Page findTodoByOperatorIdAndWorkCode(long operatorId, String workCode, PageRequest pageRequest); diff --git a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/repository/FlowRecordRepositoryImpl.java b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/repository/FlowRecordRepositoryImpl.java index 96636f0b..1c11c340 100644 --- a/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/repository/FlowRecordRepositoryImpl.java +++ b/example/example-infra/example-infra-flow/src/main/java/com/codingapi/example/infra/flow/repository/FlowRecordRepositoryImpl.java @@ -48,6 +48,11 @@ public List findFlowRecordByProcessId(String processId) { return flowRecordEntityRepository.findFlowRecordEntityByProcessId(processId).stream().map(item->FlowRecordConvertor.convert(item,flowOperatorRepository)).toList(); } + @Override + public List findMergeFlowRecordById(String workCode, String nodeCode, long currentOperatorId) { + return flowRecordEntityRepository.findMergeFlowRecordById(currentOperatorId,workCode,nodeCode).stream().map(item->FlowRecordConvertor.convert(item,flowOperatorRepository)).toList(); + } + @Override public List findTodoFlowRecordByProcessId(String processId) { return flowRecordEntityRepository.findTodoFlowRecordByProcessId(processId) diff --git a/example/example-infra/example-infra-jpa/pom.xml b/example/example-infra/example-infra-jpa/pom.xml index 9a172039..c6273fde 100644 --- a/example/example-infra/example-infra-jpa/pom.xml +++ b/example/example-infra/example-infra-jpa/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot example-infra - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-infra/example-infra-security/pom.xml b/example/example-infra/example-infra-security/pom.xml index 1f1b053f..5142b3c7 100644 --- a/example/example-infra/example-infra-security/pom.xml +++ b/example/example-infra/example-infra-security/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-infra - 3.3.70 + 3.4.0 ../pom.xml diff --git a/example/example-infra/pom.xml b/example/example-infra/pom.xml index e233bd64..ef9a4bf3 100644 --- a/example/example-infra/pom.xml +++ b/example/example-infra/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-example - 3.3.70 + 3.4.0 ../pom.xml pom diff --git a/example/example-interface/pom.xml b/example/example-interface/pom.xml index ac1b361e..b83aa3f1 100644 --- a/example/example-interface/pom.xml +++ b/example/example-interface/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-example - 3.3.70 + 3.4.0 example-interface diff --git a/example/example-server/pom.xml b/example/example-server/pom.xml index c4e82dbe..d831841c 100644 --- a/example/example-server/pom.xml +++ b/example/example-server/pom.xml @@ -5,7 +5,7 @@ springboot-example com.codingapi.springboot - 3.3.70 + 3.4.0 4.0.0 diff --git a/example/pom.xml b/example/pom.xml index e400c393..d00d7d7e 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -19,7 +19,7 @@ springboot-example - 3.3.70 + 3.4.0 springboot-example springboot-example project for Spring Boot diff --git a/pom.xml b/pom.xml index e0c63a43..6ea293e3 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 3.3.70 + 3.4.0 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index bc8e2931..303581b8 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-parent - 3.3.70 + 3.4.0 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 656255a6..4f501410 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 3.3.70 + 3.4.0 4.0.0 diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index 5736d59c..ee87eacc 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 3.3.70 + 3.4.0 springboot-starter-flow diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java index b9908f14..e8a07925 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/FlowWorkBuilder.java @@ -73,43 +73,47 @@ public FlowWork build() { public class Nodes { - public Nodes node(String id, String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable, List buttons) { - FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable, buttons); + public Nodes node(String id, String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, TitleGenerator titleGenerator, ErrTrigger errTrigger, boolean editable, boolean mergeable, List buttons) { + FlowNode node = new FlowNode(id, name, code, view, NodeType.parser(code), approvalType, titleGenerator, operatorMatcher, timeout, errTrigger, editable,mergeable, buttons); work.addNode(node); return this; } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable, null); + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable,false, null); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable, List buttons) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable, buttons); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, null); + } + + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, long timeout, boolean editable,boolean mergeable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, timeout, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, buttons); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable, null); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, null); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable, List buttons) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable, buttons); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, boolean editable,boolean mergeable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), null, editable,mergeable, buttons); } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, List buttons) { - return node(name, code, view, approvalType, operatorMatcher, true, buttons); + return node(name, code, view, approvalType, operatorMatcher, true,false, buttons); } public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher) { - return node(name, code, view, approvalType, operatorMatcher, true, null); + return node(name, code, view, approvalType, operatorMatcher, true,false, null); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable, List buttons) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable, buttons); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable,boolean mergeable, List buttons) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable,mergeable, buttons); } - public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable) { - return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable, null); + public Nodes node(String name, String code, String view, ApprovalType approvalType, OperatorMatcher operatorMatcher, ErrTrigger errTrigger, boolean editable,boolean mergeable) { + return node(RandomGenerator.generateUUID(), name, code, view, approvalType, operatorMatcher, 0, TitleGenerator.defaultTitleGenerator(), errTrigger, editable,mergeable, null); } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java index f169b75e..09217db6 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/build/SchemaReader.java @@ -48,6 +48,7 @@ private void loadNodes() { String titleGenerator = properties.getString("titleGenerator"); String name = properties.getString("name"); boolean editable = properties.getBoolean("editable"); + boolean mergeable = properties.getBoolean("mergeable"); String view = properties.getString("view"); String type = properties.getString("type"); String approvalType = properties.getString("approvalType"); @@ -59,7 +60,7 @@ private void loadNodes() { buttons = properties.getJSONArray("buttons").toJavaList(FlowButton.class); } FlowNode flowNode = new FlowNode(id, name, code, view, NodeType.parser(type), ApprovalType.parser(approvalType), new TitleGenerator(titleGenerator), - new OperatorMatcher(operatorMatcher), timeout, StringUtils.hasLength(errTrigger) ? new ErrTrigger(errTrigger) : null, editable, buttons); + new OperatorMatcher(operatorMatcher), timeout, StringUtils.hasLength(errTrigger) ? new ErrTrigger(errTrigger) : null, editable,mergeable, buttons); flowNodes.add(flowNode); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java index fd78d2a3..4dffa302 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowNode.java @@ -77,6 +77,13 @@ public class FlowNode { */ private boolean editable; + /** + * 是否合并记录 + *

+ * 如果为true,则表示该节点可以合并记录 + */ + private boolean mergeable; + /** * 创建时间 */ @@ -147,6 +154,7 @@ public FlowNodeSerializable toSerializable() { this.approvalType, this.operatorMatcher.getScript(), this.editable, + this.mergeable, this.createTime, this.updateTime, this.timeout, @@ -167,6 +175,7 @@ public FlowNode(String id, long timeout, ErrTrigger errTrigger, boolean editable, + boolean mergeable, List buttons) { this.id = id; this.code = code; @@ -181,6 +190,7 @@ public FlowNode(String id, this.errTrigger = errTrigger; this.timeout = timeout; this.editable = editable; + this.mergeable = mergeable; this.buttons = buttons; } @@ -229,6 +239,7 @@ public FlowRecord createRecord(long workId, FlowRecord record = new FlowRecord(); record.setProcessId(processId); record.setNodeCode(this.code); + record.setMergeable(this.mergeable); record.setCreateTime(System.currentTimeMillis()); record.setWorkId(workId); record.setWorkCode(workCode); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java index 5ecaa2d1..91e850c2 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/pojo/FlowDetail.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.domain.Opinion; +import com.codingapi.springboot.flow.record.FlowMerge; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.user.IFlowOperator; import lombok.Getter; @@ -63,8 +64,14 @@ public class FlowDetail { */ private final boolean canHandle; + /** + * 合并记录 + */ + private final List mergeRecords; + public FlowDetail(FlowRecord flowRecord, + List mergeRecords, BindDataSnapshot snapshot, FlowWork flowWork, List historyRecords, @@ -72,6 +79,7 @@ public FlowDetail(FlowRecord flowRecord, boolean canHandle) { this.operators = operators; this.flowRecord = flowRecord; + this.mergeRecords = mergeRecords; this.flowWork = flowWork; this.bindData = snapshot.toBindData(); this.historyRecords = historyRecords; @@ -91,6 +99,7 @@ public FlowDetail(FlowWork flowWork, this.operators = operators; this.flowCreateTime = 0; this.flowRecord = null; + this.mergeRecords = null; this.historyRecords = null; this.bindData = null; this.opinions = null; diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java new file mode 100644 index 00000000..5ef07031 --- /dev/null +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowMerge.java @@ -0,0 +1,14 @@ +package com.codingapi.springboot.flow.record; + +import com.codingapi.springboot.flow.bind.IBindData; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class FlowMerge { + + private final FlowRecord flowRecord; + private final IBindData bindData; + +} diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java index 2f91d341..d8f11670 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/record/FlowRecord.java @@ -49,6 +49,11 @@ public class FlowRecord { */ private String nodeCode; + /** + * 是否可合并 + */ + private boolean mergeable; + /** * 流程标题 */ @@ -401,6 +406,7 @@ public FlowRecord copy() { record.setWorkCode(this.workCode); record.setProcessId(this.processId); record.setNodeCode(this.nodeCode); + record.setMergeable(this.mergeable); record.setTitle(this.title); record.setCurrentOperator(this.currentOperator); record.setFlowType(this.flowType); diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java index 49b23716..192f9f9c 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/repository/FlowRecordRepository.java @@ -49,6 +49,16 @@ public interface FlowRecordRepository { List findFlowRecordByProcessId(String processId); + /** + * 获取合并的流程记录 + * @param workCode 流程编码 + * @param nodeCode 节点编码 + * @param currentOperatorId 当前操作者ID + * @return List of FlowRecord + */ + List findMergeFlowRecordById(String workCode,String nodeCode,long currentOperatorId); + + /** * 查询所有未完成的流程记录 * diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java index d6e80dea..97e7418d 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/serializable/FlowNodeSerializable.java @@ -69,6 +69,11 @@ public class FlowNodeSerializable implements Serializable { */ private boolean editable; + /** + * 是否可合并审批 + */ + private boolean mergeable; + /** * 创建时间 */ @@ -95,6 +100,6 @@ public class FlowNodeSerializable implements Serializable { public FlowNode toFlowNode() { return new FlowNode(id, code, name, new TitleGenerator(titleGenerator), type, view, approvalType, - new OperatorMatcher(operatorMatcher), editable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger),buttons); + new OperatorMatcher(operatorMatcher), editable,mergeable, createTime, updateTime, timeout, errTrigger == null ? null : new ErrTrigger(errTrigger),buttons); } } diff --git a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java index c51f8249..2402b47a 100644 --- a/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java +++ b/springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/impl/FlowDetailService.java @@ -5,6 +5,7 @@ import com.codingapi.springboot.flow.domain.FlowNode; import com.codingapi.springboot.flow.domain.FlowWork; import com.codingapi.springboot.flow.pojo.FlowDetail; +import com.codingapi.springboot.flow.record.FlowMerge; import com.codingapi.springboot.flow.record.FlowRecord; import com.codingapi.springboot.flow.repository.*; import com.codingapi.springboot.flow.service.FlowRecordVerifyService; @@ -45,6 +46,16 @@ public FlowDetail detail(long recordId, IFlowOperator currentOperator) { FlowRecord flowRecord = flowRecordVerifyService.getFlowRecord(); FlowWork flowWork = flowRecordVerifyService.getFlowWork(); + List mergeRecords = null; + if(flowRecord.isTodo() && flowRecord.isMergeable()){ + List flowRecords = flowRecordRepository.findMergeFlowRecordById(flowRecord.getWorkCode(),flowRecord.getNodeCode(),currentOperator.getUserId()); + if(!flowRecords.isEmpty()){ + mergeRecords = flowRecords.stream().map(record->{ + BindDataSnapshot bindDataSnapshot = flowBindDataRepository.getBindDataSnapshotById(record.getSnapshotId()); + return new FlowMerge(record,bindDataSnapshot.toBindData()); + }).toList(); + } + } BindDataSnapshot snapshot = flowBindDataRepository.getBindDataSnapshotById(flowRecord.getSnapshotId()); List flowRecords = @@ -63,7 +74,7 @@ public FlowDetail detail(long recordId, IFlowOperator currentOperator) { } } - return new FlowDetail(flowRecord, snapshot, flowWork, flowRecords, operators, currentOperator != null && flowRecord.isTodo() && flowRecord.isOperator(currentOperator)); + return new FlowDetail(flowRecord,mergeRecords, snapshot, flowWork, flowRecords, operators, currentOperator != null && flowRecord.isTodo() && flowRecord.isOperator(currentOperator)); } diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java index 74038f2b..9c7f66ea 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/repository/FlowRecordRepositoryImpl.java @@ -49,6 +49,17 @@ public List findFlowRecordByProcessId(String processId) { .toList(); } + @Override + public List findMergeFlowRecordById(String workCode, String nodeCode, long operatorId) { + return cache.stream() + .filter(record -> record.isTodo() && record.getCurrentOperator().getUserId() == operatorId + && record.getWorkCode().equals(workCode) + && record.getNodeCode().equals(nodeCode) + && record.isMergeable() + ) + .toList(); + } + @Override public List findTodoFlowRecordByProcessId(String processId) { return cache.stream().filter(record -> record.isTodo() && record.getProcessId().equals(processId)).toList(); diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java index 97010832..d04a3124 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java @@ -53,7 +53,7 @@ void errorMatcherOperatorTest(){ .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createOperatorErrTrigger("+dept.getId()+")}"), true) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createOperatorErrTrigger("+dept.getId()+")}"), true,false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() @@ -145,7 +145,7 @@ void errorMatcherNodeTest(){ .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createNodeErrTrigger('manager')}"), true) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, new OperatorMatcher("def run(content){return []}"), new ErrTrigger("def run(content){return content.createNodeErrTrigger('manager')}"), true,false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java index fb30aa70..b8496b0e 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java @@ -386,7 +386,7 @@ void saveDisableTest() { .title("请假流程") .nodes() .node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) - .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), false) + .node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), false,false) .node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId())) .node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher()) .relations() diff --git a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java index 314524f3..963afde1 100644 --- a/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java +++ b/springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ScriptBuildTest.java @@ -14,7 +14,7 @@ public class ScriptBuildTest { @Test void copy() { User user = new User("张三"); - String script = "{\"nodes\":[{\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"type\":\"start-node\",\"x\":593,\"y\":96,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"type\":\"node-node\",\"x\":620,\"y\":239,\"properties\":{\"name\":\"流程节点\",\"code\":\"flow\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '8899-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":10,\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"custom\",\"errTriggerType\":\"custom\"}},{\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"type\":\"over-node\",\"x\":828,\"y\":582,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"type\":\"circulate-node\",\"x\":839,\"y\":409,\"properties\":{\"name\":\"抄送节点\",\"code\":\"circulate\",\"type\":\"CIRCULATE\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"CIRCULATE\",\"timeout\":0,\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"b68837fb-dca8-41d2-908c-dc079a7f61de\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"targetNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"startPoint\":{\"x\":593,\"y\":118.5},\"endPoint\":{\"x\":620,\"y\":216.5},\"pointsList\":[{\"x\":593,\"y\":118.5},{\"x\":593,\"y\":218.5},{\"x\":620,\"y\":116.5},{\"x\":620,\"y\":216.5}]},{\"id\":\"73e04b95-50f6-44cc-a960-d3007d27fd48\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"targetNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"startPoint\":{\"x\":720,\"y\":239},\"endPoint\":{\"x\":739,\"y\":409},\"pointsList\":[{\"x\":720,\"y\":239},{\"x\":820,\"y\":239},{\"x\":639,\"y\":409},{\"x\":739,\"y\":409}]},{\"id\":\"f6929c79-b168-4c3c-9f8f-9dc21fcaf29d\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"targetNodeId\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"startPoint\":{\"x\":839,\"y\":431.5},\"endPoint\":{\"x\":828,\"y\":559.5},\"pointsList\":[{\"x\":839,\"y\":431.5},{\"x\":839,\"y\":531.5},{\"x\":828,\"y\":459.5},{\"x\":828,\"y\":559.5}]}]}"; + String script = "{\"nodes\":[{\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"type\":\"start-node\",\"x\":593,\"y\":96,\"properties\":{\"name\":\"开始节点\",\"code\":\"start\",\"type\":\"START\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"type\":\"node-node\",\"x\":620,\"y\":239,\"properties\":{\"name\":\"流程节点\",\"code\":\"flow\",\"type\":\"APPROVAL\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '8899-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"SIGN\",\"timeout\":10,\"id\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"custom\",\"errTriggerType\":\"custom\"}},{\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"type\":\"over-node\",\"x\":828,\"y\":582,\"properties\":{\"name\":\"结束节点\",\"code\":\"over\",\"type\":\"OVER\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCurrentOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"UN_SIGN\",\"timeout\":0,\"id\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"width\":200,\"height\":45,\"operatorMatcherType\":\"any\",\"titleGeneratorType\":\"default\",\"errTriggerType\":\"custom\"}},{\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"type\":\"circulate-node\",\"x\":839,\"y\":409,\"properties\":{\"name\":\"抄送节点\",\"code\":\"circulate\",\"type\":\"CIRCULATE\",\"view\":\"default\",\"operatorMatcher\":\"def run(content) {return [content.getCreateOperator().getUserId()];}\",\"editable\":true,\"mergeable\":true,\"titleGenerator\":\"def run(content){ return content.getCurrentOperator().getName() + '-' + content.getFlowWork().getTitle() + '-' + content.getFlowNode().getName();}\",\"errTrigger\":\"\",\"approvalType\":\"CIRCULATE\",\"timeout\":0,\"id\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"width\":200,\"height\":45}}],\"edges\":[{\"id\":\"b68837fb-dca8-41d2-908c-dc079a7f61de\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"b82a84e7-2c1d-4e15-a3c5-6f7f6e263acd\",\"targetNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"startPoint\":{\"x\":593,\"y\":118.5},\"endPoint\":{\"x\":620,\"y\":216.5},\"pointsList\":[{\"x\":593,\"y\":118.5},{\"x\":593,\"y\":218.5},{\"x\":620,\"y\":116.5},{\"x\":620,\"y\":216.5}]},{\"id\":\"73e04b95-50f6-44cc-a960-d3007d27fd48\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":2,\"back\":false},\"sourceNodeId\":\"3c2c420a-003b-4f51-9489-3cdcda0bbe35\",\"targetNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"startPoint\":{\"x\":720,\"y\":239},\"endPoint\":{\"x\":739,\"y\":409},\"pointsList\":[{\"x\":720,\"y\":239},{\"x\":820,\"y\":239},{\"x\":639,\"y\":409},{\"x\":739,\"y\":409}]},{\"id\":\"f6929c79-b168-4c3c-9f8f-9dc21fcaf29d\",\"type\":\"bezier\",\"properties\":{\"outTrigger\":\"def run(content) {return true;}\",\"order\":1,\"back\":false},\"sourceNodeId\":\"2ecdb8aa-00b2-42af-b3ed-c776d2431b38\",\"targetNodeId\":\"b527b4a5-f11f-4052-9848-2c0426da970c\",\"startPoint\":{\"x\":839,\"y\":431.5},\"endPoint\":{\"x\":828,\"y\":559.5},\"pointsList\":[{\"x\":839,\"y\":431.5},{\"x\":839,\"y\":531.5},{\"x\":828,\"y\":459.5},{\"x\":828,\"y\":559.5}]}]}"; FlowWork flowWork = FlowWorkBuilder.builder(user) .title("请假流程") .schema(script) diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 7357d48d..0c800ff6 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 3.3.70 + 3.4.0 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index d8df9f02..c6c90a81 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 3.3.70 + 3.4.0 springboot-starter diff --git a/springboot-starter/src/main/resources/banner.txt b/springboot-starter/src/main/resources/banner.txt index 861f409d..b2bf2e44 100644 --- a/springboot-starter/src/main/resources/banner.txt +++ b/springboot-starter/src/main/resources/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 3.3.70 +CodingApi SpringBoot-Starter 3.4.0 springboot version (${spring-boot.version}) ------------------------------------------------------ From f4dd903de911aaa794686aa1e074973b0f7e5541 Mon Sep 17 00:00:00 2001 From: lorne <1991wangliang@gmail.com> Date: Wed, 28 May 2025 20:35:13 +0800 Subject: [PATCH 2/2] fix sql build --- admin-ui/package.json | 6 +++--- .../example-app/example-app-cmd-domain/pom.xml | 2 +- example/example-app/example-app-cmd-meta/pom.xml | 2 +- example/example-app/example-app-query/pom.xml | 2 +- .../app/query/service/FlowAppQueryService.java | 16 +++++++++++++++- example/example-app/pom.xml | 2 +- .../example-domain/example-domain-leave/pom.xml | 2 +- .../example-domain/example-domain-user/pom.xml | 2 +- example/example-domain/pom.xml | 2 +- example/example-infra/example-infra-flow/pom.xml | 2 +- example/example-infra/example-infra-jpa/pom.xml | 2 +- .../example-infra/example-infra-security/pom.xml | 2 +- example/example-infra/pom.xml | 2 +- example/example-interface/pom.xml | 2 +- example/example-server/pom.xml | 2 +- example/pom.xml | 2 +- mobile-ui/package.json | 6 +++--- pom.xml | 2 +- springboot-starter-data-authorization/pom.xml | 2 +- springboot-starter-data-fast/pom.xml | 2 +- .../springboot/fast/jpa/SQLBuilder.java | 4 ++++ springboot-starter-flow/pom.xml | 2 +- springboot-starter-security/pom.xml | 2 +- springboot-starter/pom.xml | 2 +- springboot-starter/src/main/resources/banner.txt | 2 +- 25 files changed, 46 insertions(+), 28 deletions(-) diff --git a/admin-ui/package.json b/admin-ui/package.json index bd0d2b33..1ae79b1c 100644 --- a/admin-ui/package.json +++ b/admin-ui/package.json @@ -6,9 +6,9 @@ "@ant-design/icons": "^5.4.0", "@ant-design/pro-components": "^2.8.7", "@babel/standalone": "^7.25.6", - "@codingapi/flow-pc": "^0.0.38", - "@codingapi/form-pc": "^0.0.38", - "@codingapi/ui-framework": "^0.0.38", + "@codingapi/flow-pc": "^0.0.39", + "@codingapi/form-pc": "^0.0.39", + "@codingapi/ui-framework": "^0.0.39", "@dnd-kit/core": "^6.2.0", "@dnd-kit/sortable": "^9.0.0", "@handsontable/react-wrapper": "^15.0.0", diff --git a/example/example-app/example-app-cmd-domain/pom.xml b/example/example-app/example-app-cmd-domain/pom.xml index 5e3ccc60..350659f5 100644 --- a/example/example-app/example-app-cmd-domain/pom.xml +++ b/example/example-app/example-app-cmd-domain/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-app - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-app/example-app-cmd-meta/pom.xml b/example/example-app/example-app-cmd-meta/pom.xml index 12baf9b8..98b1dc11 100644 --- a/example/example-app/example-app-cmd-meta/pom.xml +++ b/example/example-app/example-app-cmd-meta/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-app - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-app/example-app-query/pom.xml b/example/example-app/example-app-query/pom.xml index b345ff99..e86c2eae 100644 --- a/example/example-app/example-app-query/pom.xml +++ b/example/example-app/example-app-query/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-app - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-app/example-app-query/src/main/java/com/codingapi/example/app/query/service/FlowAppQueryService.java b/example/example-app/example-app-query/src/main/java/com/codingapi/example/app/query/service/FlowAppQueryService.java index 63a24e88..e4a464ab 100644 --- a/example/example-app/example-app-query/src/main/java/com/codingapi/example/app/query/service/FlowAppQueryService.java +++ b/example/example-app/example-app-query/src/main/java/com/codingapi/example/app/query/service/FlowAppQueryService.java @@ -49,7 +49,21 @@ public Page findAllByOperatorId(SearchRequest searchRequest) { public Page findTodoByOperatorId(SearchRequest searchRequest) { User user = userRepository.getUserByUsername(TokenContext.current().getUsername()); String lastId = searchRequest.getParameter("lastId"); - SQLBuilder sqlBuilder = new SQLBuilder("from FlowRecordEntity r where r.currentOperatorId = ?1 and r.flowType = 'TODO' and r.flowStatus = 'RUNNING' "); + SQLBuilder sqlBuilder = new SQLBuilder( + """ + select r from FlowRecordEntity r + LEFT JOIN (select min(m.id) as id from FlowRecordEntity m where m.currentOperatorId = ?1 and m.flowType = 'TODO' and m.flowStatus = 'RUNNING' and m.mergeable = true ) debup + on r.id = debup.id + where r.currentOperatorId = ?1 and r.flowType = 'TODO' and r.flowStatus = 'RUNNING' + and (r.mergeable !=true or debup.id is NOT null ) + """, + """ + select count(r) from FlowRecordEntity r + LEFT JOIN (select min(m.id) as id from FlowRecordEntity m where m.currentOperatorId = ?1 and m.flowType = 'TODO' and m.flowStatus = 'RUNNING' and m.mergeable = true ) debup + on r.id = debup.id + where r.currentOperatorId = ?1 and r.flowType = 'TODO' and r.flowStatus = 'RUNNING' + and (r.mergeable !=true or debup.id is NOT null ) + """); sqlBuilder.addParam(user.getId()); if(StringUtils.hasText(lastId)){ sqlBuilder.append(" and r.id < ?",Long.parseLong(lastId)); diff --git a/example/example-app/pom.xml b/example/example-app/pom.xml index 7be2f63b..e4fea5bd 100644 --- a/example/example-app/pom.xml +++ b/example/example-app/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-example - 3.4.0 + 3.4.1 ../pom.xml pom diff --git a/example/example-domain/example-domain-leave/pom.xml b/example/example-domain/example-domain-leave/pom.xml index 66e35998..2a973b18 100644 --- a/example/example-domain/example-domain-leave/pom.xml +++ b/example/example-domain/example-domain-leave/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-domain - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-domain/example-domain-user/pom.xml b/example/example-domain/example-domain-user/pom.xml index 9f201b24..b1e5bccd 100644 --- a/example/example-domain/example-domain-user/pom.xml +++ b/example/example-domain/example-domain-user/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-domain - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-domain/pom.xml b/example/example-domain/pom.xml index 5d5430d8..be9f417f 100644 --- a/example/example-domain/pom.xml +++ b/example/example-domain/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-example - 3.4.0 + 3.4.1 ../pom.xml 4.0.0 diff --git a/example/example-infra/example-infra-flow/pom.xml b/example/example-infra/example-infra-flow/pom.xml index 59c261c5..b2475ef6 100644 --- a/example/example-infra/example-infra-flow/pom.xml +++ b/example/example-infra/example-infra-flow/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot example-infra - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-infra/example-infra-jpa/pom.xml b/example/example-infra/example-infra-jpa/pom.xml index c6273fde..7ffd56de 100644 --- a/example/example-infra/example-infra-jpa/pom.xml +++ b/example/example-infra/example-infra-jpa/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot example-infra - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-infra/example-infra-security/pom.xml b/example/example-infra/example-infra-security/pom.xml index 5142b3c7..b02ccce8 100644 --- a/example/example-infra/example-infra-security/pom.xml +++ b/example/example-infra/example-infra-security/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot example-infra - 3.4.0 + 3.4.1 ../pom.xml diff --git a/example/example-infra/pom.xml b/example/example-infra/pom.xml index ef9a4bf3..5729925c 100644 --- a/example/example-infra/pom.xml +++ b/example/example-infra/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-example - 3.4.0 + 3.4.1 ../pom.xml pom diff --git a/example/example-interface/pom.xml b/example/example-interface/pom.xml index b83aa3f1..1bed8aa7 100644 --- a/example/example-interface/pom.xml +++ b/example/example-interface/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-example - 3.4.0 + 3.4.1 example-interface diff --git a/example/example-server/pom.xml b/example/example-server/pom.xml index d831841c..857f7243 100644 --- a/example/example-server/pom.xml +++ b/example/example-server/pom.xml @@ -5,7 +5,7 @@ springboot-example com.codingapi.springboot - 3.4.0 + 3.4.1 4.0.0 diff --git a/example/pom.xml b/example/pom.xml index d00d7d7e..44c38aa8 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -19,7 +19,7 @@ springboot-example - 3.4.0 + 3.4.1 springboot-example springboot-example project for Spring Boot diff --git a/mobile-ui/package.json b/mobile-ui/package.json index d45ebafa..12472531 100644 --- a/mobile-ui/package.json +++ b/mobile-ui/package.json @@ -4,9 +4,9 @@ "private": true, "dependencies": { "@babel/standalone": "^7.25.6", - "@codingapi/flow-mobile": "^0.0.38", - "@codingapi/form-mobile": "^0.0.38", - "@codingapi/ui-framework": "^0.0.38", + "@codingapi/flow-mobile": "^0.0.39", + "@codingapi/form-mobile": "^0.0.39", + "@codingapi/ui-framework": "^0.0.39", "@logicflow/core": "^2.0.10", "@logicflow/extension": "^2.0.14", "@reduxjs/toolkit": "^2.2.7", diff --git a/pom.xml b/pom.xml index 6ea293e3..0a96bf7c 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.codingapi.springboot springboot-parent - 3.4.0 + 3.4.1 https://github.com/codingapi/springboot-framewrok springboot-parent diff --git a/springboot-starter-data-authorization/pom.xml b/springboot-starter-data-authorization/pom.xml index 303581b8..b55a1146 100644 --- a/springboot-starter-data-authorization/pom.xml +++ b/springboot-starter-data-authorization/pom.xml @@ -6,7 +6,7 @@ com.codingapi.springboot springboot-parent - 3.4.0 + 3.4.1 springboot-starter-data-authorization diff --git a/springboot-starter-data-fast/pom.xml b/springboot-starter-data-fast/pom.xml index 4f501410..4b67101b 100644 --- a/springboot-starter-data-fast/pom.xml +++ b/springboot-starter-data-fast/pom.xml @@ -5,7 +5,7 @@ springboot-parent com.codingapi.springboot - 3.4.0 + 3.4.1 4.0.0 diff --git a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java index 020e2802..9a3aebda 100644 --- a/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java +++ b/springboot-starter-data-fast/src/main/java/com/codingapi/springboot/fast/jpa/SQLBuilder.java @@ -19,6 +19,10 @@ public SQLBuilder(String sql) { this(null, sql, "select count(1) from " + sql); } + public SQLBuilder(String sql,String countSql) { + this(null, sql, countSql); + } + public SQLBuilder(Class clazz, String sql) { this(clazz, sql, "select count(1) from " + sql); } diff --git a/springboot-starter-flow/pom.xml b/springboot-starter-flow/pom.xml index ee87eacc..b462d8e1 100644 --- a/springboot-starter-flow/pom.xml +++ b/springboot-starter-flow/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 3.4.0 + 3.4.1 springboot-starter-flow diff --git a/springboot-starter-security/pom.xml b/springboot-starter-security/pom.xml index 0c800ff6..cccd450d 100644 --- a/springboot-starter-security/pom.xml +++ b/springboot-starter-security/pom.xml @@ -6,7 +6,7 @@ springboot-parent com.codingapi.springboot - 3.4.0 + 3.4.1 springboot-starter-security diff --git a/springboot-starter/pom.xml b/springboot-starter/pom.xml index c6c90a81..1ddafc71 100644 --- a/springboot-starter/pom.xml +++ b/springboot-starter/pom.xml @@ -5,7 +5,7 @@ com.codingapi.springboot springboot-parent - 3.4.0 + 3.4.1 springboot-starter diff --git a/springboot-starter/src/main/resources/banner.txt b/springboot-starter/src/main/resources/banner.txt index b2bf2e44..e5b9eb75 100644 --- a/springboot-starter/src/main/resources/banner.txt +++ b/springboot-starter/src/main/resources/banner.txt @@ -1,4 +1,4 @@ ------------------------------------------------------ -CodingApi SpringBoot-Starter 3.4.0 +CodingApi SpringBoot-Starter 3.4.1 springboot version (${spring-boot.version}) ------------------------------------------------------