Browse Source

controller层整合

master
Yen 3 years ago
parent
commit
c8a3b9eea2
  1. 5
      src/main/java/com/qs/serve/modules/bpm/conf/FlowServiceFactory.java
  2. 103
      src/main/java/com/qs/serve/modules/bpm/controller/BpmDeployFormController.java
  3. 27
      src/main/java/com/qs/serve/modules/bpm/controller/BpmFlowDefinitionController.java
  4. 94
      src/main/java/com/qs/serve/modules/bpm/controller/FlowDefinitionController.java
  5. 72
      src/main/java/com/qs/serve/modules/bpm/controller/FlowInstanceController.java
  6. 74
      src/main/java/com/qs/serve/modules/bpm/entity/BpmDeployForm.java
  7. 26
      src/main/java/com/qs/serve/modules/bpm/entity/dto/BpmnDto.java
  8. 23
      src/main/java/com/qs/serve/modules/bpm/entity/dto/DeployBpmnBo.java
  9. 31
      src/main/java/com/qs/serve/modules/bpm/entity/dto/DeployViewerDto.java
  10. 2
      src/main/java/com/qs/serve/modules/bpm/entity/dto/FlowNextDto.java
  11. 2
      src/main/java/com/qs/serve/modules/bpm/entity/dto/FlowTaskDto.java
  12. 14
      src/main/java/com/qs/serve/modules/bpm/mapper/BpmDeployFormMapper.java
  13. 17
      src/main/java/com/qs/serve/modules/bpm/service/BpmDeployFormService.java
  14. 37
      src/main/java/com/qs/serve/modules/bpm/service/impl/BpmDeployFormServiceImpl.java
  15. 458
      src/main/java/com/qs/serve/modules/bpm/service/impl/IFlowTaskServiceImpl.java

5
src/main/java/com/qs/serve/modules/bpm/conf/FlowServiceFactory.java

@ -1,5 +1,6 @@
package com.qs.serve.modules.bpm.conf; package com.qs.serve.modules.bpm.conf;
import com.qs.serve.modules.bpm.service.BpmFormService;
import lombok.Getter; import lombok.Getter;
import org.flowable.engine.*; import org.flowable.engine.*;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -27,8 +28,8 @@ public class FlowServiceFactory {
@Resource @Resource
protected TaskService taskService; protected TaskService taskService;
//@Resource @Resource
//protected FormService formService; protected BpmFormService formService;
@Resource @Resource
protected HistoryService historyService; protected HistoryService historyService;

103
src/main/java/com/qs/serve/modules/bpm/controller/BpmDeployFormController.java

@ -0,0 +1,103 @@
package com.qs.serve.modules.bpm.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.common.model.annotation.SysLog;
import com.qs.serve.common.model.dto.PageVo;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.model.enums.BizType;
import com.qs.serve.common.model.enums.SystemModule;
import com.qs.serve.common.util.PageUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.qs.serve.modules.bpm.entity.BpmDeployForm;
import com.qs.serve.modules.bpm.service.BpmDeployFormService;
import javax.validation.Valid;
import java.util.List;
/**
* 工作流 部署表单关联 后台接口
* @author YenHex
* @since 2022-08-23
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("bpm/deployForm")
public class BpmDeployFormController {
private BpmDeployFormService bpmDeployFormService;
/**
* 翻页查询
* @param param
* @return
*/
@GetMapping("/page")
@PreAuthorize("hasRole('bpm:deployForm:query')")
public R<PageVo<BpmDeployForm>> getPage(BpmDeployForm param){
PageUtil.startPage();
LambdaQueryWrapper<BpmDeployForm> deployFormWrapper = new LambdaQueryWrapper<>(param);
List<BpmDeployForm> list = bpmDeployFormService.list(deployFormWrapper);
return R.byPageHelperList(list);
}
/**
* 根据ID查询
* @param id
* @return
*/
@GetMapping("/getById/{id}")
@SysLog(module = SystemModule.BPM, title = "部署表单关联", biz = BizType.QUERY)
@PreAuthorize("hasRole('bpm:deployForm:query')")
public R<BpmDeployForm> getById(@PathVariable("id") String id){
BpmDeployForm bpmDeployForm = bpmDeployFormService.getById(id);
return R.ok(bpmDeployForm);
}
/**
* 根据ID更新
* @param param
* @return
*/
@PostMapping("/updateById")
@SysLog(module = SystemModule.BPM, title = "部署表单关联", biz = BizType.UPDATE)
@PreAuthorize("hasRole('bpm:deployForm:update')")
public R<?> updateById(@RequestBody @Valid BpmDeployForm param){
boolean result = bpmDeployFormService.updateById(param);
return R.isTrue(result);
}
/**
* 新增部署表单关联
* @param param
* @return
*/
@PostMapping("/save")
@SysLog(module = SystemModule.BPM, title = "部署表单关联", biz = BizType.INSERT)
@PreAuthorize("hasRole('bpm:deployForm:insert')")
public R<?> save(@RequestBody @Valid BpmDeployForm param){
boolean result = bpmDeployFormService.save(param);
return R.isTrue(result);
}
/**
* 删除部署表单关联
* @param id
* @return
*/
@DeleteMapping("/deleteById/{id}")
@SysLog(module = SystemModule.BPM, title = "部署表单关联", biz = BizType.DELETE)
@PreAuthorize("hasRole('bpm:deployForm:delete')")
public R<?> deleteById(@PathVariable("id") String id){
boolean result = bpmDeployFormService.removeById(id);
return R.isTrue(result);
}
}

