Pārlūkot izejas kodu

bpm 增加任务分配到指定人时,发送短信通知

YunaiV 3 gadi atpakaļ
vecāks
revīzija
e3b86b3d7a

+ 39 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/message/BpmMessageConvert.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.adminserver.modules.bpm.convert.message;
+
+import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
+import org.activiti.api.task.model.Task;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.Mappings;
+import org.mapstruct.factory.Mappers;
+
+@Mapper
+public interface BpmMessageConvert {
+
+    BpmMessageConvert INSTANCE = Mappers.getMapper(BpmMessageConvert.class);
+
+    default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, SysUserDO startUser, Task task) {
+        BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
+        copyTo(processInstance, reqDTO);
+        copyTo(startUser, reqDTO);
+        copyTo(task, reqDTO);
+        return reqDTO;
+    }
+    @Mapping(source = "name", target = "processInstanceName")
+    void copyTo(ProcessInstance from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to);
+    @Mappings({
+            @Mapping(source = "id", target = "startUserId"),
+            @Mapping(source = "nickname", target = "startUserNickname")
+    })
+    void copyTo(SysUserDO from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to);
+    @Mappings({
+            @Mapping(source = "id", target = "taskId"),
+            @Mapping(source = "name", target = "taskName"),
+            @Mapping(source = "assignee", target = "assigneeUserId")
+    })
+    void copyTo(Task task, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to);
+
+}

+ 26 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/message/BpmMessageEnum.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.adminserver.modules.bpm.enums.message;
+
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Bpm 消息的枚举
+ *
+ * @author 芋道源码
+ */
+@AllArgsConstructor
+@Getter
+public enum BpmMessageEnum {
+
+    TASK_ASSIGNED("bpm_task_assigned"); // 任务被分配时,发送给审批人
+
+    /**
+     * 短信模板的标识
+     *
+     * 关联 {@link SysSmsTemplateDO#getCode()}
+     */
+    private final String smsCode;
+
+
+}

+ 6 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTaskEventListener.java

@@ -53,6 +53,12 @@ public class BpmTaskEventListener<T extends RuntimeEvent<?, ?>>
             return;
         }
 
+        // 审核人修改时,进行拓展表,并额外发送通知
+        if (event.getEventType() == TaskRuntimeEvent.TaskEvents.TASK_ASSIGNED) {
+            taskService.updateTaskExtAssign(event.getEntity());
+            return;
+        }
+
         // 其它事件,进行更新拓展表
         taskService.updateTaskExt(event.getEntity());
     }

+ 18 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/BpmMessageService.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.adminserver.modules.bpm.service.message;
+
+import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
+
+import javax.validation.Valid;
+
+/**
+ * BPM 消息 Service 接口
+ *
+ * TODO 芋艿:未来支持消息的可配置;不同的流程,在什么场景下,需要发送什么消息,消息的内容是什么;
+ *
+ * @author 芋道源码
+ */
+public interface BpmMessageService {
+
+    void sendMessageWhenTaskAssigned(@Valid BpmMessageSendWhenTaskCreatedReqDTO reqDTO);
+
+}

+ 46 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+ * BPM 发送任务创建的 Request DTO
+ */
+@Data
+public class BpmMessageSendWhenTaskCreatedReqDTO {
+
+    /**
+     * 流程实例的编号
+     */
+    @NotEmpty(message = "流程实例的编号不能为空")
+    private String processInstanceId;
+    /**
+     * 流程实例的名字
+     */
+    @NotEmpty(message = "流程实例的名字不能为空")
+    private String processInstanceName;
+    @NotEmpty(message = "发起人的用户编号")
+    private String startUserId;
+    @NotEmpty(message = "发起人的昵称")
+    private String startUserNickname;
+
+    /**
+     * 流程任务的编号
+     */
+    @NotEmpty(message = "流程任务的编号不能为空")
+    private String taskId;
+    /**
+     * 流程任务的名字
+     */
+    @NotEmpty(message = "流程任务的名字不能为空")
+    private String taskName;
+
+    /**
+     * 审批人的用户编号
+     */
+    @NotNull(message = "审批人的用户编号不能为空")
+    private Long assigneeUserId;
+
+}

