update 添加 FlwCommonUtils 工具类,优化消息发送和用户获取逻辑

This commit is contained in:
AprilWind 2025-08-27 20:31:55 +08:00
parent 05c9528549
commit 44195984d9
8 changed files with 150 additions and 199 deletions

View File

@ -18,6 +18,7 @@ import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.utils.FlwCommonUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -206,7 +207,7 @@ public class FlwTaskController extends BaseController {
*/
@GetMapping("/currentTaskAllUser/{taskId}")
public R<List<UserDTO>> currentTaskAllUser(@PathVariable Long taskId) {
return R.ok(flwTaskService.currentTaskAllUser(List.of(taskId)));
return R.ok(FlwCommonUtils.currentTaskAllUser(List.of(taskId)));
}
/**

View File

@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.warm.flow.core.FlowEngine;
import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.Definition;
import org.dromara.warm.flow.core.entity.Instance;
@ -20,9 +21,9 @@ import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.bo.FlowCopyBo;
import org.dromara.workflow.handler.FlowProcessEventHandler;
import org.dromara.workflow.service.IFlwCommonService;
import org.dromara.workflow.service.IFlwInstanceService;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.utils.FlwCommonUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
@ -41,10 +42,8 @@ import java.util.Map;
public class WorkflowGlobalListener implements GlobalListener {
private final IFlwTaskService flwTaskService;
private final IFlwInstanceService instanceService;
private final IFlwInstanceService flwInstanceService;
private final FlowProcessEventHandler flowProcessEventHandler;
private final IFlwCommonService flwCommonService;
private final InsService insService;
/**
* 创建监听器任务创建时执行
@ -77,7 +76,7 @@ public class WorkflowGlobalListener implements GlobalListener {
FlowParams flowParams = listenerVariable.getFlowParams();
Definition definition = listenerVariable.getDefinition();
Instance instance = listenerVariable.getInstance();
String applyNodeCode = flwCommonService.applyNodeCode(definition.getId());
String applyNodeCode = FlwCommonUtils.applyNodeCode(definition.getId());
for (Task flowTask : nextTasks) {
// 如果办理或者退回并行存在需要指定办理人则直接覆盖办理人
if (variable.containsKey(flowTask.getNodeCode()) && TaskStatusEnum.isPassOrBack(flowParams.getHisStatus())) {
@ -117,6 +116,7 @@ public class WorkflowGlobalListener implements GlobalListener {
}
//申请人提交事件
Boolean submit = MapUtil.getBool(variable, FlowConstant.SUBMIT);
InsService insService = FlowEngine.insService();
if (submit != null && submit) {
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance, instance.getFlowStatus(), variable, true);
} else {
@ -127,7 +127,7 @@ public class WorkflowGlobalListener implements GlobalListener {
}
if (!BusinessStatusEnum.initialState(instance.getFlowStatus())) {
if (task != null && CollUtil.isNotEmpty(nextTasks) && nextTasks.size() == 1
&& flwCommonService.applyNodeCode(definition.getId()).equals(nextTasks.get(0).getNodeCode())) {
&& FlwCommonUtils.applyNodeCode(definition.getId()).equals(nextTasks.get(0).getNodeCode())) {
// 如果为画线指定驳回 线条指定为驳回 驳回得节点为申请人节点 则修改流程状态为退回
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance, BusinessStatusEnum.BACK.getStatus(), params, false);
// 修改流程实例状态
@ -154,17 +154,16 @@ public class WorkflowGlobalListener implements GlobalListener {
}
if (variable.containsKey(FlowConstant.FLOW_COPY_LIST)) {
List<FlowCopyBo> flowCopyList = MapUtil.get(variable, FlowConstant.FLOW_COPY_LIST, new TypeReference<>() {});
List<FlowCopyBo> flowCopyList = MapUtil.get(variable, FlowConstant.FLOW_COPY_LIST, new TypeReference<>() {
});
// 添加抄送人
flwTaskService.setCopy(task, flowCopyList);
}
if (variable.containsKey(FlowConstant.MESSAGE_TYPE)) {
List<String> messageType = MapUtil.get(variable, FlowConstant.MESSAGE_TYPE, new TypeReference<>() {});
List<String> messageType = MapUtil.get(variable, FlowConstant.MESSAGE_TYPE, new TypeReference<>() {
});
String notice = MapUtil.getStr(variable, FlowConstant.MESSAGE_NOTICE);
// 消息通知
if (CollUtil.isNotEmpty(messageType)) {
flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
}
FlwCommonUtils.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
}
insService.removeVariables(instance.getId(),
FlowConstant.FLOW_COPY_LIST,
@ -190,7 +189,7 @@ public class WorkflowGlobalListener implements GlobalListener {
if (flwTaskService.isTaskEnd(instanceId)) {
String status = BusinessStatusEnum.FINISH.getStatus();
// 更新流程状态为已完成
instanceService.updateStatus(instanceId, status);
flwInstanceService.updateStatus(instanceId, status);
log.info("流程已结束,状态更新为: {}", status);
return status;
}

View File

@ -1,41 +0,0 @@
package org.dromara.workflow.service;
import org.dromara.common.core.domain.dto.UserDTO;
import java.util.List;
/**
* 通用 工作流服务
*
* @author LionLi
*/
public interface IFlwCommonService {
/**
* 发送消息
*
* @param flowName 流程定义名称
* @param instId 实例id
* @param messageType 消息类型
* @param message 消息内容为空则发送默认配置的消息内容
*/
void sendMessage(String flowName, Long instId, List<String> messageType, String message);
/**
* 发送消息
*
* @param messageType 消息类型
* @param message 消息内容
* @param subject 邮件标题
* @param userList 接收用户
*/
void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList);
/**
* 申请人节点编码
*
* @param definitionId 流程定义id
* @return 申请人节点编码
*/
String applyNodeCode(Long definitionId);
}