27
src/main/java/com/qs/serve/modules/bpm/controller/BpmFlowDefinitionController.java

@ -1,27 +0,0 @@
package com.qs.serve.modules.bpm.controller;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 流程定义
* @author YenHex
* @since 2022/8/18
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("bpm/definition")
public class BpmFlowDefinitionController {
//流程定义列表
//保存流程
//获取流程
//删除流程
//启动流程实例
//激活或挂起流程定义
//
}

94
src/main/java/com/qs/serve/modules/bpm/controller/FlowDefinitionController.java

@ -0,0 +1,94 @@
package com.qs.serve.modules.bpm.controller;
import com.qs.serve.common.model.dto.PageVo;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.util.PageUtil;
import com.qs.serve.modules.bpm.entity.dto.DeployBpmnBo;
import com.qs.serve.modules.bpm.entity.dto.FlowProcDefDto;
import com.qs.serve.modules.bpm.service.IFlowDefinitionService;
import com.qs.serve.modules.sys.service.SysRoleService;
import com.qs.serve.modules.sys.service.SysUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 流程定义
* @author YenHex
* @since 2022/8/18
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("bpm/definition")
public class FlowDefinitionController {
private IFlowDefinitionService flowDefinitionService;
private SysUserService userService;
private SysRoleService sysRoleService;
/**
* 流程定义列表
* @param name
* @return
*/
@GetMapping(value = "/list")
public R<PageVo<FlowProcDefDto>> list(@RequestParam(required = false) String name) {
PageUtil.startPage();
List<FlowProcDefDto> list = flowDefinitionService.list(name);
return R.byPageHelperList(list);
}
/**
* 部署流程
* @param deployBpmnBo
* @return
*/
@PostMapping("/deploy")
public R<?> deploy(@RequestBody DeployBpmnBo deployBpmnBo){
return R.ok();
}
/**
* 根据流程定义id启动流程实例
* @param procDefId 流程定义id
* @param variables 变量集合,json对象
* @return
*/
@PostMapping("/start/{procDefId}")
public R start(@PathVariable(value = "procDefId") String procDefId, @RequestBody Map<String, Object> variables) {
flowDefinitionService.startProcessInstanceById(procDefId, variables);
return R.ok();
}
/**
* 激活或挂起流程定义
* @param state 1:激活,2:挂起
* @param deployId 流程部署ID
* @return
*/
@PutMapping(value = "/updateState")
public R updateState(@RequestParam Integer state,@RequestParam String deployId) {
flowDefinitionService.updateState(state, deployId);
return R.ok();
}
/**
* 删除流程
* @param deployIds
* @return
*/
@DeleteMapping(value = "/delete")
public R delete(String[] deployIds) {
for (String deployId : deployIds) {
flowDefinitionService.delete(deployId);
}
return R.ok();
}
}

