update 流程图处理
This commit is contained in:
+10
-29
@@ -2,7 +2,6 @@ package com.jero.modules.activiti.controller;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.jero.common.api.vo.Result;
|
import com.jero.common.api.vo.Result;
|
||||||
@@ -13,19 +12,15 @@ import com.jero.modules.activiti.entity.ProcessNodeOrigin;
|
|||||||
import com.jero.modules.activiti.service.LawsProcessNodeOriginService;
|
import com.jero.modules.activiti.service.LawsProcessNodeOriginService;
|
||||||
import com.jero.modules.activiti.service.LawsProcessNodeService;
|
import com.jero.modules.activiti.service.LawsProcessNodeService;
|
||||||
import com.jero.modules.activiti.service.ProcessService;
|
import com.jero.modules.activiti.service.ProcessService;
|
||||||
import com.jero.modules.activiti.vo.AddTaskVO;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import io.swagger.annotations.ApiParam;
|
import io.swagger.annotations.ApiParam;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||||
import org.activiti.bpmn.model.BpmnModel;
|
import org.activiti.bpmn.model.BpmnModel;
|
||||||
import org.activiti.editor.constants.ModelDataJsonConstants;
|
|
||||||
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
|
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
|
||||||
import org.activiti.engine.*;
|
import org.activiti.engine.*;
|
||||||
import org.activiti.engine.repository.Deployment;
|
import org.activiti.engine.repository.Deployment;
|
||||||
import org.activiti.engine.repository.Model;
|
|
||||||
import org.activiti.engine.repository.ProcessDefinition;
|
import org.activiti.engine.repository.ProcessDefinition;
|
||||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||||
import org.activiti.engine.runtime.ProcessInstance;
|
import org.activiti.engine.runtime.ProcessInstance;
|
||||||
@@ -41,12 +36,8 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.xml.stream.XMLInputFactory;
|
|
||||||
import javax.xml.stream.XMLStreamReader;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +49,7 @@ import java.util.*;
|
|||||||
@RestController
|
@RestController
|
||||||
@Api(tags = "流程控制")
|
@Api(tags = "流程控制")
|
||||||
@RequestMapping("/modeler")
|
@RequestMapping("/modeler")
|
||||||
public class AController {
|
public class ActivitiController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProcessService processService;
|
private ProcessService processService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -109,7 +100,6 @@ public class AController {
|
|||||||
processDefinitionQuery.deploymentId(deployment.getId());
|
processDefinitionQuery.deploymentId(deployment.getId());
|
||||||
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
|
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
|
||||||
String processDefinitionId = processDefinition.getId();
|
String processDefinitionId = processDefinition.getId();
|
||||||
processNodeOriginService.saveNodeList(processDefinitionId);
|
|
||||||
map.put("流程定义Id:", processDefinitionId);
|
map.put("流程定义Id:", processDefinitionId);
|
||||||
|
|
||||||
return Result.OK(map);
|
return Result.OK(map);
|
||||||
@@ -295,19 +285,6 @@ public class AController {
|
|||||||
return Result.OK();
|
return Result.OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/addTask")
|
|
||||||
@ApiOperation("新增节点")
|
|
||||||
public Object addTask(@RequestBody AddTaskVO addTaskVO, HttpServletResponse response) {
|
|
||||||
return processNodeOriginService.addTask(addTaskVO,response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("保存节点列表")
|
|
||||||
@GetMapping("/saveNodeList")
|
|
||||||
public Object saveNodeList(String processDefinitionId) {
|
|
||||||
processNodeOriginService.saveNodeList(processDefinitionId);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@GetMapping(value = "/readResource")
|
@GetMapping(value = "/readResource")
|
||||||
@ApiOperation(value = "获取实时流程图", notes = "获取实时流程图,输出跟踪流程信息")
|
@ApiOperation(value = "获取实时流程图", notes = "获取实时流程图,输出跟踪流程信息")
|
||||||
@@ -320,13 +297,17 @@ public class AController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/export/{modelId}")
|
@GetMapping(value = "/export")
|
||||||
@ApiOperation(value = "将流程模型导出为 bpmn文件", notes = "将流程模型导出为 bpmn文件")
|
@ApiOperation(value = "将流程模型导出为 bpmn文件", notes = "将流程模型导出为 bpmn文件")
|
||||||
public void export(@PathVariable("modelId") @ApiParam("流程模型Id") String modelId, HttpServletResponse
|
public void export(@RequestParam(value = "modelId", required = false) String modelId, HttpServletResponse response) {
|
||||||
response) {
|
|
||||||
try {
|
try {
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(modelId);
|
ObjectNode objectNode = null;
|
||||||
|
try {
|
||||||
|
objectNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelId));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(objectNode);
|
||||||
// 流程非空判断
|
// 流程非空判断
|
||||||
if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
|
if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
|
||||||
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
|
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
|
||||||
+62
-5
@@ -1,11 +1,16 @@
|
|||||||
package com.jero.modules.activiti.controller;
|
package com.jero.modules.activiti.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.jero.common.api.vo.Result;
|
import com.jero.common.api.vo.Result;
|
||||||
|
import com.jero.modules.activiti.entity.ProcessModelNode;
|
||||||
|
import com.jero.modules.activiti.entity.ProcessNodeOrigin;
|
||||||
import com.jero.modules.activiti.service.LawsProcessNodeOriginService;
|
import com.jero.modules.activiti.service.LawsProcessNodeOriginService;
|
||||||
|
import com.jero.modules.activiti.service.ProcessModelNodeService;
|
||||||
import com.jero.modules.activiti.util.CreatedTools;
|
import com.jero.modules.activiti.util.CreatedTools;
|
||||||
|
import com.jero.modules.activiti.vo.AddTaskVO;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
@@ -31,6 +36,7 @@ import javax.xml.stream.XMLStreamReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -44,7 +50,7 @@ import java.util.Map;
|
|||||||
@RestController
|
@RestController
|
||||||
@Api(tags = "工作流模板管理")
|
@Api(tags = "工作流模板管理")
|
||||||
@RequestMapping("/activitiModel")
|
@RequestMapping("/activitiModel")
|
||||||
public class ActivitiModelerController {
|
public class ModelerController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RepositoryService repositoryService;
|
private RepositoryService repositoryService;
|
||||||
@@ -52,6 +58,8 @@ public class ActivitiModelerController {
|
|||||||
private ObjectMapper objectMapper;
|
private ObjectMapper objectMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private LawsProcessNodeOriginService processNodeOriginService;
|
private LawsProcessNodeOriginService processNodeOriginService;
|
||||||
|
@Resource
|
||||||
|
private ProcessModelNodeService processModelNodeService;
|
||||||
//@Autowired
|
//@Autowired
|
||||||
//private IFormVariableService iFormVariableService;
|
//private IFormVariableService iFormVariableService;
|
||||||
//@Autowired
|
//@Autowired
|
||||||
@@ -62,7 +70,7 @@ public class ActivitiModelerController {
|
|||||||
@ApiImplicitParam(name = "name", value = "模型名称")
|
@ApiImplicitParam(name = "name", value = "模型名称")
|
||||||
})
|
})
|
||||||
@PostMapping("/importModelFile")
|
@PostMapping("/importModelFile")
|
||||||
public void importModelFile(@RequestPart(value = "file", required = false) MultipartFile file,
|
public Result<String> importModelFile(@RequestPart(value = "file", required = false) MultipartFile file,
|
||||||
@RequestParam(value = "name", required = false) String name) throws Exception {
|
@RequestParam(value = "name", required = false) String name) throws Exception {
|
||||||
InputStream fileInputStream = file.getInputStream();
|
InputStream fileInputStream = file.getInputStream();
|
||||||
XMLInputFactory xif = XMLInputFactory.newInstance();
|
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||||
@@ -79,8 +87,12 @@ public class ActivitiModelerController {
|
|||||||
model.setKey(modelKey);
|
model.setKey(modelKey);
|
||||||
model.setMetaInfo(modelNode.toString());
|
model.setMetaInfo(modelNode.toString());
|
||||||
repositoryService.saveModel(model);
|
repositoryService.saveModel(model);
|
||||||
|
String modelId = model.getId();
|
||||||
ObjectNode objectNode = new BpmnJsonConverter().convertToJson(bpmnModel);
|
ObjectNode objectNode = new BpmnJsonConverter().convertToJson(bpmnModel);
|
||||||
repositoryService.addModelEditorSource(model.getId(), objectNode.toString().getBytes("utf-8"));
|
repositoryService.addModelEditorSource(modelId, objectNode.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
//生成节点
|
||||||
|
processModelNodeService.generateNode(modelId);
|
||||||
|
return Result.OK(modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "新建模板")
|
@ApiOperation(value = "新建模板")
|
||||||
@@ -235,7 +247,7 @@ public class ActivitiModelerController {
|
|||||||
Deployment deployment = repositoryService.createDeployment()
|
Deployment deployment = repositoryService.createDeployment()
|
||||||
.name(modelData.getName())
|
.name(modelData.getName())
|
||||||
.category(modelData.getCategory())
|
.category(modelData.getCategory())
|
||||||
.addString(processName, new String(bpmnBytes, "UTF-8"))
|
.addString(processName, new String(bpmnBytes, StandardCharsets.UTF_8))
|
||||||
.deploy();
|
.deploy();
|
||||||
modelData.setDeploymentId(deployment.getId());
|
modelData.setDeploymentId(deployment.getId());
|
||||||
repositoryService.saveModel(modelData);
|
repositoryService.saveModel(modelData);
|
||||||
@@ -245,7 +257,7 @@ public class ActivitiModelerController {
|
|||||||
processDefinitionQuery.deploymentId(deployment.getId());
|
processDefinitionQuery.deploymentId(deployment.getId());
|
||||||
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
|
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
|
||||||
String processDefinitionId = processDefinition.getId();
|
String processDefinitionId = processDefinition.getId();
|
||||||
processNodeOriginService.saveNodeList(processDefinitionId);
|
processNodeOriginService.copyNodeFromModel(modelId,processDefinitionId);
|
||||||
// 4、输出部署信息
|
// 4、输出部署信息
|
||||||
Map<String, String> map = new HashMap<>();
|
Map<String, String> map = new HashMap<>();
|
||||||
map.put("流程部署id:", deployment.getId());
|
map.put("流程部署id:", deployment.getId());
|
||||||
@@ -255,4 +267,49 @@ public class ActivitiModelerController {
|
|||||||
return Result.OK(map);
|
return Result.OK(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getNodeList")
|
||||||
|
@ApiImplicitParam(name = "modelId", value = "模型id")
|
||||||
|
@ApiOperation("获得节点列表")
|
||||||
|
public Result<Map<String,Object>> getNodeList(String modelId) {
|
||||||
|
//查询节点信息
|
||||||
|
LambdaQueryWrapper<ProcessModelNode> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(ProcessModelNode::getModelId,modelId);
|
||||||
|
//wrapper.eq(ProcessModelNode::getNodeType,"userTask");
|
||||||
|
wrapper.orderByAsc(ProcessModelNode::getSort);
|
||||||
|
List<ProcessModelNode> nodeOriginList = processModelNodeService.list(wrapper);
|
||||||
|
ArrayList<Map<String,Object>> nodes = new ArrayList<>();
|
||||||
|
ArrayList<Map<String,Object>> edges = new ArrayList<>();
|
||||||
|
for (ProcessModelNode modelNode : nodeOriginList) {
|
||||||
|
String nodeType = modelNode.getNodeType();
|
||||||
|
String nodeName = modelNode.getNodeName();
|
||||||
|
if ("sequenceFlow".equals(nodeType)){
|
||||||
|
if (!"驳回".equals(nodeName)){
|
||||||
|
Map<String,Object> edge = new HashMap<>();
|
||||||
|
edge.put("source",modelNode.getXmlSourceRef());
|
||||||
|
edge.put("target",modelNode.getXmlTargetRef());
|
||||||
|
edges.add(edge);
|
||||||
|
}
|
||||||
|
}else if (!"endEvent".equals(nodeType)&&!"startEvent".equals(nodeType)){
|
||||||
|
Map<String,Object> node = new HashMap<>();
|
||||||
|
node.put("id",modelNode.getXmlNodeId());
|
||||||
|
node.put("name",nodeName!=null?nodeName:"");
|
||||||
|
node.put("isApprovalNode",modelNode.getIsApprovalNode());
|
||||||
|
node.put("isCanDeleted",modelNode.getIsCanDeleted());
|
||||||
|
nodes.add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<String,Object> result = new HashMap<>();
|
||||||
|
result.put("nodes",nodes);
|
||||||
|
result.put("edges",edges);
|
||||||
|
return Result.OK(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/addTask")
|
||||||
|
@ApiOperation("新增节点")
|
||||||
|
public Object addTask(@RequestBody AddTaskVO addTaskVO, HttpServletResponse response) {
|
||||||
|
return processModelNodeService.addTask(addTaskVO,response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package com.jero.modules.activiti.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*@author liJiaRao
|
||||||
|
*@date 2023-10-08 18:01
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程节点加签表
|
||||||
|
*/
|
||||||
|
@ApiModel(description = "流程节点加签表")
|
||||||
|
@Data
|
||||||
|
@TableName(value = "process_model_node")
|
||||||
|
public class ProcessModelNode {
|
||||||
|
/**
|
||||||
|
* 主键id
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
@ApiModelProperty(value = "主键id")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型id
|
||||||
|
*/
|
||||||
|
@TableField(value = "model_id")
|
||||||
|
@ApiModelProperty(value = "模型id")
|
||||||
|
private String modelId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点名称
|
||||||
|
*/
|
||||||
|
@TableField(value = "node_name")
|
||||||
|
@ApiModelProperty(value = "节点名称")
|
||||||
|
private String nodeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点类型
|
||||||
|
*/
|
||||||
|
@TableField(value = "node_type")
|
||||||
|
@ApiModelProperty(value = "节点类型")
|
||||||
|
private String nodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子流程id
|
||||||
|
*/
|
||||||
|
@TableField(value = "xml_sub_node_id")
|
||||||
|
@ApiModelProperty(value = "子流程id")
|
||||||
|
private String xmlSubNodeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xml节点Id
|
||||||
|
*/
|
||||||
|
@TableField(value = "xml_node_id")
|
||||||
|
@ApiModelProperty(value = "xml节点Id")
|
||||||
|
private String xmlNodeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xml来源节点id
|
||||||
|
*/
|
||||||
|
@TableField(value = "xml_source_ref")
|
||||||
|
@ApiModelProperty(value = "xml来源节点id")
|
||||||
|
private String xmlSourceRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xml目标节点id
|
||||||
|
*/
|
||||||
|
@TableField(value = "xml_target_ref")
|
||||||
|
@ApiModelProperty(value = "xml目标节点id")
|
||||||
|
private String xmlTargetRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否审批节点
|
||||||
|
*/
|
||||||
|
@TableField(value = "is_approval_node")
|
||||||
|
@ApiModelProperty(value = "是否审批节点")
|
||||||
|
private Integer isApprovalNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否可删除
|
||||||
|
*/
|
||||||
|
@TableField(value = "is_can_deleted")
|
||||||
|
@ApiModelProperty(value = "是否可删除")
|
||||||
|
private Integer isCanDeleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
@TableField(value = "sort")
|
||||||
|
@ApiModelProperty(value = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
@TableField(value = "create_by")
|
||||||
|
@ApiModelProperty(value = "创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "create_time")
|
||||||
|
@ApiModelProperty(value = "创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
@TableField(value = "update_by")
|
||||||
|
@ApiModelProperty(value = "更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "update_time")
|
||||||
|
@ApiModelProperty(value = "更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属部门
|
||||||
|
*/
|
||||||
|
@TableField(value = "sys_code")
|
||||||
|
@ApiModelProperty(value = "所属部门")
|
||||||
|
private String sysCode;
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package com.jero.modules.activiti.mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.jero.modules.activiti.entity.ProcessModelNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*@author liJiaRao
|
||||||
|
*@date 2023-10-08 14:08
|
||||||
|
*/
|
||||||
|
public interface ProcessModelNodeMapper extends BaseMapper<ProcessModelNode> {
|
||||||
|
int insertList(@Param("list")List<ProcessModelNode> list);
|
||||||
|
|
||||||
|
int deleteByModelId(@Param("modelId")String modelId);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.jero.modules.activiti.mapper.ProcessModelNodeMapper">
|
||||||
|
<!--auto generated by MybatisCodeHelper on 2023-10-08-->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,
|
||||||
|
model_id,
|
||||||
|
node_name,
|
||||||
|
node_type,
|
||||||
|
xml_node_id,
|
||||||
|
xml_source_ref,
|
||||||
|
xml_target_ref,
|
||||||
|
is_approval_node,
|
||||||
|
is_can_deleted,
|
||||||
|
sort,
|
||||||
|
create_by,
|
||||||
|
create_time,
|
||||||
|
update_by,
|
||||||
|
update_time,
|
||||||
|
sys_code
|
||||||
|
</sql>
|
||||||
|
<resultMap id="BaseResultMap" type="com.jero.modules.activiti.entity.ProcessModelNode">
|
||||||
|
<result column="id" property="id"/>
|
||||||
|
<result column="model_id" property="modelId"/>
|
||||||
|
<result column="node_name" property="nodeName"/>
|
||||||
|
<result column="node_type" property="nodeType"/>
|
||||||
|
<result column="xml_node_id" property="xmlNodeId"/>
|
||||||
|
<result column="xml_source_ref" property="xmlSourceRef"/>
|
||||||
|
<result column="xml_target_ref" property="xmlTargetRef"/>
|
||||||
|
<result column="is_approval_node" property="isApprovalNode"/>
|
||||||
|
<result column="is_can_deleted" property="isCanDeleted"/>
|
||||||
|
<result column="sort" property="sort"/>
|
||||||
|
<result column="create_by" property="createBy"/>
|
||||||
|
<result column="create_time" property="createTime"/>
|
||||||
|
<result column="update_by" property="updateBy"/>
|
||||||
|
<result column="update_time" property="updateTime"/>
|
||||||
|
<result column="sys_code" property="sysCode"/>
|
||||||
|
</resultMap>
|
||||||
|
<insert id="insertList">
|
||||||
|
INSERT INTO process_model_node(
|
||||||
|
id,
|
||||||
|
model_id,
|
||||||
|
node_name,
|
||||||
|
node_type,
|
||||||
|
xml_node_id,
|
||||||
|
xml_source_ref,
|
||||||
|
xml_target_ref,
|
||||||
|
is_approval_node,
|
||||||
|
is_can_deleted,
|
||||||
|
sort,
|
||||||
|
create_by,
|
||||||
|
create_time,
|
||||||
|
update_by,
|
||||||
|
update_time,
|
||||||
|
sys_code
|
||||||
|
)VALUES
|
||||||
|
<foreach collection="list" item="element" index="index" separator=",">
|
||||||
|
(
|
||||||
|
#{element.id,jdbcType=VARCHAR},
|
||||||
|
#{element.modelId,jdbcType=VARCHAR},
|
||||||
|
#{element.nodeName,jdbcType=VARCHAR},
|
||||||
|
#{element.nodeType},
|
||||||
|
#{element.xmlNodeId},
|
||||||
|
#{element.xmlSourceRef},
|
||||||
|
#{element.xmlTargetRef},
|
||||||
|
#{element.isApprovalNode,jdbcType=TINYINT},
|
||||||
|
#{element.isCanDeleted,jdbcType=TINYINT},
|
||||||
|
#{element.sort,jdbcType=TINYINT},
|
||||||
|
#{element.createBy,jdbcType=VARCHAR},
|
||||||
|
#{element.createTime,jdbcType=TIMESTAMP},
|
||||||
|
#{element.updateBy,jdbcType=VARCHAR},
|
||||||
|
#{element.updateTime,jdbcType=TIMESTAMP},
|
||||||
|
#{element.sysCode,jdbcType=VARCHAR}
|
||||||
|
)
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!--auto generated by MybatisCodeHelper on 2023-10-08-->
|
||||||
|
<delete id="deleteByModelId">
|
||||||
|
delete from process_model_node
|
||||||
|
where model_id=#{modelId}
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
||||||
+23
-196
@@ -1,24 +1,33 @@
|
|||||||
package com.jero.modules.activiti.service;
|
package com.jero.modules.activiti.service;
|
||||||
|
|
||||||
import cn.hutool.core.lang.UUID;
|
import cn.hutool.core.lang.UUID;
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.jero.common.constant.enums.YesOrNoEnum;
|
import com.jero.common.constant.enums.YesOrNoEnum;
|
||||||
import com.jero.common.exception.JeroBootException;
|
import com.jero.common.exception.JeroBootException;
|
||||||
|
import com.jero.modules.activiti.entity.ProcessModelNode;
|
||||||
import com.jero.modules.activiti.mapper.ActGeBytearrayMapper;
|
import com.jero.modules.activiti.mapper.ActGeBytearrayMapper;
|
||||||
|
import com.jero.modules.activiti.mapper.ProcessModelNodeMapper;
|
||||||
import com.jero.modules.activiti.vo.AddTaskVO;
|
import com.jero.modules.activiti.vo.AddTaskVO;
|
||||||
import org.activiti.bpmn.BpmnAutoLayout;
|
import org.activiti.bpmn.BpmnAutoLayout;
|
||||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||||
import org.activiti.bpmn.model.*;
|
import org.activiti.bpmn.model.*;
|
||||||
import org.activiti.bpmn.model.Process;
|
import org.activiti.bpmn.model.Process;
|
||||||
|
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
|
||||||
import org.activiti.engine.*;
|
import org.activiti.engine.*;
|
||||||
|
import org.activiti.engine.repository.Model;
|
||||||
|
import org.activiti.engine.repository.ProcessDefinition;
|
||||||
|
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.xml.stream.XMLInputFactory;
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -42,204 +51,22 @@ public class LawsProcessNodeOriginService extends ServiceImpl<LawsProcessNodeOri
|
|||||||
private ActGeBytearrayMapper actGeBytearrayMapper;
|
private ActGeBytearrayMapper actGeBytearrayMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private LawsProcessNodeOriginMapper processNodeOriginMapper;
|
private LawsProcessNodeOriginMapper processNodeOriginMapper;
|
||||||
|
@Resource
|
||||||
|
private ProcessModelNodeMapper processModelNodeMapper;
|
||||||
|
|
||||||
|
public void copyNodeFromModel(String modelId, String processDefinitionId) {
|
||||||
|
LambdaQueryWrapper<ProcessModelNode> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(ProcessModelNode::getModelId,modelId);
|
||||||
|
List<ProcessModelNode> processModelNodes = processModelNodeMapper.selectList(wrapper);
|
||||||
|
|
||||||
public void saveNodeList(String processDefinitionId) {
|
|
||||||
final BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
|
|
||||||
Process process = bpmnModel.getMainProcess();
|
|
||||||
Collection<FlowElement> flowElements = process.getFlowElements();
|
|
||||||
List<ProcessNodeOrigin> processNodeOriginList = new ArrayList<>();
|
List<ProcessNodeOrigin> processNodeOriginList = new ArrayList<>();
|
||||||
int sort = 1;
|
for (ProcessModelNode processModelNode : processModelNodes) {
|
||||||
List<String> gatewayIdList = new ArrayList<>();
|
ProcessNodeOrigin processNodeOrigin = new ProcessNodeOrigin();
|
||||||
processNodeOriginList = handlerLawsProcessNodeOrigin(flowElements,sort,gatewayIdList,processDefinitionId);
|
BeanUtils.copyProperties(processModelNode,processNodeOrigin);
|
||||||
List<String> approvalNodeIdList = processNodeOriginList.stream()
|
processNodeOrigin.setId(null);
|
||||||
.filter(item -> gatewayIdList.contains(item.getXmlTargetRef()))
|
processNodeOrigin.setProcessDefinitionId(processDefinitionId);
|
||||||
.map(ProcessNodeOrigin::getXmlSourceRef)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
for (ProcessNodeOrigin processNodeOrigin : processNodeOriginList) {
|
|
||||||
String xmlNodeId = processNodeOrigin.getXmlNodeId();
|
|
||||||
if (approvalNodeIdList.contains(xmlNodeId) ){
|
|
||||||
processNodeOrigin.setIsApprovalNode(YesOrNoEnum.YES.getInteger());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
processNodeOriginMapper.insertList(processNodeOriginList);
|
processNodeOriginMapper.insertList(processNodeOriginList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object addTask(AddTaskVO addTaskVO, HttpServletResponse response) {
|
|
||||||
try {
|
|
||||||
String processDefinitionId = addTaskVO.getProcessDefinitionId();
|
|
||||||
String xmlNodeId = addTaskVO.getXmlNodeId();
|
|
||||||
String nodeName = addTaskVO.getNodeName();
|
|
||||||
//查找当前节点
|
|
||||||
LambdaQueryWrapper<ProcessNodeOrigin> processNodeOriginLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
processNodeOriginLambdaQueryWrapper.eq(ProcessNodeOrigin::getXmlNodeId, xmlNodeId)
|
|
||||||
.eq(ProcessNodeOrigin::getProcessDefinitionId, processDefinitionId);
|
|
||||||
|
|
||||||
ProcessNodeOrigin processNodeOrigin = processNodeOriginMapper.selectOne(processNodeOriginLambdaQueryWrapper);
|
|
||||||
if (processNodeOrigin == null || !YesOrNoEnum.YES.getInteger().equals(processNodeOrigin.getIsApprovalNode())) {
|
|
||||||
throw new JeroBootException("只能在审批节点后新增");
|
|
||||||
}
|
|
||||||
processNodeOriginLambdaQueryWrapper.clear();
|
|
||||||
//查找节点的流出线
|
|
||||||
processNodeOriginLambdaQueryWrapper.eq(ProcessNodeOrigin::getXmlSourceRef, xmlNodeId)
|
|
||||||
.eq(ProcessNodeOrigin::getProcessDefinitionId, processDefinitionId);
|
|
||||||
ProcessNodeOrigin flowOrigin1 = processNodeOriginMapper.selectOne(processNodeOriginLambdaQueryWrapper);
|
|
||||||
|
|
||||||
processNodeOriginLambdaQueryWrapper.clear();
|
|
||||||
//查找流出线指向的网关
|
|
||||||
processNodeOriginLambdaQueryWrapper.eq(ProcessNodeOrigin::getXmlNodeId, flowOrigin1.getXmlTargetRef())
|
|
||||||
.eq(ProcessNodeOrigin::getProcessDefinitionId, processDefinitionId);
|
|
||||||
ProcessNodeOrigin gatewayOrigin = processNodeOriginMapper.selectOne(processNodeOriginLambdaQueryWrapper);
|
|
||||||
|
|
||||||
processNodeOriginLambdaQueryWrapper.clear();
|
|
||||||
//查找网关指向的线
|
|
||||||
processNodeOriginLambdaQueryWrapper.eq(ProcessNodeOrigin::getXmlSourceRef, gatewayOrigin.getXmlNodeId())
|
|
||||||
.eq(ProcessNodeOrigin::getNodeName, "通过")
|
|
||||||
.eq(ProcessNodeOrigin::getProcessDefinitionId, processDefinitionId);
|
|
||||||
|
|
||||||
ProcessNodeOrigin flowOrigin2 = processNodeOriginMapper.selectOne(processNodeOriginLambdaQueryWrapper);
|
|
||||||
|
|
||||||
BpmnModel bpmnModelOrigin = repositoryService.getBpmnModel(processDefinitionId);
|
|
||||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
|
||||||
byte[] bytesOrigin = converter.convertToXML(bpmnModelOrigin);
|
|
||||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytesOrigin);
|
|
||||||
|
|
||||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
|
||||||
BpmnModel bpmnModel = converter.convertToBpmnModel(factory.createXMLStreamReader(inputStream));
|
|
||||||
Process process = bpmnModel.getMainProcess();
|
|
||||||
SequenceFlow flowElement = (SequenceFlow) process.getFlowElement(flowOrigin2.getXmlNodeId());
|
|
||||||
process.removeFlowElement(flowOrigin2.getXmlNodeId());
|
|
||||||
|
|
||||||
UserTask userTask = createUserTask(nodeName, null);
|
|
||||||
String userTaskId = userTask.getId();
|
|
||||||
flowElement.setTargetRef(userTaskId);
|
|
||||||
process.addFlowElement(flowElement);
|
|
||||||
process.addFlowElement(userTask);
|
|
||||||
process.addFlowElement(createGateway(process, userTaskId, flowOrigin2.getXmlTargetRef(), processNodeOrigin.getXmlNodeId()));
|
|
||||||
|
|
||||||
//重新绘画图形
|
|
||||||
BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(bpmnModel);
|
|
||||||
bpmnAutoLayout.execute();
|
|
||||||
|
|
||||||
//把bpmnModel对象转换成字符
|
|
||||||
byte[] bytes = converter.convertToXML(bpmnModel);
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
|
|
||||||
String filename = bpmnModel.getMainProcess().getId() + ".bpmn";
|
|
||||||
response.setContentType("application/force-download");// 设置强制下载不打开
|
|
||||||
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
|
||||||
IOUtils.copy(in, response.getOutputStream());
|
|
||||||
response.flushBuffer();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (XMLStreamException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
protected static UserTask createUserTask(String name, String assignee) {
|
|
||||||
String id = "Activity_" + UUID.randomUUID();
|
|
||||||
UserTask userTask = new UserTask();
|
|
||||||
userTask.setName(name);
|
|
||||||
userTask.setId(id);
|
|
||||||
userTask.setAssignee(assignee!=null?assignee:"${"+id.replace("-","")+"}");
|
|
||||||
return userTask;
|
|
||||||
}
|
|
||||||
protected static SequenceFlow createSequenceFlow(String from, String to) {
|
|
||||||
SequenceFlow flow = new SequenceFlow();
|
|
||||||
flow.setSourceRef(from);
|
|
||||||
flow.setTargetRef(to);
|
|
||||||
flow.setId("Flow_"+ UUID.randomUUID());
|
|
||||||
return flow;
|
|
||||||
}
|
|
||||||
protected static SequenceFlow createSequenceFlow(String from, String to,String name,String conditionExpression) {
|
|
||||||
SequenceFlow flow = new SequenceFlow();
|
|
||||||
flow.setSourceRef(from);
|
|
||||||
flow.setTargetRef(to);
|
|
||||||
flow.setName(name);
|
|
||||||
flow.setConditionExpression(conditionExpression);
|
|
||||||
flow.setId("Flow_"+ UUID.randomUUID());
|
|
||||||
return flow;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ExclusiveGateway createGateway(Process process, String originId, String targetIdYes, String targetIdNo) {
|
|
||||||
ExclusiveGateway gateway = new ExclusiveGateway();
|
|
||||||
String id = "Gateway_" + UUID.randomUUID();
|
|
||||||
gateway.setId(id);
|
|
||||||
List<SequenceFlow> incomingFlows = new ArrayList<>();
|
|
||||||
SequenceFlow sequenceFlow = createSequenceFlow(originId, id);
|
|
||||||
process.addFlowElement(sequenceFlow);
|
|
||||||
incomingFlows.add(sequenceFlow);
|
|
||||||
gateway.setIncomingFlows(incomingFlows);
|
|
||||||
List<SequenceFlow> outgoingFlows = new ArrayList<>();
|
|
||||||
SequenceFlow sequenceFlow1 = createSequenceFlow(id, targetIdYes, "通过", "${pass}");
|
|
||||||
SequenceFlow sequenceFlow2 = createSequenceFlow(id, targetIdNo, "驳回", "${!pass}");
|
|
||||||
process.addFlowElement(sequenceFlow1);
|
|
||||||
process.addFlowElement(sequenceFlow2);
|
|
||||||
outgoingFlows.add(sequenceFlow1);
|
|
||||||
outgoingFlows.add(sequenceFlow2);
|
|
||||||
gateway.setOutgoingFlows(outgoingFlows);
|
|
||||||
return gateway;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ProcessNodeOrigin> handlerLawsProcessNodeOrigin(
|
|
||||||
Collection<FlowElement> flowElements,
|
|
||||||
int sort,
|
|
||||||
List<String> gatewayIdList,
|
|
||||||
String processDefinitionId) {
|
|
||||||
List<ProcessNodeOrigin> processNodeOriginList = new ArrayList<>();
|
|
||||||
for (FlowElement flowElement : flowElements) {
|
|
||||||
ProcessNodeOrigin processNodeOrigin = new ProcessNodeOrigin();
|
|
||||||
|
|
||||||
String nodeName = processNodeOrigin.getNodeName();
|
|
||||||
String nodeType = processNodeOrigin.getNodeType();
|
|
||||||
String xmlNodeId = processNodeOrigin.getXmlNodeId();
|
|
||||||
String xmlSourceRef = processNodeOrigin.getXmlSourceRef();
|
|
||||||
String xmlTargetRef = processNodeOrigin.getXmlTargetRef();
|
|
||||||
if (flowElement instanceof UserTask) {
|
|
||||||
UserTask userTask = (UserTask) flowElement;
|
|
||||||
nodeType = "userTask";
|
|
||||||
nodeName = userTask.getName();
|
|
||||||
xmlNodeId = userTask.getId();
|
|
||||||
} else if (flowElement instanceof SequenceFlow) {
|
|
||||||
SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
|
|
||||||
nodeType = "sequenceFlow";
|
|
||||||
nodeName = sequenceFlow.getName();
|
|
||||||
xmlNodeId = sequenceFlow.getId();
|
|
||||||
xmlSourceRef = sequenceFlow.getSourceRef();
|
|
||||||
xmlTargetRef = sequenceFlow.getTargetRef();
|
|
||||||
} else if (flowElement instanceof ExclusiveGateway) {
|
|
||||||
ExclusiveGateway gateway = (ExclusiveGateway) flowElement;
|
|
||||||
nodeType = "gateway";
|
|
||||||
nodeName = gateway.getName();
|
|
||||||
xmlNodeId = gateway.getId();
|
|
||||||
gatewayIdList.add(xmlNodeId);
|
|
||||||
} else if (flowElement instanceof SubProcess) {
|
|
||||||
SubProcess subProcess = (SubProcess) flowElement;
|
|
||||||
Collection<FlowElement> flowElements1 = subProcess.getFlowElements();
|
|
||||||
List<ProcessNodeOrigin> processNodeOrigins = handlerLawsProcessNodeOrigin(flowElements1, sort, gatewayIdList, processDefinitionId);
|
|
||||||
processNodeOriginList.addAll(processNodeOrigins);
|
|
||||||
nodeType = "subProcess";
|
|
||||||
nodeName = subProcess.getName();
|
|
||||||
xmlNodeId = subProcess.getId();
|
|
||||||
} else if (flowElement instanceof EndEvent) {
|
|
||||||
EndEvent endEvent = (EndEvent) flowElement;
|
|
||||||
nodeType = "endEvent";
|
|
||||||
nodeName = endEvent.getName();
|
|
||||||
xmlNodeId = endEvent.getId();
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
processNodeOrigin.setProcessDefinitionId(processDefinitionId);
|
|
||||||
processNodeOrigin.setNodeName(nodeName);
|
|
||||||
processNodeOrigin.setNodeType(nodeType);
|
|
||||||
processNodeOrigin.setXmlNodeId(xmlNodeId);
|
|
||||||
processNodeOrigin.setXmlSourceRef(xmlSourceRef);
|
|
||||||
processNodeOrigin.setXmlTargetRef(xmlTargetRef);
|
|
||||||
processNodeOrigin.setSort(sort++);
|
|
||||||
processNodeOrigin.setIsApprovalNode(YesOrNoEnum.NO.getInteger());
|
|
||||||
processNodeOrigin.setIsCanDeleted(YesOrNoEnum.NO.getInteger());
|
|
||||||
processNodeOriginList.add(processNodeOrigin);
|
|
||||||
}
|
|
||||||
return processNodeOriginList;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+316
@@ -0,0 +1,316 @@
|
|||||||
|
package com.jero.modules.activiti.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import com.jero.common.constant.enums.YesOrNoEnum;
|
||||||
|
import com.jero.common.exception.JeroBootException;
|
||||||
|
import com.jero.modules.activiti.entity.ProcessModelNode;
|
||||||
|
import com.jero.modules.activiti.vo.AddTaskVO;
|
||||||
|
import org.activiti.bpmn.BpmnAutoLayout;
|
||||||
|
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||||
|
import org.activiti.bpmn.model.*;
|
||||||
|
import org.activiti.bpmn.model.Process;
|
||||||
|
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
|
||||||
|
import org.activiti.engine.RepositoryService;
|
||||||
|
import org.activiti.engine.repository.Model;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.jero.modules.activiti.mapper.ProcessModelNodeMapper;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*@author liJiaRao
|
||||||
|
*@date 2023-10-08 14:08
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class ProcessModelNodeService extends ServiceImpl<ProcessModelNodeMapper, ProcessModelNode> {
|
||||||
|
@Resource
|
||||||
|
private RepositoryService repositoryService;
|
||||||
|
@Resource
|
||||||
|
private ProcessModelNodeMapper processModelNodeMapper;
|
||||||
|
|
||||||
|
public void generateNode(String modelId) {
|
||||||
|
ObjectNode objectNode = null;
|
||||||
|
try {
|
||||||
|
objectNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelId));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(objectNode);
|
||||||
|
Process process = bpmnModel.getMainProcess();
|
||||||
|
Collection<FlowElement> flowElements = process.getFlowElements();
|
||||||
|
List<ProcessModelNode> processModelNodeList = new ArrayList<>();
|
||||||
|
int sort = 1;
|
||||||
|
List<String> gatewayIdList = new ArrayList<>();
|
||||||
|
processModelNodeList = handlerLawsProcessModelNode(flowElements,sort,gatewayIdList,modelId, null);
|
||||||
|
List<String> approvalNodeIdList = processModelNodeList.stream()
|
||||||
|
.filter(item -> gatewayIdList.contains(item.getXmlTargetRef()))
|
||||||
|
.map(ProcessModelNode::getXmlSourceRef)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (ProcessModelNode processModelNode : processModelNodeList) {
|
||||||
|
String xmlNodeId = processModelNode.getXmlNodeId();
|
||||||
|
if (approvalNodeIdList.contains(xmlNodeId) ){
|
||||||
|
processModelNode.setIsApprovalNode(YesOrNoEnum.YES.getInteger());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processModelNodeMapper.insertList(processModelNodeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object addTask(AddTaskVO addTaskVO, HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
String modelId = addTaskVO.getModelId();
|
||||||
|
String xmlNodeId = addTaskVO.getXmlNodeId();
|
||||||
|
String nodeName = addTaskVO.getNodeName();
|
||||||
|
|
||||||
|
//查询模型
|
||||||
|
Model model = repositoryService.getModel(modelId);
|
||||||
|
String deploymentId = model.getDeploymentId();
|
||||||
|
|
||||||
|
//查找当前节点
|
||||||
|
LambdaQueryWrapper<ProcessModelNode> processModelNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
processModelNodeLambdaQueryWrapper.eq(ProcessModelNode::getXmlNodeId, xmlNodeId)
|
||||||
|
.eq(ProcessModelNode::getModelId, modelId);
|
||||||
|
|
||||||
|
ProcessModelNode processModelNode = processModelNodeMapper.selectOne(processModelNodeLambdaQueryWrapper);
|
||||||
|
if (processModelNode == null || !YesOrNoEnum.YES.getInteger().equals(processModelNode.getIsApprovalNode())) {
|
||||||
|
throw new JeroBootException("只能在审批节点后新增");
|
||||||
|
}
|
||||||
|
processModelNodeLambdaQueryWrapper.clear();
|
||||||
|
//查找节点的流出线
|
||||||
|
processModelNodeLambdaQueryWrapper.eq(ProcessModelNode::getXmlSourceRef, xmlNodeId)
|
||||||
|
.eq(ProcessModelNode::getModelId, modelId);
|
||||||
|
ProcessModelNode flowOrigin1 = processModelNodeMapper.selectOne(processModelNodeLambdaQueryWrapper);
|
||||||
|
|
||||||
|
processModelNodeLambdaQueryWrapper.clear();
|
||||||
|
//查找流出线指向的网关
|
||||||
|
processModelNodeLambdaQueryWrapper.eq(ProcessModelNode::getXmlNodeId, flowOrigin1.getXmlTargetRef())
|
||||||
|
.eq(ProcessModelNode::getModelId, modelId);
|
||||||
|
ProcessModelNode gatewayOrigin = processModelNodeMapper.selectOne(processModelNodeLambdaQueryWrapper);
|
||||||
|
|
||||||
|
processModelNodeLambdaQueryWrapper.clear();
|
||||||
|
//查找网关指向的线
|
||||||
|
processModelNodeLambdaQueryWrapper.eq(ProcessModelNode::getXmlSourceRef, gatewayOrigin.getXmlNodeId())
|
||||||
|
.eq(ProcessModelNode::getNodeName, "通过")
|
||||||
|
.eq(ProcessModelNode::getModelId, modelId);
|
||||||
|
|
||||||
|
ProcessModelNode flowOrigin2 = processModelNodeMapper.selectOne(processModelNodeLambdaQueryWrapper);
|
||||||
|
byte[] modelEditorSource = repositoryService.getModelEditorSource(modelId);
|
||||||
|
ObjectNode objectNode = (ObjectNode) new ObjectMapper().readTree(modelEditorSource);
|
||||||
|
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(objectNode);
|
||||||
|
|
||||||
|
Process process = bpmnModel.getMainProcess();
|
||||||
|
SequenceFlow flowElement = (SequenceFlow) process.getFlowElement(flowOrigin2.getXmlNodeId());
|
||||||
|
process.removeFlowElement(flowOrigin2.getXmlNodeId());
|
||||||
|
//新增节点
|
||||||
|
UserTask userTask = createUserTask(nodeName);
|
||||||
|
String userTaskId = userTask.getId();
|
||||||
|
flowElement.setTargetRef(userTaskId);
|
||||||
|
process.addFlowElement(flowElement);
|
||||||
|
process.addFlowElement(userTask);
|
||||||
|
ExclusiveGateway gateway = createGateway(process, userTaskId, flowOrigin2.getXmlTargetRef(), processModelNode.getXmlNodeId());
|
||||||
|
process.addFlowElement(gateway);
|
||||||
|
List<SequenceFlow> incomingFlows1 = gateway.getIncomingFlows();
|
||||||
|
userTask.setOutgoingFlows(incomingFlows1);
|
||||||
|
|
||||||
|
//重新绘画图形
|
||||||
|
BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(bpmnModel);
|
||||||
|
bpmnAutoLayout.execute();
|
||||||
|
//更新model
|
||||||
|
ObjectNode objectNode1 = new BpmnJsonConverter().convertToJson(bpmnModel);
|
||||||
|
String json = objectNode1.toString();
|
||||||
|
byte[] bytes1 = json.getBytes(StandardCharsets.UTF_8);
|
||||||
|
repositoryService.addModelEditorSource(model.getId(), bytes1);
|
||||||
|
|
||||||
|
//把新增的节点同步到数据库
|
||||||
|
LambdaUpdateWrapper<ProcessModelNode> updateFlow = new LambdaUpdateWrapper<>();
|
||||||
|
updateFlow.eq(ProcessModelNode::getXmlNodeId,flowOrigin2.getXmlNodeId());
|
||||||
|
updateFlow.set(ProcessModelNode::getXmlTargetRef,userTaskId);
|
||||||
|
processModelNodeMapper.update(null,updateFlow);
|
||||||
|
insertUserTask(modelId, userTask);
|
||||||
|
List<SequenceFlow> incomingFlows = gateway.getIncomingFlows();
|
||||||
|
for (SequenceFlow incomingFlow : incomingFlows) {
|
||||||
|
insertFlow(modelId, incomingFlow);
|
||||||
|
}
|
||||||
|
insertGateway(modelId, gateway);
|
||||||
|
List<SequenceFlow> outgoingFlows = gateway.getOutgoingFlows();
|
||||||
|
for (SequenceFlow outgoingFlow : outgoingFlows) {
|
||||||
|
insertFlow(modelId, outgoingFlow);
|
||||||
|
}
|
||||||
|
|
||||||
|
//把bpmnModel对象转换成字符
|
||||||
|
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||||
|
byte[] bytes = converter.convertToXML(bpmnModel);
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
|
||||||
|
String filename = bpmnModel.getMainProcess().getId() + ".bpmn";
|
||||||
|
response.setContentType("application/force-download");// 设置强制下载不打开
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||||
|
IOUtils.copy(in, response.getOutputStream());
|
||||||
|
response.flushBuffer();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertGateway(String modelId, ExclusiveGateway gateway) {
|
||||||
|
ProcessModelNode gatewayNode = new ProcessModelNode();
|
||||||
|
gatewayNode.setModelId(modelId);
|
||||||
|
gatewayNode.setNodeName(gateway.getName());
|
||||||
|
gatewayNode.setNodeType("gateway");
|
||||||
|
gatewayNode.setXmlNodeId(gateway.getId());
|
||||||
|
gatewayNode.setIsApprovalNode(0);
|
||||||
|
gatewayNode.setIsCanDeleted(0);
|
||||||
|
processModelNodeMapper.insert(gatewayNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertUserTask(String modelId, UserTask userTask) {
|
||||||
|
ProcessModelNode userTaskNode = new ProcessModelNode();
|
||||||
|
userTaskNode.setModelId(modelId);
|
||||||
|
userTaskNode.setNodeName(userTask.getName());
|
||||||
|
userTaskNode.setNodeType("userTask");
|
||||||
|
userTaskNode.setXmlNodeId(userTask.getId());
|
||||||
|
userTaskNode.setIsApprovalNode(1);
|
||||||
|
userTaskNode.setIsCanDeleted(1);
|
||||||
|
processModelNodeMapper.insert(userTaskNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertFlow(String modelId, SequenceFlow incomingFlow) {
|
||||||
|
ProcessModelNode flowNode = new ProcessModelNode();
|
||||||
|
flowNode.setModelId(modelId);
|
||||||
|
flowNode.setNodeName(incomingFlow.getName());
|
||||||
|
flowNode.setNodeType("sequenceFlow");
|
||||||
|
flowNode.setXmlNodeId(incomingFlow.getId());
|
||||||
|
flowNode.setIsApprovalNode(0);
|
||||||
|
flowNode.setIsCanDeleted(0);
|
||||||
|
flowNode.setXmlSourceRef(incomingFlow.getSourceRef());
|
||||||
|
flowNode.setXmlTargetRef(incomingFlow.getTargetRef());
|
||||||
|
processModelNodeMapper.insert(flowNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static UserTask createUserTask(String name) {
|
||||||
|
String id = "Activity_" + RandomUtil.randomString(8);
|
||||||
|
UserTask userTask = new UserTask();
|
||||||
|
userTask.setName(name);
|
||||||
|
userTask.setId(id);
|
||||||
|
userTask.setAssignee("${"+id.replace("-","")+"}");
|
||||||
|
return userTask;
|
||||||
|
}
|
||||||
|
protected static SequenceFlow createSequenceFlow(String from, String to) {
|
||||||
|
SequenceFlow flow = new SequenceFlow();
|
||||||
|
flow.setSourceRef(from);
|
||||||
|
flow.setTargetRef(to);
|
||||||
|
flow.setId("Flow_"+ RandomUtil.randomString(8));
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
protected static SequenceFlow createSequenceFlow(String from, String to,String name,String conditionExpression) {
|
||||||
|
SequenceFlow flow = new SequenceFlow();
|
||||||
|
flow.setSourceRef(from);
|
||||||
|
flow.setTargetRef(to);
|
||||||
|
flow.setName(name);
|
||||||
|
flow.setConditionExpression(conditionExpression);
|
||||||
|
flow.setId("Flow_"+ RandomUtil.randomString(8));
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static ExclusiveGateway createGateway(Process process, String originId, String targetIdYes, String targetIdNo) {
|
||||||
|
ExclusiveGateway gateway = new ExclusiveGateway();
|
||||||
|
String id = "Gateway_" + RandomUtil.randomString(8);
|
||||||
|
gateway.setId(id);
|
||||||
|
List<SequenceFlow> incomingFlows = new ArrayList<>();
|
||||||
|
SequenceFlow sequenceFlow = createSequenceFlow(originId, id);
|
||||||
|
process.addFlowElement(sequenceFlow);
|
||||||
|
incomingFlows.add(sequenceFlow);
|
||||||
|
gateway.setIncomingFlows(incomingFlows);
|
||||||
|
List<SequenceFlow> outgoingFlows = new ArrayList<>();
|
||||||
|
SequenceFlow sequenceFlow1 = createSequenceFlow(id, targetIdYes, "通过", "${pass}");
|
||||||
|
SequenceFlow sequenceFlow2 = createSequenceFlow(id, targetIdNo, "驳回", "${!pass}");
|
||||||
|
process.addFlowElement(sequenceFlow1);
|
||||||
|
process.addFlowElement(sequenceFlow2);
|
||||||
|
outgoingFlows.add(sequenceFlow1);
|
||||||
|
outgoingFlows.add(sequenceFlow2);
|
||||||
|
gateway.setOutgoingFlows(outgoingFlows);
|
||||||
|
return gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProcessModelNode> handlerLawsProcessModelNode(
|
||||||
|
Collection<FlowElement> flowElements,
|
||||||
|
int sort,
|
||||||
|
List<String> gatewayIdList,
|
||||||
|
String modelId, String subNodeId) {
|
||||||
|
List<ProcessModelNode> processModelNodeList = new ArrayList<>();
|
||||||
|
for (FlowElement flowElement : flowElements) {
|
||||||
|
ProcessModelNode processModelNode = new ProcessModelNode();
|
||||||
|
|
||||||
|
String nodeName = processModelNode.getNodeName();
|
||||||
|
String nodeType = processModelNode.getNodeType();
|
||||||
|
String xmlNodeId = processModelNode.getXmlNodeId();
|
||||||
|
String xmlSourceRef = processModelNode.getXmlSourceRef();
|
||||||
|
String xmlTargetRef = processModelNode.getXmlTargetRef();
|
||||||
|
if (flowElement instanceof UserTask) {
|
||||||
|
UserTask userTask = (UserTask) flowElement;
|
||||||
|
nodeType = "userTask";
|
||||||
|
nodeName = userTask.getName();
|
||||||
|
xmlNodeId = userTask.getId();
|
||||||
|
} else if (flowElement instanceof SequenceFlow) {
|
||||||
|
SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
|
||||||
|
nodeType = "sequenceFlow";
|
||||||
|
nodeName = sequenceFlow.getName();
|
||||||
|
xmlNodeId = sequenceFlow.getId();
|
||||||
|
xmlSourceRef = sequenceFlow.getSourceRef();
|
||||||
|
xmlTargetRef = sequenceFlow.getTargetRef();
|
||||||
|
} else if (flowElement instanceof ExclusiveGateway) {
|
||||||
|
ExclusiveGateway gateway = (ExclusiveGateway) flowElement;
|
||||||
|
nodeType = "gateway";
|
||||||
|
nodeName = gateway.getName();
|
||||||
|
xmlNodeId = gateway.getId();
|
||||||
|
gatewayIdList.add(xmlNodeId);
|
||||||
|
} else if (flowElement instanceof SubProcess) {
|
||||||
|
SubProcess subProcess = (SubProcess) flowElement;
|
||||||
|
Collection<FlowElement> flowElements1 = subProcess.getFlowElements();
|
||||||
|
xmlNodeId = subProcess.getId();
|
||||||
|
List<ProcessModelNode> processModelNodes = handlerLawsProcessModelNode(flowElements1, sort, gatewayIdList, modelId, xmlNodeId);
|
||||||
|
processModelNodeList.addAll(processModelNodes);
|
||||||
|
nodeType = "subProcess";
|
||||||
|
nodeName = subProcess.getName();
|
||||||
|
} else if (flowElement instanceof StartEvent) {
|
||||||
|
StartEvent startEvent = (StartEvent) flowElement;
|
||||||
|
nodeType = "startEvent";
|
||||||
|
nodeName = startEvent.getName();
|
||||||
|
xmlNodeId = startEvent.getId();
|
||||||
|
}else if (flowElement instanceof EndEvent) {
|
||||||
|
EndEvent endEvent = (EndEvent) flowElement;
|
||||||
|
nodeType = "endEvent";
|
||||||
|
nodeName = endEvent.getName();
|
||||||
|
xmlNodeId = endEvent.getId();
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
processModelNode.setModelId(modelId);
|
||||||
|
processModelNode.setNodeName(nodeName);
|
||||||
|
processModelNode.setNodeType(nodeType);
|
||||||
|
processModelNode.setXmlSubNodeId(subNodeId);
|
||||||
|
processModelNode.setXmlNodeId(xmlNodeId);
|
||||||
|
processModelNode.setXmlSourceRef(xmlSourceRef);
|
||||||
|
processModelNode.setXmlTargetRef(xmlTargetRef);
|
||||||
|
processModelNode.setSort(sort++);
|
||||||
|
processModelNode.setIsApprovalNode(YesOrNoEnum.NO.getInteger());
|
||||||
|
processModelNode.setIsCanDeleted(YesOrNoEnum.NO.getInteger());
|
||||||
|
processModelNodeList.add(processModelNode);
|
||||||
|
}
|
||||||
|
return processModelNodeList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,10 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class AddTaskVO {
|
public class AddTaskVO {
|
||||||
/**
|
/**
|
||||||
* 流程定义id
|
* 模型id
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "流程定义id")
|
@ApiModelProperty(value = "模型id")
|
||||||
private String processDefinitionId;
|
private String modelId;
|
||||||
/**
|
/**
|
||||||
* xml节点Id
|
* xml节点Id
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user