View File

@ -1,7 +1,6 @@
package org.dromara.workflow.service;
import org.dromara.common.core.domain.dto.StartProcessReturnDTO;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.warm.flow.core.entity.Node;
@ -111,8 +110,8 @@ public interface IFlwTaskService {
/**
* 获取可驳回的前置节点
*
* @param taskId 任务id
* @param nowNodeCode 当前节点
* @param taskId 任务id
* @param nowNodeCode 当前节点
* @return 结果
*/
List<Node> getBackTaskNode(Long taskId, String nowNodeCode);
@ -190,14 +189,6 @@ public interface IFlwTaskService {
*/
boolean taskOperation(TaskOperationBo bo, String taskOperation);
/**
* 获取当前任务的所有办理人
*
* @param taskIds 任务id
* @return 结果
*/
List<UserDTO> currentTaskAllUser(List<Long> taskIds);
/**
* 按照节点编码查询节点
*

View File

@ -1,107 +0,0 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.UserDTO;
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.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.warm.flow.core.enums.SkipType;
import org.dromara.warm.flow.core.service.NodeService;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.service.IFlwCommonService;
import org.dromara.workflow.service.IFlwTaskService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* 工作流工具
*
* @author LionLi
*/
@ConditionalOnEnable
@Slf4j
@RequiredArgsConstructor
@Service
public class FlwCommonServiceImpl implements IFlwCommonService {
private final NodeService nodeService;
/**
* 发送消息
*
* @param flowName 流程定义名称
* @param messageType 消息类型
* @param message 消息内容为空则发送默认配置的消息内容
*/
@Override
public void sendMessage(String flowName, Long instId, List<String> messageType, String message) {
IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class);
List<FlowTask> list = flwTaskService.selectByInstId(instId);
if (StringUtils.isBlank(message)) {
message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。";
}
List<UserDTO> userList = flwTaskService.currentTaskAllUser(StreamUtils.toList(list, FlowTask::getId));
if (CollUtil.isEmpty(userList)) {
return;
}
sendMessage(messageType, message, "单据审批提醒", userList);
}
/**
* 发送消息
*
* @param messageType 消息类型
* @param message 消息内容
* @param subject 邮件标题
* @param userList 接收用户
*/
@Override
public void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList) {
for (String code : messageType) {
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
if (ObjectUtil.isEmpty(messageTypeEnum)) {
continue;
}
switch (messageTypeEnum) {
case SYSTEM_MESSAGE -> {
SseMessageDto dto = new SseMessageDto();
dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList()));
dto.setMessage(message);
SseMessageUtils.publishMessage(dto);
}
case EMAIL_MESSAGE -> {
MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), subject, message);
}
case SMS_MESSAGE -> {
//todo 短信发送
}
default -> throw new IllegalStateException("Unexpected value: " + messageTypeEnum);
}
}
}
/**
* 申请人节点编码
*
* @param definitionId 流程定义id
* @return 申请人节点编码
*/
@Override
public String applyNodeCode(Long definitionId) {
Node startNode = nodeService.getStartNode(definitionId);
Node nextNode = nodeService.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.PASS.getKey());
return nextNode.getNodeCode();
}
}

