Skip to content
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
package com.codingapi.flow.action;

import com.codingapi.flow.node.IAuditNode;
import com.codingapi.flow.node.manager.OperatorManager;
import com.codingapi.flow.node.manager.StrategyManager;
import com.codingapi.flow.operator.IFlowOperator;
import com.codingapi.flow.node.IFlowNode;
import com.codingapi.flow.record.FlowRecord;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.flow.strategy.MultiOperatorAuditStrategy;
import com.codingapi.flow.utils.RandomUtils;
import lombok.Getter;
import lombok.SneakyThrows;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

@Getter
public abstract class BaseAction implements IFlowAction {
Expand Down Expand Up @@ -72,14 +67,10 @@ public Map<String, Object> toMap() {
}

@Override
public List<FlowRecord> trigger(FlowSession flowSession, FlowRecord currentRecord) {
return null;
public List<FlowRecord> generateRecords(FlowSession flowSession) {
return List.of();
}

@Override
public boolean isDone(FlowSession session, FlowRecord currentRecord, List<FlowRecord> currentRecords) {
return true;
}

@SneakyThrows
@SuppressWarnings("unchecked")
Expand All @@ -96,47 +87,25 @@ protected static <T extends BaseAction> T fromMap(Map<String, Object> data, Clas
}


@Override
public void run(FlowSession flowSession) {}

/**
* 生成下一节点的记录
*
* @param currentNode 当前节点
* @param triggerSession 触发会话
* @param currentRecord 当前记录
* @return 下一节节点的记录
* 触发并执行后续节点
* @param flowSession 当前会话
* @param consumer 节点处理
*/
protected List<FlowRecord> generateNextRecords(IAuditNode currentNode, FlowSession triggerSession, FlowRecord currentRecord) {
List<FlowRecord> records = new ArrayList<>();
OperatorManager operatorManager = currentNode.operators(triggerSession);
List<IFlowOperator> operators = operatorManager.getOperators();
for (int order = 0; order < operators.size(); order++) {
IFlowOperator operator = operators.get(order);
FlowRecord flowRecord = new FlowRecord(triggerSession.updateSession(operator), this.id, currentRecord.getProcessId(), currentRecord.getId(), order);
records.add(flowRecord);
}
if (operators.size() > 1) {
StrategyManager strategyManager = currentNode.strategies();
MultiOperatorAuditStrategy.Type multiOperatorAuditStrategyType = strategyManager.getMultiOperatorAuditStrategyType();
// 如果是顺序审批,则隐藏掉后续的人员的审批记录
if (multiOperatorAuditStrategyType == MultiOperatorAuditStrategy.Type.SEQUENCE) {
for (int i = 1; i < records.size(); i++) {
FlowRecord record = records.get(i);
record.hidden();
}
}
// 如果是随机审批,则隐藏掉后续的人员的审批记录
if (multiOperatorAuditStrategyType == MultiOperatorAuditStrategy.Type.RANDOM_ONE) {
int index = RandomUtils.randomInt(operators.size());

List<FlowRecord> newRecords = new ArrayList<>();
for (FlowRecord record : records) {
if (record.getNodeOrder() == index) {
record.resetNodeOrder(0);
newRecords.add(record);
}
public void triggerNode(FlowSession flowSession, Consumer<FlowSession> consumer) {
List<IFlowNode> nextNodes = flowSession.matchNextNodes();
for (IFlowNode node : nextNodes) {
FlowSession triggerSession = flowSession.updateSession(node);
if (node.continueTrigger(triggerSession)) {
this.triggerNode(triggerSession,consumer);
}else {
if (consumer != null) {
consumer.accept(triggerSession);
}
return newRecords;
}
}
return records;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.codingapi.flow.action;


import com.codingapi.flow.node.IFlowNode;
import com.codingapi.flow.record.FlowRecord;
import com.codingapi.flow.session.FlowSession;

Expand Down Expand Up @@ -36,20 +35,20 @@ public interface IFlowAction {
/**
* 执行动作
*/
List<FlowRecord> trigger(FlowSession flowSession, FlowRecord currentRecord);
List<FlowRecord> generateRecords(FlowSession flowSession);

/**
* 转换为map
*/
Map<String, Object> toMap();


/**
* 流程是否结束
*
* @param session session
* @param currentRecord 当前审批记录
* @param currentRecords 当前节点所有人提交的记录
* @return 是否结束
* 执行动作
* 业务流程的处理入口时通过run函数触发开启的流程
* @param flowSession 会话
*/
boolean isDone(FlowSession session, FlowRecord currentRecord, List<FlowRecord> currentRecords);
void run(FlowSession flowSession);


}
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.codingapi.flow.action;

import com.codingapi.flow.node.IAuditNode;
import com.codingapi.flow.context.RepositoryContext;
import com.codingapi.flow.event.FlowRecordDoneEvent;
import com.codingapi.flow.event.FlowRecordTodoEvent;
import com.codingapi.flow.event.IFlowEvent;
import com.codingapi.flow.node.BaseAuditNode;
import com.codingapi.flow.node.IFlowNode;
import com.codingapi.flow.node.manager.StrategyManager;
import com.codingapi.flow.record.FlowRecord;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.flow.strategy.MultiOperatorAuditStrategy;
import com.codingapi.flow.utils.RandomUtils;
import com.codingapi.springboot.framework.event.EventPusher;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
* 通过
* 通过
*/
public class PassAction extends BaseAction {

Expand All @@ -29,58 +33,60 @@ public static PassAction fromMap(Map<String, Object> data) {
return BaseAction.fromMap(data, PassAction.class);
}

@Override
public boolean isDone(FlowSession session, FlowRecord currentRecord, List<FlowRecord> currentRecords) {
// 多人审批
if (currentRecords.size() > 1) {
StrategyManager strategyManager = session.getCurrentNode().strategies();
MultiOperatorAuditStrategy.Type multiOperatorAuditStrategyType = strategyManager.getMultiOperatorAuditStrategyType();
// 顺序审批
if (multiOperatorAuditStrategyType == MultiOperatorAuditStrategy.Type.SEQUENCE) {
int currentOrder = currentRecord.getNodeOrder();
int maxNodeOrder = currentRecords.size() - 1;
return currentOrder >= maxNodeOrder;
}
// 或签
if (multiOperatorAuditStrategyType == MultiOperatorAuditStrategy.Type.ANY) {
return true;
}
// 并签
if (multiOperatorAuditStrategyType == MultiOperatorAuditStrategy.Type.MERGE) {
float percent = strategyManager.getMultiOperatorAuditMergePercent();
long total = currentRecords.size();
// 尚未办理的数量为所有待办数-1,1是当前办理的这条记录
long todoCount = currentRecords.stream().filter(FlowRecord::isTodo).count() - 1;
long doneCount = total - todoCount;
return doneCount >= total * percent;
}
}
return true;
}

@Override
public List<FlowRecord> trigger(FlowSession flowSession, FlowRecord currentRecord) {
public List<FlowRecord> generateRecords(FlowSession flowSession) {
FlowRecord currentRecord = flowSession.getCurrentRecord();
List<FlowRecord> records = new ArrayList<>();
if (currentRecord.isReturnRecord()) {
// 退回后的流程重新提交
IAuditNode currentNode = flowSession.getWorkflow().getAuditNode(currentRecord.getReturnNodeId());
BaseAuditNode currentNode = (BaseAuditNode) flowSession.getWorkflow().getFlowNode(currentRecord.getReturnNodeId());
StrategyManager strategyManager = currentNode.strategies();
// 是否退回到退回节点
if (strategyManager.isResume()) {
FlowSession triggerSession = flowSession.updateSession(currentNode);
List<FlowRecord> nextRecords = this.generateNextRecords(currentNode, triggerSession.updateSession(currentNode), currentRecord);
List<FlowRecord> nextRecords = currentNode.generateCurrentRecords(triggerSession.updateSession(currentNode));
records.addAll(nextRecords);
}
} else {
List<IAuditNode> nextNodes = flowSession.nextNodes();
for (IAuditNode node : nextNodes) {
//TODO 如果是条件节点,则自动完成当前记录,并构建下一个记录
List<FlowRecord> nextRecords = this.generateNextRecords(node, flowSession.updateSession(node), currentRecord);
IFlowNode currentNode = flowSession.getCurrentNode();
List<FlowRecord> nextRecords = currentNode.generateCurrentRecords(flowSession);
if (!nextRecords.isEmpty()) {
records.addAll(nextRecords);
}
}
return records;
}


@Override
public void run(FlowSession flowSession) {
List<IFlowEvent> flowEvents = new ArrayList<>();
List<FlowRecord> recordList = new ArrayList<>();
FlowRecord flowRecord = flowSession.getCurrentRecord();
IFlowNode currentNode = flowSession.getCurrentNode();
boolean done = currentNode.isDone(flowSession);
flowRecord.update(flowSession.getFormData().toMapData(), flowSession.getAdvice().getAdvice(), flowSession.getAdvice().getSignKey(), done);
// 添加流程结束事件
flowEvents.add(new FlowRecordDoneEvent(flowRecord));
recordList.add(flowRecord);

if (done) {
this.triggerNode(flowSession,(triggerSession)->{
List<FlowRecord> records = this.generateRecords(triggerSession);
if (!records.isEmpty()) {
for (FlowRecord record : records) {
if (record.isShow()) {
flowEvents.add(new FlowRecordTodoEvent(record));
}
}
recordList.addAll(records);
}
});
}

RepositoryContext.getInstance().saveRecords(recordList);

flowEvents.forEach(EventPusher::push);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.codingapi.flow.action;

import com.codingapi.flow.node.IAuditNode;
import com.codingapi.flow.context.RepositoryContext;
import com.codingapi.flow.event.FlowRecordTodoEvent;
import com.codingapi.flow.event.IFlowEvent;
import com.codingapi.flow.node.IFlowNode;
import com.codingapi.flow.record.FlowRecord;
import com.codingapi.flow.script.action.RejectActionScript;
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.flow.utils.RandomUtils;
import com.codingapi.springboot.framework.event.EventPusher;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

Expand All @@ -26,7 +29,7 @@ public RejectAction() {
this.title = "拒绝";
this.type = ActionType.REJECT;
this.display = new ActionDisplay(this.title);
this.script = RejectActionScript.defaultScript();
this.script = RejectActionScript.startScript();
}

public void setScript(String script) {
Expand All @@ -48,32 +51,45 @@ public static RejectAction fromMap(Map<String, Object> data) {
}

@Override
public List<FlowRecord> trigger(FlowSession flowSession, FlowRecord currentRecord) {
public List<FlowRecord> generateRecords(FlowSession flowSession) {
RejectActionScript.RejectResult rejectResult = script.execute(flowSession);
IAuditNode currentNode = null;
IFlowNode currentNode = null;
// 返回指定节点
if (rejectResult.isReturnNode()) {
String nodeId = rejectResult.getNodeId();
currentNode = flowSession.getWorkflow().getAuditNode(nodeId);
currentNode = flowSession.getWorkflow().getFlowNode(nodeId);
}
// 流程结束(非正常)
if (rejectResult.isTerminate()) {
currentNode = flowSession.getWorkflow().getEndNode();
}
// 退回上级节点
if (rejectResult.isReturnPrev()) {
long fromId = currentRecord.getFromId();
FlowRecord preRecord = FlowScriptContext.getInstance().getRecordById(fromId);
if (preRecord == null) {
throw new IllegalArgumentException("preRecord is null");
}
currentNode = flowSession.getWorkflow().getAuditNode(preRecord.getNodeId());
}
if (currentNode == null) {
throw new IllegalArgumentException("currentNode is null");
}
flowSession = flowSession.updateSession(currentNode);
return currentNode.generateCurrentRecords(flowSession);
}

@Override
public void run(FlowSession flowSession) {
List<IFlowEvent> flowEvents = new ArrayList<>();
List<FlowRecord> recordList = new ArrayList<>();

FlowRecord flowRecord = flowSession.getCurrentRecord();
flowRecord.update(flowSession.getFormData().toMapData(), flowSession.getAdvice().getAdvice(), flowSession.getAdvice().getSignKey(), true);
recordList.add(flowRecord);

List<FlowRecord> records = this.generateRecords(flowSession);
if(!records.isEmpty()) {
recordList.addAll(records);
for (FlowRecord record : records) {
if (record.isShow()) {
flowEvents.add(new FlowRecordTodoEvent(record));
}
}
}
RepositoryContext.getInstance().saveRecords(recordList);
flowEvents.forEach(EventPusher::push);

FlowSession triggerSession = flowSession.updateSession(currentNode);
return this.generateNextRecords(currentNode, triggerSession, currentRecord);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.codingapi.flow.action;

import com.codingapi.flow.record.FlowRecord;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.flow.utils.RandomUtils;

import java.util.List;
import java.util.Map;

/**
Expand All @@ -24,9 +21,4 @@ public static SaveAction fromMap(Map<String, Object> data) {
}


@Override
public boolean isDone(FlowSession session, FlowRecord currentRecord, List<FlowRecord> currentRecords) {
// 保存按钮,不创建后续流程
return false;
}
}
Loading