Skip to content

Commit f9f3181

Browse files
author
rstyro
committed
工作流demo
1 parent 1b7bee1 commit f9f3181

14 files changed

Lines changed: 841 additions & 0 deletions

File tree

springboot-camunda/.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/mvnw text eol=lf
2+
*.cmd text eol=crlf

springboot-camunda/.gitignore

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
HELP.md
2+
target/
3+
.mvn/wrapper/maven-wrapper.jar
4+
!**/src/main/**/target/
5+
!**/src/test/**/target/
6+
7+
### STS ###
8+
.apt_generated
9+
.classpath
10+
.factorypath
11+
.project
12+
.settings
13+
.springBeans
14+
.sts4-cache
15+
16+
### IntelliJ IDEA ###
17+
.idea
18+
*.iws
19+
*.iml
20+
*.ipr
21+
22+
### NetBeans ###
23+
/nbproject/private/
24+
/nbbuild/
25+
/dist/
26+
/nbdist/
27+
/.nb-gradle/
28+
build/
29+
!**/src/main/**/build/
30+
!**/src/test/**/build/
31+
32+
### VS Code ###
33+
.vscode/

springboot-camunda/pom.xml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>3.5.6</version>
9+
<relativePath/>
10+
</parent>
11+
<groupId>top.lrshuai.camunda</groupId>
12+
<artifactId>springboot-camunda</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<name>springboot-camunda</name>
15+
<description>springboot-camunda</description>
16+
17+
<properties>
18+
<java.version>17</java.version>
19+
<camunda.version>7.21.0</camunda.version>
20+
<mysql.version>8.3.0</mysql.version>
21+
<lombok.version>1.18.30</lombok.version>
22+
</properties>
23+
24+
<dependencies>
25+
<dependency>
26+
<groupId>org.springframework.boot</groupId>
27+
<artifactId>spring-boot-starter-web</artifactId>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>org.camunda.bpm.springboot</groupId>
32+
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
33+
<version>${camunda.version}</version>
34+
</dependency>
35+
<!-- Camunda 提供的 Web 界面(如 Tasklist、Cockpit) -->
36+
<dependency>
37+
<groupId>org.camunda.bpm.springboot</groupId>
38+
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
39+
<version>${camunda.version}</version>
40+
</dependency>
41+
42+
<!-- 扩展和可选 提供REST API,允许外部应用通过HTTP协议与引擎交互 -->
43+
<dependency>
44+
<groupId>org.camunda.bpm.springboot</groupId>
45+
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
46+
<version>${camunda.version}</version>
47+
</dependency>
48+
49+
<!-- Mysql Connector -->
50+
<dependency>
51+
<groupId>com.mysql</groupId>
52+
<artifactId>mysql-connector-j</artifactId>
53+
<version>${mysql.version}</version>
54+
</dependency>
55+
56+
<dependency>
57+
<groupId>org.projectlombok</groupId>
58+
<artifactId>lombok</artifactId>
59+
<version>${lombok.version}</version>
60+
</dependency>
61+
62+
<dependency>
63+
<groupId>org.springframework.boot</groupId>
64+
<artifactId>spring-boot-starter-test</artifactId>
65+
<scope>test</scope>
66+
</dependency>
67+
68+
</dependencies>
69+
70+
<build>
71+
<plugins>
72+
<plugin>
73+
<groupId>org.springframework.boot</groupId>
74+
<artifactId>spring-boot-maven-plugin</artifactId>
75+
</plugin>
76+
</plugins>
77+
</build>
78+
79+
</project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package top.lrshuai.camunda;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
import org.springframework.context.ConfigurableApplicationContext;
7+
import org.springframework.core.env.Environment;
8+
9+
@Slf4j
10+
@SpringBootApplication
11+
public class SpringbootCamundaApplication {
12+
13+
public static void main(String[] args) {
14+
ConfigurableApplicationContext application = SpringApplication.run(SpringbootCamundaApplication.class, args);
15+
Environment env = application.getEnvironment();
16+
// String ip = NetUtil.getLocalhostStr();
17+
String ip = "127.0.0.1";
18+
String port = env.getProperty("server.port");
19+
String contextPath = env.getProperty("server.servlet.context-path","");
20+
String banner = """
21+
\n\t
22+
----------------------------------------------------------
23+
SpringbootCamundaApplication is running! Access URLs:
24+
Local: \t\thttp://localhost:%s%s/
25+
External: \thttp://%s:%s%s/
26+
----------------------------------------------------------
27+
""".formatted(port, contextPath, ip, port, contextPath);
28+
log.info(banner);
29+
}
30+
31+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package top.lrshuai.camunda.config;
2+
3+
import jakarta.annotation.Resource;
4+
import org.camunda.bpm.engine.RepositoryService;
5+
import org.springframework.boot.CommandLineRunner;
6+
import org.springframework.stereotype.Component;
7+
8+
//@Component
9+
public class ProcessAutoDeployerConfig implements CommandLineRunner {
10+
11+
@Resource
12+
private RepositoryService repositoryService;
13+
14+
@Override
15+
public void run(String... args) throws Exception {
16+
// 自动部署resources目录下的BPMN文件
17+
repositoryService.createDeployment()
18+
.name("LeaveProcessDeployment")
19+
.addClasspathResource("process/leave.bpmn") // 替换为您的BPMN文件路径
20+
.deploy();
21+
22+
System.out.println("流程部署完成");
23+
}
24+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package top.lrshuai.camunda.controller;
2+
3+
import jakarta.annotation.Resource;
4+
import org.camunda.bpm.engine.HistoryService;
5+
import org.camunda.bpm.engine.IdentityService;
6+
import org.camunda.bpm.engine.RuntimeService;
7+
import org.camunda.bpm.engine.TaskService;
8+
import org.camunda.bpm.engine.history.HistoricActivityInstance;
9+
import org.camunda.bpm.engine.history.HistoricProcessInstance;
10+
import org.camunda.bpm.engine.task.Task;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.web.bind.annotation.*;
13+
import top.lrshuai.camunda.dto.LeaveApplicationDto;
14+
15+
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.stream.Collectors;
19+
20+
@RestController
21+
@RequestMapping("/api/leave")
22+
public class LeaveProcessController {
23+
24+
@Resource
25+
private RuntimeService runtimeService;
26+
27+
@Resource
28+
private TaskService taskService;
29+
30+
@Resource
31+
private HistoryService historyService;
32+
33+
@Resource
34+
private IdentityService identityService;
35+
36+
/**
37+
* 启动请假流程
38+
*/
39+
@PostMapping("/start")
40+
public ResponseEntity<Map<String, Object>> startLeaveProcess(@RequestBody LeaveApplicationDto application) {
41+
try {
42+
// 设置流程启动者
43+
identityService.setAuthenticatedUserId(application.getApplicant());
44+
45+
Map<String, Object> variables = new HashMap<>();
46+
variables.put("applicant", application.getApplicant());
47+
variables.put("leaveType", application.getLeaveType());
48+
variables.put("startDate", application.getStartDate());
49+
variables.put("endDate", application.getEndDate());
50+
variables.put("leaveDays", application.getLeaveDays());
51+
variables.put("reason", application.getReason());
52+
// 设置审批人(实际项目中可以从用户服务获取)
53+
variables.put("departmentManager", "manager_" + getDepartment(application.getApplicant()));
54+
variables.put("director", "director_company");
55+
56+
var instance = runtimeService.startProcessInstanceByKey("LeaveProcess", variables);
57+
58+
Map<String, Object> result = new HashMap<>();
59+
result.put("processInstanceId", instance.getId());
60+
result.put("message", "请假流程已启动");
61+
62+
return ResponseEntity.ok(result);
63+
64+
} finally {
65+
identityService.clearAuthentication();
66+
}
67+
}
68+
69+
/**
70+
* 获取用户待办任务
71+
* @param userId 用户
72+
*/
73+
@GetMapping("/tasks/{userId}")
74+
public ResponseEntity<List<Map<String, Object>>> getUserTasks(@PathVariable String userId) {
75+
List<Task> tasks = taskService.createTaskQuery()
76+
.taskAssignee(userId)
77+
.orderByTaskCreateTime()
78+
.desc()
79+
.list();
80+
81+
List<Map<String, Object>> taskList = tasks.stream().map(task -> {
82+
Map<String, Object> taskInfo = new HashMap<>();
83+
taskInfo.put("taskId", task.getId());
84+
taskInfo.put("taskName", task.getName());
85+
taskInfo.put("processInstanceId", task.getProcessInstanceId());
86+
taskInfo.put("createTime", task.getCreateTime());
87+
taskInfo.put("dueDate", task.getDueDate());
88+
89+
// 获取流程变量
90+
Map<String, Object> variables = taskService.getVariables(task.getId());
91+
taskInfo.put("applicant", variables.get("applicant"));
92+
taskInfo.put("leaveType", variables.get("leaveType"));
93+
taskInfo.put("leaveDays", variables.get("leaveDays"));
94+
taskInfo.put("startDate", variables.get("startDate"));
95+
96+
return taskInfo;
97+
}).collect(Collectors.toList());
98+
99+
return ResponseEntity.ok(taskList);
100+
}
101+
102+
/**
103+
* 审批任务
104+
* @param taskId 任务id
105+
* @param approved 审批变量
106+
* @param comment 审批意见
107+
*/
108+
@PostMapping("/approve/{taskId}")
109+
public ResponseEntity<Map<String, Object>> approveTask(
110+
@PathVariable String taskId,
111+
@RequestParam Boolean approved,
112+
@RequestParam(required = false) String comment) {
113+
114+
Map<String, Object> variables = new HashMap<>();
115+
116+
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
117+
if (task == null) {
118+
throw new RuntimeException("任务不存在");
119+
}
120+
121+
// 根据任务ID设置对应的审批变量
122+
if ("UserTask_ManagerApprove".equals(task.getTaskDefinitionKey())) {
123+
variables.put("managerApproved", approved);
124+
variables.put("managerComment", comment);
125+
} else if ("UserTask_DirectorApprove".equals(task.getTaskDefinitionKey())) {
126+
variables.put("directorApproved", approved);
127+
variables.put("directorComment", comment);
128+
}
129+
130+
taskService.complete(taskId, variables);
131+
132+
Map<String, Object> result = new HashMap<>();
133+
result.put("message", "审批完成");
134+
result.put("taskId", taskId);
135+
result.put("approved", approved);
136+
137+
return ResponseEntity.ok(result);
138+
}
139+
140+
/**
141+
* 获取流程历史
142+
* @param processInstanceId 请假实例id
143+
*/
144+
@GetMapping("/history/{processInstanceId}")
145+
public ResponseEntity<Map<String, Object>> getProcessHistory(@PathVariable String processInstanceId) {
146+
HistoricProcessInstance processInstance = historyService
147+
.createHistoricProcessInstanceQuery()
148+
.processInstanceId(processInstanceId)
149+
.singleResult();
150+
151+
List<HistoricActivityInstance> activities = historyService
152+
.createHistoricActivityInstanceQuery()
153+
.processInstanceId(processInstanceId)
154+
.orderByHistoricActivityInstanceStartTime()
155+
.asc()
156+
.list();
157+
158+
Map<String, Object> history = new HashMap<>();
159+
history.put("processInstance", processInstance);
160+
history.put("activities", activities);
161+
162+
return ResponseEntity.ok(history);
163+
}
164+
165+
private String getDepartment(String userId) {
166+
// 模拟根据用户ID获取部门信息
167+
// 实际项目中应该调用用户服务
168+
return "tech"; // 返回部门代码
169+
}
170+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package top.lrshuai.camunda.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonFormat;
4+
import lombok.Data;
5+
import org.springframework.format.annotation.DateTimeFormat;
6+
7+
import java.time.LocalDateTime;
8+
9+
@Data
10+
public class LeaveApplicationDto {
11+
//申请人
12+
private String applicant;
13+
// 请假类型:年假、事假...
14+
private String leaveType;
15+
16+
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
17+
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
18+
private LocalDateTime startDate;
19+
20+
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
21+
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
22+
private LocalDateTime endDate;
23+
// 请假天数
24+
private Double leaveDays;
25+
//备注
26+
private String reason;
27+
}

0 commit comments

Comments
 (0)