72
src/main/java/com/qs/serve/modules/bpm/controller/FlowInstanceController.java

@ -0,0 +1,72 @@
package com.qs.serve.modules.bpm.controller;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.modules.bpm.entity.vo.FlowTaskVo;
import com.qs.serve.modules.bpm.service.IFlowInstanceService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 流程实例管理
* @author YenHex
* @since 2022/8/23
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("bpm/instance")
public class FlowInstanceController {
private IFlowInstanceService flowInstanceService;
/**
* 根据流程定义id启动流程实例
* @param procDefId 流程定义id
* @param variables 变量集合,json对象
* @return
*/
@PostMapping("/startBy/{procDefId}")
public R startById(@PathVariable(value = "procDefId") String procDefId, @RequestBody Map<String, Object> variables) {
flowInstanceService.startProcessInstanceById(procDefId, variables);
return R.ok();
}
/**
* 激活或挂起流程实例
* @param state 1:激活,2:挂起
* @param instanceId 流程实例ID
* @return
*/
@PostMapping(value = "/updateState")
public R updateState( @RequestParam Integer state, @RequestParam String instanceId) {
flowInstanceService.updateState(state,instanceId);
return R.ok();
}
/**
* 结束流程实例
* @param flowTaskVo
* @return
*/
@PostMapping(value = "/stopProcessInstance")
public R stopProcessInstance(@RequestBody FlowTaskVo flowTaskVo) {
flowInstanceService.stopProcessInstance(flowTaskVo);
return R.ok();
}
/**
* 删除流程实例
* @param instanceId 流程实例ID
* @param deleteReason 删除原因
* @return
*/
@DeleteMapping(value = "/delete")
public R delete(@RequestParam String instanceId, @RequestParam(required = false) String deleteReason) {
flowInstanceService.delete(instanceId,deleteReason);
return R.ok();
}
}

74
src/main/java/com/qs/serve/modules/bpm/entity/BpmDeployForm.java

@ -0,0 +1,74 @@
package com.qs.serve.modules.bpm.entity;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotBlank;
/**
* 部署表单关联 实体类
* @author YenHex
* @since 2022-08-23
*/
@Data
@TableName("bpm_deploy_form")
public class BpmDeployForm implements Serializable {
private static final long serialVersionUID = 1L;
/** id */
@TableId(type = IdType.AUTO)
private Long id;
/** 表单主键 */
private Long formId;
/** 流程定义主键 */
@Length(max = 32,message = "流程定义主键长度不能超过32字")
private String deployId;
/** 备注 */
@Length(max = 255,message = "备注长度不能超过255字")
private String remark;
/** 创建时间 */
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/** 创建人 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** 更新时间 */
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/** 更新人 */
@TableField(fill = FieldFill.UPDATE)
private String updateBy;
/** 租户id */
@JsonIgnore
@JsonProperty
private String tenantId;
/** 删除标识 */
@JsonIgnore
@JsonProperty
private Boolean delFlag;
}

26
src/main/java/com/qs/serve/modules/bpm/entity/dto/BpmnDto.java

@ -1,26 +0,0 @@
package com.qs.serve.modules.bpm.entity.dto;
import lombok.Data;
/**
* @author YenHex
* @since 2022/8/15
*/
@Data
public class BpmnDto {
private static class StartEvent{
private String id;
private String name;
}
private static class EndEvent{
private String id;
private String name;
}
private static class ServiceTask{
private String id;
private String name;
private String activitiClass;
}
}

23
src/main/java/com/qs/serve/modules/bpm/entity/dto/DeployBpmnBo.java