View File

@ -33,8 +33,8 @@ import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.domain.FlowCategory;
import org.dromara.workflow.domain.vo.FlowDefinitionVo;
import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.service.IFlwCommonService;
import org.dromara.workflow.service.IFlwDefinitionService;
import org.dromara.workflow.utils.FlwCommonUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -64,7 +64,6 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
private final FlowNodeMapper flowNodeMapper;
private final FlowSkipMapper flowSkipMapper;
private final FlwCategoryMapper flwCategoryMapper;
private final IFlwCommonService flwCommonService;
/**
* 查询流程定义列表
@ -121,7 +120,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, id));
List<String> errorMsg = new ArrayList<>();
if (CollUtil.isNotEmpty(flowNodes)) {
String applyNodeCode = flwCommonService.applyNodeCode(id);
String applyNodeCode = FlwCommonUtils.applyNodeCode(id);
for (FlowNode flowNode : flowNodes) {
if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) {
errorMsg.add(flowNode.getNodeName());

View File

@ -16,7 +16,6 @@ import org.dromara.common.core.domain.dto.StartProcessReturnDTO;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.ValidatorUtils;
@ -51,10 +50,10 @@ import org.dromara.workflow.domain.vo.FlowTaskVo;
import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.mapper.FlwInstanceBizExtMapper;
import org.dromara.workflow.mapper.FlwTaskMapper;
import org.dromara.workflow.service.IFlwCommonService;
import org.dromara.workflow.service.IFlwNodeExtService;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.utils.FlwCommonUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -83,12 +82,10 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
private final FlowTaskMapper flowTaskMapper;
private final FlowHisTaskMapper flowHisTaskMapper;
private final IdentifierGenerator identifierGenerator;
private final UserService userService;
private final FlwTaskMapper flwTaskMapper;
private final FlwCategoryMapper flwCategoryMapper;
private final FlowNodeMapper flowNodeMapper;
private final IFlwTaskAssigneeService flwTaskAssigneeService;
private final IFlwCommonService flwCommonService;
private final IFlwNodeExtService flwNodeExtService;
private final FlwInstanceBizExtMapper flwInstanceBizExtMapper;
@ -479,7 +476,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
Instance inst = insService.getById(task.getInstanceId());
BusinessStatusEnum.checkBackStatus(inst.getFlowStatus());
Long definitionId = task.getDefinitionId();
String applyNodeCode = flwCommonService.applyNodeCode(definitionId);
String applyNodeCode = FlwCommonUtils.applyNodeCode(definitionId);
Map<String, Object> variable = new HashMap<>();
// 消息类型
@ -600,7 +597,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
//设置按钮权限
flowTaskVo.setButtonList(flwNodeExtService.buildButtonPermissionsFromExt(flowNode.getExt()));
flowTaskVo.setNodeRatio(flowNode.getNodeRatio());
flowTaskVo.setApplyNode(flowNode.getNodeCode().equals(flwCommonService.applyNodeCode(task.getDefinitionId())));
flowTaskVo.setApplyNode(flowNode.getNodeCode().equals(FlwCommonUtils.applyNodeCode(task.getDefinitionId())));
return flowTaskVo;
}
@ -788,21 +785,6 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
return true;
}
/**
* 获取当前任务的所有办理人
*
* @param taskIds 任务id
*/
@Override
public List<UserDTO> currentTaskAllUser(List<Long> taskIds) {
// 获取与当前任务关联的用户列表
List<User> userList = FlowEngine.userService().getByAssociateds(taskIds);
if (CollUtil.isEmpty(userList)) {
return Collections.emptyList();
}
return userService.selectListByIds(StreamUtils.toList(userList, e -> Convert.toLong(e.getProcessedBy())));
}
/**
* 按照节点编码查询节点
*
@ -827,13 +809,13 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
if (CollUtil.isEmpty(bo.getTaskIdList())) {
return false;
}
List<UserDTO> userList = this.currentTaskAllUser(bo.getTaskIdList());
List<UserDTO> userList = FlwCommonUtils.currentTaskAllUser(bo.getTaskIdList());
if (CollUtil.isEmpty(userList)) {
return false;
}
List<String> messageType = bo.getMessageType();
String message = bo.getMessage();
flwCommonService.sendMessage(messageType, message, "单据审批提醒", userList);
FlwCommonUtils.sendMessage(messageType, message, "单据审批提醒", userList);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new ServiceException(e.getMessage());

View File

@ -0,0 +1,127 @@
package org.dromara.workflow.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.common.core.domain.dto.UserDTO;
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.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.warm.flow.core.FlowEngine;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.warm.flow.core.entity.User;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.service.IFlwTaskService;
import java.util.*;
/**
* 工作流工具类
*
* @author AprilWind
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FlwCommonUtils {
private static final IFlwTaskService FLW_TASK_SERVICE = SpringUtils.getBean(IFlwTaskService.class);
private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class);
private static final String DEFAULT_SUBJECT = "单据审批提醒";
/**
* 根据流程实例发送消息给当前处理人
*
* @param flowName 流程定义名称
* @param instId 流程实例ID
* @param messageType 消息类型列表
* @param message 消息内容为空则使用默认消息
*/
public static void sendMessage(String flowName, Long instId, List<String> messageType, String message) {
if (CollUtil.isEmpty(messageType)) {
return;
}
List<FlowTask> taskList = FLW_TASK_SERVICE.selectByInstId(instId);
if (CollUtil.isEmpty(taskList)) {
return;
}
if (StringUtils.isBlank(message)) {
message = "有新的【" + flowName + "】单据已经提交至您,请及时处理。";
}
List<UserDTO> userList = currentTaskAllUser(StreamUtils.toList(taskList, FlowTask::getId));
if (CollUtil.isEmpty(userList)) {
return;
}
sendMessage(messageType, message, DEFAULT_SUBJECT, userList);
}
/**
* 发送消息给指定用户列表
*
* @param messageType 消息类型列表
* @param message 消息内容
* @param subject 邮件标题
* @param userList 接收用户列表
*/
public static void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList) {
if (CollUtil.isEmpty(messageType) || CollUtil.isEmpty(userList)) {
return;
}
List<Long> userIds = new ArrayList<>(StreamUtils.toSet(userList, UserDTO::getUserId));
Set<String> emails = StreamUtils.toSet(userList, UserDTO::getEmail);
for (String code : messageType) {
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
if (ObjectUtil.isEmpty(messageTypeEnum)) {
continue;
}
switch (messageTypeEnum) {
case SYSTEM_MESSAGE -> {
SseMessageDto dto = new SseMessageDto();
dto.setUserIds(userIds);
dto.setMessage(message);
SseMessageUtils.publishMessage(dto);
}
case EMAIL_MESSAGE -> MailUtils.sendText(emails, subject, message);
case SMS_MESSAGE -> {
//todo 短信发送
}
default -> throw new IllegalStateException("Unexpected value: " + messageTypeEnum);
}
}
}
/**
* 获取申请人节点编码
*
* @param definitionId 流程定义id
* @return 申请人节点编码
*/
public static String applyNodeCode(Long definitionId) {
List<Node> firstBetweenNode = FlowEngine.nodeService().getFirstBetweenNode(definitionId, new HashMap<>());
return firstBetweenNode.get(0).getNodeCode();
}
/**
* 获取当前任务的所有办理人
*
* @param taskIds 任务id
*/
public static List<UserDTO> currentTaskAllUser(List<Long> taskIds) {
// 获取与当前任务关联的用户列表
List<User> userList = FlowEngine.userService().getByAssociateds(taskIds);
if (CollUtil.isEmpty(userList)) {
return Collections.emptyList();
}
return USER_SERVICE.selectListByIds(StreamUtils.toList(userList, e -> Convert.toLong(e.getProcessedBy())));
}
}