mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-03-29 00:33:24 +08:00
update 工作流消息推送增加前端路由跳转
This commit is contained in:
@@ -53,6 +53,14 @@ public interface UserService {
|
|||||||
*/
|
*/
|
||||||
String selectEmailById(Long userId);
|
String selectEmailById(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 用户列表
|
||||||
|
*/
|
||||||
|
UserDTO selectById(Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过用户ID查询用户列表
|
* 通过用户ID查询用户列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -641,6 +641,24 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
|||||||
return ObjectUtils.notNullGetter(sysUser, SysUser::getEmail);
|
return ObjectUtils.notNullGetter(sysUser, SysUser::getEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过用户ID查询用户
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 用户列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public UserDTO selectById(Long userId) {
|
||||||
|
SysUserVo vo = baseMapper.selectVoOne(new LambdaQueryWrapper<SysUser>()
|
||||||
|
.select(SysUser::getUserId, SysUser::getDeptId, SysUser::getUserName,
|
||||||
|
SysUser::getNickName, SysUser::getUserType, SysUser::getEmail,
|
||||||
|
SysUser::getPhoneNumber, SysUser::getGender, SysUser::getStatus,
|
||||||
|
SysUser::getCreateTime)
|
||||||
|
.eq(SysUser::getStatus, SystemConstants.NORMAL)
|
||||||
|
.eq(SysUser::getUserId, userId));
|
||||||
|
return BeanUtil.copyProperties(vo, UserDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过用户ID查询用户列表
|
* 通过用户ID查询用户列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -58,6 +58,26 @@ public interface FlowConstant {
|
|||||||
*/
|
*/
|
||||||
String MESSAGE_NOTICE = "messageNotice";
|
String MESSAGE_NOTICE = "messageNotice";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的发起页面路径。
|
||||||
|
*/
|
||||||
|
String PATH_MY_DOCUMENT = "/task/myDocument";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的待办页面路径。
|
||||||
|
*/
|
||||||
|
String PATH_TASK_WAITING = "/task/taskWaiting";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的已办页面路径。
|
||||||
|
*/
|
||||||
|
String PATH_TASK_FINISH = "/task/taskFinish";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的抄送页面路径。
|
||||||
|
*/
|
||||||
|
String PATH_TASK_COPY = "/task/taskCopyList";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务状态字典类型编码。
|
* 任务状态字典类型编码。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.common.core.domain.dto.UserDTO;
|
||||||
import org.dromara.common.core.enums.BusinessStatusEnum;
|
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||||
import org.dromara.common.core.service.UserService;
|
import org.dromara.common.core.service.UserService;
|
||||||
import org.dromara.common.core.utils.StreamUtils;
|
import org.dromara.common.core.utils.StreamUtils;
|
||||||
@@ -21,6 +22,7 @@ import org.dromara.warm.flow.core.listener.GlobalListener;
|
|||||||
import org.dromara.warm.flow.core.listener.ListenerVariable;
|
import org.dromara.warm.flow.core.listener.ListenerVariable;
|
||||||
import org.dromara.workflow.common.ConditionalOnEnable;
|
import org.dromara.workflow.common.ConditionalOnEnable;
|
||||||
import org.dromara.workflow.common.constant.FlowConstant;
|
import org.dromara.workflow.common.constant.FlowConstant;
|
||||||
|
import org.dromara.workflow.common.enums.MessageTypeEnum;
|
||||||
import org.dromara.workflow.common.enums.TaskStatusEnum;
|
import org.dromara.workflow.common.enums.TaskStatusEnum;
|
||||||
import org.dromara.workflow.domain.bo.FlowCopyBo;
|
import org.dromara.workflow.domain.bo.FlowCopyBo;
|
||||||
import org.dromara.workflow.domain.vo.NodeExtVo;
|
import org.dromara.workflow.domain.vo.NodeExtVo;
|
||||||
@@ -31,10 +33,7 @@ import org.dromara.workflow.service.IFlwNodeExtService;
|
|||||||
import org.dromara.workflow.service.IFlwTaskService;
|
import org.dromara.workflow.service.IFlwTaskService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 工作流全局监听器,处理任务流转中的扩展变量、消息和事件发布。
|
* 工作流全局监听器,处理任务流转中的扩展变量、消息和事件发布。
|
||||||
@@ -198,12 +197,14 @@ public class WorkflowGlobalListener implements GlobalListener {
|
|||||||
String status = determineFlowStatus(instance);
|
String status = determineFlowStatus(instance);
|
||||||
if (StringUtils.isNotBlank(status)) {
|
if (StringUtils.isNotBlank(status)) {
|
||||||
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance, status, params, false);
|
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance, status, params, false);
|
||||||
|
notifyInitiatorIfNeeded(definition, instance, status, variable);
|
||||||
}
|
}
|
||||||
if (!BusinessStatusEnum.initialState(instance.getFlowStatus())) {
|
if (!BusinessStatusEnum.initialState(instance.getFlowStatus())) {
|
||||||
if (task != null && CollUtil.isNotEmpty(nextTasks) && nextTasks.size() == 1
|
if (task != null && CollUtil.isNotEmpty(nextTasks) && nextTasks.size() == 1
|
||||||
&& flwCommonService.applyNodeCode(definition.getId()).equals(nextTasks.get(0).getNodeCode())) {
|
&& flwCommonService.applyNodeCode(definition.getId()).equals(nextTasks.get(0).getNodeCode())) {
|
||||||
// 如果为画线指定驳回 线条指定为驳回 驳回得节点为申请人节点 则修改流程状态为退回
|
// 如果为画线指定驳回 线条指定为驳回 驳回得节点为申请人节点 则修改流程状态为退回
|
||||||
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance, BusinessStatusEnum.BACK.getStatus(), params, false);
|
flowProcessEventHandler.processHandler(definition.getFlowCode(), instance, BusinessStatusEnum.BACK.getStatus(), params, false);
|
||||||
|
notifyInitiatorIfNeeded(definition, instance, BusinessStatusEnum.BACK.getStatus(), variable);
|
||||||
// 修改流程实例状态
|
// 修改流程实例状态
|
||||||
instance.setFlowStatus(BusinessStatusEnum.BACK.getStatus());
|
instance.setFlowStatus(BusinessStatusEnum.BACK.getStatus());
|
||||||
FlowEngine.insService().updateById(instance);
|
FlowEngine.insService().updateById(instance);
|
||||||
@@ -237,7 +238,10 @@ public class WorkflowGlobalListener implements GlobalListener {
|
|||||||
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);
|
String notice = MapUtil.getStr(variable, FlowConstant.MESSAGE_NOTICE);
|
||||||
flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
|
// 退回到申请人时只保留“已退回”结果消息,避免再追加一条“新的待办”形成重复提醒。
|
||||||
|
if (shouldSendTaskMessage(flowParams, definition, nextTasks)) {
|
||||||
|
flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FlowEngine.insService().removeVariables(instance.getId(),
|
FlowEngine.insService().removeVariables(instance.getId(),
|
||||||
FlowConstant.FLOW_COPY_LIST,
|
FlowConstant.FLOW_COPY_LIST,
|
||||||
@@ -247,6 +251,46 @@ public class WorkflowGlobalListener implements GlobalListener {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldSendTaskMessage(FlowParams flowParams, Definition definition, List<Task> nextTasks) {
|
||||||
|
if (flowParams == null || !TaskStatusEnum.BACK.getStatus().equals(flowParams.getHisStatus())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (CollUtil.isEmpty(nextTasks) || nextTasks.size() != 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 只有“退回到申请人”场景需要拦截待办提醒,其余退回/流转仍然保留待办消息。
|
||||||
|
String applyNodeCode = flwCommonService.applyNodeCode(definition.getId());
|
||||||
|
return !StringUtils.equals(applyNodeCode, nextTasks.get(0).getNodeCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyInitiatorIfNeeded(Definition definition, Instance instance, String status, Map<String, Object> variable) {
|
||||||
|
if (!StringUtils.equalsAny(status, BusinessStatusEnum.FINISH.getStatus(), BusinessStatusEnum.BACK.getStatus())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(instance.getCreateBy())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BusinessStatusEnum statusEnum = BusinessStatusEnum.getByStatus(status);
|
||||||
|
if (statusEnum == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Long createBy = Convert.toLong(instance.getCreateBy(), null);
|
||||||
|
if (createBy == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UserDTO initiator = userService.selectById(createBy);
|
||||||
|
if (initiator == null || initiator.getUserId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 已完成、已退回这类结果消息只发给发起人,不再混入处理人待办消息。
|
||||||
|
List<String> messageType = Collections.singletonList(MessageTypeEnum.SYSTEM_MESSAGE.getCode());
|
||||||
|
if (MapUtil.isNotEmpty(variable) && variable.containsKey(FlowConstant.MESSAGE_TYPE)) {
|
||||||
|
messageType = MapUtil.get(variable, FlowConstant.MESSAGE_TYPE, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
flwCommonService.sendResultMessage(definition.getFlowName(), statusEnum, messageType, Collections.singletonList(initiator));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据流程实例确定最终状态
|
* 根据流程实例确定最终状态
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.dromara.workflow.service;
|
package org.dromara.workflow.service;
|
||||||
|
|
||||||
|
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||||
import org.dromara.common.core.domain.dto.UserDTO;
|
import org.dromara.common.core.domain.dto.UserDTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -31,6 +32,27 @@ public interface IFlwCommonService {
|
|||||||
*/
|
*/
|
||||||
void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList);
|
void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送带跳转路径的消息。
|
||||||
|
*
|
||||||
|
* @param messageType 消息类型
|
||||||
|
* @param message 消息内容
|
||||||
|
* @param subject 邮件标题
|
||||||
|
* @param userList 接收用户
|
||||||
|
* @param path 前端跳转路径
|
||||||
|
*/
|
||||||
|
void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList, String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送工作流结果消息给指定用户。
|
||||||
|
*
|
||||||
|
* @param flowName 流程名称
|
||||||
|
* @param status 流程状态
|
||||||
|
* @param messageType 消息类型
|
||||||
|
* @param userList 接收用户
|
||||||
|
*/
|
||||||
|
void sendResultMessage(String flowName, BusinessStatusEnum status, List<String> messageType, List<UserDTO> userList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请人节点编码
|
* 申请人节点编码
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
import org.dromara.common.core.domain.dto.PushPayloadDTO;
|
||||||
import org.dromara.common.core.domain.dto.UserDTO;
|
import org.dromara.common.core.domain.dto.UserDTO;
|
||||||
|
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||||
import org.dromara.common.core.enums.PushSourceEnum;
|
import org.dromara.common.core.enums.PushSourceEnum;
|
||||||
import org.dromara.common.core.enums.PushTypeEnum;
|
import org.dromara.common.core.enums.PushTypeEnum;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
@@ -28,6 +29,8 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.dromara.workflow.common.constant.FlowConstant.PATH_MY_DOCUMENT;
|
||||||
|
import static org.dromara.workflow.common.constant.FlowConstant.PATH_TASK_WAITING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 工作流工具
|
* 工作流工具
|
||||||
@@ -68,7 +71,8 @@ public class FlwCommonServiceImpl implements IFlwCommonService {
|
|||||||
if (CollUtil.isEmpty(userList)) {
|
if (CollUtil.isEmpty(userList)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendMessage(messageType, message, DEFAULT_SUBJECT, userList);
|
// 发给当前处理人的工作流消息统一进入“我的待办”。
|
||||||
|
sendMessage(messageType, message, DEFAULT_SUBJECT, userList, PATH_TASK_WAITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,11 +85,27 @@ public class FlwCommonServiceImpl implements IFlwCommonService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList) {
|
public void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList) {
|
||||||
|
sendMessage(messageType, message, subject, userList, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResultMessage(String flowName, BusinessStatusEnum status, List<String> messageType, List<UserDTO> userList) {
|
||||||
|
if (status == null || CollUtil.isEmpty(messageType) || CollUtil.isEmpty(userList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 审批结果类消息面向发起人查看,统一跳转到“我发起的”。
|
||||||
|
String message = "您发起的【" + flowName + "】单据审批已" + status.getDesc() + "。";
|
||||||
|
sendMessage(messageType, message, DEFAULT_SUBJECT, userList, PATH_MY_DOCUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(List<String> messageType, String message, String subject, List<UserDTO> userList, String path) {
|
||||||
if (CollUtil.isEmpty(messageType) || CollUtil.isEmpty(userList)) {
|
if (CollUtil.isEmpty(messageType) || CollUtil.isEmpty(userList)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<Long> userIds = new ArrayList<>(StreamUtils.toSet(userList, UserDTO::getUserId));
|
List<Long> userIds = new ArrayList<>(StreamUtils.toSet(userList, UserDTO::getUserId));
|
||||||
Set<String> emails = StreamUtils.toSet(userList, UserDTO::getEmail);
|
Set<String> emails = StreamUtils.toSet(userList, UserDTO::getEmail);
|
||||||
|
emails.removeIf(StringUtils::isBlank);
|
||||||
|
|
||||||
for (String code : messageType) {
|
for (String code : messageType) {
|
||||||
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
|
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
|
||||||
@@ -95,11 +115,11 @@ public class FlwCommonServiceImpl implements IFlwCommonService {
|
|||||||
try {
|
try {
|
||||||
switch (messageTypeEnum) {
|
switch (messageTypeEnum) {
|
||||||
case SYSTEM_MESSAGE -> {
|
case SYSTEM_MESSAGE -> {
|
||||||
|
// 站内消息直接携带前端路由,消息盒子点击后可按路径分流。
|
||||||
messageService.publishMessage(userIds, PushPayloadDTO.of(
|
messageService.publishMessage(userIds, PushPayloadDTO.of(
|
||||||
PushTypeEnum.MESSAGE,
|
PushTypeEnum.MESSAGE,
|
||||||
PushSourceEnum.WORKFLOW,
|
PushSourceEnum.WORKFLOW,
|
||||||
message,
|
message, null, path
|
||||||
null
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
case EMAIL_MESSAGE -> MailUtils.sendText(emails, subject, message);
|
case EMAIL_MESSAGE -> MailUtils.sendText(emails, subject, message);
|
||||||
|
|||||||
@@ -363,6 +363,14 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
|||||||
.setAssociated(taskId));
|
.setAssociated(taskId));
|
||||||
// 批量保存抄送人员
|
// 批量保存抄送人员
|
||||||
FlowEngine.userService().saveBatch(userList);
|
FlowEngine.userService().saveBatch(userList);
|
||||||
|
// 抄送消息进入“我的抄送”,不和待办列表混用。
|
||||||
|
flwCommonService.sendMessage(
|
||||||
|
List.of(org.dromara.workflow.common.enums.MessageTypeEnum.SYSTEM_MESSAGE.getCode()),
|
||||||
|
"您收到一条新的流程抄送,请及时查看。",
|
||||||
|
"单据抄送提醒",
|
||||||
|
userService.selectListByIds(StreamUtils.toList(flowCopyList, FlowCopyBo::getUserId)),
|
||||||
|
PATH_TASK_COPY
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -824,11 +832,13 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
|||||||
userIdList.addAll(StreamUtils.toList(bo.getUserIds(), Convert::toLong));
|
userIdList.addAll(StreamUtils.toList(bo.getUserIds(), Convert::toLong));
|
||||||
}
|
}
|
||||||
if (CollUtil.isNotEmpty(userIdList)) {
|
if (CollUtil.isNotEmpty(userIdList)) {
|
||||||
|
// 转办、委托、加减签等运行时操作,消息接收人统一从“我的待办”进入处理。
|
||||||
flwCommonService.sendMessage(
|
flwCommonService.sendMessage(
|
||||||
bo.getMessageType(),
|
bo.getMessageType(),
|
||||||
StringUtils.isNotBlank(bo.getMessage()) ? bo.getMessage() : "单据「" + op.getDesc() + "」通知",
|
StringUtils.isNotBlank(bo.getMessage()) ? bo.getMessage() : "单据「" + op.getDesc() + "」通知",
|
||||||
"单据「" + op.getDesc() + "」提醒",
|
"单据「" + op.getDesc() + "」提醒",
|
||||||
userService.selectListByIds(userIdList)
|
userService.selectListByIds(userIdList),
|
||||||
|
PATH_TASK_WAITING
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -907,7 +917,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
|||||||
}
|
}
|
||||||
List<String> messageType = bo.getMessageType();
|
List<String> messageType = bo.getMessageType();
|
||||||
String message = bo.getMessage();
|
String message = bo.getMessage();
|
||||||
flwCommonService.sendMessage(messageType, message, "单据审批提醒", userList);
|
flwCommonService.sendMessage(messageType, message, "单据审批提醒", userList, PATH_TASK_WAITING);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user