|
@@ -0,0 +1,225 @@
|
|
|
+package com.fjhx.flow.service.flow.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
+import com.fjhx.flow.core.FlowBean;
|
|
|
+import com.fjhx.flow.core.FlowDelegate;
|
|
|
+import com.fjhx.flow.entity.flow.dto.InitiateDto;
|
|
|
+import com.fjhx.flow.entity.flow.po.FlowDefinition;
|
|
|
+import com.fjhx.flow.entity.flow.po.FlowDefinitionNode;
|
|
|
+import com.fjhx.flow.entity.flow.po.FlowExample;
|
|
|
+import com.fjhx.flow.entity.flow.po.FlowExampleDetail;
|
|
|
+import com.fjhx.flow.enums.FlowStatus;
|
|
|
+import com.fjhx.flow.enums.HandleType;
|
|
|
+import com.fjhx.flow.enums.NodeTypeEnum;
|
|
|
+import com.fjhx.flow.service.flow.*;
|
|
|
+import com.googlecode.aviator.AviatorEvaluator;
|
|
|
+import com.googlecode.aviator.Expression;
|
|
|
+import com.ruoyi.common.constant.DatasourceConstant;
|
|
|
+import com.ruoyi.common.constant.StatusConstant;
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.PlatformTransactionManager;
|
|
|
+import org.springframework.transaction.TransactionDefinition;
|
|
|
+import org.springframework.transaction.TransactionStatus;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class FlowProcessServiceImpl implements FlowProcessService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FlowDefinitionService flowDefinitionService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FlowDefinitionNodeService flowDefinitionNodeService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FlowExampleService flowExampleService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FlowExampleDetailService flowExampleDetailService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PlatformTransactionManager platformTransactionManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TransactionDefinition transactionDefinition;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void initiate(InitiateDto dto) {
|
|
|
+
|
|
|
+
|
|
|
+ Class<? extends FlowDelegate> flowDelegateCls = FlowBean.getBean(dto.getFlowKey());
|
|
|
+
|
|
|
+
|
|
|
+ FlowDelegate flowDelegate;
|
|
|
+ try {
|
|
|
+ flowDelegate = flowDelegateCls.newInstance();
|
|
|
+ flowDelegate.initTemplateMap();
|
|
|
+ } catch (InstantiationException e) {
|
|
|
+ throw new ServiceException("实例化异常");
|
|
|
+ } catch (IllegalAccessException e) {
|
|
|
+ throw new ServiceException("非法访问异常");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ FlowDefinition flowDefinition = flowDefinitionService.getOne(q -> q
|
|
|
+ .eq(FlowDefinition::getFlowKey, dto.getFlowKey())
|
|
|
+ .eq(FlowDefinition::getCurrentVersion, StatusConstant.YES));
|
|
|
+
|
|
|
+ if (flowDefinition == null) {
|
|
|
+ throw new ServiceException("没有找到可用流程");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ List<FlowDefinitionNode> flowDefinitionNodeList = flowDefinitionNodeService
|
|
|
+ .list(q -> q.eq(FlowDefinitionNode::getFlowDefinitionId, flowDefinition.getId()));
|
|
|
+
|
|
|
+
|
|
|
+ Map<Long, List<FlowDefinitionNode>> parentNodeMap = flowDefinitionNodeList.stream()
|
|
|
+ .collect(Collectors.groupingBy(FlowDefinitionNode::getParentId));
|
|
|
+
|
|
|
+
|
|
|
+ FlowDefinitionNode startNode = flowDefinitionNodeList.stream()
|
|
|
+ .filter(item -> NodeTypeEnum.START.getKey().equals(item.getNodeType()))
|
|
|
+ .findFirst().orElse(null);
|
|
|
+
|
|
|
+ if (startNode == null) {
|
|
|
+ throw new ServiceException("没有找到开始节点");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ FlowDefinitionNode nextUserNode = getNextUserNode(startNode, parentNodeMap);
|
|
|
+
|
|
|
+
|
|
|
+ TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ long flowId = IdWorker.getId();
|
|
|
+
|
|
|
+
|
|
|
+ DynamicDataSourceContextHolder.push(DatasourceConstant.MASTER_NAME);
|
|
|
+
|
|
|
+ FlowExample flowExample = new FlowExample();
|
|
|
+ List<FlowExampleDetail> flowExampleDetailList = new ArrayList<>();
|
|
|
+
|
|
|
+
|
|
|
+ Long businessId = flowDelegate.start(flowId, dto.getData());
|
|
|
+
|
|
|
+ FlowExampleDetail startExampleDetail = new FlowExampleDetail();
|
|
|
+ startExampleDetail.setFlowExampleId(flowId);
|
|
|
+ startExampleDetail.setFlowDefinitionNodeId(startNode.getId());
|
|
|
+ startExampleDetail.setFlowDefinitionNodeType(startNode.getNodeType());
|
|
|
+ startExampleDetail.setHandleType(HandleType.NEXT.getKey());
|
|
|
+ flowExampleDetailList.add(startExampleDetail);
|
|
|
+
|
|
|
+
|
|
|
+ if (NodeTypeEnum.END.equals(NodeTypeEnum.getEnum(nextUserNode.getNodeType()))) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ flowDelegate.end();
|
|
|
+
|
|
|
+
|
|
|
+ flowExample.setStatus(FlowStatus.HAVE_PASSED.getKey());
|
|
|
+
|
|
|
+
|
|
|
+ FlowExampleDetail endExampleDetail = new FlowExampleDetail();
|
|
|
+ startExampleDetail.setFlowExampleId(flowId);
|
|
|
+ startExampleDetail.setFlowDefinitionNodeId(nextUserNode.getId());
|
|
|
+ startExampleDetail.setFlowDefinitionNodeType(nextUserNode.getNodeType());
|
|
|
+ startExampleDetail.setHandleType(HandleType.OVER.getKey());
|
|
|
+ flowExampleDetailList.add(endExampleDetail);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ flowExample.setStatus(FlowStatus.IN_PROGRESS.getKey());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ DynamicDataSourceContextHolder.push(DatasourceConstant.SLAVE_NAME);
|
|
|
+
|
|
|
+ flowExample.setTitle(getTitle(flowDelegate.getTemplateMap()));
|
|
|
+ flowExample.setDefinitionId(flowDefinition.getId());
|
|
|
+ flowExample.setDefintionNodeId(nextUserNode.getId());
|
|
|
+ flowExample.setBusinessId(businessId);
|
|
|
+ flowExampleService.save(flowExample);
|
|
|
+ flowExampleDetailService.saveBatch(flowExampleDetailList);
|
|
|
+
|
|
|
+
|
|
|
+ platformTransactionManager.commit(transaction);
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ platformTransactionManager.rollback(transaction);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 查找下一个用户执行节点
|
|
|
+ *
|
|
|
+ * @param currentNode 当前节点
|
|
|
+ * @param parentNodeMap 父节点map
|
|
|
+ * @return 用户节点
|
|
|
+ */
|
|
|
+ private FlowDefinitionNode getNextUserNode(FlowDefinitionNode currentNode, Map<Long, List<FlowDefinitionNode>> parentNodeMap) {
|
|
|
+
|
|
|
+
|
|
|
+ List<FlowDefinitionNode> nextNodeList = parentNodeMap.get(currentNode.getId());
|
|
|
+
|
|
|
+
|
|
|
+ if (!NodeTypeEnum.BRANCH.equals(NodeTypeEnum.getEnum(currentNode.getNodeType()))) {
|
|
|
+
|
|
|
+ if (nextNodeList.size() != 1) {
|
|
|
+ throw new ServiceException("流程定义错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ return nextNodeList.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (FlowDefinitionNode flowDefinitionNode : nextNodeList) {
|
|
|
+ String handlingMethod = flowDefinitionNode.getHandlingMethod();
|
|
|
+ if (StrUtil.isBlank(handlingMethod)) {
|
|
|
+ throw new ServiceException("未配置分支流转表达式");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return nextNodeList.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getTitle(Map<String, String> map) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 校验el表达式
|
|
|
+ *
|
|
|
+ * @param map
|
|
|
+ * @param expression
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static boolean expressionResult(Map<String, Object> map, String expression) {
|
|
|
+ Expression exp = AviatorEvaluator.compile(expression);
|
|
|
+ final Object execute = exp.execute(map);
|
|
|
+ return Boolean.parseBoolean(String.valueOf(execute));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ HashMap<Object, Object> map1 = new HashMap<>();
|
|
|
+ map1.put("test2", "2");
|
|
|
+
|
|
|
+ HashMap<String, Object> map = new HashMap<>();
|
|
|
+ map.put("admin", new Date());
|
|
|
+ map.put("admin2", DateUtil.offsetDay(new Date(), 1));
|
|
|
+ System.out.println(expressionResult(map, "admin < admin2"));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|