@ -0,0 +1,23 @@
package com.qs.serve.modules.bpm.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @author YenHex
* @since 2022/8/15
*/
@Data
public class DeployBpmnBo {
/** 流程定义名称 */
private String definitionName;
/** 流程定义名称 */
private String groupName;
/** 前端视图对象 */
private DeployViewerDto viewer;
}

31
src/main/java/com/qs/serve/modules/bpm/entity/dto/DeployViewerDto.java

@ -0,0 +1,31 @@
package com.qs.serve.modules.bpm.entity.dto;
import lombok.Data;
import java.util.List;
/**
* @author YenHex
* @since 2022/8/15
*/
@Data
public class DeployViewerDto {
private String nodeId;
private String nodeLabel;
/**
* approval -- userTask
* branch -- ex-gateway x2
* condition -- flow
* stat
* end
*/
private String type;
private List<Object> conditions;
private List<DeployViewerDto> conditionNodes;
private List<DeployViewerDto> childNode;
}

2
src/main/java/com/qs/serve/modules/bpm/entity/dto/FlowNextDto.java

@ -2,6 +2,7 @@ package com.qs.serve.modules.bpm.entity.dto;
import com.qs.serve.modules.sys.entity.SysRole; import com.qs.serve.modules.sys.entity.SysRole;
import com.qs.serve.modules.sys.entity.SysUser; import com.qs.serve.modules.sys.entity.SysUser;
import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@ -11,6 +12,7 @@ import java.util.List;
* @author YenHex * @author YenHex
* @since 2022/8/18 * @since 2022/8/18
*/ */
@Data
public class FlowNextDto implements Serializable { public class FlowNextDto implements Serializable {
private String type; private String type;

2
src/main/java/com/qs/serve/modules/bpm/entity/dto/FlowTaskDto.java

@ -36,7 +36,7 @@ public class FlowTaskDto {
/** /**
* 任务执行人Id * 任务执行人Id
*/ */
private Long assigneeId; private String assigneeId;
/** /**
* 部门名称 * 部门名称

14
src/main/java/com/qs/serve/modules/bpm/mapper/BpmDeployFormMapper.java

@ -0,0 +1,14 @@
package com.qs.serve.modules.bpm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qs.serve.modules.bpm.entity.BpmDeployForm;
/**
* 部署表单关联 Mapper
* @author YenHex
* @date 2022-08-23
*/
public interface BpmDeployFormMapper extends BaseMapper<BpmDeployForm> {
}

17
src/main/java/com/qs/serve/modules/bpm/service/BpmDeployFormService.java

@ -0,0 +1,17 @@
package com.qs.serve.modules.bpm.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qs.serve.modules.bpm.entity.BpmDeployForm;
import com.qs.serve.modules.bpm.entity.BpmForm;
/**
* 部署表单关联 服务接口
* @author YenHex
* @date 2022-08-23
*/
public interface BpmDeployFormService extends IService<BpmDeployForm> {
BpmForm selectSysDeployFormByDeployId(String deployId);
}

37
src/main/java/com/qs/serve/modules/bpm/service/impl/BpmDeployFormServiceImpl.java

@ -0,0 +1,37 @@
package com.qs.serve.modules.bpm.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qs.serve.modules.bpm.entity.BpmForm;
import com.qs.serve.modules.bpm.mapper.BpmFormMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.qs.serve.modules.bpm.entity.BpmDeployForm;
import com.qs.serve.modules.bpm.service.BpmDeployFormService;
import com.qs.serve.modules.bpm.mapper.BpmDeployFormMapper;
/**
* 部署表单关联 服务实现类
* @author YenHex
* @since 2022-08-23
*/
@Slf4j
@Service
@AllArgsConstructor
public class BpmDeployFormServiceImpl extends ServiceImpl<BpmDeployFormMapper,BpmDeployForm> implements BpmDeployFormService {
private final BpmFormMapper bpmFormMapper;
@Override
public BpmForm selectSysDeployFormByDeployId(String deployId) {
LambdaQueryWrapper<BpmDeployForm> lqw = new LambdaQueryWrapper<>();
lqw.eq(BpmDeployForm::getDeployId,deployId);
BpmDeployForm deployForm = getOne(lqw);
if(deployForm!=null){
return bpmFormMapper.selectById(deployForm.getFormId());
}
return null;
}
}

458
src/main/java/com/qs/serve/modules/bpm/service/impl/IFlowTaskServiceImpl.java

@ -1,21 +1,31 @@
package com.qs.serve.modules.bpm.service.impl; package com.qs.serve.modules.bpm.service.impl;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qs.serve.common.model.dto.R; import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.util.Assert; import com.qs.serve.common.util.Assert;
import com.qs.serve.common.util.AuthContextUtils; import com.qs.serve.common.util.AuthContextUtils;
import com.qs.serve.common.util.CollectionUtil; import com.qs.serve.common.util.CollectionUtil;
import com.qs.serve.modules.bpm.common.consts.ProcessConstants;
import com.qs.serve.modules.bpm.common.enums.FlowComment; import com.qs.serve.modules.bpm.common.enums.FlowComment;
import com.qs.serve.modules.bpm.common.util.FindNextNodeUtil;
import com.qs.serve.modules.bpm.common.util.FlowableUtils; import com.qs.serve.modules.bpm.common.util.FlowableUtils;
import com.qs.serve.modules.bpm.conf.FlowServiceFactory; import com.qs.serve.modules.bpm.conf.FlowServiceFactory;
import com.qs.serve.modules.bpm.entity.BpmForm;
import com.qs.serve.modules.bpm.entity.dto.FlowCommentDto;
import com.qs.serve.modules.bpm.entity.dto.FlowNextDto;
import com.qs.serve.modules.bpm.entity.dto.FlowTaskDto; import com.qs.serve.modules.bpm.entity.dto.FlowTaskDto;
import com.qs.serve.modules.bpm.entity.dto.FlowViewerDto;
import com.qs.serve.modules.bpm.entity.vo.FlowTaskVo; import com.qs.serve.modules.bpm.entity.vo.FlowTaskVo;
import com.qs.serve.modules.bpm.service.BpmDeployFormService;
import com.qs.serve.modules.bpm.service.IFlowTaskService; import com.qs.serve.modules.bpm.service.IFlowTaskService;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.qs.serve.modules.sys.entity.SysDept; import com.qs.serve.modules.sys.entity.SysDept;
import com.qs.serve.modules.sys.entity.SysRole;
import com.qs.serve.modules.sys.entity.SysUser; import com.qs.serve.modules.sys.entity.SysUser;
import com.qs.serve.modules.sys.service.SysDeptService; import com.qs.serve.modules.sys.service.SysDeptService;
import com.qs.serve.modules.sys.service.SysRoleService;
import com.qs.serve.modules.sys.service.SysUserService; import com.qs.serve.modules.sys.service.SysUserService;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -67,6 +77,8 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas
private final SysUserService sysUserService; private final SysUserService sysUserService;
private final SysDeptService sysDeptService; private final SysDeptService sysDeptService;
private final SysRoleService sysRoleService;
private final BpmDeployFormService bpmDeployFormService;
/** /**
* 完成任务 * 完成任务
@ -99,7 +111,118 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas
@Override @Override
public void taskReject(FlowTaskVo flowTaskVo) { public void taskReject(FlowTaskVo flowTaskVo) {
if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
Assert.throwEx("任务处于挂起状态"); Assert.throwEx("任务处于挂起状态!");
}
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// 获取全部节点列表,包含子节点
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
// 获取当前任务节点元素
FlowElement source = null;
if (allElements != null) {
for (FlowElement flowElement : allElements) {
// 类型为用户节点
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
// 获取节点信息
source = flowElement;
}
}
}
// 目的获取所有跳转到的节点 targetIds
// 获取当前节点的所有父级用户任务节点
// 深度优先算法思想:延边迭代深入
List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
Assert.throwEx("当前节点为初始任务节点,不能驳回");
}
// 获取活动 ID 即节点 Key
List<String> parentUserTaskKeyList = new ArrayList<>();
parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
// 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序
List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
// 数据清洗,将回滚导致的脏数据清洗掉
List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
// 此时历史任务实例为倒序,获取最后走的节点
List<String> targetIds = new ArrayList<>();
// 循环结束标识,遇到当前目标节点的次数
int number = 0;
StringBuilder parentHistoricTaskKey = new StringBuilder();
for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
// 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过
if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
continue;
}
parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
number++;
}
// 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次
// 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环
// number == 1,第一次遇到当前节点
// number == 2,第二次遇到,代表最后一次的循环范围
if (number == 2) {
break;
}
// 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点
if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
targetIds.add(historicTaskInstanceKey);
}
}
// 目的获取所有需要被跳转的节点 currentIds
// 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路
UserTask oneUserTask = parentUserTaskList.get(0);
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需驳回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况
if (targetIds.size() > 1 && currentIds.size() > 1) {
Assert.throwEx("任务出现多对多情况,无法撤回");
}
// 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// 设置驳回意见
currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()));
try {
// 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况
if (targetIds.size() > 1) {
// 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId()).
moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
}
// 如果父级任务只有一个,因此当前任务可能为网关中的任务
if (targetIds.size() == 1) {
// 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
}
} catch (FlowableObjectNotFoundException e) {
Assert.throwEx("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
Assert.throwEx("无法取消或开始活动");
} }
} }
@ -109,7 +232,72 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas
*/ */
@Override @Override
public void taskReturn(FlowTaskVo flowTaskVo) { public void taskReturn(FlowTaskVo flowTaskVo) {
if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
Assert.throwEx("任务处于挂起状态");
}
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// 获取全部节点列表,包含子节点
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
// 获取当前任务节点元素
FlowElement source = null;
// 获取跳转的节点元素
FlowElement target = null;
if (allElements != null) {
for (FlowElement flowElement : allElements) {
// 当前任务节点元素
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
source = flowElement;
}
// 跳转的节点元素
if (flowElement.getId().equals(flowTaskVo.getTargetKey())) {
target = flowElement;
}
}
}
// 从当前节点向前扫描
// 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转
// 否则目标节点相对于当前节点,属于串行
Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null);
if (!isSequential) {
Assert.throwEx("当前节点相对于目标节点,不属于串行关系,无法回退");
}
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需退回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// 设置回退意见
currentTaskIds.forEach(currentTaskId -> taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment()));
try {
// 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
Assert.throwEx("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
Assert.throwEx("无法取消或开始活动");
}
} }
/** /**
@ -388,34 +576,290 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas
return R.ok(page); return R.ok(page);
} }
/**
* 已办任务列表
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return
*/
@Override @Override
public R<?> finishedList(Integer pageNum, Integer pageSize) { public R<?> finishedList(Integer pageNum, Integer pageSize) {
return null; Page<FlowTaskDto> page = new Page<>();
String userId = AuthContextUtils.getSysUserId();
HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
.includeProcessVariables()
.finished()
.taskAssignee(userId)
.orderByHistoricTaskInstanceEndTime()
.desc();
List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(pageSize * (pageNum - 1), pageSize);
List<FlowTaskDto> hisTaskList = Lists.newArrayList();
for (HistoricTaskInstance histTask : historicTaskInstanceList) {
FlowTaskDto flowTask = new FlowTaskDto();
// 当前流程信息
flowTask.setTaskId(histTask.getId());
// 审批人员信息
flowTask.setCreateTime(histTask.getCreateTime());
flowTask.setFinishTime(histTask.getEndTime());
flowTask.setDuration(getDate(histTask.getDurationInMillis()));
flowTask.setProcDefId(histTask.getProcessDefinitionId());
flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
flowTask.setTaskName(histTask.getName());
// 流程定义信息
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(histTask.getProcessDefinitionId())
.singleResult();
flowTask.setDeployId(pd.getDeploymentId());
flowTask.setProcDefName(pd.getName());
flowTask.setProcDefVersion(pd.getVersion());
flowTask.setProcInsId(histTask.getProcessInstanceId());
flowTask.setHisProcInsId(histTask.getProcessInstanceId());
// 流程发起人信息
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(histTask.getProcessInstanceId())
.singleResult();
SysUser startUser = sysUserService.getById(historicProcessInstance.getStartUserId());
flowTask.setStartUserId(startUser.getId());
flowTask.setStartUserName(startUser.getName());
if(startUser.getDeptId()!=null){
SysDept sysDept = sysDeptService.getById(startUser.getDeptId());
flowTask.setStartDeptName(sysDept!=null?sysDept.getName():null);
}
hisTaskList.add(flowTask);
}
page.setTotal(taskInstanceQuery.count());
page.setRecords(hisTaskList);
// Map<String, Object> result = new HashMap<>();
// result.put("result",page);
// result.put("finished",true);
return R.ok(page);
} }
/**
* 流程历史流转记录
* @param procInsId 流程实例Id
* @param deployId
* @return
*/
@Override @Override
public R<?> flowRecord(String procInsId, String deployId) { public R<?> flowRecord(String procInsId, String deployId) {
return null; Map<String, Object> map = new HashMap<String, Object>();
if (StringUtils.isNotBlank(procInsId)) {
List<HistoricActivityInstance> list = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.orderByHistoricActivityInstanceStartTime()
.desc().list();
List<FlowTaskDto> hisFlowList = new ArrayList<>();
for (HistoricActivityInstance histIns : list) {
if (StringUtils.isNotBlank(histIns.getTaskId())) {
FlowTaskDto flowTask = new FlowTaskDto();
flowTask.setTaskId(histIns.getTaskId());
flowTask.setTaskName(histIns.getActivityName());
flowTask.setCreateTime(histIns.getStartTime());
flowTask.setFinishTime(histIns.getEndTime());
if (StringUtils.isNotBlank(histIns.getAssignee())) {
SysUser sysUser = sysUserService.getById(histIns.getAssignee());
flowTask.setAssigneeId(sysUser.getId());
flowTask.setAssigneeName(sysUser.getName());
if(sysUser.getDeptId()!=null){
SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
flowTask.setDeptName(sysDept==null?null:sysDept.getName());
}
}
// 展示审批人员
List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId());
StringBuilder stringBuilder = new StringBuilder();
for (HistoricIdentityLink identityLink : linksForTask) {
// 获选人,候选组/角色(多个)
if ("candidate".equals(identityLink.getType())) {
if (StringUtils.isNotBlank(identityLink.getUserId())) {
SysUser sysUser = sysUserService.getById(identityLink.getUserId());
stringBuilder.append(sysUser.getName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.getById(identityLink.getGroupId());
stringBuilder.append(sysRole.getName()).append(",");
}
}
}
if (StringUtils.isNotBlank(stringBuilder)) {
flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
}
flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
// 获取意见评论内容
List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
commentList.forEach(comment -> {
if (histIns.getTaskId().equals(comment.getTaskId())) {
flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
}
});
hisFlowList.add(flowTask);
}
}
map.put("flowList", hisFlowList);
// // 查询当前任务是否完成
// List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
// if (CollectionUtils.isNotEmpty(taskList)) {
// map.put("finished", true);
// } else {
// map.put("finished", false);
// }
}
// 第一次申请获取初始化表单
if (StringUtils.isNotBlank(deployId)) {
BpmForm sysForm = bpmDeployFormService.selectSysDeployFormByDeployId(deployId);
if (Objects.isNull(sysForm)) {
return R.error("请先配置流程表单");
}
map.put("formData", JSONObject.parseObject(sysForm.getFormContext()));
}
return R.ok(map);
} }
/**
* 根据任务ID查询挂载的表单信息
* @param taskId 任务Id
* @return
*/
@Override @Override
public Task getTaskForm(String taskId) { public Task getTaskForm(String taskId) {
return null; Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
return task;
} }
/**
* 获取流程执行过程
* @param procInsId
* @param executionId
* @return
*/
@Override @Override
public R<?> getFlowViewer(String procInsId, String executionId) { public R<?> getFlowViewer(String procInsId, String executionId) {
return null; List<FlowViewerDto> flowViewerList = new ArrayList<>();
FlowViewerDto flowViewerDto;
// 获取任务开始节点(临时处理方式)
List<HistoricActivityInstance> startNodeList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.orderByHistoricActivityInstanceStartTime()
.asc().listPage(0,3);
for (HistoricActivityInstance startInstance : startNodeList) {
if (!"sequenceFlow".equals(startInstance.getActivityType())) {
flowViewerDto = new FlowViewerDto();
if (!"sequenceFlow".equals(startInstance.getActivityType())) {
flowViewerDto.setKey(startInstance.getActivityId());
// 根据流程节点处理时间校验改节点是否已完成
flowViewerDto.setCompleted(!Objects.isNull(startInstance.getEndTime()));
flowViewerList.add(flowViewerDto);
}
}
}
// 历史节点
List<HistoricActivityInstance> hisActIns = historyService.createHistoricActivityInstanceQuery()
.executionId(executionId)
.orderByHistoricActivityInstanceStartTime()
.asc().list();
for (HistoricActivityInstance activityInstance : hisActIns) {
if (!"sequenceFlow".equals(activityInstance.getActivityType())) {
flowViewerDto = new FlowViewerDto();
flowViewerDto.setKey(activityInstance.getActivityId());
// 根据流程节点处理时间校验改节点是否已完成
flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime()));
flowViewerList.add(flowViewerDto);
}
}
return R.ok(flowViewerList);
} }
/**
* 获取流程变量
* @param taskId
* @return
*/
@Override @Override
public R<?> processVariables(String taskId) { public R<?> processVariables(String taskId) {
return null; // 流程变量
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
if (Objects.nonNull(historicTaskInstance)) {
return R.ok(historicTaskInstance.getProcessVariables());
} else {
Map<String, Object> variables = taskService.getVariables(taskId);
return R.ok(variables);
}
} }
/**
* 获取下一节点
* @param flowTaskVo 任务
* @return
*/
@Override @Override
public R<?> getNextFlowNode(FlowTaskVo flowTaskVo) { public R<?> getNextFlowNode(FlowTaskVo flowTaskVo) {
return null; List<SysUser> allUserList = sysUserService.list();
// Step 1. 获取当前节点并找到下一步节点
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
FlowNextDto flowNextDto = new FlowNextDto();
if (Objects.nonNull(task)) {
// Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
Map<String, Object> variables = taskService.getVariables(task.getId());
List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables);
if (CollectionUtils.isNotEmpty(nextUserTask)) {
for (UserTask userTask : nextUserTask) {
MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
// 会签节点
if (Objects.nonNull(multiInstance)) {
List<SysUser> list = allUserList;
flowNextDto.setVars(ProcessConstants.PROCESS_MULTI_INSTANCE_USER);
flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
flowNextDto.setUserList(list);
} else {
// 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
// 处理加载动态指定下一节点接收人员信息
if (ProcessConstants.DATA_TYPE.equals(dataType)) {
// 指定单个人员
if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) {
List<SysUser> list = allUserList;
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(ProcessConstants.USER_TYPE_ASSIGNEE);
flowNextDto.setUserList(list);
}
// 候选人员(多个)
if (ProcessConstants.USER_TYPE_USERS.equals(userType)) {
List<SysUser> list = allUserList;
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(ProcessConstants.USER_TYPE_USERS);
flowNextDto.setUserList(list);
}
// 候选组
if (ProcessConstants.USER_TYPE_ROUPS.equals(userType)) {
List<SysRole> sysRoles = sysRoleService.list();
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(ProcessConstants.USER_TYPE_ROUPS);
flowNextDto.setRoleList(sysRoles);
}
} else {
flowNextDto.setType(ProcessConstants.FIXED);
}
}
}
} else {
return R.ok("流程已完结", null);
}
}
return R.ok(flowNextDto);
}
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
} }
/** /**

Loading…
Cancel
Save