From 59749c51d8d50b6493b508956097f09c437d9a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E6=97=A0=E6=B6=AF?= <2637171921@qq.com> Date: Wed, 27 Aug 2025 17:34:29 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=93=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../disciplinary/ArchivingNotifyListener.java | 85 ++++++++-- .../disciplinary/GenericMessageListener.java | 2 +- .../InitiatorNotificationListener.java | 2 +- .../MessageProcessorListener.java | 2 +- .../MultiInstanceMessageListener.java | 2 +- .../SchoolLeaderApprovalListener.java | 85 +++++++--- .../disciplinary/StuInfoListener.java | 146 ++++++++++++++---- .../disciplinary/XSJYGLKListener.java | 2 +- .../disciplinary/XYWJCLWYHListener.java | 2 +- ...StuDisciplinaryApplicationServiceImpl.java | 2 +- 10 files changed, 254 insertions(+), 76 deletions(-) diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/ArchivingNotifyListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/ArchivingNotifyListener.java index 3619a28..eb5710c 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/ArchivingNotifyListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/ArchivingNotifyListener.java @@ -1,55 +1,106 @@ package com.srs.flowable.listener.disciplinary; +import com.srs.common.utils.SecurityUtils; import com.srs.common.utils.WeChatUtil; import com.srs.common.utils.spring.SpringUtils; +import com.srs.comprehensive.domain.CphMsg; +import com.srs.comprehensive.service.ICphMsgService; import com.srs.flowable.mapper.DisciplinaryMapper; import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.SequenceFlow; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.ExecutionListener; import org.springframework.stereotype.Component; import java.util.List; /** - * 执行监听器:在“学生教育管理科审批归档”节点开始时, 知无涯 - * 向负责归档的角色发送企业微信通知。 + * 为“学生教育管理科审批归档”节点做准备 知无涯 + *
+ * 它的职责包括: + * 1. 主动清理上一个节点残留的变量。 + * 2. 查询“学生教育管理科归档”组的成员。 + * 3. 向所有成员发送企业微信通知。 + * 4. 为所有成员创建内部消息。 + *
*/ -@Component +@Component("archivingNotifyListener") // 明确指定Bean名称 @Slf4j public class ArchivingNotifyListener implements ExecutionListener { @Override - public void notify(DelegateExecution delegateExecution) { - log.info("流程实例 [{}]: 已进入学生教育管理科审批归档节点,准备发送通知。", delegateExecution.getProcessInstanceId()); + public void notify(DelegateExecution execution) { + log.info("流程实例 [{}]: 触发 ArchivingNotifyListener (一体化),为'学生教育管理科审批归档'节点发送所有通知...", execution.getProcessInstanceId()); + + // --- 步骤 1: 主动清理上一个节点残留的流程变量 --- + if (execution.hasVariable("approval")) { + execution.removeVariable("approval"); + log.info("已清理上一个节点残留的 'approval' 变量。"); + } + if (execution.hasVariable("userList")) { + execution.removeVariable("userList"); + log.info("已清理上一个节点残留的 'userList' 变量。"); + } try { DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + ICphMsgService cphMsgService = SpringUtils.getBean(ICphMsgService.class); + WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); - // 1. 【核心】定义负责归档的角色的 role_key。 + // --- 步骤 2: 查询“学生教育管理科归档”组的成员 --- final String ARCHIVING_ROLE_KEY = "xsjyglkspgd"; - - // 2. 根据角色Key查询用户ID列表 List* 该监听器被设计为在SequenceFlow的'take'事件上触发。 * 它会智能地从流程变量中读取单个接收人(变量名: approval)或多个接收人(变量名: userList), diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorNotificationListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorNotificationListener.java index c3e8ff7..b0efd5d 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorNotificationListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorNotificationListener.java @@ -13,7 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** - * 【线上专用监听器】在流程结果返回给发起人时, + * 在流程结果返回给发起人时, 知无涯 * 负责发送企业微信和内部消息两种通知。 */ @Component("initiatorNotificationListener") // 使用一个全新的、明确的Bean名称 diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MessageProcessorListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MessageProcessorListener.java index 4ebd9c7..1a5acda 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MessageProcessorListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MessageProcessorListener.java @@ -13,7 +13,7 @@ import javax.annotation.PostConstruct; import java.util.List; /** - * 【任务监听器】在任务完成后,删除内部消息。 + * 【任务监听器】在任务完成后,删除内部消息。 知无涯 *
* 该监听器被设计为在UserTask的'complete'事件上触发。 * 它通过解析消息内容中的隐藏HTML标识来找到与当前已完成任务关联的消息, diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MultiInstanceMessageListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MultiInstanceMessageListener.java index 475da2b..505dda3 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MultiInstanceMessageListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MultiInstanceMessageListener.java @@ -14,7 +14,7 @@ import org.springframework.stereotype.Component; import java.util.List; /** - * 【多实例专用线上监听器】为即将到来的多实例任务创建内部消息。 + * 为即将到来的多实例任务创建内部消息。 知无涯 *
* 它只从流程变量 `userList` 中读取接收人列表。 *
diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/SchoolLeaderApprovalListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/SchoolLeaderApprovalListener.java index 5bc4cfa..7cc5c74 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/SchoolLeaderApprovalListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/SchoolLeaderApprovalListener.java @@ -1,55 +1,104 @@ package com.srs.flowable.listener.disciplinary; +import com.srs.common.utils.SecurityUtils; import com.srs.common.utils.WeChatUtil; import com.srs.common.utils.spring.SpringUtils; +import com.srs.comprehensive.domain.CphMsg; +import com.srs.comprehensive.service.ICphMsgService; import com.srs.flowable.mapper.DisciplinaryMapper; import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.SequenceFlow; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.ExecutionListener; import org.springframework.stereotype.Component; import java.util.List; /** - * 执行监听器:在“校领导审批”节点开始时,向校领导发送企业微信通知。 知无涯 - * (简化版:因为流程能到达此节点,即表示前序节点已全票通过) + * 为“校领导审批”节点做准备 知无涯 + *+ * 它的职责包括: + * 1. 主动清理上一个节点残留的变量。 + * 2. 查询校领导组成员。 + * 3. 向所有成员发送企业微信通知。 + * 4. 为所有成员创建内部消息。 + *
*/ -@Component +@Component("schoolLeaderApprovalListener") @Slf4j public class SchoolLeaderApprovalListener implements ExecutionListener { @Override - public void notify(DelegateExecution delegateExecution) { - log.info("流程实例 [{}]: 已进入校领导审批节点,准备发送通知。", delegateExecution.getProcessInstanceId()); + public void notify(DelegateExecution execution) { + log.info("流程实例 [{}]: 触发 SchoolLeaderApprovalListener (一体化),为'校领导审批'节点发送所有通知...", execution.getProcessInstanceId()); + + // --- 步骤 1: 主动清理上一个节点残留的流程变量 --- + if (execution.hasVariable("approval")) { + execution.removeVariable("approval"); + log.info("已清理上一个节点残留的 'approval' 变量。"); + } + if (execution.hasVariable("userList")) { + execution.removeVariable("userList"); + log.info("已清理上一个节点残留的 'userList' 变量。"); + } try { DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + ICphMsgService cphMsgService = SpringUtils.getBean(ICphMsgService.class); + WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); - // 1. 【核心】定义“校领导”这个角色的 role_key + // --- 步骤 2: 查询校领导组成员 --- final String LEADER_ROLE_KEY = "xldsp"; - - // 2. 根据角色Key查询用户ID列表 List+ * 它的核心职责是: + * 1. 从流程变量 'stuId' 中获取学生ID。 + * 2. 将学生ID设置到 'approval' 流程变量中,供下一个UserTask分配办理人。 + * 3. 向该学生发送企业微信通知。 + * 4. 为该学生创建内部消息,并确保任务名正确。 + *
*/ -@Component +@Component("stuInfoListener") // 保持Bean名称不变 @Slf4j public class StuInfoListener implements ExecutionListener { + @Autowired + private DisciplinaryMapper disciplinaryMapper; + + @Autowired + private ICphMsgService cphMsgService; + + @Autowired(required = false) + private WeChatUtil weChatUtil; + + @PostConstruct + public void checkDependencies() { + Assert.notNull(disciplinaryMapper, "DisciplinaryMapper in StuInfoListener is not injected!"); + Assert.notNull(cphMsgService, "ICphMsgService in StuInfoListener is not injected!"); + } + @Override - public void notify(DelegateExecution delegateExecution) { - // 1. 从流程变量中获取学生ID - Object stuIdObj = delegateExecution.getVariable("stuId"); + public void notify(DelegateExecution execution) { + log.info("流程实例 [{}]: 触发 StuInfoListener (一体化版),为'学生接收'节点准备数据并发送通知...", execution.getProcessInstanceId()); - // 安全检查:确保stuId存在且类型正确 - if (!(stuIdObj instanceof Long)) { - log.error("流程实例 [{}] 在结束时未能获取到有效的 'stuId' 变量,无法发送最终通知。", delegateExecution.getProcessInstanceId()); - return; + // --- 步骤 1: 安全地获取学生ID --- + Object stuIdObj = execution.getVariable("stuId"); + if (stuIdObj == null) { + throw new IllegalStateException("核心流程变量 'stuId' 未找到。"); } - Long stuId = (Long) stuIdObj; - log.info("流程实例 [{}] 即将结束,准备向学生ID: {} 发送最终通知。", delegateExecution.getProcessInstanceId(), stuId); - // 2. 向该学生发送企业微信通知 + Long stuId; try { - DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + stuId = Long.parseLong(stuIdObj.toString()); + } catch (NumberFormatException e) { + throw new IllegalStateException("流程变量 'stuId' 类型错误。"); + } - // 根据学生ID查询其对应的企业微信账号(userName) - String userName = disciplinaryMapper.getUserNameByUserId(stuId); + // --- 步骤 2: (核心) 设置下一个任务的办理人 --- + execution.setVariable("approval", stuId); + log.info("已成功将下一个任务的办理人('approval')设置为学生ID: {}", stuId); - // 检查是否找到了对应的企业微信账号 - if (!StringUtils.hasText(userName)) { - log.warn("流程实例 [{}]: 根据学生ID '{}' 未找到对应的企业微信账号,无法发送最终通知。", delegateExecution.getProcessInstanceId(), stuId); - return; // 中止发送逻辑 + // --- 步骤 3: (可选) 发送企业微信通知 --- + sendWeChatNotification(stuId); + + // --- 步骤 4: (关键新增) 创建内部消息,并确保任务名正确 --- + createInternalMessage(stuId, execution); + } + + /** + * 发送企业微信通知的私有方法 + */ + private void sendWeChatNotification(Long stuId) { + if (weChatUtil != null) { + try { + String studentUserName = disciplinaryMapper.getUserNameByUserId(stuId); + if (studentUserName != null && !studentUserName.isEmpty()) { + String content = "同学你好,关于你的一项违纪处分申请已有最终结果,请登录系统在'我的待办'中查看并确认。"; + weChatUtil.sendTextMessage(studentUserName, content); + log.info("已成功向学生 (ID:{}) 发送企业微信通知。", stuId); + } else { + log.warn("未找到学生 (ID:{}) 对应的企业微信账号,未发送通知。", stuId); + } + } catch (Exception e) { + log.error("向学生 (ID:{}) 发送企业微信时发生异常: {}", stuId, e.getMessage(), e); } - - // 3. 构建并发送通知内容 - WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); - String content = "您好,关于您的违纪处理流程已办结,最终结果已生成。请点击登录系统查看详情。"; - - weChatUtil.sendTextMessage(userName, content); - log.info("流程实例 [{}]: 已成功向学生ID '{}' (企业微信账号: {}) 发送了流程办结通知。", delegateExecution.getProcessInstanceId(), stuId, userName); - - } catch (Exception e) { - // 即使通知失败,也不应影响流程的正常结束 - log.error("流程实例 [{}]: 在向学生ID '{}' 发送最终通知时出现异常。错误详情: {}", - delegateExecution.getProcessInstanceId(), stuId, e.getMessage(), e); } } + + /** + * 创建内部消息的私有方法 + */ + private void createInternalMessage(Long receiverId, DelegateExecution execution) { + try { + FlowElement nextElement = getNextFlowElement(execution); +// String taskName = (nextElement != null && nextElement.getName() != null) ? nextElement.getName() : "结果确认"; +// String activityId = (nextElement != null) ? nextElement.getId() : "Activity_0iy3ij6"; // 备用ID + String taskName = "学生接收"; + String activityId = "Activity_0iy3ij6"; // 备用ID + + + String messageText = "您有一条新的【" + taskName + "】待办任务需要处理。"; + String link = "请点击前往处理。"; + String hiddenIdentifier = String.format("", + execution.getProcessInstanceId(), activityId); + String internalMessageContent = messageText + link + hiddenIdentifier; + + Long senderId = SecurityUtils.getUserId() != null ? SecurityUtils.getUserId() : 1L; + + CphMsg cphMsg = new CphMsg(); + cphMsg.setReceiver(receiverId); + cphMsg.setSender(senderId); + cphMsg.setContent(internalMessageContent); + + cphMsgService.insertCphMsg(cphMsg); + log.info("已成功为学生 (ID:{}) 创建内部消息。", receiverId); + } catch (Exception e) { + log.error("为学生 (ID:{}) 创建内部消息时发生异常: {}", receiverId, e.getMessage(), e); + } + } + + /** + * 安全地获取线上监听器的下一个目标节点 + */ + private FlowElement getNextFlowElement(DelegateExecution execution) { + if (execution.getCurrentFlowElement() instanceof SequenceFlow) { + return ((SequenceFlow) execution.getCurrentFlowElement()).getTargetFlowElement(); + } + return null; + } } \ No newline at end of file diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XSJYGLKListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XSJYGLKListener.java index adc1f54..1db63d0 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XSJYGLKListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XSJYGLKListener.java @@ -10,7 +10,7 @@ import org.springframework.stereotype.Component; import java.util.List; /** - * 【线上监听器-升级版】为“学生教育管理科审核”节点做准备。 + * 为“学生教育管理科审核”节点做准备。 知无涯 * 1. 向该候选组的所有成员发送企业微信通知。 * 2. 将该组的所有成员ID列表存入 'userList' 流程变量,供下游监听器(GenericMessageListener)使用。 */ diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XYWJCLWYHListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XYWJCLWYHListener.java index 4de3ea2..a29c0be 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XYWJCLWYHListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XYWJCLWYHListener.java @@ -14,7 +14,7 @@ import org.springframework.util.CollectionUtils; import java.util.List; /** - * 【生产者线上监听器】为“学院违纪处理委员会”多实例任务准备数据。 + * 为“学院违纪处理委员会”多实例任务准备数据。 知无涯 * 1. 设置 'userList' 变量供多实例节点本身消费。 * 2. 设置 'nextTaskNameForMessage' 变量供下游消息监听器消费。 * 3. 发送企业微信通知。 diff --git a/srs-routine/src/main/java/com/srs/routine/service/impl/RtStuDisciplinaryApplicationServiceImpl.java b/srs-routine/src/main/java/com/srs/routine/service/impl/RtStuDisciplinaryApplicationServiceImpl.java index 3a2053e..2b747e5 100644 --- a/srs-routine/src/main/java/com/srs/routine/service/impl/RtStuDisciplinaryApplicationServiceImpl.java +++ b/srs-routine/src/main/java/com/srs/routine/service/impl/RtStuDisciplinaryApplicationServiceImpl.java @@ -265,7 +265,7 @@ public class RtStuDisciplinaryApplicationServiceImpl extends ServiceImpl