From d0c8c8683965132bd6eee13fe0c32e9684713dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E6=97=A0=E6=B6=AF?= <2637171921@qq.com> Date: Mon, 25 Aug 2025 14:50:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- srs-admin/src/main/resources/application.yml | 2 +- .../comprehensive/mapper/CphMsgMapper.java | 8 ++ .../comprehensive/service/ICphMsgService.java | 8 ++ .../service/impl/CphMsgServiceImpl.java | 10 ++ .../mapper/comprehensive/CphMsgMapper.xml | 12 +++ .../disciplinary/GenericMessageListener.java | 36 ++++--- .../MessageProcessorListener.java | 99 +++++++++++++++++++ ...StuDisciplinaryApplicationServiceImpl.java | 2 +- 8 files changed, 159 insertions(+), 18 deletions(-) create mode 100644 srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MessageProcessorListener.java diff --git a/srs-admin/src/main/resources/application.yml b/srs-admin/src/main/resources/application.yml index 01f0640..afe0801 100644 --- a/srs-admin/src/main/resources/application.yml +++ b/srs-admin/src/main/resources/application.yml @@ -21,7 +21,7 @@ srs: # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 正式:8085 测试:8088 - port: 8085 + port: 8088 servlet: # 应用的访问路径 context-path: / diff --git a/srs-comprehensive/src/main/java/com/srs/comprehensive/mapper/CphMsgMapper.java b/srs-comprehensive/src/main/java/com/srs/comprehensive/mapper/CphMsgMapper.java index a18b327..50b6399 100644 --- a/srs-comprehensive/src/main/java/com/srs/comprehensive/mapper/CphMsgMapper.java +++ b/srs-comprehensive/src/main/java/com/srs/comprehensive/mapper/CphMsgMapper.java @@ -55,6 +55,14 @@ public interface CphMsgMapper extends BaseMapper */ public int deleteCphMsgById(Long id); + /** + * 根据接收人和内容中的标识来查找流程消息 (使用LIKE查询) 知无涯 + * + * @param cphMsg 包含 receiver 和 content (作为模糊查询的标识) 的查询对象 + * @return 匹配的消息列表 + */ + public List selectCphMsgListForFlowable(CphMsg cphMsg); + /** * 批量删除消息 * diff --git a/srs-comprehensive/src/main/java/com/srs/comprehensive/service/ICphMsgService.java b/srs-comprehensive/src/main/java/com/srs/comprehensive/service/ICphMsgService.java index 6d9cf84..eae412d 100644 --- a/srs-comprehensive/src/main/java/com/srs/comprehensive/service/ICphMsgService.java +++ b/srs-comprehensive/src/main/java/com/srs/comprehensive/service/ICphMsgService.java @@ -59,6 +59,14 @@ public interface ICphMsgService */ public int deleteCphMsgById(Long id); + /** + * 删除消息信息 精准匹配版 + * + * @param cphMsg 消息 + * @return 列表 + */ + List selectCphMsgListForFlowable(CphMsg cphMsg); + /** * 根据学号查询用户ID * diff --git a/srs-comprehensive/src/main/java/com/srs/comprehensive/service/impl/CphMsgServiceImpl.java b/srs-comprehensive/src/main/java/com/srs/comprehensive/service/impl/CphMsgServiceImpl.java index d3a13e0..a739eb0 100644 --- a/srs-comprehensive/src/main/java/com/srs/comprehensive/service/impl/CphMsgServiceImpl.java +++ b/srs-comprehensive/src/main/java/com/srs/comprehensive/service/impl/CphMsgServiceImpl.java @@ -95,6 +95,16 @@ public class CphMsgServiceImpl extends ServiceImpl implemen { return cphMsgMapper.deleteCphMsgById(id); } + /** + * 删除消息信息 + * + * @param cphMsg 消息 + * @return 结果 + */ + @Override + public List selectCphMsgListForFlowable(CphMsg cphMsg) { + return cphMsgMapper.selectCphMsgListForFlowable(cphMsg); + } /** * 根据学号查询用户ID diff --git a/srs-comprehensive/src/main/resources/mapper/comprehensive/CphMsgMapper.xml b/srs-comprehensive/src/main/resources/mapper/comprehensive/CphMsgMapper.xml index 8c6b99e..6ea5ee4 100644 --- a/srs-comprehensive/src/main/resources/mapper/comprehensive/CphMsgMapper.xml +++ b/srs-comprehensive/src/main/resources/mapper/comprehensive/CphMsgMapper.xml @@ -84,4 +84,16 @@ + + + diff --git a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/GenericMessageListener.java b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/GenericMessageListener.java index 3f0ad56..50c1305 100644 --- a/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/GenericMessageListener.java +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/GenericMessageListener.java @@ -13,14 +13,14 @@ import java.util.Collections; import java.util.List; /** - * 【通用线上监听器】为即将到来的任务创建内部“我的消息”记录。 + * 【通用线上监听器】为即将到来的任务创建内部“我的消息”记录。 知无涯1 *

