update 升级warm-flow到1.3.0 调整流程办理 ,驳回,终止等 添加自定义监听
This commit is contained in:
parent
ccf28de33d
commit
4d40a1f4fa
8
pom.xml
8
pom.xml
@ -51,7 +51,7 @@
|
||||
<!-- 面向运行时的D-ORM依赖 -->
|
||||
<anyline.version>8.7.2-20240808</anyline.version>
|
||||
<!--工作流配置-->
|
||||
<warm-flow.version>1.2.10</warm-flow.version>
|
||||
<warm-flow.version>1.3.0</warm-flow.version>
|
||||
|
||||
<!-- 插件版本 -->
|
||||
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
|
||||
@ -130,6 +130,12 @@
|
||||
<artifactId>warm-flow-plugin-spel</artifactId>
|
||||
<version>${warm-flow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.minliuhua</groupId>
|
||||
<artifactId>warm-flow-plugin-ui-sb-web</artifactId>
|
||||
<version>${warm-flow.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- JustAuth 的依赖配置-->
|
||||
<dependency>
|
||||
|
@ -18,9 +18,9 @@ public class ProcessEvent implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程定义key
|
||||
* 流程定义编码
|
||||
*/
|
||||
private String key;
|
||||
private String flowCode;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
|
@ -18,14 +18,14 @@ public class ProcessTaskEvent implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程定义key
|
||||
* 流程定义编码
|
||||
*/
|
||||
private String key;
|
||||
private String flowCode;
|
||||
|
||||
/**
|
||||
* 审批节点key
|
||||
* 审批节点编码
|
||||
*/
|
||||
private String taskDefinitionKey;
|
||||
private String nodeCode;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
|
@ -74,6 +74,10 @@
|
||||
<groupId>io.github.minliuhua</groupId>
|
||||
<artifactId>warm-flow-plugin-spel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.minliuhua</groupId>
|
||||
<artifactId>warm-flow-plugin-ui-sb-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -171,17 +171,6 @@ public class FlwDefinitionController extends BaseController {
|
||||
return R.ok("操作成功", defService.xmlString(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询流程图
|
||||
*
|
||||
* @param instanceId 流程实例id
|
||||
* @throws IOException 异常
|
||||
*/
|
||||
@GetMapping("/flowChart/{instanceId}")
|
||||
public R<String> flowChart(@PathVariable Long instanceId) throws IOException {
|
||||
return R.ok("操作成功", defService.flowChart(instanceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活/挂起流程定义
|
||||
*
|
||||
|
@ -14,6 +14,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程实例管理 控制层
|
||||
@ -107,4 +108,15 @@ public class FlwInstanceController extends BaseController {
|
||||
public TableDataInfo<FlowInstanceVo> getPageByCurrent(InstanceBo instanceBo, PageQuery pageQuery) {
|
||||
return flwInstanceService.getPageByCurrent(instanceBo, pageQuery);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取流程图,流程记录
|
||||
*
|
||||
* @param businessId 业务id
|
||||
*/
|
||||
@GetMapping("/getFlowImage/{businessId}")
|
||||
public R<Map<String, Object>> getFlowImage(@PathVariable String businessId) {
|
||||
return R.ok(flwInstanceService.getFlowImage(businessId));
|
||||
}
|
||||
}
|
||||
|
@ -158,12 +158,8 @@ public class FlwTaskController extends BaseController {
|
||||
@Log(title = "任务管理", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/terminationTask")
|
||||
public R<Instance> terminationTask(@RequestBody TerminationBo bo) {
|
||||
FlowParams flowParams = new FlowParams();
|
||||
flowParams.handler(String.valueOf(LoginHelper.getUserId()));
|
||||
flowParams.message(bo.getComment());
|
||||
flowParams.permissionFlag(WorkflowUtils.permissionList());
|
||||
return R.ok(taskService.termination(bo.getTaskId(), flowParams));
|
||||
public R<Boolean> terminationTask(@RequestBody TerminationBo bo) {
|
||||
return R.ok(flwTaskService.terminationTask(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,6 +67,11 @@ public class FlowHisTaskVo implements Serializable {
|
||||
*/
|
||||
private Integer cooperateType;
|
||||
|
||||
/**
|
||||
* 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)
|
||||
*/
|
||||
private String cooperateTypeName;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
@ -163,4 +168,9 @@ public class FlowHisTaskVo implements Serializable {
|
||||
* 流程定义编码
|
||||
*/
|
||||
private String flowCode;
|
||||
|
||||
/**
|
||||
* 运行时长
|
||||
*/
|
||||
private String runDuration;
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package org.dromara.workflow.handler;
|
||||
|
||||
import org.dromara.common.core.domain.event.ProcessEvent;
|
||||
import org.dromara.common.core.domain.event.ProcessTaskEvent;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 流程监听服务
|
||||
*
|
||||
* @author may
|
||||
* @date 2024-06-02
|
||||
*/
|
||||
@Component
|
||||
public class FlowProcessEventHandler {
|
||||
|
||||
/**
|
||||
* 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
|
||||
*
|
||||
* @param flowCode 流程定义编码
|
||||
* @param businessKey 业务id
|
||||
* @param status 状态
|
||||
* @param submit 当为true时为申请人节点办理
|
||||
*/
|
||||
public void processHandler(String flowCode, String businessKey, String status, boolean submit) {
|
||||
ProcessEvent processEvent = new ProcessEvent();
|
||||
processEvent.setFlowCode(flowCode);
|
||||
processEvent.setBusinessKey(businessKey);
|
||||
processEvent.setStatus(status);
|
||||
processEvent.setSubmit(submit);
|
||||
SpringUtils.context().publishEvent(processEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行办理任务监听
|
||||
*
|
||||
* @param flowCode 流程定义编码
|
||||
* @param nodeCode 审批节点编码
|
||||
* @param taskId 任务id
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
public void processTaskHandler(String flowCode, String nodeCode, String taskId, String businessKey) {
|
||||
ProcessTaskEvent processTaskEvent = new ProcessTaskEvent();
|
||||
processTaskEvent.setFlowCode(flowCode);
|
||||
processTaskEvent.setNodeCode(nodeCode);
|
||||
processTaskEvent.setTaskId(taskId);
|
||||
processTaskEvent.setBusinessKey(businessKey);
|
||||
SpringUtils.context().publishEvent(processTaskEvent);
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import org.dromara.workflow.domain.bo.InstanceBo;
|
||||
import org.dromara.workflow.domain.vo.FlowInstanceVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程实例 服务层
|
||||
@ -74,4 +75,12 @@ public interface IFlwInstanceService {
|
||||
* @return 结果
|
||||
*/
|
||||
TableDataInfo<FlowInstanceVo> getPageByCurrent(InstanceBo instanceBo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 获取流程图,流程记录
|
||||
*
|
||||
* @param businessId 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
Map<String, Object> getFlowImage(String businessId);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.dromara.workflow.service;
|
||||
|
||||
import com.warm.flow.core.entity.HisTask;
|
||||
import com.warm.flow.core.entity.Instance;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.workflow.domain.bo.*;
|
||||
@ -94,4 +95,12 @@ public interface IFlwTaskService {
|
||||
* @return 结果
|
||||
*/
|
||||
List<HisTask> getBackTaskNode(String instanceId);
|
||||
|
||||
/**
|
||||
* 终止任务
|
||||
*
|
||||
* @param bo 参数
|
||||
* @return 结果
|
||||
*/
|
||||
boolean terminationTask(TerminationBo bo);
|
||||
}
|
||||
|
@ -2,29 +2,24 @@ package org.dromara.workflow.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.warm.flow.core.FlowFactory;
|
||||
import com.warm.flow.core.constant.ExceptionCons;
|
||||
import com.warm.flow.core.dto.FlowParams;
|
||||
import com.warm.flow.core.entity.*;
|
||||
import com.warm.flow.core.enums.CooperateType;
|
||||
import com.warm.flow.core.enums.FlowStatus;
|
||||
import com.warm.flow.core.enums.NodeType;
|
||||
import com.warm.flow.core.enums.SkipType;
|
||||
import com.warm.flow.core.service.DefService;
|
||||
import com.warm.flow.core.service.InsService;
|
||||
import com.warm.flow.core.service.NodeService;
|
||||
import com.warm.flow.core.service.TaskService;
|
||||
import com.warm.flow.core.utils.AssertUtil;
|
||||
import com.warm.flow.core.service.*;
|
||||
import com.warm.flow.orm.entity.FlowDefinition;
|
||||
import com.warm.flow.orm.entity.FlowHisTask;
|
||||
import com.warm.flow.orm.entity.FlowInstance;
|
||||
import com.warm.flow.orm.mapper.FlowDefinitionMapper;
|
||||
import com.warm.flow.orm.mapper.FlowHisTaskMapper;
|
||||
import com.warm.flow.orm.mapper.FlowInstanceMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.UserConstants;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
@ -32,15 +27,18 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.workflow.domain.bo.FlowInstanceBo;
|
||||
import org.dromara.workflow.domain.bo.InstanceBo;
|
||||
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
|
||||
import org.dromara.workflow.domain.vo.FlowInstanceVo;
|
||||
import org.dromara.workflow.mapper.FlwInstanceMapper;
|
||||
import org.dromara.workflow.service.IFlwInstanceService;
|
||||
import org.dromara.workflow.utils.WorkflowUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程实例 服务层实现
|
||||
@ -53,9 +51,8 @@ import java.util.List;
|
||||
public class FlwInstanceServiceImpl implements IFlwInstanceService {
|
||||
|
||||
private final InsService insService;
|
||||
private final NodeService nodeService;
|
||||
private final DefService defService;
|
||||
private final TaskService taskService;
|
||||
private final FlowHisTaskMapper flowHisTaskMapper;
|
||||
private final FlowInstanceMapper flowInstanceMapper;
|
||||
private final FlwInstanceMapper flwInstanceMapper;
|
||||
private final FlowDefinitionMapper flowDefinitionMapper;
|
||||
@ -70,6 +67,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
|
||||
public TableDataInfo<FlowInstanceVo> getPageByRunning(Instance instance, PageQuery pageQuery) {
|
||||
QueryWrapper<FlowInstanceBo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("t.flow_status", FlowStatus.APPROVAL.getKey());
|
||||
queryWrapper.eq("t.del_flag", UserConstants.USER_NORMAL);
|
||||
Page<FlowInstanceVo> page = flwInstanceMapper.page(pageQuery.build(), queryWrapper);
|
||||
TableDataInfo<FlowInstanceVo> build = TableDataInfo.build();
|
||||
build.setRows(BeanUtil.copyToList(page.getRecords(), FlowInstanceVo.class));
|
||||
@ -130,38 +128,15 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
|
||||
return insService.remove(instanceIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销流程
|
||||
*
|
||||
* @param businessId 业务id
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean cancelProcessApply(String businessId) {
|
||||
FlowInstance flowInstance = instanceByBusinessId(businessId);
|
||||
if (ObjectUtil.isNull(flowInstance)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Definition definition = defService.getById(flowInstance.getDefinitionId());
|
||||
List<Task> list = taskService.list(FlowFactory.newTask().setInstanceId(flowInstance.getId()));
|
||||
// 获取已发布的流程节点
|
||||
List<Node> nodes = nodeService.getByFlowCode(definition.getFlowCode());
|
||||
AssertUtil.isTrue(CollUtil.isEmpty(nodes), ExceptionCons.NOT_PUBLISH_NODE);
|
||||
// 获取开始节点
|
||||
Node startNode = nodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null);
|
||||
AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE);
|
||||
|
||||
// 获取下一个节点,如果是网关节点,则重新获取后续节点
|
||||
//List<Node> nextNodes = FlowFactory.taskService().getNextByCheckGateWay(new FlowParams(), getFirstBetween(startNode));
|
||||
//Node node = nextNodes.get(0);
|
||||
// FlowParams flowParams = FlowParams.build().nodeCode(node.getNodeCode()).skipType(SkipType.PASS.getKey()).permissionFlag(WorkflowUtils.permissionList());
|
||||
// taskService.skip(list.get(0).getId(), flowParams);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Node getFirstBetween(Node startNode) {
|
||||
List<Skip> skips = FlowFactory.skipService().list(FlowFactory.newSkip().setDefinitionId(startNode.getDefinitionId()).setNowNodeCode(startNode.getNodeCode()));
|
||||
Skip skip = skips.get(0);
|
||||
return FlowFactory.nodeService().getOne(FlowFactory.newNode().setDefinitionId(startNode.getDefinitionId()).setNodeCode(skip.getNextNodeCode()));
|
||||
throw new RuntimeException("暂未开发");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,4 +177,58 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService {
|
||||
build.setTotal(page.getTotal());
|
||||
return build;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getFlowImage(String businessId) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
FlowInstance flowInstance = instanceByBusinessId(businessId);
|
||||
LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(FlowHisTask::getInstanceId, flowInstance.getId());
|
||||
wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey());
|
||||
wrapper.orderByDesc(FlowHisTask::getCreateTime);
|
||||
List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper);
|
||||
List<FlowHisTaskVo> list = BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class);
|
||||
for (FlowHisTaskVo vo : list) {
|
||||
vo.setCooperateTypeName(CooperateType.getValueByKey(vo.getCooperateType()));
|
||||
if (vo.getUpdateTime() != null && vo.getCreateTime() != null) {
|
||||
vo.setRunDuration(getDuration(vo.getUpdateTime().getTime() - vo.getCreateTime().getTime()));
|
||||
}
|
||||
}
|
||||
map.put("list", list);
|
||||
try {
|
||||
String flowChart = defService.flowChart(flowInstance.getId());
|
||||
map.put("image", flowChart);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务完成时间处理
|
||||
*
|
||||
* @param time 时间
|
||||
*/
|
||||
private String getDuration(long time) {
|
||||
|
||||
long day = time / (24 * 60 * 60 * 1000);
|
||||
long hour = (time / (60 * 60 * 1000) - day * 24);
|
||||
long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60);
|
||||
long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);
|
||||
|
||||
if (day > 0) {
|
||||
return day + "天" + hour + "小时" + minute + "分钟";
|
||||
}
|
||||
if (hour > 0) {
|
||||
return hour + "小时" + minute + "分钟";
|
||||
}
|
||||
if (minute > 0) {
|
||||
return minute + "分钟";
|
||||
}
|
||||
if (second > 0) {
|
||||
return second + "秒";
|
||||
} else {
|
||||
return 0 + "秒";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.warm.flow.core.dto.FlowParams;
|
||||
import com.warm.flow.core.entity.HisTask;
|
||||
import com.warm.flow.core.entity.Instance;
|
||||
import com.warm.flow.core.entity.Task;
|
||||
import com.warm.flow.core.entity.User;
|
||||
import com.warm.flow.core.entity.*;
|
||||
import com.warm.flow.core.enums.FlowStatus;
|
||||
import com.warm.flow.core.enums.NodeType;
|
||||
import com.warm.flow.core.enums.SkipType;
|
||||
import com.warm.flow.core.service.DefService;
|
||||
import com.warm.flow.core.service.InsService;
|
||||
import com.warm.flow.core.service.TaskService;
|
||||
import com.warm.flow.core.service.UserService;
|
||||
@ -32,6 +30,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.workflow.domain.bo.*;
|
||||
import org.dromara.workflow.domain.vo.*;
|
||||
import org.dromara.workflow.handler.FlowProcessEventHandler;
|
||||
import org.dromara.workflow.mapper.FlwTaskMapper;
|
||||
import org.dromara.workflow.service.IFlwInstanceService;
|
||||
import org.dromara.workflow.service.IFlwTaskService;
|
||||
@ -64,6 +63,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
private final FlowTaskMapper flowTaskMapper;
|
||||
private final FlowHisTaskMapper flowHisTaskMapper;
|
||||
private final FlowSkipMapper flowSkipMapper;
|
||||
private final FlowProcessEventHandler flowProcessEventHandler;
|
||||
private final DefService defService;
|
||||
|
||||
/**
|
||||
* 启动任务
|
||||
@ -126,14 +127,31 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
try {
|
||||
String userId = String.valueOf(LoginHelper.getUserId());
|
||||
Long taskId = completeTaskBo.getTaskId();
|
||||
FlowTask flowTask = flowTaskMapper.selectById(taskId);
|
||||
Instance ins = insService.getById(flowTask.getInstanceId());
|
||||
//流程定义
|
||||
Definition definition = defService.getById(flowTask.getDefinitionId());
|
||||
//流程提交监听
|
||||
if (FlowStatus.TOBESUBMIT.getKey().equals(ins.getFlowStatus()) || FlowStatus.REJECT.getKey().equals(ins.getFlowStatus())) {
|
||||
flowProcessEventHandler.processHandler(definition.getFlowCode(), ins.getBusinessId(), ins.getFlowStatus(), true);
|
||||
}
|
||||
//办理任务监听
|
||||
flowProcessEventHandler.processTaskHandler(definition.getFlowCode(), flowTask.getNodeCode(),
|
||||
taskId.toString(), ins.getBusinessId());
|
||||
FlowParams flowParams = new FlowParams();
|
||||
flowParams.variable(completeTaskBo.getVariables());
|
||||
flowParams.skipType(SkipType.PASS.getKey());
|
||||
flowParams.message(completeTaskBo.getMessage());
|
||||
flowParams.handler(userId);
|
||||
flowParams.permissionFlag(WorkflowUtils.permissionList());
|
||||
Instance instance = taskService.skip(taskId, flowParams);
|
||||
setHandler(instance);
|
||||
setHandler(taskService.skip(taskId, flowParams));
|
||||
//判断是否流程结束
|
||||
Instance instance = insService.getById(ins.getId());
|
||||
if (FlowStatus.isFinished(instance.getFlowStatus())) {
|
||||
//流程结束执行监听
|
||||
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance.getBusinessId(),
|
||||
FlowStatus.FINISHED.getKey(), false);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
@ -297,6 +315,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
throw new ServiceException("任务不存在!");
|
||||
}
|
||||
Long definitionId = flowTasks.get(0).getDefinitionId();
|
||||
Definition definition = defService.getById(definitionId);
|
||||
List<FlowSkip> flowSkips = flowSkipMapper.selectList(new LambdaQueryWrapper<>(FlowSkip.class).eq(FlowSkip::getDefinitionId, definitionId));
|
||||
FlowSkip flowSkip = StreamUtils.findFirst(flowSkips, e -> NodeType.START.getKey().equals(e.getNowNodeType()));
|
||||
//开始节点的下一节点
|
||||
@ -316,6 +335,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
flowParams.setPermissionFlag(WorkflowUtils.permissionList());
|
||||
Instance instance = taskService.skip(taskId, flowParams);
|
||||
setHandler(instance);
|
||||
flowProcessEventHandler.processHandler(definition.getFlowCode(),
|
||||
instance.getBusinessId(), FlowStatus.REJECT.getKey(), false);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
@ -340,4 +361,32 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止任务
|
||||
*
|
||||
* @param bo 参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean terminationTask(TerminationBo bo) {
|
||||
try {
|
||||
FlowTask flowTask = flowTaskMapper.selectById(bo.getTaskId());
|
||||
Instance ins = insService.getById(flowTask.getInstanceId());
|
||||
//流程定义
|
||||
Definition definition = defService.getById(flowTask.getDefinitionId());
|
||||
FlowParams flowParams = new FlowParams();
|
||||
flowParams.handler(String.valueOf(LoginHelper.getUserId()));
|
||||
flowParams.message(bo.getComment());
|
||||
flowParams.permissionFlag(WorkflowUtils.permissionList());
|
||||
taskService.termination(bo.getTaskId(), flowParams);
|
||||
//流程终止监听
|
||||
flowProcessEventHandler.processHandler(definition.getFlowCode(),
|
||||
ins.getBusinessId(), FlowStatus.INVALID.getKey(), false);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package org.dromara.workflow.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.warm.flow.core.enums.FlowStatus;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.event.ProcessEvent;
|
||||
@ -84,7 +85,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
|
||||
public TestLeaveVo insertByBo(TestLeaveBo bo) {
|
||||
TestLeave add = MapstructUtils.convert(bo, TestLeave.class);
|
||||
if (StringUtils.isBlank(add.getStatus())) {
|
||||
add.setStatus(BusinessStatusEnum.DRAFT.getStatus());
|
||||
add.setStatus(FlowStatus.TOBESUBMIT.getKey());
|
||||
}
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
@ -116,25 +117,25 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
|
||||
|
||||
/**
|
||||
* 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
|
||||
* 正常使用只需#processEvent.key=='leave1'
|
||||
* 正常使用只需#processEvent.flowCode=='leave1'
|
||||
* 示例为了方便则使用startsWith匹配了全部示例key
|
||||
*
|
||||
* @param processEvent 参数
|
||||
*/
|
||||
@EventListener(condition = "#processEvent.key.startsWith('leave')")
|
||||
@EventListener(condition = "#processEvent.flowCode.startsWith('leaveFlow-serial1')")
|
||||
public void processHandler(ProcessEvent processEvent) {
|
||||
log.info("当前任务执行了{}", processEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey()));
|
||||
testLeave.setStatus(processEvent.getStatus());
|
||||
if (processEvent.isSubmit()) {
|
||||
testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
testLeave.setStatus(FlowStatus.APPROVAL.getKey());
|
||||
}
|
||||
baseMapper.updateById(testLeave);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行办理任务监听
|
||||
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断
|
||||
* 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
|
||||
* 在方法中判断流程节点key
|
||||
* if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) {
|
||||
* //执行业务逻辑
|
||||
@ -142,11 +143,11 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
|
||||
*
|
||||
* @param processTaskEvent 参数
|
||||
*/
|
||||
@EventListener(condition = "#processTaskEvent.key=='leave1' && #processTaskEvent.taskDefinitionKey=='Activity_14633hx'")
|
||||
@EventListener(condition = "#processTaskEvent.flowCode=='leaveFlow-serial1' && #processTaskEvent.nodeCode=='Activity_14633hx'")
|
||||
public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
|
||||
log.info("当前任务执行了{}", processTaskEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
|
||||
testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
testLeave.setStatus(FlowStatus.APPROVAL.getKey());
|
||||
baseMapper.updateById(testLeave);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package org.dromara.workflow.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.warm.flow.core.entity.Task;
|
||||
import com.warm.flow.core.entity.User;
|
||||
import com.warm.flow.orm.entity.FlowUser;
|
||||
import lombok.AccessLevel;
|
||||
@ -14,12 +12,7 @@ import org.dromara.common.core.service.UserService;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mail.utils.MailUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.websocket.dto.WebSocketMessageDto;
|
||||
import org.dromara.common.websocket.utils.WebSocketUtils;
|
||||
import org.dromara.workflow.common.enums.MessageTypeEnum;
|
||||
import org.dromara.workflow.domain.vo.ParticipantVo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -31,56 +24,6 @@ import java.util.*;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class WorkflowUtils {
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param list 任务
|
||||
* @param name 流程名称
|
||||
* @param messageType 消息类型
|
||||
* @param message 消息内容,为空则发送默认配置的消息内容
|
||||
*/
|
||||
public static void sendMessage(List<Task> list, String name, List<String> messageType, String message, UserService userService) {
|
||||
Set<Long> userIds = new HashSet<>();
|
||||
if (StringUtils.isBlank(message)) {
|
||||
message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。";
|
||||
}
|
||||
for (Task t : list) {
|
||||
ParticipantVo taskParticipant = null; //= WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService);
|
||||
if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
|
||||
List<Long> userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
|
||||
if (CollUtil.isNotEmpty(userIdList)) {
|
||||
userIds.addAll(userIdList);
|
||||
}
|
||||
}
|
||||
List<Long> candidate = taskParticipant.getCandidate();
|
||||
if (CollUtil.isNotEmpty(candidate)) {
|
||||
userIds.addAll(candidate);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(userIds)) {
|
||||
List<UserDTO> userList = userService.selectListByIds(new ArrayList<>(userIds));
|
||||
for (String code : messageType) {
|
||||
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
|
||||
if (ObjectUtil.isNotEmpty(messageTypeEnum)) {
|
||||
switch (messageTypeEnum) {
|
||||
case SYSTEM_MESSAGE:
|
||||
WebSocketMessageDto dto = new WebSocketMessageDto();
|
||||
dto.setSessionKeys(new ArrayList<>(userIds));
|
||||
dto.setMessage(message);
|
||||
WebSocketUtils.publishMessage(dto);
|
||||
break;
|
||||
case EMAIL_MESSAGE:
|
||||
MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message);
|
||||
break;
|
||||
case SMS_MESSAGE:
|
||||
//todo 短信发送
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前用户所有权限
|
||||
*
|
||||
|
@ -1,38 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<definition flowCode="leaveFlow-serial1" flowName="串行-简单" version="1.0" fromCustom="N"
|
||||
fromPath="system/leave/approve">
|
||||
<definition flowCode="leaveFlow-serial1" flowName="串行-简单" version="1.0" formCustom="N"
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.GlobalListener.GlobalStartListener@@com.ruoyi.system.GlobalListener.GlobalAssignmentListener@@com.ruoyi.system.GlobalListener.GlobalFinishListener@@com.ruoyi.system.GlobalListener.GlobalCreateListener"
|
||||
formPath="system/leave/approve">
|
||||
<node nodeType="start" nodeCode="1" nodeName="开始" coordinate="120,280|120,280" skipAnyNode="N"
|
||||
listenerType="start,assignment,finish,permission,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@323@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.PermissionListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@com.ruoyi.system.Listener.AssignmentListener@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
<skip coordinate="140,280;230,280" skipType="PASS">2</skip>
|
||||
</node>
|
||||
<node nodeType="between" nodeCode="2" nodeName="待提交" permissionFlag="role:1,role:2" coordinate="280,280|280,280"
|
||||
skipAnyNode="N" nodeRatio="0"
|
||||
listenerType="start,assignment,finish,permission,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@323@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.PermissionListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@com.ruoyi.system.Listener.AssignmentListener@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
<skip coordinate="330,280;430,280" skipType="PASS">3</skip>
|
||||
</node>
|
||||
<node nodeType="between" nodeCode="3" nodeName="组长审批" permissionFlag="role:1,role:2"
|
||||
coordinate="480,280|480,280" skipAnyNode="Y" nodeRatio="0"
|
||||
listenerType="start,assignment,finish,permission,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@323@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.PermissionListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@com.ruoyi.system.Listener.AssignmentListener@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
<skip coordinate="530,280;650,280" skipType="PASS">4</skip>
|
||||
</node>
|
||||
<node nodeType="between" nodeCode="4" nodeName="部门经理审批" permissionFlag="role:1,role:2"
|
||||
coordinate="700,280|700,280" skipAnyNode="N" nodeRatio="0"
|
||||
listenerType="start,assignment,finish,permission,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@323@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.PermissionListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@com.ruoyi.system.Listener.AssignmentListener@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
<skip coordinate="750,280;870,280" skipType="PASS">5</skip>
|
||||
<skip coordinate="700,240;700,210;280,210;280,240" skipType="REJECT">2</skip>
|
||||
</node>
|
||||
<node nodeType="between" nodeCode="5" nodeName="hr审批" permissionFlag="warmFlowInitiator"
|
||||
coordinate="920,280|920,280" skipAnyNode="Y" nodeRatio="0"
|
||||
listenerType="start,assignment,finish,permission,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@323@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.PermissionListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@com.ruoyi.system.Listener.AssignmentListener@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.CreateListener">
|
||||
<skip coordinate="970,280;1100,280" skipType="PASS">6</skip>
|
||||
</node>
|
||||
<node nodeType="end" nodeCode="6" nodeName="结束" coordinate="1120,280|1120,280" skipAnyNode="N"
|
||||
listenerType="start,assignment,finish,permission,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@323@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.PermissionListener@@com.ruoyi.system.Listener.CreateListener"/>
|
||||
listenerType="start,assignment,finish,create"
|
||||
listenerPath="com.ruoyi.system.Listener.StartListener@@com.ruoyi.system.Listener.AssignmentListener@@com.ruoyi.system.Listener.FinishListener@@com.ruoyi.system.Listener.CreateListener"/>
|
||||
</definition>
|
||||
|
Loading…
x
Reference in New Issue
Block a user