update 升级warm-flow到1.3.0 调整流程办理 ,驳回,终止等 添加自定义监听

This commit is contained in:
gssong 2024-10-26 17:35:41 +08:00
parent ccf28de33d
commit 4d40a1f4fa
16 changed files with 259 additions and 150 deletions

View File

@ -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>

View File

@ -18,9 +18,9 @@ public class ProcessEvent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 流程定义key
* 流程定义编码
*/
private String key;
private String flowCode;
/**
* 业务id

View File

@ -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

View File

@ -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>

View File

@ -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));
}
/**
* 激活/挂起流程定义
*

View File

@ -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));
}
}

View File

@ -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));
}
/**

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 + "";
}
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}
}
}
/**
* 当前用户所有权限
*

View File

@ -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>