处理提交
This commit is contained in:
69
JeeThink-activiti/pom.xml
Normal file
69
JeeThink-activiti/pom.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>jeethink</artifactId>
|
||||
<groupId>com.jeethink</groupId>
|
||||
<version>3.1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>jeethink-activiti</artifactId>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.activiti</groupId>
|
||||
<artifactId>activiti-spring-boot-starter-rest-api</artifactId>
|
||||
<version>${activiti.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jeethink</groupId>
|
||||
<artifactId>jeethink-framework</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jeethink</groupId>
|
||||
<artifactId>jeethink-system</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jeethink</groupId>
|
||||
<artifactId>jeethink-common</artifactId>
|
||||
</dependency>
|
||||
<!--activiti modeler 5.22 start-->
|
||||
<dependency>
|
||||
<groupId>org.activiti</groupId>
|
||||
<artifactId>activiti-json-converter</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.activiti</groupId>
|
||||
<artifactId>activiti-bpmn-model</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- xml解析依赖-->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-codec</artifactId>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-css</artifactId>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-svg-dom</artifactId>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-svggen</artifactId>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
<!-- xml解析依赖-->
|
||||
<!--activiti modeler 5.22 end-->
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,26 @@
|
||||
package com.jeethink.activiti.config;
|
||||
|
||||
import org.activiti.spring.SpringProcessEngineConfiguration;
|
||||
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ActivitiConfig implements ProcessEngineConfigurationConfigurer {
|
||||
|
||||
@Autowired
|
||||
private ICustomProcessDiagramGenerator customProcessDiagramGenerator;
|
||||
|
||||
/**
|
||||
* 解決工作流生成图片乱码问题
|
||||
*
|
||||
* @param processEngineConfiguration
|
||||
*/
|
||||
@Override
|
||||
public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
|
||||
processEngineConfiguration.setActivityFontName("宋体");
|
||||
processEngineConfiguration.setAnnotationFontName("宋体");
|
||||
processEngineConfiguration.setLabelFontName("宋体");
|
||||
processEngineConfiguration.setProcessDiagramGenerator(customProcessDiagramGenerator);
|
||||
}
|
||||
}
|
@ -0,0 +1,245 @@
|
||||
package com.jeethink.activiti.config;
|
||||
|
||||
import org.activiti.bpmn.model.AssociationDirection;
|
||||
import org.activiti.bpmn.model.GraphicInfo;
|
||||
import org.activiti.image.exception.ActivitiImageException;
|
||||
import org.activiti.image.impl.DefaultProcessDiagramCanvas;
|
||||
import org.activiti.image.util.ReflectUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.LineBreakMeasurer;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
|
||||
public class CustomProcessDiagramCanvas extends DefaultProcessDiagramCanvas {
|
||||
|
||||
protected static Color LABEL_COLOR = new Color(0, 0, 0);
|
||||
|
||||
//font
|
||||
protected String activityFontName = "宋体";
|
||||
protected String labelFontName = "宋体";
|
||||
protected String annotationFontName = "宋体";
|
||||
|
||||
private static volatile boolean flag = false;
|
||||
|
||||
public CustomProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType) {
|
||||
super(width, height, minX, minY, imageType);
|
||||
}
|
||||
|
||||
public CustomProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType,
|
||||
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
|
||||
super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName,
|
||||
customClassLoader);
|
||||
}
|
||||
|
||||
public void drawHighLight(boolean isStartOrEnd, int x, int y, int width, int height, Color color) {
|
||||
Paint originalPaint = g.getPaint();
|
||||
Stroke originalStroke = g.getStroke();
|
||||
|
||||
g.setPaint(color);
|
||||
g.setStroke(MULTI_INSTANCE_STROKE);
|
||||
if (isStartOrEnd) {// 开始、结束节点画圆
|
||||
g.drawOval(x, y, width, height);
|
||||
} else {// 非开始、结束节点画圆角矩形
|
||||
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 5, 5);
|
||||
g.draw(rect);
|
||||
}
|
||||
g.setPaint(originalPaint);
|
||||
g.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public void drawSequenceflow(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault,
|
||||
boolean highLighted, double scaleFactor, Color color) {
|
||||
drawConnection(xPoints, yPoints, conditional, isDefault, "sequenceFlow", AssociationDirection.ONE, highLighted,
|
||||
scaleFactor, color);
|
||||
}
|
||||
|
||||
public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault,
|
||||
String connectionType, AssociationDirection associationDirection, boolean highLighted, double scaleFactor,
|
||||
Color color) {
|
||||
|
||||
Paint originalPaint = g.getPaint();
|
||||
Stroke originalStroke = g.getStroke();
|
||||
|
||||
g.setPaint(CONNECTION_COLOR);
|
||||
if (connectionType.equals("association")) {
|
||||
g.setStroke(ASSOCIATION_STROKE);
|
||||
} else if (highLighted) {
|
||||
g.setPaint(color);
|
||||
g.setStroke(HIGHLIGHT_FLOW_STROKE);
|
||||
}
|
||||
|
||||
for (int i = 1; i < xPoints.length; i++) {
|
||||
Integer sourceX = xPoints[i - 1];
|
||||
Integer sourceY = yPoints[i - 1];
|
||||
Integer targetX = xPoints[i];
|
||||
Integer targetY = yPoints[i];
|
||||
Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY);
|
||||
g.draw(line);
|
||||
}
|
||||
|
||||
if (isDefault) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
|
||||
drawDefaultSequenceFlowIndicator(line, scaleFactor);
|
||||
}
|
||||
|
||||
if (conditional) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
|
||||
drawConditionalSequenceFlowIndicator(line, scaleFactor);
|
||||
}
|
||||
|
||||
if (associationDirection.equals(AssociationDirection.ONE)
|
||||
|| associationDirection.equals(AssociationDirection.BOTH)) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2],
|
||||
xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]);
|
||||
drawArrowHead(line, scaleFactor);
|
||||
}
|
||||
if (associationDirection.equals(AssociationDirection.BOTH)) {
|
||||
Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]);
|
||||
drawArrowHead(line, scaleFactor);
|
||||
}
|
||||
g.setPaint(originalPaint);
|
||||
g.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public void drawLabel(boolean highLighted, String text, GraphicInfo graphicInfo, boolean centered) {
|
||||
float interline = 1.0f;
|
||||
|
||||
// text
|
||||
if (text != null && text.length() > 0) {
|
||||
Paint originalPaint = g.getPaint();
|
||||
Font originalFont = g.getFont();
|
||||
if (highLighted) {
|
||||
g.setPaint(WorkflowConstants.COLOR_NORMAL);
|
||||
} else {
|
||||
g.setPaint(LABEL_COLOR);
|
||||
}
|
||||
g.setFont(new Font(labelFontName, Font.BOLD, 10));
|
||||
|
||||
int wrapWidth = 100;
|
||||
int textY = (int) graphicInfo.getY();
|
||||
|
||||
// TODO: use drawMultilineText()
|
||||
AttributedString as = new AttributedString(text);
|
||||
as.addAttribute(TextAttribute.FOREGROUND, g.getPaint());
|
||||
as.addAttribute(TextAttribute.FONT, g.getFont());
|
||||
AttributedCharacterIterator aci = as.getIterator();
|
||||
FontRenderContext frc = new FontRenderContext(null, true, false);
|
||||
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
|
||||
|
||||
while (lbm.getPosition() < text.length()) {
|
||||
TextLayout tl = lbm.nextLayout(wrapWidth);
|
||||
textY += tl.getAscent();
|
||||
Rectangle2D bb = tl.getBounds();
|
||||
double tX = graphicInfo.getX();
|
||||
if (centered) {
|
||||
tX += (int) (graphicInfo.getWidth() / 2 - bb.getWidth() / 2);
|
||||
}
|
||||
tl.draw(g, (float) tX, textY);
|
||||
textY += tl.getDescent() + tl.getLeading() + (interline - 1.0f) * tl.getAscent();
|
||||
}
|
||||
|
||||
// restore originals
|
||||
g.setFont(originalFont);
|
||||
g.setPaint(originalPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage generateBufferedImage(String imageType) {
|
||||
if (closed) {
|
||||
throw new ActivitiImageException("ProcessDiagramGenerator already closed");
|
||||
}
|
||||
|
||||
// Try to remove white space
|
||||
minX = (minX <= WorkflowConstants.PROCESS_PADDING) ? WorkflowConstants.PROCESS_PADDING : minX;
|
||||
minY = (minY <= WorkflowConstants.PROCESS_PADDING) ? WorkflowConstants.PROCESS_PADDING : minY;
|
||||
BufferedImage imageToSerialize = processDiagram;
|
||||
if (minX >= 0 && minY >= 0) {
|
||||
imageToSerialize = processDiagram.getSubimage(
|
||||
minX - WorkflowConstants.PROCESS_PADDING,
|
||||
minY - WorkflowConstants.PROCESS_PADDING,
|
||||
canvasWidth - minX + WorkflowConstants.PROCESS_PADDING,
|
||||
canvasHeight - minY + WorkflowConstants.PROCESS_PADDING);
|
||||
}
|
||||
return imageToSerialize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(String imageType) {
|
||||
this.processDiagram = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
|
||||
this.g = processDiagram.createGraphics();
|
||||
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setPaint(Color.black);
|
||||
|
||||
Font font = new Font(activityFontName, Font.BOLD, FONT_SIZE);
|
||||
g.setFont(font);
|
||||
this.fontMetrics = g.getFontMetrics();
|
||||
|
||||
LABEL_FONT = new Font(labelFontName, Font.ITALIC, 10);
|
||||
ANNOTATION_FONT = new Font(annotationFontName, Font.PLAIN, FONT_SIZE);
|
||||
//优化加载速度
|
||||
if(flag) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/userTask.png", customClassLoader));
|
||||
SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/scriptTask.png", customClassLoader));
|
||||
SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/serviceTask.png", customClassLoader));
|
||||
RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/receiveTask.png", customClassLoader));
|
||||
SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/sendTask.png", customClassLoader));
|
||||
MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/manualTask.png", customClassLoader));
|
||||
BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/businessRuleTask.png", customClassLoader));
|
||||
SHELL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/shellTask.png", customClassLoader));
|
||||
CAMEL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/camelTask.png", customClassLoader));
|
||||
MULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/muleTask.png", customClassLoader));
|
||||
|
||||
TIMER_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/timer.png", customClassLoader));
|
||||
COMPENSATE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/compensate-throw.png", customClassLoader));
|
||||
COMPENSATE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/compensate.png", customClassLoader));
|
||||
ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/error-throw.png", customClassLoader));
|
||||
ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/error.png", customClassLoader));
|
||||
MESSAGE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/message-throw.png", customClassLoader));
|
||||
MESSAGE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/message.png", customClassLoader));
|
||||
SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/signal-throw.png", customClassLoader));
|
||||
SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/signal.png", customClassLoader));
|
||||
/* String baseUrl = Thread.currentThread().getContextClassLoader().getResource("static/img/activiti/").getPath();
|
||||
SCRIPTTASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"scriptTask.png"));
|
||||
USERTASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"userTask.png"));
|
||||
SERVICETASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"serviceTask.png"));
|
||||
RECEIVETASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"receiveTask.png"));
|
||||
SENDTASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"sendTask.png"));
|
||||
MANUALTASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"manualTask.png"));
|
||||
BUSINESS_RULE_TASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"businessRuleTask.png"));
|
||||
SHELL_TASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"shellTask.png"));
|
||||
CAMEL_TASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"camelTask.png"));
|
||||
MULE_TASK_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"muleTask.png"));
|
||||
|
||||
TIMER_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"timer.png"));
|
||||
COMPENSATE_THROW_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"compensate-throw.png"));
|
||||
COMPENSATE_CATCH_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"compensate.png"));
|
||||
ERROR_THROW_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"error-throw.png"));
|
||||
ERROR_CATCH_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"error.png"));
|
||||
MESSAGE_THROW_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"message-throw.png"));
|
||||
MESSAGE_CATCH_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"message.png"));
|
||||
SIGNAL_THROW_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"signal-throw.png"));
|
||||
SIGNAL_CATCH_IMAGE = ImageIO.read(new FileInputStream(baseUrl+"signal.png"));*/
|
||||
flag = true;
|
||||
} catch (IOException e) {
|
||||
flag = false;
|
||||
LOGGER.warn("Could not load image for process diagram creation: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
package com.jeethink.activiti.config;
|
||||
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.activiti.bpmn.model.*;
|
||||
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
public class CustomProcessDiagramGenerator extends DefaultProcessDiagramGenerator implements ICustomProcessDiagramGenerator{
|
||||
//预初始化流程图绘制,大大提升了系统启动后首次查看流程图的速度
|
||||
static {
|
||||
new CustomProcessDiagramCanvas(10,10,0,0,"png", "宋体","宋体","宋体",null);
|
||||
}
|
||||
|
||||
public CustomProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType,
|
||||
List<String> highLightedActivities, List<String> highLightedFlows, String activityFontName,
|
||||
String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor,
|
||||
Color[] colors, Set<String> currIds) {
|
||||
|
||||
if(null == highLightedActivities) {
|
||||
highLightedActivities = Collections.<String>emptyList();
|
||||
}
|
||||
if(null == highLightedFlows) {
|
||||
highLightedFlows = Collections.<String>emptyList();
|
||||
}
|
||||
|
||||
prepareBpmnModel(bpmnModel);
|
||||
|
||||
CustomProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
|
||||
|
||||
// Draw pool shape, if process is participant in collaboration
|
||||
for (Pool pool : bpmnModel.getPools()) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
|
||||
processDiagramCanvas.drawPoolOrLane(pool.getName(), graphicInfo);
|
||||
}
|
||||
|
||||
// Draw lanes
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
for (Lane lane : process.getLanes()) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId());
|
||||
processDiagramCanvas.drawPoolOrLane(lane.getName(), graphicInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw activities and their sequence-flows
|
||||
for (Process process: bpmnModel.getProcesses()) {
|
||||
List<FlowNode> flowNodeList= process.findFlowElementsOfType(FlowNode.class);
|
||||
for (FlowNode flowNode : flowNodeList) {
|
||||
drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor, colors, currIds);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw artifacts
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
|
||||
for (Artifact artifact : process.getArtifacts()) {
|
||||
drawArtifact(processDiagramCanvas, bpmnModel, artifact);
|
||||
}
|
||||
|
||||
List<SubProcess> subProcesses = process.findFlowElementsOfType(SubProcess.class, true);
|
||||
if (subProcesses != null) {
|
||||
for (SubProcess subProcess : subProcesses) {
|
||||
for (Artifact subProcessArtifact : subProcess.getArtifacts()) {
|
||||
drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return processDiagramCanvas;
|
||||
}
|
||||
|
||||
protected void drawActivity(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode,
|
||||
List<String> highLightedActivities, List<String> highLightedFlows, double scaleFactor, Color[] colors, Set<String> currIds) {
|
||||
ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass());
|
||||
if (drawInstruction != null) {
|
||||
|
||||
drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode);
|
||||
|
||||
// Gather info on the multi instance marker
|
||||
boolean multiInstanceSequential = false, multiInstanceParallel = false, collapsed = false;
|
||||
if (flowNode instanceof Activity) {
|
||||
Activity activity = (Activity) flowNode;
|
||||
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();
|
||||
if (multiInstanceLoopCharacteristics != null) {
|
||||
multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential();
|
||||
multiInstanceParallel = !multiInstanceSequential;
|
||||
}
|
||||
}
|
||||
|
||||
// Gather info on the collapsed marker
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
if (flowNode instanceof SubProcess) {
|
||||
collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded();
|
||||
} else if (flowNode instanceof CallActivity) {
|
||||
collapsed = true;
|
||||
}
|
||||
|
||||
if (scaleFactor == 1.0) {
|
||||
// Actually draw the markers
|
||||
processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(),(int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(),
|
||||
multiInstanceSequential, multiInstanceParallel, collapsed);
|
||||
}
|
||||
|
||||
// Draw highlighted activities
|
||||
if (highLightedActivities.contains(flowNode.getId())) {
|
||||
if(!CollectionUtils.isEmpty(currIds)
|
||||
&&currIds.contains(flowNode.getId())
|
||||
&& !(flowNode instanceof Gateway)) {//非结束节点,并且是当前节点
|
||||
drawHighLight((flowNode instanceof StartEvent), processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()), colors[1]);
|
||||
}else {//普通节点
|
||||
drawHighLight((flowNode instanceof StartEvent)||(flowNode instanceof EndEvent),processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()), colors[0]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Outgoing transitions of activity
|
||||
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
|
||||
String flowId = sequenceFlow.getId();
|
||||
boolean highLighted = (highLightedFlows.contains(flowId));
|
||||
String defaultFlow = null;
|
||||
if (flowNode instanceof Activity) {
|
||||
defaultFlow = ((Activity) flowNode).getDefaultFlow();
|
||||
} else if (flowNode instanceof Gateway) {
|
||||
defaultFlow = ((Gateway) flowNode).getDefaultFlow();
|
||||
}
|
||||
|
||||
boolean isDefault = false;
|
||||
if (defaultFlow != null && defaultFlow.equalsIgnoreCase(flowId)) {
|
||||
isDefault = true;
|
||||
}
|
||||
// boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && !(flowNode instanceof Gateway);
|
||||
|
||||
String sourceRef = sequenceFlow.getSourceRef();
|
||||
String targetRef = sequenceFlow.getTargetRef();
|
||||
FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef);
|
||||
FlowElement targetElement = bpmnModel.getFlowElement(targetRef);
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(flowId);
|
||||
if (graphicInfoList != null && graphicInfoList.size() > 0) {
|
||||
graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList);
|
||||
int xPoints[]= new int[graphicInfoList.size()];
|
||||
int yPoints[]= new int[graphicInfoList.size()];
|
||||
|
||||
for (int i=1; i<graphicInfoList.size(); i++) {
|
||||
GraphicInfo graphicInfo = graphicInfoList.get(i);
|
||||
GraphicInfo previousGraphicInfo = graphicInfoList.get(i-1);
|
||||
|
||||
if (i == 1) {
|
||||
xPoints[0] = (int) previousGraphicInfo.getX();
|
||||
yPoints[0] = (int) previousGraphicInfo.getY();
|
||||
}
|
||||
xPoints[i] = (int) graphicInfo.getX();
|
||||
yPoints[i] = (int) graphicInfo.getY();
|
||||
|
||||
}
|
||||
//画高亮线
|
||||
processDiagramCanvas.drawSequenceflow(xPoints, yPoints, false, isDefault, highLighted, scaleFactor, colors[0]);
|
||||
|
||||
// Draw sequenceflow label
|
||||
// GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(flowId);
|
||||
// if (labelGraphicInfo != null) {
|
||||
// processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false);
|
||||
// }else {//解决流程图连线名称不显示的BUG
|
||||
GraphicInfo lineCenter = getLineCenter(graphicInfoList);
|
||||
processDiagramCanvas.drawLabel(highLighted, sequenceFlow.getName(), lineCenter, Math.abs(xPoints[1]-xPoints[0]) >= 5);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Nested elements
|
||||
if (flowNode instanceof FlowElementsContainer) {
|
||||
for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) {
|
||||
if (nestedFlowElement instanceof FlowNode) {
|
||||
drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement,
|
||||
highLightedActivities, highLightedFlows, scaleFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected void drawHighLight(boolean isStartOrEnd, CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo, Color color) {
|
||||
processDiagramCanvas.drawHighLight(isStartOrEnd, (int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), color);
|
||||
}
|
||||
|
||||
protected static CustomProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType,
|
||||
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
|
||||
|
||||
// We need to calculate maximum values to know how big the image will be in its entirety
|
||||
double minX = Double.MAX_VALUE;
|
||||
double maxX = 0;
|
||||
double minY = Double.MAX_VALUE;
|
||||
double maxY = 0;
|
||||
|
||||
for (Pool pool : bpmnModel.getPools()) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
|
||||
minX = graphicInfo.getX();
|
||||
maxX = graphicInfo.getX() + graphicInfo.getWidth();
|
||||
minY = graphicInfo.getY();
|
||||
maxY = graphicInfo.getY() + graphicInfo.getHeight();
|
||||
}
|
||||
|
||||
List<FlowNode> flowNodes = gatherAllFlowNodes(bpmnModel);
|
||||
for (FlowNode flowNode : flowNodes) {
|
||||
|
||||
GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
|
||||
// width
|
||||
if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) {
|
||||
maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth();
|
||||
}
|
||||
if (flowNodeGraphicInfo.getX() < minX) {
|
||||
minX = flowNodeGraphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) {
|
||||
maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight();
|
||||
}
|
||||
if (flowNodeGraphicInfo.getY() < minY) {
|
||||
minY = flowNodeGraphicInfo.getY();
|
||||
}
|
||||
|
||||
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
|
||||
if (graphicInfoList != null) {
|
||||
for (GraphicInfo graphicInfo : graphicInfoList) {
|
||||
// width
|
||||
if (graphicInfo.getX() > maxX) {
|
||||
maxX = graphicInfo.getX();
|
||||
}
|
||||
if (graphicInfo.getX() < minX) {
|
||||
minX = graphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (graphicInfo.getY() > maxY) {
|
||||
maxY = graphicInfo.getY();
|
||||
}
|
||||
if (graphicInfo.getY()< minY) {
|
||||
minY = graphicInfo.getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Artifact> artifacts = gatherAllArtifacts(bpmnModel);
|
||||
for (Artifact artifact : artifacts) {
|
||||
|
||||
GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId());
|
||||
|
||||
if (artifactGraphicInfo != null) {
|
||||
// width
|
||||
if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) {
|
||||
maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth();
|
||||
}
|
||||
if (artifactGraphicInfo.getX() < minX) {
|
||||
minX = artifactGraphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) {
|
||||
maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight();
|
||||
}
|
||||
if (artifactGraphicInfo.getY() < minY) {
|
||||
minY = artifactGraphicInfo.getY();
|
||||
}
|
||||
}
|
||||
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId());
|
||||
if (graphicInfoList != null) {
|
||||
for (GraphicInfo graphicInfo : graphicInfoList) {
|
||||
// width
|
||||
if (graphicInfo.getX() > maxX) {
|
||||
maxX = graphicInfo.getX();
|
||||
}
|
||||
if (graphicInfo.getX() < minX) {
|
||||
minX = graphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (graphicInfo.getY() > maxY) {
|
||||
maxY = graphicInfo.getY();
|
||||
}
|
||||
if (graphicInfo.getY()< minY) {
|
||||
minY = graphicInfo.getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nrOfLanes = 0;
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
for (Lane l : process.getLanes()) {
|
||||
|
||||
nrOfLanes++;
|
||||
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());
|
||||
// // width
|
||||
if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) {
|
||||
maxX = graphicInfo.getX() + graphicInfo.getWidth();
|
||||
}
|
||||
if (graphicInfo.getX() < minX) {
|
||||
minX = graphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) {
|
||||
maxY = graphicInfo.getY() + graphicInfo.getHeight();
|
||||
}
|
||||
if (graphicInfo.getY() < minY) {
|
||||
minY = graphicInfo.getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special case, see https://activiti.atlassian.net/browse/ACT-1431
|
||||
if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) {
|
||||
// Nothing to show
|
||||
minX = 0;
|
||||
minY = 0;
|
||||
}
|
||||
|
||||
return new CustomProcessDiagramCanvas((int) maxX + 10,(int) maxY + 10, (int) minX, (int) minY,
|
||||
imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities,
|
||||
List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName,
|
||||
ClassLoader customClassLoader, double scaleFactor, Color[] colors, Set<String> currIds) {
|
||||
CustomProcessDiagramCanvas customProcessDiagramCanvas = generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows,
|
||||
activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor,colors, currIds);
|
||||
BufferedImage bufferedImage = customProcessDiagramCanvas.generateBufferedImage(imageType);
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
ImageOutputStream imOut;
|
||||
try {
|
||||
imOut = ImageIO.createImageOutputStream(bs);
|
||||
ImageIO.write(bufferedImage, "PNG", imOut);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
InputStream is = new ByteArrayInputStream(bs.toByteArray());
|
||||
return is;
|
||||
}
|
||||
@Override
|
||||
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
|
||||
return generateDiagram(bpmnModel, imageType, Collections.<String>emptyList(), Collections.<String>emptyList(),
|
||||
activityFontName, labelFontName, annotationFontName, customClassLoader, 1.0, new Color[] {Color.BLACK, Color.BLACK}, null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.jeethink.activiti.config;
|
||||
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.image.ProcessDiagramGenerator;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ICustomProcessDiagramGenerator extends ProcessDiagramGenerator {
|
||||
InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities,
|
||||
List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName,
|
||||
ClassLoader customClassLoader, double scaleFactor, Color[] colors, Set<String> currIds);
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package com.jeethink.activiti.config;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* 常量类
|
||||
*@author jjd
|
||||
**/
|
||||
public final class WorkflowConstants {
|
||||
|
||||
/**businessKey**/
|
||||
public static final String WORKLOW_BUSINESS_KEY = "businessKey";
|
||||
/**按钮网关**/
|
||||
public static final String WAY_TYPE = "wayType";
|
||||
/**按钮网关**/
|
||||
public static final String WAY_TYPE_PREFIX = "way_type_";
|
||||
/**项目id**/
|
||||
public static final String PROJECT_ID = "projectId";
|
||||
/**核心企业Id变量**/
|
||||
public static final String CORE_ENTERPRISE_ID="coreEnterpriseId";
|
||||
/**链属企业Id变量**/
|
||||
public static final String CHAIN_ENTERPRISE_ID="chainEnterpriseId";
|
||||
/**银行企业Id变量**/
|
||||
public static final String BANK_ENTERPRISE_ID="bankEnterpriseId";
|
||||
/**保理公司Id变量**/
|
||||
public static final String BAOLI_ENTERPRISE_ID="baoliEnterpriseId";
|
||||
/**立账开立企业Id变量**/
|
||||
public static final String START_ENTERPRISE_ID="startEnterpriseId";
|
||||
/**立账合作企业Id变量**/
|
||||
public static final String PARTNER_ENTERPRISE_ID="partnerEnterpriseId";
|
||||
/**母公司企业id**/
|
||||
public static final String PARENT_ENTERPRISE_ID="parentEnterpriseId";
|
||||
/**指定签收企业id**/
|
||||
public static final String RECEIVE_ENTERPRISE_ID ="receiveEnterpriseId";
|
||||
/**转出方企业Id变量**/
|
||||
public static final String TRANSFER_ENTERPRISE_ID="transEnterpriseId";
|
||||
/**指定签收企业id**/
|
||||
public static final String AC_TASK_ID ="acTaskId";
|
||||
/**企业所有角色**/
|
||||
public static final String ENT_ALL_ROLE ="all";
|
||||
/**运营所有角色**/
|
||||
public static final String OPER_ALL_ROLE ="oper";
|
||||
/**流程定义缓存时间**/
|
||||
public static final int PROCESS_DEFINITION_CACHE = 60;
|
||||
/**流程实例激活**/
|
||||
public static final int PROCESS_INSTANCE_ACTIVE = 1;
|
||||
|
||||
/**流程实例挂起**/
|
||||
public static final int PROCESS_INSTANCE_SUSPEND = 0;
|
||||
|
||||
/**读取图片**/
|
||||
public static final String READ_IMAGE = "image";
|
||||
|
||||
/**读取xml**/
|
||||
public static final String READ_XML = "xml";
|
||||
|
||||
/**流程激活**/
|
||||
public static final Integer ACTIVE_PROCESSDEFINITION = 1;
|
||||
|
||||
/**流程挂起**/
|
||||
public static final Integer SUSPEND_PROCESSDEFINITION = 2;
|
||||
|
||||
/**流程状态:0-全部,1-正常,2-已挂起**/
|
||||
public static final int QUERY_ALL = 0;
|
||||
public static final int QUERY_NORMAL = 1;
|
||||
public static final int QUERY_SUSPENDED = 2;
|
||||
|
||||
/**流程实例状态:0-全部,1-正常,2-已删除**/
|
||||
public static final int INSTANCE_ALL = 0;
|
||||
public static final int INSTANCE_NOT_DELETED = 1;
|
||||
public static final int INSTANCE_DELETED = 2;
|
||||
|
||||
/** 系统管理员ID **/
|
||||
public static final String INTERFACE_SYSTEM_ID = "-1";
|
||||
/** 系统管理员名称 **/
|
||||
public static final String INTERFACE_SYSTEM_NAME = "系统操作";
|
||||
|
||||
/** 流程部署类型:1-启动并激活,2-启动即挂起 **/
|
||||
public static final int PROCESS_START_ACTIVE = 1;
|
||||
public static final int PROCESS_START_SUSPEND = 2;
|
||||
|
||||
/** 用于标识流程项目配置信息校验结果:1:新流程,2:新版本, 3:流程类别有误 **/
|
||||
public static final int CHECK_NEW_PROCESS = 1;
|
||||
public static final int CHECK_NEW_VERSION = 2;
|
||||
public static final int CHECK_ERROR_PROCESS_TYPE = 3;
|
||||
|
||||
/** 默认网关条件值 **/
|
||||
public static final Integer default_GATEWAY_CONDITION_VALUE = 1;
|
||||
|
||||
/** 工作流-业务状态表数据类型:1-工作流状态,2-业务状态 **/
|
||||
public static final Integer PROCESS_STATUS = 1;
|
||||
public static final Integer BIZNESS_STATUS = 2;
|
||||
|
||||
/** 新增流程时标识:1-直接保存,2-提示覆盖 **/
|
||||
public static final Integer PROCESS_STATUS_SAVE = 1;
|
||||
public static final Integer BIZNESS_STATUS_WARN = 2;
|
||||
|
||||
/** 模板类型标识:1-新创建或直接导入的模板,2-默认模板生成 **/
|
||||
public static final Integer MODEL_TYPE_1 = 1;
|
||||
public static final Integer MODEL_TYPE_2 = 2;
|
||||
|
||||
/** 查询流程定义标识:1-查询最新版本流程定义,2-查询所有版本 **/
|
||||
public static final Integer QUERY_PROCESS_LATEST_VERSION = 1;
|
||||
public static final Integer QUERY_PROCESS_ALL_VERSION = 2;
|
||||
|
||||
/** 按钮网关 通过1 */
|
||||
public static final String WAY_TYPE_PASS = "1";
|
||||
/** 按钮网关 驳回或结束0 */
|
||||
public static final String WAY_TYPE_REJECT = "0";
|
||||
|
||||
/** 按钮网关 退回2 */
|
||||
public static final String WAY_TYPE_BACK = "2";
|
||||
|
||||
/**任务参数为空**/
|
||||
public static final int TASK_CHECK_PARAM_NULL = -1;
|
||||
/**任务已办理**/
|
||||
public static final int TASK_CHECK_COMPLETED = 1;
|
||||
/**无权限办理**/
|
||||
public static final int TASK_CHECK_NO_PERMISSIONS= 2;
|
||||
/**任务校验通过**/
|
||||
public static final int TASK_CHECK_PASS = 0;
|
||||
/** 动态流程图颜色定义 **/
|
||||
public static final Color COLOR_NORMAL = new Color(0, 205, 0);
|
||||
public static final Color COLOR_CURRENT = new Color(255, 0, 0);
|
||||
|
||||
/** 定义生成流程图时的边距(像素) **/
|
||||
public static final int PROCESS_PADDING = 5;
|
||||
|
||||
/** 定义新版业务进度查询包含的流程类型 **/
|
||||
// public static final List<ProcessTypeEnum> INCLUDE_PROCEE_TYPE = Lists.newArrayList(
|
||||
// ProcessTypeEnum.BUILD_ACCOUNT_APPLY,
|
||||
// ProcessTypeEnum.CREDIT_LETTER_APPLY,
|
||||
// ProcessTypeEnum.CREDIT_LETTER_TRANSFER,
|
||||
// ProcessTypeEnum.CREDIT_LETTER_CASH);
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.jeethink.activiti.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.jeethink.activiti.domain.ActIdGroup;
|
||||
import com.jeethink.common.core.controller.BaseController;
|
||||
import com.jeethink.common.core.page.PageDomain;
|
||||
import com.jeethink.common.core.page.TableDataInfo;
|
||||
import com.jeethink.common.core.page.TableSupport;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
|
||||
import org.activiti.engine.IdentityService;
|
||||
import org.activiti.engine.identity.Group;
|
||||
import org.activiti.engine.identity.GroupQuery;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程用户组Controller
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-10-02
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/activiti/actIdGroup")
|
||||
public class ActIdGroupController extends BaseController
|
||||
{
|
||||
|
||||
|
||||
@Autowired
|
||||
private IdentityService identityService;
|
||||
|
||||
|
||||
/**
|
||||
* 查询流程用户组列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(ActIdGroup query)
|
||||
{
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Integer pageNum = pageDomain.getPageNum();
|
||||
Integer pageSize = pageDomain.getPageSize();
|
||||
|
||||
GroupQuery groupQuery = identityService.createGroupQuery();
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
groupQuery.groupId(query.getId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(query.getName())) {
|
||||
groupQuery.groupNameLike("%" + query.getName() + "%");
|
||||
}
|
||||
List<Group> groupList = groupQuery.listPage((pageNum - 1) * pageSize, pageSize);
|
||||
Page<ActIdGroup> list = new Page<>();
|
||||
list.setTotal(groupQuery.count());
|
||||
list.setPageNum(pageNum);
|
||||
list.setPageSize(pageSize);
|
||||
for (Group group: groupList) {
|
||||
ActIdGroup idGroup = new ActIdGroup();
|
||||
idGroup.setId(group.getId());
|
||||
idGroup.setName(group.getName());
|
||||
list.add(idGroup);
|
||||
}
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.jeethink.activiti.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.jeethink.activiti.domain.ActIdUser;
|
||||
import com.jeethink.common.core.controller.BaseController;
|
||||
import com.jeethink.common.core.domain.entity.SysUser;
|
||||
import com.jeethink.common.core.page.PageDomain;
|
||||
import com.jeethink.common.core.page.TableDataInfo;
|
||||
import com.jeethink.common.core.page.TableSupport;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
import com.jeethink.system.service.ISysUserService;
|
||||
|
||||
import org.activiti.engine.IdentityService;
|
||||
import org.activiti.engine.identity.User;
|
||||
import org.activiti.engine.identity.UserQuery;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程用户Controller
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-10-02
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/activiti/actIdUser")
|
||||
public class ActIdUserController extends BaseController {
|
||||
|
||||
|
||||
@Autowired
|
||||
private IdentityService identityService;
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
|
||||
/**
|
||||
* 查询流程用户列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(ActIdUser query)
|
||||
{
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Integer pageNum = pageDomain.getPageNum();
|
||||
Integer pageSize = pageDomain.getPageSize();
|
||||
|
||||
UserQuery userQuery = identityService.createUserQuery();
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
userQuery.userId(query.getId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(query.getFirst())) {
|
||||
userQuery.userFirstNameLike("%" + query.getFirst() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(query.getEmail())) {
|
||||
userQuery.userEmailLike("%" + query.getEmail() + "%");
|
||||
}
|
||||
List<User> userList = userQuery.listPage((pageNum - 1) * pageSize, pageSize);
|
||||
Page<ActIdUser> list = new Page<>();
|
||||
list.setTotal(userQuery.count());
|
||||
list.setPageNum(pageNum);
|
||||
list.setPageSize(pageSize);
|
||||
for (User user: userList) {
|
||||
ActIdUser idUser = new ActIdUser();
|
||||
idUser.setId(user.getId());
|
||||
idUser.setFirst(user.getFirstName());
|
||||
idUser.setEmail(user.getEmail());
|
||||
list.add(idUser);
|
||||
}
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 选择系统用户
|
||||
// */
|
||||
// @GetMapping("/authUser/selectUser")
|
||||
// public String selectUser(String taskId, ModelMap mmap) {
|
||||
// mmap.put("taskId", taskId);
|
||||
// return prefix + "/selectUser";
|
||||
// }
|
||||
|
||||
@PostMapping("/systemUserList")
|
||||
@ResponseBody
|
||||
public TableDataInfo systemUserList(SysUser user) {
|
||||
startPage();
|
||||
List<SysUser> list = userService.selectUserList(user);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,301 @@
|
||||
package com.jeethink.activiti.controller;
|
||||
|
||||
import com.jeethink.activiti.config.ICustomProcessDiagramGenerator;
|
||||
import com.jeethink.activiti.config.WorkflowConstants;
|
||||
import com.jeethink.activiti.domain.ActivitiBaseEntity;
|
||||
import com.jeethink.activiti.domain.HistoricActivity;
|
||||
import com.jeethink.activiti.service.IProcessService;
|
||||
import com.jeethink.common.core.controller.BaseController;
|
||||
import com.jeethink.common.core.domain.AjaxResult;
|
||||
import com.jeethink.common.core.page.TableDataInfo;
|
||||
import com.jeethink.common.utils.SecurityUtils;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.bpmn.model.FlowNode;
|
||||
import org.activiti.bpmn.model.SequenceFlow;
|
||||
import org.activiti.engine.*;
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.impl.RepositoryServiceImpl;
|
||||
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
|
||||
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.*;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/process")
|
||||
public class ProcessController extends BaseController {
|
||||
|
||||
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
|
||||
@Autowired
|
||||
private ProcessEngine processEngine;
|
||||
|
||||
@Autowired
|
||||
private IProcessService processService;
|
||||
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
|
||||
|
||||
/**
|
||||
* 审批历史列表
|
||||
* @param instanceId
|
||||
* @return
|
||||
*/
|
||||
// @RequiresPermissions("process:leave:list")
|
||||
@GetMapping("/listHistory/{instanceId}")
|
||||
@ResponseBody
|
||||
public TableDataInfo listHistory(@PathVariable String instanceId, HistoricActivity historicActivity) {
|
||||
startPage();
|
||||
List<HistoricActivity> list = processService.selectHistoryList(instanceId, historicActivity);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/read-resource")
|
||||
public void readResource(String pProcessInstanceId, HttpServletResponse response)
|
||||
throws Exception {
|
||||
|
||||
String processDefinitionId = "";
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(pProcessInstanceId).singleResult();
|
||||
if(processInstance == null) {
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(pProcessInstanceId).singleResult();
|
||||
processDefinitionId = historicProcessInstance.getProcessDefinitionId();
|
||||
} else {
|
||||
processDefinitionId = processInstance.getProcessDefinitionId();
|
||||
}
|
||||
ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
|
||||
ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();
|
||||
|
||||
String resourceName = pd.getDiagramResourceName();
|
||||
|
||||
if(resourceName.endsWith(".png") && StringUtils.isEmpty(pProcessInstanceId) == false)
|
||||
{
|
||||
getActivitiProccessImage(pProcessInstanceId,response);
|
||||
//ProcessDiagramGenerator.generateDiagram(pde, "png", getRuntimeService().getActiveActivityIds(processInstanceId));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 通过接口读取
|
||||
InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), resourceName);
|
||||
|
||||
// 输出资源内容到相应对象
|
||||
byte[] b = new byte[1024];
|
||||
int len = -1;
|
||||
while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
|
||||
response.getOutputStream().write(b, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程图像,已执行节点和流程线高亮显示
|
||||
*/
|
||||
public void getActivitiProccessImage(String pProcessInstanceId, HttpServletResponse response) {
|
||||
//logger.info("[开始]-获取流程图图像");
|
||||
try {
|
||||
// 获取历史流程实例
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(pProcessInstanceId).singleResult();
|
||||
|
||||
if (historicProcessInstance == null) {
|
||||
//throw new BusinessException("获取流程实例ID[" + pProcessInstanceId + "]对应的历史流程实例失败!");
|
||||
}
|
||||
else {
|
||||
// 获取流程定义
|
||||
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
|
||||
.getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());
|
||||
|
||||
// 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
|
||||
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(pProcessInstanceId).orderByHistoricActivityInstanceId().asc().list();
|
||||
|
||||
// 已执行的节点ID集合
|
||||
List<String> executedActivityIdList = new ArrayList<String>();
|
||||
int index = 1;
|
||||
//logger.info("获取已经执行的节点ID");
|
||||
for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
|
||||
executedActivityIdList.add(activityInstance.getActivityId());
|
||||
|
||||
//logger.info("第[" + index + "]个已执行节点=" + activityInstance.getActivityId() + " : " +activityInstance.getActivityName());
|
||||
index++;
|
||||
}
|
||||
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
|
||||
|
||||
// 已执行的线集合
|
||||
List<String> flowIds = new ArrayList<String>();
|
||||
// 获取流程走过的线 (getHighLightedFlows是下面的方法)
|
||||
flowIds = getHighLightedFlows(bpmnModel,processDefinition, historicActivityInstanceList);
|
||||
|
||||
// // 获取流程图图像字符流
|
||||
// ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
|
||||
// //配置字体
|
||||
// InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds,"宋体","微软雅黑","黑体",null,2.0);
|
||||
|
||||
Set<String> currIds = runtimeService.createExecutionQuery().processInstanceId(pProcessInstanceId).list()
|
||||
.stream().map(e->e.getActivityId()).collect(Collectors.toSet());
|
||||
|
||||
ICustomProcessDiagramGenerator diagramGenerator = (ICustomProcessDiagramGenerator) processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
|
||||
InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList,
|
||||
flowIds, "宋体", "宋体", "宋体", null, 1.0, new Color[] { WorkflowConstants.COLOR_NORMAL, WorkflowConstants.COLOR_CURRENT }, currIds);
|
||||
|
||||
response.setContentType("image/png");
|
||||
OutputStream os = response.getOutputStream();
|
||||
int bytesRead = 0;
|
||||
byte[] buffer = new byte[8192];
|
||||
while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
os.close();
|
||||
imageStream.close();
|
||||
}
|
||||
//logger.info("[完成]-获取流程图图像");
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
//logger.error("【异常】-获取流程图失败!" + e.getMessage());
|
||||
//throw new BusinessException("获取流程图失败!" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getHighLightedFlows(BpmnModel bpmnModel,ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> historicActivityInstances) {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //24小时制
|
||||
List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
|
||||
|
||||
for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
|
||||
// 对历史流程节点进行遍历
|
||||
// 得到节点定义的详细信息
|
||||
FlowNode activityImpl = (FlowNode)bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());
|
||||
|
||||
|
||||
List<FlowNode> sameStartTimeNodes = new ArrayList<FlowNode>();// 用以保存后续开始时间相同的节点
|
||||
FlowNode sameActivityImpl1 = null;
|
||||
|
||||
HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);// 第一个节点
|
||||
HistoricActivityInstance activityImp2_ ;
|
||||
|
||||
for(int k = i + 1 ; k <= historicActivityInstances.size() - 1; k++) {
|
||||
activityImp2_ = historicActivityInstances.get(k);// 后续第1个节点
|
||||
|
||||
if ( activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") &&
|
||||
df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime())) ) //都是usertask,且主节点与后续节点的开始时间相同,说明不是真实的后继节点
|
||||
{
|
||||
|
||||
}
|
||||
else {
|
||||
sameActivityImpl1 = (FlowNode)bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());//找到紧跟在后面的一个节点
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
sameStartTimeNodes.add(sameActivityImpl1); // 将后面第一个节点放在时间相同节点的集合里
|
||||
for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
|
||||
HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
|
||||
HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
|
||||
|
||||
if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime())) )
|
||||
{// 如果第一个节点和第二个节点开始时间相同保存
|
||||
FlowNode sameActivityImpl2 = (FlowNode)bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
|
||||
sameStartTimeNodes.add(sameActivityImpl2);
|
||||
}
|
||||
else
|
||||
{// 有不相同跳出循环
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows() ; // 取出节点的所有出去的线
|
||||
|
||||
for (SequenceFlow pvmTransition : pvmTransitions)
|
||||
{// 对所有的线进行遍历
|
||||
FlowNode pvmActivityImpl = (FlowNode)bpmnModel.getMainProcess().getFlowElement( pvmTransition.getTargetRef());// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
|
||||
if (sameStartTimeNodes.contains(pvmActivityImpl)) {
|
||||
highFlows.add(pvmTransition.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return highFlows;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/delegate")
|
||||
@ResponseBody
|
||||
public AjaxResult delegate(String taskId, String delegateToUser) {
|
||||
processService.delegate(taskId, SecurityUtils.getUsername(), delegateToUser);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@PostMapping( "/cancelApply/{instanceId}")
|
||||
@ResponseBody
|
||||
public AjaxResult cancelApply(@PathVariable String instanceId) {
|
||||
processService.cancelApply(instanceId, "用户撤销");
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@PostMapping( "/suspendOrActiveApply")
|
||||
@ResponseBody
|
||||
public AjaxResult suspendOrActiveApply(@RequestBody ActivitiBaseEntity activitiBaseEntity) {
|
||||
processService.suspendOrActiveApply(activitiBaseEntity.getInstanceId(), activitiBaseEntity.getSuspendState());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@GetMapping("/showVerifyDialog/{taskId}")
|
||||
public AjaxResult showVerifyDialog(@PathVariable("taskId") String taskId) {
|
||||
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
String verifyName = task.getTaskDefinitionKey().substring(0, 1).toUpperCase() + task.getTaskDefinitionKey().substring(1);
|
||||
return AjaxResult.success(verifyName);
|
||||
}
|
||||
/**
|
||||
* 完成任务
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/complete")
|
||||
@ResponseBody
|
||||
public AjaxResult complete( @RequestBody ActivitiBaseEntity activitiBaseEntity) {
|
||||
List<Task> taskList = taskService.createTaskQuery()
|
||||
.processInstanceId(activitiBaseEntity.getInstanceId())
|
||||
// .singleResult();
|
||||
.list();
|
||||
|
||||
if (!CollectionUtils.isEmpty(taskList)) {
|
||||
TaskEntityImpl task = (TaskEntityImpl) taskList.get(0);
|
||||
activitiBaseEntity.setTaskId(task.getId());
|
||||
|
||||
}
|
||||
processService.complete(activitiBaseEntity,"leave");
|
||||
return AjaxResult.success("任务已完成");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package com.jeethink.activiti.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.jeethink.activiti.domain.ProcessDefinition;
|
||||
import com.jeethink.activiti.service.ProcessDefinitionService;
|
||||
import com.jeethink.common.annotation.Log;
|
||||
import com.jeethink.common.config.JeeThinkConfig;
|
||||
import com.jeethink.common.constant.Constants;
|
||||
import com.jeethink.common.core.controller.BaseController;
|
||||
import com.jeethink.common.core.domain.AjaxResult;
|
||||
import com.jeethink.common.core.page.TableDataInfo;
|
||||
import com.jeethink.common.enums.BusinessType;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
import com.jeethink.common.utils.file.FileUploadUtils;
|
||||
|
||||
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.RepositoryService;
|
||||
import org.activiti.engine.repository.Model;
|
||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.aspectj.weaver.loadtime.Aj;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/definition")
|
||||
public class ProcessDefinitionController extends BaseController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ProcessDefinitionController.class);
|
||||
|
||||
private String prefix = "definition";
|
||||
|
||||
@Autowired
|
||||
private ProcessDefinitionService processDefinitionService;
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
|
||||
@GetMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(ProcessDefinition processDefinition) {
|
||||
List<ProcessDefinition> list = processDefinitionService.listProcessDefinition(processDefinition);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 部署流程定义
|
||||
*/
|
||||
@Log(title = "流程定义", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/upload")
|
||||
@ResponseBody
|
||||
public AjaxResult upload(MultipartFile file) {
|
||||
try {
|
||||
if (!file.isEmpty()) {
|
||||
String extensionName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.') + 1);
|
||||
if (!"bpmn".equalsIgnoreCase(extensionName)
|
||||
&& !"zip".equalsIgnoreCase(extensionName)
|
||||
&& !"bar".equalsIgnoreCase(extensionName)) {
|
||||
return AjaxResult.error("流程定义文件仅支持 bpmn, zip 和 bar 格式!");
|
||||
}
|
||||
// p.s. 此时 FileUploadUtils.upload() 返回字符串 fileName 前缀为 Constants.RESOURCE_PREFIX,需剔除
|
||||
// 详见: FileUploadUtils.getPathFileName(...)
|
||||
String fileName = FileUploadUtils.upload(JeeThinkConfig.getProfile()+ "/processDefiniton", file);
|
||||
|
||||
if (StringUtils.isNotBlank(fileName)) {
|
||||
String realFilePath = JeeThinkConfig.getProfile()+ fileName.substring(Constants.RESOURCE_PREFIX.length());
|
||||
processDefinitionService.deployProcessDefinition(realFilePath);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
||||
return AjaxResult.error("不允许上传空文件!");
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("上传流程定义文件失败!", e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Log(title = "流程定义", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/remove/{ids}")
|
||||
@ResponseBody
|
||||
public AjaxResult remove(String ids) {
|
||||
try {
|
||||
return toAjax(processDefinitionService.deleteProcessDeploymentByIds(ids));
|
||||
}
|
||||
catch (Exception e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// @Log(title = "流程定义", businessType = BusinessType.EXPORT)
|
||||
// @PostMapping("/export")
|
||||
// @ResponseBody
|
||||
// public AjaxResult export() {
|
||||
// List<ProcessDefinition> list = processDefinitionService.listProcessDefinition(new ProcessDefinition());
|
||||
// ExcelUtil<ProcessDefinition> util = new ExcelUtil<>(ProcessDefinition.class);
|
||||
// return util.exportExcel(list, "流程定义数据");
|
||||
// }
|
||||
|
||||
@PostMapping( "/suspendOrActiveApply")
|
||||
@ResponseBody
|
||||
public AjaxResult suspendOrActiveApply(@RequestBody ProcessDefinition processDefinition) {
|
||||
processDefinitionService.suspendOrActiveApply(processDefinition.getId(), processDefinition.getSuspendState());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取流程资源
|
||||
*
|
||||
* @param processDefinitionId 流程定义ID
|
||||
* @param resourceName 资源名称
|
||||
*/
|
||||
@RequestMapping(value = "/readResource")
|
||||
public void readResource(@RequestParam("processDefinitionId") String processDefinitionId, @RequestParam("resourceName") String resourceName, HttpServletResponse response)
|
||||
throws Exception {
|
||||
ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
|
||||
org.activiti.engine.repository.ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();
|
||||
|
||||
// 通过接口读取
|
||||
InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), resourceName);
|
||||
|
||||
// 输出资源内容到相应对象
|
||||
byte[] b = new byte[1024];
|
||||
int len = -1;
|
||||
while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
|
||||
response.getOutputStream().write(b, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换流程定义为模型
|
||||
* @param processDefinitionId
|
||||
* @return
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws XMLStreamException
|
||||
*/
|
||||
@PostMapping(value = "/convert2Model")
|
||||
@ResponseBody
|
||||
public AjaxResult convertToModel(@RequestBody String processDefinitionId)
|
||||
throws UnsupportedEncodingException, XMLStreamException {
|
||||
org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
|
||||
.processDefinitionId(processDefinitionId).singleResult();
|
||||
|
||||
InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
|
||||
processDefinition.getResourceName());
|
||||
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||
InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
|
||||
XMLStreamReader xtr = xif.createXMLStreamReader(in);
|
||||
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
|
||||
|
||||
BpmnJsonConverter converter = new BpmnJsonConverter();
|
||||
ObjectNode modelNode = converter.convertToJson(bpmnModel);
|
||||
Model modelData = repositoryService.newModel();
|
||||
modelData.setKey(processDefinition.getKey());
|
||||
modelData.setName(processDefinition.getResourceName());
|
||||
modelData.setCategory(processDefinition.getDeploymentId());
|
||||
|
||||
ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
|
||||
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
|
||||
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
|
||||
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
|
||||
modelData.setMetaInfo(modelObjectNode.toString());
|
||||
|
||||
repositoryService.saveModel(modelData);
|
||||
|
||||
repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
|
||||
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.jeethink.common.annotation.Excel;
|
||||
import com.jeethink.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 流程用户组对象 act_id_group
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-10-02
|
||||
*/
|
||||
public class ActIdGroup extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@Excel(name = "组ID")
|
||||
private String id;
|
||||
|
||||
/** 版本 */
|
||||
private Long rev;
|
||||
|
||||
/** 名称 */
|
||||
@Excel(name = "名称")
|
||||
private String name;
|
||||
|
||||
/** 类型 */
|
||||
private String type;
|
||||
|
||||
private String[] userIds;
|
||||
|
||||
/** 用户是否存在此用户组标识 默认不存在 */
|
||||
private boolean flag = false;
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
public void setRev(Long rev)
|
||||
{
|
||||
this.rev = rev;
|
||||
}
|
||||
|
||||
public Long getRev()
|
||||
{
|
||||
return rev;
|
||||
}
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
public void setType(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public String[] getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(String[] userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
public boolean isFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void setFlag(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("rev", getRev())
|
||||
.append("name", getName())
|
||||
.append("type", getType())
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.jeethink.common.annotation.Excel;
|
||||
import com.jeethink.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 流程用户对象 act_id_user
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-10-02
|
||||
*/
|
||||
public class ActIdUser extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@Excel(name = "用户ID")
|
||||
private String id;
|
||||
|
||||
/** 版本 */
|
||||
private Long rev;
|
||||
|
||||
/** 名字 */
|
||||
@Excel(name = "名字")
|
||||
private String first;
|
||||
|
||||
/** 姓氏 */
|
||||
private String last;
|
||||
|
||||
/** 邮箱 */
|
||||
@Excel(name = "邮箱")
|
||||
private String email;
|
||||
|
||||
/** 密码 */
|
||||
private String pwd;
|
||||
|
||||
/** 头像 */
|
||||
private String pictureId;
|
||||
|
||||
/** 用户组 */
|
||||
private String[] groupIds;
|
||||
|
||||
/** 用户组是否存在此用户标识 默认不存在 */
|
||||
private boolean flag = false;
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
public void setRev(Long rev)
|
||||
{
|
||||
this.rev = rev;
|
||||
}
|
||||
|
||||
public Long getRev()
|
||||
{
|
||||
return rev;
|
||||
}
|
||||
public void setFirst(String first)
|
||||
{
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
public String getFirst()
|
||||
{
|
||||
return first;
|
||||
}
|
||||
public void setLast(String last)
|
||||
{
|
||||
this.last = last;
|
||||
}
|
||||
|
||||
public String getLast()
|
||||
{
|
||||
return last;
|
||||
}
|
||||
public void setEmail(String email)
|
||||
{
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getEmail()
|
||||
{
|
||||
return email;
|
||||
}
|
||||
public void setPwd(String pwd)
|
||||
{
|
||||
this.pwd = pwd;
|
||||
}
|
||||
|
||||
public String getPwd()
|
||||
{
|
||||
return pwd;
|
||||
}
|
||||
public void setPictureId(String pictureId)
|
||||
{
|
||||
this.pictureId = pictureId;
|
||||
}
|
||||
|
||||
public String getPictureId()
|
||||
{
|
||||
return pictureId;
|
||||
}
|
||||
|
||||
public String[] getGroupIds() {
|
||||
return groupIds;
|
||||
}
|
||||
|
||||
public void setGroupIds(String[] groupIds) {
|
||||
this.groupIds = groupIds;
|
||||
}
|
||||
|
||||
public boolean isFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void setFlag(boolean flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("rev", getRev())
|
||||
.append("first", getFirst())
|
||||
.append("last", getLast())
|
||||
.append("email", getEmail())
|
||||
.append("pwd", getPwd())
|
||||
.append("pictureId", getPictureId())
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jeethink.common.annotation.Excel;
|
||||
import com.jeethink.common.core.domain.BaseEntity;
|
||||
|
||||
public class ActivitiBaseEntity extends BaseEntity {
|
||||
|
||||
/** 流程实例ID */
|
||||
@Excel(name = "流程实例ID")
|
||||
private String instanceId;
|
||||
/** 申请人姓名 */
|
||||
private String applyUserName;
|
||||
/** 标题 */
|
||||
@Excel(name = "标题")
|
||||
private String title;
|
||||
|
||||
/** 原因 */
|
||||
@Excel(name = "原因")
|
||||
private String reason;
|
||||
|
||||
/** 任务ID */
|
||||
private String taskId;
|
||||
|
||||
/** 任务名称 */
|
||||
private String taskName;
|
||||
|
||||
/** 办理时间 */
|
||||
private Date doneTime;
|
||||
|
||||
/** 创建人 */
|
||||
private String createUserName;
|
||||
|
||||
|
||||
/** 流程实例状态 1 激活 2 挂起 */
|
||||
private String suspendState;
|
||||
private Map<String, Object> processParams;
|
||||
|
||||
|
||||
public String getApplyUserName() {
|
||||
return applyUserName;
|
||||
}
|
||||
|
||||
public void setApplyUserName(String applyUserName) {
|
||||
this.applyUserName = applyUserName;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(String taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public Date getDoneTime() {
|
||||
return doneTime;
|
||||
}
|
||||
|
||||
public void setDoneTime(Date doneTime) {
|
||||
this.doneTime = doneTime;
|
||||
}
|
||||
|
||||
public String getCreateUserName() {
|
||||
return createUserName;
|
||||
}
|
||||
|
||||
public void setCreateUserName(String createUserName) {
|
||||
this.createUserName = createUserName;
|
||||
}
|
||||
|
||||
public String getSuspendState() {
|
||||
return suspendState;
|
||||
}
|
||||
|
||||
public void setSuspendState(String suspendState) {
|
||||
this.suspendState = suspendState;
|
||||
}
|
||||
|
||||
public void setInstanceId(String instanceId)
|
||||
{
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
public String getInstanceId()
|
||||
{
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
public void setReason(String reason)
|
||||
{
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public String getReason()
|
||||
{
|
||||
return reason;
|
||||
}
|
||||
|
||||
public Map<String, Object> getProcessParams() {
|
||||
if (processParams == null)
|
||||
{
|
||||
processParams = new HashMap<>();
|
||||
}
|
||||
return processParams;
|
||||
}
|
||||
|
||||
public void setProcessParams(Map<String, Object> processParams) {
|
||||
this.processParams = processParams;
|
||||
}
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.jeethink.common.annotation.Excel;
|
||||
import com.jeethink.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 待办事项对象 biz_todo_item
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-11-08
|
||||
*/
|
||||
public class BizTodoItem extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键 ID */
|
||||
private Long id;
|
||||
|
||||
/** 事项标题 */
|
||||
@Excel(name = "事项标题")
|
||||
private String itemName;
|
||||
|
||||
/** 事项内容 */
|
||||
@Excel(name = "事项内容")
|
||||
private String itemContent;
|
||||
|
||||
/** 模块名称 (必须以 uri 一致) */
|
||||
@Excel(name = "模块名称")
|
||||
private String module;
|
||||
|
||||
/** 任务 ID */
|
||||
@Excel(name = "任务 ID")
|
||||
private String taskId;
|
||||
|
||||
/** 流程实例 ID */
|
||||
@Excel(name = "流程实例 ID")
|
||||
private String instanceId;
|
||||
|
||||
/** 任务名称 (必须以表单页面名称一致) */
|
||||
@Excel(name = "任务名称")
|
||||
private String taskName;
|
||||
|
||||
/** 节点名称 */
|
||||
@Excel(name = "节点名称")
|
||||
private String nodeName;
|
||||
|
||||
/** 是否查看 default 0 (0 否 1 是) */
|
||||
@Excel(name = "是否查看")
|
||||
private String isView;
|
||||
|
||||
/** 是否处理 default 0 (0 否 1 是) */
|
||||
@Excel(name = "是否处理")
|
||||
private String isHandle;
|
||||
|
||||
/** 待办人 ID */
|
||||
@Excel(name = "待办人 ID")
|
||||
private String todoUserId;
|
||||
|
||||
/** 待办人名称 */
|
||||
@Excel(name = "待办人名称")
|
||||
private String todoUserName;
|
||||
|
||||
/** 处理人 ID */
|
||||
@Excel(name = "处理人 ID")
|
||||
private String handleUserId;
|
||||
|
||||
/** 处理人名称 */
|
||||
@Excel(name = "处理人名称")
|
||||
private String handleUserName;
|
||||
|
||||
/** 通知时间 */
|
||||
@Excel(name = "通知时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date todoTime;
|
||||
|
||||
/** 处理时间 */
|
||||
@Excel(name = "处理时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date handleTime;
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setItemName(String itemName) {
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
public String getItemName() {
|
||||
return itemName;
|
||||
}
|
||||
public void setItemContent(String itemContent) {
|
||||
this.itemContent = itemContent;
|
||||
}
|
||||
|
||||
public String getItemContent() {
|
||||
return itemContent;
|
||||
}
|
||||
public void setModule(String module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
public void setTaskId(String taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public String getNodeName() {
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
public void setNodeName(String nodeName) {
|
||||
this.nodeName = nodeName;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
public void setIsView(String isView) {
|
||||
this.isView = isView;
|
||||
}
|
||||
|
||||
public String getIsView() {
|
||||
return isView;
|
||||
}
|
||||
public void setIsHandle(String isHandle) {
|
||||
this.isHandle = isHandle;
|
||||
}
|
||||
|
||||
public String getIsHandle() {
|
||||
return isHandle;
|
||||
}
|
||||
public void setTodoUserId(String todoUserId) {
|
||||
this.todoUserId = todoUserId;
|
||||
}
|
||||
|
||||
public String getTodoUserId() {
|
||||
return todoUserId;
|
||||
}
|
||||
public void setTodoUserName(String todoUserName) {
|
||||
this.todoUserName = todoUserName;
|
||||
}
|
||||
|
||||
public String getTodoUserName() {
|
||||
return todoUserName;
|
||||
}
|
||||
public void setHandleUserId(String handleUserId) {
|
||||
this.handleUserId = handleUserId;
|
||||
}
|
||||
|
||||
public String getHandleUserId() {
|
||||
return handleUserId;
|
||||
}
|
||||
public void setHandleUserName(String handleUserName) {
|
||||
this.handleUserName = handleUserName;
|
||||
}
|
||||
|
||||
public String getHandleUserName() {
|
||||
return handleUserName;
|
||||
}
|
||||
public void setTodoTime(Date todoTime) {
|
||||
this.todoTime = todoTime;
|
||||
}
|
||||
|
||||
public Date getTodoTime() {
|
||||
return todoTime;
|
||||
}
|
||||
public void setHandleTime(Date handleTime) {
|
||||
this.handleTime = handleTime;
|
||||
}
|
||||
|
||||
public Date getHandleTime() {
|
||||
return handleTime;
|
||||
}
|
||||
|
||||
public String getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public void setInstanceId(String instanceId) {
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("itemName", getItemName())
|
||||
.append("itemContent", getItemContent())
|
||||
.append("module", getModule())
|
||||
.append("instanceId", getInstanceId())
|
||||
.append("taskId", getTaskId())
|
||||
.append("taskName", getTaskName())
|
||||
.append("isView", getIsView())
|
||||
.append("isHandle", getIsHandle())
|
||||
.append("todoUserId", getTodoUserId())
|
||||
.append("todoUserName", getTodoUserName())
|
||||
.append("handleUserId", getHandleUserId())
|
||||
.append("handleUserName", getHandleUserName())
|
||||
.append("todoTime", getTodoTime())
|
||||
.append("handleTime", getHandleTime())
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import org.activiti.engine.impl.persistence.entity.HistoricActivityInstanceEntityImpl;
|
||||
|
||||
public class HistoricActivity extends HistoricActivityInstanceEntityImpl {
|
||||
|
||||
/** 审批批注 */
|
||||
private String comment;
|
||||
|
||||
/** 办理人姓名 */
|
||||
private String assigneeName;
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public String getAssigneeName() {
|
||||
return assigneeName;
|
||||
}
|
||||
|
||||
public void setAssigneeName(String assigneeName) {
|
||||
this.assigneeName = assigneeName;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import com.jeethink.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 汇讯数码科技(深圳)有限公司
|
||||
* 创建日期:2020/9/14-13:57
|
||||
* 版本 开发者 日期
|
||||
* 1.0 Danny 2020/9/14
|
||||
*/
|
||||
public class ModelerVo {
|
||||
private String name;
|
||||
private String key;
|
||||
private String description;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package com.jeethink.activiti.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.jeethink.common.annotation.Excel;
|
||||
import com.jeethink.common.core.domain.BaseEntity;
|
||||
|
||||
public class ProcessDefinition extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
@Excel(name = "流程名称")
|
||||
private String name;
|
||||
|
||||
@Excel(name = "流程KEY")
|
||||
private String key;
|
||||
|
||||
@Excel(name = "流程版本")
|
||||
private int version;
|
||||
|
||||
@Excel(name = "所属分类")
|
||||
private String category;
|
||||
|
||||
@Excel(name = "流程描述")
|
||||
private String description;
|
||||
|
||||
private String deploymentId;
|
||||
|
||||
@Excel(name = "部署时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date deploymentTime;
|
||||
|
||||
@Excel(name = "流程图")
|
||||
private String diagramResourceName;
|
||||
|
||||
@Excel(name = "流程定义")
|
||||
private String resourceName;
|
||||
|
||||
/** 流程实例状态 1 激活 2 挂起 */
|
||||
private String suspendState;
|
||||
|
||||
private String suspendStateName;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDeploymentId() {
|
||||
return deploymentId;
|
||||
}
|
||||
|
||||
public void setDeploymentId(String deploymentId) {
|
||||
this.deploymentId = deploymentId;
|
||||
}
|
||||
|
||||
public Date getDeploymentTime() {
|
||||
return deploymentTime;
|
||||
}
|
||||
|
||||
public void setDeploymentTime(Date deploymentTime) {
|
||||
this.deploymentTime = deploymentTime;
|
||||
}
|
||||
|
||||
public String getDiagramResourceName() {
|
||||
return diagramResourceName;
|
||||
}
|
||||
|
||||
public void setDiagramResourceName(String diagramResourceName) {
|
||||
this.diagramResourceName = diagramResourceName;
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
public void setResourceName(String resourceName) {
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
public String getSuspendState() {
|
||||
return suspendState;
|
||||
}
|
||||
|
||||
public void setSuspendState(String suspendState) {
|
||||
this.suspendState = suspendState;
|
||||
}
|
||||
|
||||
public String getSuspendStateName() {
|
||||
return suspendStateName;
|
||||
}
|
||||
|
||||
public void setSuspendStateName(String suspendStateName) {
|
||||
this.suspendStateName = suspendStateName;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.jeethink.activiti.form;
|
||||
|
||||
import org.activiti.engine.form.AbstractFormType;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 用户表单字段类型
|
||||
*
|
||||
* @author henryyan
|
||||
*/
|
||||
@Component
|
||||
public class UsersFormType extends AbstractFormType {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "users";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertFormValueToModelValue(String propertyValue) {
|
||||
String[] split = StringUtils.split(propertyValue, ",");
|
||||
return Arrays.asList(split);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertModelValueToFormValue(Object modelValue) {
|
||||
return ObjectUtils.toString(modelValue);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.jeethink.activiti.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import com.jeethink.activiti.domain.BizTodoItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 待办事项Mapper接口
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-11-08
|
||||
*/
|
||||
public interface BizTodoItemMapper {
|
||||
/**
|
||||
* 查询待办事项
|
||||
*
|
||||
* @param id 待办事项ID
|
||||
* @return 待办事项
|
||||
*/
|
||||
public BizTodoItem selectBizTodoItemById(Long id);
|
||||
|
||||
/**
|
||||
* 查询待办事项列表
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 待办事项集合
|
||||
*/
|
||||
public List<BizTodoItem> selectBizTodoItemList(BizTodoItem bizTodoItem);
|
||||
|
||||
/**
|
||||
* 新增待办事项
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBizTodoItem(BizTodoItem bizTodoItem);
|
||||
|
||||
/**
|
||||
* 修改待办事项
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBizTodoItem(BizTodoItem bizTodoItem);
|
||||
|
||||
/**
|
||||
* 删除待办事项
|
||||
*
|
||||
* @param id 待办事项ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBizTodoItemById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除待办事项
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBizTodoItemByIds(String[] ids);
|
||||
|
||||
@Select("SELECT * FROM BIZ_TODO_ITEM WHERE TASK_ID = #{taskId}")
|
||||
BizTodoItem selectTodoItemByTaskId(@Param(value = "taskId") String taskId);
|
||||
|
||||
@Select("SELECT USER_ID_ FROM ACT_ID_MEMBERSHIP WHERE GROUP_ID_ = (SELECT GROUP_ID_ FROM ACT_RU_IDENTITYLINK WHERE TASK_ID_ = #{taskId})")
|
||||
List<String> selectTodoUserListByTaskId(@Param(value = "taskId") String taskId);
|
||||
|
||||
@Select("SELECT * FROM BIZ_TODO_ITEM WHERE TASK_ID = #{taskId} AND TODO_USER_ID = #{todoUserId}")
|
||||
BizTodoItem selectTodoItemByCondition(@Param(value = "taskId") String taskId, @Param(value = "todoUserId") String todoUserId);
|
||||
|
||||
@Select("SELECT USER_ID_ FROM ACT_ID_MEMBERSHIP WHERE USER_ID_ = (SELECT USER_ID_ FROM ACT_RU_IDENTITYLINK WHERE TASK_ID_ = #{taskId})")
|
||||
String selectTodoUserByTaskId(String id);
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeethink.activiti.modeler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.activiti.editor.constants.ModelDataJsonConstants;
|
||||
import org.activiti.engine.ActivitiException;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.repository.Model;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Tijs Rademakers
|
||||
*/
|
||||
@RestController
|
||||
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
|
||||
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@RequestMapping(value="/modeler/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
|
||||
public ObjectNode getEditorJson(@PathVariable String modelId) {
|
||||
ObjectNode modelNode = null;
|
||||
|
||||
Model model = repositoryService.getModel(modelId);
|
||||
|
||||
if (model != null) {
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(model.getMetaInfo())) {
|
||||
modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
|
||||
} else {
|
||||
modelNode = objectMapper.createObjectNode();
|
||||
modelNode.put(MODEL_NAME, model.getName());
|
||||
}
|
||||
modelNode.put(MODEL_ID, model.getId());
|
||||
ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(
|
||||
new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
|
||||
modelNode.put("model", editorJsonNode);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error creating model JSON", e);
|
||||
throw new ActivitiException("Error creating model JSON", e);
|
||||
}
|
||||
}
|
||||
return modelNode;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeethink.activiti.modeler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.activiti.editor.constants.ModelDataJsonConstants;
|
||||
import org.activiti.engine.ActivitiException;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.repository.Model;
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.image.PNGTranscoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author Tijs Rademakers
|
||||
*/
|
||||
@RestController
|
||||
public class ModelSaveRestResource implements ModelDataJsonConstants {
|
||||
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@RequestMapping(value="/modeler/model/{modelId}/save", method = RequestMethod.POST)
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
public void saveModel(@PathVariable String modelId, @RequestBody MultiValueMap<String, String> values) {
|
||||
try {
|
||||
|
||||
Model model = repositoryService.getModel(modelId);
|
||||
|
||||
ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
|
||||
|
||||
modelJson.put(MODEL_NAME, values.getFirst("name"));
|
||||
modelJson.put(MODEL_DESCRIPTION, values.getFirst("description"));
|
||||
model.setMetaInfo(modelJson.toString());
|
||||
model.setName(values.getFirst("name"));
|
||||
|
||||
repositoryService.saveModel(model);
|
||||
|
||||
repositoryService.addModelEditorSource(model.getId(), values.getFirst("json_xml").getBytes("utf-8"));
|
||||
|
||||
InputStream svgStream = new ByteArrayInputStream(values.getFirst("svg_xml").getBytes("utf-8"));
|
||||
TranscoderInput input = new TranscoderInput(svgStream);
|
||||
|
||||
PNGTranscoder transcoder = new PNGTranscoder();
|
||||
// Setup output
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
TranscoderOutput output = new TranscoderOutput(outStream);
|
||||
|
||||
// Do the transformation
|
||||
transcoder.transcode(input, output);
|
||||
final byte[] result = outStream.toByteArray();
|
||||
repositoryService.addModelEditorSourceExtra(model.getId(), result);
|
||||
outStream.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error saving model", e);
|
||||
throw new ActivitiException("Error saving model", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
package com.jeethink.activiti.modeler;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.jeethink.activiti.domain.ModelerVo;
|
||||
import com.jeethink.common.annotation.Log;
|
||||
import com.jeethink.common.config.JeeThinkConfig;
|
||||
import com.jeethink.common.constant.HttpStatus;
|
||||
import com.jeethink.common.core.controller.BaseController;
|
||||
import com.jeethink.common.core.domain.AjaxResult;
|
||||
import com.jeethink.common.core.page.PageDomain;
|
||||
import com.jeethink.common.core.page.TableDataInfo;
|
||||
import com.jeethink.common.core.page.TableSupport;
|
||||
import com.jeethink.common.enums.BusinessType;
|
||||
|
||||
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.RepositoryService;
|
||||
import org.activiti.engine.impl.persistence.entity.ModelEntityImpl;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.Model;
|
||||
import org.activiti.engine.repository.ModelQuery;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
import static org.activiti.editor.constants.ModelDataJsonConstants.MODEL_DESCRIPTION;
|
||||
import static org.activiti.editor.constants.ModelDataJsonConstants.MODEL_NAME;
|
||||
|
||||
@Controller
|
||||
public class ModelerController extends BaseController {
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
||||
@GetMapping("/modeler/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(ModelEntityImpl modelEntity) {
|
||||
ModelQuery modelQuery = repositoryService.createModelQuery();
|
||||
modelQuery.orderByLastUpdateTime().desc();
|
||||
|
||||
// 条件过滤
|
||||
if (com.jeethink.common.utils.StringUtils.isNotBlank(modelEntity.getKey())) {
|
||||
modelQuery.modelKey(modelEntity.getKey());
|
||||
}
|
||||
if (com.jeethink.common.utils.StringUtils.isNotBlank(modelEntity.getName())) {
|
||||
modelQuery.modelNameLike("%" + modelEntity.getName() + "%");
|
||||
}
|
||||
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Integer pageNum = pageDomain.getPageNum();
|
||||
Integer pageSize = pageDomain.getPageSize();
|
||||
|
||||
List<Model> resultList = modelQuery.listPage((pageNum - 1) * pageSize, pageSize);
|
||||
|
||||
Page<Model> list = new Page<>();
|
||||
list.addAll(resultList);
|
||||
|
||||
list.setTotal(modelQuery.count());
|
||||
list.setPageNum(pageNum);
|
||||
list.setPageSize(pageSize);
|
||||
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建模型
|
||||
*/
|
||||
@RequestMapping(value = "/modeler/create")
|
||||
@ResponseBody
|
||||
public AjaxResult create( @RequestBody ModelerVo modelerVo) {
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ObjectNode editorNode = objectMapper.createObjectNode();
|
||||
editorNode.put("id", "canvas");
|
||||
editorNode.put("resourceId", "canvas");
|
||||
ObjectNode stencilSetNode = objectMapper.createObjectNode();
|
||||
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
|
||||
editorNode.put("stencilset", stencilSetNode);
|
||||
|
||||
ObjectNode modelObjectNode = objectMapper.createObjectNode();
|
||||
modelObjectNode.put(MODEL_NAME, modelerVo.getName());
|
||||
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
|
||||
String description = StringUtils.defaultString(modelerVo.getDescription());
|
||||
modelObjectNode.put(MODEL_DESCRIPTION, description);
|
||||
|
||||
Model newModel = repositoryService.newModel();
|
||||
newModel.setMetaInfo(modelObjectNode.toString());
|
||||
newModel.setName(modelerVo.getName());
|
||||
newModel.setKey(StringUtils.defaultString(modelerVo.getKey()));
|
||||
|
||||
repositoryService.saveModel(newModel);
|
||||
repositoryService.addModelEditorSource(newModel.getId(), editorNode.toString().getBytes("utf-8"));
|
||||
|
||||
return new AjaxResult(HttpStatus.SUCCESS, "创建模型成功", newModel.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("创建模型失败:", e);
|
||||
}
|
||||
return AjaxResult.error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Model部署流程
|
||||
*/
|
||||
@RequestMapping(value = "/modeler/deploy/{modelId}")
|
||||
@ResponseBody
|
||||
public AjaxResult deploy(@PathVariable("modelId") String modelId, RedirectAttributes redirectAttributes) {
|
||||
try {
|
||||
Model modelData = repositoryService.getModel(modelId);
|
||||
ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
|
||||
byte[] bpmnBytes = null;
|
||||
|
||||
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
|
||||
bpmnBytes = new BpmnXMLConverter().convertToXML(model);
|
||||
|
||||
String processName = modelData.getName() + ".bpmn20.xml";
|
||||
Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes, "UTF-8")).deploy();
|
||||
LOGGER.info("部署成功,部署ID=" + deployment.getId());
|
||||
return AjaxResult.success("部署成功");
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("根据模型部署流程失败:modelId={}", modelId, e);
|
||||
|
||||
}
|
||||
return AjaxResult.error("部署失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出model的xml文件
|
||||
*/
|
||||
@RequestMapping(value = "/modeler/export/{modelId}")
|
||||
@ResponseBody
|
||||
public AjaxResult export(@PathVariable("modelId") String modelId) {
|
||||
OutputStream out = null;
|
||||
try {
|
||||
Model modelData = repositoryService.getModel(modelId);
|
||||
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
|
||||
JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
|
||||
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
|
||||
|
||||
// 流程非空判断
|
||||
if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
|
||||
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
|
||||
byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
|
||||
String filename = bpmnModel.getMainProcess().getId() + ".bpmn";
|
||||
|
||||
File file = new File(getAbsoluteFile(filename));
|
||||
if(file.exists()){
|
||||
file.delete();
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(bpmnBytes,0,bpmnBytes.length);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
return AjaxResult.success(filename);
|
||||
} else {
|
||||
return AjaxResult.error();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("导出model的xml文件失败:modelId={}", modelId, e);
|
||||
return AjaxResult.error("导出model的xml文件失败:modelId={}", modelId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*
|
||||
* @param filename 文件名称
|
||||
*/
|
||||
public String getAbsoluteFile(String filename)
|
||||
{
|
||||
String downloadPath = JeeThinkConfig.getDownloadPath() + filename;
|
||||
File desc = new File(downloadPath);
|
||||
if (!desc.getParentFile().exists())
|
||||
{
|
||||
desc.getParentFile().mkdirs();
|
||||
}
|
||||
return downloadPath;
|
||||
}
|
||||
|
||||
|
||||
@Log(title = "流程模型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/modeler/remove/{ids}")
|
||||
@ResponseBody
|
||||
public AjaxResult remove(@PathVariable String ids) {
|
||||
try {
|
||||
repositoryService.deleteModel(ids);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jeethink.activiti.modeler;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.activiti.engine.ActivitiException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
/**
|
||||
* @author Tijs Rademakers
|
||||
*/
|
||||
@RestController
|
||||
public class StencilsetRestResource {
|
||||
|
||||
@RequestMapping(value="/modeler/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
|
||||
public @ResponseBody String getStencilset() {
|
||||
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
|
||||
try {
|
||||
return IOUtils.toString(stencilsetStream, "utf-8");
|
||||
} catch (Exception e) {
|
||||
throw new ActivitiException("Error while loading stencil set", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.jeethink.activiti.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.jeethink.activiti.domain.BizTodoItem;
|
||||
|
||||
/**
|
||||
* 待办事项Service接口
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-11-08
|
||||
*/
|
||||
public interface IBizTodoItemService {
|
||||
/**
|
||||
* 查询待办事项
|
||||
*
|
||||
* @param id 待办事项ID
|
||||
* @return 待办事项
|
||||
*/
|
||||
public BizTodoItem selectBizTodoItemById(Long id);
|
||||
|
||||
/**
|
||||
* 查询待办事项列表
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 待办事项集合
|
||||
*/
|
||||
public List<BizTodoItem> selectBizTodoItemList(BizTodoItem bizTodoItem);
|
||||
|
||||
/**
|
||||
* 新增待办事项
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBizTodoItem(BizTodoItem bizTodoItem);
|
||||
|
||||
/**
|
||||
* 修改待办事项
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBizTodoItem(BizTodoItem bizTodoItem);
|
||||
|
||||
/**
|
||||
* 批量删除待办事项
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBizTodoItemByIds(String ids);
|
||||
|
||||
/**
|
||||
* 删除待办事项信息
|
||||
*
|
||||
* @param id 待办事项ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBizTodoItemById(Long id);
|
||||
|
||||
int insertTodoItem(String instanceId, String itemName, String itemContent, String module);
|
||||
|
||||
BizTodoItem selectBizTodoItemByCondition(String taskId, String todoUserId);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.jeethink.activiti.service;
|
||||
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
|
||||
import com.jeethink.activiti.domain.ActivitiBaseEntity;
|
||||
import com.jeethink.activiti.domain.HistoricActivity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IProcessService {
|
||||
|
||||
/**
|
||||
* 查询审批历史列表
|
||||
* @param processInstanceId
|
||||
* @param historicActivity
|
||||
* @return
|
||||
*/
|
||||
List<HistoricActivity> selectHistoryList(String processInstanceId, HistoricActivity historicActivity);
|
||||
|
||||
/**
|
||||
* 提交申请
|
||||
* @param applyUserId 申请人
|
||||
* @param businessKey 业务表 id
|
||||
* @param key 流程定义 key
|
||||
* @param variables 流程变量
|
||||
* @return
|
||||
*/
|
||||
ProcessInstance submitApply(String applyUserId, String businessKey, String itemName, String itemConent, String key, Map<String, Object> variables);
|
||||
|
||||
List<Task> findTodoTasks(String userId, String key);
|
||||
|
||||
List<HistoricTaskInstance> findDoneTasks(String userId, String key);
|
||||
|
||||
void complete(ActivitiBaseEntity activitiBaseEntity, String module);
|
||||
|
||||
/**
|
||||
* 委托任务
|
||||
* @param taskId
|
||||
* @param delegateToUser
|
||||
*/
|
||||
void delegate(String taskId, String fromUser, String delegateToUser);
|
||||
|
||||
void cancelApply(String instanceId, String deleteReason);
|
||||
|
||||
void suspendOrActiveApply(String instanceId, String suspendState);
|
||||
|
||||
String findBusinessKeyByInstanceId(String instanceId);
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
package com.jeethink.activiti.service;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.jeethink.common.core.page.PageDomain;
|
||||
import com.jeethink.common.core.page.TableSupport;
|
||||
import com.jeethink.common.core.text.Convert;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
@Transactional
|
||||
@Service
|
||||
public class ProcessDefinitionService {
|
||||
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
/**
|
||||
* 分页查询流程定义文件
|
||||
* @return
|
||||
*/
|
||||
public Page<com.jeethink.activiti.domain.ProcessDefinition> listProcessDefinition(com.jeethink.activiti.domain.ProcessDefinition processDefinition) {
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Integer pageNum = pageDomain.getPageNum();
|
||||
Integer pageSize = pageDomain.getPageSize();
|
||||
|
||||
Page<com.jeethink.activiti.domain.ProcessDefinition> list = new Page<>();
|
||||
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
|
||||
processDefinitionQuery.orderByProcessDefinitionId().orderByProcessDefinitionVersion().desc();
|
||||
if (StringUtils.isNotBlank(processDefinition.getName())) {
|
||||
processDefinitionQuery.processDefinitionNameLike("%" + processDefinition.getName() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(processDefinition.getKey())) {
|
||||
processDefinitionQuery.processDefinitionKeyLike("%" + processDefinition.getKey() + "%");
|
||||
}
|
||||
if (StringUtils.isNotBlank(processDefinition.getCategory())) {
|
||||
processDefinitionQuery.processDefinitionCategoryLike("%" + processDefinition.getCategory() + "%");
|
||||
}
|
||||
|
||||
List<ProcessDefinition> processDefinitionList;
|
||||
if (pageNum != null && pageSize != null) {
|
||||
processDefinitionList = processDefinitionQuery.listPage((pageNum - 1) * pageSize, pageSize);
|
||||
list.setTotal(processDefinitionQuery.count());
|
||||
list.setPageNum(pageNum);
|
||||
list.setPageSize(pageSize);
|
||||
} else {
|
||||
processDefinitionList = processDefinitionQuery.list();
|
||||
}
|
||||
for (ProcessDefinition definition: processDefinitionList) {
|
||||
ProcessDefinitionEntityImpl entityImpl = (ProcessDefinitionEntityImpl) definition;
|
||||
com.jeethink.activiti.domain.ProcessDefinition entity = new com.jeethink.activiti.domain.ProcessDefinition();
|
||||
entity.setId(definition.getId());
|
||||
entity.setKey(definition.getKey());
|
||||
entity.setName(definition.getName());
|
||||
entity.setCategory(definition.getCategory());
|
||||
entity.setVersion(definition.getVersion());
|
||||
entity.setDescription(definition.getDescription());
|
||||
entity.setDeploymentId(definition.getDeploymentId());
|
||||
Deployment deployment = repositoryService.createDeploymentQuery()
|
||||
.deploymentId(definition.getDeploymentId())
|
||||
.singleResult();
|
||||
entity.setDeploymentTime(deployment.getDeploymentTime());
|
||||
entity.setDiagramResourceName(definition.getDiagramResourceName());
|
||||
entity.setResourceName(definition.getResourceName());
|
||||
entity.setSuspendState(entityImpl.getSuspensionState() + "");
|
||||
if (entityImpl.getSuspensionState() == 1) {
|
||||
entity.setSuspendStateName("已激活");
|
||||
} else {
|
||||
entity.setSuspendStateName("已挂起");
|
||||
}
|
||||
list.add(entity);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void deployProcessDefinition(String filePath) throws FileNotFoundException {
|
||||
if (StringUtils.isNotBlank(filePath)) {
|
||||
if (filePath.endsWith(".zip")) {
|
||||
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(filePath));
|
||||
repositoryService.createDeployment()
|
||||
.addZipInputStream(inputStream)
|
||||
.deploy();
|
||||
} else if (filePath.endsWith(".bpmn")) {
|
||||
repositoryService.createDeployment()
|
||||
.addInputStream(filePath, new FileInputStream(filePath))
|
||||
.deploy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int deleteProcessDeploymentByIds(String deploymentIds) throws Exception {
|
||||
String[] deploymentIdsArr = Convert.toStrArray(deploymentIds);
|
||||
int counter = 0;
|
||||
for (String deploymentId: deploymentIdsArr) {
|
||||
List<ProcessInstance> instanceList = runtimeService.createProcessInstanceQuery()
|
||||
.deploymentId(deploymentId)
|
||||
.list();
|
||||
if (!CollectionUtils.isEmpty(instanceList)) {
|
||||
// 存在流程实例的流程定义
|
||||
throw new Exception("删除失败,存在运行中的流程实例");
|
||||
}
|
||||
repositoryService.deleteDeployment(deploymentId, true); // true 表示级联删除引用,比如 act_ru_execution 数据
|
||||
counter++;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
public void suspendOrActiveApply(String id, String suspendState) {
|
||||
if ("1".equals(suspendState)) {
|
||||
// 当流程定义被挂起时,已经发起的该流程定义的流程实例不受影响(如果选择级联挂起则流程实例也会被挂起)。
|
||||
// 当流程定义被挂起时,无法发起新的该流程定义的流程实例。
|
||||
// 直观变化:act_re_procdef 的 SUSPENSION_STATE_ 为 2
|
||||
repositoryService.suspendProcessDefinitionById(id);
|
||||
} else if ("2".equals(suspendState)) {
|
||||
repositoryService.activateProcessDefinitionById(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package com.jeethink.activiti.service.impl;
|
||||
|
||||
import com.jeethink.activiti.domain.BizTodoItem;
|
||||
import com.jeethink.activiti.mapper.BizTodoItemMapper;
|
||||
import com.jeethink.activiti.service.IBizTodoItemService;
|
||||
import com.jeethink.common.core.domain.entity.SysUser;
|
||||
import com.jeethink.common.core.text.Convert;
|
||||
import com.jeethink.common.utils.DateUtils;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
import com.jeethink.system.mapper.SysUserMapper;
|
||||
|
||||
import org.activiti.engine.TaskService;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 待办事项Service业务层处理
|
||||
*
|
||||
* @author Xianlu Tech
|
||||
* @date 2019-11-08
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class BizTodoItemServiceImpl implements IBizTodoItemService {
|
||||
@Autowired
|
||||
private BizTodoItemMapper bizTodoItemMapper;
|
||||
@Autowired
|
||||
private SysUserMapper userMapper;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
|
||||
/**
|
||||
* 查询待办事项
|
||||
*
|
||||
* @param id 待办事项ID
|
||||
* @return 待办事项
|
||||
*/
|
||||
@Override
|
||||
public BizTodoItem selectBizTodoItemById(Long id) {
|
||||
return bizTodoItemMapper.selectBizTodoItemById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询待办事项列表
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 待办事项
|
||||
*/
|
||||
@Override
|
||||
public List<BizTodoItem> selectBizTodoItemList(BizTodoItem bizTodoItem) {
|
||||
return bizTodoItemMapper.selectBizTodoItemList(bizTodoItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增待办事项
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBizTodoItem(BizTodoItem bizTodoItem) {
|
||||
return bizTodoItemMapper.insertBizTodoItem(bizTodoItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改待办事项
|
||||
*
|
||||
* @param bizTodoItem 待办事项
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBizTodoItem(BizTodoItem bizTodoItem) {
|
||||
return bizTodoItemMapper.updateBizTodoItem(bizTodoItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除待办事项对象
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBizTodoItemByIds(String ids) {
|
||||
return bizTodoItemMapper.deleteBizTodoItemByIds(Convert.toStrArray(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除待办事项信息
|
||||
*
|
||||
* @param id 待办事项ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBizTodoItemById(Long id) {
|
||||
return bizTodoItemMapper.deleteBizTodoItemById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTodoItem(String instanceId, String itemName, String itemContent, String module) {
|
||||
BizTodoItem todoItem = new BizTodoItem();
|
||||
todoItem.setItemName(itemName);
|
||||
todoItem.setItemContent(itemContent);
|
||||
todoItem.setIsView("0");
|
||||
todoItem.setIsHandle("0");
|
||||
todoItem.setModule(module);
|
||||
todoItem.setTodoTime(DateUtils.getNowDate());
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceId(instanceId).active().list();
|
||||
int counter = 0;
|
||||
for (Task task: taskList) {
|
||||
|
||||
// todoitem 去重
|
||||
BizTodoItem bizTodoItem = bizTodoItemMapper.selectTodoItemByTaskId(task.getId());
|
||||
if (bizTodoItem != null) continue;
|
||||
|
||||
BizTodoItem newItem = new BizTodoItem();
|
||||
BeanUtils.copyProperties(todoItem, newItem);
|
||||
newItem.setInstanceId(instanceId);
|
||||
newItem.setTaskId(task.getId());
|
||||
newItem.setTaskName("task" + task.getTaskDefinitionKey().substring(0, 1).toUpperCase() + task.getTaskDefinitionKey().substring(1));
|
||||
newItem.setNodeName(task.getName());
|
||||
String assignee = task.getAssignee();
|
||||
if (StringUtils.isNotBlank(assignee)) {
|
||||
newItem.setTodoUserId(assignee);
|
||||
SysUser user = userMapper.selectUserByUserName(assignee);
|
||||
newItem.setTodoUserName(user.getNickName());
|
||||
bizTodoItemMapper.insertBizTodoItem(newItem);
|
||||
counter++;
|
||||
} else {
|
||||
// 查询候选用户组
|
||||
List<String> todoUserIdList = bizTodoItemMapper.selectTodoUserListByTaskId(task.getId());
|
||||
if (!CollectionUtils.isEmpty(todoUserIdList)) {
|
||||
for (String todoUserId: todoUserIdList) {
|
||||
SysUser todoUser = userMapper.selectUserByUserName(todoUserId);
|
||||
newItem.setTodoUserId(todoUser.getUserName());
|
||||
newItem.setTodoUserName(todoUser.getNickName());
|
||||
bizTodoItemMapper.insertBizTodoItem(newItem);
|
||||
counter++;
|
||||
}
|
||||
} else {
|
||||
// 查询候选用户
|
||||
String todoUserId = bizTodoItemMapper.selectTodoUserByTaskId(task.getId());
|
||||
SysUser todoUser = userMapper.selectUserByUserName(todoUserId);
|
||||
newItem.setTodoUserId(todoUser.getUserName());
|
||||
newItem.setTodoUserName(todoUser.getNickName());
|
||||
bizTodoItemMapper.insertBizTodoItem(newItem);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BizTodoItem selectBizTodoItemByCondition(String taskId, String todoUserId) {
|
||||
return bizTodoItemMapper.selectTodoItemByCondition(taskId, todoUserId);
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
package com.jeethink.activiti.service.impl;
|
||||
|
||||
import com.jeethink.activiti.domain.ActivitiBaseEntity;
|
||||
import com.jeethink.activiti.domain.BizTodoItem;
|
||||
import com.jeethink.activiti.domain.HistoricActivity;
|
||||
import com.jeethink.activiti.service.IBizTodoItemService;
|
||||
import com.jeethink.activiti.service.IProcessService;
|
||||
import com.jeethink.common.core.domain.entity.SysUser;
|
||||
import com.jeethink.common.utils.DateUtils;
|
||||
import com.jeethink.common.utils.SecurityUtils;
|
||||
import com.jeethink.common.utils.StringUtils;
|
||||
import com.jeethink.system.mapper.SysUserMapper;
|
||||
|
||||
import org.activiti.engine.HistoryService;
|
||||
import org.activiti.engine.IdentityService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.TaskService;
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricActivityInstanceQuery;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Comment;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class ProcessServiceImpl implements IProcessService {
|
||||
protected final Logger logger = LoggerFactory.getLogger(ProcessServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
private IdentityService identityService;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private SysUserMapper userMapper;
|
||||
@Autowired
|
||||
private IBizTodoItemService bizTodoItemService;
|
||||
|
||||
@Override
|
||||
public ProcessInstance submitApply(String applyUserId, String businessKey, String itemName, String itemConent, String module, Map<String, Object> variables) {
|
||||
// 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
|
||||
identityService.setAuthenticatedUserId(applyUserId);
|
||||
// 启动流程时设置业务 key
|
||||
ProcessInstance instance = runtimeService.startProcessInstanceByKey(module, businessKey, variables);
|
||||
// 下一节点处理人待办事项
|
||||
bizTodoItemService.insertTodoItem(instance.getProcessInstanceId(), itemName, itemConent, module);
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> findTodoTasks(String userId, String key) {
|
||||
List<Task> tasks = new ArrayList<Task>();
|
||||
// 根据当前人的ID查询
|
||||
List<Task> todoList = taskService
|
||||
.createTaskQuery()
|
||||
.processDefinitionKey(key)
|
||||
.taskAssignee(userId)
|
||||
.list();
|
||||
// 根据当前人未签收的任务
|
||||
List<Task> unsignedTasks = taskService
|
||||
.createTaskQuery()
|
||||
.processDefinitionKey(key)
|
||||
.taskCandidateUser(userId)
|
||||
.list();
|
||||
// 合并
|
||||
tasks.addAll(todoList);
|
||||
tasks.addAll(unsignedTasks);
|
||||
return tasks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricTaskInstance> findDoneTasks(String userId, String key) {
|
||||
List<HistoricTaskInstance> list = historyService
|
||||
.createHistoricTaskInstanceQuery()
|
||||
.processDefinitionKey(key)
|
||||
.taskAssignee(userId)
|
||||
.finished()
|
||||
.orderByHistoricTaskInstanceEndTime()
|
||||
.desc()
|
||||
.list();
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(ActivitiBaseEntity activitiBaseEntity,String module) {
|
||||
Map<String, Object> variables =new HashMap<String, Object>();
|
||||
String comment = null; // 批注
|
||||
boolean agree = true;
|
||||
try {
|
||||
for(Map.Entry<String, Object> entry : activitiBaseEntity.getProcessParams().entrySet()){
|
||||
String parameterName = entry.getKey();
|
||||
// 参数结构:B_name,B为类型,name为属性名称
|
||||
String[] parameter = parameterName.split("_");
|
||||
if (parameter.length == 2) {
|
||||
String paramValue = (String) entry.getValue();
|
||||
Object value = paramValue;
|
||||
if (parameter[0].equals("B")) {
|
||||
value = BooleanUtils.toBoolean(paramValue);
|
||||
agree = (boolean) value;
|
||||
} else if (parameter[0].equals("DT")) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
value = sdf.parse(paramValue);
|
||||
} else if (parameter[0].equals("COM")) {
|
||||
comment = paramValue;
|
||||
}
|
||||
variables.put(parameter[1], value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (StringUtils.isNotEmpty(comment)) {
|
||||
identityService.setAuthenticatedUserId(SecurityUtils.getUsername());
|
||||
comment = agree ? "【同意】" + comment : "【拒绝】" + comment;
|
||||
taskService.addComment(activitiBaseEntity.getTaskId(), activitiBaseEntity.getInstanceId(), comment);
|
||||
}
|
||||
// 被委派人处理完成任务
|
||||
// p.s. 被委托的流程需要先 resolved 这个任务再提交。
|
||||
// 所以在 complete 之前需要先 resolved
|
||||
// resolveTask() 要在 claim() 之前,不然 act_hi_taskinst 表的 assignee 字段会为 null
|
||||
taskService.resolveTask(activitiBaseEntity.getTaskId(), variables);
|
||||
// 只有签收任务,act_hi_taskinst 表的 assignee 字段才不为 null
|
||||
taskService.claim(activitiBaseEntity.getTaskId(), SecurityUtils.getUsername());
|
||||
taskService.complete(activitiBaseEntity.getTaskId(), variables);
|
||||
|
||||
// 更新待办事项状态
|
||||
BizTodoItem query = new BizTodoItem();
|
||||
query.setTaskId(activitiBaseEntity.getTaskId());
|
||||
// 考虑到候选用户组,会有多个 todoitem 办理同个 task
|
||||
List<BizTodoItem> updateList = CollectionUtils.isEmpty(bizTodoItemService.selectBizTodoItemList(query)) ? null : bizTodoItemService.selectBizTodoItemList(query);
|
||||
for (BizTodoItem update: updateList) {
|
||||
// 找到当前登录用户的 todoitem,置为已办
|
||||
if (update.getTodoUserId().equals(SecurityUtils.getUsername())) {
|
||||
update.setIsView("1");
|
||||
update.setIsHandle("1");
|
||||
update.setHandleUserId(SecurityUtils.getUsername());
|
||||
update.setHandleUserName(SecurityUtils.getNickName());
|
||||
update.setHandleTime(DateUtils.getNowDate());
|
||||
bizTodoItemService.updateBizTodoItem(update);
|
||||
} else {
|
||||
bizTodoItemService.deleteBizTodoItemById(update.getId()); // 删除候选用户组其他 todoitem
|
||||
}
|
||||
}
|
||||
|
||||
// 下一节点处理人待办事项
|
||||
bizTodoItemService.insertTodoItem(activitiBaseEntity.getInstanceId(),activitiBaseEntity.getTitle(),activitiBaseEntity.getReason(), module);
|
||||
} catch (Exception e) {
|
||||
logger.error("error on complete task {}, variables={}", new Object[]{activitiBaseEntity.getTaskId(), variables, e});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricActivity> selectHistoryList(String processInstanceId, HistoricActivity historicActivity) {
|
||||
// PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
// Integer pageNum = pageDomain.getPageNum();
|
||||
// Integer pageSize = pageDomain.getPageSize();
|
||||
List<HistoricActivity> activityList = new ArrayList<>();
|
||||
HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery();
|
||||
if (StringUtils.isNotBlank(historicActivity.getAssignee())) {
|
||||
query.taskAssignee(historicActivity.getAssignee());
|
||||
}
|
||||
if (StringUtils.isNotBlank(historicActivity.getActivityName())) {
|
||||
query.activityName(historicActivity.getActivityName());
|
||||
}
|
||||
List<HistoricActivityInstance> list = query.processInstanceId(processInstanceId)
|
||||
.activityType("userTask")
|
||||
.finished()
|
||||
.orderByHistoricActivityInstanceStartTime()
|
||||
.desc()
|
||||
.list();
|
||||
// .listPage((pageNum - 1) * pageSize, pageNum * pageSize);
|
||||
list.forEach(instance -> {
|
||||
HistoricActivity activity = new HistoricActivity();
|
||||
BeanUtils.copyProperties(instance, activity);
|
||||
String taskId = instance.getTaskId();
|
||||
List<Comment> comment = taskService.getTaskComments(taskId, "comment");
|
||||
if (!CollectionUtils.isEmpty(comment)) {
|
||||
activity.setComment(comment.get(0).getFullMessage());
|
||||
}
|
||||
SysUser sysUser = userMapper.selectUserByUserName(instance.getAssignee());
|
||||
if (sysUser != null) {
|
||||
activity.setAssigneeName(sysUser.getUserName());
|
||||
}
|
||||
activityList.add(activity);
|
||||
});
|
||||
return activityList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delegate(String taskId, String fromUser, String delegateToUser) {
|
||||
taskService.delegateTask(taskId, delegateToUser);
|
||||
// 更新待办事项
|
||||
// BizTodoItem updateItem = bizTodoItemService.selectBizTodoItemByCondition(taskId, fromUser);
|
||||
// if (updateItem != null) {
|
||||
// SysUser todoUser = userMapper.selectUserByLoginName(delegateToUser);
|
||||
// updateItem.setTodoUserId(delegateToUser);
|
||||
// updateItem.setTodoUserName(todoUser.getUserName());
|
||||
// bizTodoItemService.updateBizTodoItem(updateItem);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelApply(String instanceId, String deleteReason) {
|
||||
// 执行此方法后未审批的任务 act_ru_task 会被删除,流程历史 act_hi_taskinst 不会被删除,并且流程历史的状态为finished完成
|
||||
runtimeService.deleteProcessInstance(instanceId, deleteReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspendOrActiveApply(String instanceId, String suspendState) {
|
||||
if ("1".equals(suspendState)) {
|
||||
// 当流程实例被挂起时,无法通过下一个节点对应的任务id来继续这个流程实例。
|
||||
// 通过挂起某一特定的流程实例,可以终止当前的流程实例,而不影响到该流程定义的其他流程实例。
|
||||
// 激活之后可以继续该流程实例,不会对后续任务造成影响。
|
||||
// 直观变化:act_ru_task 的 SUSPENSION_STATE_ 为 2
|
||||
runtimeService.suspendProcessInstanceById(instanceId);
|
||||
} else if ("2".equals(suspendState)) {
|
||||
runtimeService.activateProcessInstanceById(instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findBusinessKeyByInstanceId(String instanceId) {
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
|
||||
if (processInstance == null) {
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(instanceId)
|
||||
.singleResult();
|
||||
return historicProcessInstance.getBusinessKey();
|
||||
} else {
|
||||
return processInstance.getBusinessKey();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
<?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.jeethink.activiti.mapper.BizTodoItemMapper">
|
||||
|
||||
<resultMap type="BizTodoItem" id="BizTodoItemResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="itemName" column="item_name" />
|
||||
<result property="itemContent" column="item_content" />
|
||||
<result property="module" column="module" />
|
||||
<result property="instanceId" column="instance_id" />
|
||||
<result property="taskId" column="task_id" />
|
||||
<result property="taskName" column="task_name" />
|
||||
<result property="nodeName" column="node_name" />
|
||||
<result property="isView" column="is_view" />
|
||||
<result property="isHandle" column="is_handle" />
|
||||
<result property="todoUserId" column="todo_user_id" />
|
||||
<result property="todoUserName" column="todo_user_name" />
|
||||
<result property="handleUserId" column="handle_user_id" />
|
||||
<result property="handleUserName" column="handle_user_name" />
|
||||
<result property="todoTime" column="todo_time" />
|
||||
<result property="handleTime" column="handle_time" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectBizTodoItemVo">
|
||||
select id, item_name, item_content, module, instance_id, task_id, task_name, node_name, is_view, is_handle, todo_user_id, todo_user_name, handle_user_id, handle_user_name, todo_time, handle_time from biz_todo_item
|
||||
</sql>
|
||||
|
||||
<select id="selectBizTodoItemList" parameterType="BizTodoItem" resultMap="BizTodoItemResult">
|
||||
<include refid="selectBizTodoItemVo"/>
|
||||
<where>
|
||||
<if test="itemName != null and itemName != ''"> and item_name like concat('%', #{itemName}, '%')</if>
|
||||
<if test="itemContent != null and itemContent != ''"> and item_content = #{itemContent}</if>
|
||||
<if test="module != null and module != ''"> and module = #{module}</if>
|
||||
<if test="instanceId != null and instanceId != ''"> and instance_id = #{instanceId}</if>
|
||||
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if>
|
||||
<if test="taskName != null and taskName != ''"> and task_name like concat('%', #{taskName}, '%')</if>
|
||||
<if test="nodeName != null and nodeName != ''"> and node_name like concat('%', #{nodeName}, '%')</if>
|
||||
<if test="isView != null and isView != ''"> and is_view = #{isView}</if>
|
||||
<if test="isHandle != null and isHandle != ''"> and is_handle = #{isHandle}</if>
|
||||
<if test="todoUserId != null and todoUserId != ''"> and todo_user_id like concat('%', #{todoUserId}, '%')</if>
|
||||
<if test="todoUserName != null and todoUserName != ''"> and todo_user_name like concat('%', #{todoUserName}, '%')</if>
|
||||
<if test="handleUserId != null and handleUserId != ''"> and handle_user_id like concat('%', #{handleUserId}, '%')</if>
|
||||
<if test="handleUserName != null and handleUserName != ''"> and handle_user_name like concat('%', #{handleUserName}, '%')</if>
|
||||
<if test="todoTime != null "> and todo_time = #{todoTime}</if>
|
||||
<if test="handleTime != null "> and handle_time = #{handleTime}</if>
|
||||
<if test="params.todoItemStartTime != null and params.todoItemStartTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(todo_time,'%y%m%d') >= date_format(#{params.todoItemStartTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="params.todoItemEndTime != null and params.todoItemEndTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(todo_time,'%y%m%d') <= date_format(#{params.todoItemEndTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="params.handleStartTime != null and params.handleStartTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(handle_time,'%y%m%d') >= date_format(#{params.handleStartTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="params.handleEndTime != null and params.handleEndTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(handle_time,'%y%m%d') <= date_format(#{params.handleEndTime},'%y%m%d')
|
||||
</if>
|
||||
order by todo_time desc
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectBizTodoItemById" parameterType="Long" resultMap="BizTodoItemResult">
|
||||
<include refid="selectBizTodoItemVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertBizTodoItem" parameterType="BizTodoItem" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into biz_todo_item
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="itemName != null and itemName != ''">item_name,</if>
|
||||
<if test="itemContent != null and itemContent != ''">item_content,</if>
|
||||
<if test="module != null and module != ''">module,</if>
|
||||
<if test="instanceId != null and instanceId != ''">instance_id,</if>
|
||||
<if test="taskId != null and taskId != ''">task_id,</if>
|
||||
<if test="taskName != null and taskName != ''">task_name,</if>
|
||||
<if test="nodeName != null and nodeName != ''">node_name,</if>
|
||||
<if test="isView != null and isView != ''">is_view,</if>
|
||||
<if test="isHandle != null and isHandle != ''">is_handle,</if>
|
||||
<if test="todoUserId != null ">todo_user_id,</if>
|
||||
<if test="todoUserName != null and todoUserName != ''">todo_user_name,</if>
|
||||
<if test="handleUserId != null ">handle_user_id,</if>
|
||||
<if test="handleUserName != null and handleUserName != ''">handle_user_name,</if>
|
||||
<if test="todoTime != null ">todo_time,</if>
|
||||
<if test="handleTime != null ">handle_time,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="itemName != null and itemName != ''">#{itemName},</if>
|
||||
<if test="itemContent != null and itemContent != ''">#{itemContent},</if>
|
||||
<if test="module != null and module != ''">#{module},</if>
|
||||
<if test="instanceId != null and instanceId != ''">#{instanceId},</if>
|
||||
<if test="taskId != null and taskId != ''">#{taskId},</if>
|
||||
<if test="taskName != null and taskName != ''">#{taskName},</if>
|
||||
<if test="nodeName != null and nodeName != ''">#{nodeName},</if>
|
||||
<if test="isView != null and isView != ''">#{isView},</if>
|
||||
<if test="isHandle != null and isHandle != ''">#{isHandle},</if>
|
||||
<if test="todoUserId != null ">#{todoUserId},</if>
|
||||
<if test="todoUserName != null and todoUserName != ''">#{todoUserName},</if>
|
||||
<if test="handleUserId != null ">#{handleUserId},</if>
|
||||
<if test="handleUserName != null and handleUserName != ''">#{handleUserName},</if>
|
||||
<if test="todoTime != null ">#{todoTime},</if>
|
||||
<if test="handleTime != null ">#{handleTime},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateBizTodoItem" parameterType="BizTodoItem">
|
||||
update biz_todo_item
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="itemName != null and itemName != ''">item_name = #{itemName},</if>
|
||||
<if test="itemContent != null and itemContent != ''">item_content = #{itemContent},</if>
|
||||
<if test="module != null and module != ''">module = #{module},</if>
|
||||
<if test="instanceId != null and instanceId != ''">instance_id = #{instanceId},</if>
|
||||
<if test="taskId != null and taskId != ''">task_id = #{taskId},</if>
|
||||
<if test="taskName != null and taskName != ''">task_name = #{taskName},</if>
|
||||
<if test="nodeName != null and nodeName != ''">node_name = #{nodeName},</if>
|
||||
<if test="isView != null and isView != ''">is_view = #{isView},</if>
|
||||
<if test="isHandle != null and isHandle != ''">is_handle = #{isHandle},</if>
|
||||
<if test="todoUserId != null ">todo_user_id = #{todoUserId},</if>
|
||||
<if test="todoUserName != null and todoUserName != ''">todo_user_name = #{todoUserName},</if>
|
||||
<if test="handleUserId != null ">handle_user_id = #{handleUserId},</if>
|
||||
<if test="handleUserName != null and handleUserName != ''">handle_user_name = #{handleUserName},</if>
|
||||
<if test="todoTime != null ">todo_time = #{todoTime},</if>
|
||||
<if test="handleTime != null ">handle_time = #{handleTime},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteBizTodoItemById" parameterType="Long">
|
||||
delete from biz_todo_item where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteBizTodoItemByIds" parameterType="String">
|
||||
delete from biz_todo_item where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
1319
JeeThink-activiti/src/main/resources/stencilset.json
Normal file
1319
JeeThink-activiti/src/main/resources/stencilset.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user