在com.example.emos.workflow.config.quart
包声明MeetingRoomJob.java
类
public class MeetingRoomJob extends QuartzJobBean {
@Autowired
private RedisTemplate redisTemplate;
@Override
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
Map map = ctx.getJobDetail().getJobDataMap();
String uuid = map.get("uuid").toString();
Date date = DateUtil.parse(map.get("expire").toString(), "yyyy-MM-dd HH:mm:ss");
//生成当前唯一的视频会议房间ID
for (; ; ) {
long roomId = RandomUtil.randomLong(1L, 4294967295L);
if (redisTemplate.hasKey("roomId-" + roomId)) {
continue;
} else {
redisTemplate.opsForValue().set("roomId-" + roomId, uuid);
redisTemplate.expireAt("roomId-" + roomId, date);
redisTemplate.opsForValue().set(uuid, roomId);
redisTemplate.expireAt(uuid, date);
break;
}
}
}
}
在com.example.emos.workflow.config.quart
包创建MeetingStatusJob
类。
@Slf4j
@Component
public class MeetingStatusJob extends QuartzJobBean {
@Autowired
private MeetingService meetingService;
@Autowired
private AmectService amectService;
@Autowired
private AmectTypeService amectTypeService;
@Transactional
@Override
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
Map map = ctx.getJobDetail().getJobDataMap();
String uuid = MapUtil.getStr(map, "uuid");
Integer status = MapUtil.getInt(map, "status");
String title = MapUtil.getStr(map, "title");
String date = MapUtil.getStr(map, "date");
String start = MapUtil.getStr(map, "start");
String end = MapUtil.getStr(map, "end");
String flag=MapUtil.getStr(map,"flag");
//更新会议状态
HashMap param = new HashMap();
param.put("status", status);
param.put("uuid", uuid);
meetingService.updateMeetingStatus(param);
log.debug("会议状态更新成功");
if("end".equals(flag)){
//生成缺席名单
ArrayList<Integer> list = meetingService.searchMeetingUnpresent(uuid);
if (list != null && list.size() > 0) {
JSONArray array = new JSONArray();
list.forEach(one -> {
array.put(one);
});
param = new HashMap() {{
put("uuid", uuid);
put("unpresent", JSONUtil.toJsonStr(array));
}};
meetingService.updateMeetingUnpresent(param);
//查询缺席会议的罚款金额和ID
map = amectTypeService.searchByType("缺席会议");
BigDecimal money = (BigDecimal) map.get("money");
Integer typeId = (Integer) map.get("id");
//根据缺席名单生成罚款单
TbAmect amect = new TbAmect();
amect.setAmount(money);
amect.setTypeId(typeId);
amect.setReason("缺席" + date + " " + start + "~" + end + "的" + title);
list.forEach(one -> {
amect.setUuid(IdUtil.simpleUUID());
amect.setUserId(one);
amectService.insert(amect);
});
}
}
}
}
在com.example.emos.workflow.config.quart
包创建MeetingWorkflowJob
类。
@Slf4j
@Component
public class MeetingWorkflowJob extends QuartzJobBean {
@Autowired
private RuntimeService runtimeService;
@Autowired
private HistoryService historyService;
@Autowired
private MeetingService meetingService;
@Autowired
private WorkflowService workflowService;
/**
* 检查工作里的审批状态
*
* @param ctx
* @throws JobExecutionException
*/
@Override
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
Map map = ctx.getJobDetail().getJobDataMap();
String uuid = map.get("uuid").toString();
String instanceId = map.get("instanceId").toString();
//判断会议审批是不是未结束
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
if (instance != null) {
map.put("processStatus", "未结束");
workflowService.deleteProcessById(uuid, instanceId, "会议", "会议过期");
HashMap param = new HashMap();
param.put("uuid", uuid);
param.put("status", 2); //更改会议状态为已拒绝
meetingService.updateMeetingStatus(param); //更新会议状态
log.debug("会议已失效");
}
}
}
在com.example.emos.workflow.config.quart
包创建QuartzUtil类。
@Component
@Slf4j
public class QuartzUtil {
@Resource
private Scheduler scheduler;
public void addJob(JobDetail jobDetail, String jobName, String jobGroupName, Date start) {
try {
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow())
.startAt(start).build();
scheduler.scheduleJob(jobDetail, trigger);
log.debug("成功添加" + jobName + "定时器");
} catch (SchedulerException e) {
log.error("定时器添加失败",e);
}
}
public void deleteJob(String jobName, String jobGroupName) {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
try {
scheduler.resumeTrigger(triggerKey);
scheduler.unscheduleJob(triggerKey);
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
log.debug("成功删除" + jobName + "定时器");
} catch (SchedulerException e) {
log.error("定时器删除失败",e);
}
}
}
在com.example.emos.workflow.config
包中创建DroolsConfiguration
@Configuration
public class DroolsConfiguration {
private static final String RULES_PATH = "rules/";
@Bean
@ConditionalOnMissingBean(KieFileSystem.class)
public KieFileSystem kieFileSystem() throws IOException {
KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
for (Resource file : getRuleFiles()) {
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
}
return kieFileSystem;
}
private Resource[] getRuleFiles() throws IOException {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
}
@Bean
@ConditionalOnMissingBean(KieContainer.class)
public KieContainer kieContainer() throws IOException {
final KieRepository kieRepository = getKieServices().getRepository();
kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
kieBuilder.buildAll();
return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
}
private KieServices getKieServices() {
return KieServices.Factory.get();
}
@Bean
@ConditionalOnMissingBean(KieBase.class)
public KieBase kieBase() throws IOException {
return kieContainer().getKieBase();
}
@Bean
@ConditionalOnMissingBean(KieSession.class)
public KieSession kieSession() throws IOException {
KieSession kieSession = kieContainer().newKieSession();
return kieSession;
}
@Bean
@ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
public KModuleBeanFactoryPostProcessor kiePostProcessor() {
return new KModuleBeanFactoryPostProcessor();
}
}
在WorkflowService 中补充抽象方法。
public interface WorkflowService {
public boolean searchProcessStatus(String instanceId);
public void deleteProcessById(String uuid, String instanceId, String type, String reason);
public ArrayList searchProcessUsers(String instanceId);
public HashMap searchTaskByPage(HashMap param);
public HashMap searchApprovalContent(String instanceId, int userId,String[] role, String type, String status);
public HashMap searchApprovalContent(String instanceId, int userId,String[] role, String type, String status);
}
在WorkflowServiceImpl
中添加如下代码
@Service
public class WorkflowServiceImpl implements WorkflowService {
……
@Override
public boolean searchProcessStatus(String instanceId) {
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
if (instance != null) {
//工作流未结束
return false;
} else {
//工作流已经结束
return true;
}
}
@Override
public void deleteProcessById(String uuid, String instanceId, String type, String reason) {
long count = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).count();
if (count > 0) {
runtimeService.deleteProcessInstance(instanceId, reason); //删除工作流
}
count = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).count();
if (count > 0) {
historyService.deleteHistoricProcessInstance(instanceId); //删除工作流历史
}
//判断是否是会议工作流,然后删除定时器
if (type.equals("会议申请")) {
quartzUtil.deleteJob(uuid, "会议开始任务组");
quartzUtil.deleteJob(uuid, "会议结束任务组");
quartzUtil.deleteJob(uuid, "会议工作流组");
quartzUtil.deleteJob(uuid, "创建会议室ID任务组");
}
}
@Override
public ArrayList searchProcessUsers(String instanceId) {
List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(instanceId).finished().list();
ArrayList<String> list = new ArrayList<>();
taskList.forEach(one -> {
list.add(one.getAssignee());
});
return list;
}
@Override
public HashMap searchTaskByPage(HashMap param) {
ArrayList<Approval> list = new ArrayList();
int userId = (Integer) param.get("userId");
JSONArray role = (JSONArray) param.get("role");
int start = (Integer) param.get("start");
int length = (Integer) param.get("length");
String status = (String) param.get("status");
String creatorName = MapUtil.getStr(param, "creatorName");
String type = MapUtil.getStr(param, "type");
String instanceId = MapUtil.getStr(param, "instanceId");
Long totalCount = 0L;
List<String> assignee = new ArrayList();
assignee.add(userId + "");
role.forEach(one -> {
assignee.add(one.toString());
});
if ("待审批".equals(status)) {
TaskQuery taskQuery = taskService.createTaskQuery().orderByTaskCreateTime().desc()
.includeProcessVariables().includeTaskLocalVariables().taskAssigneeIds(assignee);
if (StrUtil.isNotBlank(creatorName)) {
taskQuery.processVariableValueEquals("creatorName", creatorName);
}
if (StrUtil.isNotBlank(type)) {
taskQuery.processVariableValueEquals("type", type);
}
if (StrUtil.isNotBlank(instanceId)) {
taskQuery.processInstanceId(instanceId);
}
totalCount = taskQuery.count();
List<Task> taskList = taskQuery.listPage(start, length);
for (Task task : taskList) {
Map map = task.getProcessVariables();
Approval approval = createApproval(task.getProcessInstanceId(), status, map);
approval.setTaskId(task.getId());
list.add(approval);
}
} else {
if ("已审批".equals(status)) {
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
.orderByHistoricTaskInstanceStartTime().desc()
.includeTaskLocalVariables().includeProcessVariables()
.taskAssigneeIds(assignee).finished().processUnfinished();
if (StrUtil.isNotBlank(creatorName)) {
taskQuery.processVariableValueEquals("creatorName", creatorName);
}
if (StrUtil.isNotBlank(type)) {
taskQuery.processVariableValueEquals("type", type);
}
if (StrUtil.isNotBlank(instanceId)) {
taskQuery.processInstanceId(instanceId);
}
totalCount = taskQuery.count();
List<HistoricTaskInstance> taskList = taskQuery.listPage(start, length);
for (HistoricTaskInstance task : taskList) {
Map map = task.getProcessVariables();
Approval approval = createApproval(task.getProcessInstanceId(), status, map);
approval.setTaskId(task.getId());
list.add(approval);
}
} else if ("已结束".equals(status)) {
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
.orderByHistoricTaskInstanceStartTime().desc()
.includeTaskLocalVariables().includeProcessVariables()
.taskAssigneeIds(assignee).finished().processFinished();
List<HistoricTaskInstance> taskList = taskQuery.listPage(start, length);
for (HistoricTaskInstance task : taskList) {
Map map = task.getProcessVariables();
Approval approval = createApproval(task.getProcessInstanceId(), status, map);
approval.setTaskId(task.getId());
list.add(approval);
}
}
}
HashMap map = new HashMap();
map.put("list", list);
map.put("totalCount", totalCount);
map.put("pageIndex", start);
map.put("pageSize", length);
return map;
}
@Override
public HashMap searchApprovalContent(String instanceId, int userId, String[] role, String type, String status) {
HashMap map = null;
List<String> assignee = new ArrayList();
assignee.add(userId + "");
for (String one : role) {
assignee.add(one);
}
if ("会议申请".equals(type)) {
map = meetingService.searchMeetingByInstanceId(instanceId);
} else if ("员工请假".equals(type)) {
map = leaveService.searchLeaveByInstanceId(instanceId);
} else if ("报销申请".equals(type)) {
map = reimService.searchReimByInstanceId(instanceId);
}
Map variables;
if (!"已结束".equals(status)) {
variables = runtimeService.getVariables(instanceId);
} else {
HistoricTaskInstance instance = historyService.createHistoricTaskInstanceQuery()
.includeTaskLocalVariables().includeProcessVariables().processInstanceId(instanceId).taskAssigneeIds(assignee).processFinished().list().get(0);
variables = instance.getProcessVariables();
}
if (variables != null && variables.containsKey("files")) {
ArrayNode files = (ArrayNode) variables.get("files");
map.put("files", files);
}
// map.put("list", variables.get("list"));
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
if (instance != null) {
map.put("result", "");
} else {
map.put("result", variables.get("result"));
}
return map;
}
private Approval createApproval(String processId, String status, Map map) {
String type = (String) map.get("type");
String createDate = (String) map.get("createDate");
boolean filing = (Boolean) map.get("filing");
Approval approval = new Approval();
approval.setCreatorName(map.get("creatorName").toString());
approval.setProcessId(processId);
approval.setType(type);
approval.setTitle(map.get("title").toString());
approval.setStatus(status);
approval.setCreateDate(createDate);
approval.setFiling(filing);
approval.setResult(MapUtil.getStr(map, "result"));
return approval;
}
@Override
public void approvalTask(HashMap param) {
taskService.complete(taskId);
}
}
编写Web方法之前,需要创建若干Form类
@Data
public class SearchProcessStatusForm {
@NotBlank(message = "instanceId不能为空")
private String instanceId;
@NotBlank(message = "code不能为空")
private String code;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@Data
public class DeleteProcessByIdForm {
@NotBlank(message = "instanceId不能为空")
private String instanceId;
@NotBlank(message = "type不能为空")
private String type;
@NotBlank(message = "reason不能为空")
private String reason;
@NotBlank(message = "code不能为空")
private String code;
private String uuid;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@Data
public class SearchProcessUsersForm {
@NotBlank(message = "instanceId不能为空")
private String instanceId;
@NotBlank(message = "code不能为空")
private String code;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@Data
public class SearchApprovalContentForm {
@NotBlank(message = "instanceId不能为空")
@Pattern(regexp = "^[0-9A-Za-z\\-]{36}$", message = "instanceId内容不正确")
private String instanceId;
@NotNull(message = "userId不能为空")
@Min(value = 1, message = "userId不能小于1")
private Integer userId;
@NotEmpty(message = "role不能为空")
private String[] role;
@NotBlank(message = "type不能为空")
@Pattern(regexp = "^员工请假$|^会议申请$|^报销申请$", message = "type内容不正确")
private String type;
@NotBlank(message = "status不能为空")
@Pattern(regexp = "^待审批$|^已审批$|^已结束$", message = "status内容不正确")
private String status;
@NotBlank(message = "code不能为空")
private String code;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@Data
public class SearchTaskByPageForm {
@NotNull(message = "userId不能为空")
@Min(value = 1, message = "userId不能小于1")
private Integer userId;
@NotEmpty(message = "role不能为空")
private String[] role;
@NotNull(message = "page不能为空")
@Min(value = 1, message = "page不能小于1")
private Integer page;
@NotNull(message = "length不能为空")
@Range(min = 10, max = 100, message = "length必须在10~100之间")
private Integer length;
@Pattern(regexp = "^员工请假$|^会议申请$|^报销申请$", message = "type内容不正确")
private String type;
@NotBlank(message = "status不能为空")
@Pattern(regexp = "^待审批$|^已审批$|^已结束$", message = "status内容不正确")
private String status;
@Pattern(regexp = "^[\\e4e00-\\u9fa5]{2,20}$", message = "creatorName内容不正确")
private String creatorName;
@Pattern(regexp = "^[0-9A-Za-z\\-]{36}$", message = "instanceId内容不正确")
private String instanceId;
@NotBlank(message = "code不能为空")
private String code;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@Data
public class StartLeaveProcessForm {
@NotNull(message = "creatorId不能为空")
@Min(value = 1, message = "creatorId不能小于1")
private Integer creatorId;
@NotBlank(message = "creatorName不能为空")
@Pattern(regexp = "^[\\u4e00-\\u9fa5]{2,15}$", message = "creatorName内容不正确")
private String creatorName;
@NotBlank(message = "title不能为空")
@Pattern(regexp = "^[a-zA-Z0-9\\u4e00-\\u9fa5]{2,30}$", message = "title内容不正确")
private String title;
@NotNull(message = "gmId不能为空")
@Min(value = 1, message = "gmId不能小于1")
private Integer gmId;
@NotNull(message = "managerId不能为空")
@Min(value = 1, message = "managerId不能小于1")
private Integer managerId;
@NotNull(message = "days不能为空")
private Double days;
@NotBlank(message = "url不能为空")
private String url;
@NotBlank(message = "code不能为空")
private String code;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@Data
public class StartReimProcessForm {
@NotNull(message = "creatorId不能为空")
@Min(value = 1, message = "creatorId不能小于1")
private Integer creatorId;
@NotBlank(message = "creatorName不能为空")
@Pattern(regexp = "^[\\u4e00-\\u9fa5]{2,15}$", message = "creatorName内容不正确")
private String creatorName;
@NotBlank(message = "title不能为空")
@Pattern(regexp = "^[a-zA-Z0-9\\u4e00-\\u9fa5]{2,30}$", message = "title内容不正确")
private String title;
@NotNull(message = "gmId不能为空")
@Min(value = 1, message = "gmId不能小于1")
private Integer gmId;
@NotNull(message = "managerId不能为空")
@Min(value = 1, message = "managerId不能小于1")
private Integer managerId;
@NotBlank(message = "url不能为空")
private String url;
@NotBlank(message = "code不能为空")
private String code;
@NotBlank(message = "tcode不能为空")
@Pattern(regexp = "^[0-9]{6}$",message = "tcode必须是6位数字")
private String tcode;
}
@RestController
@RequestMapping("/workflow")
public class WorkFlowController {
……
/**
* 查询工作流是否完成
*/
@PostMapping("/searchProcessStatus")
public R searchProcessStatus(@Valid @RequestBody SearchProcessStatusForm form) {
boolean bool = workflowService.searchProcessStatus(form.getInstanceId());
if (bool == false) {
//工作流未结束
return R.ok().put("result", "未结束");
} else {
//工作流已经结束
return R.ok().put("result", "已结束");
}
}
/**
* 删除工作流
*/
@PostMapping("/deleteProcessById")
public R deleteProcessById(@Valid @RequestBody DeleteProcessByIdForm form) {
workflowService.deleteProcessById(form.getUuid(), form.getInstanceId(), form.getType(), form.getReason());
return R.ok();
}
/**
* 查询已经结束工作流实例中所有的用户
*/
@PostMapping("/searchProcessUsers")
public R searchProcessUsers(@Valid @RequestBody SearchProcessUsersForm form) {
ArrayList list = workflowService.searchProcessUsers(form.getInstanceId());
return R.ok().put("result", list);
}
@PostMapping("/searchTaskByPage")
public R searchTaskByPage(@Valid @RequestBody SearchTaskByPageForm form) {
int page = form.getPage();
int length = form.getLength();
int start = (page - 1) * length;
HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
param.remove("page");
param.put("start", start);
HashMap map = workflowService.searchTaskByPage(param);
return R.ok().put("page", map);
}
@PostMapping("/searchApprovalContent")
public R searchApprovalContent(@Valid @RequestBody SearchApprovalContentForm form) {
HashMap map = workflowService.searchApprovalContent(form.getInstanceId(), form.getUserId(), form.getRole(), form.getType(), form.getStatus());
return R.ok().put("content", map);
}
@PostMapping("/searchApprovalBpmn")
public void searchApprovalBpmn(@Valid @RequestBody SearchApprovalBpmnForm form, HttpServletResponse response) {
response.setContentType("image/jpg");
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId(form.getInstanceId()).singleResult();
BpmnModel bpmnModel;
List activeActivityIds;
if (task != null) {
//流程定义
bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
activeActivityIds = runtimeService.getActiveActivityIds(task.getExecutionId());
} else {
HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(form.getInstanceId()).list().get(0);
bpmnModel = repositoryService.getBpmnModel(taskInstance.getProcessDefinitionId());
activeActivityIds = new ArrayList<>();
}
Map map = bpmnModel.getItemDefinitions();
DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
//绘制bpmnModel代表的流程的流程图
String os = System.getProperty("os.name").toLowerCase();
String font = "SimSun";
if (os.startsWith("win")) {
font = "宋体";
}
try (InputStream in = diagramGenerator.generateDiagram(bpmnModel, "jpg", activeActivityIds, activeActivityIds,
font, font, font,
processEngine.getProcessEngineConfiguration().getProcessEngineConfiguration().getClassLoader(), 1.0);
BufferedInputStream bin = new BufferedInputStream(in);
OutputStream out = response.getOutputStream();
BufferedOutputStream bout = new BufferedOutputStream(out);
) {
IOUtils.copy(bin, bout);
} catch (Exception e) {
e.printStackTrace();
}
}
@PostMapping("/startLeaveProcess")
public R startLeaveProcess(@Valid @RequestBody StartLeaveProcessForm form) {
HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
param.put("filing", false);
param.put("type", "员工请假");
param.put("createDate", DateUtil.today());
String instanceId = workflowService.startLeaveProcess(param);
return R.ok().put("instanceId", instanceId);
}
@PostMapping("/startReimProcess")
public R startReimProcess(@Valid @RequestBody StartReimProcessForm form) {
HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
param.put("filing", false);
param.put("type", "报销申请");
param.put("createDate", DateUtil.today());
param.remove("code");
String instanceId = workflowService.startReimProcess(param);
return R.ok().put("instanceId", instanceId);
}
}