fate: 升级流程设计器,表单设计器

This commit is contained in:
zhuyong
2024-09-05 23:51:27 +08:00
parent 27b56d3a01
commit 73acc6453c
111 changed files with 7642 additions and 9197 deletions

View File

@@ -0,0 +1,12 @@
package com.ruoyi.flowable.common.expand.el;
/**
* 扩展表达式
*
* @author Tony
* @date 2023-03-04 09:10
*/
public interface BaseEl {
}

View File

@@ -0,0 +1,32 @@
package com.ruoyi.flowable.common.expand.el;
import com.ruoyi.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 扩展表达式
*
* @author Tony
* @date 2023-03-04 12:10
*/
@Component
@Slf4j
public class FlowEl implements BaseEl {
@Resource
private ISysDeptService sysDeptService;
public String findDeptLeader(String name){
log.info("开始查询表达式变量值,getName");
return name;
}
public String getName(String name){
log.info("开始查询表达式变量值,getName");
return name;
}
}

View File

@@ -3,24 +3,15 @@ package com.ruoyi.flowable.config;
import org.flowable.engine.impl.db.DbIdGenerator;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
/**
* 流程id生成处理
* 扩展流程配置
* @author Tony
* @date 2022-12-26 10:24
*/
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
@Bean
public AsyncListenableTaskExecutor applicationTaskExecutor() {
return new SimpleAsyncTaskExecutor();
}
@Override
public void configure(SpringProcessEngineConfiguration engineConfiguration) {
engineConfiguration.setActivityFontName("宋体");

View File

@@ -1,12 +1,15 @@
package com.ruoyi.flowable.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.FlowProcDefDto;
import com.ruoyi.flowable.domain.dto.FlowSaveXmlVo;
import com.ruoyi.flowable.service.IFlowDefinitionService;
import com.ruoyi.system.domain.FlowProcDefDto;
import com.ruoyi.system.domain.SysExpression;
import com.ruoyi.system.service.ISysExpressionService;
import com.ruoyi.system.service.ISysRoleService;
@@ -16,6 +19,7 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -131,6 +135,7 @@ public class FlowDefinitionController extends BaseController {
@ApiOperation(value = "保存流程设计器内的xml文件")
@Log(title = "流程定义", businessType = BusinessType.INSERT)
@PostMapping("/save")
public AjaxResult save(@RequestBody FlowSaveXmlVo vo) {
InputStream in = null;
@@ -153,16 +158,16 @@ public class FlowDefinitionController extends BaseController {
return AjaxResult.success("导入成功");
}
@ApiOperation(value = "发起流程")
@Log(title = "发起流程", businessType = BusinessType.INSERT)
@PostMapping("/start/{procDefId}")
public AjaxResult start(@ApiParam(value = "流程定义id") @PathVariable(value = "procDefId") String procDefId,
@ApiParam(value = "变量集合,json对象") @RequestBody Map<String, Object> variables) {
return flowDefinitionService.startProcessInstanceById(procDefId, variables);
}
@ApiOperation(value = "激活或挂起流程定义")
@Log(title = "激活/挂起流程", businessType = BusinessType.UPDATE)
@PutMapping(value = "/updateState")
public AjaxResult updateState(@ApiParam(value = "1:激活,2:挂起", required = true) @RequestParam Integer state,
@ApiParam(value = "流程部署ID", required = true) @RequestParam String deployId) {
@@ -171,6 +176,7 @@ public class FlowDefinitionController extends BaseController {
}
@ApiOperation(value = "删除流程")
@Log(title = "删除流程", businessType = BusinessType.DELETE)
@DeleteMapping(value = "/{deployIds}")
public AjaxResult delete(@PathVariable String[] deployIds) {
for (String deployId : deployIds) {

View File

@@ -1,7 +1,10 @@
package com.ruoyi.flowable.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.flowable.domain.vo.FlowTaskVo;
import com.ruoyi.flowable.service.IFlowInstanceService;
import io.swagger.annotations.Api;
@@ -23,7 +26,7 @@ import java.util.Map;
@Api(tags = "工作流流程实例管理")
@RestController
@RequestMapping("/flowable/instance")
public class FlowInstanceController {
public class FlowInstanceController extends BaseController {
@Autowired
private IFlowInstanceService flowInstanceService;
@@ -36,7 +39,6 @@ public class FlowInstanceController {
}
@ApiOperation(value = "激活或挂起流程实例")
@PostMapping(value = "/updateState")
public AjaxResult updateState(@ApiParam(value = "1:激活,2:挂起", required = true) @RequestParam Integer state,
@@ -53,6 +55,7 @@ public class FlowInstanceController {
}
@ApiOperation(value = "删除流程实例")
@Log(title = "删除任务", businessType = BusinessType.DELETE)
@DeleteMapping(value = "/delete/{instanceIds}")
public AjaxResult delete(@ApiParam(value = "流程实例ID", required = true) @PathVariable String[] instanceIds,
@ApiParam(value = "删除原因") @RequestParam(required = false) String deleteReason) {
@@ -61,4 +64,4 @@ public class FlowInstanceController {
}
return AjaxResult.success();
}
}
}

View File

@@ -1,6 +1,9 @@
package com.ruoyi.flowable.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.flowable.domain.dto.FlowTaskDto;
import com.ruoyi.flowable.domain.vo.FlowQueryVo;
import com.ruoyi.flowable.domain.vo.FlowTaskVo;
@@ -29,7 +32,7 @@ import java.io.OutputStream;
@Api(tags = "工作流流程任务管理")
@RestController
@RequestMapping("/flowable/task")
public class FlowTaskController {
public class FlowTaskController extends BaseController {
@Autowired
private IFlowTaskService flowTaskService;
@@ -41,12 +44,14 @@ public class FlowTaskController {
}
@ApiOperation(value = "取消申请", response = FlowTaskDto.class)
@Log(title = "取消申请", businessType = BusinessType.UPDATE)
@PostMapping(value = "/stopProcess")
public AjaxResult stopProcess(@RequestBody FlowTaskVo flowTaskVo) {
return flowTaskService.stopProcess(flowTaskVo);
}
@ApiOperation(value = "撤回流程", response = FlowTaskDto.class)
@Log(title = "撤回流程", businessType = BusinessType.UPDATE)
@PostMapping(value = "/revokeProcess")
public AjaxResult revokeProcess(@RequestBody FlowTaskVo flowTaskVo) {
return flowTaskService.revokeProcess(flowTaskVo);
@@ -71,6 +76,12 @@ public class FlowTaskController {
return flowTaskService.flowRecord(procInsId, deployId);
}
@ApiOperation(value = "根据任务ID查询挂载的表单信息")
@GetMapping(value = "/getTaskForm")
public AjaxResult getTaskForm(String taskId) {
return flowTaskService.getTaskForm(taskId);
}
@ApiOperation(value = "流程初始化表单", response = FlowTaskDto.class)
@GetMapping(value = "/flowFormData")
@@ -85,12 +96,14 @@ public class FlowTaskController {
}
@ApiOperation(value = "审批任务")
@Log(title = "审批任务", businessType = BusinessType.UPDATE)
@PostMapping(value = "/complete")
public AjaxResult complete(@RequestBody FlowTaskVo flowTaskVo) {
return flowTaskService.complete(flowTaskVo);
}
@ApiOperation(value = "驳回任务")
@Log(title = "驳回任务", businessType = BusinessType.UPDATE)
@PostMapping(value = "/reject")
public AjaxResult taskReject(@RequestBody FlowTaskVo flowTaskVo) {
flowTaskService.taskReject(flowTaskVo);
@@ -98,6 +111,7 @@ public class FlowTaskController {
}
@ApiOperation(value = "退回任务")
@Log(title = "退回任务", businessType = BusinessType.UPDATE)
@PostMapping(value = "/return")
public AjaxResult taskReturn(@RequestBody FlowTaskVo flowTaskVo) {
flowTaskService.taskReturn(flowTaskVo);
@@ -111,6 +125,7 @@ public class FlowTaskController {
}
@ApiOperation(value = "删除任务")
@Log(title = "删除任务", businessType = BusinessType.DELETE)
@DeleteMapping(value = "/delete")
public AjaxResult delete(@RequestBody FlowTaskVo flowTaskVo) {
flowTaskService.deleteTask(flowTaskVo);
@@ -245,4 +260,18 @@ public class FlowTaskController {
return flowTaskService.flowTaskForm(taskId);
}
/**
* 流程节点信息
*
* @param procInsId 流程实例编号
* @param elementId 流程节点编号
* @return
*/
@GetMapping("/flowTaskInfo")
public AjaxResult flowTaskInfo(@RequestParam(value = "procInsId") String procInsId,
@RequestParam(value = "elementId") String elementId){
return flowTaskService.flowTaskInfo(procInsId,elementId);
}
}

View File

@@ -0,0 +1,104 @@
package com.ruoyi.flowable.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysExpression;
import com.ruoyi.system.service.ISysExpressionService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 流程达式Controller
*
* @author ruoyi
* @date 2022-12-12
*/
@RestController
@RequestMapping("/system/expression")
public class SysExpressionController extends BaseController
{
@Autowired
private ISysExpressionService sysExpressionService;
/**
* 查询流程达式列表
*/
@PreAuthorize("@ss.hasPermi('system:expression:list')")
@GetMapping("/list")
public TableDataInfo list(SysExpression sysExpression)
{
startPage();
List<SysExpression> list = sysExpressionService.selectSysExpressionList(sysExpression);
return getDataTable(list);
}
/**
* 导出流程达式列表
*/
@PreAuthorize("@ss.hasPermi('system:expression:export')")
@Log(title = "流程达式", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysExpression sysExpression)
{
List<SysExpression> list = sysExpressionService.selectSysExpressionList(sysExpression);
ExcelUtil<SysExpression> util = new ExcelUtil<SysExpression>(SysExpression.class);
util.exportExcel(response, list, "流程达式数据");
}
/**
* 获取流程达式详细信息
*/
@PreAuthorize("@ss.hasPermi('system:expression:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(sysExpressionService.selectSysExpressionById(id));
}
/**
* 新增流程达式
*/
@PreAuthorize("@ss.hasPermi('system:expression:add')")
@Log(title = "流程达式", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysExpression sysExpression)
{
return toAjax(sysExpressionService.insertSysExpression(sysExpression));
}
/**
* 修改流程达式
*/
@PreAuthorize("@ss.hasPermi('system:expression:edit')")
@Log(title = "流程达式", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysExpression sysExpression)
{
return toAjax(sysExpressionService.updateSysExpression(sysExpression));
}
/**
* 删除流程达式
*/
@PreAuthorize("@ss.hasPermi('system:expression:remove')")
@Log(title = "流程达式", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(sysExpressionService.deleteSysExpressionByIds(ids));
}
}

View File

@@ -0,0 +1,104 @@
package com.ruoyi.flowable.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysListener;
import com.ruoyi.system.service.ISysListenerService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 流程监听Controller
*
* @author Tony
* @date 2022-12-25
*/
@RestController
@RequestMapping("/system/listener")
public class SysListenerController extends BaseController
{
@Autowired
private ISysListenerService sysListenerService;
/**
* 查询流程监听列表
*/
@PreAuthorize("@ss.hasPermi('system:listener:list')")
@GetMapping("/list")
public TableDataInfo list(SysListener sysListener)
{
startPage();
List<SysListener> list = sysListenerService.selectSysListenerList(sysListener);
return getDataTable(list);
}
/**
* 导出流程监听列表
*/
@PreAuthorize("@ss.hasPermi('system:listener:export')")
@Log(title = "流程监听", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysListener sysListener)
{
List<SysListener> list = sysListenerService.selectSysListenerList(sysListener);
ExcelUtil<SysListener> util = new ExcelUtil<SysListener>(SysListener.class);
util.exportExcel(response, list, "流程监听数据");
}
/**
* 获取流程监听详细信息
*/
@PreAuthorize("@ss.hasPermi('system:listener:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(sysListenerService.selectSysListenerById(id));
}
/**
* 新增流程监听
*/
@PreAuthorize("@ss.hasPermi('system:listener:add')")
@Log(title = "流程监听", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysListener sysListener)
{
return toAjax(sysListenerService.insertSysListener(sysListener));
}
/**
* 修改流程监听
*/
@PreAuthorize("@ss.hasPermi('system:listener:edit')")
@Log(title = "流程监听", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysListener sysListener)
{
return toAjax(sysListenerService.updateSysListener(sysListener));
}
/**
* 删除流程监听
*/
@PreAuthorize("@ss.hasPermi('system:listener:remove')")
@Log(title = "流程监听", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(sysListenerService.deleteSysListenerByIds(ids));
}
}

View File

@@ -15,8 +15,19 @@ import java.util.List;
@Data
public class FlowNextDto implements Serializable {
/**
* 审批人类型
*/
private String type;
/**
* 是否需要动态指定任务审批人
*/
private String dataType;
/**
* 流程变量
*/
private String vars;
}

View File

@@ -46,7 +46,6 @@ public class FlowTaskDto implements Serializable {
@ApiModelProperty("任务执行人名称")
private String assigneeName;
@ApiModelProperty("任务执行人部门")
private String assigneeDeptName;;
@@ -60,7 +59,7 @@ public class FlowTaskDto implements Serializable {
private String category;
@ApiModelProperty("流程变量信息")
private Object procVars;
private Object variables;
@ApiModelProperty("局部变量信息")
private Object taskLocalVars;

View File

@@ -5,12 +5,13 @@ import com.googlecode.aviator.Expression;
//import com.greenpineyu.fel.FelEngine;
//import com.greenpineyu.fel.FelEngineImpl;
//import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang3.StringUtils;
//import org.apache.commons.jexl2.JexlContext;
//import org.apache.commons.jexl2.JexlEngine;
//import org.apache.commons.jexl2.MapContext;
//import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import java.util.*;
@@ -61,12 +62,17 @@ public class FindNextNodeUtil {
}
}
FlowElement flowElement = bpmnModel.getFlowElement(key);
next(flowElements, flowElement, map, data);
List<SequenceFlow> sequenceFlows = ((StartEvent)flowElement).getOutgoingFlows();
// 获取出口连线, 此时从开始节点往后,只能是一个出口
if (!sequenceFlows.isEmpty()) {
SequenceFlow sequenceFlow = sequenceFlows.get(0);
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
next(flowElements, targetFlowElement, map, data);
}
return data;
}
/**
* 查找下一节点
*
@@ -162,13 +168,13 @@ public class FindNextNodeUtil {
/**
* 判断是否是多实例子流程并且需要设置集合类型变量
*/
public static boolean checkSubProcess(String Id, Collection<FlowElement> flowElements, List<UserTask> nextUser) {
public static boolean checkSubProcess(String id, Collection<FlowElement> flowElements, List<UserTask> nextUser) {
for (FlowElement flowElement1 : flowElements) {
if (flowElement1 instanceof SubProcess && flowElement1.getId().equals(Id)) {
if (flowElement1 instanceof SubProcess && flowElement1.getId().equals(id)) {
SubProcess sp = (SubProcess) flowElement1;
if (sp.getLoopCharacteristics() != null) {
String inputDataItem = sp.getLoopCharacteristics().getInputDataItem();
// String inputDataItem = sp.getLoopCharacteristics().getInputDataItem();
UserTask userTask = new UserTask();
userTask.setId(sp.getId());
userTask.setLoopCharacteristics(sp.getLoopCharacteristics());
@@ -254,7 +260,7 @@ public class FindNextNodeUtil {
*/
public static boolean expressionResult(Map<String, Object> map, String expression) {
Expression exp = AviatorEvaluator.compile(expression);
final Object execute = exp.execute(map);
return Boolean.parseBoolean(String.valueOf(execute));
return (Boolean) exp.execute(map);
// return true;
}
}

View File

@@ -2,12 +2,14 @@ package com.ruoyi.flowable.flow;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.*;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.task.api.Task;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.history.HistoricTaskInstance;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Tony
@@ -18,6 +20,7 @@ public class FlowableUtils {
/**
* 根据节点,获取入口连线
*
* @param source
* @return
*/
@@ -39,6 +42,7 @@ public class FlowableUtils {
/**
* 根据节点,获取出口连线
*
* @param source
* @return
*/
@@ -60,6 +64,7 @@ public class FlowableUtils {
/**
* 获取全部节点列表,包含子流程节点
*
* @param flowElements
* @param allElements
* @return
@@ -79,9 +84,10 @@ public class FlowableUtils {
/**
* 迭代获取父级任务节点列表,向前找
* @param source 起始节点
*
* @param source 起始节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param userTaskList 已找到的用户任务节点
* @param userTaskList 已找到的用户任务节点
* @return
*/
public static List<UserTask> iteratorFindParentUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
@@ -98,7 +104,7 @@ public class FlowableUtils {
if (sequenceFlows != null) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -129,10 +135,11 @@ public class FlowableUtils {
/**
* 根据正在运行的任务节点,迭代获取子级任务节点列表,向后找
* @param source 起始节点(退回节点)
* @param runTaskKeyList 正在运行的任务 Key用于校验任务节点是否是正在运行的节点
*
* @param source 起始节点(退回节点)
* @param runTaskKeyList 正在运行的任务 Key用于校验任务节点是否是正在运行的节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param userTaskList 需要撤回的用户任务列表
* @param userTaskList 需要撤回的用户任务列表
* @return
*/
public static List<UserTask> iteratorFindChildUserTasks(FlowElement source, List<String> runTaskKeyList, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
@@ -149,7 +156,7 @@ public class FlowableUtils {
if (sequenceFlows != null) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -179,9 +186,10 @@ public class FlowableUtils {
/**
* 迭代获取子流程用户任务节点
* @param source 起始节点
*
* @param source 起始节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param userTaskList 需要撤回的用户任务列表
* @param userTaskList 需要撤回的用户任务列表
* @return
*/
public static List<UserTask> findChildProcessUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
@@ -193,7 +201,7 @@ public class FlowableUtils {
if (sequenceFlows != null) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -223,11 +231,12 @@ public class FlowableUtils {
/**
* 从后向前寻路,获取所有脏线路上的点
* @param source 起始节点
* @param passRoads 已经经过的点集合
*
* @param source 起始节点
* @param passRoads 已经经过的点集合
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param targets 目标脏线路终点
* @param dirtyRoads 确定为脏数据的点,因为不需要重复,因此使用 set 存储
* @param targets 目标脏线路终点
* @param dirtyRoads 确定为脏数据的点,因为不需要重复,因此使用 set 存储
* @return
*/
public static Set<String> iteratorFindDirtyRoads(FlowElement source, List<String> passRoads, Set<String> hasSequenceFlow, List<String> targets, Set<String> dirtyRoads) {
@@ -245,7 +254,7 @@ public class FlowableUtils {
if (sequenceFlows != null) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -279,9 +288,10 @@ public class FlowableUtils {
/**
* 迭代获取子流程脏路线
* 说明,假如回退的点就是子流程,那么也肯定会回退到子流程最初的用户任务节点,因此子流程中的节点全是脏路线
* @param source 起始节点
*
* @param source 起始节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param dirtyRoads 确定为脏数据的点,因为不需要重复,因此使用 set 存储
* @param dirtyRoads 确定为脏数据的点,因为不需要重复,因此使用 set 存储
* @return
*/
public static Set<String> findChildProcessAllDirtyRoad(FlowElement source, Set<String> hasSequenceFlow, Set<String> dirtyRoads) {
@@ -293,7 +303,7 @@ public class FlowableUtils {
if (sequenceFlows != null) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -315,10 +325,11 @@ public class FlowableUtils {
/**
* 判断脏路线结束节点是否在子流程上
* @param source 起始节点
*
* @param source 起始节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param targets 判断脏路线节点是否存在子流程上,只要存在一个,说明脏路线只到子流程为止
* @param inChildProcess 是否存在子流程上true 是false 否
* @param targets 判断脏路线节点是否存在子流程上,只要存在一个,说明脏路线只到子流程为止
* @param inChildProcess 是否存在子流程上true 是false 否
* @return
*/
public static Boolean dirtyTargetInChildProcess(FlowElement source, Set<String> hasSequenceFlow, List<String> targets, Boolean inChildProcess) {
@@ -330,7 +341,7 @@ public class FlowableUtils {
if (sequenceFlows != null && !inChildProcess) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -356,10 +367,11 @@ public class FlowableUtils {
/**
* 迭代从后向前扫描,判断目标节点相对于当前节点是否是串行
* 不存在直接回退到子流程中的情况,但存在从子流程出去到父流程情况
* @param source 起始节点
* @param isSequential 是否串行
*
* @param source 起始节点
* @param isSequential 是否串行
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param targetKsy 目标节点
* @param targetKsy 目标节点
* @return
*/
public static Boolean iteratorCheckSequentialReferTarget(FlowElement source, String targetKsy, Set<String> hasSequenceFlow, Boolean isSequential) {
@@ -376,7 +388,7 @@ public class FlowableUtils {
if (sequenceFlows != null) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -405,9 +417,10 @@ public class FlowableUtils {
/**
* 从后向前寻路,获取到达节点的所有路线
* 不存在直接回退到子流程,但是存在回退到父级流程的情况
* @param source 起始节点
*
* @param source 起始节点
* @param passRoads 已经经过的点集合
* @param roads 路线
* @param roads 路线
* @return
*/
public static List<List<UserTask>> findRoad(FlowElement source, List<UserTask> passRoads, Set<String> hasSequenceFlow, List<List<UserTask>> roads) {
@@ -424,7 +437,7 @@ public class FlowableUtils {
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
if (sequenceFlows != null && sequenceFlows.size() != 0) {
for (SequenceFlow sequenceFlow: sequenceFlows) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
@@ -447,7 +460,8 @@ public class FlowableUtils {
/**
* 历史节点数据清洗,清洗掉又回滚导致的脏数据
* @param allElements 全部节点信息
*
* @param allElements 全部节点信息
* @param historicTaskInstanceList 历史任务实例信息,数据采用开始时间升序
* @return
*/
@@ -541,7 +555,7 @@ public class FlowableUtils {
lastHistoricTaskInstanceList.add(stack.peek().getTaskDefinitionKey());
}
// 校验脏线路是否结束
for (int i = 0; i < deleteKeyList.size(); i ++) {
for (int i = 0; i < deleteKeyList.size(); i++) {
// 如果发现脏数据属于会签,记录下下标与对应 Key以备后续比对会签脏数据范畴开始
if (multiKey == null && multiTask.contains(stack.peek().getTaskDefinitionKey())
&& deleteKeyList.get(i).contains(stack.peek().getTaskDefinitionKey())) {
@@ -551,7 +565,7 @@ public class FlowableUtils {
// 会签脏数据处理,节点退回会签清空
// 如果在会签脏数据范畴中发现 Key改变说明会签脏数据在上个节点就结束了可以把会签脏数据删掉
if (multiKey != null && !multiKey.toString().equals(stack.peek().getTaskDefinitionKey())) {
deleteKeyList.set(multiIndex , deleteKeyList.get(multiIndex).replace(stack.peek().getTaskDefinitionKey() + ",", ""));
deleteKeyList.set(multiIndex, deleteKeyList.get(multiIndex).replace(stack.peek().getTaskDefinitionKey() + ",", ""));
multiKey = null;
// 结束进行下校验删除
multiOpera = true;
@@ -561,7 +575,7 @@ public class FlowableUtils {
// 脏数据产生的新实例中是否包含这条数据
if (multiKey == null && deleteKeyList.get(i).contains(stack.peek().getTaskDefinitionKey())) {
// 删除匹配到的部分
deleteKeyList.set(i , deleteKeyList.get(i).replace(stack.peek().getTaskDefinitionKey() + ",", ""));
deleteKeyList.set(i, deleteKeyList.get(i).replace(stack.peek().getTaskDefinitionKey() + ",", ""));
}
// 如果每组中的元素都以匹配过,说明脏数据结束
if ("".equals(deleteKeyList.get(i))) {
@@ -587,4 +601,102 @@ public class FlowableUtils {
log.info("清洗后的历史节点数据:" + lastHistoricTaskInstanceList);
return lastHistoricTaskInstanceList;
}
/**
* 从 flowElement 获取 指定名称的 拓展元素
*
* @param flowElement 元素
* @param extensionElementName 拓展元素名称
*/
public static ExtensionElement getExtensionElementFromFlowElementByName(FlowElement flowElement, String extensionElementName) {
if (flowElement == null) {
return null;
}
Map<String, List<ExtensionElement>> extensionElements = flowElement.getExtensionElements();
for (Map.Entry<String, List<ExtensionElement>> stringEntry : extensionElements.entrySet()) {
if (stringEntry.getKey().equals(extensionElementName)) {
for (ExtensionElement extensionElement : stringEntry.getValue()) {
if (extensionElement.getName().equals(extensionElementName)) {
return extensionElement;
}
}
}
}
return null;
}
/**
* 获取当前任务节点扩展属性信息
*
* @param repositoryService
* @param task 当前任务
* @return 自定义属性列表
*/
public static List<Object> getPropertyElement(RepositoryService repositoryService, org.flowable.task.api.Task task) {
FlowElement flowElement = getCurrentElement(repositoryService, task);
ExtensionElement extensionElement = FlowableUtils.getExtensionElementFromFlowElementByName(flowElement, "properties");
if (extensionElement == null) {
return Collections.emptyList();
}
return getPropertyExtensionElementByName(extensionElement, "property");
}
/**
* 获取当前任务节点
*
* @param repositoryService
* @param task
* @return
*/
public static FlowElement getCurrentElement(RepositoryService repositoryService, org.flowable.task.api.Task task) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
return bpmnModel.getFlowElement(task.getTaskDefinitionKey());
}
/**
* 根据属性名获取扩展元素中的扩展属性列表
*
* @param extensionElement 扩展元素
* @param attributesName 属性名
* @return 扩展属性列表
*/
public static List<Object> getPropertyExtensionElementByName(ExtensionElement extensionElement, String attributesName) {
try {
// 获取名称为attributesName的子元素
return Optional.ofNullable(extensionElement.getChildElements().get(attributesName))
.orElse(Collections.emptyList()) // 如果子元素不存在则返回空集合避免null引用
.stream()
.map(element -> {
// 获取子元素的属性
Map<String, List<ExtensionAttribute>> attributes = element.getAttributes();
Object propertyDto = new Object();
// 获取FlowPropertyDto的所有属性
Arrays.stream(propertyDto.getClass().getDeclaredFields())
.forEach(field -> {
field.setAccessible(true);
// 获取属性名称和值
attributes.getOrDefault(field.getName(), Collections.emptyList())
.stream()
.findFirst()
.ifPresent(attribute -> {
try {
// 反射设置属性值
field.set(propertyDto, attribute.getValue());
} catch (IllegalAccessException e) {
e.printStackTrace();
// 如果反射设置失败则忽略该属性
}
});
});
return propertyDto;
}).collect(Collectors.toList());
} catch (Exception e) {
e.printStackTrace();
return Collections.emptyList(); // 如果发生异常则返回空列表
}
}
}

View File

@@ -3,9 +3,6 @@ package com.ruoyi.flowable.service;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.flowable.domain.vo.FlowTaskVo;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
import java.util.List;
import java.util.Map;
/**

View File

@@ -154,7 +154,7 @@ public interface IFlowTaskService {
* @param taskId 任务Id
* @return
*/
Task getTaskForm(String taskId);
AjaxResult getTaskForm(String taskId);
/**
* 获取流程过程图
@@ -206,4 +206,13 @@ public interface IFlowTaskService {
* @return
*/
AjaxResult flowTaskForm(String taskId) throws Exception;
/**
* 流程节点信息
* @param procInsId
* @param elementId
* @return
*/
AjaxResult flowTaskInfo(String procInsId, String elementId);
}

View File

@@ -1,62 +0,0 @@
package com.ruoyi.flowable.service;
import com.ruoyi.system.domain.SysTaskForm;
import java.util.List;
/**
* 流程任务关联单Service接口
*
* @author Tony
* @date 2021-04-03
*/
@Deprecated
public interface ISysTaskFormService {
/**
* 查询流程任务关联单
*
* @param id 流程任务关联单ID
* @return 流程任务关联单
*/
public SysTaskForm selectSysTaskFormById(Long id);
/**
* 查询流程任务关联单列表
*
* @param sysTaskForm 流程任务关联单
* @return 流程任务关联单集合
*/
public List<SysTaskForm> selectSysTaskFormList(SysTaskForm sysTaskForm);
/**
* 新增流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
public int insertSysTaskForm(SysTaskForm sysTaskForm);
/**
* 修改流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
public int updateSysTaskForm(SysTaskForm sysTaskForm);
/**
* 批量删除流程任务关联单
*
* @param ids 需要删除的流程任务关联单ID
* @return 结果
*/
public int deleteSysTaskFormByIds(Long[] ids);
/**
* 删除流程任务关联单信息
*
* @param id 流程任务关联单ID
* @return 结果
*/
public int deleteSysTaskFormById(Long id);
}

View File

@@ -6,8 +6,8 @@ import com.github.pagehelper.PageInfo;
import com.ruoyi.flowable.common.constant.ProcessConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.system.domain.FlowProcDefDto;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.service.IFlowDefinitionService;
@@ -55,9 +55,6 @@ public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFl
@Resource
private ISysDeptService sysDeptService;
@Resource
private ISysPostService postService;
@Resource
private FlowDeployMapper flowDeployMapper;
@@ -199,19 +196,15 @@ public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFl
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUserId());
runtimeService.startProcessInstanceById(procDefId, variables);
// 流程发起时 跳过发起人节点
// SysUser sysUser = SecurityUtils.getLoginUser().getUser();
// identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
// variables.put(ProcessConstants.PROCESS_INITIATOR, "");
// ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
// // 给第一步申请人节点设置任务执行人和意见
// Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
// if (Objects.nonNull(task)) {
// taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), sysUser.getNickName() + "发起流程申请");
//// taskService.setAssignee(task.getId(), sysUser.getUserId().toString());
// taskService.complete(task.getId(), variables);
// }
ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
// 给第一步申请人节点设置任务执行人和意见
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
if (Objects.nonNull(task)) {
taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), sysUser.getNickName() + "发起流程申请");
taskService.complete(task.getId(), variables);
}
return AjaxResult.success("流程启动成功");
} catch (Exception e) {
e.printStackTrace();

View File

@@ -2,11 +2,9 @@ package com.ruoyi.flowable.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.flowable.common.constant.ProcessConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
@@ -14,10 +12,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.flowable.domain.dto.FlowCommentDto;
import com.ruoyi.flowable.domain.dto.FlowNextDto;
import com.ruoyi.flowable.domain.dto.FlowTaskDto;
import com.ruoyi.flowable.domain.dto.FlowViewerDto;
import com.ruoyi.flowable.domain.dto.*;
import com.ruoyi.flowable.domain.vo.FlowQueryVo;
import com.ruoyi.flowable.domain.vo.FlowTaskVo;
import com.ruoyi.flowable.factory.FlowServiceFactory;
@@ -38,13 +33,11 @@ import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
@@ -321,56 +314,6 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
*/
@Override
public AjaxResult findReturnTaskList(FlowTaskVo flowTaskVo) {
// // 当前任务 task
// Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// // 从流程历史任务中获取可退回节点
//// List<HistoricActivityInstance> hisActIns = historyService.createHistoricActivityInstanceQuery()
//// .executionId(task.getExecutionId())
//// .activityType("userTask")
//// .orderByHistoricActivityInstanceStartTime()
//// .finished()
//// .desc()
//// .list();
////
//// // 可回退的节点列表
//// List<ReturnTaskNodeVo> returnTaskNodeList = new ArrayList<>();
//// ReturnTaskNodeVo returnTaskNodeVo;
//// for (HistoricActivityInstance activityInstance : hisActIns) {
//// returnTaskNodeVo = new ReturnTaskNodeVo();
//// returnTaskNodeVo.setId(activityInstance.getActivityId());
//// // 根据流程节点处理时间校验改节点是否已完成
//// returnTaskNodeVo.setName(activityInstance.getActivityName());
//// returnTaskNodeList.add(returnTaskNodeVo);
//// }
// List<UserTask> userTaskList = new ArrayList<>();
// // 获取流程定义信息
// ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// // 获取所有节点信息,暂不考虑子流程情况
// Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// Collection<FlowElement> flowElements = process.getFlowElements();
// // 获取当前任务节点元素
// UserTask source = null;
// if (flowElements != null) {
// for (FlowElement flowElement : flowElements) {
// // 类型为用户节点
// if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
// source = (UserTask) flowElement;
// }
// }
// }
// // 获取节点的所有路线
// List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
//
// for (List<UserTask> road : roads) {
// if (userTaskList.size() == 0) {
// // 还没有可回退节点直接添加
// userTaskList = road;
// } else {
// // 如果已有回退节点,则比对取交集部分
// userTaskList.retainAll(road);
// }
// }
// return AjaxResult.success(userTaskList);
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// 获取流程定义信息
@@ -629,7 +572,9 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
*/
@Override
public AjaxResult revokeProcess(FlowTaskVo flowTaskVo) {
Task task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
Task task = taskService.createTaskQuery()
.processInstanceId(flowTaskVo.getInstanceId())
.singleResult();
if (task == null) {
throw new CustomException("流程未启动或已执行完成,无法撤回");
}
@@ -641,41 +586,35 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
.asc()
.list();
String myTaskId = null;
HistoricTaskInstance myTask = null;
for (HistoricTaskInstance hti : htiList) {
if (loginUser.getUserId().toString().equals(hti.getAssignee())) {
myTaskId = hti.getId();
myTask = hti;
break;
}
}
if (null == myTaskId) {
throw new CustomException("该任务非当前用户提交,无法撤回");
}
String processDefinitionId = myTask.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//变量
// Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
String myActivityId = null;
List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
.executionId(myTask.getExecutionId()).finished().list();
for (HistoricActivityInstance hai : haiList) {
if (myTaskId.equals(hai.getTaskId())) {
myActivityId = hai.getActivityId();
break;
List<HistoricTaskInstance> historicTaskInstanceList = historyService
.createHistoricTaskInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.orderByHistoricTaskInstanceStartTime()
.asc()
.list();
Iterator<HistoricTaskInstance> it = historicTaskInstanceList.iterator();
//循环节点获取当前节点的上一节点的key
String tarKey = "";
while (it.hasNext()) {
HistoricTaskInstance his = it.next();
if (!task.getTaskDefinitionKey().equals(his.getTaskDefinitionKey())) {
tarKey = his.getTaskDefinitionKey();
}
}
FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
//记录原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows());
// 跳转节点
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(flowTaskVo.getInstanceId())
.moveActivityIdTo(task.getTaskDefinitionKey(), tarKey)
.changeState();
return AjaxResult.success();
}
@@ -699,9 +638,9 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
.orderByTaskCreateTime().desc();
// TODO 传入名称查询不到数据?
// if (StringUtils.isNotBlank(queryVo.getName())){
// taskQuery.processDefinitionNameLike(queryVo.getName());
// }
if (StringUtils.isNotBlank(queryVo.getName())) {
taskQuery.processDefinitionNameLike(queryVo.getName());
}
page.setTotal(taskQuery.count());
List<Task> taskList = taskQuery.listPage(queryVo.getPageSize() * (queryVo.getPageNum() - 1), queryVo.getPageSize());
List<FlowTaskDto> flowList = new ArrayList<>();
@@ -786,9 +725,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
flowTask.setStartUserId(startUser.getNickName());
flowTask.setStartUserName(startUser.getNickName());
if(Objects.nonNull(startUser.getDept())) {
flowTask.setStartDeptName(startUser.getDept().getDeptName());
}
flowTask.setStartDeptName(Objects.nonNull(startUser.getDept()) ? startUser.getDept().getDeptName() : "");
hisTaskList.add(flowTask);
}
page.setTotal(taskInstanceQuery.count());
@@ -898,9 +835,10 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
* @return
*/
@Override
public Task getTaskForm(String taskId) {
public AjaxResult getTaskForm(String taskId) {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
return task;
SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(task.getFormKey()));
return AjaxResult.success(sysForm.getFormContent());
}
/**
@@ -1003,11 +941,6 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
*/
@Override
public AjaxResult processVariables(String taskId) {
// HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
// .processInstanceId(task.getProcessInstanceId())
// .singleResult();
// SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
// 流程变量
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
if (Objects.nonNull(historicTaskInstance)) {
@@ -1019,7 +952,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
}
/**
* 获取下一节点
* 审批任务获取下一节点
*
* @param flowTaskVo 任务
* @return
@@ -1028,64 +961,61 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
public AjaxResult getNextFlowNode(FlowTaskVo flowTaskVo) {
// 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)) {
flowNextDto.setVars(multiInstance.getInputDataItem());
flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
flowNextDto.setDataType(ProcessConstants.DYNAMIC);
} else {
// 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(userType);
flowNextDto.setDataType(dataType);
}
}
} else {
return AjaxResult.success("流程已完结", null);
}
if (Objects.isNull(task)) {
return AjaxResult.error("任务不存在或已被审批!");
}
return AjaxResult.success(flowNextDto);
// Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
Map<String, Object> variables = taskService.getVariables(task.getId());
List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables);
if (CollectionUtils.isEmpty(nextUserTask)) {
return AjaxResult.success("流程已完结!", null);
}
return getFlowAttribute(nextUserTask);
}
/**
* 获取下一节点
* 发起流程获取下一节点
*
* @param flowTaskVo 任务
* @return
*/
@Override
public AjaxResult getNextFlowNodeByStart(FlowTaskVo flowTaskVo) {
// Step 1. 查找流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(flowTaskVo.getDeploymentId()).singleResult();
// Step 1. 获取当前节点并找到下一步节点
FlowNextDto flowNextDto = new FlowNextDto();
// Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
if (Objects.isNull(processDefinition)) {
return AjaxResult.error("流程信息不存在!");
}
// Step 2. 获取下一任务节点(网关节点时需要校验表达式)
List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasksByStart(repositoryService, processDefinition, flowTaskVo.getVariables());
if (CollectionUtils.isNotEmpty(nextUserTask)) {
for (UserTask userTask : nextUserTask) {
MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
// 会签节点
if (Objects.nonNull(multiInstance)) {
flowNextDto.setVars(multiInstance.getInputDataItem());
flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
flowNextDto.setDataType(ProcessConstants.DYNAMIC);
} else {
// 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(userType);
flowNextDto.setDataType(dataType);
}
if (CollectionUtils.isEmpty(nextUserTask)) {
return AjaxResult.error("暂未查找到下一任务,请检查流程设计是否正确!");
}
return getFlowAttribute(nextUserTask);
}
/**
* 获取任务节点属性,包含自定义属性等
*
* @param nextUserTask
*/
private AjaxResult getFlowAttribute(List<UserTask> nextUserTask) {
FlowNextDto flowNextDto = new FlowNextDto();
for (UserTask userTask : nextUserTask) {
MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
// 会签节点
if (Objects.nonNull(multiInstance)) {
flowNextDto.setVars(multiInstance.getInputDataItem());
flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
flowNextDto.setDataType(ProcessConstants.DYNAMIC);
} else {
// 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(userType);
flowNextDto.setDataType(dataType);
}
}
return AjaxResult.success(flowNextDto);
@@ -1132,7 +1062,10 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
FlowViewerDto flowViewerDto = new FlowViewerDto();
flowViewerDto.setKey(s.getActivityId());
flowViewerDto.setCompleted(true);
flowViewerList.add(flowViewerDto);
// 退回节点不进行展示
if (StringUtils.isBlank(s.getDeleteReason())) {
flowViewerList.add(flowViewerDto);
}
});
// 获取代办节点
@@ -1143,6 +1076,8 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
// 保存需要代办的节点编号
listUnFinished.forEach(s -> {
// 删除已退回节点
flowViewerList.removeIf(task -> task.getKey().equals(s.getActivityId()));
FlowViewerDto flowViewerDto = new FlowViewerDto();
flowViewerDto.setKey(s.getActivityId());
flowViewerDto.setCompleted(false);
@@ -1169,11 +1104,7 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
*/
@Override
public AjaxResult flowTaskForm(String taskId) throws Exception {
JSONObject result = new JSONObject();
result.put("formKeyExist", false);
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
// 流程变量
Map<String, Object> parameters = new HashMap<>();
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
@@ -1182,36 +1113,105 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
} else {
parameters = taskService.getVariables(taskId);
}
// TODO 暂时只处理用户任务上的表单
if (flowElement instanceof UserTask) {
String formKey = ((UserTask) flowElement).getFormKey();
if (StringUtils.isNotBlank(formKey)) {
SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(formKey));
JSONObject oldVariables = JSONObject.parseObject(JSON.toJSONString(parameters.get("variables")));
List<JSONObject> oldFields = JSON.parseObject(JSON.toJSONString(oldVariables.get("fields")), new TypeReference<List<JSONObject>>() {
});
oldFields.forEach(obj -> obj.put("disabled", true));
JSONObject data = JSONObject.parseObject(sysForm.getFormContent());
List<JSONObject> newFields = JSON.parseObject(JSON.toJSONString(data.get("fields")), new TypeReference<List<JSONObject>>() {
});
oldFields.addAll(newFields);
oldVariables.put("fields", oldFields);
oldVariables.put("disabled", false);
oldVariables.put("formBtns", true);
result.put("formData", oldVariables);
result.put("formKeyExist", true);
return AjaxResult.success("", result);
} else {
result.put("formData", parameters.get("variables"));
return AjaxResult.success("", result);
}
} else {
result.put("formData", parameters.get("variables"));
return AjaxResult.success("", result);
JSONObject oldVariables = JSONObject.parseObject(JSON.toJSONString(parameters.get("formJson")));
List<JSONObject> oldFields = JSON.parseObject(JSON.toJSONString(oldVariables.get("widgetList")), new TypeReference<List<JSONObject>>() {
});
// 设置已填写的表单为禁用状态
for (JSONObject oldField : oldFields) {
JSONObject options = oldField.getJSONObject("options");
options.put("disabled", true);
}
// TODO 暂时只处理用户任务上的表单
if (StringUtils.isNotBlank(task.getFormKey())) {
SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(task.getFormKey()));
JSONObject data = JSONObject.parseObject(sysForm.getFormContent());
List<JSONObject> newFields = JSON.parseObject(JSON.toJSONString(data.get("widgetList")), new TypeReference<List<JSONObject>>() {
});
// 表单回显时 加入子表单信息到流程变量中
for (JSONObject newField : newFields) {
String key = newField.getString("id");
// 处理图片上传组件回显问题
if ("picture-upload".equals(newField.getString("type"))) {
parameters.put(key, new ArrayList<>());
} else {
parameters.put(key, null);
}
}
oldFields.addAll(newFields);
}
oldVariables.put("widgetList", oldFields);
parameters.put("formJson", oldVariables);
return AjaxResult.success(parameters);
}
/**
* 流程节点信息
*
* @param procInsId
* @param elementId
* @return
*/
@Override
public AjaxResult flowTaskInfo(String procInsId, String elementId) {
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.activityId(elementId)
.list();
// 退回任务后有多条数据 只取待办任务进行展示
list.removeIf(task -> StringUtils.isNotBlank(task.getDeleteReason()));
if (CollectionUtils.isEmpty(list)) {
return AjaxResult.success();
}
if (list.size() > 1) {
list.removeIf(task -> Objects.nonNull(task.getEndTime()));
}
HistoricActivityInstance histIns = list.get(0);
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.selectUserById(Long.parseLong(histIns.getAssignee()));
flowTask.setAssigneeId(sysUser.getUserId());
flowTask.setAssigneeName(sysUser.getNickName());
flowTask.setDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
}
// 流程变量信息
// HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
// .includeProcessVariables().finished().taskId(histIns.getTaskId()).singleResult();
// flowTask.setVariables(historicTaskInstance.getProcessVariables());
// 展示审批人员
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.selectUserById(Long.parseLong(identityLink.getUserId()));
stringBuilder.append(sysUser.getNickName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).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());
}
});
return AjaxResult.success(flowTask);
}
/**

View File

@@ -1,93 +0,0 @@
package com.ruoyi.flowable.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysTaskFormMapper;
import com.ruoyi.system.domain.SysTaskForm;
import com.ruoyi.flowable.service.ISysTaskFormService;
/**
* 流程任务关联单Service业务层处理
*
* @author Tony
* @date 2021-04-03
*/
@Service
public class SysTaskFormServiceImpl implements ISysTaskFormService
{
@Autowired
private SysTaskFormMapper sysTaskFormMapper;
/**
* 查询流程任务关联单
*
* @param id 流程任务关联单ID
* @return 流程任务关联单
*/
@Override
public SysTaskForm selectSysTaskFormById(Long id)
{
return sysTaskFormMapper.selectSysTaskFormById(id);
}
/**
* 查询流程任务关联单列表
*
* @param sysTaskForm 流程任务关联单
* @return 流程任务关联单
*/
@Override
public List<SysTaskForm> selectSysTaskFormList(SysTaskForm sysTaskForm)
{
return sysTaskFormMapper.selectSysTaskFormList(sysTaskForm);
}
/**
* 新增流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
@Override
public int insertSysTaskForm(SysTaskForm sysTaskForm)
{
return sysTaskFormMapper.insertSysTaskForm(sysTaskForm);
}
/**
* 修改流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
@Override
public int updateSysTaskForm(SysTaskForm sysTaskForm)
{
return sysTaskFormMapper.updateSysTaskForm(sysTaskForm);
}
/**
* 批量删除流程任务关联单
*
* @param ids 需要删除的流程任务关联单ID
* @return 结果
*/
@Override
public int deleteSysTaskFormByIds(Long[] ids)
{
return sysTaskFormMapper.deleteSysTaskFormByIds(ids);
}
/**
* 删除流程任务关联单信息
*
* @param id 流程任务关联单ID
* @return 结果
*/
@Override
public int deleteSysTaskFormById(Long id)
{
return sysTaskFormMapper.deleteSysTaskFormById(id);
}
}