+ 47 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/impl/BpmMessageServiceImpl.java

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.adminserver.modules.bpm.service.message.impl;
+
+import cn.iocoder.yudao.adminserver.modules.bpm.enums.message.BpmMessageEnum;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
+import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * BPM 消息 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmMessageServiceImpl implements BpmMessageService {
+
+    @Resource
+    private SysSmsCoreService smsCoreService;
+
+    @Value("${yudao.url.admin-ui}")
+    private String adminUiUrl;
+
+    @Override
+    public void sendMessageWhenTaskAssigned(BpmMessageSendWhenTaskCreatedReqDTO reqDTO) {
+        Map<String, Object> templateParams = new HashMap<>();
+        templateParams.put("processInstanceName", reqDTO.getProcessInstanceName());
+        templateParams.put("taskName", reqDTO.getTaskName());
+        templateParams.put("startUserNickname", reqDTO.getStartUserNickname());
+        templateParams.put("taskDetailUrl", getTaskDetailUrl(reqDTO.getTaskId()));
+        smsCoreService.sendSingleSmsToAdmin(null, reqDTO.getAssigneeUserId(),
+                BpmMessageEnum.TASK_ASSIGNED.getSmsCode(), templateParams);
+    }
+
+    private String getTaskDetailUrl(String taskId) {
+        return adminUiUrl + "bpm/process-instance/detail?id=" + taskId;
+    }
+
+}

+ 8 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java

@@ -127,6 +127,13 @@ public interface BpmTaskService {
     void updateTaskExt(org.activiti.api.task.model.Task task);
 
     /**
+     * 更新 Task 拓展记录,并发送通知
+     *
+     * @param task 任务实体
+     */
+    void updateTaskExtAssign(org.activiti.api.task.model.Task task);
+
+    /**
      * 更新 Task 拓展记录为取消
      *
      * @param task 任务实体
@@ -148,4 +155,5 @@ public interface BpmTaskService {
      */
     List<BpmTaskExtDO> getTaskExtListByProcessInstanceId(String processInstanceId);
 
+
 }

+ 23 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java

@@ -1,12 +1,15 @@
 package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*;
+import cn.iocoder.yudao.adminserver.modules.bpm.convert.message.BpmMessageConvert;
 import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO;
 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmTaskExtMapper;
 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
@@ -29,10 +32,13 @@ import org.activiti.engine.task.TaskQuery;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -61,6 +67,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
     @Resource
     @Lazy // 解决循环依赖
     private BpmProcessInstanceService processInstanceService;
+    @Resource
+    private BpmMessageService messageService;
 
     @Resource
     private BpmTaskExtMapper taskExtMapper;
@@ -278,6 +286,21 @@ public class BpmTaskServiceImpl implements BpmTaskService {
     }
 
     @Override
+    public void updateTaskExtAssign(org.activiti.api.task.model.Task task) {
+        // 更新
+        updateTaskExt(task);
+        // 发送通知。由于 Activiti 操作是在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+            @Override
+            public void afterCommit() {
+                ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
+                SysUserDO startUser = userService.getUser(Long.valueOf(processInstance.getStartUserId()));
+                messageService.sendMessageWhenTaskAssigned(BpmMessageConvert.INSTANCE.convert(processInstance, startUser, task));
+            }
+        });
+    }
+
+    @Override
     public void updateTaskExtCancel(org.activiti.api.task.model.Task task) {
         BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task)
                 .setEndTime(new Date()) // 由于 Task 里没有办法拿到 endTime,所以这里设置

+ 2 - 0
yudao-admin-server/src/main/resources/application.yaml

@@ -72,5 +72,7 @@ yudao:
       - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants
   tenant: # 多租户相关配置项
     tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置
+  url:
+    admin-ui: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址
 
 debug: false