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 new file mode 100644 index 0000000..3619a28 --- /dev/null +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/ArchivingNotifyListener.java @@ -0,0 +1,55 @@ +package com.srs.flowable.listener.disciplinary; + +import com.srs.common.utils.WeChatUtil; +import com.srs.common.utils.spring.SpringUtils; +import com.srs.flowable.mapper.DisciplinaryMapper; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.stereotype.Component; +import java.util.List; + +/** + * 执行监听器:在“学生教育管理科审批归档”节点开始时, 知无涯 + * 向负责归档的角色发送企业微信通知。 + */ +@Component +@Slf4j +public class ArchivingNotifyListener implements ExecutionListener { + + @Override + public void notify(DelegateExecution delegateExecution) { + log.info("流程实例 [{}]: 已进入学生教育管理科审批归档节点,准备发送通知。", delegateExecution.getProcessInstanceId()); + + try { + DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + + // 1. 【核心】定义负责归档的角色的 role_key。 + final String ARCHIVING_ROLE_KEY = "xsjyglkspgd"; + + // 2. 根据角色Key查询用户ID列表 + List userIdList = disciplinaryMapper.getApprovalByRoleKey(ARCHIVING_ROLE_KEY); + + if (userIdList == null || userIdList.isEmpty()) { + log.warn("根据角色Key '{}' 未找到任何归档人员,无法发送通知。", ARCHIVING_ROLE_KEY); + return; + } + + // 3. 批量查询 userName 并发送通知 + List userNameList = disciplinaryMapper.getUserNamesByUserIdList(userIdList); + if (!userNameList.isEmpty()) { + String toUser = String.join("|", userNameList); + WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); + String content = "您有一条新的学生违纪归档任务待处理,请点击前往处理。"; + + weChatUtil.sendTextMessage(toUser, content); + log.info("已成功向归档角色 ({}) 发送通知。接收人: {}", ARCHIVING_ROLE_KEY, toUser); + } else { + log.warn("角色 '{}' 中找到了 {} 个用户,但无人配置企业微信账号,未发送任何通知。", ARCHIVING_ROLE_KEY, userIdList.size()); + } + + } catch (Exception e) { + log.error("向归档角色发送企业微信通知时出现异常。流程将继续。错误详情: {}", e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/EJXYSJListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/EJXYSJListener.java index 28ab42a..8f48c95 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/EJXYSJListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/EJXYSJListener.java @@ -9,7 +9,7 @@ import org.flowable.engine.delegate.ExecutionListener; import org.springframework.stereotype.Component; /** - * 根据辅导员部门id获取二级学院书记 + * 根据辅导员部门id获取二级学院书记 知无涯 */ @Component @Slf4j diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorResultListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorResultListener.java new file mode 100644 index 0000000..0aede46 --- /dev/null +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/InitiatorResultListener.java @@ -0,0 +1,61 @@ +package com.srs.flowable.listener.disciplinary; + +import com.srs.common.utils.WeChatUtil; +import com.srs.common.utils.spring.SpringUtils; +import com.srs.flowable.mapper.DisciplinaryMapper; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.stereotype.Component; + +/** + * 执行监听器:在“申请人(辅导员)接收”节点开始时, 知无涯 + * 向流程发起人发送企业微信通知,告知其结果已出。 + */ +@Component +@Slf4j +public class InitiatorResultListener implements ExecutionListener { + + @Override + public void notify(DelegateExecution delegateExecution) { + log.info("流程实例 [{}]: 已进入辅导员接收结果节点,准备向发起人发送通知。", delegateExecution.getProcessInstanceId()); + + try { + DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + + // 1. 从流程变量中获取发起人的ID。Flowable会自动将发起人ID存入名为 "INITIATOR" 的变量中。 + // 这个变量通常是 String 类型。 + Object initiatorObj = delegateExecution.getVariable("INITIATOR"); + if (initiatorObj == null) { + log.warn("在流程实例 [{}] 中未找到发起人(INITIATOR)变量,无法发送通知。", delegateExecution.getProcessInstanceId()); + return; + } + + // 2. 将发起人ID转换为 Long 类型,以便查询数据库 + Long initiatorUserId; + try { + initiatorUserId = Long.parseLong(initiatorObj.toString()); + } catch (NumberFormatException e) { + log.error("发起人(INITIATOR)变量 '{}' 无法转换为Long类型,无法发送通知。", initiatorObj); + return; + } + + // 3. 使用 initiatorUserId 查询对应的企业微信 userName + String initiatorUserName = disciplinaryMapper.getUserNameByUserId(initiatorUserId); + + if (initiatorUserName != null && !initiatorUserName.isEmpty()) { + // 4. 发送通知 + WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); + String content = "您提交的学生违纪处分申请已有最终处理结果,请点击前往处理。\""; + + weChatUtil.sendTextMessage(initiatorUserName, content); + log.info("已成功向流程发起人 ({}) 发送结果通知。", initiatorUserName); + } else { + log.warn("找到了发起人(userId:{}),但其对应的企业微信账号(userName)为空,未发送通知。", initiatorUserId); + } + + } catch (Exception e) { + log.error("向流程发起人发送结果通知时出现异常。流程将继续。错误详情: {}", e.getMessage(), e); + } + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..5bc4cfa --- /dev/null +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/SchoolLeaderApprovalListener.java @@ -0,0 +1,55 @@ +package com.srs.flowable.listener.disciplinary; + +import com.srs.common.utils.WeChatUtil; +import com.srs.common.utils.spring.SpringUtils; +import com.srs.flowable.mapper.DisciplinaryMapper; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.stereotype.Component; +import java.util.List; + +/** + * 执行监听器:在“校领导审批”节点开始时,向校领导发送企业微信通知。 知无涯 + * (简化版:因为流程能到达此节点,即表示前序节点已全票通过) + */ +@Component +@Slf4j +public class SchoolLeaderApprovalListener implements ExecutionListener { + + @Override + public void notify(DelegateExecution delegateExecution) { + log.info("流程实例 [{}]: 已进入校领导审批节点,准备发送通知。", delegateExecution.getProcessInstanceId()); + + try { + DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + + // 1. 【核心】定义“校领导”这个角色的 role_key + final String LEADER_ROLE_KEY = "xldsp"; + + // 2. 根据角色Key查询用户ID列表 + List userIdList = disciplinaryMapper.getApprovalByRoleKey(LEADER_ROLE_KEY); + + if (userIdList == null || userIdList.isEmpty()) { + log.warn("根据角色Key '{}' 未找到任何校领导用户,无法发送通知。", LEADER_ROLE_KEY); + return; + } + + // 3. 批量查询 userName 并发送通知 + List userNameList = disciplinaryMapper.getUserNamesByUserIdList(userIdList); + if (!userNameList.isEmpty()) { + String toUser = String.join("|", userNameList); + WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); + String content = "校领导您有一条新的学生违纪审批任务待处理,请点击前往处理。"; + + weChatUtil.sendTextMessage(toUser, content); + log.info("已成功向校领导 (角色: {}) 发送通知。接收人: {}", LEADER_ROLE_KEY, toUser); + } else { + log.warn("角色 '{}' 中找到了 {} 个用户,但无人配置企业微信账号,未发送任何通知。", LEADER_ROLE_KEY, userIdList.size()); + } + + } catch (Exception e) { + log.error("向校领导发送企业微信通知时出现异常。流程将继续。错误详情: {}", e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/StuInfoListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/StuInfoListener.java index cab8e3e..40c4281 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/StuInfoListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/StuInfoListener.java @@ -1,12 +1,17 @@ package com.srs.flowable.listener.disciplinary; +import com.srs.common.utils.WeChatUtil; +import com.srs.common.utils.spring.SpringUtils; +import com.srs.flowable.mapper.DisciplinaryMapper; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.ExecutionListener; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; /** - * 设置处分学生审批参数 + * 流程结束监听器。 + * 在流程的最终节点,向当事学生发送处理结果的通知。 知无涯 */ @Component @Slf4j @@ -14,10 +19,41 @@ public class StuInfoListener implements ExecutionListener { @Override public void notify(DelegateExecution delegateExecution) { - Long stuId = (Long)delegateExecution.getVariable("stuId"); + // 1. 从流程变量中获取学生ID + Object stuIdObj = delegateExecution.getVariable("stuId"); - log.info("学生信息:{}",stuId); - delegateExecution.setVariable("approval",stuId); - // todo 企业微信推送消息 + // 安全检查:确保stuId存在且类型正确 + if (!(stuIdObj instanceof Long)) { + log.error("流程实例 [{}] 在结束时未能获取到有效的 'stuId' 变量,无法发送最终通知。", delegateExecution.getProcessInstanceId()); + return; + } + Long stuId = (Long) stuIdObj; + log.info("流程实例 [{}] 即将结束,准备向学生ID: {} 发送最终通知。", delegateExecution.getProcessInstanceId(), stuId); + + // 2. 向该学生发送企业微信通知 + try { + DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean(DisciplinaryMapper.class); + + // 根据学生ID查询其对应的企业微信账号(userName) + String userName = disciplinaryMapper.getUserNameByUserId(stuId); + + // 检查是否找到了对应的企业微信账号 + if (!StringUtils.hasText(userName)) { + log.warn("流程实例 [{}]: 根据学生ID '{}' 未找到对应的企业微信账号,无法发送最终通知。", delegateExecution.getProcessInstanceId(), stuId); + return; // 中止发送逻辑 + } + + // 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); + } } -} +} \ 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 13a0cd1..16faf40 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; /** - * 学生教育管理科审核节点的执行监听器。 + * 学生教育管理科审核节点的执行监听器。 知无涯 * 向“学生教育管理科”角色发送企业微信通知。 */ @Component diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XWGSListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XWGSListener.java index 4394ee1..5345fb0 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XWGSListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/XWGSListener.java @@ -15,7 +15,7 @@ import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RequestBody; /** - * 根据辅导员的部门id,查询该部门的学无干事人员 + * 根据辅导员的部门id,查询该部门的学无干事人员 知无涯 */ @Component @Slf4j 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 ce8ecea..6963493 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 @@ -1,55 +1,72 @@ package com.srs.flowable.listener.disciplinary; import com.srs.common.utils.WeChatUtil; -import com.srs.common.utils.spring.SpringUtils; import com.srs.flowable.mapper.DisciplinaryMapper; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.ExecutionListener; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; +import java.util.stream.Collectors; /** - * 学院违纪处理委员会审批 + * 【线上监听器】为“学院违纪处理委员会”多实例任务准备数据并发送通知 知无涯 */ -@Component +@Component("xywjclwyhListener") @Slf4j public class XYWJCLWYHListener implements ExecutionListener { + // 推荐:使用依赖注入,而不是SpringUtils + @Autowired + private DisciplinaryMapper disciplinaryMapper; + + @Autowired + private WeChatUtil weChatUtil; + @Override - public void notify(DelegateExecution delegateExecution) { - DisciplinaryMapper disciplinaryMapper = SpringUtils.getBean("disciplinaryMapper"); - // 步骤 1: 根据角色Key获取审批人ID列表 (第1次DB查询) + public void notify(DelegateExecution execution) { + log.info("流程实例 [{}]: 在进入'学院违纪处理委员会'节点前,开始准备审批数据...", execution.getProcessInstanceId()); + + // 步骤 1: 单一数据库查询,获取所有需要的审批人信息 (ID和企微账号) + // List userInfos = disciplinaryMapper.getUserInfoByRoleKey("xywjclwyh"); + // 注意:如果您不方便修改Mapper,这里可以保持原来的两次查询,逻辑依然正确。 + // 我们先用原始的两次查询来演示,更具普适性。 + List userIdList = disciplinaryMapper.getApprovalByRoleKey("xywjclwyh"); - if (userIdList == null || userIdList.isEmpty()){ - log.error("未找到角色相关信息"); + + if (userIdList == null || userIdList.isEmpty()) { + log.error("角色 'xywjclwyh' 未配置或未找到任何有效用户,流程无法继续。"); throw new RuntimeException("学院违纪处理委员会审批人员未设置"); - }else{ - delegateExecution.setVariable("userList",userIdList); - // todo 企业微信推送消息 - // --- 企业微信推送消息模块 --- - try { - // 步骤 2: 一次性批量查询所有有效的userName (第2次DB查询,性能最优) - List userNameList = disciplinaryMapper.getUserNamesByUserIdList(userIdList); - - if (!userNameList.isEmpty()) { - // 步骤 3: 将 userName 列表用 "|" 连接成一个字符串 - String toUser = String.join("|", userNameList); - - WeChatUtil weChatUtil = SpringUtils.getBean(WeChatUtil.class); - String content = "您有一条新的学生违纪审批任务待处理,请点击前往处理。"; - - weChatUtil.sendTextMessage(toUser, content); - log.info("已成功向学院违纪处理委员会发送群组通知。接收人: {}", toUser); - } else { - log.warn("角色 'xywjclwyh' 存在审批人,但无人配置企业微信账号,未发送任何通知。"); - } - } catch (Exception e) { - // 保证即使通知失败,流程也能继续 - log.error("向学院违纪处理委员会发送企业微信通知时出现异常。流程将继续。错误详情: {}", e.getMessage(), e); - } } + // 步骤 2: 设置多实例任务需要的流程变量 (这是“线上”为“节点”准备的核心数据) + execution.setVariable("userList", userIdList); + log.info("流程实例 [{}]: 已成功设置'userList'变量,包含 {} 个审批人。", execution.getProcessInstanceId(), userIdList.size()); + + // 步骤 3: 发送企业微信通知 + sendWeChatNotification(userIdList, execution.getProcessInstanceId()); } -} + + /** + * 封装并执行企业微信通知逻辑 + */ + private void sendWeChatNotification(List userIdList, String processInstanceId) { + try { + List userNameList = disciplinaryMapper.getUserNamesByUserIdList(userIdList); + if (userNameList == null || userNameList.isEmpty()) { + log.warn("流程实例 [{}]: 角色'xywjclwyh'存在审批人ID,但无人配置企微账号,未发送通知。", processInstanceId); + return; + } + + String toUser = String.join("|", userNameList); + String content = "您有一条新的学生违纪审批任务待处理,请点击前往处理。"; + + weChatUtil.sendTextMessage(toUser, content); + log.info("流程实例 [{}]: 已成功向学院违纪处理委员会发送通知。接收人: {}", processInstanceId, toUser); + } catch (Exception e) { + log.error("流程实例 [{}]: 发送企微通知时出现异常,但不影响主流程。错误: {}", processInstanceId, e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/srs-flowable/src/main/java/com/srs/flowable/mapper/DisciplinaryMapper.java b/srs-flowable/src/main/java/com/srs/flowable/mapper/DisciplinaryMapper.java index 3b45c21..73cd76f 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/mapper/DisciplinaryMapper.java +++ b/srs-flowable/src/main/java/com/srs/flowable/mapper/DisciplinaryMapper.java @@ -23,7 +23,7 @@ public interface DisciplinaryMapper { */ String getUserNameByUserId(@Param("userId") Long userId); /** - * 知无涯新增:根据用户ID列表批量查询用户名列表 + * 知无涯 根据用户ID列表批量查询用户名列表 * @param userIdList 用户ID列表 * @return 用户的username列表 */ 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 bb95bfe..89eb0f1 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