From 9e0a9d8b32010f9d198cbe1c2712ca5dace3ed7a Mon Sep 17 00:00:00 2001 From: hubin Date: Sun, 5 Jan 2025 18:07:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8A=84=E9=80=81=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=B9=B6=E8=A1=8C=E5=88=86=E6=94=AF=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/aizuda/bpm/engine/QueryService.java | 8 ++ .../com/aizuda/bpm/engine/dao/FlwTaskDao.java | 2 + .../bpm/engine/impl/QueryServiceImpl.java | 5 + .../bpm/engine/impl/TaskServiceImpl.java | 16 ++- .../bpm/mybatisplus/impl/FlwTaskDaoImpl.java | 6 + .../java/test/mysql/TestParallelNode.java | 10 ++ .../test/resources/test/ccTaskParallel.json | 112 ++++++++++++++++++ 7 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 flowlong-spring-boot-starter/src/test/resources/test/ccTaskParallel.json diff --git a/flowlong-core/src/main/java/com/aizuda/bpm/engine/QueryService.java b/flowlong-core/src/main/java/com/aizuda/bpm/engine/QueryService.java index f2ec728..6b81be6 100644 --- a/flowlong-core/src/main/java/com/aizuda/bpm/engine/QueryService.java +++ b/flowlong-core/src/main/java/com/aizuda/bpm/engine/QueryService.java @@ -53,6 +53,14 @@ public interface QueryService { */ boolean existActiveSubProcess(Long instanceId); + /** + * 判断流程实例下是否存在活跃任务 + * + * @param instanceId 流程实例ID + * @return true 存在 false 不存在 + */ + boolean existActiveTask(Long instanceId); + /** * 根据任务ID获取任务对象 * diff --git a/flowlong-core/src/main/java/com/aizuda/bpm/engine/dao/FlwTaskDao.java b/flowlong-core/src/main/java/com/aizuda/bpm/engine/dao/FlwTaskDao.java index 03cb3df..9219095 100644 --- a/flowlong-core/src/main/java/com/aizuda/bpm/engine/dao/FlwTaskDao.java +++ b/flowlong-core/src/main/java/com/aizuda/bpm/engine/dao/FlwTaskDao.java @@ -42,6 +42,8 @@ public interface FlwTaskDao { Long selectCountByParentTaskId(Long parentTaskId); + Long selectCountByInstanceId(Long instanceId); + List selectListByInstanceId(Long instanceId); List selectListByInstanceIdAndTaskName(Long instanceId, String taskName); diff --git a/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/QueryServiceImpl.java b/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/QueryServiceImpl.java index 5b322d8..8e5f981 100644 --- a/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/QueryServiceImpl.java +++ b/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/QueryServiceImpl.java @@ -67,6 +67,11 @@ public class QueryServiceImpl implements QueryService { return instanceDao.selectCountByParentInstanceId(instanceId) > 0; } + @Override + public boolean existActiveTask(Long instanceId) { + return taskDao.selectCountByInstanceId(instanceId) > 0; + } + @Override public FlwHisTask getHistTask(Long taskId) { return hisTaskDao.selectById(taskId); diff --git a/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/TaskServiceImpl.java b/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/TaskServiceImpl.java index f5d667c..9f042a7 100644 --- a/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/TaskServiceImpl.java +++ b/flowlong-core/src/main/java/com/aizuda/bpm/engine/impl/TaskServiceImpl.java @@ -926,8 +926,20 @@ public class TaskServiceImpl implements TaskService { */ Optional nextNodeOptional = nodeModel.nextNode(); if (nextNodeOptional.isPresent()) { - // 执行下一个节点 - nextNodeOptional.get().execute(execution.getEngine().getContext(), execution); + // 下一个节点如果在并行分支,判断是否并行分支都执行结束 + boolean _exec = true; + NodeModel ccNextNode = nextNodeOptional.get(); + NodeModel _cnn = execution.getProcessModel().getNode(ccNextNode.getNodeKey()); + if (_cnn.getParentNode().parallelNode()) { + // 抄送节点独立占据一个分支或者存在执行任务 + if (ccNextNode.getParentNode().parallelNode() || taskDao.selectCountByInstanceId(flwTask.getInstanceId()) > 0) { + _exec = false; + } + } + if (_exec) { + // 执行下一个节点 + ccNextNode.execute(execution.getEngine().getContext(), execution); + } } else { // 不存在任何子节点结束流程 execution.endInstance(nodeModel); diff --git a/flowlong-mybatis-plus/src/main/java/com/aizuda/bpm/mybatisplus/impl/FlwTaskDaoImpl.java b/flowlong-mybatis-plus/src/main/java/com/aizuda/bpm/mybatisplus/impl/FlwTaskDaoImpl.java index 3c9a466..43ea4b9 100644 --- a/flowlong-mybatis-plus/src/main/java/com/aizuda/bpm/mybatisplus/impl/FlwTaskDaoImpl.java +++ b/flowlong-mybatis-plus/src/main/java/com/aizuda/bpm/mybatisplus/impl/FlwTaskDaoImpl.java @@ -65,6 +65,12 @@ public class FlwTaskDaoImpl implements FlwTaskDao { .eq(FlwTask::getParentTaskId, parentTaskId)); } + @Override + public Long selectCountByInstanceId(Long instanceId) { + return taskMapper.selectCount(Wrappers.lambdaQuery() + .eq(FlwTask::getInstanceId, instanceId)); + } + @Override public List selectListByInstanceId(Long instanceId) { return taskMapper.selectList(Wrappers.lambdaQuery() diff --git a/flowlong-spring-boot-starter/src/test/java/test/mysql/TestParallelNode.java b/flowlong-spring-boot-starter/src/test/java/test/mysql/TestParallelNode.java index 433183e..b6b67a6 100644 --- a/flowlong-spring-boot-starter/src/test/java/test/mysql/TestParallelNode.java +++ b/flowlong-spring-boot-starter/src/test/java/test/mysql/TestParallelNode.java @@ -1,6 +1,7 @@ package test.mysql; import com.aizuda.bpm.engine.assist.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -48,4 +49,13 @@ public class TestParallelNode extends MysqlTest { .ifPresent(flwTasks -> Assert.isFalse(flwTasks.isEmpty(), "task size should be zero")); }); } + + + @Test + public void testCcTaskParallel() { + processId = this.deployByResource("test/ccTaskParallel.json", testCreator); + flowLongEngine.startInstanceById(processId, testCreator).flatMap(instance -> + flowLongEngine.queryService().getActiveTasksByInstanceId(instance.getId())) + .ifPresent(t -> Assertions.assertEquals(1, t.size())); + } } diff --git a/flowlong-spring-boot-starter/src/test/resources/test/ccTaskParallel.json b/flowlong-spring-boot-starter/src/test/resources/test/ccTaskParallel.json new file mode 100644 index 0000000..bb9851b --- /dev/null +++ b/flowlong-spring-boot-starter/src/test/resources/test/ccTaskParallel.json @@ -0,0 +1,112 @@ +{ + "id": 11010, + "key": "ccTaskParallel", + "name": "抄送任务并行分支", + "nodeConfig": { + "nodeName": "发起人", + "nodeKey": "flk1736056686549", + "type": 0, + "childNode": { + "nodeName": "并行路由", + "nodeKey": "flk1736056692729", + "type": 8, + "parallelNodes": [ + { + "nodeName": "分支1", + "nodeKey": "flk17360566927291", + "type": 3, + "childNode": { + "nodeName": "抄送人", + "nodeKey": "flk1736056695797", + "type": 2, + "nodeAssigneeList": [ + { + "id": "test001", + "name": "CEO" + } + ], + "allowSelection": true, + "childNode": { + "nodeName": "审核人", + "nodeKey": "flk1736056818736", + "type": 1, + "setType": 1, + "nodeCandidate": { + "type": 1 + }, + "examineLevel": 1, + "examineMode": 1, + "directorLevel": 1, + "directorMode": 0, + "selectMode": 1, + "termAuto": false, + "term": 0, + "termMode": 1, + "typeOfApprove": 1, + "rejectStrategy": 2, + "rejectStart": 1, + "remind": false, + "approveSelf": 0, + "nodeAssigneeList": [ + { + "id": "test002", + "name": "夏小华" + } + ] + } + } + }, + { + "nodeName": "分支2", + "nodeKey": "flk17360566927292", + "type": 3, + "childNode": { + "nodeName": "抄送人", + "nodeKey": "flk1736056697926", + "type": 2, + "nodeAssigneeList": [ + { + "id": "test001", + "name": "CEO" + } + ], + "allowSelection": true + } + } + ], + "childNode": { + "nodeName": "审核人", + "nodeKey": "flk1736056705898", + "type": 1, + "setType": 1, + "nodeCandidate": { + "type": 1 + }, + "examineLevel": 1, + "examineMode": 1, + "directorLevel": 1, + "directorMode": 0, + "selectMode": 1, + "termAuto": false, + "term": 0, + "termMode": 1, + "typeOfApprove": 1, + "rejectStrategy": 2, + "rejectStart": 1, + "remind": false, + "approveSelf": 0, + "childNode": { + "nodeName": "结束", + "nodeKey": "flk17360566865491", + "type": -1 + }, + "nodeAssigneeList": [ + { + "id": "test003", + "name": "陈小辉" + } + ] + } + } + } +} \ No newline at end of file