* 该监听器被设计为在SequenceFlow的'take'事件上触发。 * 它会智能地从流程变量中读取单个接收人(变量名: approval)或多个接收人(变量名: userList), * 然后为每一位接收人创建一条内部消息。 *

*/ -@Component("genericMessageListener") // 定义一个清晰、通用的Spring Bean名称 +@Component("genericMessageListener") @Slf4j public class GenericMessageListener implements ExecutionListener { @@ -29,37 +29,41 @@ public class GenericMessageListener implements ExecutionListener { @Override public void notify(DelegateExecution execution) { - log.info("流程实例 [{}]: 触发通用消息监听器 (GenericMessageListener)...", execution.getProcessInstanceId()); + log.info("流程实例 [{}]: 触发通用消息监听器...", execution.getProcessInstanceId()); - // 步骤 1: 智能地从流程变量中获取接收人ID列表 List receiverIdList = getReceiverIds(execution); - - // 如果没有找到任何接收人,则记录日志并直接返回 if (receiverIdList.isEmpty()) { - log.warn("流程实例 [{}]: 未能从流程变量中找到任何有效的接收人 (未能解析 'approval' 或 'userList' 变量),已跳过创建内部消息。", execution.getProcessInstanceId()); return; } - // 步骤 2: 准备消息内容和发送人 - // 您可以根据业务需求,让消息内容更具动态性,比如从流程变量中获取任务标题 + // --- 关键改动:获取下一个即将创建的任务ID --- + // 注意:在线上监听器中,任务尚未创建,所以我们无法直接获取任务ID。 + // 但我们可以获取到这个“活动”的定义ID,它在流程定义中是唯一的。 + String activityId = execution.getCurrentActivityId(); + String taskName = execution.getCurrentFlowElement() != null ? execution.getCurrentFlowElement().getName() : "新"; - String messageContent = "您有一条新的【" + taskName + "】待办任务需要处理,请点击前往处理。"; + + // --- 关键改动:构建带有隐藏标识的消息内容 --- + String messageText = "您有一条新的【" + taskName + "】待办任务需要处理,"; + // 我们嵌入一个隐藏的span,它包含了流程实例ID和活动ID作为唯一标识 + String hiddenIdentifier = String.format("", + execution.getProcessInstanceId(), + activityId); + + String finalContent = messageText + hiddenIdentifier; + Long senderId = getSenderId(); - // 步骤 3: 遍历所有接收人,并为每位用户创建一条内部消息 for (Long receiverId : receiverIdList) { try { CphMsg cphMsg = new CphMsg(); cphMsg.setReceiver(receiverId); cphMsg.setSender(senderId); - cphMsg.setContent(messageContent); + cphMsg.setContent(finalContent); // 使用包含隐藏标识的内容 - // 调用您已有的服务插入消息 cphMsgService.insertCphMsg(cphMsg); - log.info("已成功为用户 [{}] 创建关于任务 [{}] 的内部消息。", receiverId, taskName); - + log.info("已成功为用户 [{}] 创建内部消息 (关联 Activity ID: {})。", receiverId, activityId); } catch (Exception e) { - // 捕获单个用户创建失败的异常,确保不影响其他人 log.error("为用户 [{}] 创建内部消息时发生异常: {}", receiverId, e.getMessage(), e); } } 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 new file mode 100644 index 0000000..4ebd9c7 --- /dev/null +++ b/srs-flowable/src/main/java/com/srs/flowable/listener/disciplinary/MessageProcessorListener.java @@ -0,0 +1,99 @@ +package com.srs.flowable.listener.disciplinary; // 您可以根据需要调整包路径 + +import com.srs.comprehensive.domain.CphMsg; +import com.srs.comprehensive.service.ICphMsgService; +import lombok.extern.slf4j.Slf4j; +import org.flowable.task.service.delegate.DelegateTask; +import org.flowable.task.service.delegate.TaskListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import javax.annotation.PostConstruct; +import java.util.List; + +/** + * 【任务监听器】在任务完成后,删除内部消息。 + *

