diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/controller/AController.java b/laws-modules/src/main/java/com/jero/modules/activiti/controller/ActivitiController.java similarity index 92% rename from laws-modules/src/main/java/com/jero/modules/activiti/controller/AController.java rename to laws-modules/src/main/java/com/jero/modules/activiti/controller/ActivitiController.java index fe68f468..c0e34080 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/controller/AController.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/controller/ActivitiController.java @@ -2,7 +2,6 @@ package com.jero.modules.activiti.controller; import cn.hutool.core.bean.BeanUtil; 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.node.ObjectNode; 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.LawsProcessNodeService; import com.jero.modules.activiti.service.ProcessService; -import com.jero.modules.activiti.vo.AddTaskVO; import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.converter.BpmnXMLConverter; import org.activiti.bpmn.model.BpmnModel; -import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.editor.language.json.converter.BpmnJsonConverter; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; -import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; @@ -41,12 +36,8 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamReader; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.*; @@ -58,7 +49,7 @@ import java.util.*; @RestController @Api(tags = "流程控制") @RequestMapping("/modeler") -public class AController { +public class ActivitiController { @Autowired private ProcessService processService; @Resource @@ -109,7 +100,6 @@ public class AController { processDefinitionQuery.deploymentId(deployment.getId()); ProcessDefinition processDefinition = processDefinitionQuery.singleResult(); String processDefinitionId = processDefinition.getId(); - processNodeOriginService.saveNodeList(processDefinitionId); map.put("流程定义Id:", processDefinitionId); return Result.OK(map); @@ -295,19 +285,6 @@ public class AController { 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") @ApiOperation(value = "获取实时流程图", notes = "获取实时流程图,输出跟踪流程信息") @@ -320,13 +297,17 @@ public class AController { } } - @GetMapping(value = "/export/{modelId}") + @GetMapping(value = "/export") @ApiOperation(value = "将流程模型导出为 bpmn文件", notes = "将流程模型导出为 bpmn文件") - public void export(@PathVariable("modelId") @ApiParam("流程模型Id") String modelId, HttpServletResponse - response) { + public void export(@RequestParam(value = "modelId", required = false) String modelId, HttpServletResponse response) { 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())) { BpmnXMLConverter xmlConverter = new BpmnXMLConverter(); diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/controller/ActivitiModelerController.java b/laws-modules/src/main/java/com/jero/modules/activiti/controller/ModelerController.java similarity index 77% rename from laws-modules/src/main/java/com/jero/modules/activiti/controller/ActivitiModelerController.java rename to laws-modules/src/main/java/com/jero/modules/activiti/controller/ModelerController.java index 9b97f374..72822b50 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/controller/ActivitiModelerController.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/controller/ModelerController.java @@ -1,11 +1,16 @@ 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.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; 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.ProcessModelNodeService; import com.jero.modules.activiti.util.CreatedTools; +import com.jero.modules.activiti.vo.AddTaskVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -31,6 +36,7 @@ import javax.xml.stream.XMLStreamReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -44,7 +50,7 @@ import java.util.Map; @RestController @Api(tags = "工作流模板管理") @RequestMapping("/activitiModel") -public class ActivitiModelerController { +public class ModelerController { @Autowired private RepositoryService repositoryService; @@ -52,6 +58,8 @@ public class ActivitiModelerController { private ObjectMapper objectMapper; @Resource private LawsProcessNodeOriginService processNodeOriginService; + @Resource + private ProcessModelNodeService processModelNodeService; //@Autowired //private IFormVariableService iFormVariableService; //@Autowired @@ -62,7 +70,7 @@ public class ActivitiModelerController { @ApiImplicitParam(name = "name", value = "模型名称") }) @PostMapping("/importModelFile") - public void importModelFile(@RequestPart(value = "file", required = false) MultipartFile file, + public Result importModelFile(@RequestPart(value = "file", required = false) MultipartFile file, @RequestParam(value = "name", required = false) String name) throws Exception { InputStream fileInputStream = file.getInputStream(); XMLInputFactory xif = XMLInputFactory.newInstance(); @@ -79,8 +87,12 @@ public class ActivitiModelerController { model.setKey(modelKey); model.setMetaInfo(modelNode.toString()); repositoryService.saveModel(model); + String modelId = model.getId(); 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 = "新建模板") @@ -235,7 +247,7 @@ public class ActivitiModelerController { Deployment deployment = repositoryService.createDeployment() .name(modelData.getName()) .category(modelData.getCategory()) - .addString(processName, new String(bpmnBytes, "UTF-8")) + .addString(processName, new String(bpmnBytes, StandardCharsets.UTF_8)) .deploy(); modelData.setDeploymentId(deployment.getId()); repositoryService.saveModel(modelData); @@ -245,7 +257,7 @@ public class ActivitiModelerController { processDefinitionQuery.deploymentId(deployment.getId()); ProcessDefinition processDefinition = processDefinitionQuery.singleResult(); String processDefinitionId = processDefinition.getId(); - processNodeOriginService.saveNodeList(processDefinitionId); + processNodeOriginService.copyNodeFromModel(modelId,processDefinitionId); // 4、输出部署信息 Map map = new HashMap<>(); map.put("流程部署id:", deployment.getId()); @@ -255,4 +267,49 @@ public class ActivitiModelerController { return Result.OK(map); } + @GetMapping("/getNodeList") + @ApiImplicitParam(name = "modelId", value = "模型id") + @ApiOperation("获得节点列表") + public Result> getNodeList(String modelId) { + //查询节点信息 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(ProcessModelNode::getModelId,modelId); + //wrapper.eq(ProcessModelNode::getNodeType,"userTask"); + wrapper.orderByAsc(ProcessModelNode::getSort); + List nodeOriginList = processModelNodeService.list(wrapper); + ArrayList> nodes = new ArrayList<>(); + ArrayList> edges = new ArrayList<>(); + for (ProcessModelNode modelNode : nodeOriginList) { + String nodeType = modelNode.getNodeType(); + String nodeName = modelNode.getNodeName(); + if ("sequenceFlow".equals(nodeType)){ + if (!"驳回".equals(nodeName)){ + Map 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 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 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); + } + + + } diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/entity/ProcessModelNode.java b/laws-modules/src/main/java/com/jero/modules/activiti/entity/ProcessModelNode.java new file mode 100644 index 00000000..eb8385e8 --- /dev/null +++ b/laws-modules/src/main/java/com/jero/modules/activiti/entity/ProcessModelNode.java @@ -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; +} \ No newline at end of file diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/mapper/ProcessModelNodeMapper.java b/laws-modules/src/main/java/com/jero/modules/activiti/mapper/ProcessModelNodeMapper.java new file mode 100644 index 00000000..bc0b49d3 --- /dev/null +++ b/laws-modules/src/main/java/com/jero/modules/activiti/mapper/ProcessModelNodeMapper.java @@ -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 { + int insertList(@Param("list")List list); + + int deleteByModelId(@Param("modelId")String modelId); + + +} \ No newline at end of file diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/mapper/xml/ProcessModelNodeMapper.xml b/laws-modules/src/main/java/com/jero/modules/activiti/mapper/xml/ProcessModelNodeMapper.xml new file mode 100644 index 00000000..65e8dcac --- /dev/null +++ b/laws-modules/src/main/java/com/jero/modules/activiti/mapper/xml/ProcessModelNodeMapper.xml @@ -0,0 +1,83 @@ + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 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 + + ( + #{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} + ) + + + + + + delete from process_model_node + where model_id=#{modelId} + + \ No newline at end of file diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/service/LawsProcessNodeOriginService.java b/laws-modules/src/main/java/com/jero/modules/activiti/service/LawsProcessNodeOriginService.java index 4cba937a..2f7e66ee 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/service/LawsProcessNodeOriginService.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/service/LawsProcessNodeOriginService.java @@ -1,24 +1,33 @@ package com.jero.modules.activiti.service; import cn.hutool.core.lang.UUID; +import cn.hutool.core.util.RandomUtil; 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.exception.JeroBootException; +import com.jero.modules.activiti.entity.ProcessModelNode; import com.jero.modules.activiti.mapper.ActGeBytearrayMapper; +import com.jero.modules.activiti.mapper.ProcessModelNodeMapper; 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.*; +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.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; 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; @@ -42,204 +51,22 @@ public class LawsProcessNodeOriginService extends ServiceImpl wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(ProcessModelNode::getModelId,modelId); + List processModelNodes = processModelNodeMapper.selectList(wrapper); - public void saveNodeList(String processDefinitionId) { - final BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); - Process process = bpmnModel.getMainProcess(); - Collection flowElements = process.getFlowElements(); List processNodeOriginList = new ArrayList<>(); - int sort = 1; - List gatewayIdList = new ArrayList<>(); - processNodeOriginList = handlerLawsProcessNodeOrigin(flowElements,sort,gatewayIdList,processDefinitionId); - List approvalNodeIdList = processNodeOriginList.stream() - .filter(item -> gatewayIdList.contains(item.getXmlTargetRef())) - .map(ProcessNodeOrigin::getXmlSourceRef) - .collect(Collectors.toList()); - - for (ProcessNodeOrigin processNodeOrigin : processNodeOriginList) { - String xmlNodeId = processNodeOrigin.getXmlNodeId(); - if (approvalNodeIdList.contains(xmlNodeId) ){ - processNodeOrigin.setIsApprovalNode(YesOrNoEnum.YES.getInteger()); - } + for (ProcessModelNode processModelNode : processModelNodes) { + ProcessNodeOrigin processNodeOrigin = new ProcessNodeOrigin(); + BeanUtils.copyProperties(processModelNode,processNodeOrigin); + processNodeOrigin.setId(null); + processNodeOrigin.setProcessDefinitionId(processDefinitionId); } processNodeOriginMapper.insertList(processNodeOriginList); } - public Object addTask(AddTaskVO addTaskVO, HttpServletResponse response) { - try { - String processDefinitionId = addTaskVO.getProcessDefinitionId(); - String xmlNodeId = addTaskVO.getXmlNodeId(); - String nodeName = addTaskVO.getNodeName(); - //查找当前节点 - LambdaQueryWrapper 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 incomingFlows = new ArrayList<>(); - SequenceFlow sequenceFlow = createSequenceFlow(originId, id); - process.addFlowElement(sequenceFlow); - incomingFlows.add(sequenceFlow); - gateway.setIncomingFlows(incomingFlows); - List 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 handlerLawsProcessNodeOrigin( - Collection flowElements, - int sort, - List gatewayIdList, - String processDefinitionId) { - List 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 flowElements1 = subProcess.getFlowElements(); - List 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; - } } diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/service/ProcessModelNodeService.java b/laws-modules/src/main/java/com/jero/modules/activiti/service/ProcessModelNodeService.java new file mode 100644 index 00000000..63cdae2c --- /dev/null +++ b/laws-modules/src/main/java/com/jero/modules/activiti/service/ProcessModelNodeService.java @@ -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 { + @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 flowElements = process.getFlowElements(); + List processModelNodeList = new ArrayList<>(); + int sort = 1; + List gatewayIdList = new ArrayList<>(); + processModelNodeList = handlerLawsProcessModelNode(flowElements,sort,gatewayIdList,modelId, null); + List 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 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 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 updateFlow = new LambdaUpdateWrapper<>(); + updateFlow.eq(ProcessModelNode::getXmlNodeId,flowOrigin2.getXmlNodeId()); + updateFlow.set(ProcessModelNode::getXmlTargetRef,userTaskId); + processModelNodeMapper.update(null,updateFlow); + insertUserTask(modelId, userTask); + List incomingFlows = gateway.getIncomingFlows(); + for (SequenceFlow incomingFlow : incomingFlows) { + insertFlow(modelId, incomingFlow); + } + insertGateway(modelId, gateway); + List 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 incomingFlows = new ArrayList<>(); + SequenceFlow sequenceFlow = createSequenceFlow(originId, id); + process.addFlowElement(sequenceFlow); + incomingFlows.add(sequenceFlow); + gateway.setIncomingFlows(incomingFlows); + List 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 handlerLawsProcessModelNode( + Collection flowElements, + int sort, + List gatewayIdList, + String modelId, String subNodeId) { + List 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 flowElements1 = subProcess.getFlowElements(); + xmlNodeId = subProcess.getId(); + List 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; + } +} diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/vo/AddTaskVO.java b/laws-modules/src/main/java/com/jero/modules/activiti/vo/AddTaskVO.java index 4b13dddb..f4f11d32 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/vo/AddTaskVO.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/vo/AddTaskVO.java @@ -11,10 +11,10 @@ import lombok.Data; @Data public class AddTaskVO { /** - * 流程定义id + * 模型id */ - @ApiModelProperty(value = "流程定义id") - private String processDefinitionId; + @ApiModelProperty(value = "模型id") + private String modelId; /** * xml节点Id */