+ * 该监听器被设计为在UserTask的'complete'事件上触发。 + * 它通过解析消息内容中的隐藏HTML标识来找到与当前已完成任务关联的消息, + * 并将其删除。 + *

+ */ +@Component("messageProcessorListener") // 定义一个清晰的Bean名称 +@Slf4j +public class MessageProcessorListener implements TaskListener { + + @Autowired + private ICphMsgService cphMsgService; + + /** + * 依赖检查方法,确保关键服务已注入。 + */ + @PostConstruct + public void checkDependencies() { + Assert.notNull(cphMsgService, "ICphMsgService dependency not injected for MessageProcessorListener!"); + } + + @Override + public void notify(DelegateTask delegateTask) { + // 步骤 1: 获取当前任务的办理人ID + String assigneeIdStr = delegateTask.getAssignee(); + if (assigneeIdStr == null || assigneeIdStr.isEmpty()) { + log.warn("任务 [ID: {}] 没有办理人,无法处理消息。", delegateTask.getId()); + return; + } + Long receiverId; + try { + receiverId = Long.parseLong(assigneeIdStr); + } catch (NumberFormatException e) { + log.error("任务办理人ID '{}' 无法转换为Long类型。", assigneeIdStr); + return; + } + + // 步骤 2: 获取用于查找消息的唯一标识 + String processInstanceId = delegateTask.getProcessInstanceId(); + // taskDefinitionKey 对应流程图中节点的ID,即我之前在 GenericMessageListener 中存入的 activityId + String activityId = delegateTask.getTaskDefinitionKey(); + + log.info("任务 [ID: {}, Name: {}] (办理人: {}) 已完成。开始查找并处理关联的内部消息...", + delegateTask.getId(), delegateTask.getName(), receiverId); + log.debug("用于查找的关联标识 -> ProcInst ID: [{}], Activity ID: [{}]", processInstanceId, activityId); + + try { + // 步骤 3: 构造用于模糊查询的、唯一的标识字符串 + // 这个字符串必须与 GenericMessageListener 中生成该标识的逻辑完全一致 + String searchIdentifier = String.format("data-proc-inst-id='%s' data-activity-id='%s'", + processInstanceId, + activityId); + + // 步骤 4: 创建查询参数并调用服务 + CphMsg queryParam = new CphMsg(); + queryParam.setReceiver(receiverId); + queryParam.setContent(searchIdentifier); // 将标识作为模糊查询的内容 + + // 注意:这一步要求 CphMsgMapper.xml 中的 selectCphMsgListForFlowable 方法支持对 content 字段的 LIKE 查询 + List messagesToProcess = cphMsgService.selectCphMsgListForFlowable(queryParam); + + if (messagesToProcess.isEmpty()) { + log.info("未找到需要为用户 [{}] 处理的、与当前任务关联的消息。", receiverId); + return; + } + + // 步骤 5: 遍历所有找到的消息,并进行处理(删除) + for (CphMsg msg : messagesToProcess) { + try { + cphMsgService.deleteCphMsgById(msg.getId()); + log.info("已成功删除与任务关联的消息 [ID: {}]。", msg.getId()); + } catch (Exception e) { + // 捕获单个消息删除失败的异常,确保不影响其他消息的处理 + log.error("删除消息 [ID: {}] 时发生异常: {}", msg.getId(), e.getMessage(), e); + } + } + + } catch (Exception e) { + // 捕获整个处理过程中的异常,确保不影响主流程的流转 + log.error("处理用户 [{}] 的内部消息时发生严重异常: {}", receiverId, e.getMessage(), e); + } + } +} \ No newline at end of file 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 66c2aaa..